Skip to content

Releases: wangx-wx/dsh-channel-wechat

v0.2.7 — 只有扫码登录的那个人能用

Choose a tag to compare

@wangx-wx wangx-wx released this 24 Oct 13:26

变更

  • 只有扫码登录的那个微信号能驱动这个机器人。其他人发来的消息不建会话、不执行命令、也不回复,只在插件日志里留一行带对方 id 的记录。默认零配置即可用;要授权别人,在插件页「允许使用的人」里一行填一个 id。
  • 填入名单后以名单为准,登录者不再自动包含——页面上写的名单就是实际放行的人。
  • 桌面端 Web app 已打开的会话,通道现在会接管它继续用,而不是在写租约冲突时把每条入站消息都丢掉(表现为「发了没反应」)。
  • 「允许使用的人」支持一行一个 id 粘贴,不再被单行输入框合并。

兼容性

  • DeepSeek Harness:>=0.2.0-rc.1
  • Node.js:^22.19.0 或 >=24.0.0

升级提示:默认行为是只放行登录账号。若你有第二个微信号一直在用这个机器人,升级到本版本后需要把它的 id 填进 allow,否则它发来的消息会被静默拒绝。

验证

  • npm publish --dry-run:tarball 含 lib/index.js、lib/index.d.ts、lib/client.js、两个 README、LICENSE、第三方声明与 bundle 配置。
  • npm view dsh-channel-wechat dist-tags:latest 已指向 0.2.7。
  • 本次按用户要求跳过了 pnpm build / pnpm typecheck / pnpm test:all 的全量重跑;合并前在 main 上跑过一次全量(61 files / 851 tests 全过)。

安装

dsh plugin --profile <profile> add dsh-channel-wechat@0.2.7

完整安装、配置和已知问题见 README。

v0.2.6 — 微信里切换目录、调用技能,回复不再丢失

Choose a tag to compare

@wangx-wx wangx-wx released this 22 Oct 16:27

变更

  • 新增 /cwd <绝对路径>:在微信里切换工作目录。会话的 cwd 写入后不可修改,所以这是「结束当前会话、在新目录开始新对话」,历史不会跟过来;切换结果跨重启保留。
  • 新增 /skills:列出可调用的技能名称(只列用户可调用的)。技能现在可以直接当命令发,例如 /release-workflow,这一行会作为普通消息交给模型,而不是被当作未知命令拒掉。
  • 新增 /h 作为 /help 的别名。
  • 修复:回复不再只发「一句话 + 冒号」。此前每条 assistant/message 里的旁白都当成回答发出去,真实会话里 46 条此类消息有 40 条以冒号结尾,而正文是永远不会发送的工具参数。现在只有一轮结束时的纯文本回答会发出。
  • 修复:长回答不再整条丢失。此前超过服务端接受长度的正文会被直接拒绝(微信没有重放),现在按段落/行/句子切成多段发送,并正确闭合跨段的代码围栏。
  • 修复:ret: -2 限流不再三次 1 秒重试后静默丢弃,改为识别限流后按 2s→4s→8s→16s 退避,并主动把同一 peer 的发送间隔控制在 2 秒以上。
  • 修复:宿主未提供 listRecords 时通道不再反复崩溃,改为报告「无法发现已存登录」并继续可用。
  • 修复:关闭顺序改为先等轮次结算再 drain 回复队列,正在结算的那条回复不会再被吞掉;等待有 10 秒上限,卡死的轮次不会拖住宿主退出。
  • 修复:微信里 /stop 中断的轮次不再回一条空消息。

兼容性

  • DeepSeek Harness:>=0.2.0-rc.1
  • Node.js:^22.19.0 || >=24.0.0

目录切换后沙箱写入边界仍按会话创建时的 cwd 判定,这是 Harness 侧行为,已在 commands 文档 记录。

验证

  • pnpm test:all:60 个文件 / 828 项通过(含真实 launcher 的集成测试)
  • pnpm typecheck:通过
  • pnpm build:通过

安装

dsh plugin --profile <profile> add dsh-channel-wechat@0.2.6

