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