dsh-whale-pal
给 DSH(DeepSeek Harness)的插件:跨会话记忆、压缩不丢历史、到极限自己换会话。
装进一个 profile 就生效。没有第三方依赖,插件自己不发起网络请求,代码全在这个仓库里。
要说清楚一件事:每轮萃取记忆要调一次宿主的模型,那最多 24 条对话(≤4000 字)会跟着宿主的模型请求发出去。用云端模型时,这段内容出了本机;用本地模型才不出。插件自己不存也不发别的。
它管三件事:每轮从对话里萃出事实、偏好和没做完的事,带编号存着,会变淡、能纠正;被压缩掉的历史落成档案卡,按编号取回;压不动的时候自己开一个新会话接着干。其余部分是能填的人格内核、按目录切的模式段、一张设置页和一组 /whale 命令。
它解决什么
用 DSH 的人多半自己搭环境、会写点代码。痛的是两件事:开新会话得重新交代「我叫什么、上次说到哪、别再那样说话」;聊长了,前面定过的事被压缩掉,问它就说记不清。
真正的问题不是「记得住吗」,是聊了几百轮以后,它还记不记得我说过什么,记得的东西翻不翻得出来。这个插件是冲这个来的。
三条卖点
- 跨会话记忆:开新会话不用重新交代,说过的事按编号取回。
- 压缩不丢历史:被压掉的对话落成档案卡,要细节按编号读回。
- 到极限自己换会话:压不动了,它开新会话接着干,旧会话停掉。
安装
需要:DSH 桌面版(Cordis 插件接口)、Node.js ≥ 22、一个 profile。DSH 本体要 >=0.2.2-rc.3(写在 engines.dsh 里,低于这个版本宿主会拒绝激活,不会带着缺接口的状态硬跑)。
1. 把包装进 profile 的 node_modules
npm i dsh-whale-pal
本地开发想改一次看一眼,用 junction 把仓库链进 node_modules 也一样。
2. 在 profile 的 cordis.patch.yml 里挂上
包自带 patch(cordis.patch.yml),insert 一条即可:
- insert:
- id: dsh-whale-pal
name: dsh-whale-pal
3. 重启 DSH
index.js、lib/host.js、lib/settings.js、lib/mode.js、lib/ledger/*、lib/ctx/* 都是宿主侧代码,改完必须重启。只有 lib/client.js(设置页那一段)是浏览器每次加载重读的,刷新页面就行。
装完 Web GUI 里会多出这张设置页;它自己的通道在 /api/whale-pal(/health、/status 都走这里)。
五分钟上手
- 填人格卡。 设置页十一项,能从一段文字里「拆一下」自动填;空白照收,清空就空着(只有名字会退回占位名「鲸鲸」)。
- 选一个目录当「鲸鲸」的地盘。
/whale bind把当前目录加进名单——在里面开会话就是鲸鲸模式,别处是助手模式。 - 看一眼解析结果。
/whale mode告诉你当前目录算哪边、名单里有谁。
记忆:它自己萃,不用你特意记
每轮结束(turn/end)先判这一轮够不够「有料」:默认档 important 要求人和模型都说过话、转录至少 80 字,才发一次独立的小模型调用——从最近最多 24 条(不超过 4000 字)里抽四类东西:事实、偏好、发生过的事、没做完的事;另外抽「它自己答应过的事」和「这轮做完的旧事」。每条一句话(≤40 字),一类一次最多 2 条。档位可调:off / important(默认)/ every-turn。
用独立的小模型而不是主模型当裁判,是因为主模型正在演这一轮,让它同时判自己会为了自洽把结论修饰得更好看。
记忆分短期四类和一层长期。短期就是提示里那几行——「记得 / 一直记着 / 答应过 / 未完成」;长期是从短期里升上去的,升上去之后不再占短期的名额。每条 ≤300 字,带编号,样子是 M-003。一条重不重要,不看模型当时的语气,看两件事:它属于哪一类,以及被重复提起过几次。
没再被提起的会变淡:每过一场会话淡 0.02,低于 0.12 就不再进目录;被提起 3 次升进长期层。容量满了先淘汰最淡的那条——事实 200 条、偏好 60 条、事件 60 条、未完成 30 条、长期层 40 条。淡不等于删,只是更难被想起来。淘汰会留痕:被顶掉的那条留下编号、时间和原因(最多 60 条),正文不留;拿那个编号去 read,它会说什么时候、为什么没了,而不是假装从没存在过。所以它是「把旧聊天整理成带编号的档案盒」,不是「永不遗忘的大脑」。
每轮只把目录放进系统提示:最多 5 行,每行不超过 20 字(M-003 · 别再用客服腔)。要细节时按编号取回正文,一次最多 2000 字,超了截断并写明「原文还有 N 字」,不悄悄少给。编号不许编造:查不到就说查不到,不拿最像的一条顶替。条目尽量记来源(哪场会话哪一轮),取回时会试着把当时那句话一起给出来。给不出不是「差不多」:长期层的条目不再带来源,没被压进档案卡的轮次没有原文,存档里找不到那一节的也有一部分——实测 390 条里 270 条能追到原话,其余三种情况取回时会写明是哪一种。
纠正会盖掉老结论,但台账只追加——老结论过期不改老行,另起一条。
存储在本机 ~/.dsh/whale-pal/<profile>/state.json,换会话、重启都还在。
压缩:不抢方向盘,只把被压掉的那段抄一份
触发点不写死 token 数:按当前模型窗口的「已用比例」算,可配(compaction.ratio / floorMargin)。窗口大的模型自然能聊更久,插件不假设一个固定窗口。
顺序和 DSH 原生压缩一致:先剪掉能剪的,再复测,仍然超才做摘要。剪一下就够了的时候,不摘要。摘要走宿主自己的 /compact,插件不替换压缩器。压不成的时候会在会话里提醒你手动 /compact,不会装完没动静。
压缩发生时,被压掉的那一段落成一张「档案卡」,写进笔记库的 _上下文/压缩档案/,同时保留原文;一次压缩落一批,共用批次号 B00x。压缩之后系统提示里多一份档案目录,一行一张卡(C032 · 设置页与模式绑定),模型需要细节时按编号把全文读回来。
所以压缩不是把历史丢掉,是换一种记法:常驻的只付目录的钱,细节按需取。档案能按词搜、能按批次整批列出、能整批回滚;回滚只是挪进回收站,不删。
它往会话里放什么
inject:systemPrompt, webServer, commands, tools, workspaceController。
系统提示词按顺序拼:人格内核 → 【模式】 → 【本轮状态】(记得 / 一直记着 / 答应过 / 未完成)→ 【处理流程】进度点 → 上下文档案目录。
模式按会话当前目录判,严格相等,子目录不算同一个;会话里 cd 走了,下一回合模式就跟着变。
命令与工具
| 命令 | 干什么 |
|---|---|
/whale mode |
看当前目录算哪个模式、名单里有谁 |
/whale bind / unbind |
把工作区加进 / 移出鲸鲸名单 |
/whale new |
立刻开一个新会话(助手模式带交接条) |
/whale ctx search|read|files|batch|entries|sync|open |
查上下文档案、拼一篇笔记的 Obsidian 深链 |
/whale ctx rollback B00x |
退一批压缩档案,只挪不删(挪进 _上下文/回收站/) |
/whale import rollback|undo |
回滚 / 撤销旧状态导入 |
工具 7 个:whale_ctx、whale_pal_identity、whale_pal_memory、whale_pal_ledger、whale_pal_progress、whale_pal_health、whale_pal_rollback。打开一篇笔记是 whale_ctx 的 action=open;库版本不进工具,看设置页或台账里那一行。
其余功能
- 人格内核:名称、称呼、自称、底色、价值观、边界、说话风格、总结——十一项,写在系统提示最前面。名字不预设:没填时用占位名「鲸鲸」,设置页会提示去填;填了就一直用,清空回到占位名。
- 模式段:按会话所在目录切「鲸鲸模式 / 助手模式」。模式定的是主次,不是语气——助手模式里任务准确性在前、人格表达让路,鲸鲸模式反过来。
- 台账:只追加。事件、偏离、异议、交接都在里面;结论过期不改老行,另起一条「纠正」。
- 六阶段流程:进度点写在系统提示里,一个阶段一个阶段确认,不跳步。
- 健康检查带一行实况:评估器最近的成功率(含最常见的失败原因)、记忆各类占用、最近淘汰了几条——不是只看「挂上了没」。
数据在哪
| 东西 | 位置 |
|---|---|
| 配置 | ~/.dsh/whale-pal/<profile>/config.json(bot_name、identity、whaleWorkspaces、knowledge、obsidian、compaction) |
| 状态 | 同目录 state.json(自称/称呼、记忆、约定、未完成的事) |
| 审计 | 同目录 audit.jsonl(只追加;超过 4 MB 轮转到 audit.jsonl.1,只留一份旧档) |
| 处理流程进度 | 同目录 progress.json |
| 人格状态快照 | 同目录 snapshots/,留最近 20 份 |
| 导入前的世界 | ~/.dsh/whale-pal/import-snapshots/<profile>/ |
| 台账与上下文档案 | 你的笔记库里:台账/、_上下文/ |
| 备份 | 同目录 .bak-<时间戳> 留最近 10 份;更旧的挪进 .bak-archive/,每个文件在归档里留最近 20 份 |
插件只碰笔记库里自己那两块(台账/、_上下文/)。人的笔记、项目规划、.obsidian 一概不动;换库只复制,不删源。
改错了能退:whale_pal_rollback 把一个文件退回最新 .bak;/whale ctx rollback B00x 退一整批压缩档案;从旧插件导进来的数据有单独的快照目录。
换库
设置页改笔记库路径时,默认把 台账/ 和 _上下文/ 复制到新库,先整份复制到临时目录、逐文件比 sha256、全过了才改名落地,然后才写配置。
配置是提交点:它之前的每一步失败都整单退(状态退回原样、新库副本撤掉),旧库照旧用。唯一剩下的局面是「配置没写成、写状态也退不回去」——两次写盘都炸——这时会如实告诉你「重存一次就能对齐」,不假装干净。
压不动的时候会自己开新会话
自动压缩跑完,下一轮复检仍超触发点,说明这次压缩没吃到收益。这时插件不再只劝人开新会话,而是自己开一个:
- 新会话按同一目录、同一预设建,Web GUI 里看得见,并且挂回老会话所在的工作区(不然侧栏会把它放进「未分组」)。
- 助手模式带交接条(旧会话编号、当前目录、未完成的事、档案目录),接着干。
- 鲸鲸模式干净开,不带交接条——聊天不该被一张机器写的纸条打断。
- 旧会话里说一句「已切到新会话 」就停手,自动压缩保持停用,不会再开第二个。
- 开不成都照实说(服务没挂、宿主拒了、交接条递不进去、没归到工作区),不假装开了。
- 连续几次压不成,会停掉自动压缩、只留提醒,不反复折腾。
手动想开一个:/whale new。
验证
node scripts/verify.mjs # 语法 + 导入契约 + 单测
最近一次:963 条测试(60 个文件)全通过、65 个文件语法通过、inject 契约一致,Node.js 22 与 24 各跑一遍都是这个数,CI 也是这两档矩阵。
换会话那条路 2026-11-12 在真机上验过手动入口(/whale new:会话建出来、交接条递进去、落进同一工作区);自动入口的触发条件真机造不出来(要等真压完还超),但触发之后每一步都被测试盖着。
复制目录不用 fs.cpSync:node 22 在 Windows 上 cpSync(…, {recursive:true}) 会把进程直接打死(0xC0000409,没有异常可 catch),换库和导入回滚正好都走它。所以 lib/atomic.js 里的 copyTree 自己 walk 一遍,两个版本都验过。
已知边界
minimal预设下这套等于不存在。@deepseek-ai/dsh-persona配complete: true时,它那一段就是完整系统提示词,插件注入的段全部被盖掉——人格、模式、记忆、进度点一个都不进。更坑的是whale_pal_health照样回normal:插件挂载了 ≠ 提示词进去了。验插件别用minimal。- 评估要花模型调用,也要出网:每一轮够「有料」时发一次小模型请求,转录最多 24 条 / 4000 字。所以它不省 token 也不离线;评估失败(超时、截断)的那一轮就不记任何东西,不是记一半。
- 记忆取回不全带原话:390 条样本里 270 条追得到,其余是三种断点——长期层不带来源(40 条)、该轮没进任何档案卡(30 条)、存档里没有那一节(50 条)。取回文本会写明是哪一种,不拿相近的句子顶。
- 记忆会变淡、会被淘汰,每条 ≤300 字;不是「永久记住一切」。
- 压缩摘要有损:档案留了原文,但摘要本身是压过的;能取回,不等于每轮都读得到。
- 「压完仍超就自己开新会话」能验的都验了:判据(
acted='switch')、接线层开成/开不成两半、手动入口真机跑通。没验的只剩「宿主的真实读数会不会出现压完仍超」——那是环境,不是代码。 workspaceController的「服务缺席」路径只有单测盖过,真机上造不出这个场面——算测过,不算真机验过。- 按词检索,没有向量库;不做「人格画像 / 情绪模型 / 关系数值」。
- 模式按目录判,不跟
session.header.cwd走。 - 平台:只在 Windows + DSH 桌面版(profile
desktop)上验过。Linux / macOS 没验过,路径处理和文件锁可能是另一套。 - 旧插件
dsh-persona-framework还挂在 profile 里时,本插件拒绝启动——两套人格同时注入会当场分叉,这不是 bug 是护栏。
开发
改代码前看 docs/开发指南.md:目录地图、每个子系统的改动入口、验证命令、不许破的约束、发版流程。仓库根有 .gitignore 之外的东西(备份目录、演练夹具)不是源码,别当参考。
许可
MIT,见 LICENSE。
No comments yet. Be the first to write one.