From f9fe067f688265f904687a3c64501d8613fbe7ca Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 9 Jan 2026 05:07:16 +0000 Subject: [PATCH] fix: normalize anthropic model ids --- src/agents/claude-cli-runner.ts | 5 +++++ src/agents/model-selection.test.ts | 12 +++++++++++- src/agents/model-selection.ts | 18 ++++++++++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/agents/claude-cli-runner.ts b/src/agents/claude-cli-runner.ts index cbed8c395..7f89f0ffc 100644 --- a/src/agents/claude-cli-runner.ts +++ b/src/agents/claude-cli-runner.ts @@ -277,6 +277,11 @@ async function runClaudeCliOnce(params: { const result = await runCommandWithTimeout(["claude", ...args], { timeoutMs: params.timeoutMs, cwd: params.workspaceDir, + env: (() => { + const next = { ...process.env }; + delete next.ANTHROPIC_API_KEY; + return next; + })(), }); if (process.env.CLAWDBOT_CLAUDE_CLI_LOG_OUTPUT === "1") { const stdoutDump = result.stdout.trim(); diff --git a/src/agents/model-selection.test.ts b/src/agents/model-selection.test.ts index 6011ab4fd..4335c1ae9 100644 --- a/src/agents/model-selection.test.ts +++ b/src/agents/model-selection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import type { ClawdbotConfig } from "../config/config.js"; -import { buildAllowedModelSet, modelKey } from "./model-selection.js"; +import { buildAllowedModelSet, modelKey, parseModelRef } from "./model-selection.js"; const catalog = [ { @@ -54,3 +54,13 @@ describe("buildAllowedModelSet", () => { ).toBe(true); }); }); + +describe("parseModelRef", () => { + it("normalizes anthropic/opus-4.5 to claude-opus-4-5", () => { + const ref = parseModelRef("anthropic/opus-4.5", "anthropic"); + expect(ref).toEqual({ + provider: "anthropic", + model: "claude-opus-4-5", + }); + }); +}); diff --git a/src/agents/model-selection.ts b/src/agents/model-selection.ts index 93ce39aaa..7e0f0b411 100644 --- a/src/agents/model-selection.ts +++ b/src/agents/model-selection.ts @@ -27,6 +27,15 @@ export function normalizeProviderId(provider: string): string { return normalized; } +function normalizeAnthropicModelId(model: string): string { + const trimmed = model.trim(); + if (!trimmed) return trimmed; + const lower = trimmed.toLowerCase(); + if (lower === "opus-4.5") return "claude-opus-4-5"; + if (lower === "sonnet-4.5") return "claude-sonnet-4-5"; + return trimmed; +} + export function parseModelRef( raw: string, defaultProvider: string, @@ -35,13 +44,18 @@ export function parseModelRef( if (!trimmed) return null; const slash = trimmed.indexOf("/"); if (slash === -1) { - return { provider: normalizeProviderId(defaultProvider), model: trimmed }; + const provider = normalizeProviderId(defaultProvider); + const model = + provider === "anthropic" ? normalizeAnthropicModelId(trimmed) : trimmed; + return { provider, model }; } const providerRaw = trimmed.slice(0, slash).trim(); const provider = normalizeProviderId(providerRaw); const model = trimmed.slice(slash + 1).trim(); if (!provider || !model) return null; - return { provider, model }; + const normalizedModel = + provider === "anthropic" ? normalizeAnthropicModelId(model) : model; + return { provider, model: normalizedModel }; } export function buildModelAliasIndex(params: {