mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
fix: require oauth creds for native Anthropic
This commit is contained in:
parent
db9e512424
commit
f4e8772de4
4 changed files with 35 additions and 146 deletions
|
|
@ -100,15 +100,13 @@ class TestReadClaudeCodeCredentials:
|
|||
assert creds["refreshToken"] == "sk-ant-oat01-refresh"
|
||||
assert creds["source"] == "claude_code_credentials_file"
|
||||
|
||||
def test_reads_primary_api_key_with_source(self, tmp_path, monkeypatch):
|
||||
def test_ignores_primary_api_key_for_native_anthropic_resolution(self, tmp_path, monkeypatch):
|
||||
claude_json = tmp_path / ".claude.json"
|
||||
claude_json.write_text(json.dumps({"primaryApiKey": "sk-ant-api03-primary"}))
|
||||
monkeypatch.setattr("agent.anthropic_adapter.Path.home", lambda: tmp_path)
|
||||
|
||||
creds = read_claude_code_credentials()
|
||||
assert creds is not None
|
||||
assert creds["accessToken"] == "sk-ant-api03-primary"
|
||||
assert creds["source"] == "claude_json_primary_api_key"
|
||||
assert creds is None
|
||||
|
||||
def test_returns_none_for_missing_file(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setattr("agent.anthropic_adapter.Path.home", lambda: tmp_path)
|
||||
|
|
@ -160,6 +158,15 @@ class TestResolveAnthropicToken:
|
|||
|
||||
assert get_anthropic_token_source("sk-ant-api03-primary") == "claude_json_primary_api_key"
|
||||
|
||||
def test_does_not_resolve_primary_api_key_as_native_anthropic_token(self, monkeypatch, tmp_path):
|
||||
monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
|
||||
monkeypatch.delenv("ANTHROPIC_TOKEN", raising=False)
|
||||
monkeypatch.delenv("CLAUDE_CODE_OAUTH_TOKEN", raising=False)
|
||||
(tmp_path / ".claude.json").write_text(json.dumps({"primaryApiKey": "sk-ant-api03-primary"}))
|
||||
monkeypatch.setattr("agent.anthropic_adapter.Path.home", lambda: tmp_path)
|
||||
|
||||
assert resolve_anthropic_token() is None
|
||||
|
||||
def test_falls_back_to_api_key_when_no_oauth_sources_exist(self, monkeypatch, tmp_path):
|
||||
monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-ant-api03-mykey")
|
||||
monkeypatch.delenv("ANTHROPIC_TOKEN", raising=False)
|
||||
|
|
|
|||
|
|
@ -1089,46 +1089,6 @@ class TestRunConversation:
|
|||
assert result["completed"] is True
|
||||
assert result["final_response"] == "Recovered after remint"
|
||||
|
||||
def test_anthropic_managed_key_500_falls_back_to_haiku_and_retries(self, agent):
|
||||
self._setup_agent(agent)
|
||||
agent.provider = "anthropic"
|
||||
agent.api_mode = "anthropic_messages"
|
||||
agent.model = "claude-sonnet-4-6"
|
||||
agent._anthropic_auth_source = "claude_json_primary_api_key"
|
||||
agent._anthropic_api_key = "sk-ant-api03-primary"
|
||||
|
||||
calls = {"api": 0}
|
||||
|
||||
class _ServerError(RuntimeError):
|
||||
def __init__(self):
|
||||
super().__init__("Error code: 500 - internal server error")
|
||||
self.status_code = 500
|
||||
|
||||
anthropic_response = SimpleNamespace(
|
||||
content=[SimpleNamespace(type="text", text="Recovered with haiku")],
|
||||
stop_reason="end_turn",
|
||||
usage=None,
|
||||
)
|
||||
|
||||
def _fake_api_call(api_kwargs):
|
||||
calls["api"] += 1
|
||||
if calls["api"] == 1:
|
||||
raise _ServerError()
|
||||
return anthropic_response
|
||||
|
||||
with (
|
||||
patch.object(agent, "_persist_session"),
|
||||
patch.object(agent, "_save_trajectory"),
|
||||
patch.object(agent, "_cleanup_task_resources"),
|
||||
patch.object(agent, "_interruptible_api_call", side_effect=_fake_api_call),
|
||||
):
|
||||
result = agent.run_conversation("hello")
|
||||
|
||||
assert calls["api"] == 2
|
||||
assert agent.model == "claude-haiku-4-5-20251001"
|
||||
assert result["completed"] is True
|
||||
assert result["final_response"] == "Recovered with haiku"
|
||||
|
||||
def test_context_compression_triggered(self, agent):
|
||||
"""When compressor says should_compress, compression runs."""
|
||||
self._setup_agent(agent)
|
||||
|
|
@ -2185,46 +2145,6 @@ class TestAnthropicCredentialRefresh:
|
|||
old_client.close.assert_not_called()
|
||||
rebuild.assert_not_called()
|
||||
|
||||
def test_try_fallback_anthropic_managed_key_model_switches_sonnet_to_haiku(self):
|
||||
with (
|
||||
patch("run_agent.get_tool_definitions", return_value=_make_tool_defs("web_search")),
|
||||
patch("run_agent.check_toolset_requirements", return_value={}),
|
||||
patch("agent.anthropic_adapter.build_anthropic_client", return_value=MagicMock()),
|
||||
):
|
||||
agent = AIAgent(
|
||||
api_key="sk-ant-api03-primary",
|
||||
api_mode="anthropic_messages",
|
||||
quiet_mode=True,
|
||||
skip_context_files=True,
|
||||
skip_memory=True,
|
||||
)
|
||||
|
||||
agent.model = "claude-sonnet-4-6"
|
||||
agent._anthropic_auth_source = "claude_json_primary_api_key"
|
||||
|
||||
assert agent._try_fallback_anthropic_managed_key_model() is True
|
||||
assert agent.model == "claude-haiku-4-5-20251001"
|
||||
|
||||
def test_try_fallback_anthropic_managed_key_model_ignores_normal_api_keys(self):
|
||||
with (
|
||||
patch("run_agent.get_tool_definitions", return_value=_make_tool_defs("web_search")),
|
||||
patch("run_agent.check_toolset_requirements", return_value={}),
|
||||
patch("agent.anthropic_adapter.build_anthropic_client", return_value=MagicMock()),
|
||||
):
|
||||
agent = AIAgent(
|
||||
api_key="sk-ant-api03-real-api-key",
|
||||
api_mode="anthropic_messages",
|
||||
quiet_mode=True,
|
||||
skip_context_files=True,
|
||||
skip_memory=True,
|
||||
)
|
||||
|
||||
agent.model = "claude-sonnet-4-6"
|
||||
agent._anthropic_auth_source = "anthropic_api_key_env"
|
||||
|
||||
assert agent._try_fallback_anthropic_managed_key_model() is False
|
||||
assert agent.model == "claude-sonnet-4-6"
|
||||
|
||||
def test_anthropic_messages_create_preflights_refresh(self):
|
||||
with (
|
||||
patch("run_agent.get_tool_definitions", return_value=_make_tool_defs("web_search")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue