@zmainer/dsh-wx-bridge
Drive your local DSH from WeChat: a self-hosted iLink bridge over a persistent ACP session (context lives in DSH and is resumable), phone conversations grouped into the desktop workspace, with image recognition, file messages (Excel/Word/PDF, parsed by the agent itself) and voice transcripts. Tool a
Install
dsh plugin --profile web add @zmainer/dsh-wx-bridge
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
@zmainer/dsh-wx-bridge
DSH(DeepSeek Harness)插件:把手机微信接到本机 DSH,让微信消息驱动本机执行任务。
- 宿主半:注册独立前缀路由
/wxbridge/*,托管桥进程(启动/停止/重启/体检),向设置页提供实时状态与预设下拉。 - 客户端半:设置 → 微信连接 面板(React),显示桥的真实状态、启停按钮、扫码配对,以及手机通道预设选择。
- 内核:
lib/kernel/内置零依赖的bridge.mjs(iLink 长轮询收发 + ACP 会话执行)与keeper.mjs(存活自检 + 脱树重启)。路径、工作区、知识库、预设全部可配置,无硬编码。 - 1.1.0 新增:微信内审批应答(审批卡推到微信,回「批准 / 拒绝」即可)与主动推送(任何进程用一行命令把消息推到手机)。
执行路径(1.0 起:ACP 原生会话)
手机消息不再由插件拼接上下文,而是交给 DSH 自己的会话:
微信 → iLink → bridge(内核) → 常驻 `dsh --profile acp`(Agent Client Protocol v1,stdio)
→ DSH 原生会话($DSH_HOME/sessions/…,可 list / resume)
- 每个微信联系人一条会话:会话 id 存在桥状态里;桥或宿主重启后
session/resume续接,上下文不丢。 - 每个「档位」一条独立会话:档位 = 通道预设(见下),切档不串上下文。
- 执行优先级:① ACP 原生会话 → ② 宿主内执行 → ③ 一次性 headless(兜底,仍用「固定提示词 + 历史」拼接)。
- 模型/推理强度可切(
/model、/effort),选择按 peer 记忆;每次 new/resume 后重新施加(ACP 的会话配置不随会话日志持久化)。
安装
改名说明:本插件原名@zmainer/wxbridge,自 1.0.8 起改名为@zmainer/dsh-wx-bridge
(旧包已弃用,仅保留历史版本)。插件内部标识仍是 wxbridge(cordis 插件 id、设置页面板 id、
HTTP 路由前缀 /wxbridge/* 均不变),所以迁移只需换包名,配置与数据目录都不用动。
dsh plugin --profile <profile> add @zmainer/dsh-wx-bridge
装完确认 profile 的 package.json 里 dsh.profile.bundles 含 @zmainer/dsh-wx-bridge(pnpm 因被忽略的构建脚本非零退出时,这一步会被跳过,需手工追加)。
预设(agent preset)
手机通道的身份 = 你选定的全局预设(工具 + 提示词 + 技能都来自它)。
- 面板:设置 → 微信连接 → 「手机通道预设」下拉(列表来自 DSH 名册:
$DSH_HOME/.agent-presets/用户预设 + 运行时出厂预设),点「保存预设」写入$DSH_HOME/wxbridge/config.json的acp.preset。 - 手机:
/预设列清单并切换;/预设 自检回报当前档是否真的按预设组装(system 长度 + 关键标记 + 会话头agentPreset)。 - 不指定时按
config.json的acp.preset→ 宿主settings.yaml的agent-presets.default→ 插件自带「普通对话」。 - 「普通对话」是插件自带的收窄档:不注入技能目录,人格为对话助手,不会主动读写工作区/知识库。
预设补丁(compat shim,临时)
@deepseek-ai/dsh-acp 目前不会把会话加入预设(其 create/resume 的 setup 只装模型选择与 MCP,
没有 agentPresets.mount()),因此选定预设不会生效。插件内置一个幂等补丁(lib/kernel/acp-preset-shim.mjs),
在启用预设时给已装的 dsh-acp 补上这一调用:
- 已支持 / 已打过 → 直接跳过;锚点对不上(上游改版)→ 拒绝打补丁,一个字节都不写;
- 写前备份
index.js.wxbridge-bak-<时间戳>,写后先过node --check才落盘; - 应用升级覆盖后,下一次启用预设时会自动重打(自愈);
- 关掉它:
config.json里"acp": { "patchAcp": false }(此时预设不生效,通道退回宿主组合)。
上游支持 Config.preset 后,本补丁会自动让位(检测到原生支持即不再改动文件)。
配置
配置优先级:插件 config → 配置文件 → 环境变量 → 默认值。
配置文件位置:$DSH_HOME/wxbridge/config.json
{
"dataDir": "<你的数据目录,留空则用 $DSH_HOME/wxbridge>",
"cwd": "<默认工作区,留空则用宿主启动目录>",
"vault": "<可选:Obsidian 知识库绝对路径>",
"intervalMs": 300000,
"staleMs": 300000,
"acp": {
"preset": "<预设 id,留空跟随 DSH 默认预设>",
"enabled": true,
"permPolicy": "ask",
"permPreset": "workspace-write",
"approvalTimeoutMs": 120000
}
}
键 · 说明 · 默认
dataDir · 桥的状态/日志/工作目录 · $DSH_HOME/wxbridge
cwd · 微信任务的默认工作目录 · 宿主启动目录
vault · Obsidian 知识库绝对路径(可选,供提示词模板占位符使用) · 空
allowlist · 准入模式:strict(默认)/ auto / open —— 面板「准入模式」亦可切换 · strict
dshBin · DSH 运行时入口(<安装目录>/resources/dsh-runtime/lib/bin.js)。留空=自动探测:显式参数/环境变量 → 宿主自证快照 → 宿主自己的模块解析(require.resolve('@deepseek-ai/dsh/lib/bin.js'),桌面端的入口在 app.asar 内也能解析)→ PATH/npm 全局 → 桌面安装目录扫描 → 运行中进程嗅探。入口落在 .asar 内时自动用 ELECTRON_RUN_AS_NODE=1 跑 · 自动
hostHome · 宿主的 DSH_HOME(桌面端 = harness home)。留空=自动推导:DSH_HOME → 插件自身安装路径上溯(<home>/profiles/<p>/node_modules/<pkg>/lib/index.js)→ %APPDATA%/dsh-desktop/harness → ~/.ohdsh → ~/.dsh。解析到 ⇒ ACP 会话直接写进宿主的会话仓库(手机对话出现在桌面工作区、可点开继续),微信 token 也存在宿主 home(不再每次重启被擦) · 自动
lifecycle · auto(默认)/ host(宿主托管:应用一开就拉起、应用退出即结束)/ standalone(独立 keeper 守护,应用关着也能用)。auto = 桌面宿主里用 host,CLI 形态用 standalone · auto
intervalMs / staleMs · 自检间隔 / 心跳判新阈值 · 300000
prompt · 手机任务的固定前置提示词(兜底路径用;留空 = 不加任何前缀) · 空
acp.enabled · 关掉 ACP 路径(退回一次性 headless) · true
acp.preset · 手机通道预设 id · 宿主默认预设
acp.home · ACP 子进程的 DSH_HOME(决定会话写进哪个仓库) · 宿主 home
acp.dshBin · ACP 用的 dsh 入口(默认跟随宿主运行时,schema 才一致) · 自动
acp.patch · 覆盖叠层文件路径(预设档自动生成) · 插件内置
acp.permPolicy · 审批策略:ask(默认,推到微信等回复)/ allow(自动批准)/ reject(一律拒绝) · ask
acp.permPreset · 手机通道权限预设(写进 ACP 叠层):workspace-write(默认)/ read-only / danger-full-access。越界的写与提权会在微信里弹审批卡 · workspace-write
acp.approvalTimeoutMs · 审批卡等待时长(超时按拒绝) · 120000
acp.promptTimeoutMs · 一轮 ACP 提示词的等待上限(与任务超时分开)。超时不回落:那一轮仍在跑,跑完把结果补发 · 900000
acp.patchAcp · 是否允许给已装 dsh-acp 打预设补丁 · true
环境变量:WXBRIDGE_DATA、BRIDGE_CWD、BRAIN_VAULT、DSH_BIN、BRIDGE_HOST_HOME、WXBRIDGE_ACP=off;
WXBRIDGE_NO_AUTOSTART=1 / WXBRIDGE_NO_SUPERVISE=1 可关掉自动拉起与自动守护。
配对(首台设备)
1. 宿主启动后,桥会在 dataDir/auth-token.txt 生成一次性登记 token(ACL 限本人)。
2. 在手机微信里把该 token 发给机器人(例如 <token> /help)完成登记;之后该设备免 token。
3. 未登记的发送者不会被执行:桥回一次提示(告诉对方怎么登记、或提示你去面板切 auto)并写审计日志。
4. 面板「扫码配对」可直接出二维码(需本机 qrcode 可用;扫码会重新绑定 ClawBot)。
HTTP 接口(宿主半)
方法 · 路径 · 说明
GET · /wxbridge/status · 桥实时状态(phase/polls/pid/心跳年龄/会话数/任务数)+ 数据目录
GET · /wxbridge/info · 数据目录、登记 token、已装 profile
GET · /wxbridge/log · 宿主半操作日志(最近 60 条)
GET · /wxbridge/presets · 预设名册(id/name/description)+ 当前选中值
POST · /wxbridge/preset · 写入预设选择({ "preset": "<id · 空>" })
POST · /wxbridge/allowlist · 写入准入模式({ "mode": "strict · auto · open", "restart": true })
GET · POST · /wxbridge/approval · 读/写审批策略({ "mode": "ask · allow · reject" })
POST · /wxbridge/push · 主动推送:把一条消息排队给桥代发({ "text": "…", "to": "<可选 peerId>" })
POST · /wxbridge/start · /stop · /restart · /tick · 桥生命周期(tick = 立即体检并按需自愈)
POST · /wxbridge/config · 写配置文件(dataDir/cwd/vault/intervalMs/staleMs/prompt)
POST · /wxbridge/task · /scan · /attach · 宿主内执行 / 会话归组
安全基线
- 权限预设(
acp.permPreset,默认workspace-write):手机任务默认只能写工作区;**越界的写与提权会变成
审批卡推到微信**,回「批准 / 拒绝」即可(1.1.0 起)。这正是默认从 `dan
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::19,最后更新 2026-10-23