Repository navigation
Releases: 2710586329/dsh-qq
Release list
v1.2.8 · 白名单写成字符串不再炸
这次修的是什么
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
升级前先看这一条
私聊默认不再放行陌生人。 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 不再偷连、断线日志去噪
修了什么
- 没配
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同时装会抢同一条消息,先卸掉一个。
1.2.0 — 桥、眼睛、话头
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 — 设置页回桌面版、睡前提醒忙时不丢
修了什么
设置页在桌面版 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 娘图鉴
修掉装不上的那个根子
- 桌面版 / 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 热生效
新增
- 冷会话拉回(
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
修复
- 提示词放宽三处,别再把自己捆成「应答机」。 原来那三条——「一两句到三五句就够,别一口气把话说完」「一次只说一件事,不要自顾自往下讲」「对方没问的事不用主动交代」——把回复压得又短又干,读起来像在挤牙膏。现在改成:长短跟着内容走;一次把一件事说透,也可以接着自己的话往下多讲两句;对方没问的也可以主动说一句自己的事。
- 没动的那几条仍然是底线:不用列表/路径/术语、聊天不用句号收尾、不刷屏、不黏。
安装:dsh plugin --profile desktop add dsh-qq-onebot@1.0.1
dsh-qq-onebot v1.0.0
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 — 装插件的方式写对了
这一版做了两件事
把「怎么装」写对了,顺手把文档拆开。
- 修正安装命令。 旧写法
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 顶部的警告。