为 DSH Agent 提供本地项目记忆层:把工作结论、经验教训、后续行动沉淀跨会话,并通过有界 Hot Memory 自动注入 + BM25 排序召回 + Web 面板管理。
- 语言
- TypeScript
- License
- Apache-2.0
- 分支
- main
安装
$ dsh plugin --profile web add github:Qinling-Melon-Farmers/dsh-memoir在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 Qinling-Melon-Farmers/dsh-memoir:先查看仓库 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
dsh-memoir 是 DSH 的本地项目记忆层:把 Agent 的工作结论、经验教训、后续行动沉淀到本机文件,让下一个会话自动继承这份「项目经验包」,解决「每次新会话都要重复交代项目背景」这个痛点。
核心能力
- 写入三类记忆:让 Agent 通过
memoir_record沉淀工作记录、经验教训、行动指南或备注 - 编辑已有记忆:通过
memoir_update改标题/正文/分类/标签,或标记为 superseded / archived,旧条目不会被删除 - 检索历史:通过
memoir_read按当前项目、跨项目或全局范围,配合 BM25 排序召回,支持中英文短语、代码标识符与路径关键词 - 自动注入上下文:每个会话开始时把 token 预算内的 Hot Memory 自动塞进 system prompt(默认 900/1200 token)
- 自动收尾提示:每个有实际工具调用的回合结束时,自动让 Agent 顺手沉淀本轮结论,可一键关闭
- Web 面板管理:在 DSH Web 侧边栏新增「记忆」面板,支持项目/全局浏览、排序搜索、增删改、置顶、归档、Hot Memory 预览与检索诊断
技术实现
- 语言: TypeScript(host 端 src/host/.ts,client 端 src/client/.ts(x))
- 关键依赖:
@deepseek-ai/dsh-tools(defineTool)、@deepseek-ai/dsh-system-prompt(注入段)、@deepseek-ai/dsh-host-webserver(路由)、@deepseek-ai/dsh-llm(UserMessage)、@deepseek-ai/dsh-client-runtime(client 端 bundle 注入) - 架构模式: Cordis 双面插件,含 9 个可插拔配置项;host 端注册工具、system-prompt 段、web 路由、
agent/turn-stopping事件监听;client 端通过 esbuild 打包为单文件闭包注入 DSH Web 渲染侧栏入口和面板。检索用本地倒排索引 + BM25(中文 2/3-gram + 英文单词 + 代码标识符),零 embedding、零外部服务 - 入口文件:
src/host/index.ts(host 端apply(ctx, config))+src/client/index.tsx(client 端apply(ctx)),由package.json的exports["."]与exports["./client"]分别暴露
适用场景
经常在 DSH 里做长期项目、跨多次会话的人:第一次踩过的坑、形成的项目红线、复用的部署步骤,记一次就再也不用在新会话里反复交代;中大型项目里接手别人(或几个月前的自己)写的代码时,项目记忆面板可以直接给接手者一个工作背景摘要。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | 0.1.0-rc.8+ | package.json 的 peerDependencies 声明 @deepseek-ai/dsh-llm ^0.1.0-rc.8 与 @deepseek-ai/dsh-tools ^0.1.0-rc.8;cordis.patch.yml 通过 dsh.bundle.patch 注入 web profile |
| Node.js | ^22.19.0 或 >=24.0.0 | package.json 的 engines.node 声明 |
| 平台 | macOS / Windows / Linux | 源码统一用 node:fs、node:http、node:crypto、node:os 标准模块;Windows 路径在 store 层做了全小写归一化 |
| 原生模块 | 无 | 全部依赖 Node.js 内置模块,无 node-gyp / 第三方原生模块 |
安装方式
dsh plugin --profile web add github:Qinling-Melon-Farmers/dsh-memoir
配置项
放到 cordis.patch.yml 中对应 id: memoir 的行下的 config 块(全部可选,缺省走源码默认值)。
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
enabled | 布尔 | 总开关;关闭后不注册工具、路由、注入段 | true |
announceToAgent | 布尔 | 是否在 system prompt 公告段宣告本插件存在 | true |
autoDistill | 布尔 | 每轮有实际工具调用的回合结束时,是否自动追一句归纳提示 | true |
hotMemoryTokens | 数字 | Hot Memory 注入的软目标 token 数(超出则停止追加) | 900 |
hotMemoryMaxTokens | 数字 | Hot Memory 注入的硬上限 token 数(永远不越过) | 1200 |
readDefaultLimit | 数字 | memoir_read 默认返回条数 | 8 |
readMaxLimit | 数字 | memoir_read 单次最大返回条数 | 30 |
sessionSnapshotMax | 数字 | 内存里冻结的会话快照 LRU 上限 | 128 |
queryCacheSize | 数字 | 排序召回查询的 LRU 缓存大小 | 128 |
常见问题
Q: 不做任何配置能直接用吗?
A: 可以。cordis.patch.yml 把所有配置项都标为可选默认值(enabled/announceToAgent/autoDistill 默认 true,hotMemoryTokens 默认 900,hotMemoryMaxTokens 默认 1200),不写 config 块也能正常使用。
Q: 数据存在哪里?会不会上云?
A: 全部留在本机。结构化 JSON 存在 ~/.dsh/dsh-memoir.json(唯一事实源),每个项目根目录还会自动生成 PROJECT_MEMORY.md 人类可读投影(可随 git 提交)。源码中没有任何 embedding API、向量库或云端记忆服务的调用。
Q: 会把全部历史都塞进 system prompt 吗?
A: 不会。v0.4 起只把 token 预算内的 Hot Memory(默认软目标 900 token、硬上限 1200 token)注入 system prompt;长尾历史需要时由 Agent 主动调用 memoir_read 触发 BM25 排序召回。
Q: 同会话里我刚记录的内容,下一轮就自动生效吗?
A: 不会立刻生效。注入文本会在同一会话首轮构建后冻结(保证 prompt 前缀稳定以命中前缀缓存),本会话不再重读;下一个新会话会重建并看到最新记录。
Q: 同时开两个 DSH 进程会冲突丢数据吗?
A: 不会。store 的读写走 ~/.dsh/dsh-memoir.lock 跨进程互斥(O_EXCL 独占创建 + 25ms 重试 + 5s 超时),临界区内强制重读磁盘再改写。锁带 pid/createdAt/nonce 元信息,仅在 60s 以上且 pid 已死亡时才会回收。
Q: Windows 路径大小写不同会被当成不同项目吗?
A: 会被识别为同一个项目。canonical key 把整条 Windows 路径全小写(C:\A、c:\a\、C:/A 归到同一个 c:/a 桶),但显示用的 path 仍然保留原始大小写。
Q: 如何标记一条过时记忆?会删除历史吗?
A: 用 memoir_update 把 status 设为 superseded 或 archived,或在 Web 面板里点相应按钮。源码明确不删除历史,被替代的条目留在 store 里,Web 面板可切换状态查看。
Q: 怎么卸载?
A: 从 web profile 的 bundle 配置里移除这个插入行(cordis.patch.yml 里的 memoir / dsh-memoir 行),重启 dsh web 生效;插件本身不写 DSH 源码,移除后宿主立即回到无该插件状态。
上手难度
入门 — 安装一行命令、不需要写任何配置;普通用户只需要等 Agent 自动提示或在需要时口头要求「记一下这个」即可使用。
已知问题与限制
- 项目活跃度判断依赖 cwd 路径:会话工作目录不在 Agent session header 里时,注入段会退化为只输出引导文案不注入具体记忆;同时也会跳过快照冻结、每轮重新构建。
- 跨进程锁有 5 秒超时:写入冲突严重时
memoir_record会抛出store lock timeout after 5000ms错误;锁文件被异常结束进程遗留时,只有超过 60 秒且持有 pid 已阵亡才会被下个进程回收。 - subagent / 嵌套委托会话不会被自动收尾提示打扰:自动蒸馏监听只在顶级会话(
origin !== 'subagent'且delegationDepth === 0)上触发,避免子任务被循环催归纳。 - 没有真正多用户隔离:store 以单租户形式存在,
~/.dsh/dsh-memoir.json不做权限分离,所有项目写在同一个文件里。 - 默认
queryCacheSize=128与sessionSnapshotMax=128是内存 LRU,长时间高并发运行(开几百个会话)会触发淘汰,但实测 10 万条索引的检索仍在毫秒级。
English · 中文 · 更新日志 · GitHub Releases
dsh-memoir 是 DeepSeek Harness 的本地项目记忆层:把 Agent 的工作结论、经验教训和后续行动持久化,并通过有界 Hot Memory 自动继承、按需排序召回和 Web GUI 管理,实现跨会话项目记忆。
Cache-aware local project memory for DeepSeek Harness.
- Local-only:全部数据留在本机(
~/.dsh/dsh-memoir.json+ 项目内PROJECT_MEMORY.md) - Zero external memory service:无向量数据库、无 embedding API、无云端记忆服务
- Bounded hot-memory injection:token 预算内的 Hot Memory 自动注入 system prompt(默认 900/1200)
- Ranked local recall:倒排索引 + BM25 本地排序召回,
memoir_read按需检索长尾历史 - Web GUI:侧边栏「记忆」面板——项目/全局浏览、相关排序搜索、Hot Memory Inspector、Retrieval Diagnostics
Quick Start
# 从 npm 安装到 web profile(推荐)
dsh plugin --profile web add dsh-memoir
# 或从 GitHub 安装最新源码
dsh plugin --profile web add github:Qinling-Melon-Farmers/dsh-memoir
# 或本地开发(克隆后)
dsh plugin --profile web add link:/绝对路径/dsh-memoir
安装后重启 DSH 生效(dsh web)。正常使用即可:
正常使用 Agent
↓
有实际工作的回合结束自动提醒归纳
↓
memoir_record 沉淀工作 / 教训 / 下一步
↓
未来 session 自动继承 Hot Memory(有界、排序、会话内冻结)
↓
需要长尾历史时 memoir_read(本地相关性排序召回)
Architecture
~/.dsh/dsh-memoir.json
│
│ SSOT(单一事实源)
▼
MemoirStore
┌─────────────┴─────────────┐
│ │
▼ ▼
PROJECT_MEMORY.md Retrieval Index
human-readable ranked recall
(git 可提交) │
│ ▼
│ memoir_read
│ GUI /search
│
▼
Hot Memory Selector
(token 预算)
│
▼
Session Snapshot
(每会话冻结)
│
▼
System Prompt
Memory Model:Full Memory vs Hot Memory
Full Memory(完整历史)——结构化 JSON SSOT + 自动重新生成的 PROJECT_MEMORY.md 投影。用途:完整历史、GUI 浏览、git 提交、人工检查、排序召回的数据源。
Hot Memory(有界注入)——selector 在 token 预算内选出的高价值记忆,注入 system prompt。特点:bounded / ranked / compact / session-frozen。
v0.4+ 不再把完整 PROJECT_MEMORY.md 注入模型:Hot Memory 进 prompt,长尾历史走排序召回。
Session Snapshot 冻结语义:同一 session 的注入文本只构建一次并冻结(prompt 前缀稳定,最大化 prompt-prefix cache 命中);当前 session 不重新消费自己刚写的记忆,新 session 重建并看到最新记忆。v0.4.2 起,没有唯一会话身份(session.id / agent.id)时不做冻结——宁可 cache miss,不可跨 session 错复用旧快照。
v0.5.1 生命周期完成与 rc8 兼容性
- 当前开发基线为
@deepseek-ai/dsh-* 0.1.0-rc.8;peer dependency 与开发依赖已统一到 rc8。 - 存储格式从 v2 迁移到 v3:旧条目保持原有
id、内容和时间,首次变更时补齐importance、pinned、status、supersedes与tags;启动读取不会重写旧文件。 - 默认只召回
active条目;归档和被替代条目保留在历史中,可在 Web 面板切换状态查看。显式supersedes会把目标条目标记为superseded,不会自动删除历史。 - Agent 可用
memoir_update原地编辑条目的分类、标题、正文和生命周期;Web 面板也支持编辑、置顶、标记过时、归档与恢复。 PROJECT_MEMORY.md是人类可读投影;system prompt 只注入有界 Hot Memory,完整文件不会整体注入。- GET 路由不再把浏览器传入的路径登记为活动工作区;只有可信 system-prompt cwd 才能获得面板写权限。锁文件现在带 pid、创建时间和 nonce,只在超过 60 秒且 pid 已死亡时保守回收。
memoir_read(scope: 'all')使用去重后的全局排序结果,避免当前项目与全局结果重复。
Tools
| 工具 | 作用 |
|---|---|
memoir_record | 写入 work(工作记录)/ lessons(经验教训)/ actions(行动指南)/ note(备注) |
memoir_update | 保留 id 和创建时间,更新既有条目的内容、分类、标签与生命周期;可用 supersedes 标记被替代历史 |
memoir_read | project(默认)/ global / all 的本地相关性检索,limit + compact/full 输出形态 |
memoir_read 的 query 描述与真实行为一致:本地相关性检索标题与正文,支持中文短语、英文关键词、代码标识符与路径,并按相关性排序。
Retrieval
- 无 embedding、无向量库、无外部记忆服务
- 中文 2/3-gram + 英文单词 + 代码/路径标识符分词
- BM25(文档侧保留真实 term frequency;query 侧去重)
- 标题 2.5× 加权、精确短语加权、分类权重、时间衰减
- 标题与正文各自独立的长度归一化(v0.4.2)
- epoch 感知 + 1 小时 time-bucket 的 LRU 查询缓存:limit/detail 不参与缓存键,所有输出形态共享同一份排序结果(v0.4.2)
- Query cache 指标(hits/misses/evictions/hit rate)与 Last Query(latency/candidates/returned)可观测(v0.4.2)
- 全局 recall 的 limit 是真正全局 Top-K,输出截断保留高分头部(v0.4.2)
curated 查询 Top-5 命中率 100%(质量门禁 ≥90%,见 test/recall-quality.test.ts)。
GUI
保留 v0.4 的 Project / Global / Search / Add / Delete / Diagnostics 架构,v0.4.2 起:
- 搜索统一走 RetrievalEngine:query 非空时面板调用
GET /api/dsh-memoir/search,与 agent 的memoir_read共用同一套 BM25 排序,结果按相关性排列并显示分数 - Hot Memory Inspector:展开查看当前工作区实际会被注入的 Hot Memory(Actions / Lessons / Recent state),即「下一会话到底自动继承什么」
- Retrieval Diagnostics:Retrieval Index(docs/terms/epoch)、Query Cache(hits/misses/evictions/hit rate/size/capacity)、Last Query(latency/returned)、Session Snapshot(hash/createdAt/storeRevision)
界面预览
1. 插件生效与整体 UI:侧边栏出现「记忆」入口(与 SSH / 任务看板同列、互斥展开),点击后在中心列打开记忆面板。

