kimi-webbridge-dsh 1.4.8 → 1.4.9

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 CHANGED
@@ -1,32 +1,57 @@
1
1
  # kimi-webbridge-dsh
2
2
 
3
- Kimi 浏览器扩展(**Kimi Browser Extension**,原 Kimi WebBridge)的 dsh 插件(**基础设施 + 技能注册**)。插件本身不代理浏览器操作,而是负责:
3
+ Kimi 浏览器扩展(**Kimi Browser Extension**,原 Kimi WebBridge)的 dsh 插件(**基础设施 + 官方技能包注册**)。插件本身不代理浏览器操作,而是负责:
4
4
 
5
5
  1. **保障桥完好**:守护进程二进制缺失时自动从官方 CDN 下载(跨平台、SHA-256 校验),守护进程未运行时自动拉起;
6
- 2. **注册 skill**:启动时把随包内置的 `skill.md` 注册为运行时 skill(`ctx.skills.register`,`source: bundled`),模型通过 `skill` 工具加载它,按文档用 HTTP 行使全部浏览器能力(25 个动作);
7
- 3. **注册一个瘦工具 `kimi_webbridge`**:只有 `status` 一个动作(守护进程 + 扩展健康检查),作为其他 skill(如 x-cli 系列)的桥健康锚点。
6
+ 2. **注册官方技能包**:把**原样内置**的上游技能包(`skill/SKILL.md` + `skill/references/**`,与官方 CDN 逐字节一致、按摘要锁定)注册为运行时 skill,并把该目录作为 skill 的 `resourceBase` 暴露给模型 —— 这是 skill 正文里 `references/...` 链接能被解析的前提;
7
+ 3. **注册一个瘦工具 `kimi_webbridge`**:只有 `status` 一个动作(守护进程 + 扩展 + 已安装技能副本健康检查),作为其他 skill(如 x-cli 系列)的桥健康锚点。
8
8
 
9
9
  ## 架构
10
10
 
11
11
  | 层 | 角色 |
12
12
  |---|---|
13
- | 插件(本包) | 守护进程二进制供应 + 自动启动;apply() 时注册运行时 skill |
14
- | skill(运行时注册,随包内置 `skill.md`) | 模型经 `skill` 工具加载,按文档驱动守护进程:navigate / find_tab / snapshot / read_page / find / click / mouse_click / hover / drag / fill / key_type / send_keys / select_option / dialog / evaluate / cdp / screenshot / network / upload / save_as_pdf / scroll / wait / list_tabs / close_tab / close_session |
13
+ | 插件(本包) | 守护进程二进制供应 + 自动启动;apply() 时注册运行时 skill(含 `resourceBase`) |
14
+ | skill 正文(`skill/SKILL.md`,**上游原样内置**) | 官方文档:工具表、会话、截图/PDF、iframe 读取、CDP 焦点仿真、守护进程恢复、版本不匹配处置 |
15
+ | skill 参考文档(`skill/references/**`,**上游原样内置**) | `operations.md`(守护进程运维);`cli-creator/*`(为网站生成可复用 CLI 的完整工作流) |
16
+ | 运行时增量(`DSH_RUNTIME_SECTION`,本插件追加) | 仅 dsh 特有差异:工具名映射(`read`/`read_image`/`bash`)、`kimi_webbridge` 健康锚点、references 解析方式、不要替 dsh 跑 `install-skill` |
15
17
  | 瘦工具 `kimi_webbridge` | 仅 `status` 健康检查(自带守护进程自愈) |
16
18
 
19
+ **上游文档原样内置 + 末尾追加 dsh 差异**是刻意的分层:升级技能 = 覆盖文件,永远不需要合并散文,也就不会再次出现"文档停在旧版本"的漂移。
20
+
21
+ ## 上游文档同步(本插件的核心维护动作)
22
+
23
+ 上游把 skill 与守护进程二进制**同版本发布**在同一个 CDN:
24
+
25
+ ```
26
+ https://cdn.kimi.com/webbridge/<release>/skills/kimi-webbridge.tar.gz
27
+ https://cdn.kimi.com/webbridge/<release>/skills/kimi-webbridge-windows.tar.gz # 与上面逐字节相同
28
+ ```
29
+
30
+ 本包的 `skill/` 就是该 tar 包里的 `kimi-webbridge/` 目录,**逐字节原样**,由脚本维护:
31
+
32
+ ```bash
33
+ npm run fetch-skill # 拉取 latest,重写 skill/
34
+ node scripts/fetch-upstream-skill.mjs --version v2.0.22 # 或锁定具体版本
35
+ node scripts/fetch-upstream-skill.mjs --check # 只报告上游是否已变动(不写盘)
36
+ node scripts/fetch-upstream-skill.mjs --verify-local # 不联网:校验本地文件与清单一致
37
+ ```
38
+
39
+ `skill/UPSTREAM.json` 记录:release、tar 包 SHA-256、每个文件的 SHA-256 与字节数、抓取时间。脚本拒绝安装 frontmatter 版本与 release 不一致的包,也拒绝两个平台变体不一致的情况。
40
+
17
41
  ## 安装(一次性,零手工配置)
