hermes-agent/tests/gateway/test_auth_fallback.py
Tranquil-Flow ee83a710f0 fix(gateway,cron): activate fallback_model when primary provider auth fails
When the primary provider raises AuthError (expired OAuth token,
revoked API key), the error was re-raised before AIAgent was created,
so fallback_model was never consulted. Now both gateway/run.py and
cron/scheduler.py catch AuthError specifically and attempt to resolve
credentials from the fallback_providers/fallback_model config chain
before propagating the error.

Closes #7230
2026-04-24 05:35:43 -07:00

73 lines
2.7 KiB
Python

"""Test that AuthError triggers fallback provider resolution (#7230)."""
import os
from unittest.mock import patch, MagicMock
import pytest
class TestResolveRuntimeAgentKwargsAuthFallback:
"""_resolve_runtime_agent_kwargs should try fallback on AuthError."""
def test_auth_error_tries_fallback(self, tmp_path, monkeypatch):
"""When primary provider raises AuthError, fallback is attempted."""
from hermes_cli.auth import AuthError
# Create a config with fallback
config_path = tmp_path / "config.yaml"
config_path.write_text(
"model:\n provider: openai-codex\n"
"fallback_model:\n provider: openrouter\n"
" model: meta-llama/llama-4-maverick\n"
)
monkeypatch.setattr("gateway.run._hermes_home", tmp_path)
call_count = {"n": 0}
def _mock_resolve(**kwargs):
call_count["n"] += 1
requested = kwargs.get("requested", "")
if requested and "codex" in str(requested).lower():
raise AuthError("Codex token refresh failed with status 401")
return {
"api_key": "fallback-key",
"base_url": "https://openrouter.ai/api/v1",
"provider": "openrouter",
"api_mode": "openai_chat",
"command": None,
"args": None,
"credential_pool": None,
}
monkeypatch.setenv("HERMES_INFERENCE_PROVIDER", "openai-codex")
with patch(
"hermes_cli.runtime_provider.resolve_runtime_provider",
side_effect=_mock_resolve,
):
from gateway.run import _resolve_runtime_agent_kwargs
result = _resolve_runtime_agent_kwargs()
assert result["provider"] == "openrouter"
assert result["api_key"] == "fallback-key"
# Should have been called at least twice (primary + fallback)
assert call_count["n"] >= 2
def test_auth_error_no_fallback_raises(self, tmp_path, monkeypatch):
"""When primary fails and no fallback configured, RuntimeError is raised."""
from hermes_cli.auth import AuthError
config_path = tmp_path / "config.yaml"
config_path.write_text("model:\n provider: openai-codex\n")
monkeypatch.setattr("gateway.run._hermes_home", tmp_path)
monkeypatch.setenv("HERMES_INFERENCE_PROVIDER", "openai-codex")
with patch(
"hermes_cli.runtime_provider.resolve_runtime_provider",
side_effect=AuthError("token expired"),
):
from gateway.run import _resolve_runtime_agent_kwargs
with pytest.raises(RuntimeError):
_resolve_runtime_agent_kwargs()