Skip to main content
P

dsh-wechat

perrylink/dsh-wechat

Bridges WeChat private messages to DSH with two-way text, image, file, and media transfer, aiming to restore the native DSH experience in WeChat.

Install

dsh plugin --profile web add github:perrylink/dsh-wechat

README

dsh-wechat

License DSH plugin dsh-doctor Gitee CI Version

本仓不发布 npm 包。 npm 上的裸名 dsh-wechat 属于上游 pan17/dsh-wechat不是本仓代码; 安装只走 GitHub / Gitee 源码通道(见安装)。

让微信成为 DeepSeek Harness (DSH) 的第二客户端:通过腾讯 iLink bot 协议把 微信私聊桥接到 DSH agent——文本/图片/文件/语音消息双向收发、微信内 slash 命令管理会话/工作区/Preset/模型/权限、DSH 设置页内扫码登录与连接配置。以 静态 Cordis 插件交付,零运行时 @deepseek-ai 依赖,直接调用 DSH 进程内服务。 审批/提问卡经原生 approval/request / user-questions/request waterfall 桥接,微信与 GUI 双端同卡、谁先回答谁生效(0.8.0 起恢复;见兼容性 的已知代价说明)。

发送 接收 设置页

兼容性

在 DSH 主版本 dsh-v0.1.5-alpha.1(GitHub tag;宿主 checkout 19d2e38480)上 通过 2026-09-09 本仓门禁链核验:typecheck + test(32 文件 / 370 用例)+ build + npm pack。profile 安装冒烟(L4)未执行。本插件零 @deepseek-ai 运行时依赖,不声明 peer 依赖,通过 ctx.get(...) 读取进程内服务。

  • 会话日志世代化文件名:宿主按会话格式版本命名落盘文件 (sessionFormatLogFilename)——session.v3.jsonl.zstd(0.1.5)→ session.v2.jsonl.zstd(0.1.3)→ session.v1.jsonl.zstdsession.jsonl.zstd(未版本化的 v0),压缩关闭时为同名 .jsonl。本插件 按此顺序从新到旧枚举、只读不写,因此不需要迁移;但 0.1.5 明确「不读旧、 也不被旧读」,用旧 DSH 打开 0.1.5 写出的 profile 仍会失败。
  • ctx.agent 已移除:0.1.5 起 agent 通过 setup(agentCtx, agent)第 2 参传入(AgentSetupebce3a5f04 起);本插件同时保留 ≤0.1.4 的 ctx.agent 回退,两代宿主都能挂载 preset 与模型路由。
  • 审批/提问卡走 answerer waterfall(0.8.0):0.1.2-rc.1 起 apiProxy 包 与其 mux 帧流被移除(4f00a8b82a),旧接线空转;现在本插件在根 context 以 { prepend: true } 注册 approval/requestuser-questions/request 回答者,随后立即 next() 放行下游(GUI/ACP 卡片照常弹出),把「下游 结果」与「微信回复」竞速——谁先给出有效结果谁生效。prepend 是硬约束: cordis 按注册顺序执行 waterfall,api-remotes 在自己的 apply 里注册 GUI 转发 且第三方插件行排在其后,不抢链首则回答者永不被调用。 已知代价:微信先答只结算宿主 waterfall,不结算网关 pending——浏览器里 那张卡不会自动消失,会挂到请求 signal abort 为止(GUI 先答则微信卡立即 撤除)。零回答者时提问回退 NO_PROVIDER、审批回退 'unavailable'; 策略 never 在分发前即返回 'rejected',回答者根本不会被调用。
  • /history 读面(0.8.0):内存路径改用 Session.snapshotEvents() (回退 ownEvents()),持久回退改用 sessionQuery.readSurface() (回退 readSession());listEvents() 返回的 SessionEventRecord 不带 data,永远无法还原文本,已不再用于历史。合成注入(runtime context、 skill 正文、goal 续跑等 source.kind === "plugin" 的 user 事件)按 GUI 侧栏同款规则过滤,不计入用户轮次。
  • /status 权限行(0.8.0)permissionPresets.current() 现在传会话对象 (宿主签名 current(session: Session),读会话的 permissions 投影), 0.1.2-alpha.2 起即如此;旧实现传事件数组会抛错并被吞成「不显示该行」。
  • npm 通道不适用:本仓不发布 npm 包。npm 裸名 dsh-wechat 属上游 pan17/dsh-wechat(latest 0.9.2),dsh plugin add dsh-wechat 装到的是 上游包,不是本仓代码——安装请走下面的源码通道。

功能

  • 发送 — 微信文本/图片/文件/语音消息 → DSH agent(媒体自动下载解密到 ~/.dsh-wechat/tempfile/,本地路径作为附件注入)
  • 接收 — agent 回复文本回微信;send_wechat 工具可主动推送文本/文件到微信
  • 微信 slash 命令/workspace/session/preset/model/perm/silent/notify/next/status/stop/rp/rq 等 由 bridge 直接处理(见下方命令表)
  • 审批/提问卡(双端同卡) — 微信与 GUI 弹一致的原生审批/提问卡, 谁先回复谁生效(0.8.0 起经原生 approval/request / user-questions/request answerer 桥接;微信先答时浏览器侧卡片不会自动 消失,见兼容性)。
  • 微信渠道提示词(动态注入) — 微信消息注入「通过微信」提示;GUI 消息时自动消失
  • 静默模式/silent on 后每轮只发送最终回复,设置页可切换
  • 繁忙时投递(与 DSH 同源) — 按 busyEnter 排队/插话;微信 /enter 同步
  • 跨会话通知 — 后台会话的已完成/报错/卡片通过微信提醒,/notify on|off|status 切换,默认关闭(单用户单闸)
  • 二维码登录http://127.0.0.1:3080/wechat/qr 扫码登录,设置页内嵌
  • 设置页 UI — DSH 设置 → WeChat:单卡展示状态、扫码、退出登录、连接配置与通知/静默开关(保存即生效,存储于 ~/.dsh-wechat/config.jsonstate.json
  • 断点续传sync-buf 与微信会话映射持久化,重启 DSH 后自动恢复会话
  • 单用户 — 只服务第一个微信用户;bot token 缺失/失效时不向微信推送,日志会写明原因(需重新扫码或等会话恢复)

安装(部署到 DSH profile)

⚠️ 本仓不发布 npm 包,dsh plugin add dsh-wechat 装的是别人的包。 npm 上的裸名 dsh-wechat 属于上游 pan17/dsh-wechat(latest 0.9.2); 本仓是 PerryLink/dsh-wechat(GitHub)/ gitee.com/perrylink/dsh-wechat (Gitee 镜像),只通过源码通道分发。

DSH 自带插件管理命令 dsh plugin(在 profile 目录转发 pnpm,并自动把 声明了 dsh.bundle 的依赖加入 bundle 层)。插件入口是 dist/index.js, 而 dist/ 不入库,所以先克隆并构建:

# 1) 克隆 + 构建(GitHub 或 Gitee 任选其一)
git clone https://github.com/PerryLink/dsh-wechat.git    # 或 gitee.com/perrylink/dsh-wechat
cd dsh-wechat
npm ci && npm run build        # tsc → dist/(含 dist/client.js、dist/dsh/session-log.cjs)

# 2) 以本地路径安装(自动添加依赖 + 注册 bundle 层)
npx @deepseek-ai/dsh plugin --profile <profile> add file:D:/path/to/dsh-wechat

# 3) 验证组合配置
npx @deepseek-ai/dsh --profile <profile> --dump-config   # 应看到 "- id: dsh-wechat" 行

# 4) 重启 DSH(必须),然后:
#   - 浏览器打开 设置 → WeChat:扫码登录、查看状态、改配置
#   - 或直接打开 http://127.0.0.1:3080/wechat/qr 扫码

⚠️ 别用 npx dsh plugin——npm 上 dsh 这个名字早在 2016 年就被一个不相关的 JS shell 包占了(dsh@1.0.1,作者 infusion),它没暴露 CLI bin,会报 could not determine executable to run。DSH 的 CLI 在 scoped 包 @deepseek-ai/dsh 下,必须用完整名。

更新与卸载:

# 更新:拉取 + 重新构建后重启 DSH(file: 依赖指向该工作副本,无需重新 add)
git pull && npm ci && npm run build

# 卸载(从 bundles 移除)
npx @deepseek-ai/dsh plugin --profile <profile> remove dsh-wechat

dsh plugin add github:PerryLink/dsh-wechat 目前不可用:pnpm 安装 git 依赖时只运行 prepare 脚本,本仓未声明该脚本,装出来会缺 dist/。请用上面 的本地构建 + file: 路径。修改代码后需重启 DSH 才能让改动生效。

微信命令

与 DSH 原生命令同步

点击展开:bridge 如何接入 DSH 的 ctx.commands 注册中心(计划模式 / 目标 / 压缩 等原生 slash 命令走的就是这条路)

微信消息进入后,bridge 向 DSH 的 ctx.commands 注册中心查询当前会话 已注册的命令(这是 DSH 内置的人类 slash 命令注册服务,由 @deepseek-ai/dsh-commands 提供;name /plan、name /goal、name /compact 等命令都由各自的 bundle 在那里 注册)。命中即直接交给原生 handler 执行,并把结果回执渲染到微信——和 GUI 走同 一条命令管线。

未注册的命令回落到本仓库硬写的本地命令表(/silent/next/rp/rq、 /workspace、/session 等),命中失败时按 "未知命令" 提示并作为文本转发给 agent。 DSH 的 ctx.commands 服务在某些极简装配下可能不挂载(缺失时会打一次 warn), 这种情形行为完全等同之前的版本。

所以:DSH 加任何新的 /xxx 命令 bundle,微信端无需改动即可识别——只要它是 按 DSH 命令注册契约挂上去的。例如装有 dsh-plan-mode 时微信发 /plan off 收 到原生回执 "Plan mode off.";装有 dsh-command-goal/goal <目标> 收到原生 "Goal created ...";装有 dsh-command-compact/compact 收到 "Compacted N history items (~M tokens)."——与 GUI 同款回执,由原生 handler 自己算、自己发。

/help 在末尾加一段 ── DSH 原生命令(当前 profile 已注册)──,列出当前 profile 实际注册的所有原生命令;本地命令表里已有的名字自动去重,不会重复 出现。

本地命令表

命令说明
/help/h/?帮助
/status当前状态:工作区、会话、Agent、待处理提问/权限卡、当前会话 Preset、模型、上下文、权限、默认 Preset、静默、繁忙投递、跨会话通知;末尾追加 DSH 通过 ctx.sessionProjections 注册的所有会话级状态,分四段显示——[模式](plan / goal / subagent / todos)、[用量与统计](tokenUsage / contextPressure / contextBreakdown / sessionStats / subagentTiming)、[会话](title / sessionListMetadata / permissions / imageLimits)、[其它](未识别 key 自动归类);DSH 加新 plugin 自动出现
/workspace (ws) — list | status | switch <编号|路径> | add <路径>工作区管理(list 显示各工作区会话数,不含已归档;switch/add 回复会写明恢复的会话名字和完整 id,跳过已归档;该目录无可见会话时提示发送消息将创建)
/session (s) — list [current] | switch <编号> | new | status会话管理(list 最近 20 个,标记当前,不显示 GUI 已归档会话;current 只看当前工作目录;switch 回复同时带会话名字和完整 id;new 复用当前工作区空白会话,与 GUI「新建会话」同款,无空白才新建)
/preset (p) — list | switch <名称|编号> | status默认 Preset(写入 DSH 设置,与 GUI 同步;status 看全局默认,不是当前会话;当前会话无内容时 switch 立即应用)
/model — list [提供商] | switch <提供商/模型> | status模型管理(切换立即作用于当前会话 + 设为默认;当前推理等级若新模型支持则一并保留,否则清空)
/perm — status | list | switch <名称|编号> | default [名称|编号]权限管理(switch 实时切当前会话;default 写 DSH 设置,新会话生效)
/reasoning — [list | default | switch <等级>]推理等级:查看当前/默认与模型支持的等级;switch <等级> 切换(实时 + 写默认);default 恢复模型默认
/enter queue|steer|status/busy繁忙时投递:agent 运行中收到微信消息时排队(queue)还是插话进当前轮次(steer);读写 DSH 设置 ui-conversation.busyEnter,与 GUI「繁忙时 Enter 键行为」同源同步;空闲会话始终新开一轮
/silent on|off/sl静默模式:开启后 agent 每轮的中间过程输出(工具调用、思考等)不再逐条推送,只在轮次结束时发送最终回复,避免刷屏;跨重启持久化,设置页可切换
/notify on|off|status/watch跨会话通知:后台会话的已完成/报错/卡片提醒,默认关闭(单用户单闸,设置页可切换)
/history [数量]查看最近历史消息(默认 5 条,最多 20 条);当前会话有未回答的提问/权限卡时会完整重发,可直接回复
/stop中断当前任务
/next继续发送因微信限制被缓存的消息
/rp / /rq拒绝所有待处理权限卡 / 提问卡(微信端)

其他 /xxx 命令作为文本转发给 agent;审批/提问卡双端同弹,已在其他端 处理的卡会提示(微信先答时浏览器侧卡片需等请求 abort 才消失,见 兼容性)。

所有命令均直接映射 DSH 原生服务(workspaceRegistry / sessionQuery / agentPresets / agentDefaultModel / permissionPresets),默认值与 GUI 设置页同源同步。

架构

微信 (iLink) ── long-poll getupdates ──► dsh-wechat (Cordis host plugin)
    ▲                                      │
    │ ◄── sendText/sendMedia ──────────────┤
    │                                      ▼
    │                          DSH 进程内服务(零 @deepseek-ai 运行时依赖)
    │        agents.create/resume ── agent.followup(消息入)
    │        session/event ── assistant/message、turn/end(消息出)
    │        approval/request、user-questions/request(waterfall,{ prepend: true })
    │          ── 回答者持有 promise,立即 next() 放行 GUI/ACP,双端竞速
    │        Session.snapshotEvents / sessionQuery.readSurface ── /history
    │        permissionPresets.current(session) ── /status 权限行
    │        tools.register ── send_wechat 工具

设计说明:微信端是 GUI 的第二客户端,功能不多也不少。

设置页(DSH 设置 → WeChat)

客户端半部通过 dsh.client + exports["./client"] 声明(与 dsh-mcp-manager 同款交付),挂载到 settings.section slot(nav 顺序 40):

  • 状态卡 — 登录阶段(未登录/等待扫码/已扫码,待确认/已登录/登录失败)、Bot ID、 监控运行状态、已绑定用户数,与 跨会话通知 / 静默 开关同卡展示
  • 扫码 — 未登录时页面内直接显示二维码,扫码确认后自动进入已登录
  • 操作按钮重新扫码(清除 token 重新登录)、退出登录,与保存配置同行
  • 连接配置 — baseUrl / cdnBaseUrl / botType / cwd / textChunkLimit / cardTimeoutMs / 跨会话通知(全局)/ 静默;保存即生效, 网关参数变更会自动重启长轮询;存储于 ~/.dsh-wechat/config.jsonstate.json

与宿主通信走插件自己的 HTTP API(/wechat/api/status|config|relogin| logout),客户端零 @deepseek-ai 依赖。

配置

优先级:内置默认 ← 插件行 config:~/.dsh-wechat/config.json (设置页写入,覆盖前两者)。插件行可带 config:

# 例:追加到 profile 的 cordis.patch.yml
- id: dsh-wechat
  config:
    cwd: 'C:\projects\my-project'
默认值说明
baseUrlhttps://ilinkai.weixin.qq.comiLink 网关
cdnBaseUrlhttps://novac2c.cdn.weixin.qq.com/c2c媒体 CDN
botType"3"iLink bot 类型
storageDir~/.dsh-wechattoken/sync-buf/会话映射/临时文件
cwdprocess.cwd()新会话工作目录
textChunkLimit4000微信单条消息长度上限
cardTimeoutMs1800000提问/权限卡软超时(30 分钟)
crossSessionNotifyfalse跨会话通知总闸(已完成/报错/卡片,单用户)

开发

npm install
npm run typecheck  # tsc --noEmit
npm run build      # tsc → dist/(+ scripts/copy-client.mjs 复制 client 与 session-log.cjs)
npm test           # vitest(32 个测试文件 / 370 个用例)

已知边界

0.8.0 修复的存量死缝(此前三项均静默空转)

以下三项都不是 0.1.5 回归,而是本插件早于 0.1.2 的旧接线在当前宿主上已空转; 0.8.0 逐条修复:

  1. 审批/提问卡不出现 —— 旧实现用 ctx.inject(["apiProxy"], …) 订阅 events.mux 帧流、并用 apiProxy.respond() 回注决策;apiProxy 包已被移除 (4f00a8b82a,含于 dsh-v0.1.2-rc.1),inject 永不回调。现在改为在根 context 以 { prepend: true } 注册 approval/request / user-questions/request 回答者:立即 next() 让 GUI/ACP 卡片照常弹出, 再与微信回复竞速。/rp/rq、卡片回复重新有效。 残留:微信先答时浏览器侧卡片不会自动撤除(网关 pending 只由浏览器回包 或 signal abort 结算);子 agent 发起的提问受宿主 DELEGATED_CALLER 守卫,不会进入本回答者。
  2. /history 恒空 —— 内存路径依赖不存在的 agent.session.events,持久回退 sessionQuery.listEvents 又不带 data。现在改用 Session.snapshotEvents()(回退 ownEvents())与 sessionQuery.readSurface()(回退 readSession()),并过滤 source.kind !== "user" 的合成注入。
  3. /status 权限行缺失 —— permissionPresets.current(events) 形状过时; 宿主签名是 current(session)(读 permissions 投影),0.1.2-alpha.2 起即 如此。现在直接传会话对象;服务缺失或抛错时该行仍按原样省略。 /preset switch 的「空白会话」判定同源修正:改用 Session.seq === 0 (旧的 session.events?.length === 0 恒为 false,导致 preset 从不应用到 空白会话)。

其他边界

  • send_wechat 工具对所有 agent 可见;任何会话的 agent 都能调用——绑定会话发送到绑定用户,未绑定会话回退到首个已知微信用户(单用户部署默认行为)。 单用户模式下,工具推送与 assistant 回复共享唯一一份微信 10 条/窗口限流预算:超限或发送失败自动进入 /next FIFO 缓存队列。计数和队列持久化到 state.json,普通 DSH 更新或重启后继续沿用;下一条微信入站会重置窗口并自动补发。微信真实限流响应(HTTP 200 + ret: -2 / prepare failed)也会被识别并缓存,不再误判成功。
  • /preset switch 遵循 DSH 约束:只有未产生任何内容的会话才能当场 recompose;已有内容的会话会提示 Preset 应用于下一个新会话。默认 Preset 本身写入 DSH 设置文档(agent-presets namespace),GUI 设置 页与微信双端读写同一事实源。
  • iLink 通道是腾讯官方 bot 协议,接口可能随官方调整;跟随 wechat-opencode 上游的 src/weixin/ 修复即可。

许可

MIT。src/weixin/src/adapter/ 移植自 wechat-opencode(MIT, 原始来源 @tencent-weixin/openclaw-weixin),文件头保留出处注释。

这是 PerryLink 维护的 37 个 DeepSeek Harness 插件 之一。如果它能帮到你,其他的也会:

PluginOne-liner
dsh-auto-review审批链上的第二模型自动审查,默认失败关闭
dsh-background-agents带 Web UI 侧栏、消息与中断的持久后台子代理
dsh-budgetDeepSeek Harness 的成本治理:预算、碳排与延迟一屏呈现。
dsh-checkpoint-rewindClaude Code /rewind 等价:快照、会话 fork、一次性恢复
dsh-claude-move把 Claude Code 会话、记忆、技能与 CLAUDE.md 迁入 DSH
dsh-click跨平台原生桌面控制(DeepSeek Harness),Windows 优先。
dsh-composer-historyWeb 输入框的终端式历史:方向键、Ctrl+R 搜索
dsh-data-quality数据集质量检查与引文核查(本插件可选消费的数字核查桥)
dsh-defendDeepSeek Harness 的提示注入、越狱与密钥泄露防护。
dsh-doublecheck工程纪律守卫:需求质询、测试门禁、对手评审
dsh-drawDeepSeek Harness 的统一静态图像生成路由。
dsh-fastDeepSeek Harness 只读性能诊断。
dsh-fund-research面向中国公募基金的确定性研究报告
dsh-github面向 DSH 的 GitHub PR/issues 集成,每次写入经审批门控
dsh-industry-research行业研究编排,经本插件的 ctx.researchReport.assemble 封存交付物
dsh-libraryDeepSeek Harness 的本地文档知识库。
dsh-local-aiDeepSeek Harness 的本地模型(Ollama)接入。
dsh-lsp-actions通过语言服务器的 LSP 诊断、格式化、补全、代码操作与重命名
dsh-maskPII 脱敏中间件:模型边界匿名化、展示层还原
dsh-mcp-panel只读 MCP 运行时面板:/mcp 命令 + 带状态、工具与错误的 Settings 标签页
dsh-memento审批门控的跨会话记忆:ctx.memory 接缝 + SQLite + 记忆工具
dsh-observeDeepSeek Harness 的 OpenTelemetry 与 Langfuse 可观测导出器。
dsh-output-stylesClaude Code outputStyles 等价的运行时风格切换
dsh-permission-rulesClaude Code 风格声明式 allow/deny/ask 权限规则,带审计
dsh-personal-directive个人指令注入器:顶栏开关(框架版)
dsh-plugin-guide作为按需代理技能的插件开发知识库
dsh-reach多渠道审批/提问桥接:微信/Telegram/飞书,会话控制台
dsh-research-report可验证研究报告引擎:内容寻址证据账本与封存版本
dsh-scoreDeepSeek Harness 插件的多维质量评分。
dsh-session-pin在 Web 侧栏置顶会话,带持久排序
dsh-session-syncDeepSeek Harness 的跨设备会话同步——会话存储的专用 git 镜像。
dsh-skill-pack-security安全审计技能包:密钥扫描、依赖与供应链审查
dsh-talkDeepSeek Harness 的语音优先会话闭环:对它说,听它答。
dsh-test-driveDeepSeek Harness 插件的隔离试装冒烟。
dsh-translateDeepSeek Harness 的厂商参数翻译与确定性 JSON 修复。
dsh-ticktickTickTick/滴答清单任务桥接:会话头面板 + 11 个工具

免责声明

本项目与 DeepSeek Harness、腾讯微信官方互不隶属,非官方项目, 纯属个人学习用途。使用本项目即表示你自行承担由此产生的一切后果。

Related plugins