词元之母TOK.MOM - 平台充值汇率 1:1 即 1 人民币充值到账 1 美元,支持一个 Key 调用近 600+ 海内外模型,限时特价模型低至 1 折,欢迎上岸!
alert/confirm/prompt/beforeunload)和 iframe 是我们浏览器工具中最大的两个缺口:browser_dialog 包装器。该方案无法解决检测问题——它只是在 agent 已经(通过症状)知道对话框已打开时,提供了一个更简洁的 CDP 调用。已作为被取代方案关闭。https://example.com iframe 进行测试:| 后端 | 对话框检测 | 对话框响应 | 框架树 | OOPIF Runtime.evaluate(通过 browser_cdp(frame_id=...)) |
|---|---|---|---|---|
本地 Chrome(--remote-debugging-port)/ /browser connect | ✓ | ✓ 完整流程 | ✓ | ✓ |
| Browserbase | ✓(通过 bridge) | ✓ 完整流程(通过 bridge) | ✓ | ✓(document.title = "Example Domain" 已在真实跨域 iframe 上验证) |
| Camofox | ✗ 无 CDP(仅 REST) | ✗ | 通过 DOM 快照部分支持 | ✗ |
Page.handleJavaScriptDialog 无法跟上。为解决此问题,supervisor 通过 Page.addScriptToEvaluateOnNewDocument 注入一个 bridge 脚本,将 window.alert/confirm/prompt 覆盖为向魔法主机(hermes-dialog-bridge.invalid)发起的同步 XHR。Fetch.enable 在这些 XHR 触达网络之前将其拦截——对话框变成 supervisor 捕获的 Fetch.requestPaused 事件,respond_to_dialog 通过 Fetch.fulfillRequest 以 JSON 响应体完成请求,注入的脚本对其进行解码。prompt() 仍然返回 agent 提供的字符串。从 agent 角度看,无论哪种方式,都是同一套 browser_dialog(action=...) API。已针对真实 Browserbase 会话进行端到端测试——4/4(alert/prompt/confirm-accept/confirm-dismiss)全部通过,包括值回传到页面 JS 的验证。jo-inc/camofox-browser 提交上游 issue,请求添加对话框轮询端点。task_id 对应一个在后台守护线程中运行的 asyncio.Task。持有一个到后端 CDP 端点的持久 WebSocket 连接。维护:List[PendingDialog],包含 {id, type, message, default_prompt, session_id, opened_at}Dict[frame_id, FrameInfo],包含父子关系、URL、origin,以及是否为跨域子会话Dict[session_id, SessionInfo],供交互工具将操作路由到正确的已附加会话以执行 OOPIF 操作Page.enable — javascriptDialogOpening、frameAttached、frameNavigated、frameDetachedRuntime.enable — executionContextCreated、consoleAPICalled、exceptionThrownTarget.setAutoAttach {autoAttach: true, flatten: true} — 暴露子 OOPIF target;supervisor 在每个上启用 Page+RuntimeSupervisorRegistry.get_or_start(task_id, cdp_url) — 由 browser_navigate、Browserbase 会话创建、/browser connect 调用。幂等。/browser disconnect。取消 asyncio task,关闭 WebSocket,丢弃状态。config.yaml 中的 browser.dialog_policy 配置:must_respond(默认)— 捕获,在 browser_snapshot 中呈现,等待显式的 browser_dialog(action=...) 调用。在 300s 安全超时后若无响应,则自动关闭并记录日志。防止有缺陷的 agent 永久挂起。auto_dismiss — 记录并立即关闭;agent 事后通过 browser_snapshot 内的 browser_state 查看。auto_accept — 记录并接受(适用于用户希望干净导航离开时的 beforeunload)。browser_dialog(action, prompt_text=None, dialog_id=None)action="accept" / "dismiss" → 响应指定的或唯一待处理的对话框(必填)prompt_text=... → 向 prompt() 对话框提供的文本dialog_id=... → 当多个对话框排队时用于消歧(罕见)browser_snapshot 输出中读取待处理对话框。browser_snapshot 扩展{
"pending_dialogs": [
{"id": "d-1", "type": "alert", "message": "Hello", "opened_at": 1650000000.0}
],
"recent_dialogs": [
{"id": "d-1", "type": "alert", "message": "...", "opened_at": 1650000000.0,
"closed_at": 1650000000.1, "closed_by": "remote"}
],
"frame_tree": {
"top": {"frame_id": "FRAME_A", "url": "https://example.com/", "origin": "https://example.com"},
"children": [
{"frame_id": "FRAME_B", "url": "about:srcdoc", "is_oopif": false},
{"frame_id": "FRAME_C", "url": "https://ads.example.net/", "is_oopif": true, "session_id": "SID_C"}
],
"truncated": false
}
}pending_dialogs:当前阻塞页面 JS 线程的对话框。Agent 必须调用 browser_dialog(action=...) 进行响应。在 Browserbase 上为空,因为其 CDP 代理会在约 10ms 内自动关闭对话框。recent_dialogs:最近关闭的最多 20 个对话框的环形缓冲区,带有 closed_by 标签——"agent"(我们响应了)、"auto_policy"(本地 auto_dismiss/auto_accept)、"watchdog"(must_respond 超时触发)或 "remote"(浏览器/后端主动关闭,例如 Browserbase)。这是 Browserbase 上的 agent 仍能了解发生了什么的方式。frame_tree:框架结构,包括跨域(OOPIF)子框架。上限为 30 条 + OOPIF 深度 2,以限制广告密集页面上的快照大小。当达到限制时,truncated: true 会出现;需要完整树的 agent 可使用 browser_cdp 配合 Page.getFrameTree。_browser_cdp_check 进行门控(supervisor 只能在 CDP 端点可达时运行)。在 Camofox / 无后端会话中,对话框工具被隐藏,快照省略新字段——不产生 schema 膨胀。browser_cdp(frame_id=...) 通过 supervisor 已连接的 WebSocket,使用 OOPIF 的子 sessionId 路由 CDP 调用(尤其是 Runtime.evaluate)。Agent 从 browser_snapshot.frame_tree.children[] 中 is_oopif=true 的条目获取 frame_id,并将其传递给 browser_cdp。对于同源 iframe(无专用 CDP 会话),agent 改用顶层 Runtime.evaluate 中的 contentWindow/contentDocument——当 frame_id 属于非 OOPIF 时,supervisor 会返回指向该回退方案的错误。browser_cdp 调用时打开)会遭遇签名 URL 过期,而 supervisor 的长连接则保持有效会话。jo-inc/camofox-browser 提交 issue,添加:page.on('dialog', handler)GET /tabs/:tabId/dialogs 轮询端点POST /tabs/:tabId/dialogs/:id 用于接受/关闭