@evan_zhong/browser-attach 0.16.0 → 0.17.2
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/README.md +5 -5
- package/README.zh.md +5 -5
- package/bin/browser-attach.mjs +3 -3
- package/docs/AGENT-INTEGRATION.md +3 -3
- package/docs/ARCHITECTURE.md +14 -9
- package/docs/TEST-REPORT.md +16 -1
- package/docs/USAGE.md +430 -429
- package/extension/background.js +7 -98
- package/extension/connection.js +142 -0
- package/extension/controller.js +1 -1
- package/extension/manifest.json +1 -1
- package/extension/popup.js +7 -1
- package/extension/snapshot.js +39 -19
- package/extension/version.js +11 -0
- package/extension/wait.js +1 -1
- package/package.json +2 -1
- package/scripts/check-package.mjs +1 -0
- package/src/client.mjs +58 -15
- package/src/config.mjs +5 -1
- package/src/hub.mjs +62 -17
- package/src/mcp.mjs +2 -1
- package/src/setup.mjs +87 -16
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ Merge the following into your client's MCP configuration, or see [mcp-config.jso
|
|
|
67
67
|
|
|
68
68
|
On Windows clients that require a full command extension, use `npx.cmd`. With a global install you can also configure `"command": "browser-attach", "args": ["mcp"]`. Restart the MCP client to discover the tools.
|
|
69
69
|
|
|
70
|
-
`@latest`
|
|
70
|
+
`@latest` selects the npm package at launch. For a pair already running 0.17 or newer, startup coordinates an idle Hub upgrade, synchronizes the paired extension directory and asks older connected extensions to reload themselves. First-time extension loading and the first upgrade from a pre-0.17 pair still require one manual extension reload; a pre-0.17 Hub must be stopped once before the new MCP can start. If another MCP connection is using the Hub, close it and reconnect to retry the upgrade.
|
|
71
71
|
|
|
72
72
|
Assembly steps for supported hosts are in [agent integration](docs/AGENT-INTEGRATION.md); other clients use the stdio entry above.
|
|
73
73
|
|
|
@@ -113,13 +113,12 @@ Override it explicitly with the absolute path `BROWSER_ATTACH_HOME`. The Windows
|
|
|
113
113
|
A host assembly step that writes the client entry pins the absolute paths of the current Node, CLI and the actual pairing file and sets `BROWSER_ATTACH_HOME`; it works together with a custom `--config`. When the MCP launches the Hub it passes the same absolute pairing path and directory, so different launch environments cannot derive a second configuration. See [agent integration](docs/AGENT-INTEGRATION.md).
|
|
114
114
|
|
|
115
115
|
```sh
|
|
116
|
-
browser-attach status
|
|
117
|
-
browser-attach stop
|
|
118
116
|
npm install --global @evan_zhong/browser-attach
|
|
119
|
-
browser-attach setup
|
|
120
117
|
```
|
|
121
118
|
|
|
122
|
-
|
|
119
|
+
Then restart the MCP connection. With `@latest`, restarting MCP is sufficient for later upgrades once Hub and extension are on 0.17 or newer; `setup` and `start` use the same coordination when run explicitly. Upgrading from an older pair first requires `browser-attach stop`, a restart and one manual extension reload. Custom pairing paths, ports and extension directories are retained. Closed browser profiles update when they next connect. An older MCP package cannot downgrade a newer Hub or installed extension.
|
|
120
|
+
|
|
121
|
+
An upgrade waits for extension cleanup and confirms the new version after reload; cleanup or reload failures are reported instead of replaying page actions. Manual reload remains available on the extension options page for recovery. Hub and extension versions must match for page control. The default port is `47831`; choose another port with `setup --port` when creating a pairing.
|
|
123
122
|
|
|
124
123
|
## Architecture and boundaries
|
|
125
124
|
|
|
@@ -164,6 +163,7 @@ Real-browser tests need a Chromium / Edge executable that allows loading extensi
|
|
|
164
163
|
npm run test:live -- --executable /path/to/chromium --family chromium
|
|
165
164
|
npm run test:interaction -- --executable /path/to/chromium --family chromium
|
|
166
165
|
npm run test:interaction -- --tab-indicators --executable /path/to/chromium --family chromium
|
|
166
|
+
npm run test:upgrade -- --executable /path/to/chromium
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
These tests use temporary profiles and local fixtures. Coverage and limits: [test report](docs/TEST-REPORT.md); implementation and design trade-offs: [architecture](docs/ARCHITECTURE.md).
|
package/README.zh.md
CHANGED
|
@@ -67,7 +67,7 @@ npx --yes --package=@evan_zhong/browser-attach@latest browser-attach setup
|
|
|
67
67
|
|
|
68
68
|
Windows 客户端若要求完整命令扩展名,使用 `npx.cmd`。已全局安装时,也可以配置 `"command": "browser-attach", "args": ["mcp"]`。重启 MCP 客户端后发现工具。
|
|
69
69
|
|
|
70
|
-
`@latest`
|
|
70
|
+
`@latest` 在启动时选择 npm 包版本。当配对已经运行 0.17 或更高版本时,MCP 启动会协调空闲 Hub 升级、同步已配对的扩展目录,并通知较旧扩展自行重新加载。首次加载扩展,以及从 0.17 之前版本进行的第一次升级,仍需手动重载一次扩展;旧 Hub 必须先停止,新 MCP 才能启动。如果其他 MCP 连接正在使用 Hub,请关闭这些连接后重连,以重试升级。
|
|
71
71
|
|
|
72
72
|
各宿主的装配步骤见 [Agent 集成](docs/AGENT-INTEGRATION.md);其他客户端直接使用上面的 stdio 配置。
|
|
73
73
|
|
|
@@ -113,13 +113,12 @@ Windows 客户端若要求完整命令扩展名,使用 `npx.cmd`。已全局
|
|
|
113
113
|
宿主装配步骤写入客户端条目时,会固定当前 Node、CLI 和实际配对文件的绝对路径,并设置 MCP 的 `BROWSER_ATTACH_HOME`;支持与自定义 `--config` 一起使用。MCP 启动 Hub 时继续传入同一绝对配对路径及目录,避免不同启动环境重新推导出另一份配置。详见 [Agent 集成](docs/AGENT-INTEGRATION.md)。
|
|
114
114
|
|
|
115
115
|
```sh
|
|
116
|
-
browser-attach status
|
|
117
|
-
browser-attach stop
|
|
118
116
|
npm install --global @evan_zhong/browser-attach
|
|
119
|
-
browser-attach setup
|
|
120
117
|
```
|
|
121
118
|
|
|
122
|
-
|
|
119
|
+
安装新版后重连 MCP。使用 `@latest` 时,在 Hub 与扩展已经运行 0.17 或更高版本后,重连 MCP 即可协调后续升级;显式运行 `setup` 或 `start` 也使用同一流程。从更旧版本升级时,需要先执行 `browser-attach stop`、重启 MCP,并手动重载一次扩展。自定义配对路径、端口和扩展目录会保留。未打开的浏览器 profile 在下次连接时完成更新。旧 MCP 包不会降级新版 Hub 或已安装扩展。
|
|
120
|
+
|
|
121
|
+
升级会等待扩展清理,并在重载后确认新版本;清理或重载失败会明确报告,不重放页面动作。扩展设置页保留手动重新加载按钮用于恢复。正常页面控制仍要求 Hub 与扩展版本一致。默认端口为 `47831`,创建配对时可通过 `setup --port` 选择其他端口。
|
|
123
122
|
|
|
124
123
|
## 架构与使用边界
|
|
125
124
|
|
|
@@ -164,6 +163,7 @@ node bin/browser-attach.mjs mcp
|
|
|
164
163
|
npm run test:live -- --executable /path/to/chromium --family chromium
|
|
165
164
|
npm run test:interaction -- --executable /path/to/chromium --family chromium
|
|
166
165
|
npm run test:interaction -- --tab-indicators --executable /path/to/chromium --family chromium
|
|
166
|
+
npm run test:upgrade -- --executable /path/to/chromium
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
这些测试使用临时配置和本地 fixture。测试覆盖与限制见 [验证报告](docs/TEST-REPORT.md),实现与设计取舍见 [架构与设计](docs/ARCHITECTURE.md)。
|
package/bin/browser-attach.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { ensureHub, hubIsRunning, AttachClient } from '../src/client.mjs';
|
|
|
6
6
|
try {
|
|
7
7
|
const { values, positionals } = parseArgs({ allowPositionals: true, options: {
|
|
8
8
|
config: { type: 'string', default: DEFAULT_CONFIG },
|
|
9
|
-
'extension-dir': { type: 'string' }, port: { type: 'string'
|
|
9
|
+
'extension-dir': { type: 'string' }, port: { type: 'string' },
|
|
10
10
|
nosis: { type: 'boolean', default: false }, help: { type: 'boolean', short: 'h' },
|
|
11
11
|
} });
|
|
12
12
|
const action = positionals[0] || 'mcp', configPath = values.config;
|
|
@@ -20,10 +20,10 @@ try {
|
|
|
20
20
|
const stop = () => hub.close(); process.once('SIGINT', stop); process.once('SIGTERM', stop);
|
|
21
21
|
} else if (action === 'setup') {
|
|
22
22
|
const { setup, configureNosis } = await import('../src/setup.mjs');
|
|
23
|
-
const result = await setup({ configPath, extensionDir: values['extension-dir'], port: Number(values.port) });
|
|
23
|
+
const result = await setup({ configPath, extensionDir: values['extension-dir'], port: values.port === undefined ? undefined : Number(values.port) });
|
|
24
24
|
console.log(`Extension folder: ${result.extensionDir}\nExtension ID: ${result.config.extension_id}\nPairing: ${result.configPath}`);
|
|
25
25
|
if (values.nosis) console.log(JSON.stringify(await configureNosis(undefined, { configPath: result.configPath })));
|
|
26
|
-
await ensureHub(result.configPath); console.log('Local hub
|
|
26
|
+
await ensureHub(result.configPath); console.log('Local hub ready. Load the extension in each Chrome/Edge profile on first use; subsequent upgrades reload it automatically.');
|
|
27
27
|
} else if (action === 'start') { await ensureHub(configPath); console.log('Local hub started.'); }
|
|
28
28
|
else if (action === 'status') {
|
|
29
29
|
const config = await loadConfig(configPath);
|
|
@@ -26,7 +26,7 @@ node <安装位置>/bin/browser-attach.mjs mcp --config <配对文件绝对路
|
|
|
26
26
|
|
|
27
27
|
- `BROWSER_ATTACH_HOME` 指向配对文件所在目录。
|
|
28
28
|
- Node 可执行文件、CLI 与配对文件一律使用绝对路径。宿主的启动环境(PATH、工作目录、AppData 重定向)不同,重新推导会得到第二份配对。
|
|
29
|
-
-
|
|
29
|
+
- 安装位置变化后重新执行 `setup` 并更新宿主条目。Hub 与扩展已经运行 0.17 或更高版本时,安装新版后重连 MCP 会协调空闲 Hub 与扩展自动升级;从更旧版本首次升级需先停止 Hub、重启 MCP 并手动重载一次扩展。其他 MCP 仍连接时关闭它们后重试。正常页面控制要求同版本。
|
|
30
30
|
|
|
31
31
|
工具前缀由宿主决定,原始工具名不变(`browser_discover`、`browser_claim_tab` 等)。装配后的最小验证在各宿主一致:`browser_discover(kind="browsers")` → `kind="tabs"` → `browser_claim_tab` → `browser_snapshot` → `browser_tab_control(action="release")`。
|
|
32
32
|
|
|
@@ -110,7 +110,7 @@ npm root -g # 全局安装目录;CLI 位于 <root>/@evan_zhong/browser-a
|
|
|
110
110
|
- `web` profile 开启 HMR,修改条目会就地重连;`headless`、`sdk`、`acp` 关闭 HMR,需要重启 harness。
|
|
111
111
|
- MCP 工具与原生工具一样经过 DSH 的权限检查与审批策略。
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
安装新版后重启或重连 harness,由 MCP 启动流程协调 0.17+ 的后续 Hub 与扩展升级;首次加载扩展以及从更旧版本首次升级仍需手动重载。
|
|
114
114
|
|
|
115
115
|
## 新增宿主
|
|
116
116
|
|
|
@@ -122,4 +122,4 @@ npm root -g # 全局安装目录;CLI 位于 <root>/@evan_zhong/browser-a
|
|
|
122
122
|
- 失效句柄不能跨连接复用,错误后应重新 discover + claim。
|
|
123
123
|
- 文件上传只在浏览器本机读取路径,内容不经过 Hub 或模型。
|
|
124
124
|
- 宿主把大结果保存为 Artifact 时,嵌套 JSON 长行可能被宿主的读取工具截断;这是宿主的分页行为,不能靠调大 Attach 的预算解决,也不等同于快照游标分页。
|
|
125
|
-
- `Connection closed` 时依次检查:宿主的 stderr、配对文件是否可见、`hub.log
|
|
125
|
+
- `Connection closed` 时依次检查:宿主的 stderr、配对文件是否可见、`hub.log`、是否有其他 MCP 连接阻止升级,以及扩展清理或自动重载是否失败。扩展设置页可手动重新加载以恢复。
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 架构与设计边界
|
|
2
2
|
|
|
3
|
-
当前实现为 **0.
|
|
3
|
+
当前实现为 **0.17.2**。本文说明 BrowserAttach 的组件、控制模型与设计取舍;工具参数见 [使用指南](USAGE.md)。
|
|
4
4
|
|
|
5
5
|
## 组件与数据流
|
|
6
6
|
|
|
@@ -17,11 +17,12 @@ MCP 客户端
|
|
|
17
17
|
|---|---|
|
|
18
18
|
| `bin/browser-attach.mjs` | `setup` / `mcp` / `hub` / `status` / `stop` 入口 |
|
|
19
19
|
| `src/config.mjs` | 数据目录、配对文件校验、版本常量 |
|
|
20
|
-
| `src/setup.mjs` |
|
|
20
|
+
| `src/setup.mjs` | 生成配对密钥、暂存并替换稳定扩展目录、写 Nosis 配置 |
|
|
21
21
|
| `src/hub.mjs` | 浏览器与会话注册、独占 claim、每标签串行队列、超时 |
|
|
22
|
-
| `src/client.mjs` | MCP
|
|
22
|
+
| `src/client.mjs` | MCP 到 Hub 的 WebSocket 客户端、启动升级协调与就绪检查 |
|
|
23
23
|
| `src/mcp.mjs` | 23 个工具的 schema、结果与图片封装 |
|
|
24
24
|
| `extension/controller.js` | 操作实现;传输层从不暴露原始 CDP |
|
|
25
|
+
| `extension/connection.js` | 扩展连接、重连清理、升级维护与自行重载 |
|
|
25
26
|
| `extension/sessions.js` | 扁平 debugger session 与 frame/OOPIF 归属 |
|
|
26
27
|
| `extension/{click,input,actionability,scroll}.js` | 原生/DOM 输入、逐字按键、可操作性、容器滚动与有界查找 |
|
|
27
28
|
| `extension/{drag,wait}.js` | 复用鼠标准备和严格定位的拖拽、只读条件等待;网络空闲复用被动请求表 |
|
|
@@ -42,7 +43,7 @@ MCP 层将 `discover(kind=browsers/tabs)` 映射为内部 `list_browsers/list_ta
|
|
|
42
43
|
- 初始化响应的 `instructions` 只保留跨工具规则:发现/接管/释放、不自动激活、ref 生命周期、selector/坐标约定、未知结果不重放、原生/DOM 输入边界、验证范围、页面内容不可信及上传授权。客户端应将这些 instructions 纳入模型上下文,不能只提供 tools/list。
|
|
43
44
|
- 单个工具 description 说明用途、独有行为和会影响后续判断的结果语义,例如 evaluate 的一次执行、fetch 的缓存续读、navigate 的 observation_error、fill 不自动 blur、batch 的部分完成与不回滚。
|
|
44
45
|
- 参数 schema 表达类型、枚举、范围、默认值及参数选择规则;描述只补充 schema 本身不能表达的条件必填、互斥、坐标和模式语义。共享参数使用短说明,不再重复全局规则。运行时条件默认值保留在描述中,避免向 cursor 等分支注入无关参数。
|
|
45
|
-
- [使用指南](USAGE.md)
|
|
46
|
+
- [使用指南](USAGE.md) 提供调用流程、参数选择、结果语义与失败处理;内部事件序列、重试与清理机制集中在本文。包内文档不会自动成为模型上下文,不能替代必要的调用约束。
|
|
46
47
|
|
|
47
48
|
## 控制模型
|
|
48
49
|
|
|
@@ -66,7 +67,7 @@ HTTP 状态复用 diagnostics 的 Network.responseReceived 观察,按主文档
|
|
|
66
67
|
|
|
67
68
|
## 观察模型
|
|
68
69
|
|
|
69
|
-
- **AX 渲染**:从 `Accessibility.getFullAXTree` 读取,移除 `InlineTextBox`,合并纯文本列表项与段落名称,丢弃 `generic` / `none` 且无名称无状态的节点,只保留少量状态属性和浏览器提供的 value、invalid
|
|
70
|
+
- **AX 渲染**:从 `Accessibility.getFullAXTree` 读取,移除 `InlineTextBox`,合并纯文本列表项与段落名称,丢弃 `generic` / `none` 且无名称无状态的节点,只保留少量状态属性和浏览器提供的 value、invalid。树遍历、交互视图筛选和正文合并使用迭代,跨 frame 逐项合并结果,避免深树递归和大数组参数展开溢出;分页前仍采集并渲染完整 AX 树,max_nodes 不限制采集成本。每行 `[token:n] role "name"`,`token` 是本次观察的随机前缀;这些字段不证明应用已保存。
|
|
70
71
|
- **交互视图**:可选 `profile=interactive` 在同一渲染器中仅保留 AX 控件角色、可聚焦/可编辑节点及其祖先链和控件内文本,不以 backendNodeId/ref 是否存在判断交互性。独立文本和合并正文可隐藏或截取预览,控件名称、值和 ref 的原始 AX 身份保留;默认 `full` 行为不变。筛选仍读取完整 AX 树,只降低输出与分页成本;视图参数绑定分页观察。
|
|
71
72
|
- **文本查询与精简输出**:`snapshot(query=...)` 复用同一次 AX 渲染,按当前视图中节点的完整名称(含合并正文)或 value 做不区分大小写的字面子串筛选,只输出匹配行和对应 frame 标题;不搜索 role/ref 或任意 DOM 属性,不新增索引缓存。新查询仍采集新观察并使旧 refs 失效,query 与分页绑定。默认省略 viewport、snapshot_id 和重复规则说明,`verbose=true` 返回前两项;frame 覆盖、视图、预算和游标语义保留。
|
|
72
73
|
- **ref 解析**:ref 保存 `backendNodeId`、所属 frame/session 和观察时的 AX role/name;动作时重新 `DOM.resolveNode` 并用局部 AX 查询核对语义身份。输入与求值不清空 refs,只使快照分页失效;原节点仍连接时可复用,节点替换、role/name 改变、文档或 frame 变化时安全失败,不按 role/name 猜测替代节点。
|
|
@@ -93,7 +94,7 @@ HTTP 状态复用 diagnostics 的 Network.responseReceived 观察,按主文档
|
|
|
93
94
|
- **送达预算**:原生 click/hover/press_key 的派发及可信回执另有 1250 ms 上限,清理最多 250 ms;系统菜单捕获输入时快速释放队列,仍报告结果未知并提示 Esc,不自动重放。
|
|
94
95
|
- **hover 与 drag**:hover 复用点击准备与隔离校验,仅派发一次 mouseMoved,清理不移走指针。drag 显式区分 pointer 与 HTML5;后者从真实 dragstart 截获 DragData,再用 CDP 派发 dragover/drop,校验可信 dragstart/drop/dragend。目的节点在按住后滚入视口;所有步骤共用标签队列和总预算,失败时只取消/释放本次手势。
|
|
95
96
|
- **可选输入参数**:显式 offset 在元素 content quad 上插值后沿用命中与 OOPIF 边界检查;settle_ms 在 click/drag 首次派发前等待并复查就绪。drag trajectory 只替换既有插值段,采用法向控制点、平滑进度及随机间隔权重;type 的 delay_ms 可逐间隔独立区间采样。所有等待共用总预算,超时后没有继续派发的链;省略参数时不使用随机数,沿用既有确定性路径。不新增 tab 级历史、冷却、自动激活或重放路径。
|
|
96
|
-
- **条件等待**:wait 复用严格 selector、可操作性和命中检查,支持出现、可见、可操作、文本/URL
|
|
97
|
+
- **条件等待**:wait 复用严格 selector、可操作性和命中检查,支持出现、可见、可操作、文本/URL 子串及网络空闲;文本使用 innerText,expected 子串匹配和 previous 完整旧值比较均在 500 字符结果预览截取前完成。只读轮询,错误附带条件和最后状态。
|
|
97
98
|
- **原生下拉**:select_option 直接用 selectedIndex setter 和合成 input/change 设置一个 HTML 选项,核验保留结果并返回 events_trusted=false。native click 的 select 命中(含 UA shadow 内部节点和关联 label)在派发前拒绝。
|
|
98
99
|
- **命中提示**:普通命中保留实际 hit node,沿父元素、Shadow host、slot 查找最近的 HTML/ARIA 可点击候选,返回 clickable_target;hint=false 表示未识别候选,不代表无法响应事件。CSSPseudoElement 先解析为事件所属的 originating element,提示标记 pseudo_element=true,并使用该元素安装事件校验。语义候选不会被用于替换点击目标。
|
|
99
100
|
- **遮挡失败诊断**:当前 frame 的遮挡直接复用已读取的 hit_target;祖先 frame 遮挡额外用至多 200 ms 读取命中描述,诊断节点消失时保留原遮挡错误与 backend node ID。错误包含命中点和受阻 frame。根据共享预算的派发状态区分“未派发”和“结果未知”,避免 drag 按住后准备目的节点时误报零输入。
|
|
@@ -102,9 +103,10 @@ HTTP 状态复用 diagnostics 的 Network.responseReceived 观察,按主文档
|
|
|
102
103
|
- **OOPIF 坐标**:点击从顶层派发。逐层用 `DOM.getBoxModel` 把坐标换算到祖先文档,并用 `DOM.getNodeForLocation` 确认该位置确实落在 frame owner 上,防止祖先页面的遮挡被跳过。
|
|
103
104
|
- **DOM 模式**:`mode: "dom"` 是显式的、受控的降级路径,用于原生菜单或标签拖动暂时捕获输入时操作普通 HTML 控件。它调用 `HTMLElement.click()` 或原生 value setter,事件非可信、无用户激活,且绝不会在原生失败后自动启用。
|
|
104
105
|
- **对话框策略**:ask 仍为默认;单操作/单步骤的显式 accept/dismiss 在事件回调中解除 JS 模态阻塞,保留消息与处理结果,最多自动处理 10 个。beforeunload dismiss 快速取消本次导航等待,实际主文档变化仍会停止 batch。
|
|
105
|
-
- **未知结果探测**:在可能写入的操作准备期安装目标 frame 的临时 MutationObserver,仅在不确定失败后做一次有界只读探测,回传对话框、导航、DOM
|
|
106
|
+
- **未知结果探测**:在可能写入的操作准备期安装目标 frame 的临时 MutationObserver,仅在不确定失败后做一次有界只读探测,回传对话框、导航、DOM 变动;读取最多 300 ms、清理最多 100 ms。assessment 为 observable_effects 或 no_observable_effects;观察不到变化不等于没有派发,不将证据升级成业务成功,不自动重放。
|
|
106
107
|
- **元素截图/求值 ref**:复用既有截图 clip/元数据与 ref 注册/失效模型,分别增加元素 border box 截图和显式单 DOM Element 结果;不暴露 Runtime objectId。JSON 求值自动调用函数一次并等待 Promise,缓存续读不执行脚本。
|
|
107
108
|
- **历史导航**:在已有 navigate 中选择 URL 或 back/forward,按 history entry 与主 frame 生命周期等待;同文档/BFCache 恢复不等新的加载事件,不用 evaluate 重放导航。
|
|
109
|
+
- **导航后观察**:导航成功后的快照另有 10 秒预算,文档变化或执行上下文销毁等瞬时错误最多只重读一次;权限错误和预算耗尽不重试。观察失败保留导航结果并附 observation_error,不重新派发导航。
|
|
108
110
|
- **不做通用 CDP 透传**:`browser_evaluate` 是页面表达式 API,不是 CDP 通道;没有暴露任意 domain/method 的工具。
|
|
109
111
|
|
|
110
112
|
## 诊断模型
|
|
@@ -115,11 +117,12 @@ HTTP 状态复用 diagnostics 的 Network.responseReceived 观察,按主文档
|
|
|
115
117
|
- 两类 append-only 缓冲各自维护 `seq`:读取使用 `after_seq` + `limit` + `max_chars`;续读位置必须与 tab claim 和 kind 一起保存。网络突发流量不会挤掉控制台错误。console 的 level 与 network 的 url_contains 不得跨类使用。两种 timestamp 基准不同,不混排或伪造统一时间轴。同一 requestId 的重定向用 `hop` 区分,完成事件后追加而不是覆盖请求行。
|
|
116
118
|
- 上限为每类 500 条 / 1,048,576 字符,活跃请求表 500 项;淘汰记录 `dropped_through_seq`,读取返回 `data_loss`。
|
|
117
119
|
- 导航保留缓冲,tab_control(action=release) / detach / 关闭 / 断连清理;不落盘、不修改缓存策略与 service worker。默认不读取 headers/正文;按需开启只捕获之后的 XHR/fetch,凭据头和命名敏感字段脱敏,解压后体积、并发读取、浏览器缓存和扩展日志均有界,未捕获/超限明示 unavailable。
|
|
120
|
+
- 正文读取最多 8 个并发任务;已知解压后超限的响应不读取。请求关联表溢出时可能缺少 URL/hop,但保留 request_id;控制台与网络时间戳分别采用 Unix 毫秒和 CDP 单调秒,不合并为统一时间轴。
|
|
118
121
|
|
|
119
122
|
## 安全与隐私
|
|
120
123
|
|
|
121
124
|
- Hub 只监听 `127.0.0.1`;HTTP 端点拒绝任何带 `Origin` 的请求,客户端必须携带 Bearer 密钥。
|
|
122
|
-
- 扩展连接固定校验 `chrome-extension://<extension_id>` Origin
|
|
125
|
+
- 扩展连接固定校验 `chrome-extension://<extension_id>` Origin 与随机 token。同版本才注册为可控浏览器;已配对的较旧扩展仅进入维护连接,收到重载请求后校验本机文件、完成清理再自行重载。客户端握手同样要求版本一致。
|
|
123
126
|
- 配对文件 `config.json` 与生成的 `extension/config.generated.js` 含密钥:目录在 Windows 上用当前用户 SID 收紧 ACL,在 POSIX 上为 `0700`/`0600`;发布包检查会拒绝包含 `config.generated.js`。
|
|
124
127
|
- 扩展具备 `debugger` 与 `tabGroups` 权限,操作使用用户现有登录态;只应接入信任的 MCP 客户端。网页内容、控制台与网络日志均视为非可信数据。
|
|
125
128
|
- 文件上传只传路径,Hub 与模型都不接触文件内容;选择文件可能立即把内容发给网站,因此只传任务明确指定的文件。
|
|
@@ -142,4 +145,6 @@ HTTP 状态复用 diagnostics 的 Network.responseReceived 观察,按主文档
|
|
|
142
145
|
|
|
143
146
|
## 版本与兼容
|
|
144
147
|
|
|
145
|
-
`package.json`、`src/config.mjs`、`extension/manifest.json`
|
|
148
|
+
`package.json`、`src/config.mjs`、`extension/manifest.json` 的版本必须一致。MCP 示例配置使用 `@latest`,MCP 启动、`start` 和 `setup` 共用升级协调:检查已配对 Hub → 空闲 Hub 暂停接入并确认扩展清理 → 旧 Hub 退出 → 新 Hub 独占端口后同步扩展 → 旧扩展自行重载 → 确认新版重连。该自动路径要求 Hub 与扩展已经具备 0.17 的 `connection.js` 维护协议;更旧版本的首次升级必须先停止 Hub、重启 MCP 并手动重载扩展(旧 Hub 没有升级端点,旧扩展也不处理重载命令)。MCP 在 stdio 就绪前即连接 Hub,尚未调用工具的 MCP 会话也会阻止升级。有客户端、断连清理或在途请求时返回占用错误,关闭其他 MCP 连接后重试;不强制打断页面动作。
|
|
149
|
+
|
|
150
|
+
Hub 的监听端口同时保证同一配对的文件同步只有一个执行者。扩展先完整暂存,保留稳定目录本身,逐文件替换并最后提交 manifest;替换失败恢复旧文件,进程在替换中退出时通过 `.previous` 副本恢复。配对密钥、端口和自定义目录保留,旧包不得降级新版 Hub 或扩展。扩展重载记录尝试,防止失败后无限循环;派发重载不代表升级成功,启动协调仍等待实际版本。未打开的 profile 在下次连接时处理;首次安装仍需手动加载扩展。此流程不热替换正在运行的 MCP 进程。
|
package/docs/TEST-REPORT.md
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
# 验证报告
|
|
2
2
|
|
|
3
|
-
当前版本 **0.
|
|
3
|
+
当前版本 **0.17.2**(2026-10-23)。浏览器验证使用本地 fixture 和临时 profile;测试链路在各项下说明。
|
|
4
4
|
|
|
5
5
|
## 当前版本
|
|
6
6
|
|
|
7
|
+
- `npm test`:204 项通过。新增渲染文本的 expected/previous 比较与预览截取、1.5 万层深树的 full/interactive 遍历和正文合并、15 万节点观察的分页回归。用修改前的实现分别复现深树递归和宽树数组参数展开的 `Maximum call stack size exceeded`。
|
|
8
|
+
- Chromium 156 与 Edge 155 headless 完整 stdio MCP 集成:各 254 次调用通过。真实 DOM 验证 script/style/隐藏子节点字面量不会提前满足 text wait,expected 与 previous 均等待渲染文字变化;1.2 万个显式语义节点在 max_nodes=1 下完成采集和续页,分别约 15.3 秒、16.6 秒。
|
|
9
|
+
- 剩余限制:Chromium 上 12 万个显式 group 节点的真实快照调用仍触及 MCP 60 秒请求超时。迭代渲染和逐项合并只消除栈及函数参数数量上限,不减少完整 AX 采集成本;max_nodes 仅控制分页,不代表超大页面能在现有预算内完成。
|
|
10
|
+
- `npm run test:package`:仓库外安装运行通过,23 个工具、50 个发布文件,不含配对密钥;无新增工具、运行依赖或扩展权限。
|
|
11
|
+
- 本机部署:Hub 从工作区重启,健康接口返回 0.17.2 / ready;`F:\.nosis\browser-attach\extension` 的 manifest 为 0.17.2,其余 31 个非生成源码/资源文件与工作区逐字节一致。Chrome、Edge 已自动重载并上报 0.17.2 / ready;已有 MCP 连接需重新连接。
|
|
12
|
+
|
|
13
|
+
## 0.17.1 验证
|
|
14
|
+
|
|
15
|
+
- `npm test`:200 项通过。新增并发升级与冷启动、旧配对缺少 `extension_dir` 的兼容回落、`release_all` 部分失败时的错误回传与剩余控制权保留、弹窗释放失败提示和显式重试,以及原有升级、清理和连接回归。
|
|
16
|
+
- Chromium 156 与 Edge 155:`npm run test:upgrade -- --executable <路径>` 均通过。临时 profile 开启开发者模式后,两个并发启动者将 Hub 和真实扩展从当前代码改版本号构造的兼容旧协议 0.16.9 升到 0.17.1;确认同一 profile、实际 runtime 重载后的版本,以及升级后发现/接管 → AX 查询 → DOM 点击 → 查询结果 → 释放。CDP 只用于临时 profile 的开发者模式设置,页面操作走扩展与 Hub。该脚本验证升级协议本身,不代表真实 0.16 扩展能自行重载;真实旧版本首次升级仍需手动重载。
|
|
17
|
+
- `npm run test:package`:仓库外安装运行通过,23 个工具、50 个发布文件;由已安装包中的 Hub 同步稳定扩展目录并运行 stdio MCP,不含配对密钥,无新增运行依赖或扩展权限。
|
|
18
|
+
- 本机部署:Hub 已从工作区重启并返回 0.17.1 / ready;`F:\.nosis\browser-attach\extension` 已同步,manifest 为 0.17.1。Chrome、Edge 均上报 0.17.1 并已重连。
|
|
19
|
+
|
|
20
|
+
## 0.16.0 验证
|
|
21
|
+
|
|
7
22
|
- `npm test`:184 项通过。新增 offset 的变换/越界处理、延迟区间校验、默认路径不采样随机数、拖拽曲线与精确终点、batch 参数预检、真实 stdio MCP 参数转发,以及 settle/拖拽超时后停止和调试分离取消待点击的回归。
|
|
8
23
|
- Chromium 156 与 Edge 155 headless 输入集成:各 19 个场景通过(扩展 → 独立 Hub 客户端)。新增非中心可信点击、offset hover、settle、区间逐字输入、曲线 pointer 与 HTML5 拖拽;实际记录移动坐标、可信事件和按键时间,保留原有默认路径及跨屏拖拽验证。不据此声称能通过任意网站的行为验证。
|
|
9
24
|
- Chromium 156 完整 stdio MCP 集成:244 次调用通过,保留发现/接管、输入、导航、OOPIF、日志、分页及临时页清理覆盖。
|