18
42
 
19
43
  ```powershell
20
44
  dsh plugin --profile web add kimi-webbridge-dsh
21
45
  ```
22
46
 
23
- 本包声明了 `dsh.bundle.patch`:`dsh plugin add` 会自动把它登记进 profile 的 bundle 层(`dsh.profile.bundles`),**无需手动编辑任何 cordis.patch.yml**。重启一次 `dsh web`:启动时插件把 skill 注册进运行时 registry,新会话的 skill 目录中即出现 `kimi-webbridge`。
47
+ 本包声明了 `dsh.bundle.patch`:`dsh plugin add` 会自动把它登记进 profile 的 bundle 层(`dsh.profile.bundles`),**无需手动编辑任何 cordis.patch.yml**。重启一次 `dsh web`:启动时插件把技能包注册进运行时 registry,新会话的 skill 目录中即出现 `kimi-webbridge`。
24
48
 
25
49
  ## 用法(模型视角)
26
50
 
27
- 1. 需要真实浏览器时,加载 `kimi-webbridge` skill(触发词:browser / webpage / open URL / 浏览器 / 网页 / 截图……);
51
+ 1. 需要真实浏览器时,加载 `kimi-webbridge` skill(触发词:browser / webpage / open URL / 浏览器 / 网页 / 截图……;"给某个网站做个可复用的 CLI" 也走这个 skill);
28
52
  2. 先用 `kimi_webbridge` 工具的 `status` 确认守护进程 + 扩展健康(插件自动补装/拉起二进制);
29
- 3. 按 skill 文档向 `POST http://127.0.0.1:10086/command` 发送 `{action, args, session}` 行使浏览器能力。Windows 上必须用临时文件承载 JSON(shell 会破坏非 ASCII 文本),skill 里有完整说明。
53
+ 3. 按 skill 文档向 `POST http://127.0.0.1:10086/command` 发送 `{action, args, session}`。技能正文里的 `references/...` 路径以 skill 加载时返回的 `resourceBase` 目录为基准,用 `read` 工具读取。
54
+ 4. Windows 上必须用临时文件承载 JSON(shell 会破坏非 ASCII 文本),skill 里有完整说明。
30
55
 
31
56
  ## 依赖
32
57
 
@@ -35,17 +60,32 @@ dsh plugin --profile web add kimi-webbridge-dsh
35
60
 
36
61
  ### 版本对齐
37
62
 
38
- 插件按官方 CDN 的 `version.json` 供应守护进程,因此始终与官方发布对齐;上表的存档哈希对应 **v2.0.8**(守护进程与扩展的产品名已更名为 Kimi Browser Extension)。
63
+ 插件按官方 CDN 的 `version.json` 供应守护进程,因此始终与官方发布对齐;下表哈希对应 **v2.0.22**(守护进程与扩展的产品名已更名为 Kimi Browser Extension)。
64
+
65
+ `kimi_webbridge` 的 `status` 会原样透出守护进程的 `update_available`(有更新时)、`version_mismatch`(守护进程与扩展不同步时)、`skills`(守护进程在各 agent 运行时里发现的技能副本)与 `skill_mismatch`(这些副本与扩展不同步时)。按官方约定:出现这些字段时**不要**自动执行 `upgrade` / `stop` / `restart` / `uninstall`(它们会杀掉正在运行的守护进程),而应把字段里的 `command` 原样交给用户执行。
39
66
 
40
- `kimi_webbridge` 的 `status` 会原样透出守护进程的 `update_available`(有更新时)与 `version_mismatch`(守护进程与扩展不同步时)字段。按官方约定:这两个字段出现时**不要**自动执行 `upgrade` / `stop` / `restart` / `uninstall`(它们会杀掉正在运行的守护进程),而应把字段里的 `command` 原样交给用户执行。
67
+ > dsh 不在守护进程识别/安装技能的运行时列表内(它只认 Claude Code / Codex / Hermes / OpenClaw / Kimi),所以 `skills` 为空是 dsh 下的正常结果 —— dsh 拿到技能的唯一途径就是本插件。
68
+
69
+ ### 上游能力对齐(v2.0.8 → v2.0.22)
70
+
71
+ 本插件曾停留在按 v2.0.8 手写的文档上。改为内置上游技能包后,以下上游变化自动跟进(也记录在此便于回顾):
72
+
73
+ | 上游版本 | 新增/变化 |
74
+ |---|---|
75
+ | v2.0.16 | **CDP 焦点仿真**:后台标签页的真实输入需先 `cdp Emulation.setFocusEmulationEnabled {"enabled":true}`;`Page.bringToFront` 语义重写(先开仿真、不抢用户焦点);`Target.activateTarget` 被拒绝 |
76
+ | v2.0.17 | **cli-creator 工作流**(`references/cli-creator/*` 五篇):为网站生成可复用 CLI(勘探协议 → 实现 → 配套 skill);`network` 增加 `bodyError` 语义(`detail` 必须在 `stop` 之前调用) |
77
+ | v2.0.21 | **iframe/frame 读取**:`snapshot` 返回 `frames: [{frame, url, size}]`、`read_page {"frame":"#f1"}`、`wait {"frame":"any"}`;取代旧的"跨域 iframe 请直接导航"限制 |
78
+ | v2.0.9–v2.0.15 / v2.0.18–v2.0.20 / v2.0.22 | 文档无实质变化(v2.0.22 仅改 frontmatter 版本号) |
79
+
80
+ 另有早已存在于上游、但旧手写文档遗漏的部分:`ok/data` 回包信封与 `extension_not_connected` 错误码、`find_tab` 按 host 匹配、`status` 的 `skills` / `skill_mismatch`、守护进程 `install-skill` / `upgrade` 子命令、`references/operations.md`。
41
81
 
42
82
  ### 兼容性(dsh 版本)
43
83
 
44
- 插件只 import 宿主提供的 `@deepseek-ai/*` 包,并声明为 `peerDependencies`(不打包自己的副本),所以与 dsh 版本解耦;已在 **dsh 0.1.5-rc.1** 上验证(工具注册、skill 注册、system prompt 注入、守护进程自愈均正常)。
84
+ 插件只 import 宿主提供的 `@deepseek-ai/*` 包,并声明为 `peerDependencies`(不打包自己的副本),所以与 dsh 版本解耦;已在 **dsh 0.1.7-rc.2** 上验证:工具注册、skill 注册(含 `resourceBase` 与 references 解析)、system prompt 注入、`kimi_webbridge status` 健康检查均正常。技能注册走 `ctx.skills.register`(运行时技能),并额外传入 `resourceBase: { kind: "directory", path: <skill 目录> }`——宿主会把该目录作为 skill 的基准目录渲染给模型。
45
85
 
46
86
  | peer | 声明范围 |
47
87
  |---|---|
48
- | `@deepseek-ai/dsh-tools` | `^0.1.0-rc.7 \|\| ^0.1.1-rc.2 \|\| ^0.1.2-rc.1 \|\| ^0.1.5-rc.1` |
88
+ | `@deepseek-ai/dsh-tools` | `^0.1.0-rc.7 \|\| ^0.1.1-rc.2 \|\| ^0.1.2-rc.1 \|\| ^0.1.5-rc.1 \|\| ^0.1.7-rc.2` |
49
89
  | `@deepseek-ai/dsh-llm` | 同上 |
50
90
  | `@deepseek-ai/schemastery` | `^3.18.1` |
51
91
 
@@ -55,13 +95,15 @@ dsh plugin --profile web add kimi-webbridge-dsh
55
95
 
56
96
  插件根据运行时硬件自动选择并下载对应的守护进程二进制(含 SHA-256 校验,与官方清单核对后才安装):
57
97
 
58
- | 平台 | 二进制 | 存档哈希(v2.0.8) |
98
+ | 平台 | 二进制 | 存档哈希(v2.0.22) |
59
99
  |---|---|---|
60
- | Windows x64 | `windows-amd64.exe` | `eec1976d…433c6` |
61
- | macOS arm64 | `darwin-arm64` | `04532d77…0a261` |
62
- | macOS x64 | `darwin-amd64` | `931769e9…8cc0c` |
63
- | Linux arm64 | `linux-arm64` | `ee201b44…34a3c` |
64
- | Linux x64 | `linux-amd64` | `61de010c…ce271` |
100
+ | Windows x64 | `windows-amd64.exe` | `8e9dfc5b…eb338` |
101
+ | macOS arm64 | `darwin-arm64` | `f36dfeba…901f0` |
102
+ | macOS x64 | `darwin-amd64` | `ad9aba7d…8d4ba` |
103
+ | Linux arm64 | `linux-arm64` | `6f083744…5527f` |
104
+ | Linux x64 | `linux-amd64` | `0d1b2bf5…fdcf6` |
105
+
106
+ 技能包(两个平台变体逐字节相同)v2.0.22 的 tar 摘要:`4068a646…678ed1`。
65
107
 
