mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-02 02:01:47 +00:00
fix(browser): avoid bogus Chrome launch fallback
Detect an actual Chrome/Chromium executable before printing a manual CDP launch command, including common WSL-mounted Windows browser paths, so /browser connect does not suggest google-chrome when it is unavailable.
This commit is contained in:
parent
f10a3df632
commit
69ff114ee2
5 changed files with 69 additions and 24 deletions
8
cli.py
8
cli.py
|
|
@ -6630,8 +6630,12 @@ class HermesCLI:
|
|||
else:
|
||||
print(" ⚠ Could not auto-launch Chrome")
|
||||
sys_name = _plat.system()
|
||||
print(f" Launch Chrome manually:")
|
||||
print(f" {manual_chrome_debug_command(_port, sys_name)}")
|
||||
chrome_cmd = manual_chrome_debug_command(_port, sys_name)
|
||||
if chrome_cmd:
|
||||
print(f" Launch Chrome manually:")
|
||||
print(f" {chrome_cmd}")
|
||||
else:
|
||||
print(" No Chrome/Chromium executable found in this environment")
|
||||
else:
|
||||
print(f" ⚠ Port {_port} is not reachable at {cdp_url}")
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||
|
||||
import os
|
||||
import platform
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
|
|
@ -64,6 +65,14 @@ def get_chrome_debug_candidates(system: str) -> list[str]:
|
|||
"google-chrome", "google-chrome-stable", "chromium-browser",
|
||||
"chromium", "brave-browser", "microsoft-edge",
|
||||
)
|
||||
for base in ("/mnt/c/Program Files", "/mnt/c/Program Files (x86)"):
|
||||
for parts in (
|
||||
("Google", "Chrome", "Application", "chrome.exe"),
|
||||
("Chromium", "Application", "chrome.exe"),
|
||||
("BraveSoftware", "Brave-Browser", "Application", "brave.exe"),
|
||||
("Microsoft", "Edge", "Application", "msedge.exe"),
|
||||
):
|
||||
add(os.path.join(base, *parts))
|
||||
|
||||
return candidates
|
||||
|
||||
|
|
@ -72,27 +81,29 @@ def chrome_debug_data_dir() -> str:
|
|||
return str(get_hermes_home() / "chrome-debug")
|
||||
|
||||
|
||||
def manual_chrome_debug_command(port: int = DEFAULT_BROWSER_CDP_PORT, system: str | None = None) -> str:
|
||||
def _chrome_debug_args(port: int) -> list[str]:
|
||||
return [
|
||||
f"--remote-debugging-port={port}",
|
||||
f"--user-data-dir={chrome_debug_data_dir()}",
|
||||
"--no-first-run",
|
||||
"--no-default-browser-check",
|
||||
]
|
||||
|
||||
|
||||
def manual_chrome_debug_command(port: int = DEFAULT_BROWSER_CDP_PORT, system: str | None = None) -> str | None:
|
||||
system = system or platform.system()
|
||||
data_dir = chrome_debug_data_dir()
|
||||
candidates = get_chrome_debug_candidates(system)
|
||||
if candidates:
|
||||
return " ".join(shlex.quote(part) for part in [candidates[0], *_chrome_debug_args(port)])
|
||||
|
||||
if system == "Darwin":
|
||||
return (
|
||||
'open -a "Google Chrome" --args'
|
||||
f" --remote-debugging-port={port}"
|
||||
f' --user-data-dir="{data_dir}"'
|
||||
f' --user-data-dir="{chrome_debug_data_dir()}"'
|
||||
" --no-first-run --no-default-browser-check"
|
||||
)
|
||||
if system == "Windows":
|
||||
return (
|
||||
f"chrome.exe --remote-debugging-port={port}"
|
||||
f' --user-data-dir="{data_dir}"'
|
||||
" --no-first-run --no-default-browser-check"
|
||||
)
|
||||
return (
|
||||
f"google-chrome --remote-debugging-port={port}"
|
||||
f' --user-data-dir="{data_dir}"'
|
||||
" --no-first-run --no-default-browser-check"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def try_launch_chrome_debug(port: int = DEFAULT_BROWSER_CDP_PORT, system: str | None = None) -> bool:
|
||||
|
|
@ -105,10 +116,7 @@ def try_launch_chrome_debug(port: int = DEFAULT_BROWSER_CDP_PORT, system: str |
|
|||
subprocess.Popen(
|
||||
[
|
||||
candidates[0],
|
||||
f"--remote-debugging-port={port}",
|
||||
f"--user-data-dir={chrome_debug_data_dir()}",
|
||||
"--no-first-run",
|
||||
"--no-default-browser-check",
|
||||
*_chrome_debug_args(port),
|
||||
],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import os
|
|||
from unittest.mock import patch
|
||||
|
||||
from cli import HermesCLI
|
||||
from hermes_cli.browser_connect import manual_chrome_debug_command
|
||||
|
||||
|
||||
def _assert_chrome_debug_cmd(cmd, expected_chrome, expected_port):
|
||||
|
|
@ -55,3 +56,26 @@ class TestChromeDebugLaunch:
|
|||
assert HermesCLI._try_launch_chrome_debug(9222, "Windows") is True
|
||||
|
||||
_assert_chrome_debug_cmd(captured["cmd"], installed, 9222)
|
||||
|
||||
def test_manual_command_uses_detected_linux_browser(self):
|
||||
with patch("hermes_cli.browser_connect.shutil.which", side_effect=lambda name: "/usr/bin/chromium" if name == "chromium" else None), \
|
||||
patch("hermes_cli.browser_connect.os.path.isfile", side_effect=lambda path: path == "/usr/bin/chromium"):
|
||||
command = manual_chrome_debug_command(9222, "Linux")
|
||||
|
||||
assert command is not None
|
||||
assert command.startswith("/usr/bin/chromium --remote-debugging-port=9222")
|
||||
|
||||
def test_manual_command_uses_wsl_windows_chrome_when_available(self):
|
||||
chrome = "/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
|
||||
|
||||
with patch("hermes_cli.browser_connect.shutil.which", return_value=None), \
|
||||
patch("hermes_cli.browser_connect.os.path.isfile", side_effect=lambda path: path == chrome):
|
||||
command = manual_chrome_debug_command(9222, "Linux")
|
||||
|
||||
assert command is not None
|
||||
assert command.startswith(f"'{chrome}' --remote-debugging-port=9222")
|
||||
|
||||
def test_manual_command_returns_none_when_linux_browser_missing(self):
|
||||
with patch("hermes_cli.browser_connect.shutil.which", return_value=None), \
|
||||
patch("hermes_cli.browser_connect.os.path.isfile", return_value=False):
|
||||
assert manual_chrome_debug_command(9222, "Linux") is None
|
||||
|
|
|
|||
|
|
@ -2904,14 +2904,15 @@ def test_browser_manage_connect_default_local_reports_launch_hint(monkeypatch):
|
|||
)
|
||||
with patch.dict(sys.modules, {"tools.browser_tool": fake}):
|
||||
_stub_urlopen(monkeypatch, ok=False)
|
||||
with patch("hermes_cli.browser_connect.try_launch_chrome_debug", return_value=False):
|
||||
with patch("hermes_cli.browser_connect.try_launch_chrome_debug", return_value=False), \
|
||||
patch("hermes_cli.browser_connect.get_chrome_debug_candidates", return_value=[]):
|
||||
resp = server.handle_request(
|
||||
{"id": "1", "method": "browser.manage", "params": {"action": "connect"}}
|
||||
)
|
||||
|
||||
assert resp["error"]["code"] == 5031
|
||||
assert "Start Chrome with remote debugging" in resp["error"]["message"]
|
||||
assert "google-chrome --remote-debugging-port=9222" in resp["error"]["message"]
|
||||
assert "No Chrome/Chromium executable was found" in resp["error"]["message"]
|
||||
assert "--remote-debugging-port=9222" in resp["error"]["message"]
|
||||
assert "BROWSER_CDP_URL" not in os.environ
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4762,10 +4762,18 @@ def _is_default_local_cdp(parsed) -> bool:
|
|||
def _browser_connect_error(url: str, port: int) -> str:
|
||||
from hermes_cli.browser_connect import manual_chrome_debug_command
|
||||
|
||||
command = manual_chrome_debug_command(port)
|
||||
if not command:
|
||||
return (
|
||||
f"Chrome is not reachable at {url}. "
|
||||
"No Chrome/Chromium executable was found in this environment; "
|
||||
f"install one or start Chrome with --remote-debugging-port={port}, then retry /browser connect."
|
||||
)
|
||||
|
||||
return (
|
||||
f"Chrome is not reachable at {url}. "
|
||||
"Start Chrome with remote debugging, then retry /browser connect:\n"
|
||||
f"{manual_chrome_debug_command(port)}"
|
||||
f"{command}"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue