@zmainer/dsh-wx-bridge 1.0.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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -0
  3. package/cordis.patch.yml +3 -0
  4. package/lib/client.js +440 -0
  5. package/lib/index.js +650 -0
  6. package/lib/kernel/acp-overlay-chat.yml +26 -0
  7. package/lib/kernel/acp-overlay.yml +22 -0
  8. package/lib/kernel/acp-preset-shim.mjs +162 -0
  9. package/lib/kernel/acp.mjs +232 -0
  10. package/lib/kernel/bridge.mjs +1341 -0
  11. package/lib/kernel/keeper.mjs +302 -0
  12. package/lib/kernel/second-brain-contract.txt +7 -0
  13. package/lib/pairing.js +225 -0
  14. package/lib/vendor/qr-svg.cjs +58 -0
  15. package/lib/vendor/qrcode-core/LICENSE +10 -0
  16. package/lib/vendor/qrcode-core/NOTICE.md +21 -0
  17. package/lib/vendor/qrcode-core/alignment-pattern.js +83 -0
  18. package/lib/vendor/qrcode-core/alphanumeric-data.js +59 -0
  19. package/lib/vendor/qrcode-core/bit-buffer.js +37 -0
  20. package/lib/vendor/qrcode-core/bit-matrix.js +65 -0
  21. package/lib/vendor/qrcode-core/byte-data.js +30 -0
  22. package/lib/vendor/qrcode-core/dijkstrajs.LICENSE +19 -0
  23. package/lib/vendor/qrcode-core/dijkstrajs.js +165 -0
  24. package/lib/vendor/qrcode-core/error-correction-code.js +135 -0
  25. package/lib/vendor/qrcode-core/error-correction-level.js +50 -0
  26. package/lib/vendor/qrcode-core/finder-pattern.js +22 -0
  27. package/lib/vendor/qrcode-core/format-info.js +29 -0
  28. package/lib/vendor/qrcode-core/galois-field.js +69 -0
  29. package/lib/vendor/qrcode-core/kanji-data.js +54 -0
  30. package/lib/vendor/qrcode-core/mask-pattern.js +234 -0
  31. package/lib/vendor/qrcode-core/mode.js +167 -0
  32. package/lib/vendor/qrcode-core/numeric-data.js +43 -0
  33. package/lib/vendor/qrcode-core/package.json +8 -0
  34. package/lib/vendor/qrcode-core/polynomial.js +62 -0
  35. package/lib/vendor/qrcode-core/qrcode.js +495 -0
  36. package/lib/vendor/qrcode-core/reed-solomon-encoder.js +56 -0
  37. package/lib/vendor/qrcode-core/regex.js +31 -0
  38. package/lib/vendor/qrcode-core/segments.js +330 -0
  39. package/lib/vendor/qrcode-core/utils.js +63 -0
  40. package/lib/vendor/qrcode-core/version-check.js +9 -0
  41. package/lib/vendor/qrcode-core/version.js +163 -0
  42. package/package.json +40 -0
  43. package/scripts/build-client.mjs +35 -0
  44. package/src/client.js +427 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zhy5
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # @zmainer/dsh-wx-bridge
2
+
3
+ DSH(DeepSeek Harness)插件:把**手机微信**接到本机 DSH,让微信消息驱动本机执行任务。
4
+
5
+ - **宿主半**:注册独立前缀路由 `/wxbridge/*`,托管桥进程(启动/停止/重启/体检),向设置页提供实时状态与**预设下拉**。
6
+ - **客户端半**:设置 → **微信连接** 面板(React),显示桥的真实状态、启停按钮、扫码配对,以及**手机通道预设**选择。
7
+ - **内核**:`lib/kernel/` 内置零依赖的 `bridge.mjs`(iLink 长轮询收发 + ACP 会话执行)与 `keeper.mjs`(存活自检 + 脱树重启)。路径、工作区、知识库、预设全部可配置,无硬编码。
8
+
9
+ ## 执行路径(1.0 起:ACP 原生会话)
10
+
11
+ 手机消息**不再由插件拼接上下文**,而是交给 **DSH 自己的会话**:
12
+
13
+ ```text
14
+ 微信 → iLink → bridge(内核) → 常驻 `dsh --profile acp`(Agent Client Protocol v1,stdio)
15
+ → DSH 原生会话($DSH_HOME/sessions/…,可 list / resume)
16
+ ```
17
+
18
+ - **每个微信联系人一条会话**:会话 id 存在桥状态里;桥或宿主重启后 `session/resume` 续接,上下文不丢。
19
+ - **每个「档位」一条独立会话**:档位 = 通道预设(见下),切档不串上下文。
20
+ - 执行优先级:① ACP 原生会话 → ② 宿主内执行 → ③ 一次性 headless(兜底,仍用「固定提示词 + 历史」拼接)。
21
+ - 模型/推理强度可切(`/model`、`/effort`),选择按 peer 记忆;**每次 new/resume 后重新施加**(ACP 的会话配置不随会话日志持久化)。
22
+
23
+ ## 安装
24
+
25
+ > **改名说明**:本插件原名 `@zmainer/wxbridge`,自 1.0.8 起改名为 **`@zmainer/dsh-wx-bridge`**
26
+ > (旧包已弃用,仅保留历史版本)。插件**内部标识仍是 `wxbridge`**(cordis 插件 id、设置页面板 id、
27
+ > HTTP 路由前缀 `/wxbridge/*` 均不变),所以迁移只需换包名,配置与数据目录都不用动。
28
+
29
+
30
+
31
+ ```bash
32
+ dsh plugin --profile <profile> add @zmainer/dsh-wx-bridge
33
+ ```
34
+
35
+ 装完确认 profile 的 `package.json` 里 `dsh.profile.bundles` 含 `@zmainer/dsh-wx-bridge`(pnpm 因被忽略的构建脚本非零退出时,这一步会被跳过,需手工追加)。
36
+
37
+ ## 预设(agent preset)
38
+
39
+ 手机通道的身份 = **你选定的全局预设**(工具 + 提示词 + 技能都来自它)。
40
+
41
+ - **面板**:设置 → 微信连接 → 「手机通道预设」下拉(列表来自 DSH 名册:`$DSH_HOME/.agent-presets/` 用户预设 + 运行时出厂预设),点「保存预设」写入 `$DSH_HOME/wxbridge/config.json` 的 `acp.preset`。
42
+ - **手机**:`/预设` 列清单并切换;`/预设 自检` 回报当前档**是否真的按预设组装**(system 长度 + 关键标记 + 会话头 `agentPreset`)。
43
+ - 不指定时按 `config.json` 的 `acp.preset` → 宿主 `settings.yaml` 的 `agent-presets.default` → 插件自带「普通对话」。
44
+ - 「普通对话」是插件自带的收窄档:不注入技能目录,人格为对话助手,**不会**主动读写工作区/知识库。
45
+
46
+ ### 预设补丁(compat shim,临时)
47
+
48
+ `@deepseek-ai/dsh-acp` 目前**不会**把会话加入预设(其 `create/resume` 的 setup 只装模型选择与 MCP,
49
+ 没有 `agentPresets.mount()`),因此选定预设不会生效。插件内置一个**幂等**补丁(`lib/kernel/acp-preset-shim.mjs`),
50
+ 在启用预设时给**已装**的 `dsh-acp` 补上这一调用:
51
+
52
+ - 已支持 / 已打过 → 直接跳过;锚点对不上(上游改版)→ **拒绝打补丁**,一个字节都不写;
53
+ - 写前备份 `index.js.wxbridge-bak-<时间戳>`,写后先过 `node --check` 才落盘;
54
+ - 应用升级覆盖后,下一次启用预设时会自动重打(自愈);
55
+ - 关掉它:`config.json` 里 `"acp": { "patchAcp": false }`(此时预设不生效,通道退回宿主组合)。
56
+
57
+ > 上游支持 `Config.preset` 后,本补丁会自动让位(检测到原生支持即不再改动文件)。
58
+
59
+ ## 配置
60
+
61
+ 配置优先级:插件 config → 配置文件 → 环境变量 → 默认值。
62
+
63
+ 配置文件位置:`$DSH_HOME/wxbridge/config.json`
64
+
65
+ ```json
66
+ {
67
+ "dataDir": "<你的数据目录,留空则用 $DSH_HOME/wxbridge>",
68
+ "cwd": "<默认工作区,留空则用宿主启动目录>",
69
+ "vault": "<可选:Obsidian 知识库绝对路径>",
70
+ "intervalMs": 300000,
71
+ "staleMs": 300000,
72
+ "acp": { "preset": "<预设 id,留空跟随 DSH 默认预设>", "enabled": true, "permPolicy": "allow" }
73
+ }
74
+ ```
75
+
76
+ | 键 | 说明 | 默认 |
77
+ | --- | --- | --- |
78
+ | `dataDir` | 桥的状态/日志/工作目录 | `$DSH_HOME/wxbridge` |
79
+ | `cwd` | 微信任务的默认工作目录 | 宿主启动目录 |
80
+ | `vault` | Obsidian 知识库绝对路径(可选,供提示词模板占位符使用) | 空 |
81
+ | `intervalMs` / `staleMs` | 自检间隔 / 心跳判新阈值 | 300000 |
82
+ | `prompt` | 手机任务的**固定前置提示词**(兜底路径用;留空 = 不加任何前缀) | 空 |
83
+ | `acp.enabled` | 关掉 ACP 路径(退回一次性 headless) | true |
84
+ | `acp.preset` | 手机通道预设 id | 宿主默认预设 |
85
+ | `acp.home` | ACP 子进程的 `DSH_HOME`(决定会话写进哪个仓库) | 宿主 home |
86
+ | `acp.dshBin` | ACP 用的 dsh 入口(默认跟随宿主运行时,schema 才一致) | 自动 |
87
+ | `acp.patch` | 覆盖叠层文件路径(预设档自动生成) | 插件内置 |
88
+ | `acp.permPolicy` | 权限请求策略:`allow` / `reject` | allow |
89
+ | `acp.patchAcp` | 是否允许给已装 `dsh-acp` 打预设补丁 | true |
90
+
91
+ 环境变量:`WXBRIDGE_DATA`、`BRIDGE_CWD`、`BRAIN_VAULT`、`DSH_BIN`、`BRIDGE_HOST_HOME`、`WXBRIDGE_ACP=off`;
92
+ `WXBRIDGE_NO_AUTOSTART=1` / `WXBRIDGE_NO_SUPERVISE=1` 可关掉自动拉起与自动守护。
93
+
94
+ ## 配对(首台设备)
95
+
96
+ 1. 宿主启动后,桥会在 `dataDir/auth-token.txt` 生成一次性登记 token(ACL 限本人)。
97
+ 2. 在手机微信里把该 token 发给机器人(例如 `<token> /help`)完成登记;之后该设备免 token。
98
+ 3. 未登记的发送者会被静默丢弃并写审计日志。
99
+ 4. 面板「扫码配对」可直接出二维码(需本机 `qrcode` 可用;扫码会**重新绑定** ClawBot)。
100
+
101
+ ## HTTP 接口(宿主半)
102
+
103
+ | 方法 | 路径 | 说明 |
104
+ | --- | --- | --- |
105
+ | GET | `/wxbridge/status` | 桥实时状态(phase/polls/pid/心跳年龄/会话数/任务数)+ 数据目录 |
106
+ | GET | `/wxbridge/info` | 数据目录、登记 token、已装 profile |
107
+ | GET | `/wxbridge/log` | 宿主半操作日志(最近 60 条) |
108
+ | GET | `/wxbridge/presets` | **预设名册**(id/name/description)+ 当前选中值 |
109
+ | POST | `/wxbridge/preset` | 写入预设选择(`{ "preset": "<id|空>" }`) |
110
+ | POST | `/wxbridge/start` · `/stop` · `/restart` · `/tick` | 桥生命周期(`tick` = 立即体检并按需自愈) |
111
+ | POST | `/wxbridge/config` | 写配置文件(`dataDir`/`cwd`/`vault`/`intervalMs`/`staleMs`/`prompt`) |
112
+ | POST | `/wxbridge/task` · `/scan` · `/attach` | 宿主内执行 / 会话归组 |
113
+
114
+ ## 安全基线
115
+
116
+ - **权限预设(1.0.7 起为 `danger-full-access`)**:手机端**没有可应答审批的界面**,
117
+ 而 DSH 的审批在无应答者时 fail-closed → 任何需要审批的操作都会直接失败。
118
+ 因此本插件把**手机通道**的权限预设放到最宽;**这等于把本机交给能驱动该机器人的人**,
119
+ 请配合白名单/凭据保管使用。收紧办法:叠层里 `permission.defaultPreset` 改
120
+ `workspace-write` 或 `read-only`(后者只读)。
121
+ - 发送者白名单(TOFU)+ 一次性登记 token;未登记静默丢弃。
122
+ - 子进程使用**专用 `DSH_HOME`**(`dataDir/dsh-home`),权限 `workspace-write`,**只拿模型密钥、不含微信 token**。
123
+ - 状态文件原子写 + SHA256 校验,校验失败即隔离为 `.tampered-*`。
124
+ - 输出审计:密钥形态脱敏、外发命令阻断、超大输出截断。
125
+ - 任务超时/取消走 `taskkill /T /F` 终止整棵进程树;ACP 轮次走协议 `session/cancel`。
126
+ - 常驻进程重启时清理遗留 `running` 任务,避免并发闸被永久占死。
127
+
128
+ > 数据经腾讯 iLink 通道,**不得用于涉密内容**。状态与凭据文件为明文,仅靠 ACL 保护。
129
+
130
+ ## 微信侧指令
131
+
132
+ | 指令 | 说明 |
133
+ | --- | --- |
134
+ | `/预设 [序号\|id]` | 列通道预设 / 切换(含插件自带「普通对话」) |
135
+ | `/预设 自检` | 验证当前档是否真按预设组装(system 长度 + 关键标记 + 会话头 agentPreset) |
136
+ | `/model [序号\|provider/model]` | 列模型 / 切换(按会话) |
137
+ | `/effort [序号\|值]` | 推理强度(off/low/high/max) |
138
+ | `/sessions [序号]` | 列出 / 接上 DSH 已有会话(可用于接桌面端开着的会话) |
139
+ | `/new` | 开新会话(当前档) |
140
+ | `/ws [序号\|路径]` | 列/切工作区(换工作区即换会话) |
141
+ | `/status` | 桥状态、档位、原生会话 id、模型与强度 |
142
+ | `/task` · `/cancel` | 任务与排队 / 取消运行中任务 |
143
+ | `/help` `/ping` `/approve` `/reject` | 帮助 / 探活 / 审批记录 |
144
+
145
+ 其余任意文本 → 交给 DSH 执行。
146
+
147
+ ## 最近变更
148
+
149
+ - **1.0.8**:手机指令可用性打磨 ——
150
+ ① `/help` 重写:按「看状态 / 管任务 / 会话 / 档位模型 / 工作区 / 权限」分组,每条写清**作用**;
151
+ ② `/task` 带**进度**(已跑多久、最近在用哪个工具、多久之前),不再只显示"running";
152
+ ③ `/approve`、`/reject` 从"只记一条审计"变成**真开关**(切桥对审批的应答策略,落 `config.json` 的
153
+ `acp.permPolicy`,并作用于已在跑的 ACP 子进程);
154
+ ④ `/预设 自检` 更宽容:还没跑过一轮、或找不到会话日志时都能说清原因(并回报 ACP home)。
155
+ - **1.0.7**:**手机通道不再被审批卡死** —— `dsh-acp` 只应答**带 `callId` 的工具审批**;
156
+ 沙箱升级类审批(如写工作区之外的路径)会 `next()` 转给桌面端弹窗,而手机端没有可应答的界面 →
157
+ 按 "fail-closed" 直接**执行失败**(其他用户实测)。现在把通道的权限预设设为 **`danger-full-access`**
158
+ (叠层 `permission.defaultPreset`),手机侧新增 `/权限` 查看;实测:让 ACP 会话往工作区之外写文件,
159
+ **权限请求帧 = 0**、一次成功。
160
+ ⚠️ 这是**放宽**:该通道上的一切操作不再询问。要收紧就把叠层里的 `defaultPreset` 改成
161
+ `workspace-write`(默认,写工作区之外会问)或 `read-only`。
162
+ - **1.0.6**:日志不再误导 —— `bridge-standalone.log` 是追加写的,以前面板直接 tail,
163
+ 会把**上一次尝试的崩溃**当成这一次的问题(用户实测:"为什么还有 error 日志")。
164
+ 现在每次启动前由 keeper 写一条分隔线(时间 + kernel 版本 + `data`/`cwd`/`detached` 参数),
165
+ 面板 `/bridge-log` **只显示最后一次启动之后的段落**并注明省略了多少行历史。
166
+ (顺带修掉分隔线里一个未定义常量导致的静默失败:写日志失败现在会打到 keeper 控制台。)
167
+ - **1.0.5**:**首次使用不再"启动不了"** —— 新用户还没有微信凭据时,桥此前会在启动阶段直接抛错退出;
168
+ 现在改为照常启动、进入 `wait-credentials` 状态并提示「先在面板扫码配对」,**配对写入凭据后自动接手、
169
+ 无需重启**(实测:无凭据启动 → 写凭据 → 12 秒内 phase 转 poll)。另:删掉包内写死某台机器路径的
170
+ `bridge-watchdog.ps1`(无运行时引用),并把 README 的配置示例改成中性占位。
171
+ - **1.0.4**:修「启动了却没起来」的三个沉默原因 —— ① 被拉起的桥的 stdout/stderr 以前被丢弃
172
+ (现在落 `<dataDir>/bridge-standalone.log`);② 单实例锁只看 pid 存在,Windows pid 复用会让新实例
173
+ **静默退出**(现在要求「pid 活着 **且** 心跳新鲜 120s」,否则接管并打印原因);
174
+ ③ 新增 `GET /wxbridge/bridge-log`,面板「启动/重启」后会自动回读桥的启动输出。
175
+ (另:宿主内嵌 keeper 是**只观测**,不会自愈;要"死了自动拉起"需装独立 keeper。)
176
+ - **1.0.3**:**配对二维码不再依赖用户环境** —— 此前宿主半靠 `require.resolve('qrcode')` 在用户 profile 里
177
+ 找那个包(本包 `dependencies` 为空),干净安装的机器渲染不出二维码、只剩"备用链接";
178
+ 现在把 `qrcode@1.5.4` 的编码核心与 `dijkstrajs@1.0.3`(均 MIT)vendored 进 `lib/vendor/`,
179
+ 并用自带渲染器输出 SVG data URL(自带优先,profile 里的 `qrcode` 退为兜底)。
180
+ - **1.0.2**:设置页「微信连接」面板换微信风格视觉(微信绿头卡 + 内联 SVG 双气泡 logo + 状态胶囊/呼吸点、
181
+ 四张数据卡、胶囊按钮、扫码卡片、聊天气泡样式的登记 token);修复新面板里「保存预设」会把值清空的问题;
182
+ 面板版本号改为从 `package.json` 读取(不再写死)。
183
+ - **1.0.1**:ACP 原生会话成为默认路径(上下文归 DSH、可 list/resume);
184
+ **预设选择**(面板下拉 + `/预设` + `/预设 自检`);`dsh-acp` 预设补丁(幂等、可关闭、升级自愈);
185
+ 模型/推理强度可切;面板「提示词输入框」改为预设下拉;原生控件的皮肤适配修复。
186
+
187
+ ## 许可
188
+
189
+ MIT
190
+
191
+ 本包内还**原样包含**以下第三方代码(均为 MIT,用于不依赖用户环境地渲染配对二维码):
192
+
193
+ | 位置 | 来源 | 许可 |
194
+ | --- | --- | --- |
195
+ | `lib/vendor/qrcode-core/` | `qrcode@1.5.4` 的 `lib/core/*`(编码核心,零外部依赖) | MIT © 2012 Ryan Day,见该目录 `LICENSE` |
196
+ | `lib/vendor/qrcode-core/dijkstrajs.js` | `dijkstrajs@1.0.3` 的 `dijkstra.js` | MIT,见 `dijkstrajs.LICENSE` |
197
+ | `lib/vendor/qr-svg.cjs` | 本插件自带(用上面的核心产出模块矩阵,自绘 SVG) | MIT |
198
+
199
+ 对 vendored 代码的唯一改动:`segments.js` 里 `require('dijkstrajs')` → `require('./dijkstrajs')`
200
+ (npm 打包默认忽略 `node_modules/`,改相对路径才能保证发布包里不缺文件)。详见
201
+ `lib/vendor/qrcode-core/NOTICE.md`。
@@ -0,0 +1,3 @@
1
+ - insert:
2
+ - id: wxbridge
3
+ name: '@zmainer/dsh-wx-bridge'