fix(providers): support anthropic proxy v1 endpoints
This commit is contained in:
parent
81e42335a1
commit
85e6232a07
8 changed files with 133 additions and 14 deletions
|
|
@ -113,6 +113,15 @@ class TestBuildAnthropicClient:
|
|||
"anthropic-beta": "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14"
|
||||
}
|
||||
|
||||
def test_custom_base_url_strips_trailing_v1(self):
|
||||
with patch("agent.anthropic_adapter._anthropic_sdk") as mock_sdk:
|
||||
build_anthropic_client(
|
||||
"sk-ant-api03-x",
|
||||
base_url="https://proxy.example.com/anthropic/v1",
|
||||
)
|
||||
kwargs = mock_sdk.Anthropic.call_args[1]
|
||||
assert kwargs["base_url"] == "https://proxy.example.com/anthropic"
|
||||
|
||||
def test_azure_anthropic_endpoint_keeps_context_1m_beta(self):
|
||||
with patch("agent.anthropic_adapter._anthropic_sdk") as mock_sdk:
|
||||
build_anthropic_client(
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ def _clean_env(monkeypatch):
|
|||
("https://api.moonshot.ai/v1", False, "Moonshot legacy"),
|
||||
("https://api.minimax.io/anthropic", True, "MiniMax /anthropic"),
|
||||
("https://litellm.example.com/v1/anthropic", True, "/anthropic suffix"),
|
||||
("https://litellm.example.com/anthropic/v1", True, "/anthropic/v1 base"),
|
||||
("https://litellm.example.com/anthropic/v1/models", False, "/anthropic/v1 subpath"),
|
||||
("https://api.anthropic.com", True, "native Anthropic"),
|
||||
("https://api.anthropic.com/v1", True, "native Anthropic /v1"),
|
||||
("https://openrouter.ai/api/v1", False, "OpenRouter"),
|
||||
|
|
|
|||
|
|
@ -56,13 +56,16 @@ class TestAnthropicMessagesDetection:
|
|||
def test_trailing_slash_tolerated(self):
|
||||
assert _detect_api_mode_for_url("https://api.minimax.io/anthropic/") == "anthropic_messages"
|
||||
|
||||
def test_versioned_anthropic_base_url_tolerated(self):
|
||||
assert _detect_api_mode_for_url("https://proxy.example.com/anthropic/v1") == "anthropic_messages"
|
||||
|
||||
def test_uppercase_path_tolerated(self):
|
||||
assert _detect_api_mode_for_url("https://API.MINIMAX.IO/Anthropic") == "anthropic_messages"
|
||||
|
||||
def test_anthropic_in_middle_of_path_does_not_match(self):
|
||||
def test_anthropic_endpoint_subpath_does_not_match(self):
|
||||
# The helper requires ``/anthropic`` as the path SUFFIX, not anywhere.
|
||||
# Protects against false positives on e.g. /anthropic/v1/models.
|
||||
assert _detect_api_mode_for_url("https://api.example.com/anthropic/v1") is None
|
||||
assert _detect_api_mode_for_url("https://api.example.com/anthropic/v1/models") is None
|
||||
|
||||
|
||||
class TestDefaultCase:
|
||||
|
|
|
|||
|
|
@ -215,6 +215,58 @@ class TestProviderModelIds:
|
|||
patch("hermes_cli.models._fetch_github_models", return_value=["gpt-5.4", "claude-sonnet-4.6"]):
|
||||
assert provider_model_ids("copilot-acp") == ["gpt-5.4", "claude-sonnet-4.6"]
|
||||
|
||||
def test_anthropic_provider_uses_configured_base_url_for_live_catalog(self):
|
||||
class _Resp:
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def read(self):
|
||||
return b'{"data": [{"id": "enterprise-claude"}]}'
|
||||
|
||||
with patch(
|
||||
"hermes_cli.config.load_config",
|
||||
return_value={
|
||||
"model": {
|
||||
"provider": "anthropic",
|
||||
"base_url": "http://localhost:6655/anthropic/v1",
|
||||
"api_key": "proxy-key",
|
||||
}
|
||||
},
|
||||
), patch(
|
||||
"hermes_cli.models.urllib.request.urlopen",
|
||||
return_value=_Resp(),
|
||||
) as mock_urlopen:
|
||||
assert provider_model_ids("anthropic") == ["enterprise-claude"]
|
||||
|
||||
req = mock_urlopen.call_args[0][0]
|
||||
assert req.full_url == "http://localhost:6655/anthropic/v1/models"
|
||||
assert req.get_header("X-api-key") == "proxy-key"
|
||||
|
||||
def test_custom_provider_passes_anthropic_mode_for_versioned_proxy_catalog(self):
|
||||
with patch(
|
||||
"hermes_cli.config.load_config",
|
||||
return_value={
|
||||
"model": {
|
||||
"provider": "custom",
|
||||
"base_url": "http://localhost:6655/anthropic/v1",
|
||||
"api_key": "proxy-key",
|
||||
}
|
||||
},
|
||||
), patch(
|
||||
"hermes_cli.models.fetch_api_models",
|
||||
return_value=["enterprise-claude"],
|
||||
) as mock_fetch:
|
||||
assert provider_model_ids("custom") == ["enterprise-claude"]
|
||||
|
||||
mock_fetch.assert_called_once_with(
|
||||
"proxy-key",
|
||||
"http://localhost:6655/anthropic/v1",
|
||||
api_mode="anthropic_messages",
|
||||
)
|
||||
|
||||
|
||||
# -- fetch_api_models --------------------------------------------------------
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue