dsh-builtin-browser 0.4.6 → 0.4.8

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.en.md +62 -491
  3. package/README.md +44 -470
  4. package/client.js +10 -10
  5. package/cordis.patch.yml +4 -4
  6. package/desktop-bridge/plugin-browser-bridge.js +1 -1
  7. package/docs/README.md +8 -4
  8. package/docs/architecture.md +82 -11
  9. package/docs/development.md +38 -0
  10. package/docs/limitations.md +49 -0
  11. package/docs/tool-reference.md +42 -42
  12. package/docs/user-guide.md +93 -37
  13. package/docs/why-browser.md +3 -3
  14. package/lib/browser/types.d.ts +2 -2
  15. package/lib/browser-electron/bridge-connection.d.ts +7 -1
  16. package/lib/browser-electron/bridge-connection.js +58 -3
  17. package/lib/browser-electron/desktop-bridge-host.d.ts +11 -0
  18. package/lib/browser-electron/desktop-bridge-host.js +21 -1
  19. package/lib/browser-electron/entry.d.ts +2 -2
  20. package/lib/browser-electron/entry.js +186 -103
  21. package/lib/browser-electron/history-store.d.ts +1 -1
  22. package/lib/browser-electron/history-store.js +1 -1
  23. package/lib/browser-electron/host-main.js +3 -3
  24. package/lib/browser-electron/provider.d.ts +32 -8
  25. package/lib/browser-electron/provider.js +97 -16
  26. package/lib/browser-electron/remote-host.js +1 -1
  27. package/lib/browser-electron/settings-store.d.ts +14 -6
  28. package/lib/browser-electron/settings-store.js +29 -9
  29. package/lib/index.d.ts +1 -1
  30. package/lib/index.js +1 -1
  31. package/lib/tool-browser/element-fields.d.ts +4 -4
  32. package/lib/tool-browser/element-fields.js +6 -6
  33. package/lib/tool-browser/index.d.ts +6 -6
  34. package/lib/tool-browser/index.js +196 -139
  35. package/package.json +2 -2
  36. package/scripts/verify-host-compat.mjs +6 -6
  37. package/src/browser/types.ts +2 -2
  38. package/src/browser-electron/bridge-connection.ts +61 -3
  39. package/src/browser-electron/desktop-bridge-host.ts +22 -1
  40. package/src/browser-electron/entry.ts +101 -9
  41. package/src/browser-electron/history-store.ts +1 -1
  42. package/src/browser-electron/host-main.ts +3 -3
  43. package/src/browser-electron/provider.ts +135 -31
  44. package/src/browser-electron/remote-host.ts +1 -1
  45. package/src/browser-electron/settings-store.ts +32 -13
  46. package/src/index.ts +1 -1
  47. package/src/tool-browser/element-fields.ts +6 -6
  48. package/src/tool-browser/index.ts +197 -140
package/CHANGELOG.md CHANGED
@@ -4,6 +4,82 @@
4
4
 
5
5
  ---
6
6
 