66
108
  不支持的平台组合会明确报错并提示手动安装。
67
109
 
@@ -76,18 +118,21 @@ dsh plugin --profile web add kimi-webbridge-dsh
76
118
 
77
119
  下载流程:先落盘为临时文件(`kimi-webbridge(.exe).tmp-{pid}-{时间戳}`)→ SHA-256 与官方清单核对 → 匹配才重命名为最终路径;不匹配则删除临时文件并中止,任何未验证的二进制都不会留在磁盘。该路径与官方安装器 / `kimi-webbridge upgrade` 命令完全一致,插件、官方工具共用同一份守护进程。
78
120
 
79
- ## 功能(skill 承载,25 个动作)
121
+ ## 功能(上游技能承载)
80
122
 
81
- | 能力 | 动作 |
123
+ 以官方文档为准(见 `skill/SKILL.md`),主要能力域:
124
+
125
+ | 能力 | 说明 |
82
126
  |---|---|
83
- | 导航 / 标签 | `navigate`、`find_tab`、`list_tabs`、`close_tab`、`close_session` |
84
- | 读页面 | `snapshot`(accessibility tree + `@e` 引用)、`read_page`(全文文本)、`find`(页面内搜索) |
85
- | 点击 / 输入 | `click`、`mouse_click`(真实鼠标,可信输入)、`hover`、`drag`、`fill`、`key_type`(键入,可信)、`send_keys`(组合键)、`select_option`、`dialog` |
127
+ | 导航 / 标签 | `navigate`、`find_tab`(按 host 匹配本会话标签页,`active:true` 借用用户正在看的标签页)、`list_tabs`、`close_tab`、`close_session` |
128
+ | 读页面 | `snapshot`(accessibility tree + `@e` 引用,并在有 iframe 时返回 `frames`)、`read_page`(全文文本,可 `{"frame":"#f1"}` 读 frame)、`find` |
129
+ | 点击 / 输入 | `click`、`fill`(含 ProseMirror/Lexical/Slate 等 contenteditable)、`hover`、`drag`、`select_option`、`dialog`、`scroll`、`wait`(支持 `{"frame":"any"}`) |
130
+ | 可信输入 | `mouse_click` / `key_type` / `send_keys`(CDP 真实输入);后台标签页需先用 `cdp` 打开焦点仿真 |
86
131
  | JS / CDP | `evaluate`(页面上下文)、`cdp`(chrome.debugger 直通) |
87
132
  | 截图 / PDF | `screenshot`、`save_as_pdf`(写文件、返回路径) |
88
- | 网络 / 上传 | `network`(请求捕获)、`upload`(文件上传) |
89
- | 滚动 / 等待 | `scroll`(滚动/定位)、`wait`(等待文本/选择器条件) |
133
+ | 网络 / 上传 | `network`(请求捕获;`detail` 须在 `stop` 前)、`upload` |
90
134
  | 会话分组 | 一个任务 = 一个 session = 一个标签页组,可一键清理 |
135
+ | 生成 CLI | `references/cli-creator/*`:为某个网站做可复用 CLI + 配套 skill(勘探 → 实现 → 验证) |
91
136
 
92
137
  ## 配置(可选)
93
138
 
@@ -97,7 +142,7 @@ dsh plugin --profile web add kimi-webbridge-dsh
97
142
  - id: kimi-webbridge
98
143
  config:
99
144
  autoInstallDaemon: false
