fix(cursor): add kimi-k3 with low/high/max effort tiers - #646
Conversation
Cursor serves Kimi K3 only as effort-suffixed wire ids (kimi-k3-low/-high/-max, verified via GetUsableModels 2026-07-28); the bare id returns Connect not_found. Add the base model to CURSOR_STATIC_MODELS (tier picker) and CURSOR_MODEL_EFFORT_TIERS so requests resolve to a suffixed variant, mirroring the native Kimi provider's K3 ladder.
📝 WalkthroughWalkthroughThe Cursor adapter now catalogs ChangesCursor kimi-k3 support
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant CursorDiscovery
participant EffortMap
participant ProviderRegistry
participant Catalog
CursorDiscovery->>EffortMap: Register kimi-k3 effort tiers
EffortMap-->>ProviderRegistry: Provide low, high, max mappings
ProviderRegistry->>Catalog: Apply max default reasoning effort
Catalog-->>ProviderRegistry: Expose cursor/kimi-k3 catalog metadata
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31c732653f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { id: "kimi-k2.7-code", contextWindow: CONTEXT_262K }, | ||
| // kimi-k3: cursor.com/docs/models/kimi-k3; account-verified via GetUsableModels (2026-07-28) — | ||
| // ships only as effort-suffixed kimi-k3-{low,high,max}, so the tier picker is exposed. | ||
| { id: "kimi-k3", contextWindow: CONTEXT_262K, supportsReasoningEffort: true }, |
There was a problem hiding this comment.
Document Kimi K3 in the Cursor catalog
Adding cursor/kimi-k3 with selectable low / high / max tiers changes the user-visible picker and fallback catalog, but the docs-site model coverage table still describes the Cursor fallback without this model or its effort behavior. Update the English Cursor coverage documentation and keep translated locales consistent so users can discover and correctly configure the new route.
AGENTS.md reference: AGENTS.md:L96-L97
Useful? React with 👍 / 👎.
| { id: "kimi-k2.7-code", contextWindow: CONTEXT_262K }, | ||
| // kimi-k3: cursor.com/docs/models/kimi-k3; account-verified via GetUsableModels (2026-07-28) — | ||
| // ships only as effort-suffixed kimi-k3-{low,high,max}, so the tier picker is exposed. | ||
| { id: "kimi-k3", contextWindow: CONTEXT_262K, supportsReasoningEffort: true }, |
There was a problem hiding this comment.
Preserve max as Kimi K3's catalog default
When this model is used through the Codex catalog, cursorModelReasoningEfforts supplies low / high / max but the Cursor registry supplies no modelDefaultReasoningEfforts override. Consequently, applyReasoningLevels selects high as default_reasoning_level, so an ordinary picker request explicitly sends high and never reaches the request builder's intended no-effort fallback to kimi-k3-max. Add a max default for this Cursor model, as is already done for Kimi K3 on the other provider routes, and cover the integrated catalog entry.
Useful? React with 👍 / 👎.
Wibias
left a comment
There was a problem hiding this comment.
Maintainer review (bug + security)
Verdict: REQUEST CHANGES
HEAD: 31c73265. Target dev is correct. CodeRabbit: no actionable comments. Codex: 2 open P2s (verified below). Security review (Security Review): no medium+ — static catalog/effort-tier mapping only; no auth, credential, SSRF, or trust-boundary changes.
Focused effort/discovery tests: discovery suite passes; effort-suffix file needs bun install in the review worktree (@bufbuild/protobuf) — rely on CI for the full gate. Cross-platform CI had not fully reported at review time beyond label/enforce/CodeRabbit.
Open Codex (verified against HEAD)
| Item | Verdict | Action |
|---|---|---|
P2: catalog default becomes high, not max |
Valid / required | Cursor registry has modelReasoningEfforts from the ladder ["low","high","max"] but no modelDefaultReasoningEfforts. applyReasoningLevels (effort.ts:178-180) then picks high (no medium in the ladder). Ordinary Codex picker requests therefore send high → wire kimi-k3-high, and never hit the request-builder’s no-effort → top-tier (kimi-k3-max) path that the new test documents. Native Kimi / OpenCode-Go already set "kimi-k3": "max". Add modelDefaultReasoningEfforts: { "kimi-k3": "max" } on the Cursor registry entry (providers/registry.ts) and cover it in catalog/reasoning tests. |
| P2: docs-site Cursor coverage | Valid / required | User-facing catalog change. Update English docs-site/.../guides/codex-app-models.md Cursor row (and keep translated locales consistent) so the static fallback mentions cursor/kimi-k3 and its low / high / max effort behavior. |
Diff sanity (no extra blockers)
- Tiers
["low","high","max"]matchKIMI_CODING_K3_REASONING_EFFORTS;supportsReasoningEffort: truematches the effort-map entry. medium→kimi-k3-highclamp matches existing non-medium ladder behavior (cursorEffortSuffix).- Static seed + effort-suffix tests are the right shape once the default override lands.
Required before merge
- Set Cursor
modelDefaultReasoningEfforts["kimi-k3"] = "max"(+ regression coverage). - Update docs-site Cursor coverage (EN + locales).
|
Reviewed against the current Confirmed correctCursor's own CursorBench page lists exactly Blocker: the catalog default lands on
|
PR lidge-jun#646 seeds cursor/kimi-k3 with a low/high/max effort ladder, which is the right tier data — Cursor serves K3 only as effort-suffixed wire ids and Kimi documents max as the model's API default. But the Cursor registry entry supplied no modelDefaultReasoningEfforts, and that ladder has no medium rung, so applyReasoningLevels fell through medium -> high and settled the catalog default on high. The picker then sends high explicitly and the request builder's no-effort fallback to kimi-k3-max is never reached. The other K3 routes (kimi, kimi-code, opencode-go) already carry this default, so cursor was also the odd one out. Verified in both directions: on the PR commit alone the assembled catalog row reports default_reasoning_level = high; with this line it reports max; removing the line again fails the new test with Received: "high". The existing effort-suffix tests pass either way, which is why the defect slipped through — they assert the ladder, not the assembled default. Scope check: modelRecordValue matches exact key, colon-family, then case-fold, so { "kimi-k3": "max" } cannot reach kimi-k3-max, kimi-k3-low, or any other cursor model. Confirmed across 8 model ids; only kimi-k3 is affected. Gates: tsc clean; codex-catalog 113 pass; cursor-effort-suffix + cursor-discovery 18 pass; provider-registry-parity + reasoning-effort 70 pass. Docs ship in the same commit because the prose asserts the ladder and default.
|
Maintainer follow-up: I pushed the two requested changes to this branch as Why the tier data was right but the PR was incomplete. Your Reproduced both directions on your commit: This is also why the existing
What landed in
Docs shipped in the same commit as the registry line on purpose: the prose asserts the ladder and the default, so splitting them would make the docs false at the intermediate commit. Scope check. Gates (local, on the pushed head): Thanks for the account-verified |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@docs-site/src/content/docs/ru/guides/providers.md`:
- Around line 224-226: Update the Russian Cursor note near the `cursor/kimi-k3`
description to rephrase the clause after `max`, explicitly stating that `max`
corresponds to the documented default value in the model API. Preserve the
existing meaning and the `low` / `high` / `max` ladder.
In `@tests/codex-catalog.test.ts`:
- Around line 711-712: Update the regression expectation in the supported
reasoning levels assertion to remove the unsupported "ultra" tier, leaving only
"low", "high", and "max" for the kimi-k3 effort map.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f40bb068-1367-4ac5-ba70-84e92ae41cb4
📒 Files selected for processing (7)
docs-site/src/content/docs/guides/providers.mddocs-site/src/content/docs/ja/guides/providers.mddocs-site/src/content/docs/ko/guides/providers.mddocs-site/src/content/docs/ru/guides/providers.mddocs-site/src/content/docs/zh-cn/guides/providers.mdsrc/providers/registry.tstests/codex-catalog.test.ts
| Kimi K3 только через wire id с суффиксом усилия, поэтому `cursor/kimi-k3` предоставляет лестницу | ||
| `low` / `high` / `max` и по умолчанию использует `max` — как и задокументированное значение по | ||
| умолчанию в API модели. Управляемое сервером Cursor |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the Russian case/agreement in the Cursor note.
The phrase как и задокументированное значение по умолчанию is grammatically awkward in this construction. Rephrase it so that max is explicitly stated to correspond to the documented API default.
Proposed fix
-`low` / `high` / `max` и по умолчанию использует `max` — как и задокументированное значение по
-умолчанию в API модели.
+`low` / `high` / `max` и по умолчанию использует `max`, что соответствует
+задокументированному в API модели значению по умолчанию.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Kimi K3 только через wire id с суффиксом усилия, поэтому `cursor/kimi-k3` предоставляет лестницу | |
| `low` / `high` / `max` и по умолчанию использует `max` — как и задокументированное значение по | |
| умолчанию в API модели. Управляемое сервером Cursor | |
| Kimi K3 только через wire id с суффиксом усилия, поэтому `cursor/kimi-k3` предоставляет лестницу | |
| `low` / `high` / `max` и по умолчанию использует `max`, что соответствует | |
| задокументированному в API модели значению по умолчанию. Управляемое сервером Cursor |
🧰 Tools
🪛 LanguageTool
[uncategorized] ~226-~226: Прилагательное не согласуется с существительным по падежу.
Context: ...ное значение по умолчанию в API модели. Управляемое сервером Cursor нативное выполнение read/write/d...
(Unify_Adj_NN_case)
🤖 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-site/src/content/docs/ru/guides/providers.md` around lines 224 - 226,
Update the Russian Cursor note near the `cursor/kimi-k3` description to rephrase
the clause after `max`, explicitly stating that `max` corresponds to the
documented default value in the model API. Preserve the existing meaning and the
`low` / `high` / `max` ladder.
Source: Linters/SAST tools
| expect((entry?.supported_reasoning_levels as Array<{ effort: string }>).map(level => level.effort)) | ||
| .toEqual(["low", "high", "max", "ultra"]); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the unsupported ultra tier from this regression expectation.
The Cursor effort map defines kimi-k3 as ["low", "high", "max"] (src/adapters/cursor/effort-map.ts, Line 30), and the updated provider documentation states the same ladder. This test currently asserts an extra ultra level, so it will fail against the intended catalog or conceal a source/catalog contract drift.
Proposed fix
expect((entry?.supported_reasoning_levels as Array<{ effort: string }>).map(level => level.effort))
- .toEqual(["low", "high", "max", "ultra"]);
+ .toEqual(["low", "high", "max"]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| expect((entry?.supported_reasoning_levels as Array<{ effort: string }>).map(level => level.effort)) | |
| .toEqual(["low", "high", "max", "ultra"]); | |
| expect((entry?.supported_reasoning_levels as Array<{ effort: string }>).map(level => level.effort)) | |
| .toEqual(["low", "high", "max"]); |
🤖 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 `@tests/codex-catalog.test.ts` around lines 711 - 712, Update the regression
expectation in the supported reasoning levels assertion to remove the
unsupported "ultra" tier, leaving only "low", "high", and "max" for the kimi-k3
effort map.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2201509b6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // default on `high`, the picker would send `high` explicitly, and the request builder's | ||
| // no-effort fallback to `kimi-k3-max` would never be reached. Mirrors the other K3 | ||
| // routes (kimi, kimi-code, opencode-go). | ||
| modelDefaultReasoningEfforts: { "kimi-k3": "max" }, |
There was a problem hiding this comment.
Merge the Kimi default into partial Cursor maps
When an existing Cursor configuration already has modelDefaultReasoningEfforts for an unrelated model, this new default never reaches the catalog: enrichProviderFromRegistry only copies that map when the entire field is absent (src/providers/derive.ts), whereas the request router merges it per key. As a result, cursor/kimi-k3 falls back to catalog default high for such configurations even though routing knows the registry default is max. Fresh evidence after the prior finding's fix is that the newly added override remains hidden specifically by a pre-existing partial user map; merge defaults per key and cover that configuration in the catalog regression test.
Useful? React with 👍 / 👎.
| live HTTP/2 transport. Its v2.7.1 fallback seed includes `gpt-5.6-sol` / `terra` / `luna` (1M context), | ||
| `grok-4.5` / `grok-4.5-fast` (500K), and `kimi-k3` (262K); live discovery decides which remain | ||
| visible for the account. Cursor serves Kimi K3 only as effort-suffixed wire ids, so | ||
| `cursor/kimi-k3` exposes a `low` / `high` / `max` ladder and defaults to `max`, matching the |
There was a problem hiding this comment.
Document the synthetic ultra tier
The new documentation says cursor/kimi-k3 exposes only a low / high / max ladder, but applyReasoningLevels always adds ultra to routed reasoning models, and the new catalog test explicitly expects ['low', 'high', 'max', 'ultra']. Users therefore see an undocumented fourth picker option; describe ultra as an alias that resolves to the max wire tier and make the same correction in each translated locale.
AGENTS.md reference: AGENTS.md:L96-L97
Useful? React with 👍 / 👎.
lidge-jun
left a comment
There was a problem hiding this comment.
Approving. Both requested changes landed in d2201509b, and the branch is now merged up to green dev as 60bd535f6.
Your tier data was right from the start — Cursor serves K3 only as effort-suffixed wire ids and Kimi documents max as the API default. What was missing was the registry default: with no medium rung in the ladder, applyReasoningLevels fell through medium -> high and settled the catalog on high, so the picker sent high explicitly and never reached the kimi-k3-max fallback your PR description intended. Verified on your commit alone (high), with the fix (max), and by deleting the line again (new test fails with Received: \"high\").
CI history worth noting so the reruns do not look mysterious: the first windows-latest failure was a missing timeout-headroom fix (#717) that this branch's base predated, the second was the dev kiro regression now fixed as #718, and the third was a Bun runtime panic(thread …): Internal assertion failure that cleared on rerun. All six jobs are green on 60bd535f6.
Thanks for the account-verified GetUsableModels evidence and the live smoke — that made the tier ladder easy to confirm.
Summary
Cursor serves Kimi K3 only as effort-suffixed wire ids (
kimi-k3-low,kimi-k3-high,kimi-k3-max) — verified againstGetUsableModelson 2026-07-28 with an entitled account. The bare idkimi-k3fails with Connectnot_found, and since the model was missing fromCURSOR_STATIC_MODELSit never entered the routed catalog either.src/adapters/cursor/effort-map.ts: add"kimi-k3": ["low", "high", "max"]toCURSOR_MODEL_EFFORT_TIERS, so requests resolve to a suffixed variant (bare/no-effort picks the top tiermax, same clamp behavior as other tiered models). Tiers mirror the native Kimi provider's K3 ladder (KIMI_CODING_K3_REASONING_EFFORTS).src/adapters/cursor/discovery.ts: addkimi-k3toCURSOR_STATIC_MODELS(CONTEXT_262K,supportsReasoningEffort: true) and adjust the stale "kimi sent bare" comment.Test plan
bun test tests/cursor-effort-suffix.test.ts tests/cursor-discovery.test.ts— 18 pass (new cases:cursor/kimi-k3+ low/medium/high/max/bare → suffixed wire ids, ladder["low","high","max"], static seed containskimi-k3)bun test tests/codex-catalog.test.ts tests/provider-registry-parity.test.ts tests/reasoning-effort.test.ts— 182 passPOST /v1/responsescursor/kimi-k3→completed(previouslyCursor Connect error not_found); same withreasoning.effort=lowSummary by CodeRabbit