sage-mem 0.6.3 → 0.7.0
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.
- package/README.md +282 -242
- package/lib/{dream-audit.js → autodream-audit.js} +31 -13
- package/lib/{dream-prompt.js → autodream-prompt.js} +22 -14
- package/lib/{dream-tools.js → autodream-tools.js} +159 -26
- package/lib/autodream.js +1722 -0
- package/lib/client.js +460 -142
- package/lib/index.js +219 -67
- package/lib/typert.host.js +182 -54
- package/package.json +89 -87
- package/lib/dream.js +0 -886
package/README.md
CHANGED
|
@@ -1,242 +1,282 @@
|
|
|
1
|
-
# sage-mem · DSH 的文件式记忆插件
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/sage-mem)
|
|
4
|
-
[](https://www.npmjs.com/package/sage-mem)
|
|
5
|
-
[](https://github.com/gezi-wen/sage-mem/blob/main/LICENSE)
|
|
6
|
-
[](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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
1
|
+
# sage-mem · DSH 的文件式记忆插件
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/sage-mem)
|
|
4
|
+
[](https://www.npmjs.com/package/sage-mem)
|
|
5
|
+
[](https://github.com/gezi-wen/sage-mem/blob/main/LICENSE)
|
|
6
|
+
[](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
|
+

|
|
41
|
+
|
|
42
|
+
*记忆星图:每颗星是一条记忆 —— 颜色对应类型、大小对应体积、亮度对应新鲜度,底部是四类计数与库总体积。画布上只画关系与分布;悬停或点开某颗星时才会显示那一条的文件名。*
|
|
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.7.0"
|
|
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`(「一句话说清这条是什么」)、文件名、以及可选的 `aliases`(别称)一起参与打分,最多注入 **10 条**相关记忆。旧版拿问题里的双字去全文里蒙,长记忆天生占便宜——实测长记忆在全文匹配下连寒暄问句都能注入上千 token;改用 `description` 后噪音大幅下降
|
|
123
|
+
- **换个说法也能命中**:打分是**词面重合**(双字组覆盖率),不是语义的——问「我有什么待办」而文件里写的是「代办清单」,差一个字就完全不命中。给这类记忆加一行 `aliases: [待办, todo]` 就能补上
|
|
124
|
+
- **正文超 1500 字符就截断**并标 `…(截断)`,单条记忆不会吃掉整个上下文
|
|
125
|
+
- **同一个问题不会重复注入**(按会话记签名),问第二遍不会又追加一遍
|
|
126
|
+
- **`baseline: true` 的记忆每场会话第一步无条件注入**,最多 8 条——给「你是谁」「待办清单」这类每次开场都该在场的记忆用。多条 baseline 之间的先后由 `baselinePriority` 决定(数字越大越前,缺省 0),**不按文件名排**
|
|
127
|
+
- 记忆目录读不到、权限错、frontmatter 格式坏,这些都**降级为不注入并写日志**,不会静默失效
|
|
128
|
+
|
|
129
|
+
单文件上限 512 KB;标签最多 20 个、每个 40 字符(再多就不是标签,是一句话被塞进 `tags` 了)。
|
|
130
|
+
|
|
131
|
+
## 自动做梦(autodream)
|
|
132
|
+
|
|
133
|
+
可选的记忆整理功能:把记忆目录通读一遍——合并重复的、删掉被推翻的、修索引与断链、把相对日期换成绝对日期,让下一次会话能快速对上位置。
|
|
134
|
+
|
|
135
|
+
**默认关闭**,在设置页「记忆管理 → 自动做梦」里开。三件事各自可选:
|
|
136
|
+
|
|
137
|
+
| 选项 | 取值 | 说明 |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| 触发 | 只手动 / 满足条件自动跑 | 自动模式走三级门控,**最便宜的先查**:时间门(距上次 ≥ N 小时,一次读写)→ 会话门(期间 ≥ M 个会话有更新,一次目录扫描)→ 锁(防并发)。中间夹一层 10 分钟扫描节流,免得「时间门过了、会话门没过」时每轮白扫 |
|
|
140
|
+
| 改动方式 | 只出报告 / 直接改写 | 「只出报告」模式下**写工具根本不会挂给模型**——不是靠一句「请不要写」约束,是它没有手 |
|
|
141
|
+
| 输入源 | 仅记忆目录 / 记忆 + 会话记录 | 后者会解压会话记录(zstd)做定向关键词搜索;代价是私密对话会进入模型上下文,token 成本也更高 |
|
|
142
|
+
|
|
143
|
+
### 整理用的模型可以单独指定
|
|
144
|
+
|
|
145
|
+
整理是后台批量任务,跟聊天用的不一定是同一个模型。设置页「高级设置 → 模型」可以从**当前已配置的模型路线**里挑一条(选项与「模型选择」里的目录同源,也带每条的显示名);第一项是**跟随当前会话默认模型**。
|
|
146
|
+
|
|
147
|
+
- 选了就**只认它**:路线在宿主里不存在时,**开工前就报错**(运行前的纯本地存在性校验,只比对宿主已注册的目录、不发任何请求),不会跑到一半才失败,也**不会静默回落到默认模型**。
|
|
148
|
+
- 面板下方始终显示**实际生效的是哪条**(配置指定 / 跟随默认),配置里那条路线万一从目录里消失了,下拉框也会把它显示出来而不是悄悄跳回默认。
|
|
149
|
+
- 拿不到模型目录时(宿主差异),退化成手填 `provider` 与 `model`。
|
|
150
|
+
|
|
151
|
+
### 回滚点
|
|
152
|
+
|
|
153
|
+
**只要这次是「直接改写」,开工前就先建一个回滚点**(整个记忆目录顶层 `.md` 全量快照,每条带 sha256),跑完之后你能在设置页看到它、也能一键退回去。
|
|
154
|
+
|
|
155
|
+
- 回滚点与这次运行**绑定**:报告里写着 runId,回滚点目录同名,两边对得上。
|
|
156
|
+
- **回滚本身也能退**:动手之前会先把「现在」再存一份**保护快照**(它不参与普通快照的轮转淘汰)。
|
|
157
|
+
- **范围可选**:只恢复这次运行动过的文件,或整目录回到该时点。
|
|
158
|
+
- **全程不删文件**:回滚中「不该存在」的文件一律移进 `archive/`,人工可捞回。有同名冲突就跳过并计数,绝不覆盖。
|
|
159
|
+
- 每次回滚都留痕:报告目录里写一份回滚报告,`.sage-mem/autodream/rollbacks.json` 里追加一条记录。
|
|
160
|
+
|
|
161
|
+
### 整理声明:改了什么、为什么
|
|
162
|
+
|
|
163
|
+
每一次整理都留下一份**声明**,两种形态:人读的 `memory/autodream/<runId>.md`(报告里内嵌),机读的 `.sage-mem/autodream/runs/<runId>/manifest.json`。
|
|
164
|
+
|
|
165
|
+
- 逐条记录:**文件 / 操作(新建·改写·归档)/ 缘由 / 字节变化**,外加运行前后的结构审计对比。
|
|
166
|
+
- **`reason` 应当填写。** `write_memory` 不带 `reason` **不会被拒绝**——改动照样生效,但整理声明里会把它标成「未自述」并附上宿主能追溯到的信息(第几轮 / 什么操作 / 字节变化)。**`archive_memory` 的 `reason` 仍必填**,缺了直接拒绝;被拒的动作单列一节「未能落地的改动」,不会静默消失。(不硬拒 `write_memory` 是有意的:为了一句解释而丢掉一次本来正确的修正,代价更大。)
|
|
167
|
+
- 面板的「整理记录」区列出每一趟(时间 / 模式 / 改了几条 / 是否已被回滚),点开看声明全文。
|
|
168
|
+
|
|
169
|
+
### 三道安全网
|
|
170
|
+
|
|
171
|
+
1. **安全边界在工具集上,不在提示词里**——自动做梦时宿主只把 `list_memory` / `read_memory` / `audit_memory` 交给模型,改写模式才多给 `write_memory` / `archive_memory`;输入源选「记忆 + 会话记录」时另加 `search_sessions`。而且**没有「删除」这个能力**:归档是把文件移进 `archive/`,可以人工捞回
|
|
172
|
+
2. **改写前自动建回滚点**(只快照顶层 `.md`,不含 `archive/`),落在 `<memory 目录的上一层>/.sage-mem/autodream/snapshots/<runId>/`,保留最近 N 份。理由是记忆目录**不在任何版本控制下**、删除没有回收站,「可回滚」得自己造
|
|
173
|
+
3. **跑完自动审计**:七查(索引悬空 / 漏索引 / `type` 与文件名前缀不一致 / CRLF / 双链断链 / frontmatter 里被 YAML 当注释吞掉的「空格 + #」/ 无 frontmatter),外加「读不动」单列一类,结果与前后对比写进报告。它**只报不改**
|
|
174
|
+
|
|
175
|
+
最多轮数、回滚点保留份数在「高级设置」里;**回滚的默认范围在「回滚点」区里选**。
|
|
176
|
+
|
|
177
|
+
报告落在 `memory/autodream/<runId>.md`——子目录,不会被扫成记忆条目。
|
|
178
|
+
|
|
179
|
+
> **关于自动触发**:整理沿用插件自己的定时器(`ctx.timer`,默认 30 分钟查一次门控),**没有**接进设置页那个「自动化任务」面板。原因不是偷懒:那个面板的服务到期只做一件事——往一个已存在的会话投一条 user 消息让那个 agent 正常跑一轮;它没有回调、没有条件门、也要求绑定一个会话 id。而自动做梦刻意**不走会话**(工具集由插件给、步数有上限、不污染会话记录),两者的触发模型对不上。硬接的代价远大于收益,所以不做。
|
|
180
|
+
|
|
181
|
+
### 改名说明(0.7.0)
|
|
182
|
+
|
|
183
|
+
本功能原名「做梦」(标识 `dream`),0.7.0 起叫 **自动做梦(autodream)**。旧数据不会被丢:老的配置 `.sage-mem/dream.json` 会被读出来并迁移到 `.sage-mem/autodream.json`(**旧文件保留不动**),老报告 `memory/dream/` 仍在面板里列出并标「旧版」,老快照 `.sage-mem/snapshots/` 也仍可回滚。
|
|
184
|
+
|
|
185
|
+
## 记忆文件格式
|
|
186
|
+
|
|
187
|
+
````markdown
|
|
188
|
+
---
|
|
189
|
+
name: 可选的短名
|
|
190
|
+
description: 一句话说清这条记忆是什么(检索靠它,务必写准)
|
|
191
|
+
metadata:
|
|
192
|
+
type: user # user / feedback / project / reference
|
|
193
|
+
tags: [项目, 待办] # 可选,供列表页筛选
|
|
194
|
+
aliases: [待办, todo] # 可选:换一种说法也能被检索到
|
|
195
|
+
baseline: true # 可选:新会话第一步无条件注入(上限 8 条)
|
|
196
|
+
baselinePriority: 10 # 可选:多条 baseline 之间谁先注入(越大越前)
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
记忆正文。
|
|
200
|
+
````
|
|
201
|
+
|
|
202
|
+
四类记忆:
|
|
203
|
+
|
|
204
|
+
| 类型 | 存什么 |
|
|
205
|
+
|---|---|
|
|
206
|
+
| `user` | 用户是谁 |
|
|
207
|
+
| `feedback` | 工作方式指导(建议带 `**Why:**` 与 `**How to apply:**` 两行,方便判断边界) |
|
|
208
|
+
| `project` | 进行中的工作与状态 |
|
|
209
|
+
| `reference` | 外部信息在哪找的指针 |
|
|
210
|
+
|
|
211
|
+
## 架构
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
DSH(Cordis 插件)
|
|
215
|
+
└─ sage-mem 插件(按问题检索 + 注入)← 本仓库
|
|
216
|
+
│ Node fs 直读
|
|
217
|
+
▼
|
|
218
|
+
memory/ 目录(markdown 文件,4 类)
|
|
219
|
+
├── user_*.md
|
|
220
|
+
├── feedback_*.md
|
|
221
|
+
├── project_*.md
|
|
222
|
+
├── reference_*.md
|
|
223
|
+
└── MEMORY.md ← 索引
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
没有 worker、没有 SQLite、没有 HTTP 端口、没有常驻进程。
|
|
227
|
+
|
|
228
|
+
## 权限与数据
|
|
229
|
+
|
|
230
|
+
sage-mem 只做三件事,全都在你本机:
|
|
231
|
+
|
|
232
|
+
| 它做什么 | 具体范围 |
|
|
233
|
+
|---|---|
|
|
234
|
+
| **读记忆** | 只读 `SAGE_MEM_DIR`(默认 `~/.sage-mem/memory`)下的顶层 `*.md`,单文件上限 512 KB |
|
|
235
|
+
| **写记忆** | 经 agent 的文件工具或设置页写同一个目录;`MEMORY.md`、`session-log.md` 等保留名受保护,设置页碰不到 |
|
|
236
|
+
| **注入** | 把选中的记忆作为上下文交给模型(最多 10 条相关 + 8 条 `baseline`) |
|
|
237
|
+
|
|
238
|
+
**它不做什么**:不联网、不开端口、不起常驻进程、不需要任何 API key;默认只读写记忆目录与它上一层的 `.sage-mem/` 状态目录(配置、回滚点、报告)。**例外**:输入源选「记忆 + 会话记录」时,它会额外**读** `$DSH_HOME/sessions` 下的会话记录做定向搜索——那会解压你的对话原文(含私密内容)并送进模型上下文,所以默认不开,见「自动做梦」一节;
|
|
239
|
+
不做事件全捕获(存不存由 agent 按规则判断,不是"你说了什么都记")。
|
|
240
|
+
|
|
241
|
+
记忆就是那个目录里的文件,随时可以打开确认——这也是选文件式的原因。
|
|
242
|
+
|
|
243
|
+
(唯一会调用模型的功能是「自动做梦」,默认关闭。它的模型默认跟随当前会话默认模型,也可以在设置页单独指定一条——指定了就只认它,不会静默回落。)
|
|
244
|
+
|
|
245
|
+
## DSH 兼容性
|
|
246
|
+
|
|
247
|
+
sage-mem 是纯 DSH 插件,用 `package.json` 的 **`engines.dsh`** 声明宿主要求:`>=0.1.2-rc.1` —— **单边开区间、不设上界**,所以任何未来的 DSH 版本都不会被这道声明挡住。逐版本核对记录如下:
|
|
248
|
+
|
|
249
|
+
| DSH 版本 | 状态 |
|
|
250
|
+
| --- | --- |
|
|
251
|
+
| 0.1.2-rc.1 | compatible |
|
|
252
|
+
| 0.1.3-alpha.1 | compatible |
|
|
253
|
+
| 0.1.3-alpha.2 | compatible |
|
|
254
|
+
| 0.1.5-rc.1 | compatible |
|
|
255
|
+
| 0.1.6-alpha.1 | compatible |
|
|
256
|
+
| 0.1.6-alpha.2 | compatible |
|
|
257
|
+
| 0.1.7-rc.1 | compatible |
|
|
258
|
+
| 0.1.7-rc.2 | compatible |
|
|
259
|
+
| 0.2.0-rc.1 | compatible |
|
|
260
|
+
| 0.2.0-rc.2 | compatible |
|
|
261
|
+
|
|
262
|
+
两点值得说明:
|
|
263
|
+
|
|
264
|
+
- **同一份构建同时覆盖 `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` 之间导出符号零增删)
|
|
265
|
+
- **0.5.3 起带一层防御留痕。** `deriveMessages()`(仍是同步)、`system-prompt/assemble` 事件、`context.agent.session` 这条链在升级中都没变;但如果哪天 DSH 把它们改成异步或改了名,插件会在**日志里报警**,而不是像以前那样静默地不再注入记忆
|
|
266
|
+
|
|
267
|
+
## 卸载
|
|
268
|
+
|
|
269
|
+
在 profile 的 `package.json` 里删掉 `sage-mem` 依赖,并从 `dsh.profile.bundles` 移除 `"sage-mem"`;`pnpm install` 后重启 DSH 即可。**记忆 Markdown 文件留在原目录,不受影响。**
|
|
270
|
+
|
|
271
|
+
## 相关项目
|
|
272
|
+
|
|
273
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — DSH 本体,一切皆插件
|
|
274
|
+
- [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) — DSH 插件生态清单
|
|
275
|
+
|
|
276
|
+
## 旧版
|
|
277
|
+
|
|
278
|
+
本仓库早期是 SQLite + worker 架构,已归档到 [`sqlite-worker`](https://github.com/gezi-wen/sage-mem/tree/sqlite-worker) 分支。文件式是继任实现。
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
Apache-2.0
|