diff --git a/CHANGELOG.md b/CHANGELOG.md index 13be662eff9..bbd28d3a99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -164,6 +164,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Control UI/chat: hide retired and non-public Google Gemini model IDs from chat model catalogs and route the bare `gemini-3-pro` alias to Gemini 3.1 Pro Preview instead of the shut-down Gemini 3 Pro Preview. Thanks @BunsDev. - Gateway/watch: leave `OPENCLAW_TRACE_SYNC_IO` disabled by default in `pnpm gateway:watch:raw` so watch mode avoids noisy Node sync-I/O stack traces unless explicitly requested. - Codex app-server: close stdio stdin before force-killing the managed app-server, matching Codex single-client shutdown behavior and avoiding unsettled CLI exits after successful runs. - CLI/Codex: dispose registered agent harnesses during short-lived CLI shutdown so successful Codex-backed `agent --local` runs do not leave app-server child processes alive. diff --git a/extensions/google/manifest.test.ts b/extensions/google/manifest.test.ts new file mode 100644 index 00000000000..0d16b6d7db1 --- /dev/null +++ b/extensions/google/manifest.test.ts @@ -0,0 +1,86 @@ +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; + +type GoogleManifest = { + modelCatalog?: { + suppressions?: Array<{ + provider?: string; + model?: string; + reason?: string; + }>; + }; +}; + +const RETIRED_GEMINI_CHAT_MODELS = [ + "gemini-1.5-flash", + "gemini-1.5-flash-8b", + "gemini-1.5-pro", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-exp-image-generation", + "gemini-2.0-flash-live-001", + "gemini-2.0-flash-lite-preview", + "gemini-2.0-flash-lite-preview-02-05", + "gemini-2.0-flash-preview-image-generation", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-flash-thinking-exp-01-21", + "gemini-2.0-flash-thinking-exp-1219", + "gemini-2.0-pro-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.5-flash-exp-native-audio-thinking-dialog", + "gemini-2.5-flash-image-preview", + "gemini-2.5-flash-lite-preview-06-17", + "gemini-2.5-flash-lite-preview-09-25", + "gemini-2.5-flash-lite-preview-09-2025", + "gemini-2.5-flash-preview-04-17", + "gemini-2.5-flash-preview-05-20", + "gemini-2.5-flash-preview-09-25", + "gemini-2.5-flash-preview-09-2025", + "gemini-2.5-flash-preview-native-audio-dialog", + "gemini-2.5-pro-exp-03-25", + "gemini-2.5-pro-preview-03-25", + "gemini-2.5-pro-preview-05-06", + "gemini-2.5-pro-preview-06-05", + "gemini-3-pro-preview", + "gemini-3.1-pro-preview-customtools", + "gemini-live-2.5-flash", + "gemini-live-2.5-flash-preview", + "gemini-live-2.5-flash-preview-native-audio", +] as const; + +const GOOGLE_CHAT_PROVIDERS = ["google", "google-gemini-cli", "google-vertex"] as const; + +function loadManifest(): GoogleManifest { + return JSON.parse(readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8")); +} + +describe("google manifest model catalog", () => { + it("suppresses retired Gemini chat model identifiers for all Google chat providers", () => { + const manifest = loadManifest(); + const suppressionRefs = new Set( + (manifest.modelCatalog?.suppressions ?? []).map( + (suppression) => `${suppression.provider}/${suppression.model}`, + ), + ); + + for (const provider of GOOGLE_CHAT_PROVIDERS) { + for (const model of RETIRED_GEMINI_CHAT_MODELS) { + expect(suppressionRefs).toContain(`${provider}/${model}`); + } + } + }); + + it("does not suppress still-callable Google replacement models", () => { + const manifest = loadManifest(); + const suppressionRefs = new Set( + (manifest.modelCatalog?.suppressions ?? []).map( + (suppression) => `${suppression.provider}/${suppression.model}`, + ), + ); + + expect(suppressionRefs).not.toContain("google/gemini-2.0-flash"); + expect(suppressionRefs).not.toContain("google/gemini-2.5-flash"); + expect(suppressionRefs).not.toContain("google/gemini-2.5-flash-lite"); + expect(suppressionRefs).not.toContain("google/gemini-2.5-pro"); + expect(suppressionRefs).not.toContain("google/gemini-3.1-pro-preview"); + }); +}); diff --git a/extensions/google/media-understanding-provider.video.test.ts b/extensions/google/media-understanding-provider.video.test.ts index 27d641e5c1c..12a0a634f24 100644 --- a/extensions/google/media-understanding-provider.video.test.ts +++ b/extensions/google/media-understanding-provider.video.test.ts @@ -86,10 +86,10 @@ describe("describeGeminiVideo", () => { }); const { url: seenUrl, init: seenInit } = getRequest(); - expect(result.model).toBe("gemini-3-pro-preview"); + expect(result.model).toBe("gemini-3.1-pro-preview"); expect(result.text).toBe("first\nsecond"); expect(seenUrl).toBe( - "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent", + "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-pro-preview:generateContent", ); expect(seenInit?.method).toBe("POST"); expect(seenInit?.signal).toBeInstanceOf(AbortSignal); diff --git a/extensions/google/model-id.test.ts b/extensions/google/model-id.test.ts index 5c4dd4d526a..dc462083e11 100644 --- a/extensions/google/model-id.test.ts +++ b/extensions/google/model-id.test.ts @@ -24,6 +24,7 @@ describe("google model id helpers", () => { }); it("keeps bare Gemini 3.1 Pro as an alias for Google's preview-suffixed API id", () => { + expect(normalizeGoogleModelId("gemini-3-pro")).toBe("gemini-3.1-pro-preview"); expect(normalizeGoogleModelId("gemini-3.1-pro")).toBe("gemini-3.1-pro-preview"); expect(normalizeGoogleModelId("gemini-3.1-pro-preview")).toBe("gemini-3.1-pro-preview"); }); diff --git a/extensions/google/model-id.ts b/extensions/google/model-id.ts index ea1380f0750..e4d0d581d78 100644 --- a/extensions/google/model-id.ts +++ b/extensions/google/model-id.ts @@ -2,7 +2,7 @@ const ANTIGRAVITY_BARE_PRO_IDS = new Set(["gemini-3-pro", "gemini-3.1-pro", "gem export function normalizeGoogleModelId(id: string): string { if (id === "gemini-3-pro") { - return "gemini-3-pro-preview"; + return "gemini-3.1-pro-preview"; } if (id === "gemini-3-flash") { return "gemini-3-flash-preview"; diff --git a/extensions/google/openclaw.plugin.json b/extensions/google/openclaw.plugin.json index f9225234b34..3289d21678d 100644 --- a/extensions/google/openclaw.plugin.json +++ b/extensions/google/openclaw.plugin.json @@ -10,7 +10,7 @@ "providers": { "google": { "aliases": { - "gemini-3-pro": "gemini-3-pro-preview", + "gemini-3-pro": "gemini-3.1-pro-preview", "gemini-3-flash": "gemini-3-flash-preview", "gemini-3.1-pro": "gemini-3.1-pro-preview", "gemini-3.1-flash-lite": "gemini-3.1-flash-lite-preview", @@ -20,7 +20,7 @@ }, "google-vertex": { "aliases": { - "gemini-3-pro": "gemini-3-pro-preview", + "gemini-3-pro": "gemini-3.1-pro-preview", "gemini-3-flash": "gemini-3-flash-preview", "gemini-3.1-pro": "gemini-3.1-pro-preview", "gemini-3.1-flash-lite": "gemini-3.1-flash-lite-preview", @@ -30,6 +30,505 @@ } } }, + "modelCatalog": { + "suppressions": [ + { + "provider": "google", + "model": "gemini-1.5-flash", + "reason": "Google shut down Gemini 1.5 Flash on 2025-09-29. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-1.5-flash-8b", + "reason": "Google shut down Gemini 1.5 Flash-8B on 2025-09-29. Use google/gemini-2.5-flash-lite." + }, + { + "provider": "google", + "model": "gemini-1.5-pro", + "reason": "Google shut down Gemini 1.5 Pro on 2025-09-29. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-exp", + "reason": "Google shut down this Gemini 2.0 experimental model. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-exp-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google/gemini-2.5-flash-image." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-live-001", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google/gemini-3.1-flash-live-preview." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-lite-preview", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google/gemini-2.5-flash-lite." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-lite-preview-02-05", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google/gemini-2.5-flash-lite." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-preview-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google/gemini-2.5-flash-image." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-thinking-exp", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-thinking-exp-01-21", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.0-flash-thinking-exp-1219", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.0-pro-exp", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.0-pro-exp-02-05", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-exp-native-audio-thinking-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google/gemini-3.1-flash-live-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-image-preview", + "reason": "Google shut down this Gemini image preview on 2026-01-15. Use google/gemini-2.5-flash-image." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-lite-preview-06-17", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2025-11-18. Use google/gemini-2.5-flash-lite." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-lite-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-lite-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-preview-04-17", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-07-15. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-preview-05-20", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-11-18. Use google/gemini-2.5-flash." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google/gemini-3-flash-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google/gemini-3-flash-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-flash-preview-native-audio-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google/gemini-3.1-flash-live-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-pro-exp-03-25", + "reason": "Google shut down this Gemini 2.5 Pro experiment. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-pro-preview-03-25", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-pro-preview-05-06", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-2.5-pro-preview-06-05", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-3-pro-preview", + "reason": "Google shut down Gemini 3 Pro Preview on 2026-03-09. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-3.1-pro-preview-customtools", + "reason": "This is not a public Google Gemini chat model ID. Use google/gemini-3.1-pro-preview." + }, + { + "provider": "google", + "model": "gemini-live-2.5-flash", + "reason": "This is not a current public Gemini chat model ID. Use google/gemini-3.1-flash-live-preview for Live API." + }, + { + "provider": "google", + "model": "gemini-live-2.5-flash-preview", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google/gemini-3.1-flash-live-preview." + }, + { + "provider": "google", + "model": "gemini-live-2.5-flash-preview-native-audio", + "reason": "Google shut down this Gemini Live preview. Use google/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-1.5-flash", + "reason": "Google shut down Gemini 1.5 Flash on 2025-09-29. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-1.5-flash-8b", + "reason": "Google shut down Gemini 1.5 Flash-8B on 2025-09-29. Use google-gemini-cli/gemini-2.5-flash-lite." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-1.5-pro", + "reason": "Google shut down Gemini 1.5 Pro on 2025-09-29. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-exp", + "reason": "Google shut down this Gemini 2.0 experimental model. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-exp-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google-gemini-cli/gemini-2.5-flash-image." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-live-001", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google-gemini-cli/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-lite-preview", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google-gemini-cli/gemini-2.5-flash-lite." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-lite-preview-02-05", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google-gemini-cli/gemini-2.5-flash-lite." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-preview-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google-gemini-cli/gemini-2.5-flash-image." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-thinking-exp", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-thinking-exp-01-21", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-flash-thinking-exp-1219", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-pro-exp", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.0-pro-exp-02-05", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-exp-native-audio-thinking-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google-gemini-cli/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-image-preview", + "reason": "Google shut down this Gemini image preview on 2026-01-15. Use google-gemini-cli/gemini-2.5-flash-image." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-lite-preview-06-17", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2025-11-18. Use google-gemini-cli/gemini-2.5-flash-lite." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-lite-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google-gemini-cli/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-lite-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google-gemini-cli/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-preview-04-17", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-07-15. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-preview-05-20", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-11-18. Use google-gemini-cli/gemini-2.5-flash." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google-gemini-cli/gemini-3-flash-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google-gemini-cli/gemini-3-flash-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-flash-preview-native-audio-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google-gemini-cli/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-pro-exp-03-25", + "reason": "Google shut down this Gemini 2.5 Pro experiment. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-pro-preview-03-25", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-pro-preview-05-06", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-2.5-pro-preview-06-05", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-3-pro-preview", + "reason": "Google shut down Gemini 3 Pro Preview on 2026-03-09. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-3.1-pro-preview-customtools", + "reason": "This is not a public Google Gemini chat model ID. Use google-gemini-cli/gemini-3.1-pro-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-live-2.5-flash", + "reason": "This is not a current public Gemini chat model ID. Use google-gemini-cli/gemini-3.1-flash-live-preview for Live API." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-live-2.5-flash-preview", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google-gemini-cli/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-gemini-cli", + "model": "gemini-live-2.5-flash-preview-native-audio", + "reason": "Google shut down this Gemini Live preview. Use google-gemini-cli/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-1.5-flash", + "reason": "Google retired Gemini 1.5 Flash. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-1.5-flash-8b", + "reason": "Google retired Gemini 1.5 Flash-8B. Use google-vertex/gemini-2.5-flash-lite." + }, + { + "provider": "google-vertex", + "model": "gemini-1.5-pro", + "reason": "Google retired Gemini 1.5 Pro. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-exp", + "reason": "Google shut down this Gemini 2.0 experimental model. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-exp-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google-vertex/gemini-2.5-flash-image." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-live-001", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google-vertex/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-lite-preview", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google-vertex/gemini-2.5-flash-lite." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-lite-preview-02-05", + "reason": "Google shut down this Gemini 2.0 Flash-Lite preview on 2025-12-09. Use google-vertex/gemini-2.5-flash-lite." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-preview-image-generation", + "reason": "Google shut down this Gemini 2.0 image preview. Use google-vertex/gemini-2.5-flash-image." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-thinking-exp", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-thinking-exp-01-21", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-flash-thinking-exp-1219", + "reason": "Google shut down this Gemini 2.0 thinking experiment. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-pro-exp", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.0-pro-exp-02-05", + "reason": "Google shut down this Gemini 2.0 Pro experiment. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-exp-native-audio-thinking-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google-vertex/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-image-preview", + "reason": "Google shut down this Gemini image preview on 2026-01-15. Use google-vertex/gemini-2.5-flash-image." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-lite-preview-06-17", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2025-11-18. Use google-vertex/gemini-2.5-flash-lite." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-lite-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google-vertex/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-lite-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash-Lite preview on 2026-03-31. Use google-vertex/gemini-3.1-flash-lite-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-preview-04-17", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-07-15. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-preview-05-20", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2025-11-18. Use google-vertex/gemini-2.5-flash." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-preview-09-25", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google-vertex/gemini-3-flash-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-preview-09-2025", + "reason": "Google shut down this Gemini 2.5 Flash preview on 2026-02-17. Use google-vertex/gemini-3-flash-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-flash-preview-native-audio-dialog", + "reason": "Google shut down this Gemini native-audio preview. Use google-vertex/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-pro-exp-03-25", + "reason": "Google shut down this Gemini 2.5 Pro experiment. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-pro-preview-03-25", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-pro-preview-05-06", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-2.5-pro-preview-06-05", + "reason": "Google shut down this Gemini 2.5 Pro preview on 2025-12-02. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-3-pro-preview", + "reason": "Google shut down Gemini 3 Pro Preview on 2026-03-09. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-3.1-pro-preview-customtools", + "reason": "This is not a public Google Gemini chat model ID. Use google-vertex/gemini-3.1-pro-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-live-2.5-flash", + "reason": "This is not a current public Gemini chat model ID. Use google-vertex/gemini-3.1-flash-live-preview for Live API." + }, + { + "provider": "google-vertex", + "model": "gemini-live-2.5-flash-preview", + "reason": "Google shut down this Gemini Live model on 2025-12-09. Use google-vertex/gemini-3.1-flash-live-preview." + }, + { + "provider": "google-vertex", + "model": "gemini-live-2.5-flash-preview-native-audio", + "reason": "Google shut down this Gemini Live preview. Use google-vertex/gemini-3.1-flash-live-preview." + } + ] + }, "modelPricing": { "providers": { "google-gemini-cli": { diff --git a/extensions/google/provider-models.test.ts b/extensions/google/provider-models.test.ts index 3bee176765d..e7189bf9c6b 100644 --- a/extensions/google/provider-models.test.ts +++ b/extensions/google/provider-models.test.ts @@ -118,6 +118,30 @@ describe("resolveGoogleGeminiForwardCompatModel", () => { }); }); + it("prefers current Gemini 3.1 Pro templates over retired Gemini 3 Pro templates", () => { + const model = resolveGoogleGeminiForwardCompatModel({ + providerId: "google-gemini-cli", + ctx: createContext({ + provider: "google-gemini-cli", + modelId: "gemini-3.1-pro-preview", + models: [ + createTemplateModel("google-gemini-cli", "gemini-3-pro-preview", { + contextWindow: 100_000, + }), + createTemplateModel("google-gemini-cli", "gemini-3.1-pro-preview", { + contextWindow: 1_048_576, + }), + ], + }), + }); + + expect(model).toMatchObject({ + provider: "google-gemini-cli", + id: "gemini-3.1-pro-preview", + contextWindow: 1_048_576, + }); + }); + it("preserves template reasoning metadata instead of forcing it on forward-compat clones", () => { const model = resolveGoogleGeminiForwardCompatModel({ providerId: "google", diff --git a/extensions/google/provider-models.ts b/extensions/google/provider-models.ts index baa9fd662ed..fff7d65a20b 100644 --- a/extensions/google/provider-models.ts +++ b/extensions/google/provider-models.ts @@ -20,7 +20,7 @@ const GEMMA_PREFIX = "gemma-"; const GEMINI_2_5_PRO_TEMPLATE_IDS = ["gemini-2.5-pro"] as const; const GEMINI_2_5_FLASH_LITE_TEMPLATE_IDS = ["gemini-2.5-flash-lite"] as const; const GEMINI_2_5_FLASH_TEMPLATE_IDS = ["gemini-2.5-flash"] as const; -const GEMINI_3_1_PRO_TEMPLATE_IDS = ["gemini-3-pro-preview"] as const; +const GEMINI_3_1_PRO_TEMPLATE_IDS = ["gemini-3.1-pro-preview", "gemini-3-pro-preview"] as const; const GEMINI_3_1_FLASH_LITE_TEMPLATE_IDS = ["gemini-3.1-flash-lite-preview"] as const; const GEMINI_3_1_FLASH_TEMPLATE_IDS = ["gemini-3-flash-preview"] as const; const GEMINI_3_PRO_ANTIGRAVITY_TEMPLATE_IDS = ["gemini-3-pro-low", "gemini-3-pro-high"] as const; diff --git a/extensions/google/provider-policy-api.test.ts b/extensions/google/provider-policy-api.test.ts index bd453334824..3554f6a3c27 100644 --- a/extensions/google/provider-policy-api.test.ts +++ b/extensions/google/provider-policy-api.test.ts @@ -25,7 +25,7 @@ describe("google provider policy public artifact", () => { }), ).toMatchObject({ baseUrl: "https://generativelanguage.googleapis.com/v1beta", - models: [{ id: "gemini-3-pro-preview" }], + models: [{ id: "gemini-3.1-pro-preview" }], }); }); diff --git a/src/commands/models/list.list-command.forward-compat.test.ts b/src/commands/models/list.list-command.forward-compat.test.ts index 3a276635562..1d981973f80 100644 --- a/src/commands/models/list.list-command.forward-compat.test.ts +++ b/src/commands/models/list.list-command.forward-compat.test.ts @@ -396,6 +396,40 @@ describe("modelsListCommand forward-compat", () => { ]); }); + it("keeps scoped provider fallback rows filtered by model suppression", async () => { + mocks.resolveConfiguredEntries.mockReturnValueOnce({ entries: [] }); + const currentModel = { + provider: "openai", + id: "gpt-5.5", + name: "GPT-5.5", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + input: ["text", "image"], + contextWindow: 1_048_576, + maxTokens: 65_536, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + }; + const suppressedModel = { + ...currentModel, + id: "gpt-5.3-codex-spark", + name: "GPT-5.3 Codex Spark", + }; + mocks.loadModelRegistry.mockResolvedValueOnce({ + models: [currentModel], + availableKeys: undefined, + registry: { + getAll: () => [currentModel, suppressedModel], + }, + }); + const runtime = createRuntime(); + + await modelsListCommand({ json: true, provider: "openai" }, runtime as never); + + expect(lastPrintedRows<{ key: string }>()).toEqual([ + expect.objectContaining({ key: "openai/gpt-5.5" }), + ]); + }); + it("uses provider static catalog rows for provider filters without --all", async () => { mocks.resolveConfiguredEntries.mockReturnValueOnce({ entries: [] }); mocks.hasProviderStaticCatalogForFilter.mockResolvedValueOnce(true); diff --git a/src/commands/models/list.row-sources.ts b/src/commands/models/list.row-sources.ts index d609803f59a..cebfff1663b 100644 --- a/src/commands/models/list.row-sources.ts +++ b/src/commands/models/list.row-sources.ts @@ -88,11 +88,10 @@ export async function appendAllModelRowSources( } await appendDiscoveredRows({ rows: params.rows, - models: params.modelRegistry.getAll(), + models: params.registryModels ?? params.modelRegistry.getAll(), modelRegistry: params.modelRegistry, context: params.context, resolveWithRegistry: false, - skipSuppression: true, }); } return { requiresRegistryFallback: false }; diff --git a/src/gateway/model-pricing-cache.test.ts b/src/gateway/model-pricing-cache.test.ts index 1334d51e178..750c4c7fc48 100644 --- a/src/gateway/model-pricing-cache.test.ts +++ b/src/gateway/model-pricing-cache.test.ts @@ -129,7 +129,7 @@ describe("model-pricing-cache", () => { expect.arrayContaining([ "openai/gpt-5.4", "anthropic/claude-sonnet-4-6", - "google/gemini-3-pro-preview", + "google/gemini-3.1-pro-preview", "anthropic/claude-opus-4-6", "xai/grok-4", "openrouter/anthropic/claude-opus-4-6", diff --git a/src/plugin-sdk/provider-model-id-normalize.test.ts b/src/plugin-sdk/provider-model-id-normalize.test.ts new file mode 100644 index 00000000000..7b7db29e8ae --- /dev/null +++ b/src/plugin-sdk/provider-model-id-normalize.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, it } from "vitest"; +import { normalizeGooglePreviewModelId } from "./provider-model-id-normalize.js"; + +describe("provider model id normalization", () => { + it("routes bare Gemini 3 Pro to the current Gemini 3.1 Pro preview", () => { + expect(normalizeGooglePreviewModelId("gemini-3-pro")).toBe("gemini-3.1-pro-preview"); + expect(normalizeGooglePreviewModelId("gemini-3.1-pro")).toBe("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 1cf29fc5ebb..7e907503ca2 100644 --- a/src/plugin-sdk/provider-model-id-normalize.ts +++ b/src/plugin-sdk/provider-model-id-normalize.ts @@ -2,7 +2,7 @@ const ANTIGRAVITY_BARE_PRO_IDS = new Set(["gemini-3-pro", "gemini-3.1-pro", "gem export function normalizeGooglePreviewModelId(id: string): string { if (id === "gemini-3-pro") { - return "gemini-3-pro-preview"; + return "gemini-3.1-pro-preview"; } if (id === "gemini-3-flash") { return "gemini-3-flash-preview";