mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-01 00:36:36 +00:00
fix(anthropic): stop migrating current claude-haiku-4-5 to sonnet (#87719)
Summary: - The branch preserves current Claude Haiku 4.5 refs in the Anthropic resolver and doctor migration, repoints the bare `haiku` family alias to `claude-haiku-4-5`, and updates regression tests. - PR surface: Source +5, Tests +21. Total +26 across 4 files. - Reproducibility: yes. Current main source maps the bare `haiku` alias and explicit Haiku 4.5 migration path ... de-sonnet-4-6`; the PR body also supplies before/after terminal proof for the resolver and migration tests. Automerge notes: - No ClawSweeper repair was needed after automerge opt-in. Validation: - ClawSweeper review passed for head64429e23b3. - Required merge gates passed before the squash merge. Prepared head SHA:64429e23b3Review: https://github.com/openclaw/openclaw/pull/87719#issuecomment-4566419633 Co-authored-by: alkor2000 <200923177@qq.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> Approved-by: takhoffman Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { CLAUDE_CLI_BACKEND_ID, CLAUDE_CLI_MODEL_ALIASES } from "./cli-constants
|
||||
const DEFAULT_CLAUDE_MODEL_BY_FAMILY: Record<string, string> = {
|
||||
opus: "claude-opus-4-7",
|
||||
sonnet: "claude-sonnet-4-6",
|
||||
haiku: "claude-sonnet-4-6",
|
||||
haiku: "claude-haiku-4-5",
|
||||
};
|
||||
|
||||
export type ClaudeCliAnthropicModelRefs = {
|
||||
@@ -117,6 +117,10 @@ function upgradeOldClaudeModelId(normalized: string): string | null {
|
||||
if (normalized.startsWith("claude-sonnet-4-6") || normalized.startsWith("claude-sonnet-4.6")) {
|
||||
return null;
|
||||
}
|
||||
// claude-haiku-4-5 is a current production model and must not be migrated.
|
||||
if (normalized.startsWith("claude-haiku-4-5") || normalized.startsWith("claude-haiku-4.5")) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
normalized === "claude-opus-4" ||
|
||||
hasAnyRetiredVersionPrefix(normalized, [
|
||||
@@ -140,8 +144,6 @@ function upgradeOldClaudeModelId(normalized: string): string | null {
|
||||
"claude-sonnet-4.1",
|
||||
"claude-sonnet-4-0",
|
||||
"claude-sonnet-4.0",
|
||||
"claude-haiku-4-5",
|
||||
"claude-haiku-4.5",
|
||||
]) ||
|
||||
/^claude-sonnet-4-20\d{6}/.test(normalized)
|
||||
) {
|
||||
@@ -172,7 +174,6 @@ function upgradeOldClaudeModelId(normalized: string): string | null {
|
||||
normalized === "sonnet-3.7" ||
|
||||
normalized === "sonnet-3.5" ||
|
||||
normalized === "sonnet-3" ||
|
||||
normalized === "haiku-4.5" ||
|
||||
normalized === "haiku-3.5" ||
|
||||
normalized === "haiku-3"
|
||||
) {
|
||||
|
||||
@@ -55,6 +55,28 @@ describe("anthropic Claude model refs", () => {
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-sonnet-4-7")).toBe(
|
||||
"anthropic/claude-sonnet-4-7",
|
||||
);
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-haiku-4-5")).toBe(
|
||||
"anthropic/claude-haiku-4-5",
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves the current claude-haiku-4-5 model and its bare alias", () => {
|
||||
// claude-haiku-4-5 is a current production model (not retired), so neither
|
||||
// its full ref, its dotted variant, nor the bare "haiku" family alias must
|
||||
// be rewritten to sonnet.
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-haiku-4-5")).toBe(
|
||||
"anthropic/claude-haiku-4-5",
|
||||
);
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-haiku-4.5")).toBe(
|
||||
"anthropic/claude-haiku-4.5",
|
||||
);
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-haiku-4-5@anthropic:work")).toBe(
|
||||
"anthropic/claude-haiku-4-5@anthropic:work",
|
||||
);
|
||||
// Genuinely retired Claude 3 Haiku still upgrades to the current sonnet.
|
||||
expect(resolveKnownAnthropicModelRef("anthropic/claude-3-5-haiku-20241022")).toBe(
|
||||
"anthropic/claude-sonnet-4-6",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1707,7 +1707,7 @@ describe("legacy model compat migrate", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.config?.agents?.defaults?.imageModel).toBe("anthropic/claude-sonnet-4-6");
|
||||
expect(res.config?.agents?.defaults?.imageModel).toBe("anthropic/claude-haiku-4-5");
|
||||
expect(res.config?.agents?.defaults?.imageGenerationModel).toEqual({
|
||||
primary: "github-copilot/claude-sonnet-4.6",
|
||||
fallbacks: ["github-copilot/gpt-5.4-mini"],
|
||||
@@ -1751,6 +1751,7 @@ describe("legacy model compat migrate", () => {
|
||||
});
|
||||
expect(res.config?.agents?.defaults?.workspace).toBe("/tmp/claude-3-sonnet");
|
||||
expect(res.config?.agents?.defaults?.models).toEqual({
|
||||
"anthropic/claude-haiku-4-5": { alias: "haiku" },
|
||||
"anthropic/claude-sonnet-4-6": { alias: "current-sonnet" },
|
||||
"github-copilot/claude-opus-4.7": { alias: "copilot-opus" },
|
||||
"openai/gpt-5.5-pro": { alias: "old-pro" },
|
||||
@@ -1770,10 +1771,9 @@ describe("legacy model compat migrate", () => {
|
||||
subagent?: { allowedModels?: string[] };
|
||||
}
|
||||
)?.subagent?.allowedModels,
|
||||
).toEqual(["anthropic/claude-sonnet-4-6", "*"]);
|
||||
).toEqual(["anthropic/claude-haiku-4-5", "*"]);
|
||||
expect(res.config?.channels?.modelByChannel?.telegram?.["*"]).toBe("anthropic/claude-opus-4-7");
|
||||
expectMigrationChangesToIncludeFragments(res.changes, [
|
||||
'config.agents.defaults.imageModel from "anthropic/claude-haiku-4-5" to "anthropic/claude-sonnet-4-6"',
|
||||
'config.agents.defaults.imageGenerationModel.primary from "github-copilot/claude-sonnet-4" to "github-copilot/claude-sonnet-4.6"',
|
||||
'config.agents.defaults.imageGenerationModel.fallbacks.0 from "github-copilot/grok-code-fast-1" to "github-copilot/gpt-5.4-mini"',
|
||||
'config.agents.defaults.musicGenerationModel from "vercel-ai-gateway/anthropic/claude-opus-4-5" to "vercel-ai-gateway/anthropic/claude-opus-4-6"',
|
||||
@@ -1800,7 +1800,6 @@ describe("legacy model compat migrate", () => {
|
||||
'config.agents.defaults.models key from "openai/gpt-5.2-pro" to "openai/gpt-5.5-pro"',
|
||||
'config.agents.defaults.models key from "github-copilot/gpt-5-mini" to "github-copilot/gpt-5.4-mini"',
|
||||
'config.plugins.entries.lossless-claw.config.summaryModel from "anthropic/claude-3-5-sonnet" to "anthropic/claude-sonnet-4-6"',
|
||||
'config.plugins.entries.lossless-claw.subagent.allowedModels.0 from "anthropic/claude-haiku-4-5" to "anthropic/claude-sonnet-4-6"',
|
||||
'config.channels.modelByChannel.telegram.* from "anthropic/claude-opus-4-5" to "anthropic/claude-opus-4-7"',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -635,6 +635,13 @@ function upgradeOldClaudeToken(
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
// claude-haiku-4-5 is a current production model and must not be migrated.
|
||||
if (
|
||||
normalized.startsWith("claude-haiku-4-5") ||
|
||||
normalized.startsWith("claude-haiku-4.5")
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
normalized === "claude-opus-4" ||
|
||||
hasAnyRetiredVersionPrefix(normalized, [
|
||||
@@ -658,8 +665,6 @@ function upgradeOldClaudeToken(
|
||||
"claude-sonnet-4.1",
|
||||
"claude-sonnet-4-0",
|
||||
"claude-sonnet-4.0",
|
||||
"claude-haiku-4-5",
|
||||
"claude-haiku-4.5",
|
||||
]) ||
|
||||
/^claude-sonnet-4-20\d{6}/.test(normalized)
|
||||
) {
|
||||
@@ -714,7 +719,6 @@ function upgradeOldClaudeToken(
|
||||
normalized === "sonnet-3.7" ||
|
||||
normalized === "sonnet-3.5" ||
|
||||
normalized === "sonnet-3" ||
|
||||
normalized === "haiku-4.5" ||
|
||||
normalized === "haiku-3.5" ||
|
||||
normalized === "haiku-3"
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user