diff --git a/src/cli/config-manager/detect-current-config.ts b/src/cli/config-manager/detect-current-config.ts index f158e18e2..e1fb39823 100644 --- a/src/cli/config-manager/detect-current-config.ts +++ b/src/cli/config-manager/detect-current-config.ts @@ -12,6 +12,7 @@ function detectProvidersFromOmoConfig(): { hasZaiCodingPlan: boolean hasKimiForCoding: boolean hasOpencodeGo: boolean + hasVercelAiGateway: boolean } { const omoConfigPath = getOmoConfigPath() if (!existsSync(omoConfigPath)) { @@ -21,6 +22,7 @@ function detectProvidersFromOmoConfig(): { hasZaiCodingPlan: false, hasKimiForCoding: false, hasOpencodeGo: false, + hasVercelAiGateway: false, } } @@ -34,6 +36,7 @@ function detectProvidersFromOmoConfig(): { hasZaiCodingPlan: false, hasKimiForCoding: false, hasOpencodeGo: false, + hasVercelAiGateway: false, } } @@ -43,8 +46,9 @@ function detectProvidersFromOmoConfig(): { const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/') const hasKimiForCoding = configStr.includes('"kimi-for-coding/') const hasOpencodeGo = configStr.includes('"opencode-go/') + const hasVercelAiGateway = configStr.includes('"vercel/') - return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo } + return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo, hasVercelAiGateway } } catch { return { hasOpenAI: true, @@ -52,6 +56,7 @@ function detectProvidersFromOmoConfig(): { hasZaiCodingPlan: false, hasKimiForCoding: false, hasOpencodeGo: false, + hasVercelAiGateway: false, } } } @@ -78,6 +83,7 @@ export function detectCurrentConfig(): DetectedConfig { hasZaiCodingPlan: false, hasKimiForCoding: false, hasOpencodeGo: false, + hasVercelAiGateway: false, } const { format, path } = detectConfigFormat() @@ -106,12 +112,13 @@ export function detectCurrentConfig(): DetectedConfig { const providers = openCodeConfig.provider as Record | undefined result.hasGemini = providers ? "google" in providers : false - const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo } = detectProvidersFromOmoConfig() + const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo, hasVercelAiGateway } = detectProvidersFromOmoConfig() result.hasOpenAI = hasOpenAI result.hasOpencodeZen = hasOpencodeZen result.hasZaiCodingPlan = hasZaiCodingPlan result.hasKimiForCoding = hasKimiForCoding result.hasOpencodeGo = hasOpencodeGo + result.hasVercelAiGateway = hasVercelAiGateway return result } diff --git a/src/cli/install-validators.ts b/src/cli/install-validators.ts index be429eee6..695747edf 100644 --- a/src/cli/install-validators.ts +++ b/src/cli/install-validators.ts @@ -40,6 +40,7 @@ export function formatConfigSummary(config: InstallConfig): string { lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models")) lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal")) lines.push(formatProvider("Kimi For Coding", config.hasKimiForCoding, "Sisyphus/Prometheus fallback")) + lines.push(formatProvider("Vercel AI Gateway", config.hasVercelAiGateway, "universal proxy")) lines.push("") lines.push(color.dim("─".repeat(40))) @@ -153,6 +154,10 @@ export function validateNonTuiArgs(args: InstallArgs): { valid: boolean; errors: errors.push(`Invalid --kimi-for-coding value: ${args.kimiForCoding} (expected: no, yes)`) } + if (args.vercelAiGateway !== undefined && !["no", "yes"].includes(args.vercelAiGateway)) { + errors.push(`Invalid --vercel-ai-gateway value: ${args.vercelAiGateway} (expected: no, yes)`) + } + return { valid: errors.length === 0, errors } } @@ -167,6 +172,7 @@ export function argsToConfig(args: InstallArgs): InstallConfig { hasZaiCodingPlan: args.zaiCodingPlan === "yes", hasKimiForCoding: args.kimiForCoding === "yes", hasOpencodeGo: args.opencodeGo === "yes", + hasVercelAiGateway: args.vercelAiGateway === "yes", } } @@ -179,6 +185,7 @@ export function detectedToInitialValues(detected: DetectedConfig): { zaiCodingPlan: BooleanArg kimiForCoding: BooleanArg opencodeGo: BooleanArg + vercelAiGateway: BooleanArg } { let claude: ClaudeSubscription = "no" if (detected.hasClaude) { @@ -194,5 +201,6 @@ kimiForCoding: BooleanArg zaiCodingPlan: detected.hasZaiCodingPlan ? "yes" : "no", kimiForCoding: detected.hasKimiForCoding ? "yes" : "no", opencodeGo: detected.hasOpencodeGo ? "yes" : "no", + vercelAiGateway: detected.hasVercelAiGateway ? "yes" : "no", } } diff --git a/src/cli/model-fallback-types.ts b/src/cli/model-fallback-types.ts index b195f698a..6daa24388 100644 --- a/src/cli/model-fallback-types.ts +++ b/src/cli/model-fallback-types.ts @@ -11,6 +11,7 @@ export interface ProviderAvailability { zai: boolean kimiForCoding: boolean opencodeGo: boolean + vercelAiGateway: boolean isMaxPlan: boolean } diff --git a/src/cli/model-fallback.ts b/src/cli/model-fallback.ts index 5dabb9fc1..ab67960e9 100644 --- a/src/cli/model-fallback.ts +++ b/src/cli/model-fallback.ts @@ -105,7 +105,8 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig { avail.copilot || avail.zai || avail.kimiForCoding || - avail.opencodeGo + avail.opencodeGo || + avail.vercelAiGateway if (!hasAnyProvider) { return { $schema: SCHEMA_URL, @@ -130,6 +131,8 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig { agentConfig = { model: "opencode-go/minimax-m2.7" } } else if (avail.zai) { agentConfig = { model: ZAI_MODEL } + } else if (avail.vercelAiGateway) { + agentConfig = { model: "vercel/anthropic/claude-haiku-4.5" } } if (agentConfig) { agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail) @@ -145,6 +148,8 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig { agentConfig = { model: "opencode/claude-haiku-4-5" } } else if (avail.opencodeGo) { agentConfig = { model: "opencode-go/minimax-m2.7" } + } else if (avail.vercelAiGateway) { + agentConfig = { model: "vercel/anthropic/claude-haiku-4.5" } } else if (avail.copilot) { agentConfig = { model: "github-copilot/gpt-5-mini" } } else { diff --git a/src/cli/provider-availability.ts b/src/cli/provider-availability.ts index 6d17422f7..f9ac8189b 100644 --- a/src/cli/provider-availability.ts +++ b/src/cli/provider-availability.ts @@ -13,6 +13,7 @@ export function toProviderAvailability(config: InstallConfig): ProviderAvailabil zai: config.hasZaiCodingPlan, kimiForCoding: config.hasKimiForCoding, opencodeGo: config.hasOpencodeGo, + vercelAiGateway: config.hasVercelAiGateway, isMaxPlan: config.isMax20, } } @@ -27,6 +28,7 @@ export function isProviderAvailable(provider: string, availability: ProviderAvai "zai-coding-plan": availability.zai, "kimi-for-coding": availability.kimiForCoding, "opencode-go": availability.opencodeGo, + vercel: availability.vercelAiGateway, } return mapping[provider] ?? false } diff --git a/src/cli/tui-install-prompts.ts b/src/cli/tui-install-prompts.ts index c2e5a3b49..3d5fb4584 100644 --- a/src/cli/tui-install-prompts.ts +++ b/src/cli/tui-install-prompts.ts @@ -110,6 +110,16 @@ export async function promptInstallConfig(detected: DetectedConfig): Promise { expect(sisyphus.requiresAnyModel).toBe(true) const primary = sisyphus.fallbackChain[0] - expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) + expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode", "vercel"]) expect(primary.model).toBe("claude-opus-4-6") expect(primary.variant).toBe("max") @@ -132,7 +132,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(multimodalLooker.fallbackChain).toHaveLength(4) const primary = multimodalLooker.fallbackChain[0] - expect(primary.providers).toEqual(["openai", "opencode"]) + expect(primary.providers).toEqual(["openai", "opencode", "vercel"]) expect(primary.model).toBe("gpt-5.4") expect(primary.variant).toBe("medium") @@ -144,7 +144,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(tertiary.model).toBe("glm-4.6v") const last = multimodalLooker.fallbackChain[3] - expect(last.providers).toEqual(["openai", "github-copilot", "opencode"]) + expect(last.providers).toEqual(["openai", "github-copilot", "opencode", "vercel"]) expect(last.model).toBe("gpt-5-nano") }) @@ -160,7 +160,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { const primary = prometheus.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") - expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) + expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode", "vercel"]) expect(primary.variant).toBe("max") }) @@ -176,12 +176,12 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { const primary = metis.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") - expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) + expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode", "vercel"]) expect(primary.variant).toBe("max") const openAiFallback = metis.fallbackChain.find((entry) => entry.providers.includes("openai")) expect(openAiFallback).toEqual({ - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "high", }) @@ -223,7 +223,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { const tertiary = atlas.fallbackChain[2] expect(tertiary).toEqual({ - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }) @@ -245,7 +245,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { // then expect(openAiFallback).toEqual({ - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }) @@ -261,7 +261,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { // #when - accessing hephaestus requirement // #then - requiresProvider includes openai, github-copilot, venice, and opencode expect(hephaestus).toBeDefined() - expect(hephaestus.requiresProvider).toEqual(["openai", "github-copilot", "venice", "opencode"]) + expect(hephaestus.requiresProvider).toEqual(["openai", "github-copilot", "venice", "opencode", "vercel"]) expect(hephaestus.requiresModel).toBeUndefined() }) @@ -415,12 +415,12 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => { const primary = unspecifiedHigh.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") expect(primary.variant).toBe("max") - expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) + expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode", "vercel"]) const secondary = unspecifiedHigh.fallbackChain[1] expect(secondary.model).toBe("gpt-5.4") expect(secondary.variant).toBe("high") - expect(secondary.providers).toEqual(["openai", "github-copilot", "opencode"]) + expect(secondary.providers).toEqual(["openai", "github-copilot", "opencode", "vercel"]) }) test("artistry has valid fallbackChain with gemini-3.1-pro as primary", () => { diff --git a/src/shared/model-requirements.ts b/src/shared/model-requirements.ts index 5a1889eae..4a0ce6071 100644 --- a/src/shared/model-requirements.ts +++ b/src/shared/model-requirements.ts @@ -21,7 +21,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { sisyphus: { fallbackChain: [ { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, @@ -38,7 +38,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { ], model: "kimi-k2.5", }, - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4", variant: "medium" }, + { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" }, { providers: ["zai-coding-plan", "opencode"], model: "glm-5" }, { providers: ["opencode"], model: "big-pickle" }, ], @@ -47,27 +47,27 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { hephaestus: { fallbackChain: [ { - providers: ["openai", "github-copilot", "venice", "opencode"], + providers: ["openai", "github-copilot", "venice", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }, ], - requiresProvider: ["openai", "github-copilot", "venice", "opencode"], + requiresProvider: ["openai", "github-copilot", "venice", "opencode", "vercel"], }, oracle: { fallbackChain: [ { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "high", }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, @@ -78,7 +78,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { fallbackChain: [ { providers: ["opencode-go"], model: "minimax-m2.7" }, { providers: ["opencode"], model: "minimax-m2.7-highspeed" }, - { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" }, + { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" }, { providers: ["opencode"], model: "gpt-5-nano" }, ], }, @@ -87,33 +87,33 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["github-copilot", "xai"], model: "grok-code-fast-1" }, { providers: ["opencode-go"], model: "minimax-m2.7-highspeed" }, { providers: ["opencode"], model: "minimax-m2.7" }, - { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" }, + { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" }, { providers: ["opencode"], model: "gpt-5-nano" }, ], }, "multimodal-looker": { fallbackChain: [ - { providers: ["openai", "opencode"], model: "gpt-5.4", variant: "medium" }, + { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" }, { providers: ["opencode-go"], model: "kimi-k2.5" }, { providers: ["zai-coding-plan"], model: "glm-4.6v" }, - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5-nano" }, + { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5-nano" }, ], }, prometheus: { fallbackChain: [ { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "high", }, { providers: ["opencode-go"], model: "glm-5" }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", }, ], @@ -121,12 +121,12 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { metis: { fallbackChain: [ { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "high", }, @@ -137,17 +137,17 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { momus: { fallbackChain: [ { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "xhigh", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, @@ -156,10 +156,10 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { }, atlas: { fallbackChain: [ - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" }, + { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" }, { providers: ["opencode-go"], model: "kimi-k2.5" }, { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }, @@ -168,10 +168,10 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { }, "sisyphus-junior": { fallbackChain: [ - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" }, + { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" }, { providers: ["opencode-go"], model: "kimi-k2.5" }, { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }, @@ -185,13 +185,13 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { "visual-engineering": { fallbackChain: [ { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, { providers: ["zai-coding-plan", "opencode"], model: "glm-5" }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, @@ -202,17 +202,17 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { ultrabrain: { fallbackChain: [ { - providers: ["openai", "opencode"], + providers: ["openai", "opencode", "vercel"], model: "gpt-5.4", variant: "xhigh", }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, @@ -222,17 +222,17 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { deep: { fallbackChain: [ { - providers: ["openai", "github-copilot", "venice", "opencode"], + providers: ["openai", "github-copilot", "venice", "opencode", "vercel"], model: "gpt-5.4", variant: "medium", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, @@ -241,31 +241,31 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { artistry: { fallbackChain: [ { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3.1-pro", variant: "high", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4" }, + { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4" }, ], requiresModel: "gemini-3.1-pro", }, quick: { fallbackChain: [ { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4-mini", }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-haiku-4-5", }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3-flash", }, { providers: ["opencode-go"], model: "minimax-m2.7" }, @@ -275,17 +275,17 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { "unspecified-low": { fallbackChain: [ { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6", }, { - providers: ["openai", "opencode"], + providers: ["openai", "opencode", "vercel"], model: "gpt-5.3-codex", variant: "medium", }, { providers: ["opencode-go"], model: "kimi-k2.5" }, { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3-flash", }, { providers: ["opencode-go"], model: "minimax-m2.7" }, @@ -294,12 +294,12 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { "unspecified-high": { fallbackChain: [ { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-opus-4-6", variant: "max", }, { - providers: ["openai", "github-copilot", "opencode"], + providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "high", }, @@ -323,12 +323,12 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { writing: { fallbackChain: [ { - providers: ["google", "github-copilot", "opencode"], + providers: ["google", "github-copilot", "opencode", "vercel"], model: "gemini-3-flash", }, { providers: ["opencode-go"], model: "kimi-k2.5" }, { - providers: ["anthropic", "github-copilot", "opencode"], + providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6", }, { providers: ["opencode-go"], model: "minimax-m2.7" }, diff --git a/src/shared/provider-model-id-transform.ts b/src/shared/provider-model-id-transform.ts index 38fdf869d..60676e962 100644 --- a/src/shared/provider-model-id-transform.ts +++ b/src/shared/provider-model-id-transform.ts @@ -1,4 +1,25 @@ +function inferSubProvider(model: string): string | undefined { + if (model.startsWith("claude-")) return "anthropic" + if (model.startsWith("gpt-")) return "openai" + if (model.startsWith("gemini-")) return "google" + if (model.startsWith("grok-")) return "xai" + return undefined +} + export function transformModelForProvider(provider: string, model: string): string { + if (provider === "vercel") { + const slashIndex = model.indexOf("/") + if (slashIndex !== -1) { + const subProvider = model.substring(0, slashIndex) + const subModel = model.substring(slashIndex + 1) + return `${subProvider}/${transformModelForProvider(subProvider, subModel)}` + } + const subProvider = inferSubProvider(model) + if (subProvider) { + return `${subProvider}/${transformModelForProvider(subProvider, model)}` + } + return model + } if (provider === "github-copilot") { return model .replace("claude-opus-4-6", "claude-opus-4.6")