前言¶
用 DSH 这类 harness 做智能体开发,常见困扰是会话之间什么都没留下:上一轮你告诉模型「本项目统一用 Vue3 <script setup>」,新开会话它就忘了。常见的补救是把记忆塞进向量库、靠相似度检索——代价是记忆本体变成一串不可读的数字,过期信息藏在库里,观测不到也修不了。
@max-null/dsh-memory 走的是另一条路:记忆全部是明文,检索用确定性的 BM25,写入要过人工确认闸门。下面介绍它的设计与用法。
这是什么¶
@max-null/dsh-memory 是一个面向 DeepSeek Harness 的跨会话明文记忆插件,由 Max-Null 维护,MIT 许可证,当前版本 0.6.0。它属于 @max-null/* 插件系列,与 SSID(思灵 · Seek Soul in Darkness)桌面体验整合。
它遵循 DSH「一切皆插件」的理念:不修改 DSH 源码,声明 name / inject / apply,由 Loader 从 cordis.yml 加载。
核心设计:人是所有者¶
插件的设计原则可以概括为三条:
- 人是所有者:模型只能写入
suggested状态的记忆,永远不能自我提升;只有人工确认(setStatus)才能让记忆生效。 - 可观测先于精准:每条记忆是明文,
memory_list随时可见,memory_forget随时删除,不存在「静默暗礁」。 - 确定性且缓存安全:BM25 关键词检索是存储的纯函数,无 LLM 调用。
注意 approved 与 injected 是两个独立状态:确认生效是一回事,是否每轮常驻注入是另一回事,由独立开关决定。
提供的服务、工具与注入¶
- 服务
ctx.memory:remember/list/search/forget/setStatus - 工具:
memory_save、memory_list、memory_search、memory_confirm、memory_forget、memory_update - 注入:
tool:memory指引 section +memory:recall召回 context - 检索:BM25 关键词检索,CJK 单字 + 2-gram 切分,
content与keywords字段分离加权
memory:recall 注入的是 global 与当前会话工作区里 approved + injected 的记忆,逐条带 [memory:<id>:<namespace>] 来源标记,以单行摘要进入 system prompt,并按注入预算截断;超预算时按最近使用优先截断,省略数在面板可见。memory_search 命中会更新 lastUsedAt 做冷热追踪。
两层存储¶
记忆按 namespace 分两层物理存储,各自落在独立的明文 JSON:
| namespace | 默认位置 | 用途 |
|---|---|---|
global |
$DSH_HOME/storages/memory.json |
跨项目的个人偏好 |
project |
<cwd>/.dsh/storages/memory_project_<hash>.json |
跟随仓库的项目共识,随 git 分享 |
几个细节:
- 两个根都可用 config 覆盖(
globalRoot/projectRoot)。 memory_list/memory_search不带namespace过滤时同时查两层。- 旧版双重前缀文件名在打开时自动迁移为规范名。
明文 + 落在项目文件夹内,意味着 project 层记忆能随 git 提交分享给所有协作者,团队共识可以沉淀进仓库。
安装与启用¶
1、安装:
npm install @max-null/dsh-memory
2、在 cordis.yml 加一条。记忆的存储后端由插件自己注册,storage / system-prompt / tools 等由宿主以 peerDependencies 提供:
- id: memory
name: '@max-null/dsh-memory'
可选配置¶
在 cordis.yml 的 config 里传给插件,以下均可省略:
- id: memory
name: '@max-null/dsh-memory'
config:
injectionBudget: 1500 # 常驻注入预算(字符;null = 不限制)
summaryChars: 80 # 单条注入摘要截断上限(字符)
semanticTopK: 5 # 语义侧参与融合的 topK(仅配置 embeddings 时生效)
# embeddings: { embed(texts): Promise<number[][]>, similarity? }
缺省即纯 BM25。语义融合是 0.5.2 引入的可插拔选项:配置 embeddings 后,memory_search 以 BM25 + 语义 RRF 融合,向量增量生成并持久化,嵌入调用失败自动降级为纯 BM25。记忆本体仍是明文,向量只作为检索辅助字段(vector,明文可读)。
典型使用流程¶
模型 memory_save → status: suggested(只是建议,未生效)
人 memory_confirm → status: approved(已审核;是否常驻注入由独立开关 injected 决定)
人(面板/开关) → injected: true(每轮注入,摘要化 + 预算截断)
memory_search → 关键词/语义召回任意状态记忆(命中标记 lastUsedAt)
memory_forget → 随时删除
两点说明:memory_search 不限状态,任何状态的记忆都能被召回,但只有 approved + injected 的记忆才进常驻注入;模型侧从头到尾只有「提议权」,生效与否始终由人决定。
提示词模板库(0.6.0)¶
0.6.0 新增提示词模板库,由四个工具管理:prompt_search / prompt_get / prompt_list / prompt_add。
md 文件是唯一事实源:
- global:
~/.dsh/prompt-library/*.md - 随工作区分享:
<workspace>/.dsh/prompt-library/
模板存在即生效,source: agent 角标标识模型新增的模板;前端(记忆面板「模板」tab)与模型工具检索的是同一份索引。提示词模板永不注入 system prompt。
开发与验证¶
如果你要参与开发或自行构建:
npm install
npm run typecheck # tsc 严格类型检查
npm test # vitest 单测
npm run build # 产出 dist/
node scripts/verify-loader.mjs # 用 Loader 端到端验证插件可加载
适用场景与注意¶
适合:
- 希望智能体跨会话记住个人偏好与项目共识的 DSH 用户
- 团队想把项目层共识随 git 仓库分享
- 在意记忆可审计、召回可解释,不放心向量黑盒的场景
注意:
- 插件以当前 dsh 进程权限运行,可读写其存储目录。安装任何第三方插件前,建议先检查源码与许可证(本插件为 MIT)。
- 语义检索需要在 config 中提供
embeddings实现,缺省为纯 BM25。 - 社区插件目录是独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-memory 把「记忆」从黑盒拉回明文:模型提议、人确认、BM25 确定性召回、每条可查可删。如果你在用 DSH 且苦于会话间失忆,可以按上面的步骤接入试试。
- 目录页:https://www.skillhub.cn/plugins/Max-Null/dsh-memory
- GitHub:https://github.com/Max-Null/dsh-memory