Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions hermes_cli/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,33 @@ def _has_provider_env_config(content: str) -> bool:
return any(key in content for key in _PROVIDER_ENV_HINTS)


def _honcho_is_configured_for_doctor() -> bool:
"""Return True when Honcho is configured, even if this process has no active session."""
try:
from honcho_integration.client import HonchoClientConfig

cfg = HonchoClientConfig.from_global_config()
return bool(cfg.enabled and cfg.api_key)
except Exception:
return False


def _apply_doctor_tool_availability_overrides(available: list[str], unavailable: list[dict]) -> tuple[list[str], list[dict]]:
"""Adjust runtime-gated tool availability for doctor diagnostics."""
if not _honcho_is_configured_for_doctor():
return available, unavailable

updated_available = list(available)
updated_unavailable = []
for item in unavailable:
if item.get("name") == "honcho":
if "honcho" not in updated_available:
updated_available.append("honcho")
continue
updated_unavailable.append(item)
return updated_available, updated_unavailable


def check_ok(text: str, detail: str = ""):
print(f" {color('✓', Colors.GREEN)} {text}" + (f" {color(detail, Colors.DIM)}" if detail else ""))

Expand Down Expand Up @@ -582,6 +609,7 @@ def run_doctor(args):
from model_tools import check_tool_availability, TOOLSET_REQUIREMENTS

available, unavailable = check_tool_availability()
available, unavailable = _apply_doctor_tool_availability_overrides(available, unavailable)

for tid in available:
info = TOOLSET_REQUIREMENTS.get(tid, {})
Expand Down
50 changes: 50 additions & 0 deletions tests/hermes_cli/test_doctor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Tests for hermes doctor helpers."""

from types import SimpleNamespace

import hermes_cli.doctor as doctor
from hermes_cli.doctor import _has_provider_env_config


Expand All @@ -15,3 +18,50 @@ def test_detects_custom_endpoint_without_openrouter_key(self):
def test_returns_false_when_no_provider_settings(self):
content = "TERMINAL_ENV=local\n"
assert not _has_provider_env_config(content)


class TestDoctorToolAvailabilityOverrides:
def test_marks_honcho_available_when_configured(self, monkeypatch):
monkeypatch.setattr(doctor, "_honcho_is_configured_for_doctor", lambda: True)

available, unavailable = doctor._apply_doctor_tool_availability_overrides(
[],
[{"name": "honcho", "env_vars": [], "tools": ["query_user_context"]}],
)

assert available == ["honcho"]
assert unavailable == []

def test_leaves_honcho_unavailable_when_not_configured(self, monkeypatch):
monkeypatch.setattr(doctor, "_honcho_is_configured_for_doctor", lambda: False)

honcho_entry = {"name": "honcho", "env_vars": [], "tools": ["query_user_context"]}
available, unavailable = doctor._apply_doctor_tool_availability_overrides(
[],
[honcho_entry],
)

assert available == []
assert unavailable == [honcho_entry]


class TestHonchoDoctorConfigDetection:
def test_reports_configured_when_enabled_with_api_key(self, monkeypatch):
fake_config = SimpleNamespace(enabled=True, api_key="honcho-test-key")

monkeypatch.setattr(
"honcho_integration.client.HonchoClientConfig.from_global_config",
lambda: fake_config,
)

assert doctor._honcho_is_configured_for_doctor()

def test_reports_not_configured_without_api_key(self, monkeypatch):
fake_config = SimpleNamespace(enabled=True, api_key=None)

monkeypatch.setattr(
"honcho_integration.client.HonchoClientConfig.from_global_config",
lambda: fake_config,
)

assert not doctor._honcho_is_configured_for_doctor()
Loading