@xnng/browser-relay 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +445 -0
- package/docs/README.zh-CN.md +421 -0
- package/docs/benchmarks/browser-gaps-codex-ax.json +418 -0
- package/docs/benchmarks/browser-gaps-relay-after.json +655 -0
- package/docs/benchmarks/browser-gaps-relay-baseline.json +679 -0
- package/docs/benchmarks/browser-readiness-cost.json +106 -0
- package/docs/benchmarks/browser-runtime-balanced-headed.json +412 -0
- package/docs/benchmarks/browser-runtime-balanced-rtt50.json +412 -0
- package/docs/benchmarks/browser-runtime-balanced.json +412 -0
- package/docs/benchmarks/browser-runtime-rtt50.json +194 -0
- package/docs/benchmarks/browser-runtime.json +254 -0
- package/docs/benchmarks/browser-use-parity.json +54 -0
- package/docs/benchmarks/codex-extension-audit.json +131 -0
- package/docs/benchmarks/codex-native-protocol.md +69 -0
- package/docs/benchmarks/codex-native-replay.js +116 -0
- package/docs/benchmarks/codex-native-status.json +81 -0
- package/docs/benchmarks/codex-native.json +1003 -0
- package/docs/benchmarks/extension-sessions.png +0 -0
- package/docs/benchmarks/extension-tasks.png +0 -0
- package/docs/benchmarks/iframe-routing-regression.json +37 -0
- package/docs/browser-use-comparison.md +331 -0
- package/docs/browser-use-gap-audit.md +141 -0
- package/docs/browser-use-parity.md +105 -0
- package/docs/demo/intranet.html +103 -0
- package/docs/releases/v1.5.0.md +59 -0
- package/docs/releases/v1.5.1.md +16 -0
- package/docs/releases/v1.5.2.md +42 -0
- package/docs/releases/v1.5.3.md +33 -0
- package/docs/releases/v1.5.4.md +42 -0
- package/docs/releases/v1.6.0.md +16 -0
- package/docs/remote-control-hub.md +523 -0
- package/extension/activity.js +328 -0
- package/extension/automation.js +1839 -0
- package/extension/background.js +1854 -0
- package/extension/i18n.js +149 -0
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon32.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/manifest.json +47 -0
- package/extension/observations.js +109 -0
- package/extension/options.html +289 -0
- package/extension/options.js +269 -0
- package/extension/popup.html +74 -0
- package/extension/popup.js +105 -0
- package/extension/protocol.js +45 -0
- package/extension/remote-auth.js +18 -0
- package/extension/sessions.js +134 -0
- package/extension/snapshot.js +161 -0
- package/extension/task-groups.js +108 -0
- package/extension/tasks.js +186 -0
- package/extension/wait.js +89 -0
- package/hub/README.md +42 -0
- package/hub/package-lock.json +1544 -0
- package/hub/package.json +13 -0
- package/hub/src/rpc.js +41 -0
- package/hub/src/worker.js +322 -0
- package/hub/wrangler.example.toml +19 -0
- package/package.json +83 -0
- package/server/cdp-bridge.js +200 -0
- package/server/cli.js +1798 -0
- package/server/hub-server.js +258 -0
- package/server/install.js +250 -0
- package/server/mcp-server.js +504 -0
- package/server/npx-runner.js +96 -0
- package/server/relay-server.js +1356 -0
- package/server/remote-protocol.js +76 -0
- package/server/runtime-worker.js +166 -0
- package/server/script-runtime.js +189 -0
- package/server/sdk.js +307 -0
- package/server/service-state.js +103 -0
- package/server/snapshot.js +161 -0
- package/server/uninstall.js +61 -0
- package/server/windows-service-entry.js +58 -0
- package/server/windows-service.js +360 -0
- package/skills/browser-relay/SKILL.md +192 -0
- package/skills/browser-relay/references/legacy-api.md +163 -0
- package/skills/browser-relay/references/runtime.md +240 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"date": "2026-09-09",
|
|
3
|
+
"fixture": "tests/fixtures/automation.html",
|
|
4
|
+
"scope": "Isolated real Chromium/extension; three semantic clicks after reload. Investigative trace, not a timing benchmark.",
|
|
5
|
+
"before": {
|
|
6
|
+
"failedIterationZeroBased": 14,
|
|
7
|
+
"result": "Cross frame",
|
|
8
|
+
"parentPointerDown": {
|
|
9
|
+
"x": 412.296875,
|
|
10
|
+
"y": 468.53125,
|
|
11
|
+
"scrollY": 89
|
|
12
|
+
},
|
|
13
|
+
"childPointerEvents": [
|
|
14
|
+
{
|
|
15
|
+
"type": "pointerup",
|
|
16
|
+
"text": "Cross frame",
|
|
17
|
+
"x": 52.296875,
|
|
18
|
+
"y": 18.53125
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"childButtonRect": {
|
|
22
|
+
"x": 8,
|
|
23
|
+
"y": 8,
|
|
24
|
+
"width": 88.59375,
|
|
25
|
+
"height": 21
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"inference": "Parent scrolling updated geometry before the compositor routed a complete gesture to the child. Pointer down and up reached different documents; no child click was produced.",
|
|
29
|
+
"fix": "Wait for rendered frames after actual iframe-owner scrolling, before pointer dispatch. Do not resend a click.",
|
|
30
|
+
"after": {
|
|
31
|
+
"independentConsecutiveRuns": 15,
|
|
32
|
+
"successes": 15,
|
|
33
|
+
"regressionConsecutiveRuns": 20,
|
|
34
|
+
"regressionSuccesses": 20
|
|
35
|
+
},
|
|
36
|
+
"regression": "tests/browser-e2e.test.mjs: actions through shadow DOM and cross-origin frame"
|
|
37
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# Browser Relay 1.5 与 Codex Browser Use 对比
|
|
2
|
+
|
|
3
|
+
最新主对照见[差距审计](browser-use-gap-audit.md):按用户要求,以 Relay 自身接口和 Codex
|
|
4
|
+
Browser Use 原生 AX/截图/动作工作流比较复杂任务。本文保留此前的表单执行微基准和辅助路径数据,
|
|
5
|
+
不把内部 Playwright 分支作为整体 Browser Use 的代替。
|
|
6
|
+
|
|
7
|
+
核验日期:2026-09-09。实现提交 `42c5061`,基于远端主分支 `c9f394d` 开发。
|
|
8
|
+
|
|
9
|
+
已补齐图片工具输出、持久 JavaScript 会话、语义和坐标动作、跨进程 iframe、差量快照、
|
|
10
|
+
批量任务与取消,以及本地 Playwright/CDP 接入。最明显的收益来自减少 Agent—Relay—插件
|
|
11
|
+
链路上的逐步往返。9 月 9 日无头浏览器的严格对照中,相对于只读首尾状态的旧接口流程,新动作批次在
|
|
12
|
+
注入 50 ms 往返延迟时由 1702.35 ms 降至 394.4 ms,约快 4.32 倍;本机则由 254.1 ms
|
|
13
|
+
增至 288.05 ms,慢约 13.4%。首轮的 5.47 倍同时包含移除冗余观察的收益。
|
|
14
|
+
|
|
15
|
+
**Codex 原生同题测试已完成。** 用户安装官方扩展后,使用 CUA 连接原生 Chrome 扩展,
|
|
16
|
+
AX 单步、AX 批量、原生 Playwright 各跑 5 次,15 次均成功。中位耗时分别为 902、436、788 ms。
|
|
17
|
+
另补测相同视口的可见 Chromium,Relay actions 中位数 258.4 ms。这里计的是固定任务的内层
|
|
18
|
+
工具执行时间,不能当作整个 Codex 产品或 GPT-6 模型的端到端胜率。详见文末原生实测章节。
|
|
19
|
+
|
|
20
|
+
9 月 9 日增加了旧接口精简流程和轮换执行顺序,见下方补测。新结果应优先于首轮结果用于判断
|
|
21
|
+
接口本身的收益;不能把 5.47 倍直接归因于新执行器,也不能宣称相对旧接口在本机普遍存在加速。
|
|
22
|
+
|
|
23
|
+
## 核验材料与借鉴范围
|
|
24
|
+
|
|
25
|
+
- 当前 `mcp__cua_repl` 返回的 API/工作流文档:持久 JS、AX 状态差量、索引动作、批量动作后观察。
|
|
26
|
+
- 本机官方 browser 插件包 `26.901.51231`:`docs/api.json`、`docs/accessibility.md`、
|
|
27
|
+
`docs/api-use-behavior.md`、`docs/tab-claiming-chrome.md`、`docs/capabilities/tab/cdp.md`、
|
|
28
|
+
`scripts/browser-client.mjs`。该包已经在本机,无需再次克隆。
|
|
29
|
+
- `browser-client.mjs` SHA-256:`b9b9bc2319d5ee6aa0b1e481d63bb2130d28102fc7c9080803ab5552185d9037`。
|
|
30
|
+
- `docs/api.json` SHA-256:`fc7966ffbc9010252ad3ea745e061068bec3919efff860a87e6013a38a7e277f`。
|
|
31
|
+
|
|
32
|
+
官方 Computer use 指南建议 GPT-6 使用持久代码执行环境,结合截图和短动作序列,仍支持
|
|
33
|
+
自定义函数/MCP 接口。本项目沿用自己的传输和登录态管理,把这些设计落实到执行器与工具层。
|
|
34
|
+
[官方指南](https://developers.openai.com/api/docs/guides/tools-computer-use)
|
|
35
|
+
|
|
36
|
+
异步工具调用与执行中修正属于模型/调用方协议。Relay 提供异步任务、结果查询和取消能力;
|
|
37
|
+
模型接收新要求不会自动撤回已执行的浏览器操作。
|
|
38
|
+
[异步工具](https://developers.openai.com/api/docs/guides/async-tool-calling)、
|
|
39
|
+
[执行中修正](https://developers.openai.com/api/docs/guides/steering)
|
|
40
|
+
|
|
41
|
+
## 能力对照
|
|
42
|
+
|
|
43
|
+
| 方面 | Codex 可核验接口/指导 | Browser Relay 1.5 |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| 状态读取 | AX 状态优先,支持差量 | Chrome AX 树、角色/名称/状态、引用、独立会话差量;截断不推进基线 |
|
|
46
|
+
| 元素定位 | AX 索引、Playwright 定位器 | ref、唯一 role/name、CSS、frameId;重复匹配报错,旧引用失效 |
|
|
47
|
+
| 复杂页面 | iframe、DOM/视觉操作 | 同源与跨进程 iframe、Shadow DOM;取不到的 frame 显式报告 |
|
|
48
|
+
| 图像 | 图片输出、坐标操作 | MCP image 内容块;PNG 尺寸解析、截图坐标映射、视口变化校验 |
|
|
49
|
+
| 执行效率 | 持久 JS,确定动作与观察合并 | MCP browser_exec / CLI repl 保留变量;act 在插件内连续执行并返回状态 |
|
|
50
|
+
| 交互动作 | click、drag、move、键盘、滚动等 | 单/双击、悬停、路径拖拽、输入/清空、选择/勾选、条件等待、容器滚动 |
|
|
51
|
+
| 中断 | 用户接管/中止后停止 | 按标签排队;任务查询/取消;插件弹窗取消;运行时超时重置并取消所属待执行任务 |
|
|
52
|
+
| 标签范围 | 显式选择/接管标签,匹配可见证据 | 显式 tabId、导航后 ref 失效、新建/关闭指定标签;保持已有登录态 |
|
|
53
|
+
| 开发接口 | 可选 CDP 能力和 Playwright 接口 | 本地 /cdp 虚拟会话;已测连接、定位、截图、新建、导航、关闭、断开后继续加载 |
|
|
54
|
+
| 远程机器 | 本次未实测 | 已用真实扩展 + 本地测试 Hub 验证新动作和取消;生产 Hub 未部署变更 |
|
|
55
|
+
| 桌面/其他能力 | 原生应用、剪贴板、文件对话框、WebMCP 等 | 仍聚焦 Chrome;未宣称这些额外能力与 Codex 完全等价 |
|
|
56
|
+
|
|
57
|
+
Playwright 接入保留用户默认上下文,禁止创建/销毁浏览器配置和调整共享窗口。
|
|
58
|
+
调试器自动附加不暂停新 iframe,断开连接不关闭用户浏览器。旧接口/原始 CDP 不应与同一标签上
|
|
59
|
+
正在运行的新动作组混用。页面动画可能改变元素位置,即使 URL/视口未变;坐标前仍须观察。
|
|
60
|
+
|
|
61
|
+
## 同题执行基准
|
|
62
|
+
|
|
63
|
+
任务:搜索 invoice,选择 Owner=Alice,勾选 Active only,提交并等待页面显示
|
|
64
|
+
`Found: invoice / alice / active`。每种方案都检查这个可见结果。
|
|
65
|
+
|
|
66
|
+
### 如何控制条件与计时
|
|
67
|
+
|
|
68
|
+
- 环境:macOS、Node v22.23.1、Playwright 1.63.0、Chromium 153.0.8010.12。
|
|
69
|
+
使用真实 Chromium 的 headless 模式和真实扩展,视口 1280 × 1000;并非浏览器模拟对象。
|
|
70
|
+
- 测试页:[automation.html](../tests/fixtures/automation.html)。四个表单操作后,页面固定延迟
|
|
71
|
+
120 ms 更新状态;这是已知的异步业务延迟,所有方案相同。页面没有外部业务服务器、登录或验证码。
|
|
72
|
+
- 每次测量前重新加载页面并置为当前页。浏览器启动、扩展连接、页面重载、Playwright 连接建立、
|
|
73
|
+
调试计数读取均不计入执行耗时;第一次实际观察起计时,最后一次结果快照返回后停止计时。
|
|
74
|
+
- 独立的最终 `#status` 文本断言在计时结束后运行,严格检查完整结果。提交后的等待及最后一次
|
|
75
|
+
快照在计时内。断言失败会让脚本退出,因此当前样本不能用于估计一般网页的成功率。
|
|
76
|
+
- 首轮每轮按旧 HTTP → 新 actions → Playwright 固定顺序执行,本机各 7 次、延迟各 5 次;
|
|
77
|
+
没有随机化,也没有排除专门的预热样本。后面的补测使用循环轮换顺序以减小位置偏差。
|
|
78
|
+
- 50 ms RTT 注入位置是 **Relay 与扩展之间**:本地 TCP 代理收发两个方向各延迟 25 ms。
|
|
79
|
+
Agent 与 HTTP 服务之间仍为本机连接,页面自身网络未加延迟。命令可流水执行,不能简单用
|
|
80
|
+
“命令数 × 50 ms”推算总时长。这不是公网弱网、丢包或带宽受限实验。
|
|
81
|
+
- 同一进程、同一个临时浏览器配置、同一测试页顺序执行。Playwright 客户端只在其方案运行期间
|
|
82
|
+
连接,避免其他方案被后台 CDP 流量影响。
|
|
83
|
+
|
|
84
|
+
### 每条路径到底做了什么
|
|
85
|
+
|
|
86
|
+
| 路径 | 可复核操作序列 | HTTP 次数 | 状态观察次数 |
|
|
87
|
+
| --- | --- | ---: | ---: |
|
|
88
|
+
| 旧 HTTP | 快照 → type → 快照 → eval 选择 Owner → 快照 → click 勾选 → 快照 → click 提交 → wait → 快照 | 10 | 5 |
|
|
89
|
+
| 旧 HTTP 精简,补测 | 快照 → type → eval 选择 Owner → click 勾选 → click 提交 → wait → 快照 | 7 | 2 |
|
|
90
|
+
| 新 actions | observe 获取 ref → actions 内 fill/select/check/click/wait,并返回最终状态差量 | 2 | 2 |
|
|
91
|
+
| Playwright 经 Relay | 初始 ariaSnapshot → fill → selectOption → check → click → waitFor → 最终 ariaSnapshot | WebSocket | 2 |
|
|
92
|
+
|
|
93
|
+
这里比较的是**已编写好的确定性工具执行路径**。旧方案使用已知 CSS,actions 从当轮快照
|
|
94
|
+
提取 ref,Playwright 使用已知语义定位器;没有让模型阅读三个不同 Skill 后自主决定动作。
|
|
95
|
+
旧接口的 eval 也能编写更大的 DOM 动作批次,但这可能改变原生输入事件语义,本次未作为完整替代方案测试。
|
|
96
|
+
|
|
97
|
+
### 9 月 8 日首轮结果
|
|
98
|
+
|
|
99
|
+
| 方案 | 完成次数 | 中位耗时 | HTTP 请求数 | Relay→插件命令数 | 快照文本总量 |
|
|
100
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
101
|
+
| 旧 HTTP 工作流,本机 | 7/7 | 273.5 ms | 10 | 39 | 2301 B |
|
|
102
|
+
| 新批量动作,本机 | 7/7 | 278.7 ms | 2 | 2 | 2202 B |
|
|
103
|
+
| Playwright 经 Relay CDP,本机 | 7/7 | 334.8 ms | 0 | 73 | 1425 B |
|
|
104
|
+
| 旧 HTTP 工作流,注入 50 ms RTT | 5/5 | 2205.6 ms | 10 | 38 | 2301 B |
|
|
105
|
+
| 新批量动作,注入 50 ms RTT | 5/5 | 403.0 ms | 2 | 2 | 2202 B |
|
|
106
|
+
| Playwright 经 Relay CDP,注入 50 ms RTT | 5/5 | 2465.1 ms | 0 | 70 | 1425 B |
|
|
107
|
+
|
|
108
|
+
所有数值取各次运行的中位数。HTTP 计数不包括 CDP WebSocket;命令数是逻辑请求数,并非 TCP
|
|
109
|
+
包数。文本量是 UTF-8 字节,不是 token。Playwright 的完整传输字节没有采集。
|
|
110
|
+
旧方案遵循原 Skill 的单步动作与快照流程,选项操作通过旧 eval 接口;新方案一次动作组完成。
|
|
111
|
+
|
|
112
|
+
新方案初始快照覆盖更多内容(iframe、Shadow DOM、引用与状态),完整 JSON 还包含任务与视口
|
|
113
|
+
元数据,因此不能据此声称所有返回体都更小。单次“新增一行”变化的快照由
|
|
114
|
+
1880 B 全量降为 160 B 差量。
|
|
115
|
+
|
|
116
|
+
慢链路实验使用真实 Chromium 和扩展,在本地 TCP 代理两个方向各注入 25 ms 延迟;
|
|
117
|
+
这是受控延迟实验,不代表生产互联网的真实 RTT。未运行模型推理,未计模型生成/思考耗时,
|
|
118
|
+
也没有估算模型任务成功率或 API 费用。
|
|
119
|
+
|
|
120
|
+
首轮逐次耗时,单位 ms;顺序与原始 JSON 的 iteration 一致:
|
|
121
|
+
|
|
122
|
+
| 条件 / 路径 | 逐次耗时 |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| 本机 / 旧 HTTP | 292.4, 274.7, 291.8, 270.2, 273.5, 269.7, 261.4 |
|
|
125
|
+
| 本机 / 新 actions | 278.7, 284.1, 265.9, 288.1, 269.7, 278.3, 280.1 |
|
|
126
|
+
| 本机 / Playwright | 293.0, 329.3, 338.5, 323.5, 338.4, 334.8, 342.5 |
|
|
127
|
+
| 50 ms RTT / 旧 HTTP | 2218.2, 2205.2, 2205.6, 2204.1, 2209.3 |
|
|
128
|
+
| 50 ms RTT / 新 actions | 411.1, 385.3, 403.0, 410.4, 382.9 |
|
|
129
|
+
| 50 ms RTT / Playwright | 2422.6, 2473.1, 2470.5, 2455.5, 2465.1 |
|
|
130
|
+
|
|
131
|
+
完整 JSON 返回体的本机中位数是旧 3521 B、新 3919 B,增加约 11.3%;快照文本总量
|
|
132
|
+
2301 → 2202 B 仅减少约 4.3%。新增一行的差量快照减少约 91.5%,是另一项局部实验,
|
|
133
|
+
不能替代整道任务的 token 节省数据。
|
|
134
|
+
|
|
135
|
+
- [本机原始样本](benchmarks/browser-runtime.json)
|
|
136
|
+
- [50 ms RTT 原始样本](benchmarks/browser-runtime-rtt50.json)
|
|
137
|
+
- [可复跑脚本](../scripts/benchmark-browser.mjs)
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm ci --ignore-scripts
|
|
141
|
+
npx playwright install chromium
|
|
142
|
+
npm test
|
|
143
|
+
npm run test:browser
|
|
144
|
+
npm run bench:browser
|
|
145
|
+
BROWSER_RELAY_BENCH_RUNS=5 BROWSER_RELAY_BENCH_RTT_MS=50 npm run bench:browser
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
测试使用临时 Chrome 配置、复制的扩展和随机端口,不操作用户日常浏览器或登录账号。
|
|
149
|
+
测试只替换扩展默认端口以连接隔离 Relay。截图、DOM 结果都来自真实浏览器;基础单元测试另有
|
|
150
|
+
模拟传输,以检查错误、字节边界、进程超时、任务顺序与取消。
|
|
151
|
+
|
|
152
|
+
### 9 月 9 日补测:精简旧流程并轮换顺序
|
|
153
|
+
|
|
154
|
+
为区分“减少冗余观察”和“插件内执行批次”的收益,增加 `legacy-minimal`:保留旧接口和相同动作,只移除三次中间快照。四种路径在每个网络条件下各执行 8 次;每轮将执行顺序向前轮换一位,每条路径在四个位置各出现两次。不是随机实验,也没有模型推理。
|
|
155
|
+
|
|
156
|
+
旧 API 工作流运行在当前 1.5 的兼容接口上,并未启动历史 1.4 二进制。因此这是同一实现中不同调用路径的对照,不是两个历史发布版本的全量 A/B。
|
|
157
|
+
|
|
158
|
+
| 条件 | 路径 | 完成 | 中位耗时 ms | 范围 ms | HTTP | 插件逻辑命令 | 快照 B | 完整 JSON B |
|
|
159
|
+
| --- | --- | ---: | ---: | --- | ---: | ---: | ---: | ---: |
|
|
160
|
+
| 本机 | 旧 HTTP,每步观察 | 8/8 | 262.1 | 257.1–285.9 | 10 | 39 | 2301 | 3522.0 |
|
|
161
|
+
| 本机 | 旧 HTTP,只观察首尾 | 8/8 | 254.1 | 245.5–261.8 | 7 | 30 | 926 | 1670.0 |
|
|
162
|
+
| 本机 | 新 actions 批量 | 8/8 | 288.1 | 262.3–293.1 | 2 | 2 | 2202 | 3918.5 |
|
|
163
|
+
| 本机 | Playwright 经 Relay CDP | 8/8 | 329.2 | 293.1–332.7 | WS | 73 | 1425 | 未采集 |
|
|
164
|
+
| 注入 50 ms RTT | 旧 HTTP,每步观察 | 8/8 | 2210.6 | 2197.0–2223.9 | 10 | 38 | 2301 | 3535.0 |
|
|
165
|
+
| 注入 50 ms RTT | 旧 HTTP,只观察首尾 | 8/8 | 1702.3 | 1696.5–1710.3 | 7 | 29 | 926 | 1671.5 |
|
|
166
|
+
| 注入 50 ms RTT | 新 actions 批量 | 8/8 | 394.4 | 379.0–405.6 | 2 | 2 | 2202 | 3923.5 |
|
|
167
|
+
| 注入 50 ms RTT | Playwright 经 Relay CDP | 8/8 | 2466.8 | 2433.5–2494.6 | WS | 70 | 1425 | 未采集 |
|
|
168
|
+
|
|
169
|
+
- 相对于精简旧流程,新方案本机耗时增加约 13.4%(多 33.9 ms);不能声称本机更快。
|
|
170
|
+
- 注入 50 ms RTT 后,新方案相对精简旧流程快 4.32 倍,时间减少约 76.8%。HTTP 从 7 降为 2,插件逻辑命令从 29 降为 2。
|
|
171
|
+
- 相对于精简旧流程,新方案快照 2202 B 大于 926 B,完整 JSON 也更大。两者包含的状态范围不同:新版覆盖 frame、Shadow DOM、引用和状态,不能按字节判断信息质量。
|
|
172
|
+
- 当前证据支持“中高延迟链路上批次执行有效”。并未证明新接口对所有短任务更省时、更省字节,更未证明比 Codex 原生快。
|
|
173
|
+
|
|
174
|
+
补测逐次耗时,单位 ms;各行按 iteration 排列,而非实际全局执行顺序:
|
|
175
|
+
|
|
176
|
+
| 条件 / 路径 | 逐次耗时 |
|
|
177
|
+
| --- | --- |
|
|
178
|
+
| 本机 / 旧 HTTP,每步观察 | 285.9, 262.6, 269.8, 257.1, 261.5, 268.4, 260.5, 257.9 |
|
|
179
|
+
| 本机 / 旧 HTTP,只观察首尾 | 252.4, 246.2, 254.4, 260.3, 245.5, 261.8, 260.1, 253.8 |
|
|
180
|
+
| 本机 / 新 actions 批量 | 276.4, 286.0, 290.1, 293.1, 292.1, 291.0, 262.3, 269.4 |
|
|
181
|
+
| 本机 / Playwright 经 Relay CDP | 293.1, 324.5, 328.0, 331.7, 332.7, 326.5, 330.4, 330.5 |
|
|
182
|
+
| 50 ms RTT / 旧 HTTP,每步观察 | 2215.4, 2197.0, 2198.7, 2214.3, 2223.9, 2199.9, 2214.2, 2207.0 |
|
|
183
|
+
| 50 ms RTT / 旧 HTTP,只观察首尾 | 1703.3, 1699.6, 1700.8, 1708.8, 1696.5, 1710.3, 1701.4, 1703.4 |
|
|
184
|
+
| 50 ms RTT / 新 actions 批量 | 401.5, 405.6, 379.0, 389.2, 387.6, 398.7, 390.1, 402.9 |
|
|
185
|
+
| 50 ms RTT / Playwright 经 Relay CDP | 2433.5, 2468.9, 2484.7, 2454.4, 2494.6, 2482.2, 2456.4, 2464.7 |
|
|
186
|
+
|
|
187
|
+
偶数样本的中位数取排序后中间两项的平均值,范围列保留最小值和最大值。原始 JSON 保留每次执行位置、耗时和计数。
|
|
188
|
+
|
|
189
|
+
- [补测本机原始数据](benchmarks/browser-runtime-balanced.json)
|
|
190
|
+
- [补测延迟原始数据](benchmarks/browser-runtime-balanced-rtt50.json)
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
BROWSER_RELAY_BENCH_SUITE=balanced BROWSER_RELAY_BENCH_RUNS=8 npm run bench:browser
|
|
194
|
+
BROWSER_RELAY_BENCH_SUITE=balanced BROWSER_RELAY_BENCH_RUNS=8 BROWSER_RELAY_BENCH_RTT_MS=50 npm run bench:browser
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
补测写入单独的 `browser-runtime-balanced*.json`,保留首轮原始文件。
|
|
198
|
+
|
|
199
|
+
## 提示词与 Skill
|
|
200
|
+
|
|
201
|
+
Skill 入口最初由 459 行缩减到 135 行;本轮补充已验证的行为后为 141 行,详细 SDK/HTTP 内容按需加载。执行提示词强调:
|
|
202
|
+
先获取当前状态;优先 ref/语义定位;合并已确定步骤;遇到未知页面或状态后观察;用一个可靠的
|
|
203
|
+
成功信号结束;不重复读取没有变化的快照;中止后不自动重启任务。
|
|
204
|
+
|
|
205
|
+
MCP 工具描述与运行时对象一致。`browser_exec` 是本地可信代码执行,独立进程提供超时、
|
|
206
|
+
重置与故障隔离,不是安全沙箱;HTTP/远程 Hub 没有任意本机 JS 执行入口。
|
|
207
|
+
Skill 安装会核验入口及所有参考文件,防止只复制 SKILL.md 后缺少 SDK 指南。
|
|
208
|
+
|
|
209
|
+
具体借鉴与未证明的部分:
|
|
210
|
+
|
|
211
|
+
| 从 Codex 学到的做法 | 在 Relay 的落点 | 证据与边界 |
|
|
212
|
+
| --- | --- | --- |
|
|
213
|
+
| 持久 JS 保留浏览器和标签句柄 | `server/script-runtime.js`、`runtime-worker.js`、CLI repl、MCP exec | 已测跨调用保留变量;尚未测模型实际减少多少输出 token |
|
|
214
|
+
| 一轮内合并确定动作,再观察 | 扩展 `automation.js` 批次执行、SDK act | 同题基准直接证明跨链路命令减少 |
|
|
215
|
+
| 默认 AX 与差量;需要视觉判断才截图 | observe、引用、每会话差量、图片输出 | 已测差量与坐标;尚未取得 Codex 原生截图编码、字节或耗时对照 |
|
|
216
|
+
| 用当前状态定位,失败后先重新观察 | 旧 ref 失效、重复语义目标报错、Skill 错误恢复规则 | 有真实浏览器场景验证;不代表模型在未知站点更少犯错 |
|
|
217
|
+
| 一个充分的成功信号就结束 | Skill 要求检查状态文本或业务结果 | 基准采用完整状态文本断言;未进行提示词 A/B 模型实验 |
|
|
218
|
+
| 文档按需加载,避免每轮塞全部 API | 简短入口与按需引用文件 | 行数下降不是 token 成本或任务完成时间的实测结论 |
|
|
219
|
+
|
|
220
|
+
所以,目前可以交付的是执行器能力、传输效率和工作流设计的改进。GPT-6 的视觉判断、任务规划、
|
|
221
|
+
网页泛化成功率、模型思考时间和费用,需要相同模型设置的独立 Agent 评测,不能由接口数量推导。
|
|
222
|
+
|
|
223
|
+
## Codex 原生实机对照:已完成
|
|
224
|
+
|
|
225
|
+
### 安装过程与已解决的阻塞
|
|
226
|
+
|
|
227
|
+
2026-09-09 早先按用户要求用 CUA 尝试安装官方扩展,遭遇以下问题。随后用户完成安装,
|
|
228
|
+
本会话成功连接 Chrome 扩展并执行测试。下表是历史诊断,不代表当前仍无法连接:
|
|
229
|
+
|
|
230
|
+
| 步骤 | 工具结果 | 可得结论 |
|
|
231
|
+
| --- | --- | --- |
|
|
232
|
+
| CUA 发现浏览器 | `browsers: []` | 安装前没有可用 Browser provider |
|
|
233
|
+
| CUA 打开 Codex 自身应用 | `Computer Use is not allowed to use the app 'com.openai.codex' for safety reasons.` | CUA 自身限制,不能代点该应用设置 |
|
|
234
|
+
| CUA 打开 Chrome,尝试两次 | `cgWindowNotFound` | 取不到可操作窗口;不能确认原因就是锁屏 |
|
|
235
|
+
| CUA 打开访达 | `cgWindowNotFound` | 问题也影响其他应用,安装界面未能打开 |
|
|
236
|
+
| 本地官方诊断脚本 | Default profile 没有可读 Preferences;扩展、native host 未检出 | 仅代表检查到的本地文件路径;不排除 CUA 桌面与文件系统或 profile 不一致 |
|
|
237
|
+
|
|
238
|
+
用户安装后 CUA 返回 Chrome extension provider,测试页可正常创建和操作。未尝试绕过 CUA 自身应用限制。
|
|
239
|
+
[官方安装说明](https://learn.chatgpt.com/docs/chrome-extension)
|
|
240
|
+
|
|
241
|
+
运行 `npm run bench:serve` 可启动同一测试页。完整的同题提示、计时边界、单步/批次流程、
|
|
242
|
+
失败样本处理及环境一致性要求见[原生测试协议](benchmarks/codex-native-protocol.md);
|
|
243
|
+
连接尝试保存在[机器可读状态记录](benchmarks/codex-native-status.json)。原生 Browser、
|
|
244
|
+
原生桌面 Computer Use、Playwright 经 Relay 必须分别标注,不能互相替代。
|
|
245
|
+
|
|
246
|
+
### 实际执行与计时口径
|
|
247
|
+
|
|
248
|
+
使用 `cua.createBrowserTab('chrome', fixtureUrl, ...)` 新建专用标签,浏览器视口实测为
|
|
249
|
+
1466 × 925。任务与 Relay 完全相同。通过原生 AX 返回的当前索引执行,绝不跨页面重载复用索引;
|
|
250
|
+
每次新试验读取完整初始 AX,后续采用默认差量,按新增、修改、删除的节点维护当前目标。
|
|
251
|
+
|
|
252
|
+
原生三条路径:
|
|
253
|
+
|
|
254
|
+
| 路径 | 操作 | 浏览器 API 次数 | 状态读取次数 |
|
|
255
|
+
| --- | --- | ---: | ---: |
|
|
256
|
+
| AX 单步观察 | getAXState;setValue Search + 状态;setValue Owner + 状态;setValue checkbox + 状态;click 提交 + 状态 | 9 | 5 |
|
|
257
|
+
| AX 批量 | getAXState;连续三个 setValue 和 click;最终 getAXState | 6 | 2 |
|
|
258
|
+
| 原生 Playwright | domSnapshot;fill、selectOption、check、click、waitFor 可见结果;domSnapshot | 7 | 2 |
|
|
259
|
+
|
|
260
|
+
AX 的状态读取已经等待到本题的 120 ms 异步结果,不额外插入固定 sleep。原生 Playwright
|
|
261
|
+
显式等待结果可见;两条路径都要求最后状态包含完整成功文本。
|
|
262
|
+
|
|
263
|
+
先做各一轮交互式探索:AX 单步 5 次外层 `js`,内层 API 累计 1190 ms,整轮经过 29552 ms。
|
|
264
|
+
后者包含模型决策、工具调度与会话间隔,并非纯浏览器耗时。探索时一次计时闭包因跨 REPL
|
|
265
|
+
重绑定记到了旧数组,批量汇总曾错误显示 0;原始逐操作记录可恢复为 390 ms。随后改为修改
|
|
266
|
+
固定日志对象,解决计时记录问题;两轮探索均不进入正式中位数。
|
|
267
|
+
|
|
268
|
+
正式数据采用**已验证流程的确定性脚本回放**。AX 两条路径各 5 次,先后顺序逐组交替,
|
|
269
|
+
每个 `js` 执行一组两条路径;原生 Playwright 随后另跑 5 次,未与 AX 随机交错。
|
|
270
|
+
这一步没有让模型在每次状态读取后重新规划,因此适合分析工具执行成本,不能当成 15 次独立模型任务。
|
|
271
|
+
记录每个 API 的开始、结束时间,以及重载之后到最终状态返回的脚本时间;外层工具耗时另列。
|
|
272
|
+
|
|
273
|
+
### 原生结果及可见浏览器 Relay 对照
|
|
274
|
+
|
|
275
|
+
Relay 补测使用隔离配置的可见 Chromium 153.0.8010.12,并设同样的 1466 × 925 视口。
|
|
276
|
+
四条 Relay 路径各跑 8 次,循环轮换顺序,32 次全部成功;未注入延迟。
|
|
277
|
+
|
|
278
|
+
| 实测路径 | 成功 | 内层执行中位 ms | 范围 ms | 状态文本 B |
|
|
279
|
+
| --- | ---: | ---: | --- | ---: |
|
|
280
|
+
| Codex 原生 AX 单步 | 5/5 | 902 | 860–915 | 3287 |
|
|
281
|
+
| Codex 原生 AX 批量 | 5/5 | 436 | 411–443 | 3178 |
|
|
282
|
+
| Codex 原生 Playwright | 5/5 | 788 | 763–816 | 1706 |
|
|
283
|
+
| Relay 旧 HTTP,每步观察,可见 Chromium | 8/8 | 265.25 | 见原始样本 | 2301 |
|
|
284
|
+
| Relay 旧 HTTP,只观察首尾,可见 Chromium | 8/8 | 262.95 | 见原始样本 | 926 |
|
|
285
|
+
| Relay actions,可见 Chromium | 8/8 | 258.4 | 见原始样本 | 2202 |
|
|
286
|
+
| Playwright 经 Relay CDP,可见 Chromium | 8/8 | 264.5 | 见原始样本 | 1425 |
|
|
287
|
+
|
|
288
|
+
原生逐轮脚本耗时,单位 ms:
|
|
289
|
+
|
|
290
|
+
- AX 单步:910, 902, 915, 900, 860。第 4 轮 API 累计 899 ms,另有 1 ms 脚本开销。
|
|
291
|
+
- AX 批量:413, 443, 411, 441, 436。
|
|
292
|
+
- 原生 Playwright:816, 813, 780, 788, 763。
|
|
293
|
+
|
|
294
|
+
原生 AX 合并动作后约快 **2.07 倍**,减少约 **51.7%** 时间;状态字节只减少 **3.3%**,
|
|
295
|
+
因为该题批量修改后返回了完整 AX,而逐步修改可返回差量。不能把少读三次状态理解成少三份全量快照。
|
|
296
|
+
|
|
297
|
+
这道题的 Relay actions 内层时间比原生 AX 批量低约 **40.7%**(258.4 对 436 ms,约 1.69 倍速度比)。
|
|
298
|
+
这个数值有明确限制:原生是用户 Chrome 配置,Relay 是隔离 Chromium;原生 Chrome 版本读取被
|
|
299
|
+
浏览器 URL 策略阻止,版本记为 unknown,没有通过其他通路绕过;浏览器后端和快照内容也不完全相同。
|
|
300
|
+
它是本机该固定任务的描述性对照,不能宣称普遍比 Codex 快 1.69 倍。
|
|
301
|
+
|
|
302
|
+
原生 API 计时不含外层 MCP/工具调度,Relay 的 HTTP 计时也不含外层 Agent 工具调用。
|
|
303
|
+
原生每组两个 AX 回放的外层 `js` 约 3.8–5.0 秒,包含重载、两个任务、工具调度,不能拿这个数字
|
|
304
|
+
直接除以 Relay 单题 258 ms。相关外层观测已保存在原始 JSON。模型配置、token 和实际费用未测,
|
|
305
|
+
也没有在 Codex 原生链路中注入对应的 50 ms 延迟。
|
|
306
|
+
|
|
307
|
+
### 能力实测与可吸收的经验
|
|
308
|
+
|
|
309
|
+
除了 15 次表单任务,还在同一原生标签上完成:
|
|
310
|
+
|
|
311
|
+
- AX 直接点击 Shadow DOM 按钮:显示 `Shadow done`。
|
|
312
|
+
- AX 分别点击同源和跨域 iframe 按钮:节点 34、37 均显示 `Frame done`。
|
|
313
|
+
- 根据原生截图,在画布可见绿色目标内坐标点击:显示 `Canvas done`。
|
|
314
|
+
- 根据同一截图拖动蓝色方块:显示 `Drag done`。
|
|
315
|
+
|
|
316
|
+
因此,表单、Shadow DOM、同源/跨域 iframe、截图坐标和拖拽现在都有原生实测证据。
|
|
317
|
+
原生取消、文件对话框、下载、多标签并发、生产复杂站点仍未进行对等实测,不能称为全面能力等价。
|
|
318
|
+
|
|
319
|
+
对项目的直接启示是:简单控件优先 AX/ref;把已经确定的填写与点击合并;读取状态按决策需要安排。
|
|
320
|
+
本次原生 AX 状态获取约 157–200 ms,批量后的两次状态获取占了主要时间。
|
|
321
|
+
原生 Playwright 的 check/click 各约 272–292 ms,占该路径的大部分时间;计时只定位到 API,
|
|
322
|
+
没有核实其内部开销原因。保留 Playwright 用于复杂定位与开发集成,不应把它当成短任务必然更快的路径。
|
|
323
|
+
|
|
324
|
+
- [原生 15 次逐操作计时、完整去重状态和能力结果](benchmarks/codex-native.json)
|
|
325
|
+
- [Relay 可见浏览器 32 次原始数据](benchmarks/browser-runtime-balanced-headed.json)
|
|
326
|
+
|
|
327
|
+
可见浏览器 Relay 复跑命令:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
BROWSER_RELAY_BENCH_SUITE=balanced BROWSER_RELAY_BENCH_RUNS=8 BROWSER_RELAY_BENCH_HEADED=1 BROWSER_RELAY_BENCH_WIDTH=1466 BROWSER_RELAY_BENCH_HEIGHT=925 npm run bench:browser
|
|
331
|
+
```
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Browser Relay 与 Codex Browser Use:差距审计
|
|
2
|
+
|
|
3
|
+
日期:2026-09-09。主对照为 **Browser Relay 自身的观察/动作接口,与 Codex Browser Use 的原生 AX/截图/动作工作流**。
|
|
4
|
+
不把独立 Playwright 或 Codex 的内部 locator 分支当成主比较对象。此前表单微基准保留在
|
|
5
|
+
[历史报告](browser-use-comparison.md),本报告回答复杂任务还有哪些差距、哪些值得吸收,以及已修复什么。
|
|
6
|
+
|
|
7
|
+
## 结论
|
|
8
|
+
|
|
9
|
+
在已测的基本交互上已经接近,但还不能说完整体验等价。Codex 更突出的优势是可读的页面上下文、
|
|
10
|
+
原生控件语义,以及标签归属、会话/轮次、接管、结束清理的整体设计。Relay 的长处是 CLI/MCP/SDK
|
|
11
|
+
接入、插件内批次、远程设备与可控传输;简单表单的速度数字不能覆盖这些差距。
|
|
12
|
+
|
|
13
|
+
本轮用新探针确认了 Relay 的八类具体缺口并修复。13 类探针每类三次,修复前通过 5 类,
|
|
14
|
+
修复后全部 13 类通过。**这是挑选问题的回归集,不是网站总体成功率,也不能折算成与 Codex 的百分比差距。**
|
|
15
|
+
原生 AX 则完成了 13 条交互工作流记录和 2 个额外行为探针,覆盖相同的 13 类情况;不将语义不同
|
|
16
|
+
的路径硬算成同一总分。
|
|
17
|
+
|
|
18
|
+
## 怎样测,结果怎样认定
|
|
19
|
+
|
|
20
|
+
测试页为 [browser-gaps.html](../tests/fixtures/browser-gaps.html)。每题重新打开,只有本地合成数据,
|
|
21
|
+
不操作真实账号或生产网站。每道题有独立的可见业务结果,例如 `South saved`、`Custom checked=true`。
|
|
22
|
+
对“拒绝操作”类探针,另外检查原值未改变。禁用选项属于明确设定的 UI 一致性要求。
|
|
23
|
+
|
|
24
|
+
Codex 一侧使用本会话的 `mcp__cua_repl`:先读取原生 AX,依据当前父子关系、控件状态和索引操作,
|
|
25
|
+
再读取结果。动态控件在出现或启用后重新观察,不猜索引。移动按钮用 AX 语义动作;截图坐标、
|
|
26
|
+
拖拽、普通 iframe/Shadow DOM 的基础能力已在上一轮真实验证。
|
|
27
|
+
|
|
28
|
+
Relay 一侧使用同一测试页,通过实际扩展的 `/api/observe`、`/api/actions` 与 SDK 执行。
|
|
29
|
+
测试工具仅负责启动隔离的可见 Chromium、重置页面和独立验收,**不参与两方能力排名**。
|
|
30
|
+
开始和结束状态外,动态等待在插件内完成。对照前后保留相同动作参数,包含明确的动作级 `timeoutMs`;
|
|
31
|
+
旧实现忽略该参数,修复后执行有界的准备状态等待。
|
|
32
|
+
|
|
33
|
+
原生工作流是交互式探索,只有每种流程的一条主记录;会话中包含研究和调度间隔,因此不排名这轮
|
|
34
|
+
墙钟耗时。原始文件中的内层 API 时间仅供定位开销,其中一次观察耗时 5583 ms,保留这个异常值,
|
|
35
|
+
不据此推断稳定延迟。上一轮五次重复的表单数据另有固定计时口径,也不是独立模型盲测。
|
|
36
|
+
|
|
37
|
+
## 主对照结果
|
|
38
|
+
|
|
39
|
+
| 场景 | Codex Browser Use 原生 AX 实测 | Relay 修复前 | Relay 修复后 |
|
|
40
|
+
| --- | --- | --- | --- |
|
|
41
|
+
| 延迟启用 | 观察到 disabled;启用后重新观察并点击完成。直接盲点 disabled 不报错、也没完成业务 | 立即 `element_disabled`,动作级 timeout 无效 | 有界等待启用,完成 |
|
|
42
|
+
| 动态出现 | 出现后获取当前 AX 节点并完成 | 目标不存在立即失败 | 有界等待出现,完成 |
|
|
43
|
+
| 临时遮挡 | 观察覆盖层出现、消失,再点击完成 | 立即拒绝,不能按传入 timeout 等待 | 插件内等待遮挡消失后完成 |
|
|
44
|
+
| 移动按钮 | AX 根据控件语义直接激活成功 | 本探针已通过 | 仍通过;显式等待时还检查位置稳定 |
|
|
45
|
+
| 两区域内同名 Save | AX 父容器清楚显示 North/South,选择 South 的子按钮完成 | 缺少 scope,语义目标匹配两项而失败 | snapshot 提供 within;支持 scoped target 与 SDK 子定位器 |
|
|
46
|
+
| DOM 节点替换 | 重新观察后使用当前节点,完成 | 语义目标已能重新解析 | 保留;另测旧 ref 被拒绝,不自动指向新节点 |
|
|
47
|
+
| 原生 checkbox 业务事件 | `setValue` 只改变选中值,本页 onclick 不执行;改用 `click` 得到 trusted=true 的业务结果 | check 走 DOM click,事件 trusted=false | 前台使用鼠标输入,trusted=true;校验状态且重复 check 不二次点击 |
|
|
48
|
+
| 自定义 ARIA checkbox | 从 AX 看到 checkbox,点击成功 | `not_checkable` | 支持 ARIA checkbox/radio/switch,并校验目标状态 |
|
|
49
|
+
| 禁用 option | 明确报 disabled,保持 Open | 可以选中禁用项 | 明确拒绝,保持原值;也处理禁用 optgroup |
|
|
50
|
+
| 只读输入 | AX 未标为 settable;赋值时报错,原值不变 | 已正确拒绝 | 保留 |
|
|
51
|
+
| contenteditable | setValue 后业务 input 结果更新 | 已通过 | 保留 |
|
|
52
|
+
| Shadow DOM 下的永久遮挡 | AX 能触发遮挡下按钮的语义动作 | 已拒绝覆盖下的鼠标动作 | 保留;不把原生的语义激活与鼠标命中混为一谈 |
|
|
53
|
+
| iframe 上层永久遮挡 | AX 同样能触发被遮挡 iframe 内按钮 | 鼠标事件被挡住,但动作返回成功 | 检查祖先 iframe 在实际动作点的命中;明确拒绝 |
|
|
54
|
+
|
|
55
|
+
原生“语义激活能穿过视觉遮挡”是本轮观察到的行为,不代表它一定错误或一定应该复制。
|
|
56
|
+
对本项目的鼠标动作,选择保留覆盖检查。对业务结果,控件值变化与事件触发必须分开验证。
|
|
57
|
+
|
|
58
|
+
原生工作流所需观察次数:简单范围定位、checkbox、富文本一般 2 次;重渲染 3 次;本次延迟启用、
|
|
59
|
+
出现、临时遮挡各 4 次。Relay 成功批次通常是初始 observe 加最终状态,共 2 次;等待在插件内进行。
|
|
60
|
+
这说明批次和条件等待可以减少 Agent 往返,但不能据此把原生的探索过程和脚本回放总耗时直接相除。
|
|
61
|
+
Codex Browser Use 还可以选用其他原生接口;这里的观察次数是此次默认 AX 路径的记录,不是产品的最优次数或能力上限。
|
|
62
|
+
|
|
63
|
+
### 回归中进一步发现的 iframe 时序问题
|
|
64
|
+
|
|
65
|
+
复测出现过跨进程 iframe 的 pointerdown 落在父文档、pointerup 才到子文档的情况,按钮没有
|
|
66
|
+
收到完整点击,却返回了成功。事件记录见[复现证据](benchmarks/iframe-routing-regression.json)。
|
|
67
|
+
证据指向父级滚动后 DOM 几何已更新,而输入路由尚未稳定。现在父 iframe 容器发生滚动后先等待
|
|
68
|
+
渲染帧,再派发输入;修复后独立 15 轮和回归里的 20 轮连续操作均通过。只在实际滚动时增加等待,
|
|
69
|
+
不通过重复点击掩盖问题。闭合 Shadow DOM 与 iframe 局部覆盖也有独立回归,防止过度拒绝。
|
|
70
|
+
|
|
71
|
+
### 新等待功能的成本
|
|
72
|
+
|
|
73
|
+
对已经可点击的 Add row 控件,分别跑 7 次:默认路径中位 36.9 ms,显式设置动作 timeout 的
|
|
74
|
+
稳定性等待路径 85.2 ms,多约 48.3 ms。计时只包含 Relay 动作及最终观察,不含准备和独立断言。
|
|
75
|
+
因此 Skill 只在预期出现、启用、移动或遮挡变化时建议设置等待;不默认给所有动作加等待。
|
|
76
|
+
[原始数据](benchmarks/browser-readiness-cost.json)、[复跑脚本](../scripts/benchmark-browser-readiness.mjs)。
|
|
77
|
+
|
|
78
|
+
## 插件代码看到了什么
|
|
79
|
+
|
|
80
|
+
读取的是 Chrome 已安装扩展 **1.26.901.11451**,以及本机桌面 browser 插件 **26.901.51231**。
|
|
81
|
+
Chrome 扩展的 `background.js` 为 355753 B,`content-scripts/codex.js` 为 35143 B,
|
|
82
|
+
`foreign-frame-monitor.js` 为 5158 B;没有 source map。使用只读格式化副本分析,未修改官方插件。
|
|
83
|
+
这些是发行包的 JavaScript 和随包文档,并非完整开发源码;编译组件和线上实际运行分支不全可见。
|
|
84
|
+
|
|
85
|
+
| 从发行代码核验的设计 | 具体证据 | 对 Relay 的启示 |
|
|
86
|
+
| --- | --- | --- |
|
|
87
|
+
| 标签有明确归属 | background 的 claimTab/getOwningSessionId/isClaimedBySession,绑定 sessionId、turnId、instanceId,拒绝另一活跃 session 占用 | “按标签排队”只能保证动作组顺序,还不等于整个工作流的独占 |
|
|
88
|
+
| 轮次结束与交接 | setTabMark、handoff leases、turn marks;区分保留成果、交给用户、临时标签 | 增加显式 claim/release、handoff 与任务标签清理,而不是默认关闭用户标签 |
|
|
89
|
+
| 请求和用户控制有生命周期 | startRequest/finishRequest/stopSession、AbortController、activeRequests、每标签 cursor 状态 | 当前弹窗取消可用,但还缺按会话管理的接管、状态呈现与恢复 |
|
|
90
|
+
| 断线时明确失败 | requestHost 的请求 ID/期限;native port 断开时 rejectPendingHostRequests,再调度重连 | 重连与重放必须分开;已经可能执行的写动作不自动重发 |
|
|
91
|
+
| 客户端失联后的清理 | client-heartbeat-alarm 定期检测;无客户端时停会话、detach 调试器 | 需要治理进程消失后的所属任务/标签状态,不只依赖正常结束路径 |
|
|
92
|
+
| 按需状态和文档 | accessibility.md、api-use-behavior.md:AX 优先、差量、当前索引、确定动作成组、一次充分成功验证 | 已融入 Relay Skill;本轮补充事件语义、条件等待与范围定位 |
|
|
93
|
+
| 结构化边界 | 类型/schema、能力发现;桌面服务有受限的只读 DOM 求值与独立修改操作 | Relay eval 的边界较粗,可补只读查询接口与更细的能力描述 |
|
|
94
|
+
|
|
95
|
+
不要因为扩展里有很多侧边聊天资源就认为控制能力更强;这些 UI 资源不计作浏览器执行能力。
|
|
96
|
+
Chrome 扩展与桌面服务各有职责,单看扩展的文件大小也不能推断延迟。
|
|
97
|
+
|
|
98
|
+
文件版本、SHA-256 和定位符见[源码审计记录](benchmarks/codex-extension-audit.json)。独立实现本轮改动,
|
|
99
|
+
没有把官方 bundle 代码复制到项目。
|
|
100
|
+
|
|
101
|
+
## 本轮实际吸收并落地
|
|
102
|
+
|
|
103
|
+
1. **保留上下文的语义定位。** AX 输出补 `within`、结构化节点补 `parentRef`;支持
|
|
104
|
+
`tab.getByRole('group',{name:'South'}).getByRole('button',{name:'Save'})`。不默取第一个重名按钮。
|
|
105
|
+
2. **把可预期的等待放在执行器里。** 动作可设 `timeoutMs`,在派发前等待出现、启用、无遮挡、位置稳定;
|
|
106
|
+
支持 `wait state=enabled`。默认仍快速报告错误;只有明确设置时才等待。取消、任务总时限继续生效。
|
|
107
|
+
3. **区分状态赋值与业务输入。** 前台 check 使用真实鼠标输入,支持 ARIA 控件、重复调用不重复触发。
|
|
108
|
+
后台 DOM fallback 保留并返回 strategy=dom,不宣称它等价于 trusted mouse event。
|
|
109
|
+
4. **把遮挡与控件状态校验做完整。** 检查 iframe 祖先在实际动作点是否被挡住,避免“命令成功但没点到”;
|
|
110
|
+
禁用 option/optgroup 不再改变。只重试准备状态,已经派发的点击不会重放。
|
|
111
|
+
5. **同步提示词/Skill。** 明确范围定位、准备状态等待,以及依据业务结果而非仅依据函数返回或控件值结束。
|
|
112
|
+
|
|
113
|
+
代码入口:[automation.js](../extension/automation.js)、[SDK](../server/sdk.js)、
|
|
114
|
+
[Skill](../skills/browser-relay/SKILL.md)。
|
|
115
|
+
|
|
116
|
+
## 仍有多少差距
|
|
117
|
+
|
|
118
|
+
| 层面 | 当前判断 | 尚缺的具体东西 |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| 基本动作与传输效率 | 已接近;本轮修复了可复现缺口 | 更复杂跨 frame 变换、更多真实应用的事件语义仍需验证 |
|
|
121
|
+
| 页面观察信息 | 仍有明显差距 | 普通文本框值目前一并隐藏;只读/可编辑状态、完整层次和精细选择诊断仍不如原生丰富 |
|
|
122
|
+
| 会话与用户接管 | 差距最大之一 | 标签独占、跨轮次状态、handoff、失联清理、按会话展示任务状态 |
|
|
123
|
+
| 完整浏览器工作流 | 仍不完整 | 对话框、上传/下载、导航与新标签事件的统一高层 API;不能拿低层 CDP 可调用就算已补齐 |
|
|
124
|
+
| 工具/文档体系 | 已有基础,仍需完善 | 更细能力发现、只读查询、结构化错误上下文,避免 Agent 反复补查 |
|
|
125
|
+
| 模型能力与真实网站成功率 | 本次不能下结论 | 未做干净会话盲测、多网站任务集、相同预算的端到端比较 |
|
|
126
|
+
|
|
127
|
+
下一阶段优先级应是**会话/标签归属 → 观察信息与错误上下文 → 对话框和文件闭环**。
|
|
128
|
+
这些比继续压缩固定表单的几十毫秒更能缩小整体使用体验的差距。
|
|
129
|
+
|
|
130
|
+
## 验证与原始数据
|
|
131
|
+
|
|
132
|
+
- [Codex Browser Use 原生 AX 主记录](benchmarks/browser-gaps-codex-ax.json):13 条工作流与 2 个行为探针。
|
|
133
|
+
- [Relay 修复前,39 次](benchmarks/browser-gaps-relay-baseline.json)。
|
|
134
|
+
- [Relay 修复后,39 次](benchmarks/browser-gaps-relay-after.json)。
|
|
135
|
+
- [可复跑的 Relay 探针](../scripts/benchmark-browser-gaps.mjs)。
|
|
136
|
+
- [新增真实浏览器回归](../tests/browser-reliability.test.mjs):动态等待、范围定位、可信事件与幂等、无效写入、
|
|
137
|
+
iframe 实际命中点、等待取消和不重放,连同原有场景共 20 项浏览器测试通过(18 个场景及 2 个父测试)。
|
|
138
|
+
- `npm test`:97 通过、6 个环境相关跳过,无失败;Skill 校验通过。
|
|
139
|
+
|
|
140
|
+
所有主结论对应原生 AX 或 Relay 直接接口的证据。前期辅助路径试验不作为这里的主评分,
|
|
141
|
+
尤其不能把它的控件行为直接套到 Codex Browser Use 的默认 AX 路径。
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Browser Use 优点移植:开发实现与验收
|
|
2
|
+
|
|
3
|
+
本轮把实测和本地扩展审计中确定的八个方向做成 Browser Relay 自身的实现,没有复制厂商扩展代码。这些改动由 `1.5.0-dev.1` 开发版本推进至 **1.5.0**。下文保留开发阶段的验证记录与当时的发布边界;正式版本的功能和升级方式见[1.5.0 发布说明](releases/v1.5.0.md)。
|
|
4
|
+
|
|
5
|
+
## 八项落地
|
|
6
|
+
|
|
7
|
+
| 方向 | 实现 | 主要入口 |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| 读全内容 | AX 全文、完整 URL、分页续读、子树读取;旧文本修复 display:contents、表格单元格截断 | `read`、`tab.read()`、`browser_read` |
|
|
10
|
+
| 保留归属与层级 | 按父子关系输出 article、main、表格等语义边界,去掉重复容器摘要而非正文 | `extension/observations.js` |
|
|
11
|
+
| 操作语义明确 | 可访问名称、状态和所属结构;旧按钮优先 aria-label;保留已有 scope 定位 | `observe`、scoped locators |
|
|
12
|
+
| 阅读后直接操作 | 正文、完整链接、refs 同时返回;已读完分页后才推进 diff 基线 | `url`、`ref`、`nextCursor` |
|
|
13
|
+
| 统一文本、视觉和操作 | 同一 tab 对象读内容、定位、聚焦、截图;both 模式返回文本及真实图像块 | `tab.observe({mode:'both'})`、`focus` |
|
|
14
|
+
| 标签页归属和交接 | 自动认领、冲突拒绝、release/handoff、任务创建来源、弹窗显示和停止会话 | `sessions.js`、`browser_tab`、`browser_session` |
|
|
15
|
+
| 生命周期与错误恢复 | 心跳/租约、按传输断连停止、取消贯穿任务和请求、取消先于请求的记录、部分结果与中断动作、脚本异步错误即时返回 | `tasks.js`、SDK/MCP/runtime |
|
|
16
|
+
| 提示词和 skill | 按阅读/操作/视觉选择接口,确认分页/加载/验证状态,已知动作批处理,异常按实际结果恢复 | `skills/browser-relay/`、MCP tool descriptions |
|
|
17
|
+
|
|
18
|
+
## 关键行为
|
|
19
|
+
|
|
20
|
+
- 新阅读默认聚焦 main;页面无 main 时读取整页。需要菜单、侧栏或其他控件时使用 observe。目标 subtree 支持已观察的 ref、CSS 或 role/name。
|
|
21
|
+
- 单页输出预算仍有上限,但不会静默丢弃剩余正文。nextCursor 指向同一份已捕获内容,保留 capturedAt;导航/缓存淘汰后返回 stale_observation。每个 tab 最多缓存三份、每份至多四百万字符,超限时明确要求缩小子树。跨页分割不会拆坏代理对字符。
|
|
22
|
+
- AX 链接通过 DOMSnapshot 的 backend node ID 批量关联,保留完整 URL,不为每个链接增加一次浏览器往返。
|
|
23
|
+
- 游标页读完才更新 diff 基线;没读到的内容不会被当作已见。较旧分页完成时也不会覆盖更新的基线。
|
|
24
|
+
- 新协议握手报告真实 executor 版本、runtimeId、protocol 和 features。旧扩展未握手时新服务立即返回 protocol_mismatch。doctor 会实际调用 capabilities,不再只看本地 manifest 和 daemon。
|
|
25
|
+
- 会话心跳间隔 40 秒,租约 120 秒。SDK/MCP/runtime 自动维护;短 CLI 调用以 --session 续用任务,必要时显式 heartbeat。停止/过期/断连的会话不能隐式复活。
|
|
26
|
+
- 读写会自动认领,其他会话及匿名旧/CDP 客户端不能操作已认领的 tab。租约用于可信客户端间协调,不是抵抗任意本地软件的安全隔离。
|
|
27
|
+
- release/handoff 要求没有未完成工作;保留任务创建标记。stop 取消任务并释放归属,不关闭页面、不撤销已执行动作。弹窗提供用户可见的会话停止入口。
|
|
28
|
+
- 导航默认等文档 readyState 离开 loading;不是“所有网络请求结束”,也不保证站点异步数据已到。需要时追加目标 wait。
|
|
29
|
+
- 滚动默认保持后台,隐藏标签使用 DOM 滚动,不激活标签或窗口。只有用户明确要求时才调用 focus 或允许视觉动作前置。可选 waitForChange 返回是否观察到文本变化;后台可能延迟渲染,不能因此自行切前台。viewportMoved 与 contentChanged 分开,文本变化不是新记录数量,仍需按链接/业务 ID 去重。
|
|
30
|
+
- 失败任务保留 results、completedActions 和 interruptedAction。取消会补发本任务尚未释放的按键/鼠标释放事件,不重放按下动作。取消不能保证已发出的动作未产生效果。
|
|
31
|
+
- 持久脚本的拒绝型 top-level await 错误即时返回结构化错误并保留绑定;超时重置返回 session/task IDs,便于查询部分进展。MCP notifications/cancelled 可取消普通调用与脚本运行。
|
|
32
|
+
|
|
33
|
+
## 使用例子
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
browser-relay capabilities
|
|
37
|
+
browser-relay tabs
|
|
38
|
+
browser-relay read --tab <discovered-id> --session research
|
|
39
|
+
browser-relay read --tab <discovered-id> --session research --cursor <returned-cursor>
|
|
40
|
+
browser-relay focus --tab <discovered-id> --session research
|
|
41
|
+
browser-relay observe --tab <discovered-id> --session research --mode both --output /tmp/page.png
|
|
42
|
+
browser-relay handoff --tab <discovered-id> --session research --to reviewer
|
|
43
|
+
browser-relay session stop --session reviewer
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
SDK/MCP/CLI 的现代接口共用浏览器 executor。旧 HTTP/CSS 接口保留,但在切换到旧客户端前必须 release;不要在同一认领标签上混用两套客户端。MCP 的 browser_read/browser_observe 与 browser_exec 有各自会话标识,混用前按 browser.sessionId 显式交接。
|
|
47
|
+
|
|
48
|
+
## 验收
|
|
49
|
+
|
|
50
|
+
常规检查:`npm test`,105 项通过、7 项环境条件跳过。真实浏览器回归:`npm run test:browser`,28 项通过,零失败。
|
|
51
|
+
Skill validator、`git diff --check` 与 npm 打包内容检查通过。
|
|
52
|
+
浏览器测试在隔离 profile 加载本工作树扩展,动作和读取通过 Relay SDK 发出;启动测试浏览器的兼容框架不是性能对照对象。
|
|
53
|
+
|
|
54
|
+
新增覆盖:
|
|
55
|
+
|
|
56
|
+
- 20 条长正文、长 URL、表格末尾、隐藏内容排除、main 范围、分页后无重复 diff。
|
|
57
|
+
- 子树读取、导航使旧游标失效。
|
|
58
|
+
- 两个会话竞争、匿名客户端拒绝、交接、续租/过期、停止后不隐式重启。
|
|
59
|
+
- 旧扩展协议拒绝、真实运行实例信息、断连时挂起请求立即失败。
|
|
60
|
+
- 异步浏览器错误即时返回;取消先于任务抵达时禁止执行。
|
|
61
|
+
- MCP 文本/图像组合返回、取消通知与任务 ID 对应。
|
|
62
|
+
- 弹窗显示认领者,停止时取消待办操作而保留页面。
|
|
63
|
+
- 原有 iframe、shadow DOM、控件事件、任务队列和远程 hub 回归。
|
|
64
|
+
|
|
65
|
+
### 真实 Omarchy 页面回查
|
|
66
|
+
|
|
67
|
+
使用 `node scripts/verify-reading.mjs <artifact-directory>` 在隔离 Chrome 中访问此前漏读的 `https://zh.omarchy.org/`,整个过程通过本开发版本 Relay 执行,且握手确认版本为 1.5.0-dev.1。
|
|
68
|
+
|
|
69
|
+
此次读到正文、安装栏目及完整手册链接。新接口分四页返回 66,862 UTF-8 字节;修复后的旧文本返回 37,409 字节。两种读取都找到了此前缺失的内容。原生旧对照有不同的 URL 显示策略,不能用这两个字节数推导对原生的压缩率或速度倍数。
|
|
70
|
+
|
|
71
|
+
机器摘要见 [browser-use-parity.json](benchmarks/browser-use-parity.json),弹窗截图见 [extension-sessions.png](benchmarks/extension-sessions.png)。页面正文和本地执行日志保留在本机验收 artifacts 中,未打包用户 X 推荐流。
|
|
72
|
+
|
|
73
|
+
## 开发阶段的发布边界与剩余验证
|
|
74
|
+
|
|
75
|
+
- package、插件元数据使用开发版本;Chrome 的数值 version 为 1.5.0,version_name 为 1.5.0-dev.1。
|
|
76
|
+
- publish workflow 仅由 workflow_dispatch 触发,必须明确给定与 package.json 相同的版本及 npm channel;开发版本不能用 latest。发布前运行 Linux/Windows 测试。
|
|
77
|
+
- 本机 npm 配置的默认 channel 为 next;开发版发布仍要求显式传入非 latest 的 --tag,prepublishOnly 在同步版本前拒绝缺省或 latest(覆盖 npm 不导出默认标签环境变量的情况)。
|
|
78
|
+
- 没有触发该工作流,没有推送或发版。
|
|
79
|
+
- 本轮证明的是八项设计已实现且经过上述检查,**没有证明新版在用户登录 Chrome 的完整 X 同题流程中已经追平原生**。那项验收仍需要安装/重载这个开发版本,不能沿用此前旧接口的时间数据。
|
|
80
|
+
- 租约状态和分页缓存属于当前扩展进程,重载后失效;调用方应建立新会话并重新观察。
|
|
81
|
+
|
|
82
|
+
## 独立审查后的修复(2026-09-09)
|
|
83
|
+
|
|
84
|
+
Astra 对原开发提交的独立审查发现三项 P1 和七项 P2。原有全绿测试未覆盖这些边界,不能据此认定八项能力已经验收完成。本节记录工作树中的修复,不表示发布或 X 效率对照已经完成。
|
|
85
|
+
|
|
86
|
+
| 审查问题 | 修复及回归证据 |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| HTTP 取消/超时后后续点击仍执行 | 本地服务监听响应连接中止;SDK/CLI/MCP 共用传输实现。Node/Worker hub 自身的 HTTP abort 和 RPC 超时也发送取消,不依赖 SDK。预分配任务 ID 并保留进展;browser-review、transport、hub-rpc、remote-hub 与 worker-hub 覆盖各入口 |
|
|
89
|
+
| main 内 iframe 静默漏读 | AX frame root 接到实际 DOM frame owner;同源、跨源 iframe 按宿主位置进入子树。无法接入时显式 warning;browser-review 覆盖内外 main 的范围 |
|
|
90
|
+
| runtime inspect 隐藏截断 | 移除字符串、数组和对象深度的隐式裁剪;总输出预算溢出时提供独立 runtimeOutput 游标和 readOutput 续读,回归覆盖长正文、数组、深层值及日志占满预算后的恢复 |
|
|
91
|
+
| 正文顺序错乱 | 按 AX childIds 深度优先遍历后过滤;四步内容顺序回归固定为 1→2→3→4 |
|
|
92
|
+
| article 独立标签丢失 | 仅省略经文本相等验证的重复摘要;Alice/Bob 独立 article 名称保留 |
|
|
93
|
+
| 主 frame CSS 子树 stale_ref | 子树定位统一使用当前主 frame 标识;仅为选定根保留 AX 忽略的 div/p,主文档、普通容器及跨源 frame CSS 读取通过 |
|
|
94
|
+
| MCP 取消误报连接故障 | 普通调用及 runtime 中断使用 request_cancelled、retryable=false,保留可用任务信息 |
|
|
95
|
+
| remote focus 丢失连接来源 | 递归 action 请求透传 transport;sessions 回归验证远程断连停止远程归属并保留本地归属 |
|
|
96
|
+
| 已认领 tab 阻断其他 tab 的 CDP 握手 | Browser.getVersion 读取扩展上下文的浏览器元数据;browser-review 验证连接及操作已释放 tab,同时仍拒绝操作已认领 tab |
|
|
97
|
+
| 本地 npm publish 可能将开发版设成 latest | publishConfig 默认 next,发布前要求开发版显式非 latest 标签;distribution 通过真实 npm lifecycle 验证 next 通过、缺省/latest 拒绝,未执行发布 |
|
|
98
|
+
|
|
99
|
+
本轮全量检查:`npm test` 124 通过、8 项环境条件跳过;`npm run test:browser` 36 通过、零失败。新增回归为 `tests/browser-review.test.mjs`、`tests/transport.test.mjs` 以及 runtime/MCP/session/distribution 的补充断言。独立 Astra 最终复验已将十项问题全部标为通过,独立运行的测试结果亦为 124/36。复验额外覆盖 99,800 字符、85k 日志叠加正文、18 万字符跨页及 emoji,续读结果与完整 HTTP 内容逐字符一致;真实 Node hub 的 30 秒超时后原始 HTTP 与 SDK 均停止后续点击。CLI 单次 exec 排空 185,406 字符后无失效游标或残留归属。证据归档于本机 `~/.codex/artifacts/browser-relay-review-fixes-2026-09-09/`。
|
|
100
|
+
|
|
101
|
+
取消是停止后续 Relay 动作,不会撤回页面已经启动的网络请求或定时器。传输无法送达取消时明确报告未知结果,并保留任务标识;不得自动重放。Runtime 总输出预算与浏览器分页不同;超预算后先按 runtimeOutput.readWith 续读缓存,取回被裁剪的正文和浏览器游标,再继续浏览器分页。超出续读缓存上限则明确报错,应保留结果变量后分段打印,不能通过 diff 补回先前没打印的内容。
|
|
102
|
+
|
|
103
|
+
Worker 改动按 [Cloudflare Request 文档](https://developers.cloudflare.com/workers/runtime-apis/request/) 显式传递 AbortSignal 并启用 enable_request_signal。Wrangler 本地 dry-run 打包与类型生成通过,没有上传或部署。Cloudflare 线上 DO 的真实客户端断连传播仍未验证;本地 Worker 路由/信号回归通过。Linux/Windows 实机、实际发布和登录 X 的原生效率对照也不在本轮验证结果内。
|
|
104
|
+
|
|
105
|
+
上述独立复验完成时,修复仍保留为未提交改动,尚未推送、发版、部署或替换全局安装。随后用户明确批准正式发布 1.5.0,发布状态以 GitHub Release 与 npm registry 为准。
|