feat(browser): deterministic private_browser lifecycle (Wave 5A)

Own each agent-browser session as a browser tree: the daemon's POSIX
session, its runtime files and its Chrome profile. Timeouts, launch
failures, bootstrap recovery, cancellation and shutdown clean that tree
and verify nothing survives, instead of killing only the daemon and
orphaning Chrome. Per-call cleanup no longer sweeps every Chrome under
the runtime TMPDIR.

Sessionless calls get an ephemeral browser closed before returning.
Actions on one session are serialized. Recovery is bounded by one
deadline with at most one retry for local HTML open, and the retry flag
is no longer model-visible. Observations after a failed navigation are
marked stale. read URL navigates and extracts in one batch because
agent-browser has no read command. Results carry a browser_lifecycle
receipt with stages, timings, ownership and cleanup evidence.

Playwright MCP tool calls are bounded by
ODYSSEUS_BROWSER_MCP_CALL_TIMEOUT_S and are not retried. research_navigator
now passes timeout_ms.
This commit is contained in:
Alexandre Teixeira
2026-10-01 20:59:27 +01:00
parent cb5b81022b
commit 576abb012d
9 changed files with 1552 additions and 78 deletions
+5
View File
@@ -557,6 +557,11 @@ VARIABLE_NOTES: dict[str, tuple[str, str, str]] = {
"Cache directory handed to the browser MCP server, so its npm download "
"survives a container rebuild.",
),
"ODYSSEUS_BROWSER_MCP_CALL_TIMEOUT_S": (
"Browser automation", USER,
"Upper bound in seconds for one browser MCP tool call. A call that exceeds "
"it fails without being retried.",
),
"ODYSSEUS_BROWSER_MCP_REQUIRE_CACHE": (
"Browser automation", USER,
"Truthy refuses to start the browser MCP server unless its npm package is "