From 73df329214a89eddbd45b0fa84ee99aefa8aea30 Mon Sep 17 00:00:00 2001 From: worlldz <101180447+worlldz@users.noreply.github.com> Date: Fri, 15 May 2026 18:45:02 +0300 Subject: [PATCH] fix(doctor): flag missing credentials for active openrouter provider --- hermes_cli/doctor.py | 52 ++++++++++++++++++++------------- tests/hermes_cli/test_doctor.py | 42 ++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 6f036426fa..87043bc261 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -651,31 +651,41 @@ def run_doctor(args): # Check credentials for the configured provider. # Limit to API-key providers in PROVIDER_REGISTRY — other provider - # types (OAuth, SDK, openrouter/anthropic/custom/auto) have their - # own env-var checks elsewhere in doctor, and get_auth_status() - # returns a bare {logged_in: False} for anything it doesn't - # explicitly dispatch, which would produce false positives. - if runtime_provider and runtime_provider not in {"auto", "custom", "openrouter"}: + # types (OAuth, SDK, anthropic/custom/auto) have their own env-var + # checks elsewhere in doctor, and get_auth_status() returns a bare + # {logged_in: False} for anything it doesn't explicitly dispatch, + # which would produce false positives. + if runtime_provider and runtime_provider not in ("auto", "custom"): try: - from hermes_cli.auth import PROVIDER_REGISTRY, get_auth_status - pconfig = PROVIDER_REGISTRY.get(runtime_provider) - if pconfig and getattr(pconfig, "auth_type", "") == "api_key": - status = get_auth_status(runtime_provider) or {} + if runtime_provider == "openrouter": + from hermes_cli.config import get_env_value + configured = bool( - status.get("configured") - or status.get("logged_in") - or status.get("api_key") + str(get_env_value("OPENROUTER_API_KEY") or "").strip() + or str(get_env_value("OPENAI_API_KEY") or "").strip() ) - if not configured: - check_fail( - f"model.provider '{runtime_provider}' is set but no API key is configured", - "(check ~/.hermes/.env or run 'hermes setup')", - ) - issues.append( - f"No credentials found for provider '{runtime_provider}'. " - f"Run 'hermes setup' or set the provider's API key in {_DHH}/.env, " - f"or switch providers with 'hermes config set model.provider '" + else: + from hermes_cli.auth import PROVIDER_REGISTRY, get_auth_status + + pconfig = PROVIDER_REGISTRY.get(runtime_provider) + configured = True + if pconfig and getattr(pconfig, "auth_type", "") == "api_key": + status = get_auth_status(runtime_provider) or {} + configured = bool( + status.get("configured") + or status.get("logged_in") + or status.get("api_key") ) + if not configured: + check_fail( + f"model.provider '{runtime_provider}' is set but no API key is configured", + "(check ~/.hermes/.env or run 'hermes setup')", + ) + issues.append( + f"No credentials found for provider '{runtime_provider}'. " + f"Run 'hermes setup' or set the provider's API key in {_DHH}/.env, " + f"or switch providers with 'hermes config set model.provider '" + ) except Exception: pass diff --git a/tests/hermes_cli/test_doctor.py b/tests/hermes_cli/test_doctor.py index a5b058fe45..be8c35239b 100644 --- a/tests/hermes_cli/test_doctor.py +++ b/tests/hermes_cli/test_doctor.py @@ -477,6 +477,48 @@ def test_run_doctor_accepts_bare_custom_provider(monkeypatch, tmp_path): assert "model.provider 'custom' is not a recognised provider" not in out +def test_run_doctor_flags_missing_credentials_for_active_openrouter_provider(monkeypatch, tmp_path): + home = tmp_path / ".hermes" + home.mkdir(parents=True, exist_ok=True) + (home / "config.yaml").write_text( + "model:\n" + " provider: openrouter\n" + " default: openai/gpt-4.1-mini\n", + encoding="utf-8", + ) + + monkeypatch.setattr(doctor_mod, "HERMES_HOME", home) + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", tmp_path / "project") + monkeypatch.setattr(doctor_mod, "_DHH", str(home)) + (tmp_path / "project").mkdir(exist_ok=True) + + fake_model_tools = types.SimpleNamespace( + check_tool_availability=lambda *a, **kw: ([], []), + TOOLSET_REQUIREMENTS={}, + ) + monkeypatch.setitem(sys.modules, "model_tools", fake_model_tools) + monkeypatch.delenv("OPENROUTER_API_KEY", raising=False) + monkeypatch.delenv("OPENAI_API_KEY", raising=False) + + try: + from hermes_cli import auth as _auth_mod + + monkeypatch.setattr(_auth_mod, "get_nous_auth_status", lambda: {}) + monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) + monkeypatch.setattr(_auth_mod, "get_gemini_oauth_auth_status", lambda: {}) + monkeypatch.setattr(_auth_mod, "get_minimax_oauth_auth_status", lambda: {}) + except Exception: + pass + + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + doctor_mod.run_doctor(Namespace(fix=False)) + + out = buf.getvalue() + assert "model.provider 'openrouter' is set but no API key is configured" in out + assert "No credentials found for provider 'openrouter'." in out + + @pytest.mark.parametrize( ("provider", "default_model"), [