sage-mem 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +247 -179
  2. package/package.json +89 -87
package/README.md CHANGED
@@ -1,179 +1,247 @@
1
- # sage-mem · DSH 的文件式记忆插件
2
-
3
- 给 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)装上**跨会话记忆**——agent 今天记住的事,明天的新会话自动想起来。
4
-
5
- 记忆存在**本地 markdown 文件**里(frontmatter + 正文),不是数据库。透明、可检查、防膨胀。
6
-
7
- > **DSH 版本兼容性(0.6.2 核对于 `0.2.0-rc.1`;0.5.3 核对于 `0.1.7-rc.1`)**
8
- > `@deepseek-ai/dsh-typert-protocol` 与 `@deepseek-ai/dsh-client-locale` 的 `lib/` 在 `0.1.7-rc.2` → `0.2.0-rc.1` 之间**逐字节未变**(导出符号零增删、签名零变化),peer 范围随之放宽为 `^0.1.2-rc.1 || ^0.2.0-rc.1`,同时覆盖两条版本线;插件在 0.2.0 上无需改动即可工作。
9
- > `session.deriveMessages()`(仍是同步)、`system-prompt/assemble` 事件、以及 `context.agent.session` 这条链,在 0.1.6 → 0.1.7 之间**均未改变**,本插件在 0.1.7 上无需改动即可工作。
10
- > 0.5.3 另加了一层防御:`deriveMessages()` 若哪天被改成异步,或 `Session` 上的历史读取接口被改名(0.1.7 起 `snapshotEvents` / `eventAt` / `ownEvents` 已标记弃用),插件会在**日志里报警**,而不是像以前那样静默地不再注入记忆。0.1.6 上的行为与 0.5.2 完全一致。
11
-
12
- ## 从 Claude Code 无损迁移
13
-
14
- 你已经在 Claude Code(CC)里养了一个 agent,舍不得它的记忆和人格?sage-mem 是「CC → DSH」迁移方案的一部分,**记忆与人格都能无损搬过来**:
15
-
16
- - **人格**:CC 的 `CLAUDE.md` → DSH 的 `AGENTS.md`,DSH 原生加载,纯文本一字不改就能用。
17
- - **记忆**:CC 沉淀的跨会话记忆 → sage-mem 的 `memory/` 目录(markdown + frontmatter,四类)。
18
-
19
- 没有数据库、没有私有格式——全都是 markdown 文本,**直接拷文件就完成迁移**。agent 换了身体,但依然记得你是谁、记得你们聊过什么、记得进行中的项目。
20
-
21
- ## 为什么用文件
22
-
23
- DSH 原生没有记忆系统,每个会话都是白纸。市面上的记忆方案大多走 SQLite + 常驻 worker:
24
-
25
- - 记忆写进数据库,**不透明**——想检查存了什么得查表,想清理要连数据库
26
- - 事件自动捕获会**膨胀**——"用户打了个招呼"这种无实质内容也被存进去
27
- - 需要一个**常驻 worker 进程** + 端口,多一份运维负担
28
-
29
- sage-mem 换成文件式:每条记忆一个 markdown 文件,直接用编辑器打开就能看、能改、能删。存不存由 agent 按规则判断,不是事件全捕获。没有 worker、没有 SQLite、没有端口。
30
-
31
- ## 功能
32
-
33
- - **按问题检索注入**:每次提问,插件扫记忆目录,用 frontmatter 的 `description` 和文件名做匹配,把相关记忆注入上下文,agent 第一轮就「想起来」
34
- - **每次会话必读**(v0.5):frontmatter 标了 `baseline: true` 的记忆,在新会话第一步无条件注入——给「待办清单」「你是谁」这类每次开场都该在场的记忆用(上限 5 条)
35
- - **四类记忆**:`user`(用户是谁)/ `feedback`(工作方式指导)/ `project`(项目状态)/ `reference`(外部信息指针)
36
- - **文件透明**:记忆就是 `*.md` 文件,frontmatter 存元数据,正文存内容
37
- - **防膨胀**:写入靠规则引导 agent 判断「存不存」,无实质内容、能靠代码/git 推导的不存
38
- - **Web 文件管理器**(v0.4):DSH 设置页「记忆管理」,浏览/查看/编辑/删除记忆文件,添加新记忆
39
- - **类型与标签筛选**(v0.6):文件列表顶部一排 chip,按四类 + 自定义标签筛;自定义标签写在 frontmatter 的 `tags`(flow / block / 逗号三种写法都认),从全库自动聚合带计数;与搜索框是 AND 关系
40
- - **记忆星图**(v0.4 加入,v0.6 重做):把记忆画成星空,按类型着色、按体积分级、按新鲜度分亮度,支持时间线与「诞生回放」。v0.6 换了渲染材质(中性深灰画布、锐利核心 + 收敛辉光、去掉衍射星芒与脉冲环),并把常驻满帧循环改成**按需重绘**:画面静止时不发起任何绘制
41
- - **做梦 dream**(v0.6):可选的记忆整理功能,见下一节
42
-
43
- ## 做梦(dream)
44
-
45
- 把记忆目录通读一遍:合并重复的、删掉被推翻的、修索引与断链、把相对日期换成绝对日期,让下一次会话能快速对上位置。
46
-
47
- **默认关闭**,在设置页「记忆管理 → 做梦」里开。三件事各自可选:
48
-
49
- | 选项 | 取值 | 说明 |
50
- |---|---|---|
51
- | 触发 | 只手动 / 满足条件自动跑 | 自动模式走三级门控,**最便宜的先查**:时间门(距上次 ≥ N 小时,一次读写)→ 会话门(期间 ≥ M 个会话有更新,一次目录扫描)→ 锁(防并发)。中间还夹一层 10 分钟扫描节流,免得「时间门过了、会话门没过」时每轮都重扫一遍
52
- | 改动方式 | 只出报告 / 直接改写 | 「只出报告」模式下**写工具根本不会挂给模型** —— 不是靠一句「请不要写」约束,是它没有手
53
- | 输入源 | 仅记忆目录 / 记忆 + 会话记录 | 后者会解压会话记录(zstd)做定向关键词搜索;代价是私密对话会进入模型上下文,token 成本也更高
54
-
55
- 模型可配(留空则跟随聊天页当前的默认模型),最多轮数、快照保留份数在「高级设置」里。
56
-
57
- **两道额外的安全网:**
58
-
59
- 1. **改写前自动快照**整个记忆目录(只快照顶层 `.md`,不含 `archive/`),落在 `<memory 目录的上一层>/.sage-mem/snapshots/<时间戳>/`,保留最近 N 份。理由是 memory 目录**不在任何版本控制下**、删除没有回收站,「可回滚」得自己造。
60
- 2. **跑完自动审计**:六查(索引悬空 / 漏索引 / `type` 与文件名前缀不一致 / CRLF / 双链断链 / frontmatter 里被 YAML 当注释吞掉的「空格+#」),结果与前后对比写进报告。它只报不改。
61
-
62
- 报告落在 `memory/dream/YYYYMMDD-HHmmss.md` —— 子目录,不会被扫成记忆条目。
63
-
64
- **安全边界在工具集上,不在提示词里**:做梦时宿主只把 `list_memory` / `read_memory` / `audit_memory`(+ 只读模式下的 `search_sessions`)交给模型;改写模式才多给 `write_memory` / `archive_memory`。而且没有「删除」这个能力 —— 归档是把文件移进 `archive/`,可人工捞回。
65
-
66
- ## 架构
67
-
68
- ```
69
- DSH(Cordis 插件)
70
- └─ sage-mem 插件(按问题检索 + 注入)← 本仓库
71
- │ Node fs 直读
72
- ▼
73
- memory/ 目录(markdown 文件,4 类)
74
- ├── user_*.md
75
- ├── feedback_*.md
76
- ├── project_*.md
77
- ├── reference_*.md
78
- └── MEMORY.md ← 索引
79
- ```
80
-
81
- 没有 worker、没有 SQLite、没有 HTTP 端口、没有常驻进程。
82
-
83
- ## 安装
84
-
85
- 在你的 DSH profile 的 `package.json` 里加:
86
-
87
- ```json
88
- {
89
- "dependencies": {
90
- "sage-mem": "github:gezi-wen/sage-mem"
91
- },
92
- "dsh": {
93
- "profile": {
94
- "bundles": ["sage-mem"]
95
- }
96
- }
97
- }
98
- ```
99
-
100
- 或 clone 后本地 link:
101
-
102
- ```json
103
- {
104
- "dependencies": {
105
- "sage-mem": "link:../sage-mem"
106
- }
107
- }
108
- ```
109
-
110
- 然后 `pnpm install` 重启 DSH。
111
-
112
- ## DSH 兼容性
113
-
114
- sage-mem 是纯 DSH 插件,在 `package.json` 的 `dsh.compatibility.dshReleases` 里逐版本声明兼容状态:
115
-
116
- | DSH 版本 | 状态 |
117
- | --- | --- |
118
- | 0.1.2-rc.1 | compatible |
119
- | 0.1.3-alpha.1 | compatible |
120
- | 0.1.3-alpha.2 | compatible |
121
- | 0.1.5-rc.1 | compatible |
122
- | 0.1.6-alpha.1 | compatible |
123
- | 0.1.6-alpha.2 | compatible |
124
-
125
- 自 DSH `0.1.6-alpha.2` 起,TypertCodec 契约从「读 `schema`」改为「读 `create()` 工厂」——
126
- 仍只写 `schema:` 的插件会在注册阶段直接抛错,导致整棵插件树加载失败。自 0.5.2 起每个 codec
127
- 同时带 `schema` 与 `create: () => schema`,因此**同一份构建同时兼容 alpha.1 及更早(读
128
- schema)与 alpha.2 及以后(读 create)**,升级 DSH 时不需要换插件版本。
129
-
130
- Node.js 要求 `>= 18`(见 `engines.node`)。
131
-
132
- ## 卸载
133
-
134
- 在 profile 的 `package.json` 里删掉 `sage-mem` 依赖,并从 `dsh.profile.bundles` 移除 `"sage-mem"`;
135
- `pnpm install` 后重启 DSH 即可。记忆 markdown 文件留在原目录,不受影响。
136
-
137
- ## 配置
138
-
139
- 用环境变量 `SAGE_MEM_DIR` 指定记忆目录,默认 `~/.sage-mem/memory`:
140
-
141
- ```
142
- SAGE_MEM_DIR=/path/to/your/memory
143
- ```
144
-
145
- 记忆文件格式:
146
-
147
- ```markdown
148
- ---
149
- name: 可选的短名
150
- description: 一句话说清这条记忆是什么(检索靠它,务必写准)
151
- metadata:
152
- type: user # user / feedback / project / reference
153
- baseline: true # 可选:新会话第一步无条件注入(上限 5 条)
154
- ---
155
-
156
- 记忆正文。
157
- ```
158
-
159
- `feedback` 类建议带 `**Why:**`(原因)和 `**How to apply:**`(何时生效)两行,方便判断边界。
160
-
161
- ## 验证
162
-
163
- 跨会话记忆链路(实测):
164
-
165
- 1. 会话 A 说「记住:我的猫叫芝麻,它喜欢晒太阳」——agent 按规则写进 `memory/`
166
- 2. 开新会话 B 问「我的猫叫什么」
167
- 3. agent 第一轮直接答出「芝麻」——记忆自动注入,无需 agent 自己找
168
-
169
- ## 相关项目
170
-
171
- - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — DSH 本体,一切皆插件
172
-
173
- ## 旧版
174
-
175
- 本仓库早期是 SQLite + worker 架构,已归档到 [`sqlite-worker`](../../tree/sqlite-worker) 分支。文件式是继任实现。
176
-
177
- ## License
178
-
179
- Apache-2.0
1
+ # sage-mem · DSH 的文件式记忆插件
2
+
3
+ [![npm version](https://img.shields.io/npm/v/sage-mem.svg?color=blue)](https://www.npmjs.com/package/sage-mem)
4
+ [![npm downloads](https://img.shields.io/npm/dm/sage-mem.svg)](https://www.npmjs.com/package/sage-mem)
5
+ [![license](https://img.shields.io/npm/l/sage-mem.svg)](https://github.com/gezi-wen/sage-mem/blob/main/LICENSE)
6
+ [![DSH](https://img.shields.io/badge/DSH-%E2%89%A5%200.1.2--rc.1-8a2be2)](https://github.com/deepseek-ai/deepseek-harness)
7
+
8
+ **给 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)装上跨会话记忆。纯 Markdown 存储,透明、可检查。**
9
+
10
+ > **如果这个工具帮到了你,欢迎给个 ⭐️ Star 支持一下!**
11
+
12
+ 记忆就是本地的一堆 Markdown 文件(frontmatter + 正文)——不是数据库,没有私有格式。agent 今天记住的事,明天的新会话自动想起来。
13
+
14
+ > **English** — file-based cross-session memory for DeepSeek Harness: every memory is a plain markdown file you can open, edit and delete; no database, no worker, no port.
15
+
16
+ ## 为什么需要 sage-mem
17
+
18
+ DSH 原生没有记忆系统。每个新会话都是一张白纸——agent 不记得你是谁,不记得你们昨天做到哪,不记得项目进行到哪一步。你只能每次重新交代一遍。
19
+
20
+ 市面上的记忆方案大多走 SQLite + 常驻 worker:记忆写进数据库就**不透明**(想看看存了什么得去查表),事件全捕获又会让库**膨胀**(「用户打了个招呼」也算一条),还得额外养一个进程和一个端口。
21
+
22
+ sage-mem 换一条路:**每条记忆就是一个 Markdown 文件**。用编辑器打开就能看、能改、能删;存不存由 agent 按规则判断,不做无差别捕获。让 agent 真正记住你和你的项目,而这份记忆始终握在你自己手里。
23
+
24
+ ## 核心特性
25
+
26
+ | 特性 | 说明 |
27
+ |---|---|
28
+ | **文件式存储** | 每条记忆一个 `.md`:frontmatter 存元数据,正文存内容。无数据库、无隐藏格式,VS Code 直接打开就能改 |
29
+ | **跨会话记忆** | 每轮提问自动扫记忆目录、按相关度挑出最相关的几条注入上下文。agent 第一轮就「想起来」,不需要它自己去翻文件 |
30
+ | **Claude Code 无损迁移** | CC 的记忆与人格都是 Markdown——**直接拷文件**就完成迁移,不写转换脚本。详见[下一节](#从-claude-code-无损迁移) |
31
+ | **零额外服务** | 无 worker、无 SQLite、无端口、无常驻进程,不需要额外的 API key 或云服务(运行时唯一的依赖是普通 npm 库 `zod`) |
32
+ | **防膨胀** | 靠规则引导 agent 判断「值不值得存」:无实质内容的不存,靠读代码 / git 能推出来的不存 |
33
+
34
+ 界面上还有三块附加能力(都可以不用):
35
+
36
+ - **记忆管理页**(v0.4)——DSH 设置页里的「记忆管理」:浏览、查看、编辑、删除、新建记忆,不用离开 GUI
37
+ - **类型与标签筛选**(v0.6)——文件列表顶部一排 chip,按四类 + 自定义标签筛;标签从全库自动聚合计数,与搜索框是 AND 关系
38
+ - **记忆星图**(v0.4 起,v0.6 重做)——把记忆画成星空:按类型着色、按体积分级、按新鲜度分亮度,还支持时间线与「诞生回放」。渲染是**按需重绘**,画面静止时不发起任何绘制
39
+
40
+ ![记忆星图](https://raw.githubusercontent.com/gezi-wen/sage-mem/main/docs/starmap.png)
41
+
42
+ *记忆星图:每颗星是一条记忆 —— 颜色对应类型、大小对应体积、亮度对应新鲜度,底部是四类计数与库总体积。全部 94 条记忆的文件名不会出现在图里,星图只画关系与分布。*
43
+
44
+ ## 快速开始
45
+
46
+ 需要 DSH `0.1.2-rc.1` 或更高(见[兼容性](#dsh-兼容性)),Node.js `>= 18`。
47
+
48
+ ```bash
49
+ # 把 web 换成你自己的 profile 名
50
+ dsh plugin --profile web add sage-mem
51
+ ```
52
+
53
+ `dsh plugin add` 一步做两件事:把 `sage-mem` 装进这个 profile 的依赖,**并自动把它的 bundle 追加进 `dsh.profile.bundles`**——不用手改 `package.json`。
54
+
55
+ 装完重启 DSH。确认装上了:
56
+
57
+ ```bash
58
+ dsh plugin --profile web list
59
+ ```
60
+
61
+ 然后**开一个新会话**试一句:
62
+
63
+ 1. 跟 agent 说「记住:我的猫叫芝麻,它喜欢晒太阳」——它按规则把这条写进记忆目录
64
+ 2. 再开一个**新会话**,问「我的猫叫什么」
65
+ 3. 第一轮就该答出「芝麻」——记忆由插件自动检索并注入,agent 没有主动去翻
66
+
67
+ <details>
68
+ <summary>手动安装(不想用 CLI,或要装本地开发版本)</summary>
69
+
70
+ 在 profile 的 `package.json` 里加依赖,并把包名写进 `dsh.profile.bundles`:
71
+
72
+ ```json
73
+ {
74
+ "dependencies": {
75
+ "sage-mem": "^0.6.2"
76
+ },
77
+ "dsh": {
78
+ "profile": {
79
+ "bundles": ["sage-mem"]
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ 本地开发用 clone 出来的源码:
86
+
87
+ ```json
88
+ {
89
+ "dependencies": {
90
+ "sage-mem": "link:../sage-mem"
91
+ }
92
+ }
93
+ ```
94
+
95
+ 改完跑 `pnpm install`,再重启 DSH。
96
+
97
+ </details>
98
+
99
+ ### 记忆目录
100
+
101
+ 默认在 `~/.sage-mem/memory`。想放到别处(比如放进项目仓库、跟着 git 走)就设环境变量:
102
+
103
+ ```bash
104
+ SAGE_MEM_DIR=/path/to/your/memory
105
+ ```
106
+
107
+ ## 从 Claude Code 无损迁移
108
+
109
+ 你已经在 Claude Code(CC)里养了一个 agent,舍不得它的记忆和人格?sage-mem 是「CC → DSH」迁移方案的一部分,**两样都能无损搬过来**:
110
+
111
+ | 搬什么 | 从 | 到 | 怎么搬 |
112
+ |---|---|---|---|
113
+ | **人格** | CC 的 `CLAUDE.md` | DSH 的 `AGENTS.md` | DSH 原生加载,纯文本,一字不改就能用 |
114
+ | **记忆** | CC 沉淀的跨会话记忆 | sage-mem 的 `memory/` 目录 | markdown + frontmatter 四类,拷进去即可 |
115
+
116
+ 没有数据库、没有私有格式——全都是 Markdown 文本,**直接拷文件就完成迁移**。agent 换了身体,但依然记得你是谁、记得你们聊过什么、记得进行中的项目。
117
+
118
+ ## 检索是怎么工作的
119
+
120
+ 透明的东西值得说清楚它怎么选料,因为它直接决定注入多少 token:
121
+
122
+ - **信号是 `description`,不是全文**。每条记忆的 `description`(「一句话说清这条是什么」)加文件名参与打分,最多注入 **5 条**相关记忆。旧版拿问题里的双字去全文里蒙,长记忆天生占便宜——实测连「今天天气不错」都能注入 2300 token;改用 `description` 后噪音大幅下降
123
+ - **正文超 1500 字符就截断**并标 `…(截断)`,单条记忆不会吃掉整个上下文
124
+ - **同一个问题不会重复注入**(按会话记签名),问第二遍不会又追加一遍
125
+ - **`baseline: true` 的记忆每场会话第一步无条件注入**,最多 5 条——给「你是谁」「待办清单」这类每次开场都该在场的记忆用
126
+ - 记忆目录读不到、权限错、frontmatter 格式坏,这些都**降级为不注入并写日志**,不会静默失效
127
+
128
+ 单文件上限 512 KB;标签最多 20 个、每个 40 字符(再多就不是标签,是一句话被塞进 `tags` 了)。
129
+
130
+ ## 做梦(dream)
131
+
132
+ 可选的记忆整理功能:把记忆目录通读一遍——合并重复的、删掉被推翻的、修索引与断链、把相对日期换成绝对日期,让下一次会话能快速对上位置。
133
+
134
+ **默认关闭**,在设置页「记忆管理 → 做梦」里开。三件事各自可选:
135
+
136
+ | 选项 | 取值 | 说明 |
137
+ |---|---|---|
138
+ | 触发 | 只手动 / 满足条件自动跑 | 自动模式走三级门控,**最便宜的先查**:时间门(距上次 ≥ N 小时,一次读写)→ 会话门(期间 ≥ M 个会话有更新,一次目录扫描)→ 锁(防并发)。中间夹一层 10 分钟扫描节流,免得「时间门过了、会话门没过」时每轮白扫 |
139
+ | 改动方式 | 只出报告 / 直接改写 | 「只出报告」模式下**写工具根本不会挂给模型**——不是靠一句「请不要写」约束,是它没有手 |
140
+ | 输入源 | 仅记忆目录 / 记忆 + 会话记录 | 后者会解压会话记录(zstd)做定向关键词搜索;代价是私密对话会进入模型上下文,token 成本也更高 |
141
+
142
+ 模型可配(留空则跟随聊天页当前的默认模型),最多轮数、快照保留份数在「高级设置」里。
143
+
144
+ **三道安全网:**
145
+
146
+ 1. **安全边界在工具集上,不在提示词里**——做梦时宿主只把 `list_memory` / `read_memory` / `audit_memory`(只读模式另加 `search_sessions`)交给模型,改写模式才多给 `write_memory` / `archive_memory`。而且**没有「删除」这个能力**:归档是把文件移进 `archive/`,可以人工捞回
147
+ 2. **改写前自动快照**整个记忆目录(只快照顶层 `.md`,不含 `archive/`),落在 `<memory 目录的上一层>/.sage-mem/snapshots/<时间戳>/`,保留最近 N 份。理由是记忆目录**不在任何版本控制下**、删除没有回收站,「可回滚」得自己造
148
+ 3. **跑完自动审计**:六查(索引悬空 / 漏索引 / `type` 与文件名前缀不一致 / CRLF / 双链断链 / frontmatter 里被 YAML 当注释吞掉的「空格 + #」),结果与前后对比写进报告。它**只报不改**
149
+
150
+ 报告落在 `memory/dream/YYYYMMDD-HHmmss.md`——子目录,不会被扫成记忆条目。
151
+
152
+ ## 记忆文件格式
153
+
154
+ ````markdown
155
+ ---
156
+ name: 可选的短名
157
+ description: 一句话说清这条记忆是什么(检索靠它,务必写准)
158
+ metadata:
159
+ type: user # user / feedback / project / reference
160
+ tags: [项目, 待办] # 可选,供列表页筛选
161
+ baseline: true # 可选:新会话第一步无条件注入(上限 5 条)
162
+ ---
163
+
164
+ 记忆正文。
165
+ ````
166
+
167
+ 四类记忆:
168
+
169
+ | 类型 | 存什么 |
170
+ |---|---|
171
+ | `user` | 用户是谁 |
172
+ | `feedback` | 工作方式指导(建议带 `**Why:**` 与 `**How to apply:**` 两行,方便判断边界) |
173
+ | `project` | 进行中的工作与状态 |
174
+ | `reference` | 外部信息在哪找的指针 |
175
+
176
+ ## 架构
177
+
178
+ ```
179
+ DSH(Cordis 插件)
180
+ └─ sage-mem 插件(按问题检索 + 注入)← 本仓库
181
+ │ Node fs 直读
182
+ ▼
183
+ memory/ 目录(markdown 文件,4 类)
184
+ ├── user_*.md
185
+ ├── feedback_*.md
186
+ ├── project_*.md
187
+ ├── reference_*.md
188
+ └── MEMORY.md ← 索引
189
+ ```
190
+
191
+ 没有 worker、没有 SQLite、没有 HTTP 端口、没有常驻进程。
192
+
193
+ ## 权限与数据
194
+
195
+ sage-mem 只做三件事,全都在你本机:
196
+
197
+ | 它做什么 | 具体范围 |
198
+ |---|---|
199
+ | **读记忆** | 只读 `SAGE_MEM_DIR`(默认 `~/.sage-mem/memory`)下的顶层 `*.md`,单文件上限 512 KB |
200
+ | **写记忆** | 经 agent 的文件工具或设置页写同一个目录;`MEMORY.md`、`session-log.md` 等保留名受保护,设置页碰不到 |
201
+ | **注入** | 把选中的记忆作为上下文交给模型(最多 5 条相关 + 5 条 `baseline`) |
202
+
203
+ **它不做什么**:不联网、不开端口、不起常驻进程、不需要任何 API key;不读记忆目录以外的文件;
204
+ 不做事件全捕获(存不存由 agent 按规则判断,不是"你说了什么都记")。
205
+
206
+ 记忆就是那个目录里的文件,随时可以打开确认——这也是选文件式的原因。
207
+
208
+ (唯一会调用模型的功能是「做梦」,用的是你已在用的那个模型,默认关闭。)
209
+
210
+ ## DSH 兼容性
211
+
212
+ sage-mem 是纯 DSH 插件,用 `package.json` 的 **`engines.dsh`** 声明宿主要求:`>=0.1.2-rc.1` —— **单边开区间、不设上界**,所以任何未来的 DSH 版本都不会被这道声明挡住。逐版本核对记录如下:
213
+
214
+ | DSH 版本 | 状态 |
215
+ | --- | --- |
216
+ | 0.1.2-rc.1 | compatible |
217
+ | 0.1.3-alpha.1 | compatible |
218
+ | 0.1.3-alpha.2 | compatible |
219
+ | 0.1.5-rc.1 | compatible |
220
+ | 0.1.6-alpha.1 | compatible |
221
+ | 0.1.6-alpha.2 | compatible |
222
+ | 0.1.7-rc.1 | compatible |
223
+ | 0.1.7-rc.2 | compatible |
224
+ | 0.2.0-rc.1 | compatible |
225
+ | 0.2.0-rc.2 | compatible |
226
+
227
+ 两点值得说明:
228
+
229
+ - **同一份构建同时覆盖 `0.1.x` 与 `0.2.x` 两条线。** 自 DSH `0.1.6-alpha.2` 起,TypertCodec 契约从「读 `schema`」改为「读 `create()` 工厂」——仍只写 `schema:` 的插件会在注册阶段直接抛错,把整棵插件树拖垮。自 0.5.2 起每个 codec 同时带 `schema` 与 `create: () => schema`,因此两个时代的 DSH 都能加载。peer 范围自 0.6.4 起写 `>=0.1.2-rc.1` —— 去掉上界,避免以后某个大版本被这道声明误挡(已逐字节核对 `dsh-typert-protocol` 与 `dsh-client-locale` 在 `0.1.7-rc.2 → 0.2.0-rc.1` 之间导出符号零增删)
230
+ - **0.5.3 起带一层防御留痕。** `deriveMessages()`(仍是同步)、`system-prompt/assemble` 事件、`context.agent.session` 这条链在升级中都没变;但如果哪天 DSH 把它们改成异步或改了名,插件会在**日志里报警**,而不是像以前那样静默地不再注入记忆
231
+
232
+ ## 卸载
233
+
234
+ 在 profile 的 `package.json` 里删掉 `sage-mem` 依赖,并从 `dsh.profile.bundles` 移除 `"sage-mem"`;`pnpm install` 后重启 DSH 即可。**记忆 Markdown 文件留在原目录,不受影响。**
235
+
236
+ ## 相关项目
237
+
238
+ - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — DSH 本体,一切皆插件
239
+ - [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) — DSH 插件生态清单
240
+
241
+ ## 旧版
242
+
243
+ 本仓库早期是 SQLite + worker 架构,已归档到 [`sqlite-worker`](https://github.com/gezi-wen/sage-mem/tree/sqlite-worker) 分支。文件式是继任实现。
244
+
245
+ ## License
246
+
247
+ Apache-2.0
package/package.json CHANGED
@@ -1,87 +1,89 @@
1
- {
2
- "name": "sage-mem",
3
- "description": "File-based memory plugin for DeepSeek Harness (DSH) — cross-session memory in transparent markdown files, with a memory star-map view, type/tag filtering, and an optional dream pass that consolidates memories on demand or on a schedule",
4
- "version": "0.6.2",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "exports": {
8
- ".": "./lib/index.js",
9
- "./client": "./lib/client.js",
10
- "./typert": "./lib/typert.host.js",
11
- "./package.json": "./package.json"
12
- },
13
- "files": [
14
- "lib/",
15
- "cordis.patch.yml",
16
- "NOTICE"
17
- ],
18
- "license": "Apache-2.0",
19
- "engines": {
20
- "node": ">=18"
21
- },
22
- "dsh": {
23
- "bundle": {
24
- "patch": "./cordis.patch.yml"
25
- },
26
- "client": {
27
- "platform": "web",
28
- "inject": [
29
- "@deepseek-ai/dsh-client-locale"
30
- ]
31
- },
32
- "compatibility": {
33
- "dsh": ">=0.1.2-rc.1",
34
- "dshReleases": {
35
- "0.1.2-rc.1": "compatible",
36
- "0.1.3-alpha.1": "compatible",
37
- "0.1.3-alpha.2": "compatible",
38
- "0.1.5-rc.1": "compatible",
39
- "0.1.6-alpha.1": "compatible",
40
- "0.1.6-alpha.2": "compatible",
41
- "0.1.7-rc.1": "compatible",
42
- "0.1.7-rc.2": "compatible",
43
- "0.2.0-rc.1": "compatible"
44
- }
45
- }
46
- },
47
- "dependencies": {
48
- "zod": "^4.4.3"
49
- },
50
- "devDependencies": {
51
- "react": "^18.0.0"
52
- },
53
- "peerDependencies": {
54
- "@deepseek-ai/cordis": "^4.0.2",
55
- "@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1 || ^0.2.0-rc.1",
56
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1 || ^0.2.0-rc.1",
57
- "react": "^18.0.0"
58
- },
59
- "repository": {
60
- "type": "git",
61
- "url": "git+https://github.com/gezi-wen/sage-mem.git"
62
- },
63
- "homepage": "https://github.com/gezi-wen/sage-mem#readme",
64
- "bugs": {
65
- "url": "https://github.com/gezi-wen/sage-mem/issues"
66
- },
67
- "keywords": [
68
- "memory",
69
- "ai-memory",
70
- "agent-memory",
71
- "long-term-memory",
72
- "cross-session-memory",
73
- "context-management",
74
- "knowledge-management",
75
- "markdown",
76
- "dsh",
77
- "dsh-plugin",
78
- "deepseek",
79
- "deepseek-harness",
80
- "cordis",
81
- "typert",
82
- "plugin",
83
- "ai-agent",
84
- "agent",
85
- "claude-code"
86
- ]
87
- }
1
+ {
2
+ "name": "sage-mem",
3
+ "description": "File-based memory plugin for DeepSeek Harness (DSH) — cross-session memory in transparent markdown files, with a memory star-map view, type/tag filtering, and an optional dream pass that consolidates memories on demand or on a schedule",
4
+ "version": "0.6.4",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "exports": {
8
+ ".": "./lib/index.js",
9
+ "./client": "./lib/client.js",
10
+ "./typert": "./lib/typert.host.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "files": [
14
+ "lib/",
15
+ "cordis.patch.yml",
16
+ "NOTICE"
17
+ ],
18
+ "license": "Apache-2.0",
19
+ "engines": {
20
+ "node": ">=18",
21
+ "dsh": ">=0.1.2-rc.1"
22
+ },
23
+ "dsh": {
24
+ "bundle": {
25
+ "patch": "./cordis.patch.yml"
26
+ },
27
+ "client": {
28
+ "platform": "web",
29
+ "inject": [
30
+ "@deepseek-ai/dsh-client-locale"
31
+ ]
32
+ },
33
+ "compatibility": {
34
+ "dsh": ">=0.1.2-rc.1",
35
+ "dshReleases": {
36
+ "0.1.2-rc.1": "compatible",
37
+ "0.1.3-alpha.1": "compatible",
38
+ "0.1.3-alpha.2": "compatible",
39
+ "0.1.5-rc.1": "compatible",
40
+ "0.1.6-alpha.1": "compatible",
41
+ "0.1.6-alpha.2": "compatible",
42
+ "0.1.7-rc.1": "compatible",
43
+ "0.1.7-rc.2": "compatible",
44
+ "0.2.0-rc.1": "compatible",
45
+ "0.2.0-rc.2": "compatible"
46
+ }
47
+ }
48
+ },
49
+ "dependencies": {
50
+ "zod": "^4.4.3"
51
+ },
52
+ "devDependencies": {
53
+ "react": "^18.0.0"
54
+ },
55
+ "peerDependencies": {
56
+ "@deepseek-ai/cordis": "^4.0.2",
57
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.2-rc.1",
58
+ "@deepseek-ai/dsh-client-locale": ">=0.1.2-rc.1",
59
+ "react": "^18.0.0"
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/gezi-wen/sage-mem.git"
64
+ },
65
+ "homepage": "https://github.com/gezi-wen/sage-mem#readme",
66
+ "bugs": {
67
+ "url": "https://github.com/gezi-wen/sage-mem/issues"
68
+ },
69
+ "keywords": [
70
+ "memory",
71
+ "ai-memory",
72
+ "agent-memory",
73
+ "long-term-memory",
74
+ "cross-session-memory",
75
+ "context-management",
76
+ "knowledge-management",
77
+ "markdown",
78
+ "dsh",
79
+ "dsh-plugin",
80
+ "deepseek",
81
+ "deepseek-harness",
82
+ "cordis",
83
+ "typert",
84
+ "plugin",
85
+ "ai-agent",
86
+ "agent",
87
+ "claude-code"
88
+ ]
89
+ }