完整安装、配置和已知问题见 README。

v0.2.5 — 通道长期运行、卡片提权与输入状态

Choose a tag to compare

@wangx-wx wangx-wx released this 19 Oct 14:51

变更

  • 修复:通道不再在启动满 24 小时后静默停止轮询。此前运行上限是代码里的默认值,生产路径从未覆盖,到期后循环正常退出、没有任何报错。
  • 新增:审批卡增加第 3 个选项「本会话全部权限」,可直接把当前会话切到 danger-full-access,等同于发送 /permission danger-full-access。该预设捆绑 approval: never,因此本会话之后不再弹审批卡;/new 会按配置的权限重新创建会话。
  • 新增:生成回复期间在微信显示「对方正在输入」,每 5 秒续期一次。票据获取失败或状态上报被拒时静默跳过,不影响回复。

兼容性

  • DeepSeek Harness:>=0.2.0-rc.1
  • Node.js:^22.19.0 || >=24.0.0

验证

  • pnpm test:all:58 个文件 / 732 项通过(含依赖已构建 DeepSeek Harness checkout 的集成测试)
  • pnpm typecheck:通过
  • pnpm build:通过

安装

dsh plugin --profile <profile> add dsh-channel-wechat@0.2.5

完整安装、配置和已知问题见 README。

v0.2.4 — 微信里查看与切换模型

Choose a tag to compare

@wangx-wx wangx-wx released this 18 Oct 06:45

变更

  • 新增 /models:按供应商列出当前部署真实的可用模型,并标出插件当前配置的那一项。
  • 新增 /model <provider/model>:在微信里切换本插件使用的模型,下一条消息即生效,不需要 /new。
  • 修复 /help 在微信里挤成一行:现在每条之间空一行,并带上各命令自己的说明。
  • 升级文档新增「先 remove 再装、必须带版本号」一节,并补上微信内命令参考。

兼容性

  • DeepSeek Harness:>=0.2.0-rc.1
  • Node.js:^22.19.0 || >=24.0.0

/model 只写本插件自己的 provider/model 两个字段,不会改动 GUI 的默认模型,
也不影响 GUI 里已打开的会话。

验证

  • pnpm test:all:677 项通过(unit 563、integration 114),0 失败 0 跳过
  • pnpm typecheck:0 错误
  • 集成测试运行在打包版 DSH 0.2.1-rc.2 上
  • npm publish --dry-run:12 个文件,含 lib/index.js、lib/index.d.ts、lib/client.js

安装

dsh plugin --profile <profile> add dsh-channel-wechat@0.2.4

已安装旧版本的 profile 需要先 remove 再装(只写包名会被现有版本范围满足,pnpm 不会升级)。
装完完全重启 DSH。详见 安装说明。

v0.2.3 — 修好 0.2.2 里没生效的退出修复

Choose a tag to compare

@wangx-wx wangx-wx released this 17 Oct 14:17

这个版本修的是 0.2.2 里没生效的修复。

0.2.2 这个 tag 含有「把 abort 信号传进长轮询」的改动,却不含「Channel 真正读取该信号」的那一半——于是关桌面端/升级时仍会撞上:

Host did not complete graceful task teardown
(exit null, signal SIGTERM, shutdown acknowledged true, graceful deadline exceeded true)

已发布版本不能重发,只能由新版本覆盖。实测:SIGTERM → 74ms 退出。

安装 / 升级

# 必须先完全退出桌面端(profile 被 Electron 独占)
dsh plugin --profile <你的 profile> remove dsh-channel-wechat
dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.2.3

必须写 @0.2.3。 只写包名会被现有版本范围满足,pnpm 判定「无需变更」→ 原样重装旧版,并报成功。

变更

