-
Notifications
You must be signed in to change notification settings - Fork 960
feat(cursor): collapse the picker into umbrella rows routed through the catalog resolver #2802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
874f597
3a192a7
967c70c
ab461a1
3dad4fb
53c5ede
23320f3
670812d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,50 @@ | ||||||||||||||
| # 050 — cursor PR merge train (wp map for the merge-round loop) | ||||||||||||||
|
|
||||||||||||||
| User instruction (2026-08-28): merge the cursor rounds one at a time; the | ||||||||||||||
| instruction is the maintainer approval for these session-authored PRs. | ||||||||||||||
|
|
||||||||||||||
| ## Rounds (dependency-first) | ||||||||||||||
|
|
||||||||||||||
| | R | PR | head | gate | | ||||||||||||||
| |---|---|---|---| | ||||||||||||||
| | R1 | #2774 backlog coalesce | codex/runturn-backlog-coalesce 286a1e5a5 | checks 25 SUCCESS + 1 SKIPPED — green; sol-medium pre-merge review | | ||||||||||||||
| | R2 | #2795 midstream echo | codex/cursor-midstream-echo | retarget to dev post-R1; CI re-run green | | ||||||||||||||
| | R3 | #2769 failed_precondition | codex/claude-classified-error-status 16cb875b8 | checks green; review | | ||||||||||||||
| | R4 | #2801 umbrella core | codex/cursor-umbrella-core 54965ef03 | CI FAIL: test 1/4 update-stop-first launcher-recovery timeout (46.8s, waitForProxy false) — UNRELATED to catalog diff (no update/launcher files touched); same infra-flaky class dev itself shows (dev run 33134096643 fails a different macos test). Gate: causal fix or evidence-backed unrelated-flake disposition + fresh green run; never rerun-until-green without a cause | | ||||||||||||||
| | R5 | #2802 umbrella wire | codex/cursor-umbrella-wire | retarget to dev post-R4; CI green | | ||||||||||||||
|
|
||||||||||||||
| ## Per-round procedure | ||||||||||||||
|
|
||||||||||||||
| 1. Exact head SHA + full check rollup via gh. | ||||||||||||||
| 2. sol-medium reviewer: independent diff review, VERDICT line. | ||||||||||||||
| 3. Blockers folded or rebutted with rationale; repairs get focused tests. | ||||||||||||||
| 4. gh pr merge --squash --delete-branch; record merge SHA. | ||||||||||||||
| 5. Child retarget (gh pr edit --base dev) + verify checks restart. | ||||||||||||||
| 6. Post-merge: origin/dev log + no new cursor-test failures. | ||||||||||||||
|
Comment on lines
+21
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Retarget stacked children before deleting the parent branch. The procedure runs Proposed procedure order-4. gh pr merge --squash --delete-branch; record merge SHA.
-5. Child retarget (gh pr edit --base dev) + verify checks restart.
+4. Child retarget (gh pr edit --base dev) + verify checks restart.
+5. gh pr merge --squash --delete-branch; record merge SHA.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| ## Round log | ||||||||||||||
|
|
||||||||||||||
| - R1 (#2774): reviewer PASS (Tesla, sol-tier; coalescing phase-safe, consumers | ||||||||||||||
| checked). MERGED squash 5511a424c via --admin (user merge instruction = | ||||||||||||||
| maintainer approval; branch policy requires review). Head branch deleted. | ||||||||||||||
| SIDE EFFECT: base deletion auto-closed stacked #2795, which GitHub cannot | ||||||||||||||
| reopen (base ref gone). Recovery: cherry-picked 58ee805/a652f0d/e167311 | ||||||||||||||
| onto origin/dev (990a83f5e; 17 tests + tsc green on rebased head), | ||||||||||||||
| force-pushed the branch, opened successor PR #2803 vs dev. | ||||||||||||||
| LESSON for R4/R5: retarget the child to dev BEFORE merging the parent with | ||||||||||||||
| --delete-branch, or merge parent without branch deletion. | ||||||||||||||
| - R2 (#2803, successor of #2795): CI 23 ok / 0 fail (CodeRabbit status | ||||||||||||||
| marker non-required); prior audits stand (cherry-pick clean). MERGED | ||||||||||||||
| squash via --admin, branch deleted. | ||||||||||||||
| - R3 (#2769): reviewer PASS (Avicenna; precedence + claude derivation + | ||||||||||||||
| 72 focused tests + clean merge simulation). MERGED squash via --admin, | ||||||||||||||
| branch deleted. | ||||||||||||||
| - R4 (#2801): CI failure root-caused by investigator (Zeno): update-stop-first | ||||||||||||||
| 45s readiness deadline exhausted on loaded runners (46-47s failures on 4+ | ||||||||||||||
| unrelated PRs; catalog diff has no launcher imports, isolated shard). | ||||||||||||||
| Causal fix 22c073e03 raised the deadline to 90s (derived budget + pinned | ||||||||||||||
| arithmetic keep it honest). Fresh CI fully green (0F, macos SUCCESS). | ||||||||||||||
| MERGED squash 7232a60a7. #2802 retargeted to dev BEFORE branch deletion | ||||||||||||||
| (R1 lesson applied) — but the parent squash still made the old chain | ||||||||||||||
| CONFLICTING; wire branch cherry-picked onto dev (874f59734, 116 tests + | ||||||||||||||
| tsc green) and force-pushed; #2802 stayed OPEN base=dev. | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,3 +10,40 @@ | |
| 3. Back-compat proof: legacy-id wire table test green (every 69 id routes | ||
| to the same wire id as before, or documented intentional change). | ||
| 4. Stack finalization: PR A -> dev, PR B stacked; retarget checks. | ||
|
|
||
| ## Closure results (2026-08-28) | ||
|
|
||
| ### Cleanliness comparison | ||
|
|
||
| | Measure | Before (opencodex) | After | senpi | omo-ai@beta | | ||
| |---|---|---|---|---| | ||
| | Picker rows (cursor, non-router) | 65 | 47 seed rows / 31 umbrella identities | ~raw roster + grouped-with-fast-splits | none (no cursor map at all) | | ||
| | Variant duplicate rows | 22 (13 thinking + 7 fast + 2 x 1m) | 1 (claude-4-sonnet-1m real wire id) + composer-2.5-fast (no effort base) | thinking split retained for Claude; fast groups separate | n/a | | ||
| | Capability truth surfaces | 2 (effort-map tables + discovery seed annotations) | 1 (catalog.ts CURSOR_CAPABILITIES) | 3 (static TS table + 336-row generated alias JSON + display-name regexes) | 0 | | ||
| | Thinking handling | 13 separate picker rows | dimension; merged into base for ALL families | Claude-only thinkingMode split | delegated | | ||
| | Fast handling | 7 separate rows | dimension; aliases only | separate catalog groups; parameter fast always "false" | delegated | | ||
| | 1M/Max-Mode | single synthetic kimi-k3-1m row | window metadata generalized (claude/gemini/kimi/gpt-5.6 1M) + evidence-gated ultra->maxMode (static kimi-k3 + live maxModeModels union) | window/maxWindow fields; maxMode from name regex + family pattern (window-size inference we rejected as unsupported) | delegated | | ||
| | Back-compat | n/a | every legacy slug byte-identical (oracle + pinned-session tests) | variant-id fallback silently degrades to representative id | n/a | | ||
|
|
||
| LOC: effort-map.ts (229) still present as the test oracle only — zero src/ | ||
| consumers remain (request-builder/discovery now import catalog.ts; discovery | ||
| keeps two legacy helpers for the transition). catalog.ts is 541 lines | ||
| INCLUDING the full capability table that previously lived across two files | ||
| plus prose. Deletion of effort-map.ts is queued for the post-merge cleanup | ||
| once the oracle freezes to literal fixtures. | ||
|
|
||
| ### Picker proof | ||
|
|
||
| cursorUmbrellaRows(): 31 identities. Excerpt: kimi-k3 {efforts:[low,high,max], | ||
| window:1000000, maxModeVerified:true} — the old kimi-k3-1m row is gone and its | ||
| capability rides the base. Seed: 51 rows (4 router + 47). | ||
|
|
||
| ### Stack | ||
|
|
||
| | PR | base | head | state | | ||
| |---|---|---|---| | ||
| | #2801 core | dev | codex/cursor-umbrella-core 54965ef03 | open | | ||
| | #2802 wire | codex/cursor-umbrella-core | codex/cursor-umbrella-wire 075c5705a | open, retarget to dev after #2801 | | ||
|
Comment on lines
+43
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Synchronize the final stack state with the merge log. Lines 45-46 still show 🤖 Prompt for AI Agents |
||
|
|
||
| Verification totals: 1137 tests / 56 cursor+catalog files pass on the wire | ||
| head; tsc 0; privacy scan pass. CI is the wide gate per user instruction. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -275,10 +275,21 @@ export interface ParsedCursorVariantId { | |
| } | ||
|
|
||
| function stripLevelSuffix(id: string): { stem: string; level?: string } { | ||
| // Prefer the parse whose stem is a KNOWN capability, and among known stems | ||
| // the most specific (longest) one: "gpt-5.5-extra-high" must parse as | ||
| // gpt-5.5-extra + high (its real single-rung wire id), not gpt-5.5 + | ||
| // extra-high (A-gate blocker 2 family). | ||
| let fallback: { stem: string; level?: string } | undefined; | ||
| let best: { stem: string; level?: string } | undefined; | ||
| for (const token of LEVEL_TOKENS) { | ||
| if (id.endsWith(`-${token}`)) return { stem: id.slice(0, -(token.length + 1)), level: token }; | ||
| if (!id.endsWith(`-${token}`)) continue; | ||
| const candidate = { stem: id.slice(0, -(token.length + 1)), level: token }; | ||
| fallback ??= candidate; | ||
| if (CURSOR_CAPABILITIES[candidate.stem] && (best === undefined || candidate.stem.length > best.stem.length)) { | ||
| best = candidate; | ||
| } | ||
| } | ||
| return { stem: id }; | ||
| return best ?? fallback ?? { stem: id }; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -287,12 +298,22 @@ function stripLevelSuffix(id: string): { stem: string; level?: string } { | |
| * `gpt-5.1-codex-max` and `gpt-5.5-extra` — whose tails collide with effort | ||
| * tokens — never mis-parse (A-gate round-1 blocker 2). | ||
| */ | ||
| /** | ||
| * Real wire ids that merely END in "-1m" — they are distinct catalog rows the | ||
| * wire serves verbatim, never the synthetic ultra marker (A-gate blocker 2: | ||
| * a real legacy wire identity must not parse as `<base>-1m`). | ||
| */ | ||
| const REAL_1M_WIRE_IDS: ReadonlySet<string> = new Set(["claude-4-sonnet-1m"]); | ||
|
|
||
| export function parseCursorVariantId(rawId: string): ParsedCursorVariantId { | ||
| const id = rawId.trim(); | ||
| // 1. Exact base identity. | ||
| if (CURSOR_CAPABILITIES[id]) { | ||
| return { baseId: id, kind: defaultKindFor(id), ultra: false, known: true }; | ||
| } | ||
| if (REAL_1M_WIRE_IDS.has(id)) { | ||
| return { baseId: id, kind: "regular", ultra: false, known: false }; | ||
| } | ||
| // 2. cursor- wire prefix (regular grok wire forms). | ||
| if (id.startsWith("cursor-")) { | ||
| const inner = parseCursorVariantId(id.slice("cursor-".length)); | ||
|
|
@@ -444,10 +465,32 @@ export function resolveCursorSelection( | |
| ? `${capability.wirePrefix}${canonicalId}` | ||
| : canonicalId; | ||
| const ultraRequested = parsed.ultra || reasoning?.toLowerCase() === "ultra"; | ||
| const maxModeArmed = capability.maxModeVerified === true || liveMaxModeIds?.has(parsed.baseId) === true; | ||
| const evidence = liveMaxModeIds ?? liveCursorMaxModeBases; | ||
| const maxModeArmed = capability.maxModeVerified === true || evidence.has(parsed.baseId); | ||
| return { wireId, canonicalId, maxMode: ultraRequested && maxModeArmed, known: true }; | ||
|
Comment on lines
+468
to
470
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Honor the per-variant quarantine before composing the wire ID.
Route an explicit quarantined alias to a healthy default variant, or reject it before request construction. Add a regression assertion for 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| /** | ||
| * Live Max-Mode evidence (GetUsableModels maxModeModels). Provider discovery | ||
| * records the BASES the live roster flags; the resolver unions this with the | ||
| * static `maxModeVerified` gate so ultra generalizes automatically as evidence | ||
| * arrives — never from window size (devlog 260828 blocker-4 fold). | ||
| */ | ||
| let liveCursorMaxModeBases: ReadonlySet<string> = new Set(); | ||
|
|
||
| export function recordLiveCursorMaxModeModels(liveIds: readonly string[]): void { | ||
| const bases = new Set<string>(); | ||
| for (const id of liveIds) { | ||
| const parsed = parseCursorVariantId(id); | ||
| if (parsed.known) bases.add(parsed.baseId); | ||
| } | ||
| liveCursorMaxModeBases = bases; | ||
| } | ||
|
|
||
| export function liveCursorMaxModeBasesForTests(): ReadonlySet<string> { | ||
| return liveCursorMaxModeBases; | ||
| } | ||
|
|
||
| export interface CursorUmbrellaRow { | ||
| readonly id: string; | ||
| readonly efforts: readonly string[]; | ||
|
|
@@ -456,6 +499,27 @@ export interface CursorUmbrellaRow { | |
| readonly maxModeVerified: boolean; | ||
| } | ||
|
|
||
| /** | ||
| * Grok Fast keeps the parameterized wire shape (base id + effort/fast | ||
| * parameters) rather than a flattened -fast id — current Cursor clients send | ||
| * it that way and the flat form is rejected. Returns undefined for every | ||
| * other id. | ||
| */ | ||
| export function cursorGrokFastSelection( | ||
| pickedId: string, | ||
| reasoning: string | undefined, | ||
| ): { wireBaseId: string; effort: string } | undefined { | ||
| const parsed = parseCursorVariantId(pickedId); | ||
| if (!parsed.known || parsed.kind !== "fast") return undefined; | ||
| const capability = CURSOR_CAPABILITIES[parsed.baseId]; | ||
| if (capability?.wirePrefix !== "cursor-") return undefined; | ||
| const spec = capability.variants.fast; | ||
| if (!spec) return undefined; | ||
| const effort = cursorVariantEffort(spec, parsed.level ?? reasoning); | ||
| if (effort === undefined) return undefined; | ||
| return { wireBaseId: parsed.baseId, effort }; | ||
| } | ||
|
|
||
| /** | ||
| * The umbrella picker rows: one per base whose default variant is selectable. | ||
| * Thinking merges into the base row; fast/thinking-fast/legacy slugs stay | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import { | |
| cursorWireModelIdWithEffort, | ||
| CURSOR_THINKING_MODEL_IDS, | ||
| } from "./effort-map"; | ||
| import { parseCursorVariantId } from "./catalog"; | ||
|
|
||
| export interface CursorModelInfo { | ||
| id: string; | ||
|
|
@@ -76,9 +77,16 @@ function stripCursorWirePrefix(id: string): string { | |
| * ordinary `{base}-{effort}` form, or Cursor's current `{base-without-fast}-{effort}-fast` form. | ||
| */ | ||
| export function isCursorModelAvailableForAccount(modelId: string, liveIds: readonly string[]): boolean { | ||
| // Umbrella matching (devlog 260828_cursor_umbrella_catalog): a live suffix | ||
| // id counts toward its BASE — any variant dimension (thinking/fast/effort) | ||
| // proves the account can reach the umbrella. Unknown ids fall back to the | ||
| // legacy exact/suffix comparison so non-cataloged rows keep matching. | ||
| const parsedTarget = parseCursorVariantId(modelId); | ||
| return liveIds.some(raw => { | ||
| const id = stripCursorWirePrefix(raw); | ||
| if (id === modelId) return true; | ||
| const parsedLive = parseCursorVariantId(id); | ||
| if (parsedLive.known && parsedTarget.known && parsedLive.baseId === parsedTarget.baseId) return true; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an account's Useful? React with 👍 / 👎. |
||
| for (const effort of CANONICAL_EFFORT_SUFFIXES) { | ||
| if ( | ||
| id === `${modelId}-${effort}` || | ||
|
|
@@ -244,15 +252,13 @@ export function filterCursorConfiguredModelsByLiveDiscovery<T extends { id: stri | |
|
|
||
| /** | ||
| * Models GetUsableModels advertises but whose every Run returns not_found (catalog honesty, | ||
| * devlog 260826_cursor_responses_gap 060). Live probes 2026-08-26: cursor/claude-opus-5 failed | ||
| * 100% ("Cursor Connect error not_found") while its -fast and -thinking siblings — separate | ||
| * wire families — succeed. Quarantined here, in the shared filter, so live, cached, stale, and | ||
| * static serving paths all agree. Custom user provider overrides are not routed through this | ||
| * canonical seed and stay untouched. | ||
| * devlog 260826_cursor_responses_gap 060). The claude-opus-5 REGULAR wire family is the known | ||
| * case (probes 2026-08-26: 100% not_found while -fast/-thinking succeed) — under the umbrella | ||
| * catalog (devlog 260828) that quarantine moved to the RESOLVER level: the capability marks the | ||
| * regular VARIANT quarantined, the bare slug routes the healthy thinking variant, and the base | ||
| * row stays in the seed. This row-level set stays for future whole-base quarantines. | ||
| */ | ||
| export const CURSOR_KNOWN_UNCALLABLE_MODEL_IDS: ReadonlySet<string> = new Set([ | ||
| "claude-opus-5", | ||
| ]); | ||
| export const CURSOR_KNOWN_UNCALLABLE_MODEL_IDS: ReadonlySet<string> = new Set([]); | ||
|
|
||
| export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorModels([ | ||
| // Context windows and the model lineup mirror Cursor's public models/pricing docs plus the jawcode | ||
|
|
@@ -265,26 +271,26 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM | |
| // gemini/grok/kimi-k2.7/gpt-5-mini are reasoning models in the SOT but are sent bare (no tier picker). | ||
| ...CURSOR_ROUTER_MODEL_IDS.map(id => ({ id, contextWindow: CONTEXT_200K, supportsReasoningEffort: false })), | ||
|
|
||
| { id: "claude-sonnet-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| // Umbrella seed (devlog 260828_cursor_umbrella_catalog): one row per BASE | ||
| // model. Thinking merges into the base (the resolver routes the thinking | ||
| // variant); fast / thinking-fast / -1m stay routable as aliases but add no | ||
| // rows. Windows follow CURSOR_CAPABILITIES where the base is cataloged. | ||
| { id: "claude-sonnet-5", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| { id: "claude-4-sonnet", contextWindow: CONTEXT_200K }, | ||
| { id: "claude-4-sonnet-1m", contextWindow: CONTEXT_1M }, | ||
| { id: "claude-4.5-haiku", contextWindow: CONTEXT_200K }, | ||
| { id: "claude-4.5-sonnet", contextWindow: CONTEXT_200K }, | ||
| { id: "claude-4.5-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-4.6-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-4.6-sonnet", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-opus-4-7", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| // Opus Fast families: live GetUsableModels (260822) lists ONLY effort-suffixed wire ids | ||
| // ({base-without-fast}-{effort}-fast; the bare id returns not_found), so every entry | ||
| // carries a tier picker. Live-verified: claude-opus-4-8-high-fast completed a turn. | ||
| // Tiers per the 260822 dump (devlog 260822_senpi_cursor_transfer/300). | ||
| { id: "claude-opus-4-7-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-opus-4-8-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-opus-4-8", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| // claude-opus-5 (bare) removed from the seed: GetUsableModels lists it but every Run returns | ||
| // not_found (quarantined via CURSOR_KNOWN_UNCALLABLE_MODEL_IDS; -fast/-thinking families stay). | ||
| { id: "claude-opus-5-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-fable-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true }, | ||
| { id: "claude-4.6-opus", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| { id: "claude-4.6-sonnet", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| { id: "claude-opus-4-7", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| { id: "claude-opus-4-8", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| // claude-opus-5: regular variant is quarantined (not_found on every Run) but | ||
| // the umbrella row routes the THINKING variant, which is live — so the base | ||
| // row returns to the seed under the umbrella (resolver never sends the | ||
| // quarantined regular wire id for the bare slug). | ||
| { id: "claude-opus-5", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| { id: "claude-fable-5", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
|
|
||
| { id: "composer-1", contextWindow: CONTEXT_200K }, | ||
| { id: "composer-2.5", contextWindow: CONTEXT_200K }, | ||
|
|
@@ -301,17 +307,6 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM | |
| { id: "gemini-3.6-flash", contextWindow: CONTEXT_GEMINI, supportsReasoningEffort: true }, | ||
| { id: "gemini-3.7-flash", contextWindow: CONTEXT_GEMINI, supportsReasoningEffort: true }, | ||
|
|
||
| // Explicit-thinking variants (260825 live roster). Exposed as first-class ids the same way the | ||
| // Opus Fast families were in 831810c13: `isCursorModelAvailableForAccount` matches a base id | ||
| // against `{base}`, `{base}-{effort}` and the family's wire form, and none of those ever | ||
| // matched a `-thinking` id, so every one of these was invisible in the routed catalog. | ||
| // Suffix ORDER differs per family; `cursorWireModelIdWithEffort` owns that mapping. | ||
| ...CURSOR_THINKING_MODEL_IDS.map(id => ({ | ||
| id, | ||
| contextWindow: CONTEXT_200K, | ||
| supportsReasoningEffort: cursorModelHasEffortTiers(id), | ||
| })), | ||
|
|
||
| { id: "gpt-5-codex", contextWindow: CONTEXT_272K }, | ||
| { id: "gpt-5-fast", contextWindow: CONTEXT_272K }, | ||
| { id: "gpt-5-mini", contextWindow: CONTEXT_272K }, | ||
|
|
@@ -344,17 +339,15 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM | |
| { 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 }, | ||
| // kimi-k3-1m: synthetic ultra/Max-Mode picker variant (CURSOR_ULTRA_1M_MODEL_IDS) — wire sends | ||
| // kimi-k3-<effort> with maxMode=true; 1M context user-verified live on the Ultra plan | ||
| // (devlog 260826_cursor_responses_gap/025). inferCursorContextWindow maps "1m" ids to 1M. | ||
| { id: "kimi-k3-1m", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
| // kimi-k3 folds the old synthetic kimi-k3-1m row into the umbrella: the base | ||
| // is maxModeVerified (user-verified 1M on the Ultra plan, devlog 260826/025), | ||
| // so the ultra effort rung arms Max Mode on the wire and the separate picker | ||
| // row is gone. cursor/kimi-k3-1m stays routable as an alias. | ||
| { id: "kimi-k3", contextWindow: CONTEXT_1M, supportsReasoningEffort: true }, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For normal Codex Responses traffic, selecting AGENTS.md reference: src/AGENTS.md:L24-L26 Useful? React with 👍 / 👎. |
||
|
|
||
| { id: "grok-4.5", contextWindow: 500_000, supportsReasoningEffort: true }, | ||
| { id: "grok-4.5-fast", contextWindow: 500_000, supportsReasoningEffort: true }, | ||
| // 260813 preemptive: grok-4.6 seeded ahead of Cursor's lineup update (mirrors grok-4.5). | ||
| { id: "grok-4.6", contextWindow: 500_000, supportsReasoningEffort: true }, | ||
| { id: "grok-4.6-fast", contextWindow: 500_000, supportsReasoningEffort: true }, | ||
| ]); | ||
|
|
||
| export function cursorModelIds(models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS): string[] { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Record full head SHAs for every round.
Line 18 requires an exact head SHA, but the
headcolumn uses abbreviated SHAs for R1, R3, and R4 and branch names for R2 and R5. Record the full 40-character SHA for every round, or add a separate exact-SHA column. Otherwise, this log cannot prove which commit satisfied each gate.🤖 Prompt for AI Agents