revert(browser_exec): drop pending_dialogs from results

Live probe: browser-harness tracks native dialogs in its own daemon
(Page.javascriptDialogOpening on its own target session) and the task's CDP
supervisor never captured one on harness-driven pages, so the field had no
working source. browser_dialog's text now describes what it actually does:
answer a supervisor-held dialog, its error listing candidate ids.
This commit is contained in:
Teknium committed 2026-10-23 01:41:24 -07:00
1 parent d34d78523d
commit e9bdd57dbc
3 files changed
+7 -22

No files matched your search

+6 -7
View File
@@ -1,7 +1,7 @@
"""Agent-facing tool: respond to a native JS dialog captured by the CDP supervisor.
Response-only: the agent reads ``pending_dialogs`` from a ``browser_exec`` result,
then calls ``browser_dialog(action=...)``. Gated on ``_browser_cdp_check`` so it
Response-only: the agent calls ``browser_dialog(action=...)`` for a dialog the
supervisor holds; with several queued, the error names the candidate ids. Gated on ``_browser_cdp_check`` so it
appears together with ``browser_cdp``. Design: ``website/docs/developer-guide/browser-supervisor.md``.
"""
@@ -18,15 +18,14 @@ BROWSER_DIALOG_SCHEMA: dict[str, Any] = {
"description": (
"Respond to a native JavaScript dialog (alert / confirm / prompt / "
"beforeunload) that is currently blocking the page.\n\n"
"**Workflow:** when a dialog is open, the browser_exec result lists "
"it in the ``pending_dialogs`` field with ``id``, ``type``, "
"and ``message``. Then call this tool with ``action='accept'`` or "
"**Workflow:** when a page is blocked by a native dialog the CDP "
"supervisor captured, call this tool with ``action='accept'`` or "
"``action='dismiss'``.\n\n"
"**Prompt dialogs:** pass ``prompt_text`` to supply the response "
"string. Ignored for alert/confirm/beforeunload.\n\n"
"**Multiple dialogs:** if more than one dialog is queued (rare — "
"happens when a second dialog fires while the first is still open), "
"pass ``dialog_id`` from ``pending_dialogs`` to disambiguate.\n\n"
"pass ``dialog_id`` (the error lists the candidates) to disambiguate.\n\n"
"**Availability:** only present when a CDP endpoint is attached — "
"a local Chromium-family browser via ``/browser connect``, or "
"``browser.cdp_url`` in config.yaml."
@@ -55,7 +54,7 @@ BROWSER_DIALOG_SCHEMA: dict[str, Any] = {
"type": "string",
"description": (
"Specific dialog to respond to, from "
"``pending_dialogs[].id``. Required "
"the candidate ids a previous call listed. Required "
"only when multiple dialogs are queued."
),
},
+1 -1
View File
@@ -4,7 +4,7 @@ One ``CDPSupervisor`` per Hermes ``task_id`` with a reachable CDP endpoint: one
persistent WebSocket, ``Page`` / ``Runtime`` / ``Target`` events on every attached
session (top page + auto-attached OOPIF / worker targets), pending dialogs + frame
tree exposed via a thread-safe snapshot. Not in the tool schema — output reaches the
agent via ``browser_exec`` results (``pending_dialogs``) / ``browser_dialog``. Dialog capture and frame tracking
agent via ``browser_dialog``. Dialog capture and frame tracking
are mixins (``browser_supervisor_dialogs`` / ``browser_supervisor_frames``).
Design spec: ``website/docs/developer-guide/browser-supervisor.md``.
"""
-14
View File
@@ -666,19 +666,6 @@ def _reload_if_republished(env: dict, generation: int) -> None:
_reload_daemons([daemon])
def _pending_dialogs(task_id: Optional[str]) -> dict:
"""Native dialogs the task's CDP supervisor is holding open (``browser_dialog`` answers them), page text
redacted like every other browser output."""
from agent.redact import redact_sensitive_text
from tools.browser_supervisor import SUPERVISOR_REGISTRY
supervisor = SUPERVISOR_REGISTRY.get(task_id or "default")
snapshot = supervisor.snapshot() if supervisor is not None else None
if snapshot is None or not snapshot.active or not snapshot.pending_dialogs:
return {}
return {"pending_dialogs": [{k: redact_sensitive_text(v, force=True) if isinstance(v, str) else v
for k, v in d.to_dict().items()} for d in snapshot.pending_dialogs]}
def _take_real_profile_note(route_key: str) -> dict:
"""The fallback note for the first result this route returns after falling back, then nothing."""
if route_key not in _real_profile_fallback or route_key in _real_profile_note_delivered:
@@ -783,7 +770,6 @@ def browser_exec(code: str, session: str = "", timeout_s: int = _DEFAULT_TIMEOUT
if session:
result["session"] = session
result.update(_take_real_profile_note(route_key))
result.update(_pending_dialogs(task_id))
stderr = redact_sensitive_text((proc.stderr or "").strip(), force=True)
if len(stderr) > _STDERR_CAP_CHARS:
stderr = stderr[:_STDERR_CAP_CHARS] + "\n… (stderr truncated)"