This PR merges code from `coder/aibridge` repository into `coder/coder`. It was split into 4 PRs for easier review but stacked PRs will need to be merged into this PR so all checks pass. * https://github.com/coder/coder/pull/24190 -> raw code copy (this PR, before merging PRs on top of it, it was just 1 commit: https://github.com/coder/coder/commit/70d33f33200c7e77df910957595715f81f9bec24) * https://github.com/coder/coder/pull/24570 -> update imports in `coder/coder` to use copied code * https://github.com/coder/coder/pull/24586 -> linter fixes and CI integration (also added README.md) * https://github.com/coder/coder/pull/24571 -> added exclude to scripts/check_emdash.sh check Original PR message (before PR squash): Moves coder/aibridge code into coder/coder repository. Omitted files: - `go.mod`, `go.sum`, `.gitignore`, `.github/workflows/ci.yml,` `Makefile`, `LICENSE`, `README.md` (modified README.md is added later) - `.github`, `example`, `buildinfo,` `scripts` directories Simple verification script (will list omitted files) ``` tmp=$(mktemp -d) echo "$tmp" git clone --depth=1 https://github.com/coder/aibridge "$tmp/aibridge" git clone --depth=1 --branch pb/aibridge-code-move https://github.com/coder/coder "$tmp/coder" diff -rq --exclude=.git "$tmp/aibridge" "$tmp/coder/aibridge" # rm -rf "$tmp" ```
5.6 KiB
AI Agent Guidelines for aibridge
For local overrides, create
AGENTS.local.md(gitignored).
You are an experienced, pragmatic software engineer. Simple solutions over clever ones. Readability is a primary concern.
Tone & Relationship
We're colleagues. Push back on bad ideas and speak up when something doesn't make sense. Honesty over agreeableness.
- Disagree when I'm wrong. Act as a critical peer reviewer.
- Call out bad ideas, unreasonable expectations, and mistakes.
- Ask for clarification instead of assuming. Say when you don't know something.
- Architectural decisions require discussion; routine fixes do not.
Foundational Rules
- Doing it right is better than doing it fast.
- YAGNI. Don't add features we don't need right now.
- Make the smallest reasonable changes to achieve the goal.
- Reduce code duplication, even if it takes extra effort.
- Match the style of surrounding code. Consistency within a file matters.
- Fix bugs immediately when you find them.
Essential Commands
| Task | Command | Notes |
|---|---|---|
| Test | make test |
All tests, no race detector |
| Test (race) | make test-race |
CGO_ENABLED=1, use for CI |
| Coverage | make coverage |
Prints summary to stdout |
| Format | make fmt |
gofumpt; single file: make fmt FILE=path |
| Mocks | make mocks |
Regenerate from mcp/api.go |
Always use these commands instead of running go test or gofumpt directly.
Code Navigation
Use LSP tools (go to definition, find references, hover) before resorting to grep. This codebase has 90+ Go files across multiple packages, so LSP is faster and more accurate.
Architecture Overview
AI Bridge is a smart gateway that sits between AI clients (Claude Code, Cursor,
etc.) and upstream providers (Anthropic, OpenAI). It intercepts all AI traffic
to provide centralized authn/z, auditing, token attribution, and MCP tool
administration. It runs as part of coderd (the Coder control plane). Users
authenticate with their Coder session tokens.
┌─────────────┐ ┌──────────────────────────────────────────┐
│ AI Client │ │ aibridge │
│ (Claude Code,│────▶│ RequestBridge (http.Handler) │
│ Cursor) │ │ ├── Provider (Anthropic/OpenAI) │
└─────────────┘ │ ├── Interceptor (streaming/blocking) │
│ ├── Recorder (tokens, prompts, tools) │
│ └── MCP Proxy (tool injection) │
└──────────────┬───────────────────────────┘
│
▼
┌──────────────┐
│ Upstream API │
│ (Anthropic, │
│ OpenAI) │
└──────────────┘
Key packages:
intercept/: request/response interception, per-provider subdirs (messages/,responses/,chatcompletions/)provider/: upstream provider definitions (Anthropic, OpenAI, Copilot)mcp/: MCP protocol integrationcircuitbreaker/: circuit breaker for upstream callscontext/: request-scoped context helpersinternal/integrationtest/: integration tests with mock upstreams
Go Patterns
- Follow the Uber Go Style Guide.
- Use
gofumptfor formatting (enforced bymake fmt). - Prefer table-driven tests.
- Never use
time.Sleepin tests. Usegithub.com/coder/quartzor channels/contexts for synchronization. - Use unique identifiers in tests:
fmt.Sprintf("test-%s-%d", t.Name(), time.Now().UnixNano()). - Test observable behavior, not implementation details.
Streaming Code
This codebase heavily uses SSE streaming. When modifying interceptors:
- Always handle both blocking and streaming paths.
- Test with
*_test.gofiles in the same package. They cover edge cases for chunked responses. - Be careful with goroutine lifecycle. Ensure proper cleanup on context cancellation.
Commit Style
type(scope): message
scope= real package path (e.g.,intercept/messages,provider,circuitbreaker)- Comments: full sentences, max 80 chars, explain why not what.
Do NOT
- Rewrite comments or refactor code that isn't related to your task.
- Remove context from error messages.
- Use
--no-verifyon git operations. - Add
//nolintwithout a justification comment. - Introduce new dependencies without discussion.
Common Pitfalls
| Problem | Fix |
|---|---|
| Race in streaming tests | Use t.Cleanup() and proper synchronization, never time.Sleep |
| Mock not updated | Run make mocks after changing mcp/api.go |
| Formatting failures | Run make fmt before committing |
retract directive in go.mod |
Don't remove. It's intentional (v1.0.8 conflict marker) |