diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f050e2fc899..36de90626b94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai - Docker: prune package-excluded plugin source workspaces and dependency closures so runtime images do not keep packages for plugins that were not opted in. - Providers/Ollama: treat Docker/OrbStack host aliases as local Ollama endpoints so `ollama-local` marker auth works when OpenClaw runs inside a VM/container and Ollama runs on the host. Fixes #84875. - QA-Lab: keep explicitly searchable/deferred OpenClaw dynamic tool rows report-only by default so tool-coverage gates do not treat mock discovery gaps as hard product failures. (#80319) Thanks @100yenadmin. +- Agents/config: keep non-Google provider model refs from being rewritten by Google Gemini preview-id normalization. (#84762) Thanks @zhangguiping-xydt. - Agents: cap heartbeat model bleed context hints by the stored session window when runtime model metadata is unavailable, so overflow recovery advice does not suggest a larger window than the active session actually has. - Control UI/Web Push: use `https://openclaw.ai` as the generated default VAPID subject instead of the old localhost mailbox so iOS PWA push setup uses an Apple-acceptable subject when `OPENCLAW_VAPID_SUBJECT` is unset. Fixes #83134. (#83317) Thanks @IWhatsskill. - Agents/Pi: keep embedded session transcript writes from tripping false takeover detection after packaged npm onboarding agent turns. diff --git a/src/commands/model-picker.test.ts b/src/commands/model-picker.test.ts index 437975bce4cc..21a38fbedb28 100644 --- a/src/commands/model-picker.test.ts +++ b/src/commands/model-picker.test.ts @@ -1449,6 +1449,16 @@ describe("applyModelAllowlist", () => { }); }); + it("keeps non-Google provider Gemini-looking refs unchanged while writing selected models", () => { + const config = {} as OpenClawConfig; + + const next = applyModelAllowlist(config, ["litellm/gemini-3-flash", "litellm/gemini-3.1-pro"]); + expect(next.agents?.defaults?.models).toEqual({ + "litellm/gemini-3-flash": {}, + "litellm/gemini-3.1-pro": {}, + }); + }); + it("preserves entries outside scoped allowlist updates", () => { const config = { agents: { diff --git a/src/config/model-input.ts b/src/config/model-input.ts index eac32e93252a..dbe78871a2d6 100644 --- a/src/config/model-input.ts +++ b/src/config/model-input.ts @@ -67,6 +67,8 @@ export function toAgentModelListLike(model?: AgentModelConfig): AgentModelListLi return model; } +const GOOGLE_PROVIDER_IDS = new Set(["google", "google-gemini-cli", "google-vertex"]); + export function normalizeAgentModelRefForConfig(model: string): string { const trimmed = model.trim(); const slash = trimmed.indexOf("/"); @@ -75,7 +77,11 @@ export function normalizeAgentModelRefForConfig(model: string): string { } const provider = normalizeProviderId(trimmed.slice(0, slash)); - const normalizedModel = normalizeGooglePreviewModelId(trimmed.slice(slash + 1)); + const modelSuffix = trimmed.slice(slash + 1); + const normalizedModel = + GOOGLE_PROVIDER_IDS.has(provider) || modelSuffix.startsWith("google/") + ? normalizeGooglePreviewModelId(modelSuffix) + : modelSuffix; return modelKeyForConfig(provider, normalizedModel); }