100
- daemonVersion: v2.0.8
145
+ daemonVersion: v2.0.22
101
146
  ```
102
147
 
103
148
  | 配置项 | 默认值 | 说明 |
@@ -106,9 +151,18 @@ dsh plugin --profile web add kimi-webbridge-dsh
106
151
  | `requestTimeoutMs` | `120000` | 单次请求超时(毫秒) |
107
152
  | `autoStartDaemon` | `true` | 守护进程未运行时自动启动 |
108
153
  | `autoInstallDaemon` | `true` | 二进制缺失时自动从官方 CDN 下载安装(关闭后需手动[从官方安装](https://www.kimi.com/products/kimi-webbridge)) |
109
- | `daemonVersion` | `latest` | 自动安装时的版本(可固定如 `v2.0.8`,需带 `v` 前缀与 CDN 路径一致;建议与扩展版本匹配) |
154
+ | `daemonVersion` | `latest` | 自动安装时的版本(可固定如 `v2.0.22`,需带 `v` 前缀与 CDN 路径一致;建议与扩展版本匹配) |
110
155
  | `registerSkill` | `true` | 启动时把 `kimi-webbridge` skill 注册进运行时 registry(关闭后不注册) |
111
156
 
157
+ ## 开发
158
+
159
+ ```bash
160
+ npm run check # node --check lib/index.js + 校验 skill/ 与 UPSTREAM.json 一致
161
+ npm run fetch-skill # 重新内置上游技能包(更新 skill/ 与 UPSTREAM.json)
162
+ ```
163
+
164
+ CI:`publish.yml` 在发布前跑 `npm run check`(离线、必须通过)并**报告**上游漂移(不阻断发布);`skill-drift.yml` 每周一跑 `--check`,上游一有变动就让任务失败,避免再次静默落后。
165
+
112
166
  ## 移除
113
167
 
114
168
  ```powershell
package/lib/index.js CHANGED
@@ -17,8 +17,9 @@ import { fileURLToPath } from "node:url";
17
17
  * Infrastructure-only bridge plugin:
18
18
  * - provisions the daemon binary (official Kimi CDN, SHA-256 verified) and
19
19
  * auto-starts it, keeping the bridge healthy;
