mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
fix(auxiliary): fall back to OPENROUTER_API_KEY when credential pool exhausted
_try_openrouter() returned (None, None) whenever an OpenRouter credential pool existed but was exhausted (_select_pool_entry -> (True, None)), making the OPENROUTER_API_KEY env-var fallback unreachable. Auxiliary tasks (compression, vision, web_extract) silently failed even with a valid env key. Now the pool-present branch only returns early when it successfully builds a client; an exhausted pool falls through to the env-var path. The final failure (pool exhausted AND no env var) still marks the provider unhealthy. Fixes #23452. Co-authored-by: ambition0802 <noreply@github.com>
This commit is contained in:
parent
46e18804ad
commit
c56b39c11e
2 changed files with 40 additions and 7 deletions
|
|
@ -1669,13 +1669,14 @@ def _try_openrouter(explicit_api_key: str = None, model: str = None) -> Tuple[Op
|
|||
pool_present, entry = _select_pool_entry("openrouter")
|
||||
if pool_present:
|
||||
or_key = explicit_api_key or _pool_runtime_api_key(entry)
|
||||
if not or_key:
|
||||
_mark_provider_unhealthy("openrouter", ttl=60)
|
||||
return None, None
|
||||
base_url = _pool_runtime_base_url(entry, OPENROUTER_BASE_URL) or OPENROUTER_BASE_URL
|
||||
logger.debug("Auxiliary client: OpenRouter via pool")
|
||||
return OpenAI(api_key=or_key, base_url=base_url,
|
||||
default_headers=build_or_headers()), model or _OPENROUTER_MODEL
|
||||
if or_key:
|
||||
base_url = _pool_runtime_base_url(entry, OPENROUTER_BASE_URL) or OPENROUTER_BASE_URL
|
||||
logger.debug("Auxiliary client: OpenRouter via pool")
|
||||
return OpenAI(api_key=or_key, base_url=base_url,
|
||||
default_headers=build_or_headers()), model or _OPENROUTER_MODEL
|
||||
# Pool exists but is exhausted (no usable runtime key) — fall through to
|
||||
# the OPENROUTER_API_KEY env-var path rather than failing outright.
|
||||
logger.debug("Auxiliary client: OpenRouter pool exhausted, trying OPENROUTER_API_KEY")
|
||||
|
||||
or_key = explicit_api_key or os.getenv("OPENROUTER_API_KEY")
|
||||
if not or_key:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ from agent.auxiliary_client import (
|
|||
_refresh_nous_recommended_model,
|
||||
_normalize_aux_provider,
|
||||
_try_payment_fallback,
|
||||
_try_openrouter,
|
||||
_OPENROUTER_MODEL,
|
||||
OPENROUTER_BASE_URL,
|
||||
_resolve_auto,
|
||||
_resolve_xai_oauth_for_aux,
|
||||
_CodexCompletionsAdapter,
|
||||
|
|
@ -919,6 +922,35 @@ class TestExplicitProviderRouting:
|
|||
for record in caplog.records
|
||||
)
|
||||
|
||||
def test_try_openrouter_pool_exhausted_falls_back_to_env(self, monkeypatch):
|
||||
"""Pool present but exhausted → fall through to OPENROUTER_API_KEY env var."""
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-env-fallback")
|
||||
with patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)), \
|
||||
patch("agent.auxiliary_client.OpenAI") as mock_openai:
|
||||
mock_client = MagicMock(name="openrouter_client")
|
||||
mock_openai.return_value = mock_client
|
||||
|
||||
client, model = _try_openrouter()
|
||||
|
||||
assert client is mock_client
|
||||
assert model == _OPENROUTER_MODEL
|
||||
mock_openai.assert_called_once()
|
||||
assert mock_openai.call_args.kwargs["api_key"] == "sk-or-env-fallback"
|
||||
assert mock_openai.call_args.kwargs["base_url"] == OPENROUTER_BASE_URL
|
||||
|
||||
def test_try_openrouter_pool_exhausted_no_env_marks_unhealthy(self, monkeypatch):
|
||||
"""Pool exhausted AND no env var → final failure marks provider unhealthy."""
|
||||
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
||||
with patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)), \
|
||||
patch("agent.auxiliary_client._mark_provider_unhealthy") as mock_mark, \
|
||||
patch("agent.auxiliary_client.OpenAI") as mock_openai:
|
||||
client, model = _try_openrouter()
|
||||
|
||||
assert client is None
|
||||
assert model is None
|
||||
mock_openai.assert_not_called()
|
||||
mock_mark.assert_called_once_with("openrouter", ttl=60)
|
||||
|
||||
class TestGetTextAuxiliaryClient:
|
||||
"""Test the full resolution chain for get_text_auxiliary_client."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue