diff --git a/contributors/emails/azureuser@Main.n1l05aasmpie5onxhehb5y5gra.lx.internal.cloudapp.net b/contributors/emails/azureuser@Main.n1l05aasmpie5onxhehb5y5gra.lx.internal.cloudapp.net new file mode 100644 index 000000000000..17fc35d31a58 --- /dev/null +++ b/contributors/emails/azureuser@Main.n1l05aasmpie5onxhehb5y5gra.lx.internal.cloudapp.net @@ -0,0 +1 @@ +AgenticSpark diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 6dfaa1071764..b4c5e678d8a0 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -1817,18 +1817,32 @@ def run_doctor(args): # Hermes-managed node prefix, which isn't necessarily on PATH. Mirror # dep_ensure._has_hermes_agent_browser() so doctor and dep_ensure agree # on what "installed" means; otherwise doctor false-negatives (#53192). - _managed_ab = HERMES_HOME / "node" / "bin" / "agent-browser" - _legacy_ab = HERMES_HOME / "node_modules" / ".bin" / "agent-browser" + # Resolve with PATHEXT-aware ``shutil.which`` (not a bare is_file()) + # so Windows picks the executable ``.cmd`` shim — the same class of + # miss fixed for _has_agent_browser() in #73932. + def _which_in(directory) -> str | None: + try: + if not directory.is_dir(): + return None + return shutil.which("agent-browser", path=str(directory)) + except Exception: + return None + + _managed_ab = ( + _which_in(HERMES_HOME / "node" / "bin") + or _which_in(HERMES_HOME / "node") + ) + _legacy_ab = _which_in(HERMES_HOME / "node_modules" / ".bin") if agent_browser_path.exists(): check_ok("agent-browser (Node.js)", "(browser automation)") agent_browser_ok = True elif _which_ab and agent_browser_runnable(_which_ab): check_ok("agent-browser", "(browser automation)") agent_browser_ok = True - elif _managed_ab.is_file() and agent_browser_runnable(str(_managed_ab)): + elif _managed_ab and agent_browser_runnable(_managed_ab): check_ok("agent-browser", "(browser automation)") agent_browser_ok = True - elif _legacy_ab.is_file() and agent_browser_runnable(str(_legacy_ab)): + elif _legacy_ab and agent_browser_runnable(_legacy_ab): check_ok("agent-browser", "(browser automation)") agent_browser_ok = True elif _which_ab: diff --git a/tests/hermes_cli/test_doctor.py b/tests/hermes_cli/test_doctor.py index b2fe505f3bb6..29aa0f38cbc0 100644 --- a/tests/hermes_cli/test_doctor.py +++ b/tests/hermes_cli/test_doctor.py @@ -751,6 +751,7 @@ def _run_doctor_with_managed_agent_browser(monkeypatch, tmp_path, runnable): (home / "config.yaml").write_text("memory: {}\n", encoding="utf-8") managed_ab = home / "node" / "bin" / "agent-browser" managed_ab.write_text("#!/bin/sh\n", encoding="utf-8") + managed_ab.chmod(0o755) project = tmp_path / "project" project.mkdir(exist_ok=True) # no node_modules/agent-browser here @@ -759,12 +760,18 @@ def _run_doctor_with_managed_agent_browser(monkeypatch, tmp_path, runnable): monkeypatch.setattr(doctor_mod, "HERMES_HOME", home) monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", project) monkeypatch.setattr(doctor_mod, "_DHH", str(home)) - # node on PATH, agent-browser is NOT on PATH (only in the managed bin) - monkeypatch.setattr( - doctor_mod.shutil, - "which", - lambda cmd: "/usr/bin/node" if cmd in {"node", "npm"} else None, - ) + + # node on PATH, agent-browser is NOT on PATH (only in the managed bin). + # The managed-dir rung resolves via shutil.which(..., path=