mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 02:42:24 +03:00
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun.
114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
export const CURSOR_EFFORT_SUFFIXES = ["low", "medium", "high", "xhigh", "max"] as const;
|
|
|
|
type CursorRequestedModel = {
|
|
modelId: string;
|
|
parameters: Array<{ id: string; value: string }>;
|
|
};
|
|
|
|
const CURSOR_ONE_MILLION_SUFFIX = "-1m";
|
|
const CURSOR_GPT_REASONING_LEVELS = ["none", ...CURSOR_EFFORT_SUFFIXES] as const;
|
|
|
|
const CURSOR_CLAUDE_ONE_MILLION_FAMILIES = [
|
|
{
|
|
legacyPrefix: "claude-fable-5-1",
|
|
modelId: "claude-fable-5-1",
|
|
supportsFast: false,
|
|
trailingThinking: false,
|
|
},
|
|
{
|
|
legacyPrefix: "claude-opus-5",
|
|
modelId: "claude-opus-5",
|
|
supportsFast: true,
|
|
trailingThinking: false,
|
|
},
|
|
{
|
|
legacyPrefix: "claude-opus-4-8",
|
|
modelId: "claude-opus-4-8",
|
|
supportsFast: true,
|
|
trailingThinking: false,
|
|
},
|
|
{
|
|
legacyPrefix: "claude-sonnet-5",
|
|
modelId: "claude-sonnet-5",
|
|
supportsFast: false,
|
|
trailingThinking: false,
|
|
},
|
|
{
|
|
legacyPrefix: "claude-4.6-sonnet",
|
|
modelId: "claude-sonnet-4-6",
|
|
supportsFast: false,
|
|
trailingThinking: true,
|
|
},
|
|
] as const;
|
|
|
|
type CursorClaudeOneMillionFamily = (typeof CURSOR_CLAUDE_ONE_MILLION_FAMILIES)[number];
|
|
|
|
function isCursorEffort(value: string): value is (typeof CURSOR_EFFORT_SUFFIXES)[number] {
|
|
return CURSOR_EFFORT_SUFFIXES.some((effort) => effort === value);
|
|
}
|
|
|
|
function resolveGptOneMillionContextModel(legacyId: string): CursorRequestedModel | null {
|
|
const match = /^(gpt-5\.6-(?:sol|terra|luna))-(none|low|medium|high|xhigh|max)$/.exec(legacyId);
|
|
if (!match) return null;
|
|
|
|
const [, modelId, reasoning] = match;
|
|
if (!CURSOR_GPT_REASONING_LEVELS.some((level) => level === reasoning)) return null;
|
|
return {
|
|
modelId,
|
|
parameters: [
|
|
{ id: "context", value: "1m" },
|
|
{ id: "reasoning", value: reasoning },
|
|
{ id: "fast", value: "false" },
|
|
],
|
|
};
|
|
}
|
|
|
|
function resolveClaudeOneMillionVariant(
|
|
legacyId: string,
|
|
family: CursorClaudeOneMillionFamily
|
|
): CursorRequestedModel | null {
|
|
const prefix = `${family.legacyPrefix}-`;
|
|
if (!legacyId.startsWith(prefix)) return null;
|
|
|
|
let variant = legacyId.slice(prefix.length);
|
|
const fast = variant.endsWith("-fast");
|
|
if (fast) variant = variant.slice(0, -"-fast".length);
|
|
if (fast && !family.supportsFast) return null;
|
|
|
|
const trailingThinking = family.trailingThinking && variant.endsWith("-thinking");
|
|
const leadingThinking = !family.trailingThinking && variant.startsWith("thinking-");
|
|
if (trailingThinking) variant = variant.slice(0, -"-thinking".length);
|
|
if (leadingThinking) variant = variant.slice("thinking-".length);
|
|
if (!isCursorEffort(variant)) return null;
|
|
|
|
const parameters = [
|
|
{ id: "thinking", value: String(trailingThinking || leadingThinking) },
|
|
{ id: "context", value: "1m" },
|
|
{ id: "effort", value: variant },
|
|
];
|
|
if (family.supportsFast) parameters.push({ id: "fast", value: String(fast) });
|
|
return { modelId: family.modelId, parameters };
|
|
}
|
|
|
|
function resolveClaudeOneMillionContextModel(legacyId: string): CursorRequestedModel | null {
|
|
for (const family of CURSOR_CLAUDE_ONE_MILLION_FAMILIES) {
|
|
const resolved = resolveClaudeOneMillionVariant(legacyId, family);
|
|
if (resolved) return resolved;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Cursor reuses each legacy slug for both its default and 1M context variants,
|
|
* so the public catalog adds a terminal `-1m` discriminator. Translate that
|
|
* synthetic id to the canonical wire model plus the complete parameter set
|
|
* reported by Cursor's AvailableModels metadata.
|
|
*/
|
|
export function resolveOneMillionContextModel(normalized: string): CursorRequestedModel | null {
|
|
if (!normalized.endsWith(CURSOR_ONE_MILLION_SUFFIX)) return null;
|
|
const legacyId = normalized.slice(0, -CURSOR_ONE_MILLION_SUFFIX.length);
|
|
return (
|
|
resolveGptOneMillionContextModel(legacyId) ?? resolveClaudeOneMillionContextModel(legacyId)
|
|
);
|
|
}
|