类型 内容
fix Channel 读取宿主传入的 signal;SingleRun.stop() 等待收尾而不是只 abort
fix 空闲 sleep 与回复重试 timer 加 unref():重试拖尾 2002ms → 1ms
feat 「检查更新」改为按钮触发,宿主侧不缓存;点一次就是真查一次
feat 插件发现元数据:dsh-plugin 关键词、icon、locale/*.json、市场索引

插件市场

https://wangx-wx.github.io/dsh-channel-wechat/market/index.json

路径:插件 → 实验性插件 → 更多 → 自定义插件市场 → 发现 → 添加索引源。

兼容性

engines.dsh 下界 >=0.2.0-rc.1,刻意不设上界。已验证运行时:

DSH 版本 集成测试
0.2.1-rc.2(当前打包桌面端) 111 项全通过,跳过 0
0.2.1-rc.1 全通过
0.2.0-rc.2 全通过

数据落在哪里

内容 路径
聊天记录 ~/.dsh/sessions/(永不删除;/new 只是换会话目录)
插件状态 ~/.dsh/channel-wechat/
诊断日志 ~/.dsh/channel-wechat/log/(保留 7 天)
凭证 DSH 凭据服务

已知问题

  • 出站文件的 svr_id 引用与 message_id 精度仍在观察(见 plan-v1 §Q45)
  • 更新必须由你手动执行命令:宿主进程内的插件管理器这条路会以 already-installed 拒绝,实测走不通

许可

MIT。微信协议层移植自腾讯 @tencent-weixin/openclaw-weixin(MIT),署名见 THIRD_PARTY_NOTICES.md。

v0.2.2 — 检查更新、Windows 路径修复

Choose a tag to compare

@wangx-wx wangx-wx released this 17 Oct 12:14

新增

  • 插件页的「版本与更新」卡片:检查 npm 上的新版本,发现后给出可直接复制的更新命令。
    命令用当前进程的绝对路径拼成(不依赖 PATH),并带上 --config.minimumReleaseAge=0——
    不带它,pnpm 会拒绝安装刚发布的版本,而「新版本」恰恰就是刚发布的。
  • 桌面版给出 App 自带的 dsh:终端 dsh 管理 desktop profile 会被启动器直接拒绝。

修复

  • Windows 上填不进工作目录:D:\workspace\coding\dsh-ws 被判为「必须是绝对路径」,
    保存按钮禁用。判定现在按 DSH 自己的规则,接受 POSIX 绝对、盘符限定、完整 UNC 三种写法;
    D:foo(盘符相对)与 \foo 仍拒绝——会话 cwd 记录后不可改,不能存依赖进程状态的路径。
  • 出站文件名拼接(同一假设的第二处):绝对 Windows 路径曾被拼成 D:\ws\D:\ws\out.xlsx,
    不报错,文件就是不发送。现在也按平台分隔符拼接。

为什么更新要手动执行命令

实测过三条路,只有一条是安全的:

路径 结果
进程内 pluginManager.installBundle 拒绝:already-installed
先 removeBundle 再装(官方页面做法) 报 failed,但包还在 dependencies,已从 bundles 摘除
CLI dsh plugin add <包>@latest ✅ 直接替换,bundle 保持选中

第二行最糟:插件从 GUI 消失,而没有任何提示指向这件事。官方已有同一缺陷的报告
(#9936),当前最新版仍未修。

所以卡片给的是那条不会弄坏 profile 的命令。

执行前请完全退出 DSH,装完再重开。

验证

  • 单元 532 项、集成 104 项、tsc 干净
  • 5 次变异验证全部被捕获
  • 在真实 web profile + 独立 DSH_HOME 上安装 0.2.2 并启动:两条新路由均正确应答,
    current 是从安装的 manifest 读出的运行时值

完整安装:dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.2.2

v0.2.1 — 版本号跟随 DSH,修长轮询 teardown

Choose a tag to compare

@wangx-wx wangx-wx released this 17 Oct 09:21

安装

dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.2.1

装完完全退出并重启 DSH(见下方「已知问题」)。

刚发布的版本可能被 pnpm 的观察期策略跳过,装到上一个版本。@latest 不管用,
真正的开关是 --config.minimumReleaseAge=0:

dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.2.1 --config.minimumReleaseAge=0

这个版本改了什么

版本号改为跟随 DSH

从本版起,版本号是 <DSH 主>.<DSH 次>.<我们自己的补丁号>:0.2.x 配 DSH 0.2 那一代。
补丁号完全归我们——DSH 发 0.2.2 我们不改号,只有本插件自己有改动才 +1。

兼容下界由 engines.dsh 声明

"engines": { "dsh": ">=0.2.0-rc.1" },刻意不设上界。

DSH 一旦看到 engines.dsh 就只用它判定兼容性,@deepseek-ai/dsh-* 的 peer 范围不再参与。
不设上界是因为:加了天花板,DSH 每发一个新版本、本插件未重发之前用户就装不上——
对通道插件来说,「立刻不能用」比「在未实测版本上运行」更糟。

DSH 版本 能否安装 是否已验证
0.2.0-rc.2(打包桌面端) ✅ ✅ 99 项全通过
0.2.1-rc.1 ✅ ✅ 99 项全通过
0.2.x 其余 / 0.3.x / 1.x ✅ ⚠️ 未逐一实测
0.2.0-rc.1 以前 ⛔ 安装时被拒绝并说明原因 —

修了一个真缺陷:长轮询没被中止

桌面端更新时报 Host did not complete graceful task teardown。

根因是在飞的 fetch 没被 abort,配合一个 ref'd 的 setTimeout,事件循环不退出。
原实现只「race 一个超时」——那只释放等待它的循环,没中止请求本身。
实测:改前约 114ms 结束循环、然后进程存活 10 秒以上;改后 119ms 干净退出。

升级注意

0.1.x → 0.2.x 属跨次版本,按 npm 语义是 breaking。 另外旧版不带
engines.dsh、新版带,兼容性判定口径会变。所以:

# 先完全退出桌面端(profile 被 Electron 独占)
dsh plugin --profile desktop remove dsh-channel-wechat
dsh plugin --profile desktop add dsh-channel-wechat@0.2.1

必须写 @<版本>:只写包名的话,新版本本就满足现有的 ^0.1.x 范围,
pnpm 会判定「无需变更」→ 原样重装旧版并报成功。

已知问题

装完必须完全退出并重启。 Host 启动时若插件包不在 node_modules,它不会进入
boot graph,插件页的配置区会完全不出现,且不显示任何错误(客户端负缓存是永久的)。
重启自愈。这与装的是哪个版本无关。

从插件页安装后也可能看到同样的现象——这是常态,因为 Host 早就在跑,pnpm 之后才把包装上。

数据落在哪里

用途 路径
微信会话 <DSH_HOME>/sessions/(永不删除;/new 只是换一个会话目录)
插件状态 <DSH_HOME>/plugins/channel-wechat/
诊断日志 同上,保留 7 天
微信登录凭证 DSH 的 ctx.credentials 存储

做与不做

做:文本/图片/文件消息的双向收发、斜杠命令、交互卡片、出站文件(只发
deliverables/presented 声明的,绝不扫描目录)、按 peer 持久化会话、/new 换届。

不做:群聊、/cwd、/reconnect(已注册但会明确回复未实现)。

许可

移植自腾讯 @tencent-weixin/openclaw-weixin(MIT),内联 qrcode-generator(MIT)。
完整署名见 THIRD_PARTY_NOTICES.md。

v0.1.3 — 插件页内配置默认模型与会话权限

Choose a tag to compare

@wangx-wx wangx-wx released this 16 Oct 15:15

安装

dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.1.3

装完重启 DSH。从旧版本升级请先 remove 再 add(见 docs/release.md §四之二)。

本版新增:插件页内配置模型与权限

插件详情页的「设置」里新增两个字段,都只作用于微信会话,不影响 GUI:

  • 默认模型 —— 从当前环境实际可用的模型列表里选(实时读取,不硬编码)。
    留空表示跟随配置文件的默认模型。修改只影响之后新建的会话:会话一旦建立,
    它记录的模型不可改写,这与 cwd 的语义一致。
  • 微信会话权限 —— 三档:仅查看 / 工作区内修改 / 完全权限。

⚠️ 「完全权限」会关闭微信的审批卡。 该档位在 DSH 里的定义是
sandbox: danger-full-access + approval: never,而 never 会在本插件的审批卡之前就判定,
所以卡片不再出现。因此选择它时必须先在弹窗里勾选确认。日常建议用「工作区内修改」。
权限改动同样只作用于之后新建的会话,尊重你在会话中用 /permission 做的临时调整。

一直在做的事

  • 微信 ↔ DSH 文本、命令、/stop:/goal、/compact 等原生命令直接在微信里用
  • 媒体双向:收图、引用、出站文件(真机验证)
  • 审批卡 / 提问卡:微信里批准或回答;cards: wechat 时 GUI 不重复弹卡
  • 插件页内扫码登录 / 退出,无需翻日志找链接

数据落在哪里

内容 位置
聊天记录 ~/.dsh/sessions/<cwd 转义>/channel-wechat-<peerId>[~g<N>]/
插件状态 ~/.dsh/channel-wechat/(游标 + 会话代次)
诊断日志 ~/.dsh/channel-wechat/log/channel-wechat-YYYY-MM-DD.log(留 7 天)
登录凭证 ~/.dsh/.credentials.yaml

日志留 7 天,但聊天记录永不删除 —— /new 只是换一个会话目录。

已知边界

  • 微信端可用 /permission danger-full-access 自己放宽权限(该命令是 DSH 原生的,本插件转发所有非本地命令)。它写的是会话持久事件,重启仍在,但 /new 后重置。本通道按设计是单方的,操作者即用户,故保留此行为。
  • 引用自己的消息时只拿到 svr_id,显示为「引用的消息内容未能读取」;引用 Agent 的消息正常。
  • message_id 服务端是 uint64,本插件声明为 number,仅影响一条错误日志里的数字。

不做的事

群聊(协议无依据)、多账号运行期、消息去重/节流、主动推送、自建权限体系。

许可与致谢

协议规范与部分实现来自腾讯 openclaw-weixin(MIT);
工程实践参考 wechat-claude-code(MIT)。见 THIRD_PARTY_NOTICES.md。

v0.1.2 — GUI 内登录与配置,插件只占一行

Choose a tag to compare

@wangx-wx wangx-wx released this 16 Oct 12:37

安装 / Install

dsh plugin --profile <你的 profile> add dsh-channel-wechat@0.1.2

⚠️ 升级必须带 @0.1.2,并且先 remove 再 add。
只写包名的话 ^0.1.1 已满足新版本,pnpm 会判定「无需变更」→ 原样重装旧版并报成功。
详见 docs/release.md §四之二。

本版新增

1. 登录搬进 GUI

不用再去日志里翻登录地址。侧边栏 Plugins → dsh-channel-wechat 的插件页里直接有:

  • 当前连接状态(显示已连接的账号)
  • 登录微信 → 页内显示二维码 → 手机扫码 → 需要验证码时页内输入 → 已连接
  • 退出登录(先停轮询再删除凭证)

2. 配置可在 GUI 里改

同一个页面下方是 cwd 与 cards 的表单,保存写回 profile 的 cordis.patch.yml,不必手改 YAML。

cwd 的不可变性在页面文案里写明:修改只影响之后新建的会话。

3. 插件在 profile 里只占一行

之前是两行(dsh-channel-wechat/startup + 通道本身),GUI 上因此显示两张卡片。
现在合并成一行;没有 GUI 的 profile(如 headless)上 dsh <profile> login/logout/status 照旧可用。

修复的真实缺陷

logout 从来没有真正删除凭证。 旧实现调 modifyRecord(key, async () => undefined),
而 DSH 的 credentials 契约里 mutator 返回 undefined 的含义是「保持记录不变」,不是删除。
于是「登出」一路报成功,token 却还在 store 里——下次普通启动会继续以用户刚登出的账号轮询。
现在用 deleteRecord,并补了回归测试。

数据落在哪里

内容 位置
聊天记录 ~/.dsh/sessions/<cwd 转义>/channel-wechat-<peerId>[~g<N>]/session.v4.jsonl.zstd
插件状态 ~/.dsh/channel-wechat/(游标 + 会话代次)
诊断日志 ~/.dsh/channel-wechat/log/channel-wechat-YYYY-MM-DD.log(留 7 天)
登录凭证 ~/.dsh/.credentials.yaml(DSH 凭证体系,非本插件私有)

聊天记录永不自动删除——/new 只是换一个会话目录。

已知问题

  • 引用自己的消息时微信客户端只发 svr_id,显示为「(引用的消息内容未能读取)」;引用 Agent 的消息正常
  • message_id 在协议里声明为 number 而服务端是 uint64(仅影响超过 2^53 时的引用还原)
  • cards: both 且微信先答时,GUI 那张卡会滞留到该轮结束
  • /cwd、/reconnect 已注册但未实现,会明确回复

不做的事

群聊(协议无依据)、多账号运行期、主动推送、独立 HTTP 面板、自建权限体系。

致谢与许可

MIT。协议层移植腾讯官方 @tencent-weixin/openclaw-weixin(MIT, Copyright (C) 2026 Tencent);
内联的 qrcode-generator 2.0.4(MIT, Kazuhiko Arase)。详见 THIRD_PARTY_NOTICES.md。

v0.1.1

Choose a tag to compare

@wangx-wx wangx-wx released this 16 Oct 02:04

修掉两个会让每条微信消息都失败的缺陷。0.1.0 在真实环境里装得上、能加载、路由能响应 —— 但收不到任何回复。

修复

1. 插件把 DSH 核心包装进了 profile(严重)

@deepseek-ai/schemastery 之前声明为 dependencies,于是 pnpm 在 profile 里装了一份实体副本,
与安装自带的同名同版本副本并存:

3.18.4  inode 12121912  profiles/<name>/node_modules/@deepseek-ai/schemastery
3.18.4  inode 12148791  profiles/node_modules/@deepseek-ai/schemastery

同版本、不同 inode = 两份物理模块图。 cosmokit 里的
Symbol.for("cosmokit.volatile.write") 是 cordis 响应式系统的底座,
于是插件注册的 effect 落在 Host 的 agent-loop 永远看不到的实例上:

inbound message failed: no agent factory registered (load an agent-loop plugin)
inbound message failed: cannot create effect on inactive context

版本号完全一致,所以任何版本检查都发现不了。 已改为 peerDependencies
(由 Host 闭包提供)。修复后 profile 的 node_modules/@deepseek-ai/ 为空。

2. 登录地址是唯一不落盘的诊断

登录地址原先走 console.log —— 桌面端 host 的 stdout 交给 Electron 主进程,
没有终端也不写日志。而日志文件只在「有账号可轮询」时才创建,所以首次使用时
既看不到地址、也没有日志目录。现已改走 reporter,终端与日志文件双写。

升级

add 不会升级已满足版本范围的依赖,必须带版本号:

# 先完全退出桌面端
dsh plugin --profile <name> remove dsh-channel-wechat
dsh plugin --profile <name> add dsh-channel-wechat@0.1.1

装完自查(第二项非空即说明缺陷仍在):

grep '"version"' <profile>/node_modules/dsh-channel-wechat/package.json
ls <profile>/node_modules/@deepseek-ai/

数据位置

内容 路径
会话记录 ~/.dsh/sessions/<cwd>/channel-wechat-<peerId>/session.v4.jsonl.zstd
插件状态 ~/.dsh/channel-wechat/
诊断日志 ~/.dsh/channel-wechat/log/(每日一个文件,保留 7 天)

已知问题(记录,未修)

  • 引用自己的消息时客户端只给 svr_id,显示占位文字;引用 Agent 消息正常
  • message_id 声明为 number(服务端为 uint64),当前仅影响一条错误日志
  • 默认模型不可用时插件不会在启动时报错,直到第一条消息才 400
  • DSH loader 的诊断(如 name mismatch)只写 stderr,桌面端不可见

取舍与实测数据见 docs/plan-v1.md §Q45/Q50/Q51/Q52。

致谢与许可

MIT。协议层移植自腾讯 openclaw-weixin(MIT),
详见 THIRD_PARTY_NOTICES.md。