@bitkyc08/opencodex 2.39.0 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -21
- package/gui/dist/assets/index-BHe2rl_C.js +112 -0
- package/gui/dist/assets/index-CJSb3HPe.css +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/cursor/catalog.ts +140 -7
- package/src/adapters/cursor/discovery.ts +79 -87
- package/src/adapters/cursor/effort-map.ts +11 -0
- package/src/adapters/cursor/request-builder.ts +31 -4
- package/src/adapters/cursor.ts +17 -0
- package/src/adapters/openai-chat.ts +95 -9
- package/src/adapters/openai-responses.ts +73 -9
- package/src/bridge.ts +58 -13
- package/src/claude/auth-mode.ts +6 -9
- package/src/claude/gateway-cache.ts +23 -3
- package/src/claude/model-info.ts +13 -2
- package/src/cli/access.ts +30 -0
- package/src/cli/account-extended.ts +19 -10
- package/src/cli/capabilities.ts +40 -1
- package/src/cli/claude-agent-startup-sync.ts +3 -0
- package/src/cli/claude.ts +134 -36
- package/src/cli/connect.ts +226 -0
- package/src/cli/dispatch.ts +126 -21
- package/src/cli/gui-pair-client.ts +170 -0
- package/src/cli/gui.ts +87 -0
- package/src/cli/help.ts +4 -1
- package/src/cli/index.ts +76 -22
- package/src/cli/models-runtime-subcommands.ts +34 -0
- package/src/cli/models-runtime.ts +4 -0
- package/src/cli/models.ts +2 -1
- package/src/cli/opencode.ts +2 -1
- package/src/cli/provider-runtime.ts +31 -1
- package/src/cli/registry.ts +32 -2
- package/src/cli/runtime-api.ts +10 -1
- package/src/cli/status.ts +26 -0
- package/src/cli/system-command.ts +9 -3
- package/src/client/connect.ts +650 -0
- package/src/client/hub-client.ts +457 -0
- package/src/client/hub-relay.ts +288 -0
- package/src/client/machine-api.ts +139 -0
- package/src/client/machine-auth.ts +54 -0
- package/src/client/machine-listener.ts +143 -0
- package/src/client/runtime.ts +93 -0
- package/src/client/state.ts +175 -0
- package/src/clients/config-export.ts +16 -5
- package/src/codex/auth-api.ts +169 -15
- package/src/codex/auth-context.ts +61 -6
- package/src/codex/catalog/aggregation.ts +17 -13
- package/src/codex/catalog/metadata.ts +28 -0
- package/src/codex/catalog/provider-fetch.ts +38 -5
- package/src/codex/catalog.ts +1 -1
- package/src/codex/desired-state.ts +13 -3
- package/src/codex/inject.ts +212 -31
- package/src/codex/journal.ts +54 -6
- package/src/codex/main-account.ts +105 -33
- package/src/codex/native-main-claim.ts +23 -1
- package/src/codex/native-residue.ts +7 -0
- package/src/codex/reset-credit-auto-redeem.ts +237 -0
- package/src/combos/request.ts +15 -3
- package/src/combos/types.ts +12 -0
- package/src/config/paths.ts +15 -1
- package/src/config/provider-validation.ts +40 -0
- package/src/config.ts +447 -3
- package/src/generated/compatibility-version.json +224 -108
- package/src/images/artifacts.ts +73 -37
- package/src/images/fulfill.ts +6 -1
- package/src/images/index.ts +1 -1
- package/src/images/plan.ts +16 -2
- package/src/images/synthetic-tool.ts +5 -0
- package/src/images/xai-client.ts +34 -1
- package/src/integrations/cursor-detect.ts +133 -0
- package/src/integrations/cursor-seen.ts +31 -0
- package/src/lib/errors.ts +18 -0
- package/src/lib/gui-pair-capability.ts +104 -0
- package/src/lib/lab-live-route-production.ts +2 -1
- package/src/lib/process-control.ts +4 -3
- package/src/lib/service-secrets.ts +161 -1
- package/src/lib/windows-system-proxy.ts +115 -0
- package/src/oauth/index.ts +3 -2
- package/src/oauth/pool-settings-capability.ts +55 -0
- package/src/providers/api-keys.ts +3 -1
- package/src/providers/codex-capacity.ts +34 -4
- package/src/providers/derive.ts +10 -0
- package/src/providers/fastwire.ts +10 -2
- package/src/providers/key-store.ts +197 -0
- package/src/providers/model-rename-migration.ts +3 -0
- package/src/providers/openai-sidecar.ts +3 -3
- package/src/providers/quota.ts +91 -42
- package/src/providers/registry.ts +33 -3
- package/src/reasoning-effort.ts +32 -0
- package/src/remote/protocol.ts +109 -0
- package/src/responses/citation-markers.ts +101 -0
- package/src/responses/parser.ts +43 -3
- package/src/responses/spill-store.ts +9 -4
- package/src/router.ts +72 -8
- package/src/server/auth-cors.ts +37 -1
- package/src/server/gui-session.ts +449 -0
- package/src/server/gui-static.ts +24 -7
- package/src/server/images.ts +237 -10
- package/src/server/index.ts +356 -30
- package/src/server/management/agent-settings-routes.ts +7 -1
- package/src/server/management/api-key-rotation.ts +74 -0
- package/src/server/management/combo-routes.ts +18 -6
- package/src/server/management/config-routes.ts +22 -3
- package/src/server/management/context.ts +5 -1
- package/src/server/management/cursor-integration-routes.ts +98 -0
- package/src/server/management/logs-usage-routes.ts +2 -1
- package/src/server/management/model-routes.ts +79 -1
- package/src/server/management/model-rows.ts +23 -1
- package/src/server/management/oauth-account-routes.ts +135 -2
- package/src/server/management/provider-routes.ts +143 -9
- package/src/server/management/route-registry.ts +10 -0
- package/src/server/management/session-routes.ts +13 -0
- package/src/server/management/system-routes.ts +13 -1
- package/src/server/management-api.ts +8 -3
- package/src/server/management-auth.ts +124 -82
- package/src/server/models-capabilities.ts +124 -0
- package/src/server/ports.ts +7 -0
- package/src/server/proxy-liveness.ts +7 -0
- package/src/server/request-log.ts +11 -5
- package/src/server/responses/agent-task-recovery.ts +1 -0
- package/src/server/responses/codex-auth-error.ts +3 -1
- package/src/server/responses/collaboration.ts +26 -1
- package/src/server/responses/combo-stream-preflight.ts +25 -6
- package/src/server/responses/compact.ts +32 -12
- package/src/server/responses/context-overflow.ts +49 -0
- package/src/server/responses/core.ts +196 -12
- package/src/server/responses/fetch-helpers.ts +2 -1
- package/src/server/responses/outbound-body-guard.ts +110 -0
- package/src/server/responses/ws-upstream.ts +87 -6
- package/src/server/responses-self-named-namespace-scrub.ts +181 -0
- package/src/server/system-env.ts +78 -25
- package/src/service.ts +218 -42
- package/src/types/config.ts +134 -0
- package/src/types/provider.ts +54 -1
- package/src/types/request.ts +2 -0
- package/src/types.ts +5 -0
- package/src/update/job.ts +33 -5
- package/src/usage/cost.ts +32 -1
- package/src/usage/expected-prices.ts +16 -0
- package/src/usage/log.ts +6 -2
- package/src/usage/summary.ts +48 -6
- package/gui/dist/assets/index-D-lchsPw.js +0 -112
- package/gui/dist/assets/index-uvENYLin.css +0 -1
|
@@ -32,6 +32,12 @@ export interface CursorCapability {
|
|
|
32
32
|
readonly variants: Partial<Record<CursorVariantKind, CursorVariantSpec>>;
|
|
33
33
|
/** Which variant the umbrella picker row selects (thinking merges into the base). */
|
|
34
34
|
readonly defaultVariant: CursorVariantKind;
|
|
35
|
+
/**
|
|
36
|
+
* Human picker label, in Cursor's own spelling. Codex would otherwise show the raw
|
|
37
|
+
* routed slug (`cursor/kimi-k3`), because `routedDisplayName` passes it through
|
|
38
|
+
* unchanged for every provider (codex/catalog/sync.ts).
|
|
39
|
+
*/
|
|
40
|
+
readonly displayName: string;
|
|
35
41
|
/** Context-window metadata (display/routing only — never implies maxMode). */
|
|
36
42
|
readonly window: number;
|
|
37
43
|
/** Max Mode proven on the wire for this base (static evidence; live maxModeModels unions in). */
|
|
@@ -46,6 +52,8 @@ const CONTEXT_256K = 256 * K;
|
|
|
46
52
|
const CONTEXT_272K = 272 * K;
|
|
47
53
|
const CONTEXT_500K = 500 * K;
|
|
48
54
|
const CONTEXT_1M = 1_000 * K;
|
|
55
|
+
/** Gemini publishes the exact power-of-two window, not a rounded 1M. */
|
|
56
|
+
const CONTEXT_GEMINI = 1_048_576;
|
|
49
57
|
|
|
50
58
|
const FULL = ["low", "medium", "high", "xhigh", "max"] as const;
|
|
51
59
|
const T = "thinking-then-effort" as const;
|
|
@@ -59,6 +67,7 @@ const E = "effort-then-thinking" as const;
|
|
|
59
67
|
*/
|
|
60
68
|
export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
61
69
|
"claude-4.5-opus": {
|
|
70
|
+
displayName: "Claude Opus 4.5",
|
|
62
71
|
window: CONTEXT_200K,
|
|
63
72
|
defaultVariant: "thinking",
|
|
64
73
|
variants: {
|
|
@@ -67,6 +76,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
67
76
|
},
|
|
68
77
|
},
|
|
69
78
|
"claude-4.6-opus": {
|
|
79
|
+
displayName: "Claude Opus 4.6",
|
|
70
80
|
window: CONTEXT_1M,
|
|
71
81
|
defaultVariant: "thinking",
|
|
72
82
|
variants: {
|
|
@@ -75,6 +85,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
75
85
|
},
|
|
76
86
|
},
|
|
77
87
|
"claude-4.6-sonnet": {
|
|
88
|
+
displayName: "Claude Sonnet 4.6",
|
|
78
89
|
window: CONTEXT_1M,
|
|
79
90
|
defaultVariant: "thinking",
|
|
80
91
|
variants: {
|
|
@@ -83,6 +94,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
83
94
|
},
|
|
84
95
|
},
|
|
85
96
|
"claude-4.5-sonnet": {
|
|
97
|
+
displayName: "Claude Sonnet 4.5",
|
|
86
98
|
window: CONTEXT_200K,
|
|
87
99
|
defaultVariant: "thinking",
|
|
88
100
|
variants: {
|
|
@@ -91,6 +103,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
91
103
|
},
|
|
92
104
|
},
|
|
93
105
|
"claude-4-sonnet": {
|
|
106
|
+
displayName: "Claude Sonnet 4",
|
|
94
107
|
window: CONTEXT_200K,
|
|
95
108
|
defaultVariant: "thinking",
|
|
96
109
|
variants: {
|
|
@@ -99,6 +112,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
99
112
|
},
|
|
100
113
|
},
|
|
101
114
|
"claude-fable-5": {
|
|
115
|
+
displayName: "Claude Fable 5",
|
|
102
116
|
window: CONTEXT_1M,
|
|
103
117
|
defaultVariant: "thinking",
|
|
104
118
|
variants: {
|
|
@@ -106,7 +120,41 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
106
120
|
thinking: { levels: FULL, order: T },
|
|
107
121
|
},
|
|
108
122
|
},
|
|
123
|
+
// 260902 preemptive: Claude Fable 5.1 seeded ahead of Cursor's lineup update, mirroring
|
|
124
|
+
// claude-fable-5 (same 1M window and full effort ladder). Cursor has spelled Claude ids
|
|
125
|
+
// both Anthropic-style (`claude-opus-4-7`, thinking-then-effort) and version-first
|
|
126
|
+
// (`claude-4.6-opus`, effort-then-thinking), so all three plausible spellings are seeded;
|
|
127
|
+
// the live GetUsableModels filter drops whichever the roster does not expose. Collapse to
|
|
128
|
+
// the one real spelling once it is observed.
|
|
129
|
+
"claude-fable-5-1": {
|
|
130
|
+
displayName: "Claude Fable 5.1",
|
|
131
|
+
window: CONTEXT_1M,
|
|
132
|
+
defaultVariant: "thinking",
|
|
133
|
+
variants: {
|
|
134
|
+
regular: { levels: FULL },
|
|
135
|
+
thinking: { levels: FULL, order: T },
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
"claude-fable-5.1": {
|
|
139
|
+
displayName: "Claude Fable 5.1",
|
|
140
|
+
window: CONTEXT_1M,
|
|
141
|
+
defaultVariant: "thinking",
|
|
142
|
+
variants: {
|
|
143
|
+
regular: { levels: FULL },
|
|
144
|
+
thinking: { levels: FULL, order: T },
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
"claude-5.1-fable": {
|
|
148
|
+
displayName: "Claude Fable 5.1",
|
|
149
|
+
window: CONTEXT_1M,
|
|
150
|
+
defaultVariant: "thinking",
|
|
151
|
+
variants: {
|
|
152
|
+
regular: { levels: FULL },
|
|
153
|
+
thinking: { levels: FULL, order: E },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
109
156
|
"claude-sonnet-5": {
|
|
157
|
+
displayName: "Claude Sonnet 5",
|
|
110
158
|
window: CONTEXT_1M,
|
|
111
159
|
defaultVariant: "thinking",
|
|
112
160
|
variants: {
|
|
@@ -115,6 +163,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
115
163
|
},
|
|
116
164
|
},
|
|
117
165
|
"claude-opus-4-7": {
|
|
166
|
+
displayName: "Claude Opus 4.7",
|
|
118
167
|
window: CONTEXT_1M,
|
|
119
168
|
defaultVariant: "thinking",
|
|
120
169
|
variants: {
|
|
@@ -125,6 +174,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
125
174
|
},
|
|
126
175
|
},
|
|
127
176
|
"claude-opus-4-8": {
|
|
177
|
+
displayName: "Claude Opus 4.8",
|
|
128
178
|
window: CONTEXT_1M,
|
|
129
179
|
defaultVariant: "thinking",
|
|
130
180
|
variants: {
|
|
@@ -135,6 +185,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
135
185
|
},
|
|
136
186
|
},
|
|
137
187
|
"claude-opus-5": {
|
|
188
|
+
displayName: "Claude Opus 5",
|
|
138
189
|
window: CONTEXT_1M,
|
|
139
190
|
defaultVariant: "thinking",
|
|
140
191
|
variants: {
|
|
@@ -147,32 +198,38 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
147
198
|
},
|
|
148
199
|
},
|
|
149
200
|
"glm-5.2": {
|
|
201
|
+
displayName: "GLM 5.2",
|
|
150
202
|
window: CONTEXT_1M,
|
|
151
203
|
defaultVariant: "regular",
|
|
152
204
|
variants: { regular: { levels: ["high", "max"] } },
|
|
153
205
|
},
|
|
154
206
|
"glm-5.3": {
|
|
207
|
+
displayName: "GLM 5.3",
|
|
155
208
|
window: CONTEXT_1M,
|
|
156
209
|
defaultVariant: "regular",
|
|
157
210
|
variants: { regular: { levels: ["low", "high", "max"] } },
|
|
158
211
|
},
|
|
159
212
|
"gemini-3.6-flash": {
|
|
160
|
-
|
|
213
|
+
displayName: "Gemini 3.6 Flash",
|
|
214
|
+
window: CONTEXT_GEMINI,
|
|
161
215
|
defaultVariant: "regular",
|
|
162
216
|
variants: { regular: { levels: ["minimal", "low", "medium", "high"] } },
|
|
163
217
|
},
|
|
164
218
|
"gemini-3.7-flash": {
|
|
165
|
-
|
|
219
|
+
displayName: "Gemini 3.7 Flash",
|
|
220
|
+
window: CONTEXT_GEMINI,
|
|
166
221
|
defaultVariant: "regular",
|
|
167
222
|
variants: { regular: { levels: ["low", "medium", "high"] } },
|
|
168
223
|
},
|
|
169
224
|
"kimi-k3": {
|
|
225
|
+
displayName: "Kimi K3",
|
|
170
226
|
window: CONTEXT_1M,
|
|
171
227
|
defaultVariant: "regular",
|
|
172
228
|
maxModeVerified: true,
|
|
173
229
|
variants: { regular: { levels: ["low", "high", "max"] } },
|
|
174
230
|
},
|
|
175
231
|
"grok-4.5": {
|
|
232
|
+
displayName: "Cursor Grok 4.5",
|
|
176
233
|
window: CONTEXT_500K,
|
|
177
234
|
defaultVariant: "regular",
|
|
178
235
|
wirePrefix: "cursor-",
|
|
@@ -182,6 +239,7 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
182
239
|
},
|
|
183
240
|
},
|
|
184
241
|
"grok-4.6": {
|
|
242
|
+
displayName: "Cursor Grok 4.6",
|
|
185
243
|
window: CONTEXT_500K,
|
|
186
244
|
defaultVariant: "regular",
|
|
187
245
|
wirePrefix: "cursor-",
|
|
@@ -191,71 +249,88 @@ export const CURSOR_CAPABILITIES: Record<string, CursorCapability> = {
|
|
|
191
249
|
},
|
|
192
250
|
},
|
|
193
251
|
"gpt-5.1": {
|
|
252
|
+
displayName: "GPT-5.1",
|
|
194
253
|
window: CONTEXT_272K,
|
|
195
254
|
defaultVariant: "regular",
|
|
196
255
|
variants: { regular: { levels: ["low", "high"] } },
|
|
197
256
|
},
|
|
198
257
|
"gpt-5.1-codex-max": {
|
|
258
|
+
displayName: "GPT-5.1 Codex Max",
|
|
199
259
|
window: CONTEXT_272K,
|
|
200
260
|
defaultVariant: "regular",
|
|
201
261
|
variants: { regular: { levels: ["low", "medium", "high", "xhigh"] } },
|
|
202
262
|
},
|
|
203
263
|
"gpt-5.1-codex-mini": {
|
|
264
|
+
displayName: "GPT-5.1 Codex Mini",
|
|
204
265
|
window: CONTEXT_272K,
|
|
205
266
|
defaultVariant: "regular",
|
|
206
267
|
variants: { regular: { levels: ["low", "high"] } },
|
|
207
268
|
},
|
|
208
269
|
"gpt-5.2": {
|
|
270
|
+
displayName: "GPT-5.2",
|
|
209
271
|
window: CONTEXT_272K,
|
|
210
272
|
defaultVariant: "regular",
|
|
211
273
|
variants: { regular: { levels: ["low", "high", "xhigh"] } },
|
|
212
274
|
},
|
|
213
275
|
"gpt-5.2-codex": {
|
|
276
|
+
displayName: "GPT-5.2 Codex",
|
|
214
277
|
window: CONTEXT_272K,
|
|
215
278
|
defaultVariant: "regular",
|
|
216
279
|
variants: { regular: { levels: ["low", "high", "xhigh"] } },
|
|
217
280
|
},
|
|
218
281
|
"gpt-5.3-codex": {
|
|
282
|
+
displayName: "Codex 5.3",
|
|
219
283
|
window: CONTEXT_272K,
|
|
220
284
|
defaultVariant: "regular",
|
|
221
285
|
variants: { regular: { levels: ["low", "high", "xhigh"] } },
|
|
222
286
|
},
|
|
223
287
|
"gpt-5.4": {
|
|
288
|
+
displayName: "GPT-5.4",
|
|
224
289
|
window: CONTEXT_272K,
|
|
225
290
|
defaultVariant: "regular",
|
|
226
291
|
variants: { regular: { levels: ["low", "medium", "high", "xhigh"] } },
|
|
227
292
|
},
|
|
228
293
|
"gpt-5.4-mini": {
|
|
294
|
+
displayName: "GPT-5.4 Mini",
|
|
229
295
|
window: CONTEXT_272K,
|
|
230
296
|
defaultVariant: "regular",
|
|
231
297
|
variants: { regular: { levels: ["low", "medium", "high", "xhigh"] } },
|
|
232
298
|
},
|
|
233
299
|
"gpt-5.4-nano": {
|
|
300
|
+
displayName: "GPT-5.4 Nano",
|
|
234
301
|
window: CONTEXT_272K,
|
|
235
302
|
defaultVariant: "regular",
|
|
236
303
|
variants: { regular: { levels: ["low", "medium", "high", "xhigh"] } },
|
|
237
304
|
},
|
|
238
305
|
"gpt-5.5": {
|
|
306
|
+
displayName: "GPT-5.5",
|
|
239
307
|
window: CONTEXT_272K,
|
|
240
308
|
defaultVariant: "regular",
|
|
241
309
|
variants: { regular: { levels: ["low", "medium", "high"] } },
|
|
242
310
|
},
|
|
243
311
|
"gpt-5.5-extra": {
|
|
244
|
-
|
|
312
|
+
displayName: "GPT-5.5 Extra",
|
|
313
|
+
// Live GetUsableModels reports 200K for this row, not the gpt-5 family's 272K
|
|
314
|
+
// (account-verified 260709). The seed carried the measured number; the capability
|
|
315
|
+
// table was approximating from the family.
|
|
316
|
+
window: CONTEXT_200K,
|
|
245
317
|
defaultVariant: "regular",
|
|
246
318
|
variants: { regular: { levels: ["high"] } },
|
|
247
319
|
},
|
|
248
320
|
"gpt-5.6-sol": {
|
|
321
|
+
displayName: "GPT-5.6 Sol",
|
|
249
322
|
window: CONTEXT_1M,
|
|
250
323
|
defaultVariant: "regular",
|
|
251
324
|
variants: { regular: { levels: FULL } },
|
|
252
325
|
},
|
|
253
326
|
"gpt-5.6-terra": {
|
|
327
|
+
displayName: "GPT-5.6 Terra",
|
|
254
328
|
window: CONTEXT_1M,
|
|
255
329
|
defaultVariant: "regular",
|
|
256
330
|
variants: { regular: { levels: FULL } },
|
|
257
331
|
},
|
|
258
332
|
"gpt-5.6-luna": {
|
|
333
|
+
displayName: "GPT-5.6 Luna",
|
|
259
334
|
window: CONTEXT_1M,
|
|
260
335
|
defaultVariant: "regular",
|
|
261
336
|
variants: { regular: { levels: FULL } },
|
|
@@ -368,6 +443,53 @@ function defaultKindFor(baseId: string): CursorVariantKind {
|
|
|
368
443
|
return CURSOR_CAPABILITIES[baseId]?.defaultVariant ?? "regular";
|
|
369
444
|
}
|
|
370
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Promote a variant to its fast sibling when the base declares one, else leave it alone.
|
|
448
|
+
*
|
|
449
|
+
* Thinking must map to thinkingFast rather than to the plain fast variant: the umbrella row
|
|
450
|
+
* for a Claude base routes THINKING, and its regular-fast sibling is a different product
|
|
451
|
+
* with a shorter ladder (claude-opus-5-fast stops at high) whose regular family is
|
|
452
|
+
* quarantined. A base with no fast dimension keeps its kind, so Fast degrades to today's
|
|
453
|
+
* behavior instead of erroring.
|
|
454
|
+
*/
|
|
455
|
+
export function upgradeToFast(baseId: string, kind: CursorVariantKind): CursorVariantKind {
|
|
456
|
+
const variants = CURSOR_CAPABILITIES[baseId]?.variants;
|
|
457
|
+
if (!variants) return kind;
|
|
458
|
+
if (kind === "thinking" || kind === "thinkingFast") {
|
|
459
|
+
return variants.thinkingFast ? "thinkingFast" : kind;
|
|
460
|
+
}
|
|
461
|
+
return variants.fast ? "fast" : kind;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Bases whose capability declares a fast or thinking-fast variant. */
|
|
465
|
+
export function cursorFastCapableBases(): string[] {
|
|
466
|
+
return Object.entries(CURSOR_CAPABILITIES)
|
|
467
|
+
.filter(([, capability]) => capability.variants.fast !== undefined
|
|
468
|
+
|| capability.variants.thinkingFast !== undefined)
|
|
469
|
+
.map(([baseId]) => baseId);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* The id to LIST for a base when the global fast switch is on, for clients that have no
|
|
474
|
+
* Fast toggle of their own. Undefined when the base has no fast dimension, so a caller
|
|
475
|
+
* cannot advertise an id that would not route.
|
|
476
|
+
*
|
|
477
|
+
* Composed from the base's defaultVariant rather than a bare `-fast` suffix. Measured: for a
|
|
478
|
+
* thinking-default base, `claude-opus-5-fast` parses back as the REGULAR-fast sibling and
|
|
479
|
+
* resolves to `claude-opus-5-high-fast` — a shorter ladder, in the quarantined regular
|
|
480
|
+
* family, and a different wire from what the Codex toggle sends. The mirror case is equally
|
|
481
|
+
* wrong: grok has no thinkingFast spec, so `grok-4.6-thinking-fast` would fall back to the
|
|
482
|
+
* regular spec and emit a bare `grok-4.6` with no effort and no fast marker at all.
|
|
483
|
+
*/
|
|
484
|
+
export function cursorFastIdFor(baseId: string): string | undefined {
|
|
485
|
+
const capability = CURSOR_CAPABILITIES[baseId];
|
|
486
|
+
if (!capability) return undefined;
|
|
487
|
+
const kind = upgradeToFast(baseId, capability.defaultVariant);
|
|
488
|
+
if (kind === "thinkingFast") return `${baseId}-thinking-fast`;
|
|
489
|
+
if (kind === "fast") return `${baseId}-fast`;
|
|
490
|
+
return undefined;
|
|
491
|
+
}
|
|
492
|
+
|
|
371
493
|
function normalizeRequestedEffort(reasoning: string | undefined): string | undefined {
|
|
372
494
|
const normalized = reasoning?.toLowerCase();
|
|
373
495
|
return normalized === "ultra" ? "max" : normalized;
|
|
@@ -448,20 +570,25 @@ export function resolveCursorSelection(
|
|
|
448
570
|
pickedId: string,
|
|
449
571
|
reasoning: string | undefined,
|
|
450
572
|
liveMaxModeIds?: ReadonlySet<string>,
|
|
573
|
+
options: { fast?: boolean } = {},
|
|
451
574
|
): CursorResolvedSelection {
|
|
452
575
|
const parsed = parseCursorVariantId(pickedId);
|
|
453
576
|
if (!parsed.known) {
|
|
454
577
|
return { wireId: pickedId, canonicalId: pickedId, maxMode: false, known: false };
|
|
455
578
|
}
|
|
456
579
|
const capability = CURSOR_CAPABILITIES[parsed.baseId]!;
|
|
457
|
-
|
|
580
|
+
// Codex's Fast toggle is a variant switch here; every later read must use the upgraded
|
|
581
|
+
// kind, not parsed.kind, or the wire id loses its -fast marker (or keeps the cursor-
|
|
582
|
+
// prefix that only the regular variant takes).
|
|
583
|
+
const kind = options.fast === true ? upgradeToFast(parsed.baseId, parsed.kind) : parsed.kind;
|
|
584
|
+
const spec = capability.variants[kind] ?? capability.variants.regular;
|
|
458
585
|
if (!spec) {
|
|
459
586
|
return { wireId: parsed.baseId, canonicalId: parsed.baseId, maxMode: false, known: true };
|
|
460
587
|
}
|
|
461
588
|
const requested = parsed.level ?? reasoning;
|
|
462
589
|
const effort = cursorVariantEffort(spec, requested);
|
|
463
|
-
const canonicalId = composeWireId(parsed.baseId,
|
|
464
|
-
const wireId = capability.wirePrefix &&
|
|
590
|
+
const canonicalId = composeWireId(parsed.baseId, kind, effort);
|
|
591
|
+
const wireId = capability.wirePrefix && kind === "regular"
|
|
465
592
|
? `${capability.wirePrefix}${canonicalId}`
|
|
466
593
|
: canonicalId;
|
|
467
594
|
const ultraRequested = parsed.ultra || reasoning?.toLowerCase() === "ultra";
|
|
@@ -493,6 +620,7 @@ export function liveCursorMaxModeBasesForTests(): ReadonlySet<string> {
|
|
|
493
620
|
|
|
494
621
|
export interface CursorUmbrellaRow {
|
|
495
622
|
readonly id: string;
|
|
623
|
+
readonly displayName: string;
|
|
496
624
|
readonly efforts: readonly string[];
|
|
497
625
|
readonly window: number;
|
|
498
626
|
/** Max Mode evidence present: the ultra rung maps to maxMode on the wire. */
|
|
@@ -508,9 +636,13 @@ export interface CursorUmbrellaRow {
|
|
|
508
636
|
export function cursorGrokFastSelection(
|
|
509
637
|
pickedId: string,
|
|
510
638
|
reasoning: string | undefined,
|
|
639
|
+
fast?: boolean,
|
|
511
640
|
): { wireBaseId: string; effort: string } | undefined {
|
|
512
641
|
const parsed = parseCursorVariantId(pickedId);
|
|
513
|
-
|
|
642
|
+
// Both call paths must learn the flag together: if only resolveCursorSelection did, a
|
|
643
|
+
// toggled Grok pick would emit a flattened grok-4.6-high-fast id, which the wire rejects.
|
|
644
|
+
const kind = fast === true ? upgradeToFast(parsed.baseId, parsed.kind) : parsed.kind;
|
|
645
|
+
if (!parsed.known || kind !== "fast") return undefined;
|
|
514
646
|
const capability = CURSOR_CAPABILITIES[parsed.baseId];
|
|
515
647
|
if (capability?.wirePrefix !== "cursor-") return undefined;
|
|
516
648
|
const spec = capability.variants.fast;
|
|
@@ -532,6 +664,7 @@ export function cursorUmbrellaRows(): CursorUmbrellaRow[] {
|
|
|
532
664
|
if (!spec || spec.quarantined) continue;
|
|
533
665
|
rows.push({
|
|
534
666
|
id: baseId,
|
|
667
|
+
displayName: capability.displayName,
|
|
535
668
|
efforts: spec.levels,
|
|
536
669
|
window: capability.window,
|
|
537
670
|
maxModeVerified: capability.maxModeVerified === true,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
cursorWireModelIdWithEffort,
|
|
6
6
|
CURSOR_THINKING_MODEL_IDS,
|
|
7
7
|
} from "./effort-map";
|
|
8
|
-
import { parseCursorVariantId } from "./catalog";
|
|
8
|
+
import { cursorUmbrellaRows, parseCursorVariantId } from "./catalog";
|
|
9
9
|
|
|
10
10
|
export interface CursorModelInfo {
|
|
11
11
|
id: string;
|
|
@@ -30,6 +30,8 @@ export function inferCursorContextWindow(modelId: string): number {
|
|
|
30
30
|
if (id.includes("1m")) return CONTEXT_1M;
|
|
31
31
|
if (id.startsWith("gemini-")) return CONTEXT_1M;
|
|
32
32
|
if (id === "glm-5.3" || id === "glm-5.2") return CONTEXT_1M;
|
|
33
|
+
// 260902: every Fable is a 1M model; catch live spellings the seed does not carry.
|
|
34
|
+
if (id.includes("fable")) return CONTEXT_1M;
|
|
33
35
|
if (id.startsWith("gpt-5.6-")) return CONTEXT_1M;
|
|
34
36
|
if (id.startsWith("gpt-5") || id === "gpt-5-codex") return CONTEXT_272K;
|
|
35
37
|
if (id.startsWith("grok-4.5") || id.startsWith("grok-4.6")) return 500_000;
|
|
@@ -260,96 +262,86 @@ export function filterCursorConfiguredModelsByLiveDiscovery<T extends { id: stri
|
|
|
260
262
|
*/
|
|
261
263
|
export const CURSOR_KNOWN_UNCALLABLE_MODEL_IDS: ReadonlySet<string> = new Set([]);
|
|
262
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Cursor products that are NOT a dimension of any capability base. Each carries its own
|
|
267
|
+
* label because there is no capability record to read one from. A row belongs here only
|
|
268
|
+
* when Cursor ships it as a distinct product; a variant of a cataloged base does not.
|
|
269
|
+
*/
|
|
270
|
+
export const CURSOR_PRODUCT_MODELS: readonly (CursorModelInfo & { displayName: string })[] = [
|
|
271
|
+
{ id: "claude-4.5-haiku", displayName: "Claude Haiku 4.5", contextWindow: CONTEXT_200K },
|
|
272
|
+
{ id: "composer-1", displayName: "Composer 1", contextWindow: CONTEXT_200K },
|
|
273
|
+
{ id: "composer-2.5", displayName: "Composer 2.5", contextWindow: CONTEXT_200K },
|
|
274
|
+
{ id: "gemini-2.5-flash", displayName: "Gemini 2.5 Flash", contextWindow: CONTEXT_GEMINI },
|
|
275
|
+
{ id: "gemini-3-flash", displayName: "Gemini 3 Flash", contextWindow: CONTEXT_GEMINI },
|
|
276
|
+
{ id: "gemini-3-pro", displayName: "Gemini 3 Pro", contextWindow: CONTEXT_GEMINI },
|
|
277
|
+
{ id: "gemini-3-pro-image-preview", displayName: "Gemini 3 Pro Image", contextWindow: CONTEXT_200K },
|
|
278
|
+
{ id: "gemini-3.1-pro", displayName: "Gemini 3.1 Pro", contextWindow: CONTEXT_GEMINI },
|
|
279
|
+
{ id: "gemini-3.5-flash", displayName: "Gemini 3.5 Flash", contextWindow: CONTEXT_200K },
|
|
280
|
+
{ id: "gpt-5-codex", displayName: "GPT-5 Codex", contextWindow: CONTEXT_272K },
|
|
281
|
+
{ id: "gpt-5-mini", displayName: "GPT-5 Mini", contextWindow: CONTEXT_272K },
|
|
282
|
+
{ id: "gpt-5.1-codex", displayName: "GPT-5.1 Codex", contextWindow: CONTEXT_272K },
|
|
283
|
+
{ id: "kimi-k2.7-code", displayName: "Kimi K2.7 Code", contextWindow: CONTEXT_262K },
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Real upstream wire ids that LOOK like a dimension of a cataloged base but are served as
|
|
288
|
+
* their own catalog row by Cursor, so they stay rows rather than folding into a base.
|
|
289
|
+
*
|
|
290
|
+
* - `claude-4-sonnet-1m`: a distinct 1M-window row upstream, not `claude-4-sonnet` + ultra.
|
|
291
|
+
* claude-4-sonnet carries no maxMode evidence, so folding it would invent a capability.
|
|
292
|
+
* `REAL_1M_WIRE_IDS` in catalog.ts already stops the parser reading it as the synthetic
|
|
293
|
+
* marker.
|
|
294
|
+
* - `gpt-5-fast`: there is no `gpt-5` capability base for it to be a dimension of.
|
|
295
|
+
* - `composer-2.5-fast`: composer-2.5 has no effort or variant dimensions at all.
|
|
296
|
+
*/
|
|
297
|
+
export const CURSOR_REAL_ID_EXCEPTIONS: readonly (CursorModelInfo & { displayName: string })[] = [
|
|
298
|
+
{ id: "claude-4-sonnet-1m", displayName: "Claude Sonnet 4 (1M)", contextWindow: CONTEXT_1M },
|
|
299
|
+
{ id: "gpt-5-fast", displayName: "GPT-5 Fast", contextWindow: CONTEXT_272K },
|
|
300
|
+
{ id: "composer-2.5-fast", displayName: "Composer 2.5 Fast", contextWindow: CONTEXT_200K },
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
/** Picker labels for the auto-router rows, which have no capability record. */
|
|
304
|
+
const CURSOR_ROUTER_DISPLAY_NAMES: Readonly<Record<string, string>> = {
|
|
305
|
+
auto: "Auto",
|
|
306
|
+
"auto-cost": "Auto (Cost)",
|
|
307
|
+
"auto-balance": "Auto (Balanced)",
|
|
308
|
+
"auto-intelligence": "Auto (Intelligence)",
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* The published Cursor row set. DERIVED from CURSOR_CAPABILITIES via cursorUmbrellaRows()
|
|
313
|
+
* (devlog 260902_cursor_unified_identity) so the capability table and the picker can no
|
|
314
|
+
* longer disagree: one row per base, with thinking / fast / synthetic -1m remaining
|
|
315
|
+
* routable aliases that add no rows.
|
|
316
|
+
*
|
|
317
|
+
* Before this, the seed was a hand-maintained list that drifted from the capability table —
|
|
318
|
+
* `cursorUmbrellaRows()` existed but only tests called it, so collapsing a variant changed
|
|
319
|
+
* routing without changing what Codex listed.
|
|
320
|
+
*
|
|
321
|
+
* Windows and effort ladders come from the capability record; the two lists below carry the
|
|
322
|
+
* ids that have no capability record, each with its own label and window.
|
|
323
|
+
*/
|
|
263
324
|
export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorModels([
|
|
264
|
-
// Context windows and the model lineup mirror Cursor's public models/pricing docs plus the jawcode
|
|
265
|
-
// SOT (../jawcode/packages/ai/src/models.json, `cursor` provider), which mirrors the real
|
|
266
|
-
// GetUsableModels catalog. Live discovery is the preferred path when logged in; these ids seed the
|
|
267
|
-
// routed Codex catalog and provide a static fallback. Cursor base ids carry no effort suffix here —
|
|
268
|
-
// the request builder appends the per-model suffix (see effort-map.ts) and reasoning models
|
|
269
|
-
// advertise effort so Codex exposes the tier picker. `supportsReasoningEffort` tracks whether the
|
|
270
|
-
// model has *selectable effort tiers* (CURSOR_MODEL_EFFORT_TIERS), NOT merely whether it reasons:
|
|
271
|
-
// gemini/grok/kimi-k2.7/gpt-5-mini are reasoning models in the SOT but are sent bare (no tier picker).
|
|
272
325
|
...CURSOR_ROUTER_MODEL_IDS.map(id => ({ id, contextWindow: CONTEXT_200K, supportsReasoningEffort: false })),
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
{ id: "claude-4-sonnet-1m", contextWindow: CONTEXT_1M },
|
|
281
|
-
{ id: "claude-4.5-haiku", contextWindow: CONTEXT_200K },
|
|
282
|
-
{ id: "claude-4.5-sonnet", contextWindow: CONTEXT_200K },
|
|
283
|
-
{ id: "claude-4.5-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
|
|
284
|
-
{ id: "claude-4.6-opus", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
285
|
-
{ id: "claude-4.6-sonnet", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
286
|
-
{ id: "claude-opus-4-7", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
287
|
-
{ id: "claude-opus-4-8", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
288
|
-
// claude-opus-5: regular variant is quarantined (not_found on every Run) but
|
|
289
|
-
// the umbrella row routes the THINKING variant, which is live — so the base
|
|
290
|
-
// row returns to the seed under the umbrella (resolver never sends the
|
|
291
|
-
// quarantined regular wire id for the bare slug).
|
|
292
|
-
{ id: "claude-opus-5", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
293
|
-
{ id: "claude-fable-5", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
294
|
-
|
|
295
|
-
{ id: "composer-1", contextWindow: CONTEXT_200K },
|
|
296
|
-
{ id: "composer-2.5", contextWindow: CONTEXT_200K },
|
|
297
|
-
{ id: "composer-2.5-fast", contextWindow: CONTEXT_200K },
|
|
298
|
-
|
|
299
|
-
{ id: "gemini-2.5-flash", contextWindow: CONTEXT_GEMINI },
|
|
300
|
-
{ id: "gemini-3-flash", contextWindow: CONTEXT_GEMINI },
|
|
301
|
-
{ id: "gemini-3-pro", contextWindow: CONTEXT_GEMINI },
|
|
302
|
-
{ id: "gemini-3-pro-image-preview", contextWindow: CONTEXT_200K },
|
|
303
|
-
{ id: "gemini-3.1-pro", contextWindow: CONTEXT_GEMINI },
|
|
304
|
-
{ id: "gemini-3.5-flash", contextWindow: CONTEXT_200K },
|
|
305
|
-
// 260825 live GetUsableModels: both ship only as effort-suffixed ids, so each exposes a tier
|
|
306
|
-
// picker. 3.6 is the only Cursor model with a `minimal` rung.
|
|
307
|
-
{ id: "gemini-3.6-flash", contextWindow: CONTEXT_GEMINI, supportsReasoningEffort: true },
|
|
308
|
-
{ id: "gemini-3.7-flash", contextWindow: CONTEXT_GEMINI, supportsReasoningEffort: true },
|
|
309
|
-
|
|
310
|
-
{ id: "gpt-5-codex", contextWindow: CONTEXT_272K },
|
|
311
|
-
{ id: "gpt-5-fast", contextWindow: CONTEXT_272K },
|
|
312
|
-
{ id: "gpt-5-mini", contextWindow: CONTEXT_272K },
|
|
313
|
-
{ id: "gpt-5.1", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
314
|
-
{ id: "gpt-5.1-codex", contextWindow: CONTEXT_272K },
|
|
315
|
-
{ id: "gpt-5.1-codex-max", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
316
|
-
{ id: "gpt-5.1-codex-mini", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
317
|
-
{ id: "gpt-5.2", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
318
|
-
{ id: "gpt-5.2-codex", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
319
|
-
{ id: "gpt-5.3-codex", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
320
|
-
{ id: "gpt-5.4", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
321
|
-
{ id: "gpt-5.4-mini", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
322
|
-
{ id: "gpt-5.4-nano", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
323
|
-
{ id: "gpt-5.5", contextWindow: CONTEXT_272K, supportsReasoningEffort: true },
|
|
324
|
-
// gpt-5.5-extra: absent from cursor.com docs but SURVIVES the live GetUsableModels filter
|
|
325
|
-
// (account-verified 260709, devlog/model_update/260709_model_refresh/004_live_snapshot.md).
|
|
326
|
-
{ id: "gpt-5.5-extra", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
|
|
327
|
-
{ id: "gpt-5.6-sol", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
328
|
-
{ id: "gpt-5.6-terra", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
329
|
-
{ id: "gpt-5.6-luna", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
330
|
-
|
|
331
|
-
// 260709 refresh: stale grok/composer/kimi/gpt ids dropped per current cursor.com docs; the
|
|
332
|
-
// 260709 note: grok-4.5 was deferred; confirmed live 260708 (cursor.com/models, xAI launch).
|
|
333
|
-
|
|
334
|
-
// Conflict resolution (260709): keep the refreshed 1M context + kimi-k2.7-code from de12fc8,
|
|
335
|
-
// take PR #73's supportsReasoningEffort for glm-5.2 (its effort-map tiers landed with the PR).
|
|
336
|
-
{ id: "glm-5.2", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
337
|
-
// 260814 preemptive: glm-5.3 seeded ahead of Cursor's lineup update (mirrors glm-5.2).
|
|
338
|
-
{ id: "glm-5.3", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
339
|
-
{ id: "kimi-k2.7-code", contextWindow: CONTEXT_262K },
|
|
340
|
-
// kimi-k3: cursor.com/docs/models/kimi-k3; account-verified via GetUsableModels (2026-07-28) —
|
|
341
|
-
// ships only as effort-suffixed kimi-k3-{low,high,max}, so the tier picker is exposed.
|
|
342
|
-
// kimi-k3 folds the old synthetic kimi-k3-1m row into the umbrella: the base
|
|
343
|
-
// is maxModeVerified (user-verified 1M on the Ultra plan, devlog 260826/025),
|
|
344
|
-
// so the ultra effort rung arms Max Mode on the wire and the separate picker
|
|
345
|
-
// row is gone. cursor/kimi-k3-1m stays routable as an alias.
|
|
346
|
-
{ id: "kimi-k3", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
|
|
347
|
-
|
|
348
|
-
{ id: "grok-4.5", contextWindow: 500_000, supportsReasoningEffort: true },
|
|
349
|
-
// 260813 preemptive: grok-4.6 seeded ahead of Cursor's lineup update (mirrors grok-4.5).
|
|
350
|
-
{ id: "grok-4.6", contextWindow: 500_000, supportsReasoningEffort: true },
|
|
326
|
+
...cursorUmbrellaRows().map(row => ({
|
|
327
|
+
id: row.id,
|
|
328
|
+
contextWindow: row.window,
|
|
329
|
+
supportsReasoningEffort: row.efforts.length > 0,
|
|
330
|
+
})),
|
|
331
|
+
...CURSOR_PRODUCT_MODELS,
|
|
332
|
+
...CURSOR_REAL_ID_EXCEPTIONS,
|
|
351
333
|
]);
|
|
352
334
|
|
|
335
|
+
/** Picker labels for every seeded row, for providers.cursor.modelDisplayNames. */
|
|
336
|
+
export function cursorModelDisplayNames(): Record<string, string> {
|
|
337
|
+
return Object.fromEntries([
|
|
338
|
+
...CURSOR_ROUTER_MODEL_IDS.map(id => [id, CURSOR_ROUTER_DISPLAY_NAMES[id] ?? id] as const),
|
|
339
|
+
...cursorUmbrellaRows().map(row => [row.id, row.displayName] as const),
|
|
340
|
+
...CURSOR_PRODUCT_MODELS.map(model => [model.id, model.displayName] as const),
|
|
341
|
+
...CURSOR_REAL_ID_EXCEPTIONS.map(model => [model.id, model.displayName] as const),
|
|
342
|
+
]);
|
|
343
|
+
}
|
|
344
|
+
|
|
353
345
|
export function cursorModelIds(models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS): string[] {
|
|
354
346
|
return normalizeCursorModels(models).map(model => model.id);
|
|
355
347
|
}
|
|
@@ -23,6 +23,11 @@ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
|
|
|
23
23
|
// max is always the top tier (canonical order: low < medium < high < xhigh < max), confirmed
|
|
24
24
|
// against Anthropic's effort ladder docs and Cursor's live model lineup.
|
|
25
25
|
"claude-fable-5": ["low", "medium", "high", "xhigh", "max"],
|
|
26
|
+
// 260902 preemptive: Fable 5.1 seeded ahead of Cursor's lineup update (mirrors fable-5) under
|
|
27
|
+
// the three spellings Cursor has used for Claude ids.
|
|
28
|
+
"claude-fable-5-1": ["low", "medium", "high", "xhigh", "max"],
|
|
29
|
+
"claude-fable-5.1": ["low", "medium", "high", "xhigh", "max"],
|
|
30
|
+
"claude-5.1-fable": ["low", "medium", "high", "xhigh", "max"],
|
|
26
31
|
"claude-opus-4-7": ["low", "medium", "high", "xhigh", "max"],
|
|
27
32
|
// Opus Fast tiers from the 260822 GetUsableModels dump (devlog .../300): the wire
|
|
28
33
|
// exposes {base-without-fast}-{effort}-fast only; suffix derivation at the bottom of
|
|
@@ -49,6 +54,9 @@ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
|
|
|
49
54
|
"claude-opus-4-7-thinking-fast": ["low", "medium", "high", "xhigh", "max"],
|
|
50
55
|
"claude-sonnet-5-thinking": ["low", "medium", "high", "xhigh", "max"],
|
|
51
56
|
"claude-fable-5-thinking": ["low", "medium", "high", "xhigh", "max"],
|
|
57
|
+
"claude-fable-5-1-thinking": ["low", "medium", "high", "xhigh", "max"],
|
|
58
|
+
"claude-fable-5.1-thinking": ["low", "medium", "high", "xhigh", "max"],
|
|
59
|
+
"claude-5.1-fable-thinking": ["low", "medium", "high", "xhigh", "max"],
|
|
52
60
|
"claude-4.6-opus-thinking": ["high", "max"],
|
|
53
61
|
"claude-4.5-opus-thinking": ["high"],
|
|
54
62
|
"claude-4.6-sonnet-thinking": ["medium"],
|
|
@@ -113,6 +121,9 @@ const CURSOR_THINKING_FAMILIES: Readonly<Record<string, { source: string; order:
|
|
|
113
121
|
"claude-opus-4-7-thinking-fast": { source: "claude-opus-4-7-fast", order: "thinking-then-effort" },
|
|
114
122
|
"claude-sonnet-5-thinking": { source: "claude-sonnet-5", order: "thinking-then-effort" },
|
|
115
123
|
"claude-fable-5-thinking": { source: "claude-fable-5", order: "thinking-then-effort" },
|
|
124
|
+
"claude-fable-5-1-thinking": { source: "claude-fable-5-1", order: "thinking-then-effort" },
|
|
125
|
+
"claude-fable-5.1-thinking": { source: "claude-fable-5.1", order: "thinking-then-effort" },
|
|
126
|
+
"claude-5.1-fable-thinking": { source: "claude-5.1-fable", order: "effort-then-thinking" },
|
|
116
127
|
"claude-4.6-opus-thinking": { source: "claude-4.6-opus", order: "effort-then-thinking" },
|
|
117
128
|
"claude-4.5-opus-thinking": { source: "claude-4.5-opus", order: "effort-then-thinking" },
|
|
118
129
|
"claude-4.6-sonnet-thinking": { source: "claude-4.6-sonnet", order: "effort-then-thinking" },
|