20
- * - registers the packaged skill.md (the full 25-action HTTP protocol for
21
- * driving the user's real browser) as a runtime skill via ctx.skills;
20
+ * - registers the skill package vendored under skill/ (the official upstream
21
+ * SKILL.md plus its references/) as a runtime skill via ctx.skills, with the
22
+ * directory exposed as its resource base;
22
23
  * - registers one thin tool `kimi_webbridge` whose only action is `status`
23
24
  * (daemon + extension health check) as an anchor for other skills.
24
25
  *
@@ -94,15 +95,112 @@ function manualInstallHint() {
94
95
  /** Skill identity registered into the host skill registry. */
95
96
  const SKILL_NAME = "kimi-webbridge";
96
97
 
97
- /** Model-facing routing description shown in the skill catalog. */
98
- const SKILL_DESCRIPTION = `Drive the user's real browser (with their login sessions) through the local kimi-webbridge daemon at 127.0.0.1:10086: navigate, click, type, read, screenshot, evaluate JS, raw CDP, network capture, file upload, PDF export, and tab/session management. Use this skill whenever the user wants to interact with websites, automate browser tasks, scrape web content, or do anything that needs a real browser — even simple-sounding requests. Also use when the user mentions "browser", "webpage", "open URL", "screenshot", or asks to read/interact with any website (浏览器 / 网页 / 打开网页 / 截图 / 页面).`;
98
+ /** Vendored upstream skill package: `skill/SKILL.md` plus its `references/` tree. */
99
+ const SKILL_DIR = fileURLToPath(new URL("../skill/", import.meta.url));
100
+
101
+ /** The upstream instruction file inside {@link SKILL_DIR}. */
102
+ const SKILL_PATH = join(SKILL_DIR, "SKILL.md");
103
+
104
+ /**
105
+ * Extra routing keywords appended to the description upstream ships.
106
+ *
107
+ * The official description is English; these are the Chinese terms the same users
108
+ * type. Keeping them here (rather than rewriting the vendored frontmatter) is what
109
+ * lets `skill/UPSTREAM.json` stay byte-exact against the CDN.
110
+ */
111
+ const SKILL_EXTRA_KEYWORDS = "Also use when the user mentions 浏览器 / 网页 / 打开网页 / 截图 / 页面.";
112
+
113
+ /** Used only when the vendored SKILL.md frontmatter cannot be parsed; a missing description must never disable the skill. */
114
+ const FALLBACK_SKILL_DESCRIPTION = `Drive the user's real browser (their login sessions) through the local kimi-webbridge daemon: navigate, read pages and iframes, click, type, screenshot, evaluate JS, raw CDP, network capture, file upload, PDF export, tabs and sessions — including building a reusable CLI for a website. Use whenever a task needs a real browser. (浏览器 / 网页 / 打开网页 / 截图 / 页面)`;
115
+
116
+ /**
117
+ * The section appended after the vendored upstream instructions.
118
+ *
119
+ * Everything above it is upstream's document verbatim; this carries only the deltas
120
+ * that are true in dsh (tool names, the status anchor, where references live), plus
121
+ * the upstream release the copy came from — which stripping the frontmatter would
122
+ * otherwise hide from the model. Keeping the split means refreshing the skill never
123
+ * has to merge prose.
124
+ *
125
+ * @param version - the upstream version stamped in the vendored SKILL.md, when known.
126
+ * @returns the markdown block to append.
127
+ */
128
+ function dshRuntimeSection(version) {
129
+ const provenance = typeof version === "string" && version.length > 0
130
+ ? `This skill is vendored verbatim from the official upstream release v${version}; \`skill/UPSTREAM.json\` records its digests.`
131
+ : "This skill is vendored verbatim from the official upstream release.";
132
+ return `
133
+
134
+ ## dsh runtime notes
135
+
136
+ The kimi-webbridge-dsh plugin adds these notes for this harness; where they conflict with the text above, they win.
137
+
138
+ ${provenance}
139
+
140
+ - **Health check first**: before driving the browser, call the \`kimi_webbridge\` tool with action \`status\`. It reports daemon + extension health and auto-provisions this machine — it installs the daemon binary from the official CDN (SHA-256 checked against the release manifest) when it is missing, starts it, and retries once. The binary lives at \`~/.kimi-webbridge/bin/kimi-webbridge\` and is not on \`PATH\`; running it with \`start\` yourself is also safe and idempotent.
141
+ - **Tool names in this harness**: file tools are \`read\`, \`read_image\`, \`write\` and \`edit\`; the shell tool is \`bash\`; \`kimi_webbridge\` is the status anchor. Where the text above says "open it with the Read tool" for a screenshot or PDF, use \`read_image\`.
142
+ - **References**: paths such as \`references/operations.md\` and \`references/cli-creator/workflow.md\` resolve against the base directory reported when this skill loads. Read them with the \`read\` tool.
143
+ - **Skills installer**: the daemon's own \`install-skill\` / \`upgrade\` skill refresh targets the runtimes it detects (Claude Code, Codex, Hermes, OpenClaw, Kimi) — dsh is not one of them. This plugin is how dsh receives this skill, so never run \`install-skill\` on dsh's behalf.
144
+ - **Notices**: when \`status\` reports \`version_mismatch\`, \`update_available\` or \`skill_mismatch\`, hand the user that field's \`command\` verbatim. Never run \`stop\` / \`restart\` / \`upgrade\` / \`uninstall\` yourself — they kill the user's running daemon.
145
+ `;
146
+ }
147
+
148
+ /**
149
+ * Parse the two frontmatter fields this plugin needs from the vendored SKILL.md.
150
+ *
151
+ * A deliberately small YAML subset parser: the upstream frontmatter is a fixed shape
152
+ * (`name`, a `description` block scalar, `metadata.version`), and pulling in a YAML
153
+ * dependency for three fields would cost more than it buys.
154
+ *
155
+ * @param raw - the SKILL.md text.
156
+ * @returns the description, stamped version and body without frontmatter; fields are null when absent.
157
+ */
158
+ function parseFrontmatter(raw) {
159
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(raw);
160
+ if (match === null) return { description: null, version: null, body: raw.trim() };
161
+ let description = null;
162
+ let version = null;
163
+ let block = null;
164
+ for (const line of match[1].split(/\r?\n/u)) {
165
+ if (block !== null) {
166
+ if (/^\s+\S/u.test(line)) {
167
+ block.push(line.trim());
168
+ continue;
169
+ }
170
+ description = block.join(" ").trim();
171
+ block = null;
172
+ }
173
+ if (/^description:\s*[|>]\s*$/u.test(line)) {
174
+ block = [];
175
+ continue;
176
+ }
177
+ const inline = /^description:\s*(\S.*)$/u.exec(line);
178
+ if (inline !== null) {
179
+ description = inline[1].trim();
180
+ continue;
181
+ }
182
+ const stamped = /^\s+version:\s*"?([^"\s]+)"?\s*$/u.exec(line);
183
+ if (stamped !== null) version = stamped[1];
184
+ }
185
+ if (block !== null) description = block.join(" ").trim();
186
+ return { description, version, body: raw.slice(match[0].length).trim() };
187
+ }
99
188
 
100
189
  /**
101
- * Read the packaged skill body (markdown instructions, no frontmatter).
102
- * @returns the skill body text.
190
+ * Load the vendored upstream skill package.
191
+ *
192
+ * @returns the routing description and the content to register (upstream body plus the
193
+ * dsh runtime notes, which carry the upstream release the copy came from).
103
194
  */
