diff --git a/extensions/google/model-id.test.ts b/extensions/google/model-id.test.ts index 1a24c7ed79f..e64b947123d 100644 --- a/extensions/google/model-id.test.ts +++ b/extensions/google/model-id.test.ts @@ -30,6 +30,12 @@ describe("google model id helpers", () => { expect(normalizeGoogleModelId("gemini-3.1-pro-preview")).toBe("gemini-3.1-pro-preview"); }); + it("normalizes provider-prefixed Gemini 3 Pro config ids", () => { + expect(normalizeGoogleModelId("google/gemini-3-pro-preview")).toBe( + "google/gemini-3.1-pro-preview", + ); + }); + it("adds the preview suffix for gemini 3.1 flash-lite", () => { expect(normalizeGoogleModelId("gemini-3.1-flash-lite")).toBe("gemini-3.1-flash-lite-preview"); }); diff --git a/extensions/google/model-id.ts b/extensions/google/model-id.ts index 75f7d01d9a0..80a390d9ac1 100644 --- a/extensions/google/model-id.ts +++ b/extensions/google/model-id.ts @@ -1,6 +1,12 @@ const ANTIGRAVITY_BARE_PRO_IDS = new Set(["gemini-3-pro", "gemini-3.1-pro", "gemini-3-1-pro"]); +const GOOGLE_PROVIDER_PREFIX = "google/"; export function normalizeGoogleModelId(id: string): string { + if (id.startsWith(GOOGLE_PROVIDER_PREFIX)) { + const modelId = id.slice(GOOGLE_PROVIDER_PREFIX.length); + const normalizedModelId = normalizeGoogleModelId(modelId); + return normalizedModelId === modelId ? id : `${GOOGLE_PROVIDER_PREFIX}${normalizedModelId}`; + } if (id === "gemini-3-pro" || id === "gemini-3-pro-preview") { return "gemini-3.1-pro-preview"; } diff --git a/src/config/model-alias-defaults.test.ts b/src/config/model-alias-defaults.test.ts index 710a9558512..026bc7c2e59 100644 --- a/src/config/model-alias-defaults.test.ts +++ b/src/config/model-alias-defaults.test.ts @@ -165,6 +165,35 @@ describe("applyModelDefaults", () => { }); }); + it("normalizes provider-prefixed Gemini ids in configured Google provider rows", () => { + const cfg = { + models: { + providers: { + google: { + baseUrl: "https://generativelanguage.googleapis.com/v1beta", + api: "google-generative-ai", + apiKey: "GOOGLE_API_KEY", + models: [ + { + id: "google/gemini-3-pro-preview", + name: "Gemini 3 Pro", + input: ["text", "image"], + reasoning: true, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 1_048_576, + maxTokens: 65_536, + }, + ], + }, + }, + }, + } satisfies OpenClawConfig; + + const next = applyModelDefaults(cfg); + + expect(next.models?.providers?.google?.models?.[0]?.id).toBe("google/gemini-3.1-pro-preview"); + }); + it("fills missing model provider defaults", () => { const cfg = buildProxyProviderConfig(); diff --git a/src/plugin-sdk/provider-model-id-normalize.test.ts b/src/plugin-sdk/provider-model-id-normalize.test.ts index 062622dbc42..31106f2bed9 100644 --- a/src/plugin-sdk/provider-model-id-normalize.test.ts +++ b/src/plugin-sdk/provider-model-id-normalize.test.ts @@ -8,6 +8,12 @@ describe("provider model id normalization", () => { expect(normalizeGooglePreviewModelId("gemini-3.1-pro")).toBe("gemini-3.1-pro-preview"); }); + it("routes provider-prefixed Gemini 3 Pro to the current Gemini 3.1 Pro preview", () => { + expect(normalizeGooglePreviewModelId("google/gemini-3-pro-preview")).toBe( + "google/gemini-3.1-pro-preview", + ); + }); + it("does not rewrite already-current Gemini replacement ids", () => { expect(normalizeGooglePreviewModelId("gemini-3.1-pro-preview")).toBe("gemini-3.1-pro-preview"); expect(normalizeGooglePreviewModelId("gemini-2.5-flash")).toBe("gemini-2.5-flash"); diff --git a/src/plugin-sdk/provider-model-id-normalize.ts b/src/plugin-sdk/provider-model-id-normalize.ts index 7571916ca92..3801ecf7b58 100644 --- a/src/plugin-sdk/provider-model-id-normalize.ts +++ b/src/plugin-sdk/provider-model-id-normalize.ts @@ -1,6 +1,12 @@ const ANTIGRAVITY_BARE_PRO_IDS = new Set(["gemini-3-pro", "gemini-3.1-pro", "gemini-3-1-pro"]); +const GOOGLE_PROVIDER_PREFIX = "google/"; export function normalizeGooglePreviewModelId(id: string): string { + if (id.startsWith(GOOGLE_PROVIDER_PREFIX)) { + const modelId = id.slice(GOOGLE_PROVIDER_PREFIX.length); + const normalizedModelId = normalizeGooglePreviewModelId(modelId); + return normalizedModelId === modelId ? id : `${GOOGLE_PROVIDER_PREFIX}${normalizedModelId}`; + } if (id === "gemini-3-pro" || id === "gemini-3-pro-preview") { return "gemini-3.1-pro-preview"; }