@code-yeongyu/senpi-ai 2026.9.23 → 2026.9.24-2

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.
Files changed (85) hide show
  1. package/dist/api/anthropic-messages.js +1 -1
  2. package/dist/api/anthropic-messages.js.map +1 -1
  3. package/dist/api/anthropic-tool-references.d.ts.map +1 -1
  4. package/dist/api/anthropic-tool-references.js +8 -35
  5. package/dist/api/anthropic-tool-references.js.map +1 -1
  6. package/dist/api/openai-completions.d.ts.map +1 -1
  7. package/dist/api/openai-completions.js +10 -6
  8. package/dist/api/openai-completions.js.map +1 -1
  9. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  10. package/dist/api/openai-responses-shared.js +4 -3
  11. package/dist/api/openai-responses-shared.js.map +1 -1
  12. package/dist/api/openai-responses.d.ts.map +1 -1
  13. package/dist/api/openai-responses.js +53 -1
  14. package/dist/api/openai-responses.js.map +1 -1
  15. package/dist/api/openrouter-images.js +1 -1
  16. package/dist/api/openrouter-images.js.map +1 -1
  17. package/dist/api/pi-messages.d.ts.map +1 -1
  18. package/dist/api/pi-messages.js +17 -1
  19. package/dist/api/pi-messages.js.map +1 -1
  20. package/dist/cursor/catalog-grouping.d.ts +18 -1
  21. package/dist/cursor/catalog-grouping.d.ts.map +1 -1
  22. package/dist/cursor/catalog-grouping.js +103 -3
  23. package/dist/cursor/catalog-grouping.js.map +1 -1
  24. package/dist/cursor/selection-descriptor.d.ts +3 -1
  25. package/dist/cursor/selection-descriptor.d.ts.map +1 -1
  26. package/dist/cursor/selection-descriptor.js +15 -3
  27. package/dist/cursor/selection-descriptor.js.map +1 -1
  28. package/dist/cursor/store-migration.d.ts +7 -2
  29. package/dist/cursor/store-migration.d.ts.map +1 -1
  30. package/dist/cursor/store-migration.js +92 -20
  31. package/dist/cursor/store-migration.js.map +1 -1
  32. package/dist/image-models.generated.d.ts +30 -0
  33. package/dist/image-models.generated.d.ts.map +1 -1
  34. package/dist/image-models.generated.js +30 -0
  35. package/dist/image-models.generated.js.map +1 -1
  36. package/dist/index.d.ts +2 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/model.d.ts +9 -1
  41. package/dist/model.d.ts.map +1 -1
  42. package/dist/model.js.map +1 -1
  43. package/dist/models.d.ts +6 -0
  44. package/dist/models.d.ts.map +1 -1
  45. package/dist/models.js +15 -0
  46. package/dist/models.js.map +1 -1
  47. package/dist/openai-responses-compat.d.ts +17 -0
  48. package/dist/openai-responses-compat.d.ts.map +1 -1
  49. package/dist/openai-responses-compat.js +4 -1
  50. package/dist/openai-responses-compat.js.map +1 -1
  51. package/dist/providers/cursor.d.ts.map +1 -1
  52. package/dist/providers/cursor.js +1 -0
  53. package/dist/providers/cursor.js.map +1 -1
  54. package/dist/providers/data/.manifest.json +1 -1
  55. package/dist/providers/data/amazon-bedrock.json +1 -1
  56. package/dist/providers/data/chatgpt-subscription.json +1 -1
  57. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  58. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  59. package/dist/providers/data/fireworks.json +1 -1
  60. package/dist/providers/data/github-copilot.json +1 -1
  61. package/dist/providers/data/google.json +1 -1
  62. package/dist/providers/data/minimax-cn.json +1 -1
  63. package/dist/providers/data/minimax.json +1 -1
  64. package/dist/providers/data/moonshotai-cn.json +1 -1
  65. package/dist/providers/data/moonshotai.json +1 -1
  66. package/dist/providers/data/openai.json +1 -1
  67. package/dist/providers/data/opencode-go.json +1 -1
  68. package/dist/providers/data/opencode.json +1 -1
  69. package/dist/providers/data/opengateway.json +1 -1
  70. package/dist/providers/data/openrouter.json +1 -1
  71. package/dist/providers/data/together.json +1 -1
  72. package/dist/providers/data/venice.json +1 -1
  73. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  74. package/dist/types.d.ts +11 -0
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js.map +1 -1
  77. package/dist/utils/prompt-cache-ttl.d.ts +30 -0
  78. package/dist/utils/prompt-cache-ttl.d.ts.map +1 -1
  79. package/dist/utils/prompt-cache-ttl.js +71 -14
  80. package/dist/utils/prompt-cache-ttl.js.map +1 -1
  81. package/dist/utils/tool-name-match.d.ts +30 -0
  82. package/dist/utils/tool-name-match.d.ts.map +1 -0
  83. package/dist/utils/tool-name-match.js +71 -0
  84. package/dist/utils/tool-name-match.js.map +1 -0
  85. package/package.json +2 -2
@@ -1,7 +1,9 @@
1
+ import aliasData from "./cursor-variant-aliases.json" with { type: "json" };
1
2
  import { CURSOR_MODEL_CAPABILITIES, getCursorVariantAlias, parseCursorVariantId, } from "./model-capabilities.js";
2
3
  export { parseCursorVariantId } from "./model-capabilities.js";
3
4
  const ALL_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
4
5
  const FALLBACK_WINDOW = 200000;
6
+ const STATIC_TARGETS = new Set(Object.values(aliasData.aliases).map((alias) => alias.targetId));
5
7
  function isClaude(baseId) {
6
8
  return baseId.startsWith("claude-");
7
9
  }
@@ -52,12 +54,108 @@ function pickRepresentative(members) {
52
54
  });
53
55
  return sorted[0].alias.legacyVariantId;
54
56
  }
57
+ function normalizeDerivedLevel(token) {
58
+ switch (token) {
59
+ case "none":
60
+ return "off";
61
+ case "extra-high":
62
+ return "xhigh";
63
+ case "minimal":
64
+ case "low":
65
+ case "medium":
66
+ case "high":
67
+ case "xhigh":
68
+ case "max":
69
+ return token;
70
+ default:
71
+ return undefined;
72
+ }
73
+ }
74
+ /**
75
+ * Every level is explicit: an unobserved level maps to `null` (unsupported), because the
76
+ * shared model contract treats an absent ordinary level as supported and would otherwise
77
+ * offer levels the server never listed.
78
+ */
79
+ function buildDerivedLevelMap(members) {
80
+ const map = Object.fromEntries(ALL_LEVELS.map((level) => [level, null]));
81
+ for (const member of members) {
82
+ const level = member.alias.level;
83
+ if (level !== undefined && member.level !== undefined && map[level] === null) {
84
+ map[level] = member.level;
85
+ }
86
+ }
87
+ return map;
88
+ }
89
+ function buildDerivedVariantIds(members) {
90
+ const map = {};
91
+ for (const member of members) {
92
+ const level = member.alias.level;
93
+ if (level !== undefined && map[level] === undefined)
94
+ map[level] = member.raw.id;
95
+ }
96
+ return map;
97
+ }
98
+ /**
99
+ * Derive variant-group aliases for raw ids the static alias table does not list.
100
+ * A family (shared base id, with the `-thinking` infix as a separate identity for
101
+ * Claude-style ids) is derived only when at least two distinct levels are observed
102
+ * among its unlisted non-fast members in the same batch; `-fast` variants,
103
+ * single-level families, and level-less ids stay flat exactly as today. Ids the
104
+ * static table already covers are never re-derived, so static output stays
105
+ * byte-identical (senpi#2038).
106
+ */
107
+ export function deriveCursorVariantAliases(ids) {
108
+ const families = new Map();
109
+ const rawIds = new Set(ids);
110
+ for (const id of ids) {
111
+ if (getCursorVariantAlias(id) !== undefined)
112
+ continue;
113
+ const parsed = parseCursorVariantId(id);
114
+ if (parsed.fast || parsed.level === undefined || parsed.baseId === "")
115
+ continue;
116
+ const level = normalizeDerivedLevel(parsed.level);
117
+ if (level === undefined)
118
+ continue;
119
+ const targetId = parsed.thinking === true ? `${parsed.baseId}-thinking` : parsed.baseId;
120
+ const family = families.get(targetId) ?? { targetId, levels: new Set(), members: [] };
121
+ family.levels.add(level);
122
+ family.members.push([id, level, parsed.level]);
123
+ families.set(targetId, family);
124
+ }
125
+ const derived = new Map();
126
+ for (const family of families.values()) {
127
+ // A derived target must not shadow a static identity, a static alias key, or a raw id.
128
+ if (family.levels.size < 2 ||
129
+ STATIC_TARGETS.has(family.targetId) ||
130
+ getCursorVariantAlias(family.targetId) !== undefined ||
131
+ rawIds.has(family.targetId))
132
+ continue;
133
+ const chosen = new Map();
134
+ for (const [id, level, suffix] of family.members) {
135
+ const previous = chosen.get(level);
136
+ if (previous === undefined) {
137
+ chosen.set(level, id);
138
+ continue;
139
+ }
140
+ const previousSuffix = parseCursorVariantId(previous).level;
141
+ if ((suffix === level && previousSuffix !== level) ||
142
+ ((suffix === level) === (previousSuffix === level) && id < previous)) {
143
+ chosen.set(level, id);
144
+ }
145
+ }
146
+ for (const [level, id] of chosen) {
147
+ derived.set(id, { targetId: family.targetId, legacyVariantId: id, encoding: "legacy-variant", level });
148
+ }
149
+ }
150
+ return derived;
151
+ }
55
152
  /** Normalize a raw Cursor catalog (live discovery, CLI scrape, or stored cache) into selectable identities. */
