diff --git a/.env.example b/.env.example index 036ce36..6acf4cd 100644 --- a/.env.example +++ b/.env.example @@ -37,7 +37,7 @@ OPENROUTER_API_KEY=your_openrouter_api_key_here # Optional: Default model to use # Options: 'auto' (Claude picks best model), 'pro', 'flash', 'o3', 'o3-mini', 'o4-mini', 'o4-mini-high', -# 'gpt-5', 'gpt-5-mini', 'grok', 'opus-4', 'sonnet-4', or any DIAL model if DIAL is configured +# 'gpt-5', 'gpt-5-mini', 'grok', 'opus-4.1', 'sonnet-4.1', or any DIAL model if DIAL is configured # When set to 'auto', Claude will select the best model for each task # Defaults to 'auto' if not specified DEFAULT_MODEL=auto @@ -87,14 +87,14 @@ DEFAULT_THINKING_MODE_THINKDEEP=high # - o4-mini-2025-04-16 (200K context, latest O4 mini) # - o3 (shorthand for o3-2025-04-16) # - o4-mini (shorthand for o4-mini-2025-04-16) -# - anthropic.claude-sonnet-4-20250514-v1:0 (200K context, Claude 4 Sonnet) -# - anthropic.claude-sonnet-4-20250514-v1:0-with-thinking (200K context, Claude 4 Sonnet with thinking mode) -# - anthropic.claude-opus-4-20250514-v1:0 (200K context, Claude 4 Opus) -# - anthropic.claude-opus-4-20250514-v1:0-with-thinking (200K context, Claude 4 Opus with thinking mode) -# - sonnet-4 (shorthand for Claude 4 Sonnet) -# - sonnet-4-thinking (shorthand for Claude 4 Sonnet with thinking) -# - opus-4 (shorthand for Claude 4 Opus) -# - opus-4-thinking (shorthand for Claude 4 Opus with thinking) +# - anthropic.claude-sonnet-4.1-20250805-v1:0 (200K context, Claude 4.1 Sonnet) +# - anthropic.claude-sonnet-4.1-20250805-v1:0-with-thinking (200K context, Claude 4.1 Sonnet with thinking mode) +# - anthropic.claude-opus-4.1-20250805-v1:0 (200K context, Claude 4.1 Opus) +# - anthropic.claude-opus-4.1-20250805-v1:0-with-thinking (200K context, Claude 4.1 Opus with thinking mode) +# - sonnet-4.1 (shorthand for Claude 4.1 Sonnet) +# - sonnet-4.1-thinking (shorthand for Claude 4.1 Sonnet with thinking) +# - opus-4.1 (shorthand for Claude 4.1 Opus) +# - opus-4.1-thinking (shorthand for Claude 4.1 Opus with thinking) # - gemini-2.5-pro-preview-03-25-google-search (1M context, with Google Search) # - gemini-2.5-pro-preview-05-06 (1M context, latest preview) # - gemini-2.5-flash-preview-05-20 (1M context, latest flash preview) @@ -110,8 +110,8 @@ DEFAULT_THINKING_MODE_THINKDEEP=high # GOOGLE_ALLOWED_MODELS=flash,pro # Allow both Gemini models # XAI_ALLOWED_MODELS=grok,grok-3-fast # Allow both GROK variants # DIAL_ALLOWED_MODELS=o3,o4-mini # Only allow O3/O4 models via DIAL -# DIAL_ALLOWED_MODELS=opus-4,sonnet-4 # Only Claude 4 models (without thinking) -# DIAL_ALLOWED_MODELS=opus-4-thinking,sonnet-4-thinking # Only Claude 4 with thinking mode +# DIAL_ALLOWED_MODELS=opus-4.1,sonnet-4.1 # Only Claude 4.1 models (without thinking) +# DIAL_ALLOWED_MODELS=opus-4.1-thinking,sonnet-4.1-thinking # Only Claude 4.1 with thinking mode # DIAL_ALLOWED_MODELS=gemini-2.5-pro,gemini-2.5-flash # Only Gemini 2.5 models via DIAL # # Note: These restrictions apply even in 'auto' mode - Claude will only pick from allowed models diff --git a/conf/custom_models.json b/conf/custom_models.json index f794d00..8d83e00 100644 --- a/conf/custom_models.json +++ b/conf/custom_models.json @@ -51,8 +51,8 @@ }, "models": [ { - "model_name": "anthropic/claude-opus-4", - "aliases": ["opus", "claude-opus", "claude4-opus", "claude-4-opus"], + "model_name": "anthropic/claude-opus-4.1", + "aliases": ["opus", "claude-opus", "claude-opus-4.1", "claude-4.1-opus"], "context_window": 200000, "max_output_tokens": 64000, "supports_extended_thinking": false, @@ -60,11 +60,11 @@ "supports_function_calling": false, "supports_images": true, "max_image_size_mb": 5.0, - "description": "Claude 4 Opus - Most capable Claude model with vision" + "description": "Claude Opus 4.1 - Our most capable and intelligent model yet" }, { - "model_name": "anthropic/claude-sonnet-4", - "aliases": ["sonnet", "claude-sonnet", "claude4-sonnet", "claude-4-sonnet", "claude"], + "model_name": "anthropic/claude-sonnet-4.1", + "aliases": ["sonnet", "claude-sonnet", "claude-sonnet-4.1", "claude-4.1-sonnet", "claude"], "context_window": 200000, "max_output_tokens": 64000, "supports_extended_thinking": false, @@ -72,7 +72,7 @@ "supports_function_calling": false, "supports_images": true, "max_image_size_mb": 5.0, - "description": "Claude 4 Sonnet - Balanced performance with vision" + "description": "Claude Sonnet 4.1 - High-performance model with exceptional reasoning and efficiency" }, { "model_name": "anthropic/claude-3.5-haiku", diff --git a/providers/dial.py b/providers/dial.py index 6fbf3ca..dffbfba 100644 --- a/providers/dial.py +++ b/providers/dial.py @@ -68,10 +68,10 @@ class DIALModelProvider(OpenAICompatibleProvider): description="OpenAI O4-mini via DIAL - Fast reasoning model", aliases=["o4-mini"], ), - "anthropic.claude-sonnet-4-20250514-v1:0": ModelCapabilities( + "anthropic.claude-sonnet-4.1-20250805-v1:0": ModelCapabilities( provider=ProviderType.DIAL, - model_name="anthropic.claude-sonnet-4-20250514-v1:0", - friendly_name="DIAL (Sonnet 4)", + model_name="anthropic.claude-sonnet-4.1-20250805-v1:0", + friendly_name="DIAL (Sonnet 4.1)", context_window=200_000, max_output_tokens=64_000, supports_extended_thinking=False, @@ -83,13 +83,13 @@ class DIALModelProvider(OpenAICompatibleProvider): max_image_size_mb=5.0, supports_temperature=True, temperature_constraint=create_temperature_constraint("range"), - description="Claude Sonnet 4 via DIAL - Balanced performance", - aliases=["sonnet-4"], + description="Claude Sonnet 4.1 via DIAL - Balanced performance", + aliases=["sonnet-4.1", "sonnet-4"], ), - "anthropic.claude-sonnet-4-20250514-v1:0-with-thinking": ModelCapabilities( + "anthropic.claude-sonnet-4.1-20250805-v1:0-with-thinking": ModelCapabilities( provider=ProviderType.DIAL, - model_name="anthropic.claude-sonnet-4-20250514-v1:0-with-thinking", - friendly_name="DIAL (Sonnet 4 Thinking)", + model_name="anthropic.claude-sonnet-4.1-20250805-v1:0-with-thinking", + friendly_name="DIAL (Sonnet 4.1 Thinking)", context_window=200_000, max_output_tokens=64_000, supports_extended_thinking=True, # Thinking mode variant @@ -101,13 +101,13 @@ class DIALModelProvider(OpenAICompatibleProvider): max_image_size_mb=5.0, supports_temperature=True, temperature_constraint=create_temperature_constraint("range"), - description="Claude Sonnet 4 with thinking mode via DIAL", - aliases=["sonnet-4-thinking"], + description="Claude Sonnet 4.1 with thinking mode via DIAL", + aliases=["sonnet-4.1-thinking", "sonnet-4-thinking"], ), - "anthropic.claude-opus-4-20250514-v1:0": ModelCapabilities( + "anthropic.claude-opus-4.1-20250805-v1:0": ModelCapabilities( provider=ProviderType.DIAL, - model_name="anthropic.claude-opus-4-20250514-v1:0", - friendly_name="DIAL (Opus 4)", + model_name="anthropic.claude-opus-4.1-20250805-v1:0", + friendly_name="DIAL (Opus 4.1)", context_window=200_000, max_output_tokens=64_000, supports_extended_thinking=False, @@ -119,13 +119,13 @@ class DIALModelProvider(OpenAICompatibleProvider): max_image_size_mb=5.0, supports_temperature=True, temperature_constraint=create_temperature_constraint("range"), - description="Claude Opus 4 via DIAL - Most capable Claude model", - aliases=["opus-4"], + description="Claude Opus 4.1 via DIAL - Most capable Claude model", + aliases=["opus-4.1", "opus-4"], ), - "anthropic.claude-opus-4-20250514-v1:0-with-thinking": ModelCapabilities( + "anthropic.claude-opus-4.1-20250805-v1:0-with-thinking": ModelCapabilities( provider=ProviderType.DIAL, - model_name="anthropic.claude-opus-4-20250514-v1:0-with-thinking", - friendly_name="DIAL (Opus 4 Thinking)", + model_name="anthropic.claude-opus-4.1-20250805-v1:0-with-thinking", + friendly_name="DIAL (Opus 4.1 Thinking)", context_window=200_000, max_output_tokens=64_000, supports_extended_thinking=True, # Thinking mode variant @@ -137,8 +137,8 @@ class DIALModelProvider(OpenAICompatibleProvider): max_image_size_mb=5.0, supports_temperature=True, temperature_constraint=create_temperature_constraint("range"), - description="Claude Opus 4 with thinking mode via DIAL", - aliases=["opus-4-thinking"], + description="Claude Opus 4.1 with thinking mode via DIAL", + aliases=["opus-4.1-thinking", "opus-4-thinking"], ), "gemini-2.5-pro-preview-03-25-google-search": ModelCapabilities( provider=ProviderType.DIAL, diff --git a/tests/test_chat_simple.py b/tests/test_chat_simple.py index ff649a3..35b95df 100644 --- a/tests/test_chat_simple.py +++ b/tests/test_chat_simple.py @@ -52,7 +52,7 @@ class TestChatTool: "prompt": "Test prompt", "files": ["test.txt"], "images": ["test.png"], - "model": "anthropic/claude-3-opus", + "model": "anthropic/claude-opus-4.1", "temperature": 0.7, } @@ -60,7 +60,7 @@ class TestChatTool: assert request.prompt == "Test prompt" assert request.files == ["test.txt"] assert request.images == ["test.png"] - assert request.model == "anthropic/claude-3-opus" + assert request.model == "anthropic/claude-opus-4.1" assert request.temperature == 0.7 def test_required_fields(self): @@ -69,7 +69,7 @@ class TestChatTool: from pydantic import ValidationError with pytest.raises(ValidationError): - ChatRequest(model="anthropic/claude-3-opus") + ChatRequest(model="anthropic/claude-opus-4.1") def test_model_availability(self): """Test that model availability works""" diff --git a/tests/test_dial_provider.py b/tests/test_dial_provider.py index 0b23b84..0d8d70f 100644 --- a/tests/test_dial_provider.py +++ b/tests/test_dial_provider.py @@ -48,8 +48,8 @@ class TestDIALProvider: # Test valid models assert provider.validate_model_name("o3-2025-04-16") is True assert provider.validate_model_name("o3") is True # Shorthand - assert provider.validate_model_name("anthropic.claude-opus-4-20250514-v1:0") is True - assert provider.validate_model_name("opus-4") is True # Shorthand + assert provider.validate_model_name("anthropic.claude-opus-4.1-20250805-v1:0") is True + assert provider.validate_model_name("opus-4.1") is True # Shorthand assert provider.validate_model_name("gemini-2.5-pro-preview-05-06") is True assert provider.validate_model_name("gemini-2.5-pro") is True # Shorthand @@ -63,16 +63,16 @@ class TestDIALProvider: # Test shorthand resolution assert provider._resolve_model_name("o3") == "o3-2025-04-16" assert provider._resolve_model_name("o4-mini") == "o4-mini-2025-04-16" - assert provider._resolve_model_name("opus-4") == "anthropic.claude-opus-4-20250514-v1:0" - assert provider._resolve_model_name("sonnet-4") == "anthropic.claude-sonnet-4-20250514-v1:0" + assert provider._resolve_model_name("opus-4.1") == "anthropic.claude-opus-4.1-20250805-v1:0" + assert provider._resolve_model_name("sonnet-4.1") == "anthropic.claude-sonnet-4.1-20250805-v1:0" assert provider._resolve_model_name("gemini-2.5-pro") == "gemini-2.5-pro-preview-05-06" assert provider._resolve_model_name("gemini-2.5-flash") == "gemini-2.5-flash-preview-05-20" # Test full name passthrough assert provider._resolve_model_name("o3-2025-04-16") == "o3-2025-04-16" assert ( - provider._resolve_model_name("anthropic.claude-opus-4-20250514-v1:0") - == "anthropic.claude-opus-4-20250514-v1:0" + provider._resolve_model_name("anthropic.claude-opus-4.1-20250805-v1:0") + == "anthropic.claude-opus-4.1-20250805-v1:0" ) @patch.dict(os.environ, {"DIAL_ALLOWED_MODELS": ""}, clear=False) @@ -90,16 +90,16 @@ class TestDIALProvider: assert capabilities.supports_images is True assert capabilities.supports_extended_thinking is False - # Test Claude 4 capabilities - capabilities = provider.get_capabilities("opus-4") - assert capabilities.model_name == "anthropic.claude-opus-4-20250514-v1:0" + # Test Claude 4.1 capabilities + capabilities = provider.get_capabilities("opus-4.1") + assert capabilities.model_name == "anthropic.claude-opus-4.1-20250805-v1:0" assert capabilities.context_window == 200_000 assert capabilities.supports_images is True assert capabilities.supports_extended_thinking is False - # Test Claude 4 with thinking mode - capabilities = provider.get_capabilities("opus-4-thinking") - assert capabilities.model_name == "anthropic.claude-opus-4-20250514-v1:0-with-thinking" + # Test Claude 4.1 with thinking mode + capabilities = provider.get_capabilities("opus-4.1-thinking") + assert capabilities.model_name == "anthropic.claude-opus-4.1-20250805-v1:0-with-thinking" assert capabilities.context_window == 200_000 assert capabilities.supports_images is True assert capabilities.supports_extended_thinking is True @@ -146,7 +146,7 @@ class TestDIALProvider: # Test models with vision support assert provider._supports_vision("o3-2025-04-16") is True assert provider._supports_vision("o3") is True # Via resolution - assert provider._supports_vision("anthropic.claude-opus-4-20250514-v1:0") is True + assert provider._supports_vision("anthropic.claude-opus-4.1-20250805-v1:0") is True assert provider._supports_vision("gemini-2.5-pro-preview-05-06") is True # Test unknown model (falls back to parent implementation) @@ -219,7 +219,7 @@ class TestDIALProvider: # Check that Api-Key header is set assert provider.DEFAULT_HEADERS["Api-Key"] == "test-key" - @patch.dict(os.environ, {"DIAL_ALLOWED_MODELS": "o3-2025-04-16,anthropic.claude-opus-4-20250514-v1:0"}) + @patch.dict(os.environ, {"DIAL_ALLOWED_MODELS": "o3-2025-04-16,anthropic.claude-opus-4.1-20250805-v1:0"}) @patch("utils.model_restrictions._restriction_service", None) def test_allowed_models_restriction(self): """Test model allow-list functionality.""" @@ -228,13 +228,13 @@ class TestDIALProvider: # These should be allowed assert provider.validate_model_name("o3-2025-04-16") is True assert provider.validate_model_name("o3") is True # Alias for o3-2025-04-16 - assert provider.validate_model_name("anthropic.claude-opus-4-20250514-v1:0") is True - assert provider.validate_model_name("opus-4") is True # Resolves to anthropic.claude-opus-4-20250514-v1:0 + assert provider.validate_model_name("anthropic.claude-opus-4.1-20250805-v1:0") is True + assert provider.validate_model_name("opus-4.1") is True # Resolves to anthropic.claude-opus-4.1-20250805-v1:0 # These should be blocked assert provider.validate_model_name("gemini-2.5-pro-preview-05-06") is False assert provider.validate_model_name("o4-mini-2025-04-16") is False - assert provider.validate_model_name("sonnet-4") is False # sonnet-4 is not in allowed list + assert provider.validate_model_name("sonnet-4.1") is False # sonnet-4.1 is not in allowed list @patch("httpx.Client") @patch("openai.OpenAI") diff --git a/tests/test_openrouter_provider.py b/tests/test_openrouter_provider.py index 454f372..2f28872 100644 --- a/tests/test_openrouter_provider.py +++ b/tests/test_openrouter_provider.py @@ -71,26 +71,26 @@ class TestOpenRouterProvider: provider = OpenRouterProvider(api_key="test-key") # Test alias resolution - assert provider._resolve_model_name("opus") == "anthropic/claude-opus-4" - assert provider._resolve_model_name("sonnet") == "anthropic/claude-sonnet-4" + assert provider._resolve_model_name("opus") == "anthropic/claude-opus-4.1" + assert provider._resolve_model_name("sonnet") == "anthropic/claude-sonnet-4.1" assert provider._resolve_model_name("o3") == "openai/o3" assert provider._resolve_model_name("o3-mini") == "openai/o3-mini" assert provider._resolve_model_name("o3mini") == "openai/o3-mini" assert provider._resolve_model_name("o4-mini") == "openai/o4-mini" assert provider._resolve_model_name("o4-mini") == "openai/o4-mini" - assert provider._resolve_model_name("claude") == "anthropic/claude-sonnet-4" + assert provider._resolve_model_name("claude") == "anthropic/claude-sonnet-4.1" assert provider._resolve_model_name("mistral") == "mistralai/mistral-large-2411" assert provider._resolve_model_name("deepseek") == "deepseek/deepseek-r1-0528" assert provider._resolve_model_name("r1") == "deepseek/deepseek-r1-0528" # Test case-insensitive - assert provider._resolve_model_name("OPUS") == "anthropic/claude-opus-4" + assert provider._resolve_model_name("OPUS") == "anthropic/claude-opus-4.1" assert provider._resolve_model_name("O3") == "openai/o3" assert provider._resolve_model_name("Mistral") == "mistralai/mistral-large-2411" - assert provider._resolve_model_name("CLAUDE") == "anthropic/claude-sonnet-4" + assert provider._resolve_model_name("CLAUDE") == "anthropic/claude-sonnet-4.1" # Test direct model names (should pass through unchanged) - assert provider._resolve_model_name("anthropic/claude-opus-4") == "anthropic/claude-opus-4" + assert provider._resolve_model_name("anthropic/claude-opus-4.1") == "anthropic/claude-opus-4.1" assert provider._resolve_model_name("openai/o3") == "openai/o3" # Test unknown models pass through @@ -155,8 +155,8 @@ class TestOpenRouterAutoMode: "google/gemini-2.5-pro", "openai/o3", "openai/o3-mini", - "anthropic/claude-opus-4", - "anthropic/claude-sonnet-4", + "anthropic/claude-opus-4.1", + "anthropic/claude-sonnet-4.1", ] ModelProviderRegistry.register_provider(ProviderType.OPENROUTER, OpenRouterProvider) @@ -181,7 +181,7 @@ class TestOpenRouterAutoMode: os.environ.pop("OPENAI_API_KEY", None) os.environ["OPENROUTER_API_KEY"] = "test-openrouter-key" os.environ.pop("OPENROUTER_ALLOWED_MODELS", None) - os.environ["OPENROUTER_ALLOWED_MODELS"] = "anthropic/claude-opus-4,google/gemini-2.5-flash" + os.environ["OPENROUTER_ALLOWED_MODELS"] = "anthropic/claude-opus-4.1,google/gemini-2.5-flash" os.environ["DEFAULT_MODEL"] = "auto" # Force reload to pick up new environment variable @@ -193,8 +193,8 @@ class TestOpenRouterAutoMode: mock_models = [ "google/gemini-2.5-flash", "google/gemini-2.5-pro", - "anthropic/claude-opus-4", - "anthropic/claude-sonnet-4", + "anthropic/claude-opus-4.1", + "anthropic/claude-sonnet-4.1", ] mock_registry.list_models.return_value = mock_models @@ -212,7 +212,7 @@ class TestOpenRouterAutoMode: assert len(available_models) > 0, "Should have some allowed models" - expected_allowed = {"google/gemini-2.5-flash", "anthropic/claude-opus-4"} + expected_allowed = {"google/gemini-2.5-flash", "anthropic/claude-opus-4.1"} assert ( set(available_models.keys()) == expected_allowed @@ -263,7 +263,7 @@ class TestOpenRouterRegistry: # Should have loaded models models = registry.list_models() assert len(models) > 0 - assert "anthropic/claude-opus-4" in models + assert "anthropic/claude-opus-4.1" in models assert "openai/o3" in models # Should have loaded aliases @@ -282,13 +282,13 @@ class TestOpenRouterRegistry: # Test known model caps = registry.get_capabilities("opus") assert caps is not None - assert caps.model_name == "anthropic/claude-opus-4" + assert caps.model_name == "anthropic/claude-opus-4.1" assert caps.context_window == 200000 # Claude's context window # Test using full model name - caps = registry.get_capabilities("anthropic/claude-opus-4") + caps = registry.get_capabilities("anthropic/claude-opus-4.1") assert caps is not None - assert caps.model_name == "anthropic/claude-opus-4" + assert caps.model_name == "anthropic/claude-opus-4.1" # Test unknown model caps = registry.get_capabilities("non-existent-model") @@ -301,11 +301,11 @@ class TestOpenRouterRegistry: registry = OpenRouterModelRegistry() # All these should resolve to Claude Sonnet - sonnet_aliases = ["sonnet", "claude", "claude-sonnet", "claude4-sonnet"] + sonnet_aliases = ["sonnet", "claude", "claude-sonnet", "claude-4.1-sonnet"] for alias in sonnet_aliases: config = registry.resolve(alias) assert config is not None - assert config.model_name == "anthropic/claude-sonnet-4" + assert config.model_name == "anthropic/claude-sonnet-4.1" class TestOpenRouterFunctionality: diff --git a/tests/test_openrouter_registry.py b/tests/test_openrouter_registry.py index 6387ebe..e3c923a 100644 --- a/tests/test_openrouter_registry.py +++ b/tests/test_openrouter_registry.py @@ -87,9 +87,9 @@ class TestOpenRouterModelRegistry: # Test various aliases test_cases = [ - ("opus", "anthropic/claude-opus-4"), - ("OPUS", "anthropic/claude-opus-4"), # Case insensitive - ("claude", "anthropic/claude-sonnet-4"), + ("opus", "anthropic/claude-opus-4.1"), + ("OPUS", "anthropic/claude-opus-4.1"), # Case insensitive + ("claude", "anthropic/claude-sonnet-4.1"), ("o3", "openai/o3"), ("deepseek", "deepseek/deepseek-r1-0528"), ("mistral", "mistralai/mistral-large-2411"), @@ -105,9 +105,9 @@ class TestOpenRouterModelRegistry: registry = OpenRouterModelRegistry() # Should be able to look up by full model name - config = registry.resolve("anthropic/claude-opus-4") + config = registry.resolve("anthropic/claude-opus-4.1") assert config is not None - assert config.model_name == "anthropic/claude-opus-4" + assert config.model_name == "anthropic/claude-opus-4.1" config = registry.resolve("openai/o3") assert config is not None @@ -131,8 +131,8 @@ class TestOpenRouterModelRegistry: # Registry now returns ModelCapabilities objects directly assert config.provider == ProviderType.OPENROUTER - assert config.model_name == "anthropic/claude-opus-4" - assert config.friendly_name == "OpenRouter (anthropic/claude-opus-4)" + assert config.model_name == "anthropic/claude-opus-4.1" + assert config.friendly_name == "OpenRouter (anthropic/claude-opus-4.1)" assert config.context_window == 200000 assert not config.supports_extended_thinking diff --git a/tests/test_parse_model_option.py b/tests/test_parse_model_option.py index 5b01c88..b23a347 100644 --- a/tests/test_parse_model_option.py +++ b/tests/test_parse_model_option.py @@ -14,8 +14,8 @@ class TestParseModelOption: def test_openrouter_beta_suffix_preserved(self): """Test that OpenRouter :beta suffix is preserved as part of model name.""" - model, option = parse_model_option("anthropic/claude-3-opus:beta") - assert model == "anthropic/claude-3-opus:beta" + model, option = parse_model_option("anthropic/claude-opus-4.1:beta") + assert model == "anthropic/claude-opus-4.1:beta" assert option is None def test_openrouter_preview_suffix_preserved(self): diff --git a/tests/test_provider_routing_bugs.py b/tests/test_provider_routing_bugs.py index f05e181..1e1363c 100644 --- a/tests/test_provider_routing_bugs.py +++ b/tests/test_provider_routing_bugs.py @@ -344,7 +344,7 @@ class TestOpenRouterAliasRestrictions: os.environ.pop("OPENAI_API_KEY", None) os.environ.pop("XAI_API_KEY", None) os.environ["OPENROUTER_API_KEY"] = "test-key" - os.environ["OPENROUTER_ALLOWED_MODELS"] = "o3-mini,anthropic/claude-opus-4,flash" + os.environ["OPENROUTER_ALLOWED_MODELS"] = "o3-mini,anthropic/claude-opus-4.1,flash" # Register OpenRouter provider from providers.openrouter import OpenRouterProvider @@ -356,7 +356,7 @@ class TestOpenRouterAliasRestrictions: expected_models = { "openai/o3-mini", # from alias - "anthropic/claude-opus-4", # full name + "anthropic/claude-opus-4.1", # full name "google/gemini-2.5-flash", # from alias } diff --git a/tests/test_provider_utf8.py b/tests/test_provider_utf8.py index b67923f..fc630e9 100644 --- a/tests/test_provider_utf8.py +++ b/tests/test_provider_utf8.py @@ -351,7 +351,7 @@ class TestLocaleModelIntegration(unittest.TestCase): def test_model_name_resolution_utf8(self): """Test model name resolution with UTF-8.""" provider = OpenAIModelProvider(api_key="test") - model_names = ["gpt-4", "gemini-2.5-flash", "claude-3-opus", "o3-pro"] + model_names = ["gpt-4", "gemini-2.5-flash", "anthropic/claude-opus-4.1", "o3-pro"] for model_name in model_names: resolved = provider._resolve_model_name(model_name) self.assertIsInstance(resolved, str) diff --git a/tests/test_supported_models_aliases.py b/tests/test_supported_models_aliases.py index e445333..256eaaf 100644 --- a/tests/test_supported_models_aliases.py +++ b/tests/test_supported_models_aliases.py @@ -105,19 +105,19 @@ class TestSupportedModelsAliases: # Test specific aliases assert "o3" in provider.SUPPORTED_MODELS["o3-2025-04-16"].aliases assert "o4-mini" in provider.SUPPORTED_MODELS["o4-mini-2025-04-16"].aliases - assert "sonnet-4" in provider.SUPPORTED_MODELS["anthropic.claude-sonnet-4-20250514-v1:0"].aliases - assert "opus-4" in provider.SUPPORTED_MODELS["anthropic.claude-opus-4-20250514-v1:0"].aliases + assert "sonnet-4.1" in provider.SUPPORTED_MODELS["anthropic.claude-sonnet-4.1-20250805-v1:0"].aliases + assert "opus-4.1" in provider.SUPPORTED_MODELS["anthropic.claude-opus-4.1-20250805-v1:0"].aliases assert "gemini-2.5-pro" in provider.SUPPORTED_MODELS["gemini-2.5-pro-preview-05-06"].aliases # Test alias resolution assert provider._resolve_model_name("o3") == "o3-2025-04-16" assert provider._resolve_model_name("o4-mini") == "o4-mini-2025-04-16" - assert provider._resolve_model_name("sonnet-4") == "anthropic.claude-sonnet-4-20250514-v1:0" - assert provider._resolve_model_name("opus-4") == "anthropic.claude-opus-4-20250514-v1:0" + assert provider._resolve_model_name("sonnet-4.1") == "anthropic.claude-sonnet-4.1-20250805-v1:0" + assert provider._resolve_model_name("opus-4.1") == "anthropic.claude-opus-4.1-20250805-v1:0" # Test case insensitive resolution assert provider._resolve_model_name("O3") == "o3-2025-04-16" - assert provider._resolve_model_name("SONNET-4") == "anthropic.claude-sonnet-4-20250514-v1:0" + assert provider._resolve_model_name("SONNET-4.1") == "anthropic.claude-sonnet-4.1-20250805-v1:0" def test_list_models_includes_aliases(self): """Test that list_models returns both base models and aliases.""" diff --git a/tools/shared/base_tool.py b/tools/shared/base_tool.py index b2b00cf..d2ce7b5 100644 --- a/tools/shared/base_tool.py +++ b/tools/shared/base_tool.py @@ -1401,7 +1401,7 @@ When recommending searches, be specific about what information you need and why "content": ( f"Image support not available: Model '{model_name}' does not support image processing. " f"Please use a vision-capable model such as 'gemini-2.5-flash', 'o3', " - f"or 'claude-3-opus' for image analysis tasks." + f"or 'claude-opus-4.1' for image analysis tasks." ), "content_type": "text", "metadata": {