feat(provider): add Kimi Code provider#508
Conversation
Add the `kimicode` provider, a dedicated type for Kimi Code's OpenAI-compatible membership endpoint at `https://api.kimi.com/coding/v1`. Kimi Code uses its own API-key realm and a stable `kimi-for-coding` model alias, so it is exposed as a distinct provider rather than overloading the general Moonshot platform type. - Introduce `internal/providers/kimicode/` with `New` and `NewWithHTTPClient` factories that wrap the shared `openai.ChatCompatible` adapter, forwarding model IDs unchanged. - Register `kimicode.Registration` in `run/providers.go` so the gateway recognizes it on startup. - Add `KIMICODE_API_KEY`, `KIMICODE_BASE_URL`, and `KIMICODE_MODELS` to `.env.template` for environment-based credential discovery. - Extend `cmd/recordapi` to support `kimicode`: add an embeddings endpoint fixture, provider-specific default models (`kimi-for-coding`, `bge_m3_embed`), embeddings capability gating, and a path override for `/v1/embeddings` so recorded fixtures match Kimi Code's route layout.
Lock in the new `kimicode` provider with unit and contract coverage so future refactors of the provider factory or chat-compatible adapter cannot silently break Kimi Code routing. - `internal/providers/kimicode/kimicode_test.go` — factory behavior for the provider, including default and custom base URL resolution. - `internal/providers/config_test.go` — discover `kimicode` in provider configuration parsing. - `run/lifecycle_test.go` — `TestMain_KimicodeProviderRegistration` pins the lifecycle wiring. - `run/providers_test.go` — assert `kimicode` appears in the registered provider types. - `tests/contract/kimicode_test.go` plus contract fixtures and golden files for chat completions, chat completion streaming, embeddings, and model listing so the contract suite can replay Kimi Code-shaped responses without live credentials.
add Kimi Code docs page, overview table row, navigation entry, and contract README fixture layout; align `/responses` support and cost wording with implementation after review.
📝 WalkthroughWalkthroughThis PR adds a new Kimicode OpenAI-compatible provider, wires it into factory registration and recordapi tooling, and adds unit/contract coverage plus docs and env-template updates. ChangesKimicode Provider Integration
Estimated code review effort: 3 (Moderate) | ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cmd/recordapi/main.go`:
- Around line 132-139: The shared embeddings recording path is being used for
providers that need different request URLs, so add provider-specific overrides
in the record API config instead of changing the common `/embeddings` entry.
Update the embeddings setup in `cmd/recordapi/main.go` so OpenAI and Groq record
against `/v1/embeddings`, while keeping the existing shared path behavior for
Gemini; use the existing embeddings request definition as the reference point.
In `@docs/providers/kimicode.mdx`:
- Around line 34-39: The KIMICODE configuration example currently shows only the
chat model list and omits the embeddings model, which can mislead users into
breaking embeddings support. Update the snippet in the kimicode guide to include
the embeddings model alongside the existing KIMICODE_MODELS example, or
explicitly mark the example as chat-only so it matches the documented embedding
behavior.
In `@tests/contract/kimicode_test.go`:
- Around line 27-94: The new Kimicode replay tests only cover success cases, so
add error-handling coverage for the replay client. Introduce a test around the
existing provider methods like TestKimicodeReplayChatCompletion or a new
TestKimicodeReplay...Error case that configures newKimicodeReplayProvider with a
non-2xx/upstream-error response for /chat/completions (or another endpoint) and
asserts the returned error is surfaced correctly. Keep the same test style and
use the existing replay helpers and provider methods to verify request
translation still happens while the error path is exercised.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e9add091-5d25-420f-88a2-70bf4af278df
📒 Files selected for processing (21)
.env.templatecmd/recordapi/main.godocs/docs.jsondocs/providers/kimicode.mdxdocs/providers/overview.mdxinternal/providers/config_test.gointernal/providers/kimicode/kimicode.gointernal/providers/kimicode/kimicode_test.gorun/lifecycle_test.gorun/providers.gorun/providers_test.gotests/contract/README.mdtests/contract/kimicode_test.gotests/contract/testdata/golden/kimicode/chat_completion.golden.jsontests/contract/testdata/golden/kimicode/chat_completion_stream.golden.jsontests/contract/testdata/golden/kimicode/embeddings.golden.jsontests/contract/testdata/golden/kimicode/models.golden.jsontests/contract/testdata/kimicode/chat_completion.jsontests/contract/testdata/kimicode/chat_completion_stream.txttests/contract/testdata/kimicode/embeddings.jsontests/contract/testdata/kimicode/models.json
| "embeddings": { | ||
| path: "/embeddings", | ||
| method: http.MethodPost, |
There was a problem hiding this comment.
Embeddings path omits version
The new embeddings endpoint defaults to /embeddings, so -provider=openai -endpoint=embeddings sends requests to https://api.openai.com/embeddings instead of the OpenAI-compatible /v1/embeddings route used by the gateway adapter. Because openai, gemini, and groq are marked as supporting embeddings without an override, the recorder now fails for those providers.
Artifacts
Repro: focused Go test harness for recorder embeddings URL construction
- Contains supporting evidence from the run (text/x-go; charset=utf-8).
Repro: verbose Go test output showing openai uses /embeddings while kimicode uses /v1/embeddings
- Keeps the command output available without making the summary code-heavy.
There was a problem hiding this comment.
Good catch. I checked the upstream docs: OpenAI and Groq both expose embeddings under /v1/embeddings, so I added overrides for both. Gemini doesn't need one because its base URL already ends in /v1beta/openai, and the docs show embeddings at .../v1beta/openai/embeddings. Kimi was already covered.
OpenAI and Groq both expose embeddings under /v1/embeddings, but the recordapi generic endpoint used /embeddings. Add provider-specific overrides so recordings target the correct upstream path. Gemini is intentionally left unchanged: its base URL already includes the /v1beta/openai prefix, so the generic /embeddings path is correct.
The docs example only listed the chat model, while the Embeddings section and .env.template document both chat and embeddings models. Update the snippet so users do not accidentally disable embeddings support by copying the example.
Add TestKimicodeReplayChatCompletionError to exercise the non-2xx path for the Kimi Code provider via the replay harness. Asserts the upstream error is surfaced correctly by the OpenAI-compatible adapter.
No functional changes; formatting only.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/providers/kimicode.mdx (1)
28-31: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winKeep the provider key and selector in sync.
providers.kimicodeis described as arbitrary, but the selector example hard-codes that key. If a user renames the entry, anyselector: "kimicode:..."values must change too or virtual routing will break.♻️ Suggested wording
<Note> The provider `type` is `kimicode` (no hyphen). The config key (`kimicode` in - the example above) is arbitrary and only identifies this entry inside your - config; it may be changed. + the example above) is arbitrary, but any selector strings that reference it + must be updated if you rename the entry. </Note>Also applies to: 46-50
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/providers/kimicode.mdx` around lines 28 - 31, The provider entry key and selector examples are inconsistent: the docs currently say the config key is arbitrary, but the `kimicodeSelector`/`selector` example hard-codes `kimicode`, which will break if users rename the provider entry. Update the wording around the `kimicode` provider example and any selector guidance so it explicitly states that the selector prefix must match the configured provider key, and adjust the related `kimicode` references in the doc to stay in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@docs/providers/kimicode.mdx`:
- Around line 28-31: The provider entry key and selector examples are
inconsistent: the docs currently say the config key is arbitrary, but the
`kimicodeSelector`/`selector` example hard-codes `kimicode`, which will break if
users rename the provider entry. Update the wording around the `kimicode`
provider example and any selector guidance so it explicitly states that the
selector prefix must match the configured provider key, and adjust the related
`kimicode` references in the doc to stay in sync.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a1509509-a689-4f5d-a1c9-c618f6272c85
📒 Files selected for processing (6)
cmd/recordapi/main.godocs/providers/kimicode.mdxrun/lifecycle_test.gorun/providers.gorun/providers_test.gotests/contract/kimicode_test.go
Closes #487 (replaces the mixed provider + header-override branch) and implements Kimi Code provider in single PR.
What
Adds a new
kimicodeprovider that routes the Kimi Code OpenAI-compatible API through GoModel, so callers can usekimi-for-codingandbge_m3_embedwith the same/v1/chat/completions,/v1/embeddings, and/v1/modelsendpoints as any other provider.User-visible behavior
kimicode. SetKIMICODE_API_KEYin the environment or declare atype: kimicodeprovider inconfig.yaml.https://api.kimi.com/coding/v1; override viaKIMICODE_BASE_URLorbase_urlin config.kimicode/kimi-for-codingandkimicode/bge_m3_embed./v1/embeddingsshape.data: [DONE].Design
Kimi Code is exposed as a pure OpenAI-compatible provider, so the implementation reuses the existing
openai.CompatibleProviderinfrastructure rather than adding a custom protocol adapter. This keeps the provider thin and means any future improvements to the OpenAI-compatible path (e.g., reasoning responses, batch, or image support) automatically apply to Kimi Code as long as the upstream API supports them.Implementation
internal/providers/kimicode/with aChatCompatibleadapter that points at the Kimi Code base URL and provider typekimicode.run/providers.gosoKIMICODE_API_KEYauto-discovers the provider.internal/providers/kimicode/kimicode_test.gocovering registration and package-level constructors.tests/contract/kimicode_test.gousing recorded replay fixtures for chat, streaming chat, models, and embeddings.cmd/recordapi/main.gofor the Kimi Code API, including the embeddings endpoint and model capability gating.docs/providers/kimicode.mdx, updateddocs/providers/overview.mdx, anddocs/docs.jsonnavigation..env.templateupdated withKIMICODE_API_KEY,KIMICODE_BASE_URL, andKIMICODE_MODELS.Verification
go build ./...passes cleanly.go test ./internal/providers/kimicode/... ./run/... ./config/...passes.go test -tags=contract ./tests/contract/... -run Kimipasses the Kimi Code replay contract tests (chat, streaming chat, models, embeddings).gofmt -lreports no diffs for the files changed on this branch; only pre-existing benchmark tooling indocs/2026-06-25_aws_gateway_benchmark/remains unformatted..env, and verified live calls against the Kimi Code API:/v1/modelslistskimicode/kimi-for-codingandkimicode/bge_m3_embed./v1/embeddingsforkimicode/bge_m3_embedreturns a 1024-dimensional vector./v1/chat/completionsforkimicode/kimi-for-codingreturns a non-streaming completion withprovider: kimicode./v1/chat/completionsreturns SSE chunks, a usage block, and terminates cleanly withdata: [DONE].Summary by CodeRabbit