33 *
44 * Cursor model ids encode the reasoning effort as a suffix (`claude-4.6-opus-high`), and the available
55 * tiers differ per model — `claude-4.6-opus` tops out at `-max`, `claude-opus-4-8` at `-xhigh`,
6- * `claude-4.6-sonnet` only has `-medium`, and `composer`/`grok`/`gemini` take no suffix at all. A bare
7- * id for a model that requires a suffix is rejected `ERROR_BAD_MODEL_NAME` (devlog 350.105).
6+ * `claude-4.6-sonnet` only has `-medium`, and most `composer`/`gemini` models take no suffix at all.
7+ * Grok Fast puts its mode marker after the effort (`grok-4.5-high-fast`). A bare id for a model that
8+ * requires a suffix is rejected `ERROR_BAD_MODEL_NAME` (devlog 350.105).
89 *
910 * Canonical effort order is always low < medium < high < xhigh < max (max is the top tier, confirmed
1011 * against Anthropic docs and Cursor's live lineup). Tiers are stored in ascending canonical order.
@@ -30,10 +31,10 @@ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
3031 // GetUsableModels (2026-07-28) lists kimi-k3 only as effort-suffixed kimi-k3-{low,high,max};
3132 // the bare id returns not_found. Tiers mirror the native Kimi provider's K3 ladder.
3233 "kimi-k3" : [ "low" , "high" , "max" ] ,
33- // GetUsableModels (2026-07-09) lists grok- 4.5-{medium,high,xhigh} and grok-4.5-fast-{ medium,high,xhigh};
34- // the bare " grok-4.5-fast" id was removed upstream and now returns not_found.
35- "grok-4.5" : [ "medium " , "high " , "xhigh " ] ,
36- "grok-4.5-fast" : [ "medium " , "high " , "xhigh " ] ,
34+ // Cursor renamed the Grok 4.5 slugs to cursor- grok-4.5-{low, medium,high} and
35+ // cursor- grok-4.5-{low,medium,high}- fast. The bare Fast id returns not_found.
36+ "grok-4.5" : [ "low " , "medium " , "high " ] ,
37+ "grok-4.5-fast" : [ "low " , "medium " , "high " ] ,
3738 "gpt-5.1" : [ "low" , "high" ] ,
3839 "gpt-5.1-codex-max" : [ "low" , "medium" , "high" , "xhigh" ] ,
3940 "gpt-5.1-codex-mini" : [ "low" , "high" ] ,
@@ -113,3 +114,14 @@ export function cursorModelEffortLadder(baseModelId: string): string[] | undefin
113114export function cursorModelHasEffortTiers ( baseModelId : string ) : boolean {
114115 return ( CURSOR_MODEL_EFFORT_TIERS [ baseModelId ] ?. length ?? 0 ) > 0 ;
115116}
117+
118+ /**
119+ * Compose a Cursor wire id from a Codex-facing base id and effort tier.
120+ * Fast variants put the mode after the effort; other models use the ordinary `{base}-{effort}` form.
121+ */
122+ export function cursorWireModelIdWithEffort ( baseModelId : string , effortSuffix : string ) : string {
123+ if ( baseModelId . endsWith ( "-fast" ) ) {
124+ return `${ baseModelId . slice ( 0 , - "-fast" . length ) } -${ effortSuffix } -fast` ;
125+ }
126+ return `${ baseModelId } -${ effortSuffix } ` ;
127+ }
0 commit comments