From ef3f3f9c08c8c3c26a7d251295dad2f139300fb1 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Fri, 13 Mar 2026 03:08:14 -0700 Subject: [PATCH] fix: normalize dot-versioned model names for Anthropic API anthropic/claude-opus-4.6 (OpenRouter format) was being sent as claude-opus-4.6 to the Anthropic API, which expects claude-opus-4-6 (hyphens, not dots). normalize_model_name() now converts dots to hyphens after stripping the provider prefix, matching Anthropic's naming convention. Fixes 404: 'model: claude-opus-4.6 was not found' --- agent/anthropic_adapter.py | 5 +++++ tests/test_anthropic_adapter.py | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/agent/anthropic_adapter.py b/agent/anthropic_adapter.py index 1e6a2a240..2678e85bb 100644 --- a/agent/anthropic_adapter.py +++ b/agent/anthropic_adapter.py @@ -328,10 +328,15 @@ def normalize_model_name(model: str) -> str: """Normalize a model name for the Anthropic API. - Strips 'anthropic/' prefix (OpenRouter format, case-insensitive) + - Converts dots to hyphens in version numbers (OpenRouter uses dots, + Anthropic uses hyphens: claude-opus-4.6 → claude-opus-4-6) """ lower = model.lower() if lower.startswith("anthropic/"): model = model[len("anthropic/"):] + # OpenRouter uses dots for version separators (claude-opus-4.6), + # Anthropic uses hyphens (claude-opus-4-6). Convert dots to hyphens. + model = model.replace(".", "-") return model diff --git a/tests/test_anthropic_adapter.py b/tests/test_anthropic_adapter.py index 1f4006d51..cc563f105 100644 --- a/tests/test_anthropic_adapter.py +++ b/tests/test_anthropic_adapter.py @@ -351,6 +351,17 @@ class TestNormalizeModelName: def test_leaves_bare_name(self): assert normalize_model_name("claude-sonnet-4-20250514") == "claude-sonnet-4-20250514" + def test_converts_dots_to_hyphens(self): + """OpenRouter uses dots (4.6), Anthropic uses hyphens (4-6).""" + assert normalize_model_name("anthropic/claude-opus-4.6") == "claude-opus-4-6" + assert normalize_model_name("anthropic/claude-sonnet-4.5") == "claude-sonnet-4-5" + assert normalize_model_name("claude-opus-4.6") == "claude-opus-4-6" + + def test_already_hyphenated_unchanged(self): + """Names already in Anthropic format should pass through.""" + assert normalize_model_name("claude-opus-4-6") == "claude-opus-4-6" + assert normalize_model_name("claude-opus-4-5-20251101") == "claude-opus-4-5-20251101" + # --------------------------------------------------------------------------- # Tool conversion