104
- function readSkillBody() {
105
- return readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "skill.md"), "utf8");
195
+ function readSkillPackage() {
196
+ const { description, version, body } = parseFrontmatter(readFileSync(SKILL_PATH, "utf8"));
197
+ if (typeof description !== "string" || description.length === 0) {
198
+ console.warn(`kimi-webbridge: ${SKILL_PATH} has no frontmatter description; falling back to the built-in routing text`);
199
+ }
200
+ return {
201
+ description: `${description ?? FALLBACK_SKILL_DESCRIPTION} ${SKILL_EXTRA_KEYWORDS}`,
202
+ content: `${body}${dshRuntimeSection(version)}`
203
+ };
106
204
  }
107
205
 
108
206
  /** Underlying transport `code` for a rejected `fetch`, which buries it one level down in `cause`. */
@@ -360,11 +458,15 @@ function apply(ctx, config = {}) {
360
458
 
361
459
  if (registerSkill) {
362
460
  try {
461
+ const skill = readSkillPackage();
462
+ // resourceBase is what lets the model resolve the upstream document's
463
+ // "references/..." links: the host renders it as this skill's base directory.
363
464
  ctx.skills.register({
364
465
  name: SKILL_NAME,
365
- description: SKILL_DESCRIPTION,
466
+ description: skill.description,
366
467
  source: "bundled",
367
- content: readSkillBody()
468
+ content: skill.content,
469
+ resourceBase: { kind: "directory", path: SKILL_DIR }
368
470
  });
369
471
  } catch (error) {
370
472
  // Never break plugin startup over skill registration; the status tool still works.
@@ -375,12 +477,12 @@ function apply(ctx, config = {}) {
375
477
  ctx.systemPrompt.section({
376
478
  name: "tool:kimi-webbridge",
377
479
  order: 105,
378
- text: "kimi-webbridge: the local kimi-webbridge daemon (127.0.0.1:10086) bridges to the user's real browser with their login sessions; this plugin provisions the daemon binary and keeps it running. The `kimi_webbridge` tool is only the status health check (daemon + extension). For any browser automation (navigation, reading pages, clicking, typing, filling forms, screenshots, JS evaluation, CDP, uploads, PDF export, tab management), load the kimi-webbridge skill and drive the daemon over HTTP exactly as that skill documents."
480
+ text: "kimi-webbridge: the local kimi-webbridge daemon (127.0.0.1:10086) bridges to the user's real browser with their login sessions; this plugin provisions the daemon binary, keeps it running, and registers the official upstream skill package (with its references/ directory). The `kimi_webbridge` tool is only the status health check (daemon + extension + installed skill copies). For any browser work — navigation, reading pages and iframes, clicking, typing, form filling, trusted input via CDP focus emulation, screenshots, JS/CDP, network capture, uploads, PDF export, tabs and sessions, and building a reusable CLI for a website — load the kimi-webbridge skill and drive the daemon over HTTP exactly as that skill (and its references) documents."
379
481
  });
380
482
 
381
483
  ctx.tools.register(defineTool({
382
484
  name: "kimi_webbridge",
383
- description: "Health check for the local kimi-webbridge bridge (daemon at " + baseUrl + " and the browser extension). The plugin auto-provisions the daemon: it installs the binary from the official Kimi CDN when missing and starts it, then retries once. Returns daemon version/uptime, extension_connected, plus version (daemon) and extension_version (extension) — a mismatch means the components have drifted (the extension likely auto-updated). This tool does NOT perform browser actions — for navigation, clicking, typing, reading pages, screenshots, JS evaluation, CDP, uploads, PDF export and tab management, load the kimi-webbridge skill, which documents the full 25-action HTTP protocol (POST " + baseUrl + "/command) to drive the user's real browser.",
485
+ description: "Health check for the local kimi-webbridge bridge (daemon at " + baseUrl + " and the browser extension). The plugin auto-provisions the daemon: it installs the binary from the official Kimi CDN when missing and starts it, then retries once. Returns daemon version/uptime, extension_connected, plus version (daemon) and extension_version (extension) — a mismatch means the components have drifted (the extension likely auto-updated) — and the upstream notices skills, version_mismatch, update_available and skill_mismatch. This tool does NOT perform browser actions — for navigation, reading pages and iframes, clicking, typing, screenshots, JS/CDP, trusted input, network capture, uploads, PDF export, tabs/sessions, or building a reusable CLI for a website, load the kimi-webbridge skill, which documents the daemon's tool protocol (POST " + baseUrl + "/command) and ships its references/ alongside.",
384
486
  parameters: {
385
487
  action: {
386
488
  type: "string",
@@ -405,7 +507,7 @@ function apply(ctx, config = {}) {
405
507
  type: "text",
406
508
  text: daemonAhead
407
509
  ? `⚠️ the browser extension (${value.extension_version}) is behind the daemon (${value.version}) — ask the user to update the extension, then retry.`
408
- : `⚠️ version drift: daemon ${value.version} vs extension ${value.extension_version} — the browser extension likely auto-updated ahead of the daemon. Re-audit the 25-action skill list and update the daemon.`
510
+ : `⚠️ version drift: daemon ${value.version} vs extension ${value.extension_version} — the browser extension likely auto-updated ahead of the daemon. Re-audit the skill against the new tool surface and update the daemon.`
409
511
  });
410
512
  }
411
513
  // The official convention: surface the release fields verbatim and let the
@@ -417,6 +519,22 @@ function apply(ctx, config = {}) {
417
519
  text: `⬆️ update available: daemon ${update.current ?? "?"} → ${update.latest ?? "?"} — tell the user and hand them this command verbatim; do NOT run it yourself: ${update.command}`
418
520
  });
419
521
  }
522
+ // Installed skill copies the daemon found in the agent runtimes it manages.
523
+ // dsh is not one of them, so an empty list is the normal dsh result.
524
+ const skills = value?.skills;
525
+ if (Array.isArray(skills) && skills.length > 0) {
526
+ const listed = skills
527
+ .map((entry) => `${entry?.agent ?? "?"}@${entry?.version ?? "?"}${typeof entry?.path === "string" ? ` (${entry.path})` : ""}`)
528
+ .join("; ");
529
+ blocks.push({ type: "text", text: `installed skill copies: ${listed}` });
530
+ }
531
+ const skillMismatch = value?.skill_mismatch;
532
+ if (skillMismatch !== null && typeof skillMismatch === "object" && typeof skillMismatch.command === "string") {
533
+ blocks.push({
534
+ type: "text",
535
+ text: `⚠️ installed kimi-webbridge skill copies are out of step with the extension (${skillMismatch.extension_version ?? "?"}) — tell the user and hand them this command verbatim; do NOT run it yourself: ${skillMismatch.command}`
536
+ });
537
+ }
420
538
  return blocks;
421
539
  }
422
540
  },
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "kimi-webbridge-dsh",
3
- "description": "Infrastructure plugin for dsh: provisions the kimi-webbridge daemon (auto-install with SHA-256 verification, auto-start) and registers the kimi-webbridge skill that documents the full 25-action browser protocol. Registers a thin kimi_webbridge tool (status health check only).",
4
- "version": "1.4.8",
3
+ "description": "Infrastructure plugin for dsh: provisions the kimi-webbridge daemon (auto-install with SHA-256 verification, auto-start) and registers the official upstream skill package (SKILL.md + references/, vendored from the CDN and digest-pinned) as a runtime skill. Registers a thin kimi_webbridge tool (status health check only).",
4
+ "version": "1.4.9",
5
5
  "license": "MIT",
6
- "repository": { "type": "git", "url": "git+https://github.com/cfanmaoli/kimi-webbridge-dsh.git" },
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/cfanmaoli/kimi-webbridge-dsh.git"
9
+ },
7
10
  "type": "module",
8
11
  "keywords": [
9
12
  "dsh",
@@ -12,6 +15,7 @@
12
15
  "webbridge",
13
16
  "browser",
14
17
  "automation",
18
+ "skill",
15
19
  "plugin",
16
20
  "cordis"
17
21
  ],
@@ -32,13 +36,18 @@
32
36
  },
33
37
  "files": [
34
38
  "lib/index.js",
35
- "skill.md",
39
+ "skill",
40
+ "scripts",
36
41
  "README.md",
37
42
  "cordis.patch.yml"
38
43
  ],
44
+ "scripts": {
45
+ "check": "node --check lib/index.js && node scripts/fetch-upstream-skill.mjs --verify-local",
46
+ "fetch-skill": "node scripts/fetch-upstream-skill.mjs"
47
+ },
39
48
  "peerDependencies": {
40
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.7 || ^0.1.1-rc.2 || ^0.1.2-rc.1 || ^0.1.5-rc.1",
41
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.7 || ^0.1.1-rc.2 || ^0.1.2-rc.1 || ^0.1.5-rc.1",
49
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.7 || ^0.1.1-rc.2 || ^0.1.2-rc.1 || ^0.1.5-rc.1 || ^0.1.7-rc.2",
50
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.7 || ^0.1.1-rc.2 || ^0.1.2-rc.1 || ^0.1.5-rc.1 || ^0.1.7-rc.2",
42
51
  "@deepseek-ai/schemastery": "^3.18.1"
43
52
  }
44
- }
53
+ }