Files
hermes-agent/tests/gateway/test_runtime_provider_override_target_model.py
teknium1 50274afa6c fix(gateway): route AuthError fallback through resolve_runtime_with_fallback
The gateway kept its own get_fallback_chain walk in _try_resolve_fallback_provider,
a near copy of the shared resolution-time helper. _resolve_runtime_agent_kwargs now
calls resolve_runtime_with_fallback(cfg) and the private loop is deleted; the
rate-limited (429) vs auth-failed log distinction (is_rate_limited_auth_error) moves
into the helper so every caller keeps it.

Also: drop the test-only resolve= seam from the helper (tests monkeypatch
hermes_cli.runtime_provider.resolve_runtime_provider instead), and log non-AuthError
fallback-entry failures at warning so a mistyped fallback provider is not silently
skipped at debug level.

Tests: test_fallback_chain_runtime_uses_the_entry_model now drives
gateway.run._resolve_runtime_agent_kwargs (red when the helper's chain walk is
sabotaged); two gateway stubs accept the helper's keyword arguments.
2026-09-19 09:42:18 -07:00

50 lines
2.2 KiB
Python

"""Gateway provider-override credential resolution keys off the override's MODEL (#112600).
Channel overrides, persisted ``/model`` switches and API-server provider refreshes all resolve
credentials through ``gateway.run._resolve_runtime_agent_kwargs_for_provider``; without the model
the ladder keys off config's ``default`` and a ``*-free`` default decides the api_mode/base_url
for a Go-only model ("Model ... is not supported")."""
import pytest
@pytest.fixture()
def _zen_free_default_home(monkeypatch, tmp_path):
home = tmp_path / "hermes"
home.mkdir()
(home / "config.yaml").write_text(
"model:\n default: mimo-v2.5-free\n provider: opencode\n base_url: https://opencode.ai/zen/v1\n")
monkeypatch.setenv("HERMES_HOME", str(home))
monkeypatch.setenv("OPENCODE_GO_API_KEY", "sk-test-go")
def test_provider_override_runtime_uses_the_override_model(_zen_free_default_home):
from gateway.run import _resolve_runtime_agent_kwargs_for_provider
runtime = _resolve_runtime_agent_kwargs_for_provider("opencode-go", target_model="mimo-v2.5")
assert runtime["provider"] == "opencode-go"
assert runtime["base_url"] == "https://opencode.ai/zen/go/v1"
def test_fallback_chain_runtime_uses_the_entry_model(_zen_free_default_home, monkeypatch):
"""The gateway's AuthError fallback goes through the shared ``resolve_runtime_with_fallback``
walker (no gateway-private loop) and keeps the entry's own model."""
import gateway.run as gateway_run
import hermes_cli.runtime_provider as rp
from hermes_cli.auth import AuthError
real_resolve = rp.resolve_runtime_provider
def primary_auth_fails(**kw):
if kw.get("requested") is None: # the primary, resolved from config.yaml
raise AuthError("primary quota exhausted (429)")
return real_resolve(**kw)
monkeypatch.setattr(rp, "resolve_runtime_provider", primary_auth_fails)
monkeypatch.setattr(gateway_run, "_load_gateway_config",
lambda: {"fallback_model": [{"provider": "opencode-go", "model": "mimo-v2.5"}]})
fb = gateway_run._resolve_runtime_agent_kwargs()
assert fb["model"] == "mimo-v2.5"
assert fb["provider"] == "opencode-go"
assert fb["base_url"] == "https://opencode.ai/zen/go/v1"