7
+ # 第四十四轮(2026-10-14,工具名空间:`browser_*` → `dsh_browser_*`)
8
+
9
+ 腾讯 BrowserSkill 的 DSH 插件(`@wxg-prc-cpg/browser-skill-dsh-plugin` @0.3.2)与本插件同装时,它六个工具一个都注册不上。根因不是它的 bug:双方都往**全局**工具层注册了 `browser_session`,宿主对重名直接抛错,而它把注册包在 `try/catch` 里只 `console.warn` —— 桌面版看不到 stdout,于是表现成"插件完全没反应"。用户先怀疑的是它坏了。
10
+
11
+ ## 改名
12
+
13
+ 33 个工具从 `browser_*` 移入 `dsh_browser_*`。判断依据是 issue 作者那句:**`browser_*` 是无前缀通用名空间,任何第三方浏览器插件都极可能撞上** —— 而这次六个名字里只撞了一个,就把对方整套拖下了水。
14
+
15
+ **这是破坏性变更**:文档、别人的提示词、肌肉记忆都要跟着改。**旧版本(0.4.7 及以前)不更新** —— 它们与旧版腾讯插件仍然撞,但那是已发布的事实,不做兼容层,靠 release notes 说明。
16
+
17
+ 对方上游(main 分支)也已把六个工具改名为 `bsk_*`,并把名字集中到 `tool-names.json`。两边各自划定名空间之后,同装互不干扰。
18
+
19
+ ## 一个名字不能再毁掉整套工具
20
+
21
+ 33 个工具原本是**顺序的直接注册**:第一个抛错会中断余下的 apply,用户看到的是一个"半存在"的插件——**那正是腾讯那个失败的同款形状**。现在每个调用点都走 `registerSafely`,碰撞变成一条点名报错的 WARN,其余工具照旧。
22
+
23
+ ## 两次做错的替换(自我更正)
24
+
25
+ 第一次用 PowerShell 的 `-replace` —— **它默认不区分大小写**,于是 `BROWSER_PROFILE_DIR` 和所有错误码常量一起被改名:`code === 'BROWSER_...'` 的比较全部失配,`BROWSER_PROFILE_DIR` 成了未定义标识符。tsc 当场抓到,但**测试从 250 掉到 218**(文件级崩溃)。
26
+
27
+ 第二次改用 `-creplace` 修常量,却踩了另一个:**PowerShell 5.1 把无 BOM 的 UTF-8 当 ANSI 读**,含中文的 36 个文件被双重编码,`client.js` 的界面文案全成了乱码——而 **tsc 依然通过**。
28
+
29
+ 两次都回滚重做,最终用一个 Node 脚本完成(默认区分大小写、默认 UTF-8)。**教训:批量改名这种操作,判据不能只有 tsc——它看不出编码损坏,也看不出语义错位。测试数从 250 掉到 218 才是真信号。**
30
+
31
+ **测试**:250 → 254(新增 4 条:命名空间完整性、无裸名残留、容错注册的形状、以及大写常量未被误改)。
32
+
33
+ ---
34
+
35
+ # 第四十三轮(2026-10-12,三个"看起来无关"的缺陷:载体被写死、宿主死了不换、设置读了不生效)
36
+
37
+ 这一轮的共同点不是症状,而是**判断被做了一次就再也不做了**:载体在启动时选一次、连接端口在建立时记一次、`browser.channel` 在 apply 时读一次。三次都发生在"当时是对的"的情况下,三次的后果都是"之后永远不对"。
38
+
39
+ ## 一、标签级三件套 + 裸根拦截(issue #26,@dengyun2018-commits)
40
+
41
+ 他带着一份本地 patch 来,已在 0.4.0 → 0.4.5 四个版本上实跑、每次 `apply --check` 零偏移。四条全部收下,两条判据换了实现:
42
+
43
+ **标签 URL 跟踪**:每个标签记住"最后一次被接受的 URL"。`listTabs` 不再探测它已知为空的标签——未提交的视图上那次往返只能回答"没有";而"从未导航"与"导航过但读不出来"终于可区分(此前两者都塌进同一个空字符串)。读失败时保留上次的 URL,而不是把标签报成空的。
44
+
45
+ **空白标签短路**:`snapshot` / `a11y` 在未导航的标签上立即返回空页,而不是在一个没有文档可提交的视图里跑采集器、先耗尽整个 30 秒预算。
46
+
47
+ **超时自愈**:超时的读操作**原位替换**卡死的视图(标签对调用方保持同一个 id),并抛出 `BROWSER_SNAPSHOT_TIMEOUT` / `BROWSER_A11Y_TIMEOUT`。此前视图留在会话里,于是**之后的每一次读都要再付一遍 30 秒**——`terminatePage` 只中断正在跑的脚本,并不会让视图变得可读。它还有个每视图 3 次的待终止上限,所以反复读会累积挂起的 evaluate。
48
+
49
+ **裸根拦截**:`browser_open` 拒绝不带 token 的 DSH web 根地址——它返回 401 页面,读起来像一个真站点。**判据用的是 `DSH_WEB_URL`(harness 自己导出的环境变量),而不是端口号**:这台机器的 GUI 在 3080 和 19387 上都跑过,硬编码端口会在最需要它的那次不匹配。识别陷阱靠的是形状——同源 + 根路径 + 无 token——不是数字。
50
+
51
+ ## 二、桌面壳退出后,浏览器面板跟着一起死
52
+
53
+ 用户报的是"浏览器不能正常使用了,只能重启 DSH"。
54
+
55
+ 链条是两处叠加:**载体只在启动时选一次,而且只能向上走**——自托管先注册,发现桌面 bridge 后把它换成 provider,紧接着 `selfHosted.dispose()`。**没有回退目标。**启动时那四次重试只覆盖"bridge 出现得晚",而代码注释自己写着这个交换是单向的。
56
+
57
+ **`refreshEndpoint` 也救不了,原因很精确**:它比较 port 和 token,而死掉的 shell 留下的文件**内容原封不动**——文件看着是新的,指向的是尸体。
58
+
59
+ **判据来自文件里本来就有的字段**:活的 shell 每 15 秒重写 `updatedAt`,所以**四次没刷新就不是"慢",是"没了"**。超过一分钟的端点现在被判定为墓碑,一次性上报,经由载体接口上新增的 `onLost`;entry 收到后用自托管把 provider 重新注册回来。**缺失 `updatedAt` 刻意不算过期**,否则所有比这个字段更老的 shell 都会在首次使用时就判死。
60
+
61
+ 失败信息也不再是裸的 `ECONNREFUSED`——它点名原因,因为读它的人正是决定要不要回退的那个。
62
+
63
+ ## 三、`browser.channel` 只在 apply 时读一次(issue #27,@sbtxdy)
64
+
65
+ 他给了一组对照测量:`Electron/44.5.1` 对 `Edg/155.0.0.0`,以及"改完不重启、进程里没有任何带插件自有 `--user-data-dir` 的 msedge.exe"。三条建议全收,第一条选了**热切换**而不是退让到 `restartRequired`。
66
+
67
+ **载体实时重选**:选择逻辑改成一个 `chooseCarrier()`,设置路由在写入改变 channel 时重跑它。这里有一处必须一起动:`adopt` 原有的一次性 guard 会把晚到的载体直接 `dispose` 掉——**防两个载体抢入是对的,对"用户改设置"恰好是错的**,因为那正是"写成功了、然后新载体被安静丢掉"的来源。现在换掉旧载体的是新载体,且在装好之后才释放。
68
+
69
+ **不生效的写会说出来**:响应区分"已应用"和"只存了"(`carrierRechosen`);载体由 composition 提供(桌面 shell)而 channel 无法生效时打 WARN。**对一次没人会读的写回 `ok`,是调用方唯一分不出"成功"和"什么都没做"的地方**。
70
+
71
+ **拼错的值不再静默**:`resolveChannel` 把未知值退回默认——它的注释写着这是有意为之("手改的错别字不该静默选中别的浏览器"),**但结果让错别字和"设置没生效"长得一模一样**。退回是对的,静默退回不是:现在会报出原值并列出接受集合。**缺席保持安静**,否则警告会变成噪音。
72
+
73
+ ## 四、自我更正
74
+
75
+ **第二节的光标是我的**:`BridgeConnection.refreshEndpoint` 的存在恰恰证明我知道"端口会变"这件事,但判据选成了"与当前不同",而墓碑的特征是"与当前相同但已经死了"。同一个字段的两端,我只写了会变的那一端。
76
+
77
+ **测试**:237 → 250(本轮新增 13 条:标签 URL 与空白短路 3 条、墓碑与回退 4 条、channel 重选 6 条)。`tsc` 干净。其中超时自愈那条是**形状断言**而不是行为断言——真跑 30 秒太慢——这一点写进了 commit 和给报告者的回复里,免得以后有人把它读强。
78
+
79
+ **发布**:0.4.7。`npm` 与仓库同步。
80
+
81
+ ---
82
+
7
83
  # 第四十二轮(2026-10-08,三个"能看见的"缺陷:跨会话读错、空白页堆积、升级登出)
8
84
 
9
85
  0.4.5 发布后,用户连续报了三个现象。**三个都在同一段代码的新实现里**,而它们看着毫不相干——一个是"别的会话读到我这边",一个是"一次开一堆空白页",一个是"升级后所有站点被登出"。前两个实际上是**同一个会话在两种状态下的两种表现**。