Skip to content

Releases: 2710586329/dsh-qq

v1.2.8 · 白名单写成字符串不再炸

Choose a tag to compare

@2710586329 2710586329 released this 30 Oct 03:19

这次修的是什么

issue #3:白名单写成字符串会把入站处理整个炸掉。

privateAllow / groupAllow 少写一对括号("123456" 而不是 ["123456"])就抛
TypeError: (c.privateAllow ?? []).map is not a function,而抛出点在消息处理深处 ——
用户只看到「发了消息没反应」,看不出是自己写错了配置。

四处一起改掉,并加了 17 条写法用例 + 四处源码护栏:

文件 原来 现在
src/inbound.js (config.privateAllow ?? []).map(...) listOf(config.privateAllow)
src/inbound.js (config.groupAllow ?? []).map(...) listOf(config.groupAllow)
src/index.js 启动白名单检查同一写法(这条 warn 自己会先崩) listOf(...)
src/reading.js privateAllow?.[0] —— 字符串会取到第一个字符,夜里读书问询发给不存在的号 listOf(...)[0]
src/wake.js Array.isArray(...) ? ... : [] —— 字符串静默变空,冷会话复活失效 listOf(...)

新增 listOf()(src/config.js):数组照收;字符串按英文逗号 / 中文逗号 / 空白拆;
数字当单个号;null、undefined、对象、布尔一律当空。

issue #2 最后剩下的两条:

  • 骨架 settings.json 的模板没跟上 1.2.2 的新默认值 —— 模板只有 wsUrl / accessToken /
    selfId 三行,而 privateMode 已经默认 allowlist,白名单空着就谁都不理;
    可这份骨架存在的场景恰好是「设置页没上场」。现在补了 "privateAllow": ["你的QQ号"]。
  • 启动那句「私聊白名单是空的」warn 说了「去设置 → QQ 里填」,但设置页没上场的人没有这条路。
    现在带上 settings.json 的完整路径。
  • test/ 没进 files、也没有 scripts.test —— CHANGELOG 里说的护栏装包的人既看不到也跑不到。
    现在 files 加上 test,npm test 可跑(test/run-all.mjs 逐个 node <file> 跑,
    绕开 node --test 在部分 Windows 环境上的 spawn EPERM)。

版本号为什么从 1.2.4 跳到 1.2.8

1.2.5–1.2.7 只在本地打过包、没发到 npm(当时 registry 上还是 1.2.2),这里一次补齐。

验证

全量 32 个测试文件逐个跑过,全部通过(含 patch-defaults / private-gate / wake /
memo-write / door-read 等既有护栏)。

v1.2.2 — 私聊默认只认白名单;补上 1.2.1 漏改的 bundle patch

Choose a tag to compare

@2710586329 2710586329 released this 27 Oct 11:27

升级前先看这一条

私聊默认不再放行陌生人。 privateMode 默认从 open 改成 allowlist,而 privateAllow 默认是空的 —— 也就是说装好之后,谁私聊它都不理,得自己把 QQ 号填进 privateAllow:

privateMode: 'allowlist'
privateAllow:
  - '你的QQ号'

这是故意的:能私聊这个号的人,就能指挥跑在你这台机器上的 agent(读文件、跑命令都算)。配置里显式写过 privateMode 的不受影响。

