fix(browser): stop stale cdp_url from stalling every startup by 10+ seconds

Tool-schema assembly at CLI/Desktop startup runs the browser-family
check_fns (browser, browser_cdp, browser_dialog, browser_vision). Each
of those gates called _get_cdp_override(), which resolves the configured
endpoint over HTTP (GET /json/version, timeout=10) — so a *stale*
browser.cdp_url pointing at a dead debug browser cost ~7 serial blocking
socket connects before the banner rendered. Measured on a real Windows
install with a dead http://[::1]:9222 config: 15.1s of an 18s launch,
with no warning or error — just mystery slowness. The value is easy to
leave behind: /browser connect writes a session-scoped env override, but
'hermes config set browser.cdp_url' persists forever while the debug
Chrome it pointed at dies on the next browser restart.

Split the helper:

- _get_cdp_override_raw() — returns the configured value (env var or
  config.yaml) with zero network I/O. Used by every is-it-configured
  gate: check_browser_requirements, _browser_cdp_check, _is_local_mode,
  _is_local_backend, _navigation_session_key, _should_inject_engine
  (via _is_local_mode), and the hermes doctor chromium-skip check.
- _get_cdp_override() — unchanged contract (raw + /json/version
  resolution), now only called on paths that are about to connect:
  session creation and the dialog-supervisor attach.

This follows the existing rule in check_browser_requirements ('do not
execute agent-browser --version here') and the browser.manage status
path, which already banned _get_cdp_override for exactly this reason
(test_browser_manage_status_does_not_call_get_cdp_override): schema
assembly must not perform blocking I/O.

A/B on the same machine, same dead endpoint: get_tool_definitions()
15.08s unpatched -> 1.89s patched, with browser_cdp/browser_dialog
still advertised (gate now keys off configuration, not reachability —
matching the documented lazy-supervisor contract in
_browser_dialog_check).

Adds a regression test asserting the browser_cdp check_fn never touches
the network.
This commit is contained in:
Teknium
2026-07-26 19:53:13 -07:00
parent c63be0daf7
commit 731aa0ccc9
6 changed files with 82 additions and 29 deletions
+19 -4
View File
@@ -561,21 +561,36 @@ def test_check_fn_false_when_no_cdp_url(monkeypatch):
import tools.browser_tool as bt
monkeypatch.setattr(bt, "check_browser_requirements", lambda: True)
monkeypatch.setattr(bt, "_get_cdp_override", lambda: "")
monkeypatch.setattr(bt, "_get_cdp_override_raw", lambda: "")
assert browser_cdp_tool._browser_cdp_check() is False
def test_check_fn_true_when_cdp_url_set(monkeypatch):
"""Gate opens as soon as a CDP URL is resolvable."""
"""Gate opens as soon as a CDP URL is configured (no network resolution)."""
import tools.browser_tool as bt
monkeypatch.setattr(bt, "check_browser_requirements", lambda: True)
monkeypatch.setattr(
bt, "_get_cdp_override", lambda: "ws://localhost:9222/devtools/browser/x"
bt, "_get_cdp_override_raw", lambda: "ws://localhost:9222/devtools/browser/x"
)
assert browser_cdp_tool._browser_cdp_check() is True
def test_check_fn_does_not_probe_network(monkeypatch):
"""The availability gate must never hit the network: a stale/unreachable
configured endpoint used to cost multiple blocking HTTP probes at every
CLI/Desktop startup (tool-schema assembly), stalling launch by 10+ s."""
import tools.browser_tool as bt
def _boom(*a, **k): # pragma: no cover — the assertion is that it's unused
raise AssertionError("check_fn must not perform network I/O")
monkeypatch.setattr(bt, "check_browser_requirements", lambda: True)
monkeypatch.setattr(bt.requests, "get", _boom)
monkeypatch.setenv("BROWSER_CDP_URL", "http://127.0.0.1:9222")
assert browser_cdp_tool._browser_cdp_check() is True
def test_check_fn_false_when_browser_requirements_fail(monkeypatch):
"""Even with a CDP URL, gate closes if the overall browser toolset is
unavailable (e.g. agent-browser not installed)."""
@@ -583,6 +598,6 @@ def test_check_fn_false_when_browser_requirements_fail(monkeypatch):
monkeypatch.setattr(bt, "check_browser_requirements", lambda: False)
monkeypatch.setattr(
bt, "_get_cdp_override", lambda: "ws://localhost:9222/devtools/browser/x"
bt, "_get_cdp_override_raw", lambda: "ws://localhost:9222/devtools/browser/x"
)
assert browser_cdp_tool._browser_cdp_check() is False