2. 项目记忆:当前项目会话的持久记忆按 工作记录 / 经验教训 / 行动指南 / 备注 分组展示,每条带时间、分类标签、标题、正文与会话来源,支持检索、刷新与逐条删除。

3. 手动添加记忆:表单选择分类、填写一句话标题与正文,与 agent 的 memoir_record 写入同一份数据,提交后 PROJECT_MEMORY.md 自动重新生成。

4. 全局记忆管理:所有项目的记忆桶(项目名、路径、更新时间、条数),跨项目检索与逐条维护。

5. 排序搜索 + Hot Memory 预览 + 记忆诊断(v0.4.2):搜索框输入 query 后走 RetrievalEngine 排序召回,每条结果带相关性分数;底部可展开「Hot Memory 预览」(查看当前工作区下一会话将自动继承的内容)与扩展后的 Memory Diagnostics(Retrieval 索引 / Query cache / 最近查询 / 会话快照)。

Storage & Privacy
~/.dsh/dsh-memoir.json ← 结构化 JSON(唯一事实源 / SSOT)
<工作区>/PROJECT_MEMORY.md ← 由 JSON 重新生成的人类可读投影(git 友好)
No cloud memory DB · No embedding API · No vector DB
JSON 是 source of truth,Markdown 是 generated projection:面板、工具、agent 三条路径写同一份数据。v0.4.2 起,面板写 API 还受工作区授权保护——浏览器提交的绝对路径不等于授权,仅当前活动 cwd 或已有 store 项目可写。
Configuration
在 cordis.patch.yml 的行上可加 config(全部可省略,默认值如下):
- insert:
- id: memoir
name: dsh-memoir
config:
enabled: true # 总开关(工具、路由、注入段)
announceToAgent: true # system prompt 公告段
autoDistill: true # 每轮有实际工作的回合结束自动提醒归纳
hotMemoryTokens: 900 # Hot Memory 目标 token 数
hotMemoryMaxTokens: 1200 # Hot Memory 硬上限(永不超过)
readDefaultLimit: 8 # memoir_read 默认返回条数
readMaxLimit: 30 # memoir_read 最大返回条数
sessionSnapshotMax: 128 # 每会话快照的 LRU 上限
queryCacheSize: 128 # 排序查询的 LRU 缓存大小
Design Trade-offs
- 有界注入 vs 全量注入:v0.3 把完整历史注入 prompt,越用越膨胀;v0.4+ 只注入预算内的 Hot Memory,长尾历史按需召回。token 基准见下方 Benchmark。
- 冻结 vs 新鲜:session 内冻结注入文本换取 prompt-prefix cache 命中;没有唯一会话身份时不冻结(v0.4.2),保证新 session 一定看到新记忆。
- Hot Memory 配额:Recent state(最新 work,1~3 条)保底、actions/lessons 排名填充,work 只进 Recent state 不重复注入(v0.4.2)。
- 多进程安全:store 的 record/remove 走
~/.dsh/dsh-memoir.lock跨进程临界区(O_EXCL 独占创建 + 超时),临界区内强制从磁盘重读再改,两个 DSH 进程交错写入不丢更新(v0.4.2)。 - Windows 路径:canonical key 全小写(
C:\A/c:\a\/C:/A一个桶),display path 保留原始大小写(v0.4.2)。 - GUI 与 Agent 同源:面板搜索与
memoir_read共用 RetrievalEngine,不再各写一套过滤逻辑(v0.4.2)。
Use Cases
| 场景 | 怎么用 |
|---|---|
| 反复出现的环境坑(乱码 / 转义 / 路径 / 权限) | 解决后记一条 lessons,附可复制的修复命令 |
| 项目红线与约定(禁 emoji、发布前跑测试、分支规范) | 记入 actions,自动注入给接手者 |
| 难查 bug 的根因与结论 | 记入 lessons / work,避免重复排查 |
| 部署 / 上线的固定步骤清单 | 记入 actions,新会话照单执行 |
| 跨项目复用经验 | 面板全局 tab 或 memoir_read(scope: 'global', query: ...) |
典型例子:第一次解决「控制台中文乱码」后把诊断结论与修复步骤记成一条 lessons(如 先 chcp 65001 …写文件一律 UTF-8 无 BOM),此后本项目每个新会话都自动继承这条经验,不再重复排查;跨项目用全局检索也能命中。记忆插件做的是把「根因 + 修复命令」沉淀为项目知识,不负责根治终端本身的编码缺陷。
Comparison
| 项目 | 主要定位 |
|---|---|
| dsh-memory | citation / 来源可追溯的引用式记忆 |
| dsh-mnemon | 更重的长期记忆体系 |
| distill | 会话蒸馏成 skill |
| dsh-memoir | 轻量的项目工作流记忆:本地、有界注入、排序召回 |
各插件定位不同,按需选择,不做谁强谁弱的比较。
Development / Benchmark / Tests
pnpm install # 安装 devDeps(typescript、esbuild、@deepseek-ai/* 类型包)
pnpm run build # tsc 构建 host + esbuild 构建 client bundle
pnpm run typecheck # 全量类型检查(src + test)
pnpm test # 142 项测试:store(含多进程锁) / snapshot / selector / retrieval / tools / routes / 自动收尾 / 集成 / client 纯逻辑 / bundle 协议与纯净性 / 发布说明
npm run bench # benchmark(100/1k/10k/100k 条目),结果写入 bench/report.md
质量门禁:Top-5 recall ≥ 90% · Hot Memory ≤ 配置 hardMax · 同会话 prompt 前缀稳定 · 全局召回 ≤ limit · 多进程写入零丢失。
v0.4.2 benchmark 摘要(node v22.23.2,budget 900/1200 tokens;完整报告见 bench/report.md。方法已修正:uncached 查询直测 search()、cached 查询先预热同一 query 再计时):
| 条目数 | 冷加载 | 热读取 | Hot Memory 构建 | 索引构建 | 未缓存查询 | 缓存查询 | 缓存命中率 | 全量 markdown tokens | 注入 tokens | 降幅 |
|---|---|---|---|---|---|---|---|---|---|---|
| 100 | 1.3 ms | 2.22 µs | 0.54 ms | 2.9 ms | 0.224 ms | 2.87 µs | 50.0% | 3870 | 902 | 76.7% |
| 1,000 | 1.6 ms | 0.40 µs | 0.70 ms | 15.0 ms | 1.419 ms | 1.45 µs | 50.0% | 38182 | 916 | 97.6% |
| 10,000 | 25.3 ms | 0.42 µs | 2.60 ms | 142.9 ms | 11.889 ms | 1.14 µs | 50.0% | 385807 | 902 | 99.8% |
| 100,000 | 158.2 ms | 0.42 µs | 31.97 ms | 2238.7 ms | 153.551 ms | 1.15 µs | 50.0% | 3907057 | 917 | 100.0% |
实现说明
- TypeScript 全栈:
src/host/*.ts(store / tools / retrieval / selector / snapshot / routes / autodistill / index,tsc 构建出lib/*.js)+src/client/*.ts(x)(esbuild 打出lib/client.js闭包工厂 bundle)。 - 双面插件:host 半注册 agent 工具、
/api/dsh-memoir路由、agent/turn-stopping自动收尾监听与按项目求值的 system prompt 注入段;client 半提供面板。运行时仅依赖官方 NPM SDK。 - 通过
dsh.bundle.patchmanifest(cordis.patch.yml的insert行)挂载,不改 DSH 源码。 - 自动收尾安全边界:仅顶级会话(跳过 subagent / 嵌套委托)、仅「有工具调用且未记录过」的回合、已中止回合不打扰、每回合至多一次。
贡献
PR 与 Issue 采用模板化 + 自动化管理:
- CONTRIBUTING.md — PR 范围、提交规范与检查清单;
- ISSUE_TRIAGE.md — Issue 标签体系、分类与关闭标准;
.github/ISSUE_TEMPLATE— Bug / 功能请求模板;.github/pull_request_template.md— PR 模板。
Bug 报告需附截图 / 日志证据、冒烟测试、引用代码与补丁;全新功能与仅文档类 PR 请先提 Issue 讨论。
Release
当前稳定版:v0.5.1(2026-08-20) · GitHub Release · npm。完整历史见 CHANGELOG.md。
每个版本的更新日志均同步维护中英文;GitHub Release 默认展开中文,英文说明收纳在可折叠的 English 区域。
版本发布由 .github/workflows/publish.yml 在 v* tag 推送后自动执行:安装依赖、校验 tag 与 package.json 版本一致、运行 typecheck/test、发布 npm,并创建同 tag 的 GitHub Release 和 tarball 资产。仓库需配置以下任一认证方式:
- npm Trusted Publishing:GitHub 仓库
Qinling-Melon-Farmers/dsh-memoir,workflowpublish.yml - GitHub Actions secret
NPM_TOKEN:使用具有发布权限且允许绕过发布 2FA 的 granular token
发布 patch 版本:
npm version patch
git push
git push origin vX.Y.Z # 使用 npm version 输出的实际版本号
npm version patch 会修改 package.json、创建版本提交并创建对应 tag;无需再次执行 git tag 或在本机执行 npm publish。
许可
Apache-2.0
收录徽章
[](https://deepseek-plugin.org/plugins/Qinling-Melon-Farmers/dsh-memoir)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。