修复

  • 1.2.1 的 wsUrl 修复没到用户手上(#2 第三次实测):只改了 src/config.js 的 schema 默认值,漏了插件包自带的 cordis.patch.yml —— 那里还写着 wsUrl: 'ws://127.0.0.1:3001',而 patch 在 schema 之后应用,「没配就不去连」那段永远走不到,装完 1.2.1 重启照样看到 ECONNREFUSED 127.0.0.1:3001。现在 patch 里 wsUrl: ''。
  • 新增护栏 test/patch-defaults.test.mjs:把 cordis.patch.yml 的每个键和 new ConfigSchema({}) 的默认值逐个比对,两处漂移就红。这个坑就是「代码对了、默认值在 patch 层被填回去」,光改代码藏不住下一次。

文档

  • README 加「谁能跟它说话(⚠️ 默认只认白名单)」一节,含从 1.2.1 及更早升级的说明。
  • docs/configuration.md 的 privateMode / privateAllow 默认值与说明改正。

升级:npm i dsh-qq-onebot@1.2.2(或 dsh plugin --profile <name> add dsh-qq-onebot@1.2.2),然后重启宿主。

v1.2.1 — 没配 wsUrl 不再偷连、断线日志去噪

Choose a tag to compare

@2710586329 2710586329 released this 27 Oct 11:08

修了什么

  • 没配 wsUrl 就不再偷连 3001(#2 第 1 条):wsUrl 的默认值原先是 ws://127.0.0.1:3001,于是「没配就先 warn 一句」成了死代码——空骨架照样连,连不上就无限重连,还让人以为是自己配错了。现在留空就完全不连接;填好保存约 0.8 秒自动接上,不用重启宿主。
  • 断线重连不再刷屏(#2 第 2 条):退避 5s→10s→20s→40s→60s,每轮打两行 warn,一小时约 120 行,重要日志全被埋了。改成状态机:第一次断打一行、带原因;之后静默累计;持续断开时每小时最多一句汇总;连回来补一句「断了多久、重试几次」。
  • README 里的日志文件名是错的(#2 第 3 条):实际落在 <workspaceRoot>/logs/dsh-qq-<日期>.log(一天一个),不是 dsh-qq-debug.log。文档已改,并补上「找不到就在磁盘上搜 dsh-qq-2026-*.log」。
  • inject 里写了废弃包名会先喊一声:dsh.client.inject 出现裸的 dsh-client-runtime / dsh-client(老文档抄来的那种)时,自检报 deprecated-inject 并给出正确写法。只按名字比对、不去 resolve,所以不会因为本机没装而误报。

新增

  • 配置 memeDb(或环境变量 DSH_QQ_MEME_DB):查梗词库的路径不再写死本机路径。两个都空时 qq_meme 如实回「没配词库」,不编出处。
  • 顺带带上上一批攒着没发的:qq_images(按消息 id 把图取回来看)、qq_meme(查梗)、合并转发真的展开、工具发出去的话也写进聊天流水、思考里的零碎不再被当成正文发出去。

升级

先退出 DSH,再:

dsh plugin --profile desktop remove dsh-qq-onebot
dsh plugin --profile desktop add dsh-qq-onebot

(profile 名换成你实际在用的那个;真正连 NapCat 的通常是 qqbot。)

一台 NapCat 的 WS 只该被一个 Agent 连着。和 dsh-onebot-hub 同时装会抢同一条消息,先卸掉一个。

npm: https://www.npmjs.com/package/dsh-qq-onebot

1.2.0 — 桥、眼睛、话头

Choose a tag to compare

@2710586329 2710586329 released this 26 Oct 10:05

1.2.0 — 桥、眼睛、话头

这版做了什么

通道回执(桥):以前消息发不出去,只有日志知道,住在 QQ 里的那只以为自己说了话、对方不理她。现在发失败会记下来,下一轮以 [通道] 开头告诉她「这是通道断了,不是对方不理你 —— 这些话对方一个字都没收到」;断线期间不再主动开口(发也白费)。开关 bridgeReceipt: false 可关。

群聊眼睛 qq_group_history:可以列群、读最近的群聊记录(days ≤ 7、limit ≤ 200,只读),不用再靠「窗口里只有我一个人」。

话头便签 qq_pin:每个会话一份 话头.md,每轮最多带 5 条还没接上的线头(空着不占地方),工具支持 add / done / drop / list。

#2 那七条:客户端半端自检(设置页消失时,日志里先说话,带错误码)、首次启动落一份带说明的骨架 settings.json(只在不存在时写)、没配 wsUrl 直接 warn、README 补三处兜底。

其中「不查 inject 里的包 Node 侧能不能 resolve」是故意的:那些包打进宿主 app.asar,实测在 profile 目录和插件目录都是 ERR_MODULE_NOT_FOUND,拿它当判据只会每次误报。

修复

  • 沉默不再扣主动开口的配额:原来投递前就计数,[SILENT] 也照扣,越克制额度烧得越快。现在真发出去才算一次。
  • 只有 reasoning、没有正文的消息也会发出去:以前拿到空串直接 return,QQ 上一个字都收不到,日志里连 warn 都没有。
  • 出站三修:行首英文标签(Good.)先剥再判、流式发过的句子不重发、同一段写两遍只留一遍。
  • 人设文件读不到时不再悄悄变回普通助手:两级兜底(文本框 → persona-cache.md),设置页常驻状态行。

升级

dsh plugin --profile <你的 profile> add dsh-qq-onebot@1.2.0

或 npm i dsh-qq-onebot@latest。升级后重启宿主生效。

为什么发这版

前半是给 QQ 里那只的:她得知道「是桥断了,不是人不理我」。后半是给装插件的人的:设置页失踪这件事,至少要有谁在日志里喊一声。

v1.1.2 — 设置页回桌面版、睡前提醒忙时不丢

Choose a tag to compare

@2710586329 2710586329 released this 25 Oct 17:34

修了什么

设置页在桌面版 DSH 0.2.x 上不显示(1.1.1「已知限制」里的那一条)

真因:1.0.0 为了能发到 npm,把 package.json 的 name 从 dsh-qq 改成了 dsh-qq-onebot,但有两处硬编码没跟着改名——client.js 里的 window.__ModuleLoader__.load({ id: 'dsh-qq' })、cordis.patch.yml 里的 name: 'dsh-qq'。

DSH 0.2.x 用 manifest 包名当作浏览器模块的身份(dsh-client-modules 的 nearestPackage() 要求 package.json.name 等于加载条目的 specifier)。名字对不上,resolveMeta() 返回 null,这条 client row 根本不进启动图——而且是静默跳过,「设置 → 插件 → 插件列表」里连一条失败记录都没有。所以它一直看起来像「注入包的问题」,其实注入包早就对了。

现在三处统一为 dsh-qq-onebot,并在 client.js 里留了注释:这三个名字必须一致。

升级提醒:如果你当年是手动把插件目录复制/软链成 node_modules/dsh-qq(旧名)装的,请改名为 node_modules/dsh-qq-onebot 再重启。用 dsh plugin add dsh-qq-onebot 装的不受影响。

睡前提醒「忙的时候先记账,然后永远不补」

tick 到点时如果那一轮会话正忙,原先是先记账再投递、投递失败也不回滚——当晚就再也不催了。现在改成「忙时先不记账」,在补发窗口(默认 30 分钟)内再找一次空档补上;窗口过了就作废,不会半夜突然冒出来催睡。另外:asleep 后醒来清标记、跨天清去重表。

测试

  • node test/sleep.test.mjs → 46 项全过(新增 4b「到点时会话正忙」、4c「过了补发窗口就不补了」)
  • node test/e2e.mjs → 全过

Full Changelog: v1.1.1...v1.1.2

v1.1.1 — 修掉 0.2.x 的 client 注入,加上非@叫醒与 AI 娘图鉴

Choose a tag to compare

@2710586329 2710586329 released this 25 Oct 17:06

修掉装不上的那个根子

  • 桌面版 / DSH 0.2.x 上装不上、设置页不显示(#1):dsh.client.inject 里写的 @deepseek-ai/dsh-client-runtime 在 0.2.x 里已经废弃(npm 上最后一个是 0.1.1-rc.2)。inject 里挂一个解析不到的包,整个 client bundle 会被静默跳过——宿主那一半照常跑,浏览器那一半根本不上场。现在注入的是官方 0.2.1 插件自己用的 @deepseek-ai/dsh-api-remotes,client.js 取槽服务也改成跟官方一致的 ctx.slots 优先。

已知限制

桌面版 0.2.x 上「设置 → QQ」这一页可能仍然不显示;宿主半端(工具、QQ 连接、收发消息)完全正常。这期间要改配置,直接编辑 $DSH_HOME/dsh-qq/settings.json——改完 800ms 内自动生效。

这几天攒下的功能

  • 群里不 @ 也叫得应:叫名字(含别名)、点名提问、关键词命中,都算在叫它,跟 @ 一样接、一样必须回
  • 概率唤醒:没人叫它时,每条群消息按比例顺带看一眼;这种「路过」允许看完不说话
  • AI 娘图鉴:15 位常见模型娘化(DeepSeek / GPT / Claude / Gemini / Grok / Llama / Mistral / Perplexity / 文心 / JEV / Kimi / GLM / Qwen / Seed / MiniMax),提到「大肥鱼」「龙娘」「通义娘」这些叫法时认得出来
  • 群词典学习:它自己卡壳的词自动记成待办,下一轮带上相关卡片
  • 外发审计:往群里发之前扫一遍,本地路径和密钥不外泄
  • 睡前提醒不再丢:刚重启过、到点时正好没人说话,也不会整条白丢

v1.1.0 — 冷会话拉回、私聊闲置期、settings 热生效

Choose a tag to compare

@2710586329 2710586329 released this 25 Oct 14:15

新增

  • 冷会话拉回(wakeColdSessions,默认关;wakeColdMax 默认 3):会话闲置久了会被回收出内存,而主动说话轮只看得见内存里的会话——冷掉之后就永远不会主动开口。开着时每轮先把它拉回来。
  • 私聊闲置期单独算(privateIdleTimeout,默认 12 小时):原来主动说话的「安静 20 分钟」和回收的「闲置 30 分钟」只差 10 分钟,一忙、会话一回收,主动说话轮就够不着它。群聊仍用 sessionIdleTimeout。
  • settings.json 跨进程热生效:另一个进程(设置页、编辑器、脚本)改了 settings.json,插件 800ms 内重新读入并就地应用,不用重启宿主。
  • 私人日记:会话目录上一级的 私人/YYYY-MM-DD.md,一天一篇,只给她自己看。

修复

  • 主动说话整天不开口:noteOutbound 把每次回复都当成「主动说过话了」,计时一直往后推,永远等不到那 20 分钟。现在只记真正主动说出口的那句。
  • 交接卡漏掉:会话文件坏了、#attach 换了新 id 时,swapSeed 只认「换代次数 > 0」,新会话成了空壳、读不到磁盘上的交接。现在 id 变了也算换代。
  • holdNightMessages 没暴露:1.0.0 的 CHANGELOG 写了这个开关,config.js 里却没有——设置页既不显示也改不了。现在补上,默认 false(半夜说话就是她醒了)。

测试

  • 新增 test/settings-watch.test.mjs(5 项:文件不存在 / 写盘生效 / 再改再生效 / 坏 JSON / 未知键过滤)。
  • context-guard、sleep 的过时断言跟上实现;e2e / context-guard / sleep / wake / settings-watch 全绿。

安装:dsh plugin --profile desktop add dsh-qq-onebot@1.1.0

dsh-qq-onebot v1.0.1

Choose a tag to compare

@2710586329 2710586329 released this 25 Oct 11:44

修复

  • 提示词放宽三处,别再把自己捆成「应答机」。 原来那三条——「一两句到三五句就够,别一口气把话说完」「一次只说一件事,不要自顾自往下讲」「对方没问的事不用主动交代」——把回复压得又短又干,读起来像在挤牙膏。现在改成:长短跟着内容走;一次把一件事说透,也可以接着自己的话往下多讲两句;对方没问的也可以主动说一句自己的事。
  • 没动的那几条仍然是底线:不用列表/路径/术语、聊天不用句号收尾、不刷屏、不黏。

安装:dsh plugin --profile desktop add dsh-qq-onebot@1.0.1

dsh-qq-onebot v1.0.0

Choose a tag to compare

@2710586329 2710586329 released this 25 Oct 11:19

dsh-qq-onebot v1.0.0

首个公开发布版。npm 上 dsh-qq 已被他人占用,本包改名为 dsh-qq-onebot;插件内部注册名仍保留 dsh-qq,配置文件里写 - id: dsh-qq 不变,老配置不用改。

安装

dsh plugin --profile desktop add dsh-qq-onebot

需要 DSH 完全退出后再装,装完重启。NapCat 与部署脚本见 README。

新增

  • 主动说话:会话安静满 20 分钟后给一次开口机会,不想说可以 [SILENT];四道闸(静默时段 / 每天上限 / 间隔 / 连续未接熔断)
  • 作息:23:30 提醒睡觉、说晚安后进入静默、夜里消息可攒到早上一起交出
  • 事实卡 qq_facts:跨会话记住称呼、作息、禁忌、答应过的事
  • 交接卡:换会话时自动写/读 交接.md,新会话接得上话
  • 思考链过滤:模型写进正文的英文自检,发出去前逐行滤掉
  • 连发合并:一口气发三条不会回三遍
  • 表情包:收图即复制、按内容起名、发图有两道硬闸
  • 会话日记改成一天一篇

修复

  • 主动说话的熔断判错了对象(模型选不说 ≠ 被冷落)
  • buildChatPrompt 里写死了本地路径,换台机器就写不进事实卡
  • 「睡了嘛」不再被当成晚安
  • 休息中不会刚说晚安就「早上」
  • 睡着的会话不再被回收(否则夜里攒的消息永远交不出去)
  • 日志固定落到 <workspaceRoot>/logs/

v0.7.2 — 装插件的方式写对了

Choose a tag to compare

@2710586329 2710586329 released this 24 Oct 11:23

这一版做了两件事

把「怎么装」写对了,顺手把文档拆开。

  • 修正安装命令。 旧写法 npx @deepseek-ai/dsh plugin --profile desktop add … 根本跑不通:desktop 这份 profile 由桌面端独占管理,npx 版 CLI 会直接报 profile "desktop" is managed exclusively by the Electron application,它还要求你自己装好 pnpm。现在改成用 DSH 自带的 dsh,并写清三件事——--profile 必填、装完进的是 package.json 的 dsh.profile.bundles(不是往 cordis.patch.yml 加一行)、装之前 DSH 要完全退出。
  • 第 3 步改成面板填。 装完直接去 设置 → QQ 填 wsUrl / accessToken,手写 YAML 只作备选。
  • README 瘦身。 466 行 → 190 行,人设 / 配置 / 部署 / 开发四块拆进 docs/,正文只留主干和 FAQ。
  • 修 CHANGELOG.md 里 3 处被写成制表符的 - tools/;npm 包里现在带 docs/。

怎么装

# 1. 先把 DSH 完全退出(托盘也退掉)
# 2. 下载下面的 dsh-qq-0.7.2.tgz,然后
dsh plugin --profile desktop add "D:\下载\dsh-qq-0.7.2.tgz"

找不到 dsh 就用完整路径:& "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd" plugin --profile desktop add "…"。

完整步骤、前置条件和常见报错见 README 的「三步跑通」。

注意

NapCat 是 QQ 协议端,不符合腾讯用户协议——用小号,账号风险自担。细节看 README 顶部的警告。