56
153
  export function normalizeCursorCatalog(rawEntries) {
154
+ const derived = deriveCursorVariantAliases(rawEntries.map((raw) => raw.id));
57
155
  const groups = new Map();
58
156
  const order = [];
59
157
  for (const raw of rawEntries) {
60
- const alias = getCursorVariantAlias(raw.id);
158
+ const alias = getCursorVariantAlias(raw.id) ?? derived.get(raw.id);
61
159
  if (!alias) {
62
160
  const parsed = parseCursorVariantId(raw.id);
63
161
  const key = `unknown${parsed.baseId}${raw.id}`;
@@ -92,7 +190,8 @@ export function normalizeCursorCatalog(rawEntries) {
92
190
  const members = groups.get(key);
93
191
  const first = members[0];
94
192
  const baseParsed = parseCursorVariantId(first.alias.targetId);
95
- const baseId = baseParsed.baseId;
193
+ const derivedGroup = members.every((member) => derived.has(member.raw.id));
194
+ const baseId = derivedGroup ? parseCursorVariantId(first.raw.id).baseId : baseParsed.baseId;
96
195
  const capability = CURSOR_MODEL_CAPABILITIES[baseId];
97
196
  const isGrouped = members.length > 1 || first.alias.targetId !== first.raw.id;
98
197
  const efforts = members.filter((member) => member.level !== undefined && member.level !== "none");
@@ -102,7 +201,7 @@ export function normalizeCursorCatalog(rawEntries) {
102
201
  id: first.alias.targetId,
103
202
  name: cleanName(members, baseId, thinkingMode),
104
203
  reasoning: true,
105
- thinkingLevelMap: buildLevelMap(members, capability),
204
+ thinkingLevelMap: derivedGroup ? buildDerivedLevelMap(members) : buildLevelMap(members, capability),
106
205
  window: capability?.window ?? FALLBACK_WINDOW,
107
206
  ...(capability?.maxWindow !== undefined ? { maxWindow: capability.maxWindow } : {}),
108
207
  input: [...new Set(members.flatMap((member) => member.raw.input))],
@@ -111,6 +210,7 @@ export function normalizeCursorCatalog(rawEntries) {
111
210
  ...(thinkingMode !== undefined ? { thinkingMode } : {}),
112
211
  representativeVariantId: pickRepresentative(members),
113
212
  legacyAliases: members.map((member) => member.alias.legacyVariantId).sort(),
213
+ ...(derivedGroup ? { variantIds: buildDerivedVariantIds(members) } : {}),
114
214
  });
115
215
  continue;
116
216
  }
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-grouping.js","sourceRoot":"","sources":["../../src/cursor/catalog-grouping.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ModelThinkingLevel, ThinkingLevelMap } from \"../types.ts\";\nimport {\n\tCURSOR_MODEL_CAPABILITIES,\n\ttype CursorModelCapability,\n\ttype CursorVariantAlias,\n\tgetCursorVariantAlias,\n\tparseCursorVariantId,\n} from \"./model-capabilities.ts\";\n\nexport { parseCursorVariantId } from \"./model-capabilities.ts\";\n\nexport interface CursorCatalogRawEntry {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly input: readonly (\"text\" | \"image\")[];\n\treadonly cursorMaxMode: boolean;\n}\n\nexport interface CursorCatalogEntry {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly reasoning: boolean;\n\treadonly thinkingLevelMap?: ThinkingLevelMap;\n\treadonly window: number;\n\treadonly maxWindow?: number;\n\treadonly input: (\"text\" | \"image\")[];\n\treadonly cursorMaxMode: boolean;\n\treadonly capabilityId?: string;\n\treadonly thinkingMode?: boolean;\n\treadonly representativeVariantId?: string;\n\treadonly legacyAliases: readonly string[];\n}\n\nconst ALL_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nconst FALLBACK_WINDOW = 200000;\n\ninterface GroupMember {\n\treadonly raw: CursorCatalogRawEntry;\n\treadonly alias: CursorVariantAlias;\n\treadonly level: string | undefined;\n\treadonly thinking: boolean | undefined;\n\treadonly fast: boolean;\n}\n\nfunction isClaude(baseId: string): boolean {\n\treturn baseId.startsWith(\"claude-\");\n}\n\nfunction cleanName(members: readonly GroupMember[], baseId: string, thinkingMode: boolean | undefined): string {\n\tconst levelWords = /(Minimal|Low|Medium|High|Extra High|XHigh|Max|None)/g;\n\tconst representative =\n\t\tmembers.find((member) => member.level === \"high\") ??\n\t\tmembers.find((member) => member.level === \"medium\") ??\n\t\tmembers.find((member) => member.level === \"low\") ??\n\t\tmembers[0];\n\tlet name = representative.raw.name;\n\tname = name.replace(/\\s*\\(NO ZDR\\)\\s*/g, \" \\u0001\").trim();\n\tname = name.replace(new RegExp(`\\\\s+${levelWords.source}\\\\b`, \"g\"), \"\");\n\tname = name.replace(/\\s+Fast\\b/g, \"\");\n\tif (thinkingMode !== true) name = name.replace(/\\s+Thinking\\b/g, \"\");\n\tname = name\n\t\t.replace(/\\u0001/g, \"(NO ZDR)\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\tif (name.length === 0) name = baseId;\n\treturn name;\n}\n\nfunction buildLevelMap(\n\tmembers: readonly GroupMember[],\n\tcapability: CursorModelCapability | undefined,\n): ThinkingLevelMap {\n\tconst observed = new Set(\n\t\tmembers.map((member) => member.level).filter((level): level is string => level !== undefined),\n\t);\n\tconst map = {} as Record<ModelThinkingLevel, string | null>;\n\tfor (const level of ALL_LEVELS) {\n\t\tif (level === \"off\") {\n\t\t\tconst offSpec = capability?.levels.off;\n\t\t\tmap.off = offSpec !== undefined && observed.has(\"none\") ? offSpec.value : null;\n\t\t\tcontinue;\n\t\t}\n\t\tconst spec = capability?.levels[level];\n\t\tmap[level] = spec !== undefined && (observed.has(level) || observed.has(spec.value)) ? spec.value : null;\n\t}\n\treturn map;\n}\n\nfunction pickRepresentative(members: readonly GroupMember[]): string {\n\tconst withLevels = members.filter((member) => member.level !== undefined && member.level !== \"none\");\n\tconst pool = withLevels.length > 0 ? withLevels : members;\n\tconst order = [\"medium\", \"low\", \"minimal\", \"high\", \"xhigh\", \"extra-high\", \"max\", \"none\"];\n\tconst sorted = [...pool].sort((a, b) => {\n\t\tconst ai = order.indexOf(a.level ?? \"none\");\n\t\tconst bi = order.indexOf(b.level ?? \"none\");\n\t\tif (ai !== bi) return ai - bi;\n\t\treturn a.alias.legacyVariantId.localeCompare(b.alias.legacyVariantId);\n\t});\n\treturn sorted[0].alias.legacyVariantId;\n}\n\n/** Normalize a raw Cursor catalog (live discovery, CLI scrape, or stored cache) into selectable identities. */\nexport function normalizeCursorCatalog(rawEntries: readonly CursorCatalogRawEntry[]): CursorCatalogEntry[] {\n\tconst groups = new Map<string, GroupMember[]>();\n\tconst order: string[] = [];\n\tfor (const raw of rawEntries) {\n\t\tconst alias = getCursorVariantAlias(raw.id);\n\t\tif (!alias) {\n\t\t\tconst parsed = parseCursorVariantId(raw.id);\n\t\t\tconst key = `unknown${parsed.baseId}${raw.id}`;\n\t\t\tif (!groups.has(key)) order.push(key);\n\t\t\tconst member: GroupMember = {\n\t\t\t\traw,\n\t\t\t\talias: { targetId: raw.id, legacyVariantId: raw.id, encoding: \"legacy-variant\" },\n\t\t\t\tlevel: parsed.level,\n\t\t\t\tthinking: parsed.thinking,\n\t\t\t\tfast: parsed.fast,\n\t\t\t};\n\t\t\tgroups.set(key, [member]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst parsed = parseCursorVariantId(raw.id);\n\t\tconst key = `${alias.targetId}${parsed.fast}`;\n\t\tif (!groups.has(key)) {\n\t\t\torder.push(key);\n\t\t\tgroups.set(key, []);\n\t\t}\n\t\t(groups.get(key) as GroupMember[]).push({\n\t\t\traw,\n\t\t\talias,\n\t\t\tlevel: parsed.level,\n\t\t\tthinking: parsed.thinking,\n\t\t\tfast: parsed.fast,\n\t\t});\n\t}\n\n\tconst out: CursorCatalogEntry[] = [];\n\tfor (const key of order) {\n\t\tconst members = groups.get(key) as GroupMember[];\n\t\tconst first = members[0];\n\t\tconst baseParsed = parseCursorVariantId(first.alias.targetId);\n\t\tconst baseId = baseParsed.baseId;\n\t\tconst capability = CURSOR_MODEL_CAPABILITIES[baseId];\n\t\tconst isGrouped = members.length > 1 || first.alias.targetId !== first.raw.id;\n\t\tconst efforts = members.filter((member) => member.level !== undefined && member.level !== \"none\");\n\n\t\tif (isGrouped && efforts.length > 0 && !first.fast) {\n\t\t\tconst thinkingMode = isClaude(baseId) ? first.thinking === true : undefined;\n\t\t\tout.push({\n\t\t\t\tid: first.alias.targetId,\n\t\t\t\tname: cleanName(members, baseId, thinkingMode),\n\t\t\t\treasoning: true,\n\t\t\t\tthinkingLevelMap: buildLevelMap(members, capability),\n\t\t\t\twindow: capability?.window ?? FALLBACK_WINDOW,\n\t\t\t\t...(capability?.maxWindow !== undefined ? { maxWindow: capability.maxWindow } : {}),\n\t\t\t\tinput: [...new Set(members.flatMap((member) => member.raw.input))],\n\t\t\t\tcursorMaxMode: members.some((member) => member.raw.cursorMaxMode),\n\t\t\t\tcapabilityId: baseId,\n\t\t\t\t...(thinkingMode !== undefined ? { thinkingMode } : {}),\n\t\t\t\trepresentativeVariantId: pickRepresentative(members),\n\t\t\t\tlegacyAliases: members.map((member) => member.alias.legacyVariantId).sort(),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const member of members) {\n\t\t\tconst memberBase = parseCursorVariantId(member.raw.id).baseId;\n\t\t\tconst memberCapability = CURSOR_MODEL_CAPABILITIES[memberBase];\n\t\t\tout.push({\n\t\t\t\tid: member.raw.id,\n\t\t\t\tname: member.raw.name,\n\t\t\t\treasoning: false,\n\t\t\t\twindow: memberCapability?.window ?? FALLBACK_WINDOW,\n\t\t\t\t...(memberCapability?.maxWindow !== undefined ? { maxWindow: memberCapability.maxWindow } : {}),\n\t\t\t\tinput: [...member.raw.input],\n\t\t\t\tcursorMaxMode: member.raw.cursorMaxMode,\n\t\t\t\tlegacyAliases: [member.alias.legacyVariantId],\n\t\t\t});\n\t\t}\n\t}\n\treturn out;\n}\n"]}
1
+ {"version":3,"file":"catalog-grouping.js","sourceRoot":"","sources":["../../src/cursor/catalog-grouping.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ModelThinkingLevel, ThinkingLevelMap } from \"../types.ts\";\nimport aliasData from \"./cursor-variant-aliases.json\" with { type: \"json\" };\nimport {\n\tCURSOR_MODEL_CAPABILITIES,\n\ttype CursorModelCapability,\n\ttype CursorVariantAlias,\n\tgetCursorVariantAlias,\n\tparseCursorVariantId,\n} from \"./model-capabilities.ts\";\n\nexport { parseCursorVariantId } from \"./model-capabilities.ts\";\n\nexport interface CursorCatalogRawEntry {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly input: readonly (\"text\" | \"image\")[];\n\treadonly cursorMaxMode: boolean;\n}\n\nexport interface CursorCatalogEntry {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly reasoning: boolean;\n\treadonly thinkingLevelMap?: ThinkingLevelMap;\n\treadonly window: number;\n\treadonly maxWindow?: number;\n\treadonly input: (\"text\" | \"image\")[];\n\treadonly cursorMaxMode: boolean;\n\treadonly capabilityId?: string;\n\treadonly thinkingMode?: boolean;\n\treadonly representativeVariantId?: string;\n\treadonly legacyAliases: readonly string[];\n\t/**\n\t * Derived-group variant ids: normalized thinking level -> the exact server-listed\n\t * variant id the live catalog serves. Present only on identities derived at\n\t * runtime from ids the static alias table does not list (senpi#2038).\n\t */\n\treadonly variantIds?: Readonly<Partial<Record<ModelThinkingLevel, string>>>;\n}\n\nconst ALL_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nconst FALLBACK_WINDOW = 200000;\nconst STATIC_TARGETS = new Set(Object.values(aliasData.aliases).map((alias) => alias.targetId));\n\ninterface GroupMember {\n\treadonly raw: CursorCatalogRawEntry;\n\treadonly alias: CursorVariantAlias;\n\treadonly level: string | undefined;\n\treadonly thinking: boolean | undefined;\n\treadonly fast: boolean;\n}\n\nfunction isClaude(baseId: string): boolean {\n\treturn baseId.startsWith(\"claude-\");\n}\n\nfunction cleanName(members: readonly GroupMember[], baseId: string, thinkingMode: boolean | undefined): string {\n\tconst levelWords = /(Minimal|Low|Medium|High|Extra High|XHigh|Max|None)/g;\n\tconst representative =\n\t\tmembers.find((member) => member.level === \"high\") ??\n\t\tmembers.find((member) => member.level === \"medium\") ??\n\t\tmembers.find((member) => member.level === \"low\") ??\n\t\tmembers[0];\n\tlet name = representative.raw.name;\n\tname = name.replace(/\\s*\\(NO ZDR\\)\\s*/g, \" \\u0001\").trim();\n\tname = name.replace(new RegExp(`\\\\s+${levelWords.source}\\\\b`, \"g\"), \"\");\n\tname = name.replace(/\\s+Fast\\b/g, \"\");\n\tif (thinkingMode !== true) name = name.replace(/\\s+Thinking\\b/g, \"\");\n\tname = name\n\t\t.replace(/\\u0001/g, \"(NO ZDR)\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\tif (name.length === 0) name = baseId;\n\treturn name;\n}\n\nfunction buildLevelMap(\n\tmembers: readonly GroupMember[],\n\tcapability: CursorModelCapability | undefined,\n): ThinkingLevelMap {\n\tconst observed = new Set(\n\t\tmembers.map((member) => member.level).filter((level): level is string => level !== undefined),\n\t);\n\tconst map = {} as Record<ModelThinkingLevel, string | null>;\n\tfor (const level of ALL_LEVELS) {\n\t\tif (level === \"off\") {\n\t\t\tconst offSpec = capability?.levels.off;\n\t\t\tmap.off = offSpec !== undefined && observed.has(\"none\") ? offSpec.value : null;\n\t\t\tcontinue;\n\t\t}\n\t\tconst spec = capability?.levels[level];\n\t\tmap[level] = spec !== undefined && (observed.has(level) || observed.has(spec.value)) ? spec.value : null;\n\t}\n\treturn map;\n}\n\nfunction pickRepresentative(members: readonly GroupMember[]): string {\n\tconst withLevels = members.filter((member) => member.level !== undefined && member.level !== \"none\");\n\tconst pool = withLevels.length > 0 ? withLevels : members;\n\tconst order = [\"medium\", \"low\", \"minimal\", \"high\", \"xhigh\", \"extra-high\", \"max\", \"none\"];\n\tconst sorted = [...pool].sort((a, b) => {\n\t\tconst ai = order.indexOf(a.level ?? \"none\");\n\t\tconst bi = order.indexOf(b.level ?? \"none\");\n\t\tif (ai !== bi) return ai - bi;\n\t\treturn a.alias.legacyVariantId.localeCompare(b.alias.legacyVariantId);\n\t});\n\treturn sorted[0].alias.legacyVariantId;\n}\n\nfunction normalizeDerivedLevel(token: string): ModelThinkingLevel | undefined {\n\tswitch (token) {\n\t\tcase \"none\":\n\t\t\treturn \"off\";\n\t\tcase \"extra-high\":\n\t\t\treturn \"xhigh\";\n\t\tcase \"minimal\":\n\t\tcase \"low\":\n\t\tcase \"medium\":\n\t\tcase \"high\":\n\t\tcase \"xhigh\":\n\t\tcase \"max\":\n\t\t\treturn token;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Every level is explicit: an unobserved level maps to `null` (unsupported), because the\n * shared model contract treats an absent ordinary level as supported and would otherwise\n * offer levels the server never listed.\n */\nfunction buildDerivedLevelMap(members: readonly GroupMember[]): ThinkingLevelMap {\n\tconst map = Object.fromEntries(ALL_LEVELS.map((level) => [level, null])) as Record<\n\t\tModelThinkingLevel,\n\t\tstring | null\n\t>;\n\tfor (const member of members) {\n\t\tconst level = member.alias.level;\n\t\tif (level !== undefined && member.level !== undefined && map[level] === null) {\n\t\t\tmap[level] = member.level;\n\t\t}\n\t}\n\treturn map;\n}\n\nfunction buildDerivedVariantIds(\n\tmembers: readonly GroupMember[],\n): Readonly<Partial<Record<ModelThinkingLevel, string>>> {\n\tconst map: Partial<Record<ModelThinkingLevel, string>> = {};\n\tfor (const member of members) {\n\t\tconst level = member.alias.level;\n\t\tif (level !== undefined && map[level] === undefined) map[level] = member.raw.id;\n\t}\n\treturn map;\n}\n\n/**\n * Derive variant-group aliases for raw ids the static alias table does not list.\n * A family (shared base id, with the `-thinking` infix as a separate identity for\n * Claude-style ids) is derived only when at least two distinct levels are observed\n * among its unlisted non-fast members in the same batch; `-fast` variants,\n * single-level families, and level-less ids stay flat exactly as today. Ids the\n * static table already covers are never re-derived, so static output stays\n * byte-identical (senpi#2038).\n */\nexport function deriveCursorVariantAliases(ids: readonly string[]): ReadonlyMap<string, CursorVariantAlias> {\n\tconst families = new Map<\n\t\tstring,\n\t\t{ targetId: string; levels: Set<ModelThinkingLevel>; members: [string, ModelThinkingLevel, string][] }\n\t>();\n\tconst rawIds = new Set(ids);\n\tfor (const id of ids) {\n\t\tif (getCursorVariantAlias(id) !== undefined) continue;\n\t\tconst parsed = parseCursorVariantId(id);\n\t\tif (parsed.fast || parsed.level === undefined || parsed.baseId === \"\") continue;\n\t\tconst level = normalizeDerivedLevel(parsed.level);\n\t\tif (level === undefined) continue;\n\t\tconst targetId = parsed.thinking === true ? `${parsed.baseId}-thinking` : parsed.baseId;\n\t\tconst family = families.get(targetId) ?? { targetId, levels: new Set(), members: [] };\n\t\tfamily.levels.add(level);\n\t\tfamily.members.push([id, level, parsed.level]);\n\t\tfamilies.set(targetId, family);\n\t}\n\tconst derived = new Map<string, CursorVariantAlias>();\n\tfor (const family of families.values()) {\n\t\t// A derived target must not shadow a static identity, a static alias key, or a raw id.\n\t\tif (\n\t\t\tfamily.levels.size < 2 ||\n\t\t\tSTATIC_TARGETS.has(family.targetId) ||\n\t\t\tgetCursorVariantAlias(family.targetId) !== undefined ||\n\t\t\trawIds.has(family.targetId)\n\t\t)\n\t\t\tcontinue;\n\t\tconst chosen = new Map<ModelThinkingLevel, string>();\n\t\tfor (const [id, level, suffix] of family.members) {\n\t\t\tconst previous = chosen.get(level);\n\t\t\tif (previous === undefined) {\n\t\t\t\tchosen.set(level, id);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst previousSuffix = parseCursorVariantId(previous).level;\n\t\t\tif (\n\t\t\t\t(suffix === level && previousSuffix !== level) ||\n\t\t\t\t((suffix === level) === (previousSuffix === level) && id < previous)\n\t\t\t) {\n\t\t\t\tchosen.set(level, id);\n\t\t\t}\n\t\t}\n\t\tfor (const [level, id] of chosen) {\n\t\t\tderived.set(id, { targetId: family.targetId, legacyVariantId: id, encoding: \"legacy-variant\", level });\n\t\t}\n\t}\n\treturn derived;\n}\n\n/** Normalize a raw Cursor catalog (live discovery, CLI scrape, or stored cache) into selectable identities. */\nexport function normalizeCursorCatalog(rawEntries: readonly CursorCatalogRawEntry[]): CursorCatalogEntry[] {\n\tconst derived = deriveCursorVariantAliases(rawEntries.map((raw) => raw.id));\n\tconst groups = new Map<string, GroupMember[]>();\n\tconst order: string[] = [];\n\tfor (const raw of rawEntries) {\n\t\tconst alias = getCursorVariantAlias(raw.id) ?? derived.get(raw.id);\n\t\tif (!alias) {\n\t\t\tconst parsed = parseCursorVariantId(raw.id);\n\t\t\tconst key = `unknown${parsed.baseId}${raw.id}`;\n\t\t\tif (!groups.has(key)) order.push(key);\n\t\t\tconst member: GroupMember = {\n\t\t\t\traw,\n\t\t\t\talias: { targetId: raw.id, legacyVariantId: raw.id, encoding: \"legacy-variant\" },\n\t\t\t\tlevel: parsed.level,\n\t\t\t\tthinking: parsed.thinking,\n\t\t\t\tfast: parsed.fast,\n\t\t\t};\n\t\t\tgroups.set(key, [member]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst parsed = parseCursorVariantId(raw.id);\n\t\tconst key = `${alias.targetId}${parsed.fast}`;\n\t\tif (!groups.has(key)) {\n\t\t\torder.push(key);\n\t\t\tgroups.set(key, []);\n\t\t}\n\t\t(groups.get(key) as GroupMember[]).push({\n\t\t\traw,\n\t\t\talias,\n\t\t\tlevel: parsed.level,\n\t\t\tthinking: parsed.thinking,\n\t\t\tfast: parsed.fast,\n\t\t});\n\t}\n\n\tconst out: CursorCatalogEntry[] = [];\n\tfor (const key of order) {\n\t\tconst members = groups.get(key) as GroupMember[];\n\t\tconst first = members[0];\n\t\tconst baseParsed = parseCursorVariantId(first.alias.targetId);\n\t\tconst derivedGroup = members.every((member) => derived.has(member.raw.id));\n\t\tconst baseId = derivedGroup ? parseCursorVariantId(first.raw.id).baseId : baseParsed.baseId;\n\t\tconst capability = CURSOR_MODEL_CAPABILITIES[baseId];\n\t\tconst isGrouped = members.length > 1 || first.alias.targetId !== first.raw.id;\n\t\tconst efforts = members.filter((member) => member.level !== undefined && member.level !== \"none\");\n\n\t\tif (isGrouped && efforts.length > 0 && !first.fast) {\n\t\t\tconst thinkingMode = isClaude(baseId) ? first.thinking === true : undefined;\n\t\t\tout.push({\n\t\t\t\tid: first.alias.targetId,\n\t\t\t\tname: cleanName(members, baseId, thinkingMode),\n\t\t\t\treasoning: true,\n\t\t\t\tthinkingLevelMap: derivedGroup ? buildDerivedLevelMap(members) : buildLevelMap(members, capability),\n\t\t\t\twindow: capability?.window ?? FALLBACK_WINDOW,\n\t\t\t\t...(capability?.maxWindow !== undefined ? { maxWindow: capability.maxWindow } : {}),\n\t\t\t\tinput: [...new Set(members.flatMap((member) => member.raw.input))],\n\t\t\t\tcursorMaxMode: members.some((member) => member.raw.cursorMaxMode),\n\t\t\t\tcapabilityId: baseId,\n\t\t\t\t...(thinkingMode !== undefined ? { thinkingMode } : {}),\n\t\t\t\trepresentativeVariantId: pickRepresentative(members),\n\t\t\t\tlegacyAliases: members.map((member) => member.alias.legacyVariantId).sort(),\n\t\t\t\t...(derivedGroup ? { variantIds: buildDerivedVariantIds(members) } : {}),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const member of members) {\n\t\t\tconst memberBase = parseCursorVariantId(member.raw.id).baseId;\n\t\t\tconst memberCapability = CURSOR_MODEL_CAPABILITIES[memberBase];\n\t\t\tout.push({\n\t\t\t\tid: member.raw.id,\n\t\t\t\tname: member.raw.name,\n\t\t\t\treasoning: false,\n\t\t\t\twindow: memberCapability?.window ?? FALLBACK_WINDOW,\n\t\t\t\t...(memberCapability?.maxWindow !== undefined ? { maxWindow: memberCapability.maxWindow } : {}),\n\t\t\t\tinput: [...member.raw.input],\n\t\t\t\tcursorMaxMode: member.raw.cursorMaxMode,\n\t\t\t\tlegacyAliases: [member.alias.legacyVariantId],\n\t\t\t});\n\t\t}\n\t}\n\treturn out;\n}\n"]}
@@ -13,7 +13,9 @@ export interface CursorResolvedSelection {
13
13
  * model id plus ordered parameters. Both Cursor transports consume this; the
14
14
  * native lane renders parameters into protobuf, the CLI lane renders a model
15
15
  * string. Absent/unsupported selections return the representative or upstream
16
- * id with zero parameters.
16
+ * id with zero parameters. Identities derived from unlisted suffix variants
17
+ * resolve each level through `cursorReasoning.variantIds` before any capability
18
+ * lookup (senpi#2038).
17
19
  */
18
20
  export declare function resolveCursorSelectionDescriptor(model: Model<"cursor-agent">, selection: ThinkingSelection | undefined): CursorResolvedSelection;
19
21
  /** Render the resolved descriptor as one CLI `--model` argv element (bracket or suffix form). */
@@ -1 +1 @@
1
- {"version":3,"file":"selection-descriptor.d.ts","sourceRoot":"","sources":["../../src/cursor/selection-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAGN,KAAK,iBAAiB,EAEtB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3F;AAiED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,EAC5B,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACtC,uBAAuB,CAiCzB;AAED,iGAAiG;AACjG,wBAAgB,0BAA0B,CACzC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,EAC5B,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACtC,MAAM,CAKR"}
1
+ {"version":3,"file":"selection-descriptor.d.ts","sourceRoot":"","sources":["../../src/cursor/selection-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAGN,KAAK,iBAAiB,EAEtB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3F;AAiED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,EAC5B,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACtC,uBAAuB,CA6CzB;AAED,iGAAiG;AACjG,wBAAgB,0BAA0B,CACzC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,EAC5B,SAAS,EAAE,iBAAiB,GAAG,SAAS,GACtC,MAAM,CAKR"}
@@ -56,7 +56,9 @@ function buildParameters(capabilityId, value, thinkingMode) {
56
56
  * model id plus ordered parameters. Both Cursor transports consume this; the
57
57
  * native lane renders parameters into protobuf, the CLI lane renders a model
58
58
  * string. Absent/unsupported selections return the representative or upstream
59
- * id with zero parameters.
59
+ * id with zero parameters. Identities derived from unlisted suffix variants
60
+ * resolve each level through `cursorReasoning.variantIds` before any capability
61
+ * lookup (senpi#2038).
60
62
  */
61
63
  export function resolveCursorSelectionDescriptor(model, selection) {
62
64
  const compat = identityCompat(model);
@@ -67,10 +69,20 @@ export function resolveCursorSelectionDescriptor(model, selection) {
67
69
  return { modelId: compat.representativeVariantId, parameters: [] };
68
70
  }
69
71
  if (selection.source === "legacy-variant") {
70
- if (selection.legacyVariantId === undefined || getCursorVariantAlias(selection.legacyVariantId) === undefined) {
72
+ const legacyId = selection.legacyVariantId;
73
+ const allowlisted = legacyId !== undefined &&
74
+ (getCursorVariantAlias(legacyId) !== undefined || Object.values(compat.variantIds ?? {}).includes(legacyId));
75
+ if (!allowlisted) {
71
76
  return { modelId: compat.representativeVariantId, parameters: [] };
72
77
  }
73
- return { modelId: selection.legacyVariantId, parameters: [] };
78
+ return { modelId: legacyId, parameters: [] };
79
+ }
80
+ const derivedVariantId = compat.variantIds?.[selection.level];
81
+ if (derivedVariantId !== undefined) {
82
+ return { modelId: derivedVariantId, parameters: [] };
83
+ }
84
+ if (compat.variantIds !== undefined) {
85
+ return { modelId: compat.representativeVariantId, parameters: [] };
74
86
  }
75
87
  const capability = CURSOR_MODEL_CAPABILITIES[compat.capabilityId];
76
88
  const spec = capability?.levels[selection.level];
@@ -1 +1 @@
1
- {"version":3,"file":"selection-descriptor.js","sourceRoot":"","sources":["../../src/cursor/selection-descriptor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CursorAgentCompat, Model } from \"../model.ts\";\nimport type { ModelThinkingLevel, ThinkingSelection } from \"../types.ts\";\nimport {\n\tCURSOR_MODEL_CAPABILITIES,\n\ttype CursorLevelSpec,\n\ttype CursorParameterId,\n\tgetCursorVariantAlias,\n} from \"./model-capabilities.ts\";\n\nexport interface CursorResolvedSelection {\n\treadonly modelId: string;\n\treadonly parameters: readonly { readonly id: CursorParameterId; readonly value: string }[];\n}\n\nfunction identityCompat(model: Model<\"cursor-agent\">): CursorAgentCompat[\"cursorReasoning\"] {\n\treturn model.compat?.cursorReasoning;\n}\n\ntype CursorReasoningIdentity = NonNullable<CursorAgentCompat[\"cursorReasoning\"]>;\n\n/**\n * Catalog-guaranteed suffix alias for a base + level, or undefined. Cursor Run\n * rejects bare capability ids with Connect `not_found` (issue #1008; live\n * probes 2026-08-20), so every resolvable level prefers the suffix variant id\n * the `GetUsableModels` catalog actually serves. Candidates try the level's\n * wire value first, then the level token itself (`extra-high` vs `xhigh`),\n * with thinking-infixed forms for thinking Claude identities.\n */\nfunction suffixAliasId(\n\tcompat: CursorReasoningIdentity,\n\tlevel: ModelThinkingLevel,\n\tspec: CursorLevelSpec,\n): string | undefined {\n\tconst suffixes = level === \"off\" ? [\"none\"] : spec.value === level ? [spec.value] : [spec.value, level];\n\tfor (const suffix of suffixes) {\n\t\tconst candidates =\n\t\t\tcompat.thinkingMode === true\n\t\t\t\t? [`${compat.capabilityId}-thinking-${suffix}`, `${compat.capabilityId}-${suffix}-thinking`]\n\t\t\t\t: [`${compat.capabilityId}-${suffix}`];\n\t\tfor (const candidate of candidates) {\n\t\t\tconst alias = getCursorVariantAlias(candidate);\n\t\t\tif (alias) return alias.legacyVariantId;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction buildParameters(\n\tcapabilityId: string,\n\tvalue: string,\n\tthinkingMode: boolean | undefined,\n): { id: CursorParameterId; value: string }[] {\n\tconst capability = CURSOR_MODEL_CAPABILITIES[capabilityId];\n\tif (!capability) return [];\n\tconst out: { id: CursorParameterId; value: string }[] = [];\n\tfor (const id of capability.parameterOrder) {\n\t\tswitch (id) {\n\t\t\tcase \"thinking\":\n\t\t\t\tout.push({ id, value: thinkingMode === true ? \"true\" : \"false\" });\n\t\t\t\tbreak;\n\t\t\tcase \"context\": {\n\t\t\t\tconst context = capability.requestContext ?? capability.defaultContext;\n\t\t\t\tif (context !== undefined) out.push({ id, value: context });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"effort\":\n\t\t\tcase \"reasoning\":\n\t\t\t\tout.push({ id, value });\n\t\t\t\tbreak;\n\t\t\tcase \"fast\":\n\t\t\t\tout.push({ id, value: \"false\" });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Resolve a Cursor model + thinking selection to its wire descriptor: the exact\n * model id plus ordered parameters. Both Cursor transports consume this; the\n * native lane renders parameters into protobuf, the CLI lane renders a model\n * string. Absent/unsupported selections return the representative or upstream\n * id with zero parameters.\n */\nexport function resolveCursorSelectionDescriptor(\n\tmodel: Model<\"cursor-agent\">,\n\tselection: ThinkingSelection | undefined,\n): CursorResolvedSelection {\n\tconst compat = identityCompat(model);\n\tconst fallback: CursorResolvedSelection = { modelId: model.upstreamModelId ?? model.id, parameters: [] };\n\tif (!compat) return fallback;\n\n\tif (selection === undefined) {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\tif (selection.source === \"legacy-variant\") {\n\t\tif (selection.legacyVariantId === undefined || getCursorVariantAlias(selection.legacyVariantId) === undefined) {\n\t\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t\t}\n\t\treturn { modelId: selection.legacyVariantId, parameters: [] };\n\t}\n\n\tconst capability = CURSOR_MODEL_CAPABILITIES[compat.capabilityId];\n\tconst spec = capability?.levels[selection.level];\n\tif (!capability || !spec) {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\tconst suffixId = suffixAliasId(compat, selection.level, spec);\n\tif (suffixId !== undefined) return { modelId: suffixId, parameters: [] };\n\n\tif (spec.encoding === \"variant-id\") {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\treturn {\n\t\tmodelId: compat.capabilityId,\n\t\tparameters: buildParameters(compat.capabilityId, spec.value, compat.thinkingMode),\n\t};\n}\n\n/** Render the resolved descriptor as one CLI `--model` argv element (bracket or suffix form). */\nexport function renderCursorCliModelString(\n\tmodel: Model<\"cursor-agent\">,\n\tselection: ThinkingSelection | undefined,\n): string {\n\tconst resolved = resolveCursorSelectionDescriptor(model, selection);\n\tif (resolved.parameters.length === 0) return resolved.modelId;\n\tconst args = resolved.parameters.map((parameter) => `${parameter.id}=${parameter.value}`).join(\",\");\n\treturn `${resolved.modelId}[${args}]`;\n}\n"]}
1
+ {"version":3,"file":"selection-descriptor.js","sourceRoot":"","sources":["../../src/cursor/selection-descriptor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CursorAgentCompat, Model } from \"../model.ts\";\nimport type { ModelThinkingLevel, ThinkingSelection } from \"../types.ts\";\nimport {\n\tCURSOR_MODEL_CAPABILITIES,\n\ttype CursorLevelSpec,\n\ttype CursorParameterId,\n\tgetCursorVariantAlias,\n} from \"./model-capabilities.ts\";\n\nexport interface CursorResolvedSelection {\n\treadonly modelId: string;\n\treadonly parameters: readonly { readonly id: CursorParameterId; readonly value: string }[];\n}\n\nfunction identityCompat(model: Model<\"cursor-agent\">): CursorAgentCompat[\"cursorReasoning\"] {\n\treturn model.compat?.cursorReasoning;\n}\n\ntype CursorReasoningIdentity = NonNullable<CursorAgentCompat[\"cursorReasoning\"]>;\n\n/**\n * Catalog-guaranteed suffix alias for a base + level, or undefined. Cursor Run\n * rejects bare capability ids with Connect `not_found` (issue #1008; live\n * probes 2026-08-20), so every resolvable level prefers the suffix variant id\n * the `GetUsableModels` catalog actually serves. Candidates try the level's\n * wire value first, then the level token itself (`extra-high` vs `xhigh`),\n * with thinking-infixed forms for thinking Claude identities.\n */\nfunction suffixAliasId(\n\tcompat: CursorReasoningIdentity,\n\tlevel: ModelThinkingLevel,\n\tspec: CursorLevelSpec,\n): string | undefined {\n\tconst suffixes = level === \"off\" ? [\"none\"] : spec.value === level ? [spec.value] : [spec.value, level];\n\tfor (const suffix of suffixes) {\n\t\tconst candidates =\n\t\t\tcompat.thinkingMode === true\n\t\t\t\t? [`${compat.capabilityId}-thinking-${suffix}`, `${compat.capabilityId}-${suffix}-thinking`]\n\t\t\t\t: [`${compat.capabilityId}-${suffix}`];\n\t\tfor (const candidate of candidates) {\n\t\t\tconst alias = getCursorVariantAlias(candidate);\n\t\t\tif (alias) return alias.legacyVariantId;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction buildParameters(\n\tcapabilityId: string,\n\tvalue: string,\n\tthinkingMode: boolean | undefined,\n): { id: CursorParameterId; value: string }[] {\n\tconst capability = CURSOR_MODEL_CAPABILITIES[capabilityId];\n\tif (!capability) return [];\n\tconst out: { id: CursorParameterId; value: string }[] = [];\n\tfor (const id of capability.parameterOrder) {\n\t\tswitch (id) {\n\t\t\tcase \"thinking\":\n\t\t\t\tout.push({ id, value: thinkingMode === true ? \"true\" : \"false\" });\n\t\t\t\tbreak;\n\t\t\tcase \"context\": {\n\t\t\t\tconst context = capability.requestContext ?? capability.defaultContext;\n\t\t\t\tif (context !== undefined) out.push({ id, value: context });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"effort\":\n\t\t\tcase \"reasoning\":\n\t\t\t\tout.push({ id, value });\n\t\t\t\tbreak;\n\t\t\tcase \"fast\":\n\t\t\t\tout.push({ id, value: \"false\" });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Resolve a Cursor model + thinking selection to its wire descriptor: the exact\n * model id plus ordered parameters. Both Cursor transports consume this; the\n * native lane renders parameters into protobuf, the CLI lane renders a model\n * string. Absent/unsupported selections return the representative or upstream\n * id with zero parameters. Identities derived from unlisted suffix variants\n * resolve each level through `cursorReasoning.variantIds` before any capability\n * lookup (senpi#2038).\n */\nexport function resolveCursorSelectionDescriptor(\n\tmodel: Model<\"cursor-agent\">,\n\tselection: ThinkingSelection | undefined,\n): CursorResolvedSelection {\n\tconst compat = identityCompat(model);\n\tconst fallback: CursorResolvedSelection = { modelId: model.upstreamModelId ?? model.id, parameters: [] };\n\tif (!compat) return fallback;\n\n\tif (selection === undefined) {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\tif (selection.source === \"legacy-variant\") {\n\t\tconst legacyId = selection.legacyVariantId;\n\t\tconst allowlisted =\n\t\t\tlegacyId !== undefined &&\n\t\t\t(getCursorVariantAlias(legacyId) !== undefined || Object.values(compat.variantIds ?? {}).includes(legacyId));\n\t\tif (!allowlisted) {\n\t\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t\t}\n\t\treturn { modelId: legacyId, parameters: [] };\n\t}\n\n\tconst derivedVariantId = compat.variantIds?.[selection.level];\n\tif (derivedVariantId !== undefined) {\n\t\treturn { modelId: derivedVariantId, parameters: [] };\n\t}\n\tif (compat.variantIds !== undefined) {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\tconst capability = CURSOR_MODEL_CAPABILITIES[compat.capabilityId];\n\tconst spec = capability?.levels[selection.level];\n\tif (!capability || !spec) {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\tconst suffixId = suffixAliasId(compat, selection.level, spec);\n\tif (suffixId !== undefined) return { modelId: suffixId, parameters: [] };\n\n\tif (spec.encoding === \"variant-id\") {\n\t\treturn { modelId: compat.representativeVariantId, parameters: [] };\n\t}\n\n\treturn {\n\t\tmodelId: compat.capabilityId,\n\t\tparameters: buildParameters(compat.capabilityId, spec.value, compat.thinkingMode),\n\t};\n}\n\n/** Render the resolved descriptor as one CLI `--model` argv element (bracket or suffix form). */\nexport function renderCursorCliModelString(\n\tmodel: Model<\"cursor-agent\">,\n\tselection: ThinkingSelection | undefined,\n): string {\n\tconst resolved = resolveCursorSelectionDescriptor(model, selection);\n\tif (resolved.parameters.length === 0) return resolved.modelId;\n\tconst args = resolved.parameters.map((parameter) => `${parameter.id}=${parameter.value}`).join(\",\");\n\treturn `${resolved.modelId}[${args}]`;\n}\n"]}
@@ -1,8 +1,13 @@
1
1
  import type { Model } from "../types.ts";
2
2
  /**
3
3
  * Idempotent stored-catalog transform: pre-grouping 204-variant cursor entries
4
- * are regrouped into selectable identities; already-grouped, unknown, and
5
- * malformed entries pass through unchanged in stable input order.
4
+ * are regrouped into selectable identities, including families the static
5
+ * alias table does not list yet, which are derived over the stored batch
6
+ * (senpi#2038). An already-grouped identity (static or derived) always wins
7
+ * over flat rows aliasing it, regardless of input order, and absorbs their
8
+ * levels without losing its own metadata; conflicting derived variants stay
9
+ * flat, and duplicate identities coalesce at their first position in stable
10
+ * input order.
6
11
  */
7
12
  export declare function regroupStoredCursorModels(models: readonly Model<"cursor-agent">[]): Model<"cursor-agent">[];
8
13
  //# sourceMappingURL=store-migration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store-migration.d.ts","sourceRoot":"","sources":["../../src/cursor/store-migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA0CzC;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CAiC3G"}
1
+ {"version":3,"file":"store-migration.d.ts","sourceRoot":"","sources":["../../src/cursor/store-migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAsB,MAAM,aAAa,CAAC;AAsD7D;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CA8F3G"}
@@ -1,8 +1,15 @@
1
- import { normalizeCursorCatalog } from "./catalog-grouping.js";
1
+ import { deriveCursorVariantAliases, normalizeCursorCatalog } from "./catalog-grouping.js";
2
2
  import { resolveCursorContextWindow } from "./context-limit-store.js";
3
- import { getCursorVariantAlias } from "./model-capabilities.js";
4
- function isGroupedShape(model) {
5
- return model.compat?.cursorReasoning !== undefined || getCursorVariantAlias(model.id) === undefined;
3
+ import { getCursorVariantAlias, parseCursorVariantId } from "./model-capabilities.js";
4
+ /**
5
+ * Fill levels a stored static group lacks from flat alias rows regrouped beside it;
6
+ * the group's own levels, representative, and compat metadata are never replaced.
7
+ */
8
+ function absorbStaticLevels(current, flatGroup) {
9
+ const additions = Object.entries(flatGroup?.thinkingLevelMap ?? {}).filter(([level, value]) => value != null && current.thinkingLevelMap?.[level] == null);
10
+ if (additions.length === 0)
11
+ return current;
12
+ return { ...current, thinkingLevelMap: { ...current.thinkingLevelMap, ...Object.fromEntries(additions) } };
6
13
  }
7
14
  function entryToModel(entry, maxTokensById) {
8
15
  const representative = entry.representativeVariantId ?? entry.legacyAliases[0] ?? entry.id;
@@ -30,6 +37,7 @@ function entryToModel(entry, maxTokensById) {
30
37
  capabilityId: entry.capabilityId,
31
38
  ...(entry.thinkingMode !== undefined ? { thinkingMode: entry.thinkingMode } : {}),
32
39
  representativeVariantId: entry.representativeVariantId,
40
+ ...(entry.variantIds !== undefined ? { variantIds: entry.variantIds } : {}),
33
41
  },
34
42
  }
35
43
  : {}),
@@ -38,13 +46,36 @@ function entryToModel(entry, maxTokensById) {
38
46
  }
39
47
  /**
40
48
  * Idempotent stored-catalog transform: pre-grouping 204-variant cursor entries
41
- * are regrouped into selectable identities; already-grouped, unknown, and
42
- * malformed entries pass through unchanged in stable input order.
49
+ * are regrouped into selectable identities, including families the static
50
+ * alias table does not list yet, which are derived over the stored batch
51
+ * (senpi#2038). An already-grouped identity (static or derived) always wins
52
+ * over flat rows aliasing it, regardless of input order, and absorbs their
53
+ * levels without losing its own metadata; conflicting derived variants stay
54
+ * flat, and duplicate identities coalesce at their first position in stable
55
+ * input order.
43
56
  */
44
57
  export function regroupStoredCursorModels(models) {
45
- const legacy = models.filter((model) => !isGroupedShape(model));
46
- if (legacy.length === 0)
47
- return [...models];
58
+ const existingGroups = new Map();
59
+ const existingDerived = new Map();
60
+ const representedTargetById = new Map();
61
+ for (const model of models) {
62
+ const reasoning = model.compat?.cursorReasoning;
63
+ if (reasoning === undefined || existingGroups.has(model.id))
64
+ continue;
65
+ existingGroups.set(model.id, model);
66
+ if (reasoning.variantIds === undefined)
67
+ continue;
68
+ existingDerived.set(model.id, model);
69
+ for (const id of Object.values(reasoning.variantIds))
70
+ representedTargetById.set(id, model.id);
71
+ }
72
+ const derived = deriveCursorVariantAliases([
73
+ ...models.filter((model) => model.compat?.cursorReasoning === undefined).map((model) => model.id),
74
+ ...[...existingDerived.values()].flatMap((model) => Object.values(model.compat?.cursorReasoning?.variantIds ?? {})),
75
+ ]);
76
+ const isLegacy = (model) => model.compat?.cursorReasoning === undefined &&
77
+ (getCursorVariantAlias(model.id) !== undefined || derived.has(model.id) || representedTargetById.has(model.id));
78
+ const legacy = models.filter(isLegacy);
48
79
  const maxTokensById = new Map(models.map((model) => [model.id, model.maxTokens]));
49
80
  const regrouped = new Map(normalizeCursorCatalog(legacy.map((model) => ({
50
81
  id: model.id,
@@ -52,25 +83,66 @@ export function regroupStoredCursorModels(models) {
52
83
  input: model.input.filter((modality) => modality !== "video"),
53
84
  cursorMaxMode: model.compat?.cursorMaxMode === true,
54
85
  }))).map((entry) => [entry.id, entryToModel(entry, maxTokensById)]));
86
+ const merged = new Map();
87
+ for (const [targetId, current] of existingGroups) {
88
+ const kept = current.compat?.cursorReasoning;
89
+ if (kept?.variantIds === undefined) {
90
+ merged.set(targetId, absorbStaticLevels(current, regrouped.get(targetId)));
91
+ continue;
92
+ }
93
+ const variantIds = { ...kept.variantIds };
94
+ const thinkingLevelMap = { ...current.thinkingLevelMap };
95
+ let changed = false;
96
+ for (const model of legacy) {
97
+ const alias = derived.get(model.id);
98
+ if (alias?.targetId !== targetId || alias.level === undefined)
99
+ continue;
100
+ if (variantIds[alias.level] !== undefined && variantIds[alias.level] !== model.id)
101
+ continue;
102
+ variantIds[alias.level] = model.id;
103
+ thinkingLevelMap[alias.level] = parseCursorVariantId(model.id).level;
104
+ changed = true;
105
+ }
106
+ merged.set(targetId, changed
107
+ ? {
108
+ ...current,
109
+ thinkingLevelMap,
110
+ compat: { ...current.compat, cursorReasoning: { ...kept, variantIds } },
111
+ }
112
+ : current);
113
+ }
55
114
  const seen = new Set();
56
115
  const out = [];
57
116
  for (const model of models) {
58
- if (isGroupedShape(model)) {
59
- out.push(model);
117
+ const alias = isLegacy(model) ? (getCursorVariantAlias(model.id) ?? derived.get(model.id)) : undefined;
118
+ const targetId = alias?.targetId ?? (isLegacy(model) ? representedTargetById.get(model.id) : undefined) ?? model.id;
119
+ const coalesced = merged.get(targetId);
120
+ if (coalesced !== undefined) {
121
+ const retainedIds = coalesced.compat?.cursorReasoning?.variantIds;
122
+ // Static groups absorb every flat alias row; derived groups keep conflicting variants flat.
123
+ const absorbed = model.id === targetId ||
124
+ (retainedIds === undefined ? isLegacy(model) : Object.values(retainedIds).includes(model.id));
125
+ if (!absorbed) {
126
+ if (!seen.has(model.id))
127
+ out.push(model);
128
+ seen.add(model.id);
129
+ continue;
130
+ }
131
+ if (!seen.has(targetId))
132
+ out.push(coalesced);
133
+ seen.add(targetId);
134
+ continue;
135
+ }
136
+ if (!isLegacy(model)) {
137
+ if (!seen.has(model.id))
138
+ out.push(model);
139
+ seen.add(model.id);
60
140
  continue;
61
141
  }
62
- const alias = getCursorVariantAlias(model.id);
63
- const targetId = alias?.targetId ?? model.id;
64
142
  if (seen.has(targetId))
65
143
  continue;
66
144
  seen.add(targetId);
67
- const transformed = regrouped.get(targetId);
68
- if (transformed !== undefined) {
69
- out.push(transformed);
70
- }
71
- else {
72
- out.push(model);
73
- }
145
+ out.push(regrouped.get(targetId) ?? model);
74
146
  }
75
147
  return out;
76
148
  }
@@ -1 +1 @@
1
- {"version":3,"file":"store-migration.js","sourceRoot":"","sources":["../../src/cursor/store-migration.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model } from \"../types.ts\";\nimport { type CursorCatalogEntry, normalizeCursorCatalog } from \"./catalog-grouping.ts\";\nimport { resolveCursorContextWindow } from \"./context-limit-store.ts\";\nimport { getCursorVariantAlias } from \"./model-capabilities.ts\";\n\nfunction isGroupedShape(model: Model<\"cursor-agent\">): boolean {\n\treturn model.compat?.cursorReasoning !== undefined || getCursorVariantAlias(model.id) === undefined;\n}\n\nfunction entryToModel(entry: CursorCatalogEntry, maxTokensById: ReadonlyMap<string, number>): Model<\"cursor-agent\"> {\n\tconst representative = entry.representativeVariantId ?? entry.legacyAliases[0] ?? entry.id;\n\tconst maxTokens = maxTokensById.get(representative) ?? maxTokensById.get(entry.id) ?? 64000;\n\treturn {\n\t\tid: entry.id,\n\t\tname: entry.name,\n\t\tapi: \"cursor-agent\",\n\t\tprovider: \"cursor\",\n\t\tbaseUrl: \"https://api2.cursor.sh\",\n\t\treasoning: entry.reasoning,\n\t\t...(entry.thinkingLevelMap ? { thinkingLevelMap: entry.thinkingLevelMap } : {}),\n\t\tinput: entry.input,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: resolveCursorContextWindow(entry.id, entry.window),\n\t\tmaxTokens,\n\t\t...(entry.representativeVariantId !== undefined && entry.representativeVariantId !== entry.id\n\t\t\t? { upstreamModelId: entry.representativeVariantId }\n\t\t\t: {}),\n\t\tcompat: {\n\t\t\t...(entry.cursorMaxMode ? { cursorMaxMode: true } : {}),\n\t\t\t...(entry.capabilityId !== undefined && entry.representativeVariantId !== undefined\n\t\t\t\t? {\n\t\t\t\t\t\tcursorReasoning: {\n\t\t\t\t\t\t\tcapabilityId: entry.capabilityId,\n\t\t\t\t\t\t\t...(entry.thinkingMode !== undefined ? { thinkingMode: entry.thinkingMode } : {}),\n\t\t\t\t\t\t\trepresentativeVariantId: entry.representativeVariantId,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t},\n\t};\n}\n\n/**\n * Idempotent stored-catalog transform: pre-grouping 204-variant cursor entries\n * are regrouped into selectable identities; already-grouped, unknown, and\n * malformed entries pass through unchanged in stable input order.\n */\nexport function regroupStoredCursorModels(models: readonly Model<\"cursor-agent\">[]): Model<\"cursor-agent\">[] {\n\tconst legacy = models.filter((model) => !isGroupedShape(model));\n\tif (legacy.length === 0) return [...models];\n\tconst maxTokensById = new Map(models.map((model) => [model.id, model.maxTokens]));\n\tconst regrouped = new Map(\n\t\tnormalizeCursorCatalog(\n\t\t\tlegacy.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\tname: model.name,\n\t\t\t\tinput: model.input.filter((modality): modality is \"text\" | \"image\" => modality !== \"video\"),\n\t\t\t\tcursorMaxMode: model.compat?.cursorMaxMode === true,\n\t\t\t})),\n\t\t).map((entry) => [entry.id, entryToModel(entry, maxTokensById)] as const),\n\t);\n\tconst seen = new Set<string>();\n\tconst out: Model<\"cursor-agent\">[] = [];\n\tfor (const model of models) {\n\t\tif (isGroupedShape(model)) {\n\t\t\tout.push(model);\n\t\t\tcontinue;\n\t\t}\n\t\tconst alias = getCursorVariantAlias(model.id);\n\t\tconst targetId = alias?.targetId ?? model.id;\n\t\tif (seen.has(targetId)) continue;\n\t\tseen.add(targetId);\n\t\tconst transformed = regrouped.get(targetId);\n\t\tif (transformed !== undefined) {\n\t\t\tout.push(transformed);\n\t\t} else {\n\t\t\tout.push(model);\n\t\t}\n\t}\n\treturn out;\n}\n"]}
1
+ {"version":3,"file":"store-migration.js","sourceRoot":"","sources":["../../src/cursor/store-migration.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model, ModelThinkingLevel } from \"../types.ts\";\nimport { type CursorCatalogEntry, deriveCursorVariantAliases, normalizeCursorCatalog } from \"./catalog-grouping.ts\";\nimport { resolveCursorContextWindow } from \"./context-limit-store.ts\";\nimport { getCursorVariantAlias, parseCursorVariantId } from \"./model-capabilities.ts\";\n\n/**\n * Fill levels a stored static group lacks from flat alias rows regrouped beside it;\n * the group's own levels, representative, and compat metadata are never replaced.\n */\nfunction absorbStaticLevels(\n\tcurrent: Model<\"cursor-agent\">,\n\tflatGroup: Model<\"cursor-agent\"> | undefined,\n): Model<\"cursor-agent\"> {\n\tconst additions = Object.entries(flatGroup?.thinkingLevelMap ?? {}).filter(\n\t\t([level, value]) => value != null && current.thinkingLevelMap?.[level as ModelThinkingLevel] == null,\n\t);\n\tif (additions.length === 0) return current;\n\treturn { ...current, thinkingLevelMap: { ...current.thinkingLevelMap, ...Object.fromEntries(additions) } };\n}\n\nfunction entryToModel(entry: CursorCatalogEntry, maxTokensById: ReadonlyMap<string, number>): Model<\"cursor-agent\"> {\n\tconst representative = entry.representativeVariantId ?? entry.legacyAliases[0] ?? entry.id;\n\tconst maxTokens = maxTokensById.get(representative) ?? maxTokensById.get(entry.id) ?? 64000;\n\treturn {\n\t\tid: entry.id,\n\t\tname: entry.name,\n\t\tapi: \"cursor-agent\",\n\t\tprovider: \"cursor\",\n\t\tbaseUrl: \"https://api2.cursor.sh\",\n\t\treasoning: entry.reasoning,\n\t\t...(entry.thinkingLevelMap ? { thinkingLevelMap: entry.thinkingLevelMap } : {}),\n\t\tinput: entry.input,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: resolveCursorContextWindow(entry.id, entry.window),\n\t\tmaxTokens,\n\t\t...(entry.representativeVariantId !== undefined && entry.representativeVariantId !== entry.id\n\t\t\t? { upstreamModelId: entry.representativeVariantId }\n\t\t\t: {}),\n\t\tcompat: {\n\t\t\t...(entry.cursorMaxMode ? { cursorMaxMode: true } : {}),\n\t\t\t...(entry.capabilityId !== undefined && entry.representativeVariantId !== undefined\n\t\t\t\t? {\n\t\t\t\t\t\tcursorReasoning: {\n\t\t\t\t\t\t\tcapabilityId: entry.capabilityId,\n\t\t\t\t\t\t\t...(entry.thinkingMode !== undefined ? { thinkingMode: entry.thinkingMode } : {}),\n\t\t\t\t\t\t\trepresentativeVariantId: entry.representativeVariantId,\n\t\t\t\t\t\t\t...(entry.variantIds !== undefined ? { variantIds: entry.variantIds } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t},\n\t};\n}\n\n/**\n * Idempotent stored-catalog transform: pre-grouping 204-variant cursor entries\n * are regrouped into selectable identities, including families the static\n * alias table does not list yet, which are derived over the stored batch\n * (senpi#2038). An already-grouped identity (static or derived) always wins\n * over flat rows aliasing it, regardless of input order, and absorbs their\n * levels without losing its own metadata; conflicting derived variants stay\n * flat, and duplicate identities coalesce at their first position in stable\n * input order.\n */\nexport function regroupStoredCursorModels(models: readonly Model<\"cursor-agent\">[]): Model<\"cursor-agent\">[] {\n\tconst existingGroups = new Map<string, Model<\"cursor-agent\">>();\n\tconst existingDerived = new Map<string, Model<\"cursor-agent\">>();\n\tconst representedTargetById = new Map<string, string>();\n\tfor (const model of models) {\n\t\tconst reasoning = model.compat?.cursorReasoning;\n\t\tif (reasoning === undefined || existingGroups.has(model.id)) continue;\n\t\texistingGroups.set(model.id, model);\n\t\tif (reasoning.variantIds === undefined) continue;\n\t\texistingDerived.set(model.id, model);\n\t\tfor (const id of Object.values(reasoning.variantIds)) representedTargetById.set(id, model.id);\n\t}\n\tconst derived = deriveCursorVariantAliases([\n\t\t...models.filter((model) => model.compat?.cursorReasoning === undefined).map((model) => model.id),\n\t\t...[...existingDerived.values()].flatMap((model) =>\n\t\t\tObject.values(model.compat?.cursorReasoning?.variantIds ?? {}),\n\t\t),\n\t]);\n\tconst isLegacy = (model: Model<\"cursor-agent\">): boolean =>\n\t\tmodel.compat?.cursorReasoning === undefined &&\n\t\t(getCursorVariantAlias(model.id) !== undefined || derived.has(model.id) || representedTargetById.has(model.id));\n\tconst legacy = models.filter(isLegacy);\n\tconst maxTokensById = new Map(models.map((model) => [model.id, model.maxTokens]));\n\tconst regrouped = new Map(\n\t\tnormalizeCursorCatalog(\n\t\t\tlegacy.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\tname: model.name,\n\t\t\t\tinput: model.input.filter((modality): modality is \"text\" | \"image\" => modality !== \"video\"),\n\t\t\t\tcursorMaxMode: model.compat?.cursorMaxMode === true,\n\t\t\t})),\n\t\t).map((entry) => [entry.id, entryToModel(entry, maxTokensById)] as const),\n\t);\n\tconst merged = new Map<string, Model<\"cursor-agent\">>();\n\tfor (const [targetId, current] of existingGroups) {\n\t\tconst kept = current.compat?.cursorReasoning;\n\t\tif (kept?.variantIds === undefined) {\n\t\t\tmerged.set(targetId, absorbStaticLevels(current, regrouped.get(targetId)));\n\t\t\tcontinue;\n\t\t}\n\t\tconst variantIds = { ...kept.variantIds };\n\t\tconst thinkingLevelMap = { ...current.thinkingLevelMap };\n\t\tlet changed = false;\n\t\tfor (const model of legacy) {\n\t\t\tconst alias = derived.get(model.id);\n\t\t\tif (alias?.targetId !== targetId || alias.level === undefined) continue;\n\t\t\tif (variantIds[alias.level] !== undefined && variantIds[alias.level] !== model.id) continue;\n\t\t\tvariantIds[alias.level] = model.id;\n\t\t\tthinkingLevelMap[alias.level] = parseCursorVariantId(model.id).level;\n\t\t\tchanged = true;\n\t\t}\n\t\tmerged.set(\n\t\t\ttargetId,\n\t\t\tchanged\n\t\t\t\t? {\n\t\t\t\t\t\t...current,\n\t\t\t\t\t\tthinkingLevelMap,\n\t\t\t\t\t\tcompat: { ...current.compat, cursorReasoning: { ...kept, variantIds } },\n\t\t\t\t\t}\n\t\t\t\t: current,\n\t\t);\n\t}\n\tconst seen = new Set<string>();\n\tconst out: Model<\"cursor-agent\">[] = [];\n\tfor (const model of models) {\n\t\tconst alias = isLegacy(model) ? (getCursorVariantAlias(model.id) ?? derived.get(model.id)) : undefined;\n\t\tconst targetId =\n\t\t\talias?.targetId ?? (isLegacy(model) ? representedTargetById.get(model.id) : undefined) ?? model.id;\n\t\tconst coalesced = merged.get(targetId);\n\t\tif (coalesced !== undefined) {\n\t\t\tconst retainedIds = coalesced.compat?.cursorReasoning?.variantIds;\n\t\t\t// Static groups absorb every flat alias row; derived groups keep conflicting variants flat.\n\t\t\tconst absorbed =\n\t\t\t\tmodel.id === targetId ||\n\t\t\t\t(retainedIds === undefined ? isLegacy(model) : Object.values(retainedIds).includes(model.id));\n\t\t\tif (!absorbed) {\n\t\t\t\tif (!seen.has(model.id)) out.push(model);\n\t\t\t\tseen.add(model.id);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!seen.has(targetId)) out.push(coalesced);\n\t\t\tseen.add(targetId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!isLegacy(model)) {\n\t\t\tif (!seen.has(model.id)) out.push(model);\n\t\t\tseen.add(model.id);\n\t\t\tcontinue;\n\t\t}\n\t\tif (seen.has(targetId)) continue;\n\t\tseen.add(targetId);\n\t\tout.push(regrouped.get(targetId) ?? model);\n\t}\n\treturn out;\n}\n"]}
@@ -275,6 +275,21 @@ export declare const IMAGE_MODELS: {
275
275
  cacheWrite: number;
276
276
  };
277
277
  };
278
+ readonly "inclusionai/ming-image-0.1-design-layer": {
279
+ id: string;
280
+ name: string;
281
+ api: "openrouter-images";
282
+ provider: string;
283
+ baseUrl: string;
284
+ input: ("image" | "text")[];
285
+ output: "image"[];
286
+ cost: {
287
+ input: number;
288
+ output: number;
289
+ cacheRead: number;
290
+ cacheWrite: number;
291
+ };
292
+ };
278
293
  readonly "krea/krea-2-large": {
279
294
  id: string;
280
295
  name: string;
@@ -725,6 +740,21 @@ export declare const IMAGE_MODELS: {
725
740
  cacheWrite: number;
726
741
  };
727
742
  };
743
+ readonly "recraft/recraft-v4.1-flash": {
744
+ id: string;
745
+ name: string;
746
+ api: "openrouter-images";
747
+ provider: string;
748
+ baseUrl: string;
749
+ input: "text"[];
750
+ output: "image"[];
751
+ cost: {
752
+ input: number;
753
+ output: number;
754
+ cacheRead: number;
755
+ cacheWrite: number;
756
+ };
757
+ };
728
758
  readonly "recraft/recraft-v4.1-pro": {
729
759
  id: string;
730
760
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;gBAWrB,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;;;gBAcV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;CAI6D,CAAC"}
1
+ {"version":3,"file":"image-models.generated.d.ts","sourceRoot":"","sources":["../src/image-models.generated.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;gBAWrB,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;;;gBAcV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;;;;;;;;;gBAYV,KAAK;gBACL,MAAM;gBACN,SAAS;gBACT,UAAU;;;;CAI6D,CAAC"}