From 7d5afcbb3f836f0ae83de602b1a603a3bb2ab82a Mon Sep 17 00:00:00 2001 From: zhang-guiping Date: Fri, 22 May 2026 01:45:57 +0800 Subject: [PATCH] fix #84745: scope Google preview model normalization to Google providers only (#84762) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: - The branch scopes config-time Google Gemini preview model normalization to Google providers or nested `google/` proxy suffixes, adds model-picker regression coverage, and adds a changelog entry. - Reproducibility: yes. by source inspection. Current main sends every provider suffix through the Google prev ... i-3-flash` deterministically becomes `litellm/gemini-3-flash-preview`; I did not run a live cron preflight. Automerge notes: - PR branch already contained follow-up commit before automerge: fix(config): scope Google preview model normalization to Google provi… - PR branch already contained follow-up commit before automerge: fix #84745: scope Google preview model normalization to Google provid… - PR branch already contained follow-up commit before automerge: fix #84745: preserve proxy Google model normalization Validation: - ClawSweeper review passed for head c59163c809542b8a89db257729cd3a87d3bb62e6. - Required merge gates passed before the squash merge. Prepared head SHA: c59163c809542b8a89db257729cd3a87d3bb62e6 Review: https://github.com/openclaw/openclaw/pull/84762#issuecomment-4504169062 Co-authored-by: zhang-guiping Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com> Co-authored-by: 张贵萍0668001030 Co-authored-by: Claude Opus 4.7 Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + src/commands/model-picker.test.ts | 10 ++++++++++ src/config/model-input.ts | 8 +++++++- 3 files changed, 18 insertions(+), 1 deletion(-) 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); }