From 4ce1dde32d5106259466fe5304101adc40b0fcf1 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Mon, 13 Apr 2026 21:31:00 +0900 Subject: [PATCH] CLI: isolate provider model id transforms from shared mocks --- src/cli/provider-model-id-transform.test.ts | 678 ++++++++++---------- src/cli/provider-model-id-transform.ts | 62 +- 2 files changed, 406 insertions(+), 334 deletions(-) diff --git a/src/cli/provider-model-id-transform.test.ts b/src/cli/provider-model-id-transform.test.ts index e87fc12ff..d745ff097 100644 --- a/src/cli/provider-model-id-transform.test.ts +++ b/src/cli/provider-model-id-transform.test.ts @@ -1,339 +1,351 @@ import { describe, expect, test } from "bun:test" import { transformModelForProvider } from "./provider-model-id-transform" +import { transformModelForProvider as transformSharedModelForProvider } from "../shared/provider-model-id-transform" describe("transformModelForProvider", () => { - describe("github-copilot provider", () => { - test("transforms claude-opus-4-6 to claude-opus-4.6", () => { - // #given github-copilot provider and claude-opus-4-6 model - const provider = "github-copilot" - const model = "claude-opus-4-6" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-opus-4.6 - expect(result).toBe("claude-opus-4.6") - }) - - test("transforms claude-sonnet-4-5 to claude-sonnet-4.5", () => { - // #given github-copilot provider and claude-sonnet-4-5 model - const provider = "github-copilot" - const model = "claude-sonnet-4-5" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-sonnet-4.5 - expect(result).toBe("claude-sonnet-4.5") - }) - - test("transforms claude-haiku-4-5 to claude-haiku-4.5", () => { - // #given github-copilot provider and claude-haiku-4-5 model - const provider = "github-copilot" - const model = "claude-haiku-4-5" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-haiku-4.5 - expect(result).toBe("claude-haiku-4.5") - }) - - test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { - // #given github-copilot provider and gemini-3.1-pro model - const provider = "github-copilot" - const model = "gemini-3.1-pro" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to gemini-3.1-pro-preview - expect(result).toBe("gemini-3.1-pro-preview") - }) - - test("transforms gemini-3-flash to gemini-3-flash-preview", () => { - // #given github-copilot provider and gemini-3-flash model - const provider = "github-copilot" - const model = "gemini-3-flash" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to gemini-3-flash-preview - expect(result).toBe("gemini-3-flash-preview") - }) - - test("prevents double transformation of gemini-3.1-pro-preview", () => { - // #given github-copilot provider and gemini-3.1-pro-preview model (already transformed) - const provider = "github-copilot" - const model = "gemini-3.1-pro-preview" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should NOT become gemini-3.1-pro-preview-preview - expect(result).toBe("gemini-3.1-pro-preview") - }) - - test("prevents double transformation of gemini-3-flash-preview", () => { - // #given github-copilot provider and gemini-3-flash-preview model (already transformed) - const provider = "github-copilot" - const model = "gemini-3-flash-preview" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should NOT become gemini-3-flash-preview-preview - expect(result).toBe("gemini-3-flash-preview") - }) - }) - - describe("google provider", () => { - test("transforms gemini-3-flash to gemini-3-flash-preview", () => { - // #given google provider and gemini-3-flash model - const provider = "google" - const model = "gemini-3-flash" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to gemini-3-flash-preview - expect(result).toBe("gemini-3-flash-preview") - }) - - test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { - // #given google provider and gemini-3.1-pro model - const provider = "google" - const model = "gemini-3.1-pro" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to gemini-3.1-pro-preview - expect(result).toBe("gemini-3.1-pro-preview") - }) - - test("passes through other gemini models unchanged", () => { - // #given google provider and gemini-2.5-flash model - const provider = "google" - const model = "gemini-2.5-flash" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should pass through unchanged - expect(result).toBe("gemini-2.5-flash") - }) - - test("prevents double transformation of gemini-3-flash-preview", () => { - // #given google provider and gemini-3-flash-preview model (already transformed) - const provider = "google" - const model = "gemini-3-flash-preview" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should NOT become gemini-3-flash-preview-preview - expect(result).toBe("gemini-3-flash-preview") - }) - - test("prevents double transformation of gemini-3.1-pro-preview", () => { - // #given google provider and gemini-3.1-pro-preview model (already transformed) - const provider = "google" - const model = "gemini-3.1-pro-preview" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should NOT become gemini-3.1-pro-preview-preview - expect(result).toBe("gemini-3.1-pro-preview") - }) - - test("does not transform claude models for google provider", () => { - // #given google provider and claude-opus-4-6 model - const provider = "google" - const model = "claude-opus-4-6" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should pass through unchanged (google doesn't use claude) - expect(result).toBe("claude-opus-4-6") - }) - }) - - describe("anthropic provider", () => { - test("transforms claude-opus-4-6 to claude-opus-4.6", () => { - // #given anthropic provider and claude-opus-4-6 model - const provider = "anthropic" - const model = "claude-opus-4-6" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-opus-4.6 - expect(result).toBe("claude-opus-4.6") - }) - - test("transforms claude-sonnet-4-6 to claude-sonnet-4.6", () => { - // #given anthropic provider and claude-sonnet-4-6 model - const provider = "anthropic" - const model = "claude-sonnet-4-6" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-sonnet-4.6 - expect(result).toBe("claude-sonnet-4.6") - }) - - test("transforms claude-haiku-4-5 to claude-haiku-4.5", () => { - // #given anthropic provider and claude-haiku-4-5 model - const provider = "anthropic" - const model = "claude-haiku-4-5" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should transform to claude-haiku-4.5 - expect(result).toBe("claude-haiku-4.5") - }) - }) - - describe("vercel provider", () => { - test("prepends anthropic/ and applies anthropic transform for claude models", () => { - // #given vercel provider and claude-opus-4-6 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "claude-opus-4-6") - - // #then should produce anthropic/claude-opus-4.6 - expect(result).toBe("anthropic/claude-opus-4.6") - }) - - test("prepends anthropic/ and applies anthropic transform for claude-sonnet", () => { - // #given vercel provider and claude-sonnet-4-6 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "claude-sonnet-4-6") - - // #then should produce anthropic/claude-sonnet-4.6 - expect(result).toBe("anthropic/claude-sonnet-4.6") - }) - - test("prepends anthropic/ and applies anthropic transform for claude-haiku", () => { - // #given vercel provider and claude-haiku-4-5 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "claude-haiku-4-5") - - // #then should produce anthropic/claude-haiku-4.5 - expect(result).toBe("anthropic/claude-haiku-4.5") - }) - - test("prepends openai/ for gpt models", () => { - // #given vercel provider and gpt-5.4 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "gpt-5.4") - - // #then should produce openai/gpt-5.4 - expect(result).toBe("openai/gpt-5.4") - }) - - test("prepends google/ and applies google transform for gemini models", () => { - // #given vercel provider and gemini-3.1-pro model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "gemini-3.1-pro") - - // #then should produce google/gemini-3.1-pro-preview - expect(result).toBe("google/gemini-3.1-pro-preview") - }) - - test("prepends google/ without -preview for gemini-3-flash", () => { - // #given vercel provider and gemini-3-flash model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "gemini-3-flash") - - // #then should produce google/gemini-3-flash (gateway does not use -preview for this model) - expect(result).toBe("google/gemini-3-flash") - }) - - test("prepends xai/ for grok models", () => { - // #given vercel provider and grok-code-fast-1 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "grok-code-fast-1") - - // #then should produce xai/grok-code-fast-1 - expect(result).toBe("xai/grok-code-fast-1") - }) - - test("delegates to sub-provider when model already has sub-provider prefix", () => { - // #given vercel provider and anthropic/claude-opus-4-6 (already prefixed) - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "anthropic/claude-opus-4-6") - - // #then should apply anthropic transform within the prefix - expect(result).toBe("anthropic/claude-opus-4.6") - }) - - test("prepends minimax/ for minimax models", () => { - // #given vercel provider and minimax-m2.7 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "minimax-m2.7") - - // #then should produce minimax/minimax-m2.7 - expect(result).toBe("minimax/minimax-m2.7") - }) - - test("prepends moonshotai/ for kimi models", () => { - // #given vercel provider and kimi-k2.5 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "kimi-k2.5") - - // #then should produce moonshotai/kimi-k2.5 - expect(result).toBe("moonshotai/kimi-k2.5") - }) - - test("prepends zai/ for glm models", () => { - // #given vercel provider and glm-5 model - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "glm-5") - - // #then should produce zai/glm-5 - expect(result).toBe("zai/glm-5") - }) - - test("passes through unknown models without sub-provider prefix", () => { - // #given vercel provider and an unknown model name - // #when transformModelForProvider is called - const result = transformModelForProvider("vercel", "big-pickle") - - // #then should pass through unchanged - expect(result).toBe("big-pickle") - }) - }) - - describe("unknown provider", () => { - test("passes model through unchanged for unknown provider", () => { - // #given unknown provider and any model - const provider = "unknown-provider" - const model = "some-model" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should pass through unchanged - expect(result).toBe("some-model") - }) - - test("passes gemini-3-flash through unchanged for unknown provider", () => { - // #given unknown provider and gemini-3-flash model - const provider = "unknown-provider" - const model = "gemini-3-flash" - - // #when transformModelForProvider is called - const result = transformModelForProvider(provider, model) - - // #then should pass through unchanged (no transformation for unknown provider) - expect(result).toBe("gemini-3-flash") - }) - }) + describe("github-copilot provider", () => { + test("transforms claude-opus-4-6 to claude-opus-4.6", () => { + // #given github-copilot provider and claude-opus-4-6 model + const provider = "github-copilot" + const model = "claude-opus-4-6" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-opus-4.6 + expect(result).toBe("claude-opus-4.6") + }) + + test("transforms claude-sonnet-4-5 to claude-sonnet-4.5", () => { + // #given github-copilot provider and claude-sonnet-4-5 model + const provider = "github-copilot" + const model = "claude-sonnet-4-5" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-sonnet-4.5 + expect(result).toBe("claude-sonnet-4.5") + }) + + test("transforms claude-haiku-4-5 to claude-haiku-4.5", () => { + // #given github-copilot provider and claude-haiku-4-5 model + const provider = "github-copilot" + const model = "claude-haiku-4-5" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-haiku-4.5 + expect(result).toBe("claude-haiku-4.5") + }) + + test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { + // #given github-copilot provider and gemini-3.1-pro model + const provider = "github-copilot" + const model = "gemini-3.1-pro" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to gemini-3.1-pro-preview + expect(result).toBe("gemini-3.1-pro-preview") + }) + + test("transforms gemini-3-flash to gemini-3-flash-preview", () => { + // #given github-copilot provider and gemini-3-flash model + const provider = "github-copilot" + const model = "gemini-3-flash" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to gemini-3-flash-preview + expect(result).toBe("gemini-3-flash-preview") + }) + + test("prevents double transformation of gemini-3.1-pro-preview", () => { + // #given github-copilot provider and gemini-3.1-pro-preview model (already transformed) + const provider = "github-copilot" + const model = "gemini-3.1-pro-preview" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should NOT become gemini-3.1-pro-preview-preview + expect(result).toBe("gemini-3.1-pro-preview") + }) + + test("prevents double transformation of gemini-3-flash-preview", () => { + // #given github-copilot provider and gemini-3-flash-preview model (already transformed) + const provider = "github-copilot" + const model = "gemini-3-flash-preview" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should NOT become gemini-3-flash-preview-preview + expect(result).toBe("gemini-3-flash-preview") + }) + }) + + describe("google provider", () => { + test("transforms gemini-3-flash to gemini-3-flash-preview", () => { + // #given google provider and gemini-3-flash model + const provider = "google" + const model = "gemini-3-flash" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to gemini-3-flash-preview + expect(result).toBe("gemini-3-flash-preview") + }) + + test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { + // #given google provider and gemini-3.1-pro model + const provider = "google" + const model = "gemini-3.1-pro" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to gemini-3.1-pro-preview + expect(result).toBe("gemini-3.1-pro-preview") + }) + + test("passes through other gemini models unchanged", () => { + // #given google provider and gemini-2.5-flash model + const provider = "google" + const model = "gemini-2.5-flash" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should pass through unchanged + expect(result).toBe("gemini-2.5-flash") + }) + + test("prevents double transformation of gemini-3-flash-preview", () => { + // #given google provider and gemini-3-flash-preview model (already transformed) + const provider = "google" + const model = "gemini-3-flash-preview" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should NOT become gemini-3-flash-preview-preview + expect(result).toBe("gemini-3-flash-preview") + }) + + test("prevents double transformation of gemini-3.1-pro-preview", () => { + // #given google provider and gemini-3.1-pro-preview model (already transformed) + const provider = "google" + const model = "gemini-3.1-pro-preview" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should NOT become gemini-3.1-pro-preview-preview + expect(result).toBe("gemini-3.1-pro-preview") + }) + + test("does not transform claude models for google provider", () => { + // #given google provider and claude-opus-4-6 model + const provider = "google" + const model = "claude-opus-4-6" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should pass through unchanged (google doesn't use claude) + expect(result).toBe("claude-opus-4-6") + }) + }) + + describe("anthropic provider", () => { + test("transforms claude-opus-4-6 to claude-opus-4.6", () => { + // #given anthropic provider and claude-opus-4-6 model + const provider = "anthropic" + const model = "claude-opus-4-6" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-opus-4.6 + expect(result).toBe("claude-opus-4.6") + }) + + test("transforms claude-sonnet-4-6 to claude-sonnet-4.6", () => { + // #given anthropic provider and claude-sonnet-4-6 model + const provider = "anthropic" + const model = "claude-sonnet-4-6" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-sonnet-4.6 + expect(result).toBe("claude-sonnet-4.6") + }) + + test("transforms claude-haiku-4-5 to claude-haiku-4.5", () => { + // #given anthropic provider and claude-haiku-4-5 model + const provider = "anthropic" + const model = "claude-haiku-4-5" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should transform to claude-haiku-4.5 + expect(result).toBe("claude-haiku-4.5") + }) + }) + + describe("vercel provider", () => { + test("prepends anthropic/ and applies anthropic transform for claude models", () => { + // #given vercel provider and claude-opus-4-6 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "claude-opus-4-6") + + // #then should produce anthropic/claude-opus-4.6 + expect(result).toBe("anthropic/claude-opus-4.6") + }) + + test("prepends anthropic/ and applies anthropic transform for claude-sonnet", () => { + // #given vercel provider and claude-sonnet-4-6 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "claude-sonnet-4-6") + + // #then should produce anthropic/claude-sonnet-4.6 + expect(result).toBe("anthropic/claude-sonnet-4.6") + }) + + test("prepends anthropic/ and applies anthropic transform for claude-haiku", () => { + // #given vercel provider and claude-haiku-4-5 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "claude-haiku-4-5") + + // #then should produce anthropic/claude-haiku-4.5 + expect(result).toBe("anthropic/claude-haiku-4.5") + }) + + test("prepends openai/ for gpt models", () => { + // #given vercel provider and gpt-5.4 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "gpt-5.4") + + // #then should produce openai/gpt-5.4 + expect(result).toBe("openai/gpt-5.4") + }) + + test("prepends google/ and applies google transform for gemini models", () => { + // #given vercel provider and gemini-3.1-pro model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "gemini-3.1-pro") + + // #then should produce google/gemini-3.1-pro-preview + expect(result).toBe("google/gemini-3.1-pro-preview") + }) + + test("prepends google/ without -preview for gemini-3-flash", () => { + // #given vercel provider and gemini-3-flash model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "gemini-3-flash") + + // #then should produce google/gemini-3-flash (gateway does not use -preview for this model) + expect(result).toBe("google/gemini-3-flash") + }) + + test("prepends xai/ for grok models", () => { + // #given vercel provider and grok-code-fast-1 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "grok-code-fast-1") + + // #then should produce xai/grok-code-fast-1 + expect(result).toBe("xai/grok-code-fast-1") + }) + + test("delegates to sub-provider when model already has sub-provider prefix", () => { + // #given vercel provider and anthropic/claude-opus-4-6 (already prefixed) + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "anthropic/claude-opus-4-6") + + // #then should apply anthropic transform within the prefix + expect(result).toBe("anthropic/claude-opus-4.6") + }) + + test("prepends minimax/ for minimax models", () => { + // #given vercel provider and minimax-m2.7 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "minimax-m2.7") + + // #then should produce minimax/minimax-m2.7 + expect(result).toBe("minimax/minimax-m2.7") + }) + + test("prepends moonshotai/ for kimi models", () => { + // #given vercel provider and kimi-k2.5 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "kimi-k2.5") + + // #then should produce moonshotai/kimi-k2.5 + expect(result).toBe("moonshotai/kimi-k2.5") + }) + + test("prepends zai/ for glm models", () => { + // #given vercel provider and glm-5 model + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "glm-5") + + // #then should produce zai/glm-5 + expect(result).toBe("zai/glm-5") + }) + + test("passes through unknown models without sub-provider prefix", () => { + // #given vercel provider and an unknown model name + // #when transformModelForProvider is called + const result = transformModelForProvider("vercel", "big-pickle") + + // #then should pass through unchanged + expect(result).toBe("big-pickle") + }) + }) + + describe("unknown provider", () => { + test("passes model through unchanged for unknown provider", () => { + // #given unknown provider and any model + const provider = "unknown-provider" + const model = "some-model" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should pass through unchanged + expect(result).toBe("some-model") + }) + + test("passes gemini-3-flash through unchanged for unknown provider", () => { + // #given unknown provider and gemini-3-flash model + const provider = "unknown-provider" + const model = "gemini-3-flash" + + // #when transformModelForProvider is called + const result = transformModelForProvider(provider, model) + + // #then should pass through unchanged (no transformation for unknown provider) + expect(result).toBe("gemini-3-flash") + }) + }) + + test("uses a CLI-local transform implementation", () => { + // #given + const cliResult = transformModelForProvider("anthropic", "claude-opus-4-6") + const sharedResult = transformSharedModelForProvider("anthropic", "claude-opus-4-6") + + // #when + expect(transformModelForProvider).not.toBe(transformSharedModelForProvider) + expect(cliResult).toBe("claude-opus-4.6") + expect(sharedResult).toBe("claude-opus-4.6") + }) }) diff --git a/src/cli/provider-model-id-transform.ts b/src/cli/provider-model-id-transform.ts index e6cb06231..82942fe74 100644 --- a/src/cli/provider-model-id-transform.ts +++ b/src/cli/provider-model-id-transform.ts @@ -1 +1,61 @@ -export { transformModelForProvider } from "../shared/provider-model-id-transform" +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" + if (model.startsWith("minimax-")) return "minimax" + if (model.startsWith("kimi-")) return "moonshotai" + if (model.startsWith("glm-")) return "zai" + return undefined +} + +const CLAUDE_VERSION_DOT = /claude-(\w+)-(\d+)-(\d+)/g +const GEMINI_31_PRO_PREVIEW = /gemini-3\.1-pro(?!-)/g +const GEMINI_3_FLASH_PREVIEW = /gemini-3-flash(?!-)/g + +function claudeVersionDot(model: string): string { + return model.replace(CLAUDE_VERSION_DOT, "claude-$1-$2.$3") +} + +function applyGatewayTransforms(model: string): string { + return claudeVersionDot(model).replace( + GEMINI_31_PRO_PREVIEW, + "gemini-3.1-pro-preview", + ) +} + +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}/${applyGatewayTransforms(subModel)}` + } + + const subProvider = inferSubProvider(model) + if (subProvider) { + return `${subProvider}/${applyGatewayTransforms(model)}` + } + + return model + } + + if (provider === "github-copilot") { + return claudeVersionDot(model) + .replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview") + .replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview") + } + + if (provider === "google") { + return model + .replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview") + .replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview") + } + + if (provider === "anthropic") { + return claudeVersionDot(model) + } + + return model +}