diff --git a/tests/hermes_cli/test_doctor.py b/tests/hermes_cli/test_doctor.py index aae133a0eb59b..1897e8d5e27c7 100644 --- a/tests/hermes_cli/test_doctor.py +++ b/tests/hermes_cli/test_doctor.py @@ -411,140 +411,6 @@ def test_run_doctor_accepts_stable_key_when_provider_name_differs( assert "model.provider 'custom:local-127.0.0.1:11434' is unknown" not in out -def test_run_doctor_accepts_bare_custom_provider(monkeypatch, tmp_path): - home = tmp_path / ".hermes" - home.mkdir(parents=True, exist_ok=True) - (home / "config.yaml").write_text( - "model:\n" - " provider: custom\n" - " default: local-model\n" - " base_url: http://localhost:8000/v1\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) - - try: - from hermes_cli import auth as _auth_mod - monkeypatch.setattr(_auth_mod, "get_nous_auth_status_local", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_xai_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 '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_local", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_codex_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"), - [ - ("opencode-zen", "anthropic/claude-sonnet-4.6"), - ("kilocode", "anthropic/claude-sonnet-4.6"), - ("kimi-coding", "kimi-k2"), - ("nvidia", "qwen/qwen3.5-122b-a10b"), - ("moa", "anthropic/claude-sonnet-4.6"), - ], -) -def test_run_doctor_accepts_hermes_provider_ids_that_catalog_aliases( - monkeypatch, tmp_path, provider, default_model -): - home = tmp_path / ".hermes" - home.mkdir(parents=True, exist_ok=True) - (home / "config.yaml").write_text( - "model:\n" - f" provider: {provider}\n" - f" default: {default_model}\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) - - try: - from hermes_cli import auth as _auth_mod - monkeypatch.setattr(_auth_mod, "get_nous_auth_status_local", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_xai_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 f"model.provider '{provider}' is not a recognised provider" not in out - assert f"model.provider '{provider}' is unknown" not in out - if provider in {"opencode-zen", "kilocode", "nvidia"}: - assert ( - f"model.default '{default_model}' uses a vendor/model slug but provider is '{provider}'" - not in out - ) - - def test_run_doctor_accepts_vendor_slugs_for_named_custom_provider(monkeypatch, tmp_path): home = tmp_path / ".hermes" home.mkdir(parents=True, exist_ok=True) @@ -595,89 +461,6 @@ def test_run_doctor_accepts_vendor_slugs_for_named_custom_provider(monkeypatch, -def test_run_doctor_accepts_kimi_coding_cn_provider(monkeypatch, tmp_path): - home = tmp_path / ".hermes" - home.mkdir(parents=True, exist_ok=True) - (home / ".env").write_text("KIMI_CN_API_KEY=***\n", encoding="utf-8") - (home / "config.yaml").write_text( - "model:\n" - " provider: kimi-coding-cn\n" - " default: kimi-k2.6\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) - - try: - from hermes_cli import auth as _auth_mod - monkeypatch.setattr(_auth_mod, "get_nous_auth_status_local", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_auth_status", lambda provider: {"logged_in": True}) - monkeypatch.setattr(_auth_mod, "get_xai_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 'kimi-coding-cn' is not a recognised provider" not in out - - -def test_run_doctor_termux_does_not_mark_browser_available_without_agent_browser(monkeypatch, tmp_path): - home = tmp_path / ".hermes" - home.mkdir(parents=True, exist_ok=True) - (home / "config.yaml").write_text("memory: {}\n", encoding="utf-8") - project = tmp_path / "project" - project.mkdir(exist_ok=True) - - monkeypatch.setenv("TERMUX_VERSION", "0.118.3") - monkeypatch.setenv("PREFIX", "/data/data/com.termux/files/usr") - monkeypatch.setattr(doctor_mod, "HERMES_HOME", home) - monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", project) - monkeypatch.setattr(doctor_mod, "_DHH", str(home)) - monkeypatch.setattr(doctor_mod.shutil, "which", lambda cmd: "/data/data/com.termux/files/usr/bin/node" if cmd in {"node", "npm"} else None) - - fake_model_tools = types.SimpleNamespace( - check_tool_availability=lambda *a, **kw: (["terminal"], [{"name": "browser", "env_vars": [], "tools": ["browser_navigate"]}]), - TOOLSET_REQUIREMENTS={ - "terminal": {"name": "terminal"}, - "browser": {"name": "browser"}, - }, - ) - monkeypatch.setitem(sys.modules, "model_tools", fake_model_tools) - - try: - from hermes_cli import auth as _auth_mod - monkeypatch.setattr(_auth_mod, "get_nous_auth_status_local", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_codex_auth_status", lambda: {}) - monkeypatch.setattr(_auth_mod, "get_xai_oauth_auth_status", lambda: {}) - except Exception: - pass - - import io, contextlib - buf = io.StringIO() - with contextlib.redirect_stdout(buf): - doctor_mod.run_doctor(Namespace(fix=False)) - out = buf.getvalue() - - assert "✓ browser" not in out - assert "browser" in out - assert "system dependency not met" in out - assert "agent-browser is not installed (expected in the tested Termux path)" in out - assert "npm install -g agent-browser && agent-browser install" in out - - def _run_doctor_with_managed_agent_browser(monkeypatch, tmp_path, runnable): """Set up run_doctor with node present, agent-browser only in the Hermes-managed node bin (~/.hermes/node/bin), not on PATH or in