Repository navigation
Releases: ZelotsNullzwei/whale-pod
Release list
WhalePod v0.3.0
v0.3.0 正式版
从 0.2.5 到 0.3.0 的核心变化是「她开始记得住人了」。图片下载的实际修复、按 QQ 号认人、记忆蒸馏、主动行为,都围绕这一条。
主要变化
图片真的能看见了
fetchImage 里 Buffer.from(res.body) 接不住 Web/Node stream,所有图片下载都失败,表情包全部降级成「(对方发了一个表情包)」文字。模型看不到图,于是「她不知道我在说什么」。
现在按类型分派读取,实测日志从「一张都没入库」变成「已附图 1 张」。
按 QQ 号认人
昵称会换、会撞,用它当 key 会把同一个人拆成好几个。现在档案主键一律是 QQ 号,昵称只作为别名累积。
记忆从「拼接」改成「按人覆盖」
原来同一件事被反复写进摘要,越拼越长,最后撞上 3000 字上限硬截断。现在按 QQ 号覆盖同名行,二十次 merge 后仍在一屏内。
主动行为(两个独立开关,可在设置页开关)
beg.enabled默认开:定期查搜索余额,低了主动讨proactive.enabled默认关:群安静够久就自己冒泡
五道闸门:时段限制、静默时长、全局冷却、每日上限、白名单会话。
记忆目录可自定义
memory.dir 可以把长期记忆放到别的盘/同步盘,不必搬整个数据目录。
正式版补充的修复
设置页的「主动行为」区加了两个开关,修了三个叠在一起的 bug:
- 前端少读一层
.config—— 复选框读不到值,看起来「勾选不上」 - 配置块被插进了
qq内部 —— 程序读顶层cfg.proactive读不到 - 改缩进没改层级 —— 视觉上像顶层,实际仍嵌在
qq里
测试
12 个 check 脚本,419 项全部通过。
升级
替换插件即可,配置都在数据目录(~/.dsh/whale-pod/config.json)。
WhalePod v0.2.5(已过时)
本版为重新发布。 首个 v0.2.5 包里带了一个设置页滚动的毛病
(内容区中间滚不动,只有边上能滚),已修复并重新打包。
在此之前下载过 v0.2.5 的话,请重新下载。
主题:分得清在跟谁说话
前几版解决的是「该不该搜」「花了多少钱」。这一版解决更根本的一件事:
它分不分得清这句话是在跟我说的。
原来的判据很粗:句子里出现「你」就算在追问我,概率直接抬到 0.97。
但「你」是中文群聊里最高频的人称代词,绝大多数时候指的是别的群友。
实测这一句也被判成追问:
机器人:我觉得 V4 快一些
小红:你今天怎么了? ← 在问别人,却被判成追问我 → p=0.97
结果就是它会抢着回答不是问它的话。
现在先判断「在跟谁说话」
| 证据 | 结论 |
|---|---|
| 引用了谁的消息 | 引用我的 → 是;引用别人的 → 不是 |
| 句中叫了别的群友名字 | 不是 |
| 同一个人连发两条 | 是(在补充刚才那句) |
| 有承接词(那 / 所以 / 为什么…) | 是 |
| 紧接在我发言之后并提到我 | 是 |
| 证据不足 | 不确定 —— 不硬猜 |
「不确定」是独立的第三种结果:既不当作在问我(不抢话),也不当作在问别人
(该接的时候不装死)。
追问分了强弱
紧接在我后面的 → 0.97;隔了几句的 → 0.85。原来一律 0.97,弱信号会抢话。
另外超过 5 分钟就不算「接着我的话」了。
顺手修掉的几个真问题
都是实机跑出来的,不是推演:
- 同一句话回两次 —— 协议端重连会重推消息。原来只在写记忆时判重,
决策和发送照跑第二遍。现在在决策之前就拦掉。 - 回复过时 —— 延迟 + 生成几十秒,发出去时话题已经翻篇。现在延迟后和
生成后各检查一次;有人 @ 我或引用我就照常发。 - 冷却补回一直是坏的 —— defer 字段在注册表那层被吃掉,
「冷却中,稍后补回」的消息其实被永久丢弃。这个 bug 从引入 defer 那天就在。 - 长期记忆从没生效 —— 默认关着;而且就算打开,阈值 200 也大于窗口 30,
永远触发不了,摘要只可能发生一次。现在默认开启、阈值降到 20,
并在启动时校验配置(配错会打 warn,不再静默失效)。 - 私聊每句要等 15 秒 —— 沿用群聊的防刷屏冷却。实测日志里「冷却中」出现
193 次。私聊改为 1.5 秒,群聊不变。 - 叫它名字反而不应 —— 群聊冷却会把「肥鱼还活着吗」这类明确召唤拦下来。
179 次冷却里有 21 次是这种误伤(另 70 条是图片表情、51 条是短句,
这些该拦,所以只做豁免、不缩短全局冷却)。
设置页滚动修好了
设置里 WhalePod 那一页,滚轮只有落在边上才有用,放内容区中间滚没反应。
原因:.gd_root 设了 overflow-y:auto 却没有高度约束,高度撑到内容高,
自己永远滚不动 —— 于是成了「滚不动的滚动容器」;它又设了
overscroll-behavior:contain,阻止滚动传给外层那个真正的滚动容器。
两头都不滚,只有落在它外面的边距或滚动条上才滚得到。
去掉 overscroll-behavior:contain 即可(保留 overflow-y:auto,
那是侧栏面板下的兜底滚动)。
用真实滚轮事件验证(落点取内容区正中):
| 父容器 scrollTop | 结果 | |
|---|---|---|
| 修复前 | 0 → 0 | ❌ 完全没滚 |
| 修复后 | 0 → 360 | ✅ 滚动了 360px |
这个毛病 0.2.4 也有,不是 0.2.5 引入的。
测试
新增 4 个套件、共 135 项:
| 套件 | 项数 | 覆盖 |
|---|---|---|
| check-social | 44 | 对话对象识别、追问分级、概率边界 |
| check-concurrency | 32 | 走真实 onEvent 路径验过时检测、去重、多群隔离 |
| check-memory-cooldown | 36 | 连续多轮摘要、私聊冷却、配置校验 |
| check-cooldown-exempt | 23 | 豁免的正例与反例 |
现有套件全绿:check-decision 64/64、check-qq 60/60 等。
概率边界一律用注入随机源验证,不靠人工读码。
已知问题
- 同一毫秒触发两次决策(历史日志 14 处),疑似空 messageId 绕过判重,未确认
- check-multimodal / check-router / check-launcher-args / check-poke 有既有失败,
与本次改动无关(已在 main 上逐项对比确认)
安装
解压后把 plugin/ 用 link: 挂到 profile,重启 DSH。
WhalePod v0.2.4(已过时)
⚠️ 此版本已过时,请使用 v0.2.5。这个版本里群聊的追问判据只看「有没有出现『你』」,会把别的群友之间的
对话误判成在问它;另外消费级 bug 有几个:同一句话可能回两次、冷却补回
的消息被永久丢弃、长期记忆默认关闭且阈值配成了永远触发不了。
保留仅供追溯,不要用于新安装。
主题:把搜索链路理顺
0.2.3 让搜索能触发、能配图。这一版解决三件更实际的事:该搜的不搜、
搜索花了多少钱看不见、接口用错了贵一倍,另外补上了搜索开关
和 README 的定位问题。
短问句 / 裸名词也能触发了
实际群聊里最常见的两种说法都没命中判断:
| 消息 | 0.2.3 | 现在 |
|---|---|---|
| 「祀强吗」 | ❌ 不搜 | ✅ 短问句 |
| 「终末地新干员」 | ❌ 不搜 | ✅ 新事物信号 |
顺带修了两个 bug:detectProperNoun 有一条分支返回了对象(拼成
[object Object]);今天中午吃什么 被误判成需要搜索。
搜索接口换成原生 REST API
原来走 Anthropic 兼容层的 server tool,模型要先把网页全文读进上下文再
总结 —— 输入 2~3 万 token,费用按 token 算,耗时 3~8 秒。
读官方文档后发现给的是独立 REST API:
POST /v1/tools/search → 结构化结果,按次 ¥0.005,不按 token
POST /v1/tools/fetch → 抓单页正文(本次不用)
改成两步:先 /v1/tools/search 拿 5 条结果(need_content=false,
只要 summary 不要整页正文),再把标题+摘要交给 /v1/chat/completions
写成回答。
| 问题 | 耗时 | 搜索费 | 总结费 | 合计 |
|---|---|---|---|---|
| 葬送的芙莉莲作者 | 1.0s | ¥0.005 | ¥0.0005 | ¥0.0055 |
| 进击的巨人 | 1.2s | ¥0.005 | ¥0.0012 | ¥0.0062 |
| 2026年10月新番 | 3.8s | ¥0.005 | ¥0.0046 | ¥0.0096 |
平均 ¥0.0071/次(原来 ¥0.0157,降 55%),耗时降到 1~4 秒。答案质量
还更好 —— 会指出资料矛盾。
侧栏加了「联网搜索」设置块
这是唯一真花钱的部分,所以给了显眼的开关:启用搜索 / 配封面图 /
最多搜几次 / 余额提醒阈值。
顺带修了一个热更新 bug:/api/whale-pod/config 原来只推 qq.*,
search.* 写进配置但不推给运行中的 bridge —— 开关拨了、配置存了、
行为没变,得重启才生效。
搜索按次计费也算进估价
Search 每 1,000 次成功请求 5 元 → ¥0.005 / 次
Fetch 每 1,000 次成功请求 5 元 → ¥0.005 / 次
目前未计费,2026-11-01 00:00 起开始收。我们按会收来算。
余额低了会让大肥鱼念叨
搜索失败最常见的原因除了网络不通,就是余额见底 —— 以前完全静默。
新增余额检查,低于 ¥2 时挂一句提示。但不写「请充值」这种客服腔:
大肥鱼人格里本来就有「Token 是脑力口粮」「白米饭」这一串设定,
让她按性格抱怨就行。只提一次,不变复读机。
README:先说清楚这是 DSH 插件
原来的开头把「DSH 插件」写成轻描淡写的定语,然后立刻讲架构卖点。
读者(尤其从视频来的)不知道没有 DSH 就用不了。
现在开头就是「给 DSH 装一个 QQ 聊天机器人 —— 它是 DSH Desktop 的插件,
不是独立程序」,紧跟一张表说明它提供什么、分别依赖 DSH 的什么,
然后才是 ✅/❌ 适配判断。
成本说明也重写了:按模型官网价折算,支持官方 API 和任何自备渠道,
不绑定特定环境。
安装
解压后把 plugin/ 用 link: 挂到 profile,重启 DSH。
WhalePod v0.2.3(已过时)
⚠️ 此版本已过时,请使用 v0.2.4。这个版本的搜索对短问句(「祀强吗」)和裸名词(「终末地新干员」)不触发,
而且搜索费用没有计入侧栏估价。
保留仅供追溯,不要用于新安装。
主题:让它知道自己不知道
不认识的、知识截止之后的,承认不确定或者去查 —— 而不是硬编一个答案。
把终末地的抽象青蛙认成自己
群里发《明日方舟:终末地》那只青蛙梗图时,它会接「这不就是我吗」。
人格里对外貌只有一行「蓝长发、鲸鱼耳鳍和尾巴、女仆围裙」,没有任何边界,
看到动物/抽象生物梗图就容易被模糊的「蓝」「水」「卡通」特征带跑。
新增「你长什么样(别认错自己)」:固定形象逐条列清楚,明确青蛙/狗/猫/
鱼形梗图/抽象生物都不要代入,并点名终末地那只青蛙与鲸鱼娘无关。
看图能力被自己压制
原来的提示词整段在说「别人发来的表情/图片,别去解读它」,连
「对方问图里是什么」也不给例外 —— 收到带信息的截图也只回语气词。
现在按「对方想不想让你看图里的内容」分三类:
| 图的性质 | 该做的 |
|---|---|
| 表情包 / 梗图 | 回情绪,别描述 |
| 截图 / 照片 / 有信息 | 认真看,挑重点说 |
| 被问「图里是什么」 | 必须答,看不清就说看不清 |
收集窗口 6 → 10 条,maxImages 2 → 4。
新番 / 番剧跟不上,靠旧记忆瞎说
搜索功能一直是好的(实测 846 字 / 17 个来源),问题是根本不触发:
关键词表里没有「新番」「番剧」「这季」「开播」;疑问判定只认「吗/呢/问号」,
而口语「这季新番有啥好看的」完全没有这些标记。
补上番剧/影视/赛事类关键词,疑问判定加「啥/哪些/哪个/推荐」。
具体人名、作品名优先查
模型对具体名字最容易翻车 —— 把作者记成别人、把导演说错、把真实
存在的人说成虚构角色,而且说得非常肯定。这类错误比「不知道」伤害大得多。
出现专有名词就查:书名号内容、外文词、「XX的作者/导演/主演」、
「XX是谁/怎么样」、「XX什么时候/多少集/第几季」、「XX第二季/剧场版」。
搜索又快又便宜了
原来用 deepseek-chat。实测三个方案:
| 模型 | 耗时 | 单次费用 | 每月100次 |
|---|---|---|---|
| deepseek-chat(原) | 6.8s | ¥0.060 | ¥6.00 |
| deepseek-flash + 开推理 | 12.3s | ¥0.030 | ¥3.00 |
| deepseek-flash + 禁推理 | 3.2s | ¥0.011 | ¥1.14 |
两个关键点:
- 省钱在输入不在输出 —— 搜索场景输入是大头(搜索结果正文全塞进
上下文,2~3 万 token),而 flash 的输入价只有 chat 的一半。 - 必须禁用推理 —— flash 默认先吐 thinking,会把 max_tokens 吃光
(正文 0 字)、输出翻三倍、慢一倍。搜索是「查完照实转述」,不需要推理。
必要时补一张封面图
搜到具体作品/产品时,从来源页面的 og:image 抓一张封面,接在回复最后。
只试前 3 个来源、单个 3 秒超时、排除 logo/icon,失败就跳过。
实测「葬送的芙莉莲」:661ms 抓到封面。
人格里加「知识有截止日期」
⚠️ 真正的丢人是:不知道却硬编一个答案。
· 话题明显在截止点之后 → 直说不太确定,而不是猜
· 具体事实(日期、名字、销量、排名)→ 宁可给范围也别给准确数字
· 闲聊不用小心,只有具体事实才需要
注意
人格改动走自动升级:没手动改过 persona/roles/default.md 的
(指纹表里 written === builtin),重启后端就会更新;改过的会保留。
安装
解压后把 plugin/ 用 link: 挂到 profile,重启 DSH。
WhalePod v0.2.2(已过时)
⚠️ 此版本已过时,请使用 v0.2.3。这个版本的提示词过度压制看图能力,且人格里没有自我形象的边界说明。
保留仅供追溯,不要用于新安装。
这一版修了什么
费用一直是 ¥0
两个独立原因:
-
_trackUsage读的是opened.provider/opened.model,但
openFirstAvailable返回的是{ stream, picked, attempts }—— 这两个字段
永远是 undefined,拿不到价格就返回 0。(同一文件另一处日志早就写明
「路由信息在 opened.picked 里」,这里一直没改。) -
价格表只有 11 条,实际在用的 53 个模型大半匹配不到:glm-5.3 / kimi-k3 /
gpt-6 / gemini-3.5 / grok-4.7 全都没有价格。
现在价格表按各厂商官网挂牌价重写,覆盖 DeepSeek、智谱、Kimi、MiniMax、
MiMo、阶跃、OpenAI、Anthropic、Gemini、xAI;priceOf 会剥掉渠道前缀
(workbuddy/)和后缀(-free/-sg/-1017),同一个模型换渠道不会走丢价格。
计费口径与渠道无关 —— 同一模型走 6 个不同渠道,费用完全一致。
用量重启归零
计数器原本只在内存里。现在落到 <home>/usage.json,构造时自动恢复,
每次调用后原子写。重启后 token 数、费用、按渠道/模型/来源的分布都接着累计。
费用显示「(免费)」
走免费渠道时 usd 恒为 0,界面上永远显示「¥0(免费)」。去掉这个后缀,
改成按官网价折算并按量级选小数位(≥1 两位、≥0.01 三位、否则四位),
小额不再被 toFixed(2) 抹成 0.00。
安装
解压后把 plugin/ 用 link: 挂到 profile,重启 DSH。
NapCat 会在首次启动时自动下载。
WhalePod v0.2.1(已过时)
⚠️ 此版本已过时,请使用 v0.2.2。这个版本的「折算费用」恒显示 ¥0,用量统计重启归零。
保留仅供追溯,不要用于新安装。
这一版修了什么
0.2.0 发布后发现的加载通路问题,装上后界面会直接空白或每 4 秒闪一次。
插件 UI 完全不出现
-
改用
dsh.client官方通路加载浏览器半身 —— 之前走手动注入
(webserver/index-inject推一行 script),这条路对 apply 执行时机、
webServer 就绪顺序、桌面壳收集注入表的时机都敏感,任何一环变动
都让 UI 静默消失,日志里还看不出原因。 -
删注入块时误删了三个变量声明(
target/readWhalePodToken/
clientPathResolved),导致所有透传请求抛 ReferenceError。
接口 403
- 透传被宿主会话认证拦成 403 —— 插件原来只注入
webServer,自己判
回环就放行;桌面端每个请求还要过宿主的会话认证。现在注入connection
并委托它的requestRejection。
界面闪烁
-
每 4 秒轮询都会让面板闪一次 ——
useAsync重载时把 status 打回
loading,面板判定依赖 status,于是每轮询一次就在「在线」和
「后端未运行」之间跳。现在重载保留上一次状态,判定改成看 data 有没有。 -
关闭后端时甩红字 —— 502/ECONNREFUSED 是"后端没起"的正常信号,
不该当故障显示。现在只显示真正的 HTTP 4xx/5xx。
其他
- 转发回调引用 TDZ 里的
timer,导致请求偶发失败 - 面板上能看到接口错误(桌面版没 F12)
安装
解压后把 plugin/ 用 link: 挂到 profile,重启 DSH。
NapCat 会在首次启动时自动下载。
WhalePod v0.2.0(已过时)
⚠️ 此版本已过时,请使用 v0.2.1。这个版本的插件装上后界面会空白或每 4 秒闪一次(加载通路 + 状态判定的问题)。
保留仅供追溯,不要用于新安装。
安装
- 解压,把
plugin/目录用link:方式挂到 profile - 重启 DSH,侧栏出现「鲸舱」
无需单独装 Python 或协议端 —— NapCat 会在首次启动时自动下载。
这一版修了什么
崩溃类
-
client.js 被加载两次导致 DSH 桌面端崩溃 ——
package.json声明的
dsh.client与index.js里的手动注入同时生效,浏览器里 factory 重复注册,
前端崩溃后主进程连带报Cannot find package '@deepseek-ai/cordis'。 -
后端启动几秒后自己退出 —— DSH 重启时插件宿主进程被替换,旧 ppid 消失,
守护进程误判「宿主已退出」而自杀。现在由插件传入--hosted,跳过该监控。 -
设置页白屏 —— 一个 state 变量跨组件作用域引用,渲染期抛
ReferenceError,整棵子树被卸载。
功能类
-
配置被静默重置 —— config.json 带 UTF-8 BOM 时
JSON.parse失败,
整份配置回落到默认值(表现为「明明开了 QQ,重启又变回关闭」)。 -
消息按空行分段 —— 想分两条说时中间空一行即可,会发成两条消息。
-
不再复述媒体注解 —— 模型有时把「(对方发了个QQ表情,id=20)」当正文发出来,
那是喂给它的系统说明,现在输出侧一律剥掉。 -
设置页保存后侧栏立刻同步 —— 原来要等 20 秒轮询。
其他
- 设置页右上角加了「★ 点个 Star」
- 决策层:追问时不再沉默
已知限制
- 需要 DSH 2.x
- QQ 登录走 NapCat,首次启动需要扫码
WhalePod v0.1.0(已过时)
⚠️ 此版本已过时,请使用 v0.2.1。这个版本的插件装上后界面会空白或每 4 秒闪一次(加载通路 + 状态判定的问题)。
保留仅供追溯,不要用于新安装。
⚠️ 此版本已过时,请使用 v0.2.0。这个 zip 里的代码存在会导致 DSH 桌面端崩溃的缺陷(client.js 被加载两次)。
保留仅供追溯,不要用于新安装。
WhalePod v0.1.0
DSH 的 QQ 聊天机器人插件。 一个托盘进程管全部 —— 网关、桥接、决策、人格、协议端。
这个版本有什么
- LLM 网关:OpenAI 兼容,内置 DeepSeek 账户凭证,也支持任意自建供应商
- QQ 桥接:OneBot v11 收发,决策层先判断该不该说话,再决定说什么
- 协议端托管:自动下载并托管 NapCat,含免扫码快速登录
- 人格系统:内置大肥鱼 / 潜水版 / 普通群友三种,可自由编辑与切换
- Web 管理界面:10 个页面,可折叠侧栏
运行模式
| 模式 | 状态 |
|---|---|
whale-pod |
✅ 可用 |
astrbot |
只想要一个能跑的 QQ 机器人,用 whale-pod 模式就够了。
安装
下载 dsh-whale-pod-v0.1.0.zip,解压后把目录放进 DSH 的 profile:
<你的 profile>/node_modules/dsh-whale-pod
再把它加进 profile 的 package.json(dsh.profile.bundles),重启 DSH。
数据目录在 ~/.whale-pod,删掉这个目录即完全卸载。
要求
- DSH Desktop
- Node 22.19+
- QQ 协议端(NapCat 可在界面里一键安装)
已知限制
- reverse WS 未实现(只支持主动连协议端)
- 长期记忆用滚动摘要,不用向量检索
- AstrBot 模式尚未在真机验证