From 9e5d0380b0ecb3fe923609d363240605af3dfa0c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 2 May 2026 06:39:49 +0100 Subject: [PATCH] fix: preserve legacy runtime model allowlists --- CHANGELOG.md | 1 + src/agents/model-selection.test.ts | 28 +++++++++++++++++++ .../doctor-legacy-config.migrations.test.ts | 5 ++++ .../shared/legacy-config-core-normalizers.ts | 1 + 4 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d03d696b54..888f47e92eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Agents/models: keep legacy CLI runtime model refs such as `claude-cli/*` in the configured allowlist after canonical runtime migration, so cron `payload.model` overrides keep working. Fixes #75753. Thanks @RyanSandoval. - CLI/directory: report unsupported directory operations for installed channel plugins instead of prompting to reinstall the plugin when it lacks a directory adapter. Fixes #75770. Thanks @lawong888. - Web search: keep public provider requests on the strict SSRF guard and reserve private-network access for explicit self-hosted SearXNG/Firecrawl endpoints. Fixes #74357 and supersedes #74360. Thanks @fede-kamel. - Web search/Firecrawl: allow self-hosted private/internal Firecrawl `baseUrl` endpoints, including HTTP for private targets, while keeping hosted Firecrawl on the strict official endpoint. Fixes #63877 and supersedes #59666, #63941, and #74013. Thanks @jhthompson12, @jzakirov, @Mlightsnow, and @shad0wca7. diff --git a/src/agents/model-selection.test.ts b/src/agents/model-selection.test.ts index ba172294d10..af11246986c 100644 --- a/src/agents/model-selection.test.ts +++ b/src/agents/model-selection.test.ts @@ -858,6 +858,34 @@ describe("model-selection", () => { }); }); + it("keeps legacy CLI runtime refs accepted when canonical runtime refs are also configured", () => { + const cfg = { + agents: { + defaults: { + agentRuntime: { id: "claude-cli" }, + model: { primary: "anthropic/claude-sonnet-4-6" }, + models: { + "anthropic/claude-sonnet-4-6": {}, + "claude-cli/claude-sonnet-4-6": {}, + }, + }, + }, + } as OpenClawConfig; + + const result = resolveAllowedModelRef({ + cfg, + catalog: BUNDLED_ALLOWLIST_CATALOG, + raw: "claude-cli/claude-sonnet-4-6", + defaultProvider: "anthropic", + defaultModel: "claude-sonnet-4-6", + }); + + expect(result).toEqual({ + key: "claude-cli/claude-sonnet-4-6", + ref: { provider: "claude-cli", model: "claude-sonnet-4-6" }, + }); + }); + it("strips trailing auth profile suffix before allowlist matching", () => { const cfg: OpenClawConfig = { agents: { diff --git a/src/commands/doctor-legacy-config.migrations.test.ts b/src/commands/doctor-legacy-config.migrations.test.ts index 56ee052f5f8..cd64a1348e7 100644 --- a/src/commands/doctor-legacy-config.migrations.test.ts +++ b/src/commands/doctor-legacy-config.migrations.test.ts @@ -497,7 +497,9 @@ describe("normalizeCompatibilityConfigValues", () => { fallback: "pi", }); expect(res.config.agents?.defaults?.models).toEqual({ + "codex/gpt-5.5": { alias: "legacy-codex" }, "openai/gpt-5.5": { alias: "gpt", params: { temperature: 0.2 } }, + "codex/gpt-5.4-mini": {}, "openai/gpt-5.4-mini": {}, }); expect(res.config.agents?.list?.[0]).toMatchObject({ @@ -557,6 +559,7 @@ describe("normalizeCompatibilityConfigValues", () => { }); expect(res.config.agents?.defaults?.agentRuntime).toEqual({ id: "claude-cli" }); expect(res.config.agents?.defaults?.models).toEqual({ + "claude-cli/claude-opus-4-7": { alias: "Opus" }, "anthropic/claude-opus-4-7": { alias: "Anthropic Opus" }, }); }); @@ -583,6 +586,7 @@ describe("normalizeCompatibilityConfigValues", () => { }); expect(res.config.agents?.defaults?.agentRuntime).toEqual({ id: "codex-cli" }); expect(res.config.agents?.defaults?.models).toEqual({ + "codex-cli/gpt-5.5": { alias: "Codex CLI" }, "openai/gpt-5.5": { alias: "OpenAI GPT" }, }); }); @@ -611,6 +615,7 @@ describe("normalizeCompatibilityConfigValues", () => { id: "google-gemini-cli", }); expect(res.config.agents?.defaults?.models).toEqual({ + "google-gemini-cli/gemini-3.1-pro-preview": { alias: "Gemini CLI" }, "google/gemini-3.1-pro-preview": { alias: "Gemini API" }, }); }); diff --git a/src/commands/doctor/shared/legacy-config-core-normalizers.ts b/src/commands/doctor/shared/legacy-config-core-normalizers.ts index cc4b287ed81..4e29b126697 100644 --- a/src/commands/doctor/shared/legacy-config-core-normalizers.ts +++ b/src/commands/doctor/shared/legacy-config-core-normalizers.ts @@ -262,6 +262,7 @@ function normalizeLegacyRuntimeAllowlistModels( const migrated = migrateLegacyRuntimeModelRef(rawKey); if (migrated?.runtime === selectedRuntime) { changed = true; + next[rawKey] = mergeModelEntry(entry, next[rawKey]); legacyEntries.push([migrated.ref, entry]); continue; }