From f7b71aa0daf4acd56dba7e9c6aee1aa8cfe477a1 Mon Sep 17 00:00:00 2001 From: Luciano Pacheco Date: Sun, 3 May 2026 23:02:23 +0000 Subject: [PATCH] fix: use configured model for gateway auth fallback --- gateway/run.py | 15 ++++- .../test_session_model_override_routing.py | 55 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/gateway/run.py b/gateway/run.py index fd89a8ea63..1728d58b1b 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -643,7 +643,11 @@ def _try_resolve_fallback_provider() -> dict | None: explicit_base_url=entry.get("base_url"), explicit_api_key=entry.get("api_key"), ) - logger.info("Fallback provider resolved: %s", runtime.get("provider")) + logger.info( + "Fallback provider resolved: %s model=%s", + runtime.get("provider"), + entry.get("model"), + ) return { "api_key": runtime.get("api_key"), "base_url": runtime.get("base_url"), @@ -652,6 +656,7 @@ def _try_resolve_fallback_provider() -> dict | None: "command": runtime.get("command"), "args": list(runtime.get("args") or []), "credential_pool": runtime.get("credential_pool"), + "model": entry.get("model"), } except Exception as fb_exc: logger.debug("Fallback entry %s failed: %s", entry.get("provider"), fb_exc) @@ -1661,6 +1666,14 @@ class GatewayRunner: ) runtime_kwargs = _resolve_runtime_agent_kwargs() + runtime_model = runtime_kwargs.pop("model", None) + if runtime_model: + logger.info( + "Runtime provider supplied explicit model override: %s -> %s", + model, + runtime_model, + ) + model = runtime_model if override and resolved_session_key: model, runtime_kwargs = self._apply_session_model_override( resolved_session_key, model, runtime_kwargs diff --git a/tests/gateway/test_session_model_override_routing.py b/tests/gateway/test_session_model_override_routing.py index edada059da..3530744e22 100644 --- a/tests/gateway/test_session_model_override_routing.py +++ b/tests/gateway/test_session_model_override_routing.py @@ -163,3 +163,58 @@ async def test_background_task_prefers_session_override_over_global_runtime(monk assert _CapturingAgent.last_init["base_url"] == "https://chatgpt.com/backend-api/codex" assert _CapturingAgent.last_init["api_key"] == "***" assert _CapturingAgent.last_init["reasoning_config"] == {"enabled": True, "effort": "high"} + +def test_gateway_auth_fallback_uses_fallback_model_from_config(tmp_path, monkeypatch): + """Regression: fallback provider must not inherit the primary model. + + If primary openai-codex auth fails and fallback_providers selects + OpenRouter/minimax, the gateway must instantiate AIAgent with the fallback + model, not the primary config model (e.g. gpt-5.5). Otherwise OpenRouter + receives an unintended GPT request. + """ + config = tmp_path / "config.yaml" + config.write_text( + """ +model: + default: gpt-5.5 + provider: openai-codex +fallback_providers: + - provider: openrouter + model: minimax/minimax-m2.7 +""".lstrip(), + encoding="utf-8", + ) + monkeypatch.setattr(gateway_run, "_hermes_home", tmp_path) + + def fake_resolve_runtime_provider(*, requested=None, explicit_base_url=None, explicit_api_key=None): + if requested in (None, "", "openai-codex"): + from hermes_cli.auth import AuthError + raise AuthError("No Codex credentials stored. Run `hermes auth` to authenticate.") + assert requested == "openrouter" + return { + "api_key": "sk-openrouter", + "base_url": "https://openrouter.ai/api/v1", + "provider": "openrouter", + "api_mode": "chat_completions", + "command": None, + "args": [], + "credential_pool": None, + } + + import hermes_cli.runtime_provider as runtime_provider + + monkeypatch.setattr(runtime_provider, "resolve_runtime_provider", fake_resolve_runtime_provider) + + runner = _make_runner() + model, runtime_kwargs = runner._resolve_session_agent_runtime( + session_key="agent:main:telegram:group:-1003715515980:63", + user_config={ + "model": {"default": "gpt-5.5", "provider": "openai-codex"}, + "fallback_providers": [{"provider": "openrouter", "model": "minimax/minimax-m2.7"}], + }, + ) + + assert model == "minimax/minimax-m2.7" + assert runtime_kwargs["provider"] == "openrouter" + assert runtime_kwargs["api_key"] == "sk-openrouter" +