dsh-browser-playwright-codex 0.8.0 → 0.8.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/CHANGELOG.md +64 -0
- package/NOTICE.md +10 -10
- package/README.md +25 -12
- package/SECURITY.md +12 -4
- package/assets/swarm-rebuild.js +3864 -0
- package/lib/challenge.d.ts +7 -4
- package/lib/challenge.js +28 -6
- package/lib/client.js +28 -2
- package/lib/config.d.ts +1 -1
- package/lib/config.js +1 -2
- package/lib/errors.d.ts +17 -0
- package/lib/errors.js +28 -0
- package/lib/gates-patch.d.ts +41 -1
- package/lib/gates-patch.js +163 -5
- package/lib/injected.js +45 -0
- package/lib/page-actions.d.ts +24 -0
- package/lib/page-actions.js +41 -10
- package/lib/session.js +55 -9
- package/lib/snapshot-aria.d.ts +0 -20
- package/lib/snapshot-aria.js +68 -3
- package/lib/snapshot-render.js +52 -7
- package/lib/swarm-contract.d.ts +11 -5
- package/lib/swarm-contract.js +11 -5
- package/lib/swarm-curtain.js +2 -2
- package/lib/swarm-intro.js +11 -9
- package/lib/tool-types.d.ts +10 -0
- package/lib/tool.js +6 -2
- package/lib/types.d.ts +6 -0
- package/package.json +18 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
## 0.8.2 — 2026-11-12
|
|
2
|
+
|
|
3
|
+
一句话摘要:**发版门禁不再会"假绿",快照引擎第一次在真实网站上被量过**——preflight 过去只读 `ℹ fail`(而且"fail 0"是写死的字符串),被取消的用例看不出、也不报;设置页这个全仓最大的零测试模块补上了走真实 HTTP 的测试,顺手修掉"已有未标记装载行时写出第二行"的坏文件路径;智能模式(aria)的解析器与可交互集对齐后,130 个任务页的降级从 18 页降到 3 页。
|
|
4
|
+
|
|
5
|
+
### Fixed — 门禁与默认值
|
|
6
|
+
|
|
7
|
+
- **preflight 的假绿通道(最要紧)**:旧实现只解析 `ℹ fail N`,摘要里的 `fail 0` 是硬编码字符串,`cancelled` / `todo` 一次都没读。0.7.8 有 7 条用例被打成 `cancelledByParent`,对外仍说"278 通过",实际只跑了 271 条。现在判读抽成 `scripts/preflight-suite.mjs`,读全部六个计数,并把下列情形都判成硬错误:`fail > 0`、`cancelled > 0`、`todo > 0`、恒等式 `tests ≠ pass + fail + cancelled + skipped + todo`、任一计数读不到、命令非零退出、出现 `cancelledByParent > 0`。**生产脚本里不允许任何外部注入测试结果的入口**(第一版加过、被复核否掉,并留了守卫测试防止再加回来)。
|
|
8
|
+
- **`swarm.enabled` 的默认方向反了**:`config.ts` 的 schema 是 `default(false)`,而 `swarm-intro.ts` 的三个入口写成 `?? true` —— 配置整体缺失时会播。改成 `?? false`,并补测试:`config` 为 `undefined` / `{}` / `{ swarm: {} }` 三种形状都不播,另有一条 `enabled: true` 的对照防止测试空转。
|
|
9
|
+
- **设置页写出重复装载行**:补丁层里已有未标记的 `- id: browser` 行时,旧实现会再追加一次模板,同一个 id 被挂两行(与 issue #4 同一类"保存写出坏文件")。现在改为**收编**那一行(保留用户键、外面套标记、只改三个闸门);若那一行属于别的包,**拒绝写入并报错**,文件一个字节不动。
|
|
10
|
+
- **SECURITY.md 与真实行为不符**:旧文写着"页面自己的 JS 仍能离开白名单",实际名单装在浏览器 context 上、请求层就会拒。按真实行为重写,并保留两条诚实的限制(Chromium 自家网络栈里的跳转靠动作后校验最终 URL;已经停在不允许域名上的标签页仍打开、只是不驱动)。
|
|
11
|
+
|
|
12
|
+
### Fixed — 快照引擎(aria / smart 模式)
|
|
13
|
+
|
|
14
|
+
- **解析器读不懂"整行被引号包住"的节点**:Playwright 在名字含双引号时会写成 `- 'tab "Section #1" [ref=e5]'`(可能带尾冒号)。旧解析器把它算格式漂移,整页降级——MiniWoB 的标签页/折叠题共 8 页因此读不了。现在容忍外层引号 + 可选尾冒号,并加了"原来能读的行不许读坏"的守卫测试。
|
|
15
|
+
- **两套"可交互"定义对不齐**:DOM 铸造集与 aria 树的可交互集不一致,会触发对齐守卫、整页回退。对齐了这几处:`tr→row`、`td→cell`、`th→columnheader`、`li→listitem`、`table/list/p/h1-6/img` 的隐式角色;`<option>` 的可见性看它的 `<select>`;`role="presentation"/"none"` 在可聚焦链接上忽略(ARIA 规范,jQuery-UI 标签页就是这样);`<input type=number>` → `spinbutton`。
|
|
16
|
+
- **实测**:MiniWoB++ 130 个任务页里,智能模式降级 **18 → 3**;`ref` 落不到 DOM 元素 **0 页 / 0 个**;130/130 有效、0 失败。真实网站 7 页 5 站(含 GitHub 仓库页、runoob 表格页、w3school 表单页、element-plus 组件页)全部 `unresolved = 0`,点击落点逐个核对。
|
|
17
|
+
- **代价与旋钮**:GitHub 仓库页从此前的"读不了、回退 legacy(81 refs / 8,517 字符)"变成"智能模式可读(134 refs / 20,780 字符)"——结构更全、也更贵。真正决定体积的是 `snapshot.maxNodes`(默认 500),不是 `interactiveOnly`:同一页 `interactiveOnly` 是 18,351 字符 / 239 refs,**只省 12% 且 ref 反而更多**(预算重新分配,不减少总量)。README 与 PLUGIN-README 已写明这个旋钮。
|
|
18
|
+
|
|
19
|
+
### Added — 测试与流程
|
|
20
|
+
|
|
21
|
+
- **设置卡端到端测试**(`tests/settings-card.test.ts`):全仓最大的零测试模块(537 行)补上 10 条,走**真实 HTTP**(`node:http` 起服务、把设置卡注册的 handler 原样接上:方法/请求头/请求体/状态码都走真实栈)。钉住 issue #4(保存后 YAML 可重新解析、无重复键、只有一个装载行)、切开关不抹 `profileDir` 等用户配置、六个路由的 `x-dsh-plugin` 防伪头、被拒请求不动文件。其中"重复装载行"与"拒绝写入"两条做过变异验证(把修复改回去,测试立刻红)。
|
|
22
|
+
- **覆盖率**:`npm run coverage`(`scripts/coverage.mjs`)。用 Node 自带的 `--experimental-test-coverage`,不引入新依赖(本机 `@deepseek-ai/*` 是指向活运行时的软链接,不能 `npm install`)。自带报告只列被加载过的文件,脚本额外把 `src/**` 全清单求差集,**把 0 覆盖模块明着列出来**。首测:43 个模块、41 个被加载、2 个 0 覆盖(纯类型文件)。**不是门禁**。
|
|
23
|
+
- **跨仓库检查显式化**:配套件文档检查移出默认套件(`tests/cross-repo/`),默认套件的数字在任何机器上一致;没设 `DSH_TOGGLE_DIR` 时 preflight 明写**「未验证」**,不再以"跳过"冒充通过。
|
|
24
|
+
- **live 三条接进发版清单**:`docs/RELEASING.md` 新增发版清单,要求发版前手动跑 `DSH_BROWSER_LIVE=1 npm run test:live`,结论写进 Release;没跑就在 CHANGELOG 明写「本次未跑 live」。preflight 每次固定打一行「未验证:live 三条」,不再悄悄消失。
|
|
25
|
+
- **一次性发布文档挪位**:`RELEASE-0.7.0.md` / `MERGE-PROGRESS.md` 移到 `docs/releases/`(**不删**,里面有回退命令),preflight 把整个目录当历史豁免——根目录发版噪声从 5 处降到 3 处。
|
|
26
|
+
|
|
27
|
+
### live 三条:本次跑过,2/3 通过
|
|
28
|
+
|
|
29
|
+
按 `docs/RELEASING.md` 手动跑了一次 `DSH_BROWSER_LIVE=1 npm run test:live`(2026-11-12):
|
|
30
|
+
|
|
31
|
+
- ✔ `example.com renders, snapshots, and screenshots`(1.3s)
|
|
32
|
+
- ✔ `example.com rejects disallowed schemes consistently`(0.03s)
|
|
33
|
+
- ✖ `wikipedia REST summary parses through evaluate` —— **本机网络到不了 wikipedia**:`page.goto` 在 30 秒后 `NAVIGATION_TIMEOUT`(这条不经过插件的新代码,属环境不可达)
|
|
34
|
+
|
|
35
|
+
所以本次 live **未全绿**,原因记录在此;它不在 `prepublishOnly` 里,不影响发布门禁。preflight 的「未验证:live 三条」行同样保留。
|
|
36
|
+
|
|
37
|
+
## 0.8.1 — 2026-11-11
|
|
38
|
+
|
|
39
|
+
一句话摘要:**快照第一次真正"看得见状态"**——填进去的值、勾选状态进快照也进页面指纹,正常的填字和勾选不再被误报成"疑似反爬墙";密码 / 验证码 / 卡号即使有值也绝不进快照。顺带削掉真实站点快照里最贵的一类垃圾(跳转包裹 URL、同一 href 的重复打印),并让 `browser_evaluate` 返回非标量时给出能照着改的错误。**另外:进场动画重新随包分发——作者 Dhvanil Patel 于 2026-11-11 邮件书面许可打包与修改,默认仍然关闭。**
|
|
40
|
+
|
|
41
|
+
### Restored
|
|
42
|
+
|
|
43
|
+
- **`assets/swarm-rebuild.js` 回到 npm 包**:Dhvanil Patel 于 2026-11-11 邮件书面许可本项目**打包 + 修改**(原话 "you are welcome to bundle and modify it as needed"),`package.json#files` 重新列入 `assets/`(原始基线 `assets/swarm-rebuild.upstream.js` 仍只留在仓库)。**功能保持默认关闭**(`swarm.enabled: false`),在设置卡里打开才播。署名与许可切分见 `README.md` 的 Credits 与 `NOTICE.md` §3。
|
|
44
|
+
- **许可不是 MIT**:邮件许可只覆盖本项目随插件分发,没有附 MIT 许可文本,也不给第三方通用许可。第三方想复用得自己去问两位作者(Joel Califa / Dhvanil Patel)。
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- **填字 / 勾选不再被误报成"疑似反爬墙"**:`snapshotFingerprint` 原来只比 url / title / refs / role=name,`checked` / `selected` / 值的变化都不算"页面变了",正常的填字、勾选会触发 no-progress 兜底并劝用户去看窗口。现在 `scan` 收集这些状态、指纹纳入,填字和勾选算成真实变化。
|
|
49
|
+
- **快照显示输入框 / 文本域里的值**:`BrowserNode` / `ChallengeNode` 新增 `value`,模型填完能看见填了什么;`<textarea>`(角色是 `textarea`,不是 `textbox`)也覆盖;`<select>` 不打印 value(它的名字已经显示当前选项);`<option>` 只在 value 属性与文本不同时才带。
|
|
50
|
+
- **`role="combobox"` 的输入框按标签判定**:排除 value 只针对真正的 `<select>`,不再按 role 排除——自动补全搜索框常带显式 `role="combobox"`,按 role 判会把它们的值也一起藏掉。
|
|
51
|
+
- **密码 / 一次性验证码 / 卡号绝不进快照**:读取 value 前先过 `isCredentialEl`(`type=password`,或 autocomplete 含 `current-password` / `new-password` / `one-time-code` / `cc-*`),与 `browser_fill` 的凭据判据一致。
|
|
52
|
+
- **`<option>` 的名字不再被整段 select 文本污染**:`closest('label')` 会把外层 label 的全部文字塞进每个 option,下拉里所有选项名字原来看起来一模一样。
|
|
53
|
+
- **no-progress 文案改成实话**:不再猜"反爬墙"、不再要求用户去看窗口,改成"这次动作没有带来可见变化;如果是提交 / 搜索 / 跳转,页面可能还在渲染,再拍一次快照确认"。
|
|
54
|
+
|
|
55
|
+
### Performance
|
|
56
|
+
|
|
57
|
+
- **跳转包裹 URL 不再打印 160 字符**:`/ck/a?`、`/url?q=`、`l.php?u=` 这类知名跳转端点渲染成 `-> (redirect wrapper)`。实测 Bing 搜索结果页每次快照省约 6,080 字符(约 1,520 token)。
|
|
58
|
+
- **同一快照内重复 href 只打印第一次**:第二次起渲染 `-> (same as e1)`,只去重显示、不合并 ref,点击行为完全不变。实测百度结果页 552 → 263 字节,ref 4 → 4 一个不少。
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- **`browser_evaluate` 返回非标量时归一化**:数组转 JSON 字符串,`undefined` / 函数转成说明文字并附改法;对象 / 字符串 / 数字 / 布尔 / null 原样返回。DSH 执行器那层的 `value is not lossless JSON` 不再让人靠猜。
|
|
63
|
+
- **新增测试**:`tests/normalize-evaluate.test.ts`、`tests/value-privacy.test.ts`、`tests/combobox-value.test.ts`,分别钉住归一化、凭据不泄漏(有牙齿:去掉守卫立刻红)、`role=combobox` 与 `<textarea>` 的 value 显示。
|
|
64
|
+
|
|
1
65
|
## 0.8.0 — 2026-11-10
|
|
2
66
|
|
|
3
67
|
一句话摘要:**动效资产被移出 npm 发布包,swarm 默认关掉**——这是主动选的合规路径,不是修 bug:那套资产的授权状态不允许再分发,与其在授权上纠缠,不如不让它随包出去。代码一行没删,本地开发者把资产放回 `assets/` 打开开关就还是完整功能;代价是 npm 用户升级后默认看不到这个效果。顺带把 0.7.9 那批修复一起封进来——npm 上的 `latest` 一直停在 0.7.8,`v0.7.9` 只是本地 tag,所以从 0.7.8 直接升上来的用户会一次拿到两个版本的全部内容。
|
package/NOTICE.md
CHANGED
|
@@ -24,28 +24,28 @@ Covers only the two analysis documents produced *for this repository*:
|
|
|
24
24
|
|
|
25
25
|
Share and adapt for **non-commercial** purposes with attribution and share-alike; commercial use is not permitted. Legal code: [`LICENSE-DOCS`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/LICENSE-DOCS) (the licence text lives in the repository; it is not part of the npm tarball).
|
|
26
26
|
|
|
27
|
-
Note the deliberate boundary: these two documents are **not shipped in the npm package** — only `README.md`, `CHANGELOG.md`, `SECURITY.md` and `NOTICE.md` travel with the plugin, and all four are MIT (§1). As of 0.8.
|
|
27
|
+
Note the deliberate boundary: these two documents are **not shipped in the npm package** — only `README.md`, `CHANGELOG.md`, `SECURITY.md` and `NOTICE.md` travel with the plugin, and all four are MIT (§1). As of 0.8.1 the tarball also carries the third-party file described in §3, under its own written permission — that file is **not** MIT, and §1 does not cover it.
|
|
28
28
|
|
|
29
|
-
## 3. The intro effect asset — third-party code,
|
|
29
|
+
## 3. The intro effect asset — third-party code, bundled with written permission
|
|
30
30
|
|
|
31
|
-
`assets/swarm-rebuild.js` (**as of 0.8.
|
|
31
|
+
`assets/swarm-rebuild.js` (**shipped again in the npm tarball as of 0.8.1** — `package.json#files` lists `assets/`, minus the pristine baseline) is **not** this project's work. The position, stated plainly:
|
|
32
32
|
|
|
33
33
|
1. **We hold written permission from Joel Califa for the effect and its choreography** (2026-11-08, on file; his one condition was that he be credited). That credit is in [`README.md`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/README.md#credits--the-intro-effect) and in the settings card.
|
|
34
|
-
2. **
|
|
35
|
-
3. **This project claims and grants no rights in that file.** It
|
|
34
|
+
2. **We hold written permission from Dhvanil Patel for the script** (email, 2026-11-11, on file): he is "happy for you to use and adapt the animation", and answers "yes, you are welcome to bundle and modify it as needed". **Bundling and modification are both covered.** No MIT (or other OSI) licence was granted — the grant is that written email, not a licence text, and it does **not** give third parties a general licence to extract and re-use the file.
|
|
35
|
+
3. **This project claims and grants no rights in that file.** It travels inside this package under that permission only. If either author withdraws it, the file — and the feature that injects it — will be removed on request.
|
|
36
36
|
|
|
37
37
|
| Origin | What | Status |
|
|
38
38
|
|---|---|---|
|
|
39
39
|
| [califa/swarm-site](https://github.com/califa/swarm-site) — **Joel Califa** | The effect itself: the page wiped white, the swarm of cursors, and the choreography that draws boxes, text and images back. The published copy declares no licence. | Written permission, 2026-11-08, condition: credit. Done. |
|
|
40
|
-
| [DhvanilPatel/swarm-cursors](https://github.com/DhvanilPatel/swarm-cursors) — **Dhvanil Patel** | `swarm-rebuild/swarm.js` at commit `3d49e0ac` (2026-11-06). That repository declares no licence ("None yet") and its README says the original Swarm was released without one. |
|
|
40
|
+
| [DhvanilPatel/swarm-cursors](https://github.com/DhvanilPatel/swarm-cursors) — **Dhvanil Patel** | `swarm-rebuild/swarm.js` at commit `3d49e0ac` (2026-11-06). That repository declares no licence ("None yet") and its README says the original Swarm was released without one. | Written permission by email, 2026-11-11: bundle + modify. Bounded to this project. |
|
|
41
41
|
|
|
42
|
-
**Modified, and the modification is disclosed.** `assets/swarm-rebuild.js` is that upstream file **with seven changes**, applied by [`scripts/swarm-patch.mjs`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/scripts/swarm-patch.mjs): (1) the vendor's own bottom control bar is removed; (2) its four DOM fields are pointed at off-screen placeholders so the rest of the code keeps working; (3) its per-frame HUD refresh returns early; (4) the end-of-playback button updates are null-guarded — that last one is a real crash fix: without it the asset throws as soon as the animation completes; (5) scanning waits for the plugin's go-ahead (so the snapshot is taken before the page is scrolled); (6) the white background no longer fades in over 0.5 s, and on early starts the scroll environment is re-detected once after the page loads; (7) its final self-start is deferred until `<html>` exists, so the whole engine can run from `addInitScript` before the page's own scripts. The pristine upstream
|
|
42
|
+
**Modified, and the modification is disclosed.** `assets/swarm-rebuild.js` is that upstream file **with seven changes**, applied by [`scripts/swarm-patch.mjs`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/scripts/swarm-patch.mjs): (1) the vendor's own bottom control bar is removed; (2) its four DOM fields are pointed at off-screen placeholders so the rest of the code keeps working; (3) its per-frame HUD refresh returns early; (4) the end-of-playback button updates are null-guarded — that last one is a real crash fix: without it the asset throws as soon as the animation completes; (5) scanning waits for the plugin's go-ahead (so the snapshot is taken before the page is scrolled); (6) the white background no longer fades in over 0.5 s, and on early starts the scroll environment is re-detected once after the page loads; (7) its final self-start is deferred until `<html>` exists, so the whole engine can run from `addInitScript` before the page's own scripts. The patched file ships inside the npm package as of 0.8.1, while the pristine upstream baseline stays **in the repository only** (`assets/swarm-rebuild.upstream.js`, SHA-256 `6a30f19d…c7bfe`) — so anyone can diff what we changed and regenerate the patched file with `npm run swarm:patch`, or check that it still matches with `npm run swarm:check`.
|
|
43
43
|
|
|
44
|
-
**运行方式也被改了**:本项目不是等网页加载完再运行这份第三方脚本,而是通过 Playwright 的 `addInitScript` 把它放到**网页自己的脚本之前**执行(只在顶层文档、且带一个 30 秒内有效的 `window.name` 标记时启动),启动时机再由 `window.__dshSwarmGo`
|
|
44
|
+
**运行方式也被改了**:本项目不是等网页加载完再运行这份第三方脚本,而是通过 Playwright 的 `addInitScript` 把它放到**网页自己的脚本之前**执行(只在顶层文档、且带一个 30 秒内有效的 `window.name` 标记时启动),启动时机再由 `window.__dshSwarmGo` 放行控制。也就是说,第三方作品的启动流程、注入时机和运行上下文都由本项目重新安排过;这一步同样落在 Dhvanil 邮件许可的「modify」范围内。
|
|
45
45
|
|
|
46
|
-
**中文**:`assets/swarm-rebuild.js` **改过**(0.8.
|
|
46
|
+
**中文**:`assets/swarm-rebuild.js` **改过**(0.8.1 起重新随 npm 包分发;原始基线只留在仓库),改动共七处 —— ①删掉原版自带的底部控制条;②把它的四个界面字段指向离屏占位元素(否则下游代码会抛错);③让每帧的界面刷新提前返回;④播完那一下设置按钮显示状态的代码加空值保护(这一处是**真崩溃修复**:不改的话动画一播完就抛错);⑤扫描改成等插件放行、开场至少停 2.8 秒(拍快照前不滚页面);⑥白底去掉 0.5 秒淡入、第一帧就盖死,提前启动时页面加载完再重认一次滚动环境;⑦结尾自启动改成「等 `<html>` 出现」,这样整台引擎能在网页脚本之前就跑起来。**打包和修改都已获得 Dhvanil Patel 邮件书面许可(2026-11-11)**;许可只覆盖本项目随插件分发,不是给第三方的通用许可,也没有附 MIT 许可文本。补丁产物随包走,原始基线 `assets/swarm-rebuild.upstream.js` 留在仓库(SHA-256 可核对),所以任何人都能 diff 出我们改了什么,用 `npm run swarm:patch` 复原生成、用 `npm run swarm:check` 校验。
|
|
47
47
|
|
|
48
|
-
What this means for you: §1 (MIT) does **not** cover `assets/swarm-rebuild.js
|
|
48
|
+
What this means for you: §1 (MIT) does **not** cover `assets/swarm-rebuild.js`; it travels in the package under the authors' written permission to this project. That permission is **not** a licence to you — if you want to re-use that file elsewhere, ask the two authors yourself.
|
|
49
49
|
|
|
50
50
|
## 4. Third-party content that is **not** redistributed here
|
|
51
51
|
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# dsh-browser-playwright-codex
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/dsh-browser-playwright-codex) [](LICENSE) [](package.json) [](https://github.com/miqian-nomad/dsh-browser-playwright-codex/releases)
|
|
3
|
+
[](https://github.com/miqian-nomad/dsh-browser-playwright-codex/actions/workflows/ci.yml) [](https://www.npmjs.com/package/dsh-browser-playwright-codex) [](https://www.npmjs.com/package/dsh-browser-playwright-codex) [](LICENSE) [](package.json) [](https://github.com/miqian-nomad/dsh-browser-playwright-codex/releases) [](https://github.com/deepseek-ai/deepseek-harness)
|
|
4
4
|
|
|
5
|
-
> [](https://www.dsh.so/zh/artifact/dsh-browser-playwright-codex/) [](https://www.dsh.so/zh/artifact/dsh-browser-playwright-codex/)
|
|
6
6
|
|
|
7
7
|
**一句话**:让 AI 用你**已经登录的账号**在真实网页上干活 —— 填表、抓取列表、多标签查后台;浏览器窗口就在你桌面上、你随时看得见。原生弹框会被挂起、**绝不替你点「确定」**(机制级);验证码/挑战页会被识别出来,并以提示要求模型停下交给你(**提示不是阻断**)。登录/二次验证**没有探测器**,靠模型从快照看出来并停下;密码、一次性验证码、卡号字段 `browser_fill` **直接拒绝**——这类字由你本人在窗口里输。
|
|
8
8
|
|
|
@@ -70,12 +70,12 @@ dsh plugin --profile <name> add github:miqian-nomad/dsh-browser-playwright-codex
|
|
|
70
70
|
dsh plugin --profile <name> add link:<absolute path to this directory>
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
**Compatibility.** Built and tested against DSH `0.2.
|
|
74
|
-
wildcards**: peers `@deepseek-ai/cordis` `>=4.0
|
|
75
|
-
`@deepseek-ai/dsh-tools` `>=0.2.
|
|
73
|
+
**Compatibility.** Built and tested against DSH `0.2.2-rc.1`. The dependency ranges are **floors, not
|
|
74
|
+
wildcards**: peers `@deepseek-ai/cordis` `>=4.1.0`, `@deepseek-ai/dsh-llm` `>=0.2.2-rc.1`,
|
|
75
|
+
`@deepseek-ai/dsh-tools` `>=0.2.2-rc.1`, and the direct dependency `@deepseek-ai/schemastery` `^3.19.0`. The
|
|
76
76
|
floors exist so an empty project cannot resolve a very old `0.0.1-rc.*` build, while a newer harness still
|
|
77
77
|
installs. One cost of npm's prerelease rules: a prerelease whose `[major, minor, patch]` tuple differs from
|
|
78
|
-
`0.2.
|
|
78
|
+
`0.2.2` (for example `0.2.3-rc.*`) is outside a `>=0.2.2-rc.1` range, so you may see a **peer warning** — a
|
|
79
79
|
warning, not an install failure (pnpm does not enforce peer ranges strictly by default). After a harness
|
|
80
80
|
upgrade, `npm run doctor` re-checks that every named export this plugin imports still exists — that is the
|
|
81
81
|
fast way to tell "the harness moved" from "the plugin broke".
|
|
@@ -378,13 +378,26 @@ The tool schemas join the system-prompt assembly through `ctx.tools.register()`;
|
|
|
378
378
|
|
|
379
379
|
One tool schema block per tool (small, fixed), plus per-call result text proportional to the visible page, capped by ``snapshot.maxNodes`` and name/text limits. Actions return a fresh snapshot, so interactive flows cost roughly one snapshot per step.
|
|
380
380
|
|
|
381
|
+
The merged tools carry their own allowance rather than the default 1,650 characters. `browser_click` (
|
|
382
|
+
which absorbed the old separate point-click and hover tools) measures **2,165 characters** against a
|
|
383
|
+
budget of **2,400** — about **235 characters** of headroom left. `npm run cost` prints that per-tool
|
|
384
|
+
figure on every run, so it is measured, not estimated.
|
|
385
|
+
|
|
386
|
+
**The size knob is `snapshot.maxNodes`, not the reading mode.** The node cap decides how many
|
|
387
|
+
characters a snapshot can spend: at the default 500 the engine stops once 500 nodes are in the tree.
|
|
388
|
+
On a very large page whose snapshot is re-sent at every step, lowering it is the lever — the price is
|
|
389
|
+
fewer elements visible. `interactiveOnly` does **not** shrink the total: it spends the same node
|
|
390
|
+
budget on actionable elements only, so the same page can carry *more* refs that way. Measured on one
|
|
391
|
+
real page (a GitHub repository page, 2026-11-12): full snapshot **20,780 characters / 134 refs**; the
|
|
392
|
+
same page with `interactiveOnly: true` **18,351 characters / 239 refs**.
|
|
393
|
+
|
|
381
394
|
Measured with ``npm run cost`` (per-turn, resident in the system prompt):
|
|
382
395
|
|
|
383
396
|
| Surface | Tools | Schema characters | ≈ tokens/turn |
|
|
384
397
|
|---|---|---|---|
|
|
385
398
|
| Schema defaults (`Config({})`, no patch layer) | 16 | 11,283 | ≈ 3,134 |
|
|
386
399
|
| Shipped bundle layer (this package's `cordis.patch.yml`: both power gates off) | 16 | 11,283 | ≈ 3,134 |
|
|
387
|
-
| Everything registered (`registerDisabledTools: true`, plus `extract`) | 21 |
|
|
400
|
+
| Everything registered (`registerDisabledTools: true`, plus `extract`) | 21 | 16,146 | ≈ 4,485 |
|
|
388
401
|
|
|
389
402
|
This paragraph describes the 0.6.0 change; the table above is today's measurement. Three things changed
|
|
390
403
|
there, and only one of them was about size. (1) The click family was rewritten so each rule is stated once
|
|
@@ -464,20 +477,20 @@ The scenario suites originally surfaced four hazards, now fixed and regression-t
|
|
|
464
477
|
|
|
465
478
|
## Credits — the intro effect
|
|
466
479
|
|
|
467
|
-
The first-open effect (the page is wiped white, then a swarm of cursors draws the boxes, text and images back) is **not this project's work**, and its code is one third-party file — **
|
|
480
|
+
The first-open effect (the page is wiped white, then a swarm of cursors draws the boxes, text and images back) is **not this project's work**, and its code is one third-party file — **shipped inside the npm package again as of 0.8.1, with the authors' written permission** (still off by default):
|
|
468
481
|
|
|
469
482
|
- **The effect and its choreography** — [Swarm](https://github.com/califa/swarm-site) by **Joel Califa** ([swarm.joelcalifa.com](https://swarm.joelcalifa.com)). Used with his written permission (2026-11-08), on his one condition: **credit him** — this section is that credit.
|
|
470
|
-
- **The code** — `assets/swarm-rebuild.js`, from [`DhvanilPatel/swarm-cursors`](https://github.com/DhvanilPatel/swarm-cursors) at commit `3d49e0ac` (2026-11-06, file `swarm-rebuild/swarm.js`), **with seven changes** (all in [`scripts/swarm-patch.mjs`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/scripts/swarm-patch.mjs): the vendor's own control bar removed, its four DOM fields retargeted at off-screen placeholders, the per-frame HUD refresh short-circuited, the end-of-playback updates null-guarded — that one fixes a crash the removal would otherwise cause — scanning gated on the plugin's go-ahead, the 0.5 s white fade-in dropped, and its self-start deferred until `<html>` exists. The pristine baseline stays in the repository as `assets/swarm-rebuild.upstream.js`, SHA-256 `6a30f19d…c7bfe`).
|
|
483
|
+
- **The code** — `assets/swarm-rebuild.js`, from [`DhvanilPatel/swarm-cursors`](https://github.com/DhvanilPatel/swarm-cursors) at commit `3d49e0ac` (2026-11-06, file `swarm-rebuild/swarm.js`), **with seven changes** (all in [`scripts/swarm-patch.mjs`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/scripts/swarm-patch.mjs): the vendor's own control bar removed, its four DOM fields retargeted at off-screen placeholders, the per-frame HUD refresh short-circuited, the end-of-playback updates null-guarded — that one fixes a crash the removal would otherwise cause — scanning gated on the plugin's go-ahead, the 0.5 s white fade-in dropped, and its self-start deferred until `<html>` exists. **Dhvanil Patel granted written permission by email on 2026-11-11 to bundle and modify it**; that grant covers this plugin, not third-party re-use, and comes with no MIT licence text. The pristine baseline stays in the repository as `assets/swarm-rebuild.upstream.js`, SHA-256 `6a30f19d…c7bfe`).
|
|
471
484
|
|
|
472
485
|
The exact licensing split, and what is still outstanding, is recorded in [`NOTICE.md`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/NOTICE.md).
|
|
473
486
|
|
|
474
|
-
**中文**:首次打开网页的「进场特效」——页面被抹白,再由一群光标把方框、文字、图片一笔一笔画回来——**不是本项目自己的作品**。动效与编排出自 **Joel Califa** 的 [Swarm](https://github.com/califa/swarm-site),他于 2026-11-08 书面同意本项目使用,唯一条件是**署名**,此节即为署名;代码取自 [DhvanilPatel/swarm-cursors](https://github.com/DhvanilPatel/swarm-cursors) 的 `assets/swarm-rebuild.js
|
|
487
|
+
**中文**:首次打开网页的「进场特效」——页面被抹白,再由一群光标把方框、文字、图片一笔一笔画回来——**不是本项目自己的作品**。动效与编排出自 **Joel Califa** 的 [Swarm](https://github.com/califa/swarm-site),他于 2026-11-08 书面同意本项目使用,唯一条件是**署名**,此节即为署名;代码取自 [DhvanilPatel/swarm-cursors](https://github.com/DhvanilPatel/swarm-cursors) 的 `assets/swarm-rebuild.js`(改过七处)。**Dhvanil Patel 于 2026-11-11 邮件书面许可本项目打包与修改**,所以从 **0.8.1 起这份资产重新随 npm 包分发**(仍默认关闭);该许可只覆盖本插件,不附 MIT 许可文本。许可切分与仍在等的事见 `NOTICE.md`。
|
|
475
488
|
|
|
476
489
|
## License
|
|
477
490
|
|
|
478
|
-
MIT — **except `assets/swarm-rebuild.js`** (
|
|
491
|
+
MIT — **except `assets/swarm-rebuild.js`** (third-party work, shipped in the package as of 0.8.1 under the authors' written permission — no MIT licence text), which is covered by [Credits](#credits--the-intro-effect) above and [`NOTICE.md`](https://github.com/miqian-nomad/dsh-browser-playwright-codex/blob/main/NOTICE.md) §3. This project grants no rights in that file.
|
|
479
492
|
|
|
480
|
-
**中文**:插件本体与随包文档是 MIT;**`assets/swarm-rebuild.js`
|
|
493
|
+
**中文**:插件本体与随包文档是 MIT;**`assets/swarm-rebuild.js` 除外**(第三方作品,**0.8.1 起在作者书面许可下重新随包分发**,无 MIT 许可文本),本项目不对它主张也不授予任何权利,详见上文 Credits 与 `NOTICE.md` §3。
|
|
481
494
|
|
|
482
495
|
|
|
483
496
|
<!-- changelog:today -->
|
package/SECURITY.md
CHANGED
|
@@ -37,10 +37,18 @@ call — a click that raises `confirm()` returns the parked dialog instead of ac
|
|
|
37
37
|
|
|
38
38
|
**Which hosts it may touch is policy, not goodwill.** `allowedDomains` is enforced on every path that
|
|
39
39
|
can navigate: `browser_navigate`, `browser_open_tab`, every click variant (ref, text, geometric,
|
|
40
|
-
raw coordinates) and `browser_switch_tab`.
|
|
41
|
-
(`
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
raw coordinates) and `browser_switch_tab`. **The list is also installed on the browser context itself**
|
|
41
|
+
(`src/navigation-guard.ts`), so the browser — not just the tool layer — refuses a document request to a
|
|
42
|
+
host outside it. A page's own JavaScript (`location.href = …`), a `meta refresh`, a `<form>` posting
|
|
43
|
+
off-list and a page-opened popup all stop at the request; `fetch` / `xhr` / `EventSource` to an
|
|
44
|
+
off-list host are refused too, while rendering assets are left alone so a page does not look broken.
|
|
45
|
+
|
|
46
|
+
Two limits remain, and they are the honest part of this section. (1) Chromium follows a redirect inside
|
|
47
|
+
its own network stack, where request interception never sees the hop: after every action the page's
|
|
48
|
+
final URL is checked, an off-list landing is refused with `URL_NOT_ALLOWED`, and the tab is reset to
|
|
49
|
+
`about:blank`. (2) A tab that was **already** sitting on a disallowed host when this session took it over
|
|
50
|
+
(a profile written by an older version) stays open — the agent simply refuses to drive it. For hard
|
|
51
|
+
isolation from the whole host stack, still put an external network guard around it.
|
|
44
52
|
|
|
45
53
|
**`browser_cdp` is CDP with an allow-list.** Nineteen methods pass, matched by **exact name with no
|
|
46
54
|
family prefixes**: DOM reads (geometry, node lookup, attributes, markup), one focus action, the four
|