- Accueil
- Plugins
- Intégrations et accès distant
- dsh-wechat-channel
dsh-wechat-channel
shr-cs/dsh-wechat-channel
Canal de compte officiel WeChat pour DSH : les messages WeChat déclenchent les tours de l’agent et les réponses sont renvoyées via l’API de messagerie du service client, avec callbacks vérifiés par signature et liste d’autorisation openid.
Installer
dsh plugin --profile web add github:shr-cs/dsh-wechat-channelREADME
dsh-wechat-channel
微信公众号通道插件:在微信里发指令操控 DeepSeek Harness,并把结果推回微信。
⚠️ 两个实测踩到的坑(改了名字和路径就是为了避开它们)
1. 包名不能叫
dsh-wechatnpm 上已有一个同名第三方包dsh-wechat(走腾讯 iLink bot 协议)。 DSH 的插件世代系统按名字解析依赖:用dsh-wechat这个名字, 你的link:会被替换成.generations/live/dsh-wechat+<版本>的 junction, 加载的就不再是你写的那份代码了。本包因此命名dsh-wechat-channel。2. 路由不能占用
/wechat/status上面那个第三方包注册了/wechat/qr与/wechat/status。 DSH 的 webserver 对重复路由直接抛错(duplicate exact route "..."), 会让本插件的 effect 整体失败、插件静默不激活(没有明显报错)。 本插件因此使用独立前缀/wechat-mp,两者互不干扰、可以共存。
微信 App ──发消息──▶ 腾讯服务器 ──HTTPS 回调──▶ cloudflared 隧道
│
dsh-wechat 插件
│
① 立刻被动回复「已收到」(≤5 秒)
② 后台跑 DSH 会话(可能几分钟)
③ 客服消息接口把结果推回微信
一、先明确一条硬约束:微信回调必须公网
微信的消息回调是腾讯的服务器主动 POST 到你填的地址。发起方是腾讯机房,不是你的手机。所以:
- 回调地址必须公网可达,且是 HTTPS + 有效证书
- 局域网内手机和电脑同一个 WiFi 没有任何用——腾讯照样连不上你的内网
因此:
| 场景 | 可用方案 |
|---|---|
| 公网 | 本插件(微信) |
| 局域网 | 用 @linxin666/dsh-remote-web-ui 的手机浏览器方案(扫码配对 + 完整 GUI),本插件不覆盖 |
这两条路不是替代关系,是互补的。局域网里想用手机操作 DSH,请走 remote-web-ui。
二、安装
从 npm 安装(推荐)
dsh plugin --profile web add dsh-wechat-channel
从本地目录安装(开发用)
dsh plugin --profile web add link:<本目录绝对路径>
DSH Desktop 的 pnpm runner 会自动把 dsh-wechat-channel 注册进 dsh.profile.bundles。
新装的 bundle 需要重启 dsh web 才会加载(patchReload: live 只对补丁层生效,不管新包)。
⚠️ 为什么包名不叫
dsh-wechatnpm 上已有一个同名第三方包
dsh-wechat(走腾讯 iLink bot 协议)。 DSH 的插件世代系统按名字解析依赖:如果你把本包命名成dsh-wechat并用link:装进去, DSH Desktop 会在加载失败时触发「插件恢复」,去 npm 装那个同名包顶上, 你的link:会被替换成.generations/live/dsh-wechat+<版本>的 junction, 加载的就不再是你写的那份代码了。本包因此命名dsh-wechat-channel。
三、配置
在 profile 的用户补丁层 <DSH_HOME>/profiles/web/cordis.patch.yml 里写:
- id: wechat
config:
# 必须与公众号后台「服务器配置」里填的 Token 完全一致
token: 你自定的一个字符串
# 测试号页面上的 appID / appsecret(异步回复必需)
appId: wx********
appSecret: ********
# 回调路径。刻意避开 /wechat —— 第三方包 dsh-wechat 注册了 /wechat/status,
# DSH 的 webserver 对重复路由直接抛错,会让本插件整个激活失败。
path: /wechat-mp
# 允许下指令的 openid 白名单(见下)
allowFrom: []
requireWhitelist: true
agentPreset: standard
turnTimeoutMs: 600000
diagnostics: true
Token是你自己编的,不是微信给你的。3–32 位字母数字下划线。
四、接上公网
任意隧道都可以,本项目自带 cloudflared 二进制(bin/cloudflared.exe)。
注意:国内网络下 QUIC(UDP) 常被阻断,会表现为隧道注册成功但立刻返回 502/530,日志里刷
datagram manager error: timeout: no recent network activity。加上 --protocol http2 走 TCP 即可:
bin/cloudflared.exe tunnel --url http://127.0.0.1:<dsh web 端口> --no-autoupdate --protocol http2
拿到 https://xxxx.trycloudflare.com 后,公众号后台填 https://xxxx.trycloudflare.com/wechat-mp。
⚠️
trycloudflare.com地址是临时的,重启就变。微信要求回调 URL 稳定, 正式使用请用固定域名(@linxin666/dsh-remote-web-ui自带的固定域名中继,或自有域名的命名隧道)。
五、第一次使用
- 后台「服务器配置」填 URL 与 Token,点提交 → 应显示配置成功(插件日志会打印「验证通过 ✓」)
- 用微信关注测试号,随便发一句话
- 插件会回信告诉你的 openid,把它填进
allowFrom - 重启后即可正常下指令
allowFrom 为空时所有人都被拒绝,这是刻意的安全默认。
六、安全模型
配对设备 = 完全控制凭据。 DSH 的 agent 能执行命令、读写你的文件,而这个插件把它暴露到公网。
allowFrom白名单是唯一准入控制,请保持requireWhitelist: true- 回调入口有签名校验(SHA1 + 定长比较),错误签名一律 403
- 状态端点
/wechat-mp/status需要?key=<token>,且绝不回显 token - 只把你自己的 openid 加进白名单
七、分层结构
| 文件 | 职责 | 依赖 |
|---|---|---|
lib/protocol.js | 微信签名、XML 解析与组装 | 零依赖 |
lib/server.js | HTTP 路由处理 | 仅 protocol.js |
lib/wechat-api.js | access_token 管理 + 客服消息推送 | fetch 可注入 |
lib/bridge.js | 微信消息 ↔ DSH 会话 | agent 形状可注入 |
lib/index.js | Cordis 胶水:配置、服务装配、生命周期 | schemastery |
刻意这样分层,是为了让前四层都能脱离 harness 单独测试。
八、测试与工具
npm test # 82 项
覆盖:签名排序、CDATA 注入、白名单、5 秒死线、token 缓存与并发去重、失效重试、 长文分条、每用户串行、超时取消、会话淘汰,以及完整的异步链路 (微信消息 → 回执 → 后台跑 DSH → 客服消息推送)。
排查工具:
node tools/sign.js <token> /wechat-mp ECHO # 生成带正确签名的回调 URL
node tools/mock-wechat-server.js # 假微信服务端,接收并记录推送
九、状态端点
GET <path>/status?key=<token>
默认即 /wechat-mp/status(path 跟配置走)。返回配置状态、白名单、会话数、模型路由,
以及最近的会话事件时间线(由 diagnostics 控制)。
排查「消息发出去了但没反应」时这个端点最有用。
十、踩过的坑(都已在代码里注释说明)
[hidden]被作者样式覆盖(在 WordMaster 项目里)——提醒同类问题- 微信签名是「值的字典序」,不是参数顺序
- 公众号被动回复只有 5 秒——必须先回执再异步推送
resume的参数是resumeSessionId,传sessionId会静默走错分支- 消息必须带
role: 'user'与唯一id,否则进得了收件箱却成不了模型输入 - 不要在 setup 上下文里访问
sessionCtx.agent——没注入agent服务,Cordis 会抛cannot get property "agent" without inject,导致每一轮 turn 都以错误结束、 step 空转、日志里既没有user/message也没有request/header。 这个 bug 耗时最久,最终靠插件自己的事件诊断监听器才抓出来。
Plugins associés
dsh-web (dsh-ssh)
zhu1090093659/dsh-web
dsh-web (dsh-remote-web-ui)
zhu1090093659/dsh-web
dsh-web-ui (dsh-ssh)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-remote-web-ui)
zhu1090093659/dsh-web-ui