dsh-memory-palace 1.7.2-alpha.3 → 1.8.0-alpha.1
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 +35 -101
- package/lib/api.mjs +3 -5
- package/lib/client.js +41 -86
- package/lib/common/prompts.mjs +6 -8
- package/lib/common/records.mjs +7 -68
- package/lib/common/sections.mjs +35 -11
- package/lib/common/text.mjs +8 -3
- package/lib/distill.mjs +9 -20
- package/lib/hybrid/index.mjs +3 -4
- package/lib/hybrid/subagent.mjs +2 -2
- package/lib/hybrid/tools.mjs +32 -27
- package/lib/index.js +97 -149
- package/lib/projection.mjs +9 -7
- package/lib/tools.mjs +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
把 WorkBuddy 的文件式记忆系统移植进 [DeepSeek Harness](https://www.deepseek.com/harness/) —— 为 Harness 提供**跨会话持久化、人类可直接编辑的 Markdown 记忆**。
|
|
4
4
|
|
|
5
|
-
[](./LICENSE) [](https://awesome-dsh-plugin.com) [](https://www.npmjs.com/package/dsh-memory-palace) [](./LICENSE) [](https://awesome-dsh-plugin.com) [](https://www.npmjs.com/package/dsh-memory-palace) [](https://github.com/deepseek-ai/deepseek-harness) [](#安装)
|
|
6
6
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
@@ -14,10 +14,8 @@
|
|
|
14
14
|
- **设置页集成**:全部配置均可在 DSH 设置面板中图形化调整(按板块折叠),无需改配置文件。
|
|
15
15
|
- **自定义指令**:不适合写进记忆的特殊指令可在设置页配置,插件经系统提示词注入。
|
|
16
16
|
- **记忆注入**:长期记忆与今日日志以「会话起始快照」常驻上下文、按文件身份各只注入一次 —— 既保证每个步骤都可见,又不破坏前缀缓存、不堆积冗余快照。
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- **智能模式**:由模型自动提炼每轮新增内容,摘要进日志、长期事实进记忆。*即将移除*
|
|
20
|
-
- **混合模式(🔥推荐)**:子代理每轮自动整理日志并去重,长期记忆由主 AI 主动维护,兼顾自动化与可控性。
|
|
17
|
+
- **记忆写入(v1.8.0 起唯一模式)**:**记忆子代理**每轮自动整理今日日志并去重(章节化、标删),**长期记忆 `MEMORY.md` 由主 AI 主动维护**,兼顾自动化与可控性。
|
|
18
|
+
- v1.8.0 破坏性变更:原「主动记忆(插件模式)」与「智能模式」已整体移除。二者的能力已被覆盖——主动落档由分工指令引导主 AI 承担,逐轮摘要由记忆子代理写进日志承担。
|
|
21
19
|
- **标准插件包**:经官方插件机制一键安装,无需改动 harness。
|
|
22
20
|
|
|
23
21
|
## 记忆文件布局
|
|
@@ -42,21 +40,24 @@
|
|
|
42
40
|
**读取(每轮对话)**——两条通道并行:
|
|
43
41
|
|
|
44
42
|
```
|
|
45
|
-
①
|
|
43
|
+
① 系统提示词(恒定):记忆分工指令 / 自定义指令等固定内容,前缀缓存友好
|
|
46
44
|
② 对话历史投影(易变):用户级 + 项目级长期记忆、今日日志——按文件身份各注入一次,压缩后自动重注最新版
|
|
47
45
|
```
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
> 投影**逐文件独立截断**:用户级 `MEMORY.md` 受「用户级预算」约束,项目级 `MEMORY.md` 与今日日志各受「工作区预算」约束、互不挤占 —— 预算说的是**每个文件**的上限,不是所有文件合计的总量。被截掉的部分不丢,随时可用 `memory_read` 读取。
|
|
48
|
+
|
|
49
|
+
**写入(每轮结束)**——交给记忆子代理异步处理:
|
|
50
50
|
|
|
51
51
|
```
|
|
52
|
-
本轮结束 ──►
|
|
53
|
-
│
|
|
54
|
-
├─►
|
|
55
|
-
|
|
56
|
-
└─► 超期日志并入长期记忆后删除
|
|
52
|
+
本轮结束 ──► 前置闸门:enabled / 计划模式 / 静默预设 / 有可用记忆目录 → 否则跳过
|
|
53
|
+
│
|
|
54
|
+
├─► 记忆子代理把本轮实质内容写成章节化条目 → 今日日志(重复/过时条目标删)
|
|
55
|
+
└─► 长期记忆由主 AI 按分工指令主动维护(memory_write / memory_update_section)
|
|
57
56
|
```
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
日志文件头统一为日期标题,写入时自动补齐(历史文件不回填)。日志由子代理维护、**永不过期不删**(作为可追溯的证据层)。
|
|
59
|
+
|
|
60
|
+
> 写入没有独立的开关:**插件装上并启用即视为记忆写入启用**。停写只有两条路——profile config 里设 `enabled: false`,或命中静默预设(`silentPresets`)。
|
|
60
61
|
|
|
61
62
|
**工具**——AI 在对话中按需调用:
|
|
62
63
|
|
|
@@ -66,19 +67,19 @@
|
|
|
66
67
|
| `memory_note_user` | 用户级 | 把跨项目偏好写入 `~/.deepseek-harness/MEMORY.md`(去重) |
|
|
67
68
|
| `memory_read` | 按需 | 读取记忆。`scope` 默认 `memory`(用户级 + 项目级);可选 `project`(仅项目级,与 `memory_write` 的写侧 scope 同名)/ `today` / `yesterday` / `daily`(近三天日志)/ `all`(长期记忆 + 日志) |
|
|
68
69
|
| `memory_delete` | 用户级/项目级/每日级 | 按内容删除记忆条目(两阶段确认:先预览匹配位置与内容,用户确认后再删;删除动作经 harness 原生确认弹窗硬闸门,真人点允许才真正执行) |
|
|
69
|
-
| `memory_write
|
|
70
|
-
| `memory_update_section
|
|
71
|
-
| `memory_reorganize
|
|
70
|
+
| `memory_write` | 项目级/用户级 | 章节化写入:章节存在则末尾追加,不存在则新建章节(章节化格式规范) |
|
|
71
|
+
| `memory_update_section` | 项目级/用户级 | 整章节精确替换/单条标记删除:oldText 归一化精确匹配防 stale,失败拒绝并回显实际内容 |
|
|
72
|
+
| `memory_reorganize` | 仅项目级 | 全量重整 MEMORY.md:双门禁(超出注入预算 且 距上次重整 ≥ 冷却天数)机器校验,原子替换 + 时间戳注释,用户确认弹窗 |
|
|
72
73
|
|
|
73
74
|
## 安装
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
### CLI 版(`web` profile)
|
|
76
77
|
|
|
77
78
|
方式一:直接通过 GitHub 安装(推荐,`lib/` 构建产物已随仓库分发,装即用)
|
|
78
79
|
|
|
79
80
|
```bash
|
|
80
81
|
dsh plugin --profile web add github:lovezi0/dsh-memory-palace
|
|
81
|
-
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.7.2
|
|
82
|
+
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.7.2
|
|
82
83
|
```
|
|
83
84
|
|
|
84
85
|
方式二:clone 后本地安装(开发 / 修改源码场景)
|
|
@@ -101,103 +102,36 @@ dsh plugin --profile web add dsh-memory-palace
|
|
|
101
102
|
npm install dsh-memory-palace --registry=https://registry.npmmirror.com/
|
|
102
103
|
dsh plugin --profile web add dsh-memory-palace
|
|
103
104
|
```
|
|
104
|
-
|
|
105
|
-
卸载:
|
|
105
|
+
### CLI 版卸载
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
108
|
dsh plugin --profile web remove dsh-memory-palace
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
### Desktop 版
|
|
112
|
+
- github: `github:lovezi0/dsh-memory-palace`
|
|
113
|
+
- npm: `dsh-memory-palace`
|
|
114
|
+
|
|
111
115
|
## 配置
|
|
112
116
|
*面板路径为 DSH 设置 →「记忆」*
|
|
113
|
-
所有配置项(核心 / 自定义指令 /
|
|
117
|
+
所有配置项(核心 / 自定义指令 / 记忆写入 / 存储路径与预算 / 开发 五张卡片的字段、默认值与说明)已整理至 [CONFIG.md](./CONFIG.md)
|
|
114
118
|
|
|
115
119
|
## 开发
|
|
116
120
|
|
|
117
121
|
架构 / 构建 / 技术要点 / 蒸馏失败重试 见 [DEVELOPMENT.md](./DEVELOPMENT.md)。
|
|
118
|
-
|
|
122
|
+
提示词与蒸馏(分工指令 / 会话蒸馏 / 项目蒸馏) 见 [PROMPTS.md](./PROMPTS.md)。
|
|
119
123
|
|
|
120
124
|
## 版本历史
|
|
121
125
|
|
|
122
|
-
- **1.
|
|
123
|
-
- **1.
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
- 💪dsh Agent 预设[极简模式]时禁用记忆注入、记忆生成、记忆工具
|
|
132
|
-
- **1.7.1**
|
|
133
|
-
- 💪移除日志重注机制优化缓存命中降低堆积冗余
|
|
134
|
-
- 💪记忆设置UI优化
|
|
135
|
-
- 🔥增加自定义指令 prompt 配置与注入
|
|
136
|
-
- 💪memory_read 增加 scope 参数
|
|
137
|
-
- **1.7.0**
|
|
138
|
-
- 🔥新增独立通道注入记忆文件
|
|
139
|
-
- 🐛修复存在多种记忆路径时读取冲突的问题
|
|
140
|
-
- 💪优化记忆子 agent 投影消息节省 token
|
|
141
|
-
- 💪优化 SUBAGENT_SYSTEM 记忆输出格式
|
|
142
|
-
- **1.6.3**
|
|
143
|
-
- npm publish
|
|
144
|
-
- **1.6.3.alpha.4**
|
|
145
|
-
- 🐛修复三种记忆模式配置互串的问题
|
|
146
|
-
- 🐛修复记忆子agent工具幻觉问题
|
|
147
|
-
- **1.6.2**
|
|
148
|
-
- **1.6.2.alpha.4**
|
|
149
|
-
- 🔥适配deepseek harness 0.1.2-alpha.4
|
|
150
|
-
- **1.6.2.alpha.2**
|
|
151
|
-
- 原1.6.0发布
|
|
152
|
-
- **1.6.1**
|
|
153
|
-
- 原1.6.0.alpha.1发布
|
|
154
|
-
- **1.6.0**
|
|
155
|
-
- 🔥适配deepseek harness 0.1.2-alpha.2
|
|
156
|
-
- **1.6.0.alpha.1** *未发布npm*
|
|
157
|
-
- 🔥新增混合模式(hybrid) *仍默认插件模式,建议切换至混合模式*
|
|
158
|
-
- 🔥新增记忆子agent处理轮次会话日志
|
|
159
|
-
- 💪优化记忆文件结构做到真正人类可读
|
|
160
|
-
- 💪优化调试模式参数保存
|
|
161
|
-
- **1.4.2.alpha.1** *未发布npm*
|
|
162
|
-
- 💪记忆注入:仅首次注入 + compaction 重注
|
|
163
|
-
- 💪优化手动项目蒸馏prompt
|
|
164
|
-
- 💪[smart] 标签全移除
|
|
165
|
-
- 🐛修复记忆文件LIFO/FIFO 错配
|
|
166
|
-
- **1.4.1**
|
|
167
|
-
- 🐛修复输出预算使用错位的问题
|
|
168
|
-
- 🐛增加调试模式日志级别 *默认info 仅输出元数据日志,debug 输出完整LLM text*
|
|
169
|
-
- **1.4.0**
|
|
170
|
-
- 🔥智能模式增加最大输出Token限制
|
|
171
|
-
- 🔥智能模式增加失败重试机制
|
|
172
|
-
- 🔥智能模式会增加回馈存量记忆
|
|
173
|
-
- 🐛修复自动记录部分设置位置错误问题
|
|
174
|
-
- **1.3.0**
|
|
175
|
-
- 🔥新增计划模式禁止写入记忆
|
|
176
|
-
- 💪设置-记忆控件样式优化 *使用dsh原生样式*
|
|
177
|
-
- 💪清理重复patch信息
|
|
178
|
-
- 🔥增加调试模式 *默认关闭,仅用于智能模式蒸馏失败输出调试信息*
|
|
179
|
-
- **1.2.3**
|
|
180
|
-
- **1.2.2**
|
|
181
|
-
- 🐛修复智能模式自定义摘要模型不生效的问题
|
|
182
|
-
- **1.2.1**
|
|
183
|
-
- 💪发布npm
|
|
184
|
-
- **1.2.0**
|
|
185
|
-
- 🔥会话标题栏【记忆】按钮
|
|
186
|
-
- 🔥手动蒸馏会话与项目记忆
|
|
187
|
-
- 🐛修复记忆预算注入无效
|
|
188
|
-
- 💪项目混合式模块化重构
|
|
189
|
-
- **1.1.4**
|
|
190
|
-
- 🔥智能模式摘要上线
|
|
191
|
-
- **1.1.2**
|
|
192
|
-
- 🐛修复记忆设置保存不生效的问题
|
|
193
|
-
- **1.1.1**
|
|
194
|
-
- 💪每日日志格式简化
|
|
195
|
-
- **1.1.0**
|
|
196
|
-
- 🔥新增「智能模式/插件模式」切换功能
|
|
197
|
-
- **1.0.0**
|
|
198
|
-
- 🔥新增防闲聊闸门
|
|
199
|
-
- 🔥新增记忆公民指令
|
|
200
|
-
- 🔥新增删除记忆工具
|
|
126
|
+
- **1.8.0**
|
|
127
|
+
- **1.8.0-alpha.1**
|
|
128
|
+
- 💥移除插件模式与智能模式,记忆写入统一为混合模式
|
|
129
|
+
- 💥配置项 memoryMode / autoCaptureErrors / dailyLogRetentionDays 删除(旧值静默失效)
|
|
130
|
+
- 💥移除记忆写入总开关
|
|
131
|
+
- 🐛memory文件格式错误时读取漂移的问题
|
|
132
|
+
- 💪适配deepseek harness 0.1.7-rc.2
|
|
133
|
+
- 💪适配deepseek harness desktop
|
|
134
|
+
- **v1.7.2-legacy** — dsh-memory-palace 从 v1.0.0 的基础记忆读写(防闲聊闸门、公民指令、删除工具)起步,逐步演进到 v1.7.2 的「混合模式 + 独立通道注入 + 自定义指令 + 记忆子 agent 蒸馏」,全程主线是不断增强记忆生成/注入方式,同时持续修复模式互串、工具串台、缓存堆积等稳定性缺陷。历史,见 [CHANGELOG.md](./CHANGELOG.md)
|
|
201
135
|
- **outdated(0.x)** — 双层 Markdown 记忆读写 / 设置页集成等 0.x 历史,见 [CHANGELOG.md](./CHANGELOG.md)
|
|
202
136
|
|
|
203
137
|
## 参考与致谢
|
package/lib/api.mjs
CHANGED
|
@@ -113,9 +113,9 @@ export function applyDebugLogLinkage(section) {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
/**
|
|
116
|
-
* @param {{ ctx: object, paths: object, distill: object,
|
|
116
|
+
* @param {{ ctx: object, paths: object, distill: object, getSettingsFace: () => object | null }} deps
|
|
117
117
|
*/
|
|
118
|
-
export function registerApi({ ctx, paths, distill,
|
|
118
|
+
export function registerApi({ ctx, paths, distill, getSettingsFace }) {
|
|
119
119
|
ctx.effect(
|
|
120
120
|
() =>
|
|
121
121
|
ctx.webServer.register({
|
|
@@ -183,10 +183,8 @@ export function registerApi({ ctx, paths, distill, state, getSettingsFace }) {
|
|
|
183
183
|
if (!dirs.length) {
|
|
184
184
|
throw Object.assign(new Error("no memory dirs for this workspace"), { code: "bad-request", status: 400 });
|
|
185
185
|
}
|
|
186
|
-
// 整段会话全量蒸馏(fromSeq=0
|
|
187
|
-
// allowDelete:true —— 手动按钮开放 delete 操作(自动智能模式传 false,见 summarizeTurn)。
|
|
186
|
+
// 整段会话全量蒸馏(fromSeq=0);allowDelete:true —— 手动按钮开放 delete 操作。
|
|
188
187
|
const r = await distill.distillSessionCore(session, dirs, 0, { allowDelete: true });
|
|
189
|
-
if (r.ok && session.id === state.summarySessionId) state.lastSummarizedSeq = session.seq;
|
|
190
188
|
apiWriteOk(res, r);
|
|
191
189
|
return;
|
|
192
190
|
}
|
package/lib/client.js
CHANGED
|
@@ -19,10 +19,10 @@ window.__ModuleLoader__.load({
|
|
|
19
19
|
coreDesc: "buddy 记忆桥接与项目记忆目录",
|
|
20
20
|
custom: "自定义指令",
|
|
21
21
|
customDesc: "不适合写进用户记忆的特殊指令,经系统提示词注入",
|
|
22
|
-
smartSummary: "
|
|
23
|
-
smartSummaryDesc: "
|
|
22
|
+
smartSummary: "记忆写入",
|
|
23
|
+
smartSummaryDesc: "记忆子代理与模型参数",
|
|
24
24
|
storage: "存储路径与预算",
|
|
25
|
-
storageDesc: "
|
|
25
|
+
storageDesc: "记忆文件路径与注入预算",
|
|
26
26
|
bridgeLabel: "桥接 buddy 项目记忆",
|
|
27
27
|
bridgeHint: "项目已存在 .workbuddy / .codebuddy 记忆目录时直接读写,不再建 .deepseek-harness/memory/",
|
|
28
28
|
dirsLabel: "buddy 记忆目录(逗号分隔,按序优先)",
|
|
@@ -33,27 +33,16 @@ window.__ModuleLoader__.load({
|
|
|
33
33
|
userPathHint: "跨项目个人偏好记忆,默认 ~/.deepseek-harness/MEMORY.md",
|
|
34
34
|
wsDirLabel: "工作区记忆目录(回退)",
|
|
35
35
|
wsDirHint: "无 buddy 目录时回退到该目录,默认 .deepseek-harness/memory",
|
|
36
|
-
retentionLabel: "日志保留天数",
|
|
37
|
-
retentionHint: "超过该天数的每日日志会迁移进 MEMORY.md 后删除",
|
|
38
|
-
retentionHintHybrid: "hybrid 模式下此设置不生效:日志由记忆子代理维护、永不过期不删(证据层),保持完整。",
|
|
39
36
|
userBudgetLabel: "用户级预算(字符)",
|
|
40
|
-
userBudgetHint: "用户级 MEMORY.md
|
|
37
|
+
userBudgetHint: "用户级 MEMORY.md 经 E 投影注入时的长度上限。这是「每个文件各自」的上限,不是所有记忆合计的总量上限。",
|
|
41
38
|
wsBudgetLabel: "工作区预算(字符)",
|
|
42
|
-
wsBudgetHint: "
|
|
43
|
-
summarizeLabel: "轮次结束自动记录",
|
|
44
|
-
summarizeHint: "三种记忆模式的共用总闸门:关闭后三种模式都不写记忆。插件模式下它作为「agent 主动记忆」主路径失效时的安全网,只留原始文本、不做总结;智能模式走 LLM 智能摘要(总结 + 提炼);混合模式下整个记忆子代理停摆(不做兜底写入)。",
|
|
45
|
-
autoCaptureErrorsLabel: "对话出错时自动记录到记忆",
|
|
46
|
-
autoCaptureErrorsHint: "对话中(含代码运行报错、工具执行失败)出错时,自动把「错误现象」写入对应 MEMORY.md(用户级/项目级);「根因/方案」由 agent 按记忆公民指令主动记。默认开,关闭无需重启。",
|
|
47
|
-
memoryModeLabel: "记忆模式",
|
|
48
|
-
memoryModeHintPlugin: "插件模式:记忆公民指令 + 轮次轻量 + 错误捕获。切换需重启 dsh 生效。",
|
|
49
|
-
memoryModeHintSmart: "智能模式:LLM 智能会话摘要(summary→每日日志 + durable→MEMORY.md)。切换需重启 dsh 生效。",
|
|
50
|
-
memoryModeHintHybrid: "混合模式(默认):记忆子代理自动维护今日日志(章节化、标删去重),agent 主动维护 MEMORY.md(章节化写入、整章节替换、门禁内全量重整)。切换需重启 dsh 生效。",
|
|
39
|
+
wsBudgetHint: "工作区侧注入上限,对每个文件独立生效:项目级 MEMORY.md 与今日工作日志各自按此值截断(互不挤占),同时用作项目记忆的重整门禁阈值与 memory_read 读日志的每块上限。多目录(dsh + 桥接的 buddy 目录)并存时每个目录各注一份。",
|
|
51
40
|
reorgCooldownLabel: "重整冷却(天)",
|
|
52
|
-
reorgCooldownHint: "项目级 MEMORY.md
|
|
41
|
+
reorgCooldownHint: "项目级 MEMORY.md 全量重整的冷却天数(距上次重整);与「超出注入预算」(即文件大于「工作区预算」)双条件同时满足才允许 memory_reorganize。默认 7 天。",
|
|
53
42
|
subagentLogBudgetLabel: "子代理日志回喂预算(字符)",
|
|
54
43
|
subagentLogBudgetHint: "记忆子代理回喂今日工作日志的字符上限;超出时仅回喂章节目录,子代理按需读取章节。默认 20000。",
|
|
55
44
|
summaryModelLabel: "模型",
|
|
56
|
-
summaryModelHint: "
|
|
45
|
+
summaryModelHint: "记忆插件当前使用的模型(手动蒸馏 / 记忆子代理共用)。留空=复用当前会话的 provider/model;也可固定廉价小模型省 token。",
|
|
57
46
|
expand: "展开",
|
|
58
47
|
collapse: "收起",
|
|
59
48
|
save: "保存",
|
|
@@ -84,13 +73,13 @@ window.__ModuleLoader__.load({
|
|
|
84
73
|
dev: "开发",
|
|
85
74
|
devDesc: "蒸馏调试日志与超时",
|
|
86
75
|
distillTimeoutLabel: "蒸馏超时(秒)",
|
|
87
|
-
distillTimeoutHint: "单次蒸馏 LLM
|
|
88
|
-
summaryMaxTokensLabel: "
|
|
89
|
-
summaryMaxTokensHint: "
|
|
76
|
+
distillTimeoutHint: "单次蒸馏 LLM 调用的超时上限(秒);超时视为失败并降级。覆盖手动蒸馏与记忆子代理,默认 60 秒。",
|
|
77
|
+
summaryMaxTokensLabel: "会话蒸馏最大 Token",
|
|
78
|
+
summaryMaxTokensHint: "「蒸馏会话」最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 2000,可调大以容纳更多 durable 事实。",
|
|
90
79
|
projectMaxTokensLabel: "项目蒸馏最大 Token",
|
|
91
80
|
projectMaxTokensHint: "最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 8000。",
|
|
92
81
|
feedbackEnabledLabel: "回喂存量记忆",
|
|
93
|
-
feedbackEnabledHint: "每次蒸馏时附带项目级 + 用户级记忆作为参考,使其能基于既有记忆做增量维护(delete
|
|
82
|
+
feedbackEnabledHint: "每次蒸馏时附带项目级 + 用户级记忆作为参考,使其能基于既有记忆做增量维护(delete 仅手动蒸馏开放)。仅影响手动蒸馏;自动路径走记忆子代理、自带日志回喂。默认关。",
|
|
94
83
|
customLabel: "自定义指令内容",
|
|
95
84
|
customHint: "非空时注入系统提示词,位置在记忆插件与分工说明之后。对全部会话生效;留空则不注入。",
|
|
96
85
|
customPlaceholder: "例如:回答用中文;代码注释用英文;提交信息用祈使句…"
|
|
@@ -104,10 +93,10 @@ window.__ModuleLoader__.load({
|
|
|
104
93
|
coreDesc: "Buddy memory bridging and workspace memory dirs",
|
|
105
94
|
custom: "Custom instructions",
|
|
106
95
|
customDesc: "Special instructions that do not belong in user memory, injected via the system prompt",
|
|
107
|
-
smartSummary: "
|
|
108
|
-
smartSummaryDesc: "Memory
|
|
96
|
+
smartSummary: "Memory writes",
|
|
97
|
+
smartSummaryDesc: "Memory sub-agent and model parameters",
|
|
109
98
|
storage: "Storage & budgets",
|
|
110
|
-
storageDesc: "Memory file paths
|
|
99
|
+
storageDesc: "Memory file paths and injection budgets",
|
|
111
100
|
bridgeLabel: "Bridge buddy project memory",
|
|
112
101
|
bridgeHint: "Read/write directly into existing .workbuddy / .codebuddy memory dirs instead of creating .deepseek-harness/memory/",
|
|
113
102
|
dirsLabel: "Buddy memory dirs (comma-separated, first wins)",
|
|
@@ -118,27 +107,16 @@ window.__ModuleLoader__.load({
|
|
|
118
107
|
userPathHint: "Cross-project preferences, default ~/.deepseek-harness/MEMORY.md",
|
|
119
108
|
wsDirLabel: "Workspace memory dir (fallback)",
|
|
120
109
|
wsDirHint: "Used when no buddy dir exists, default .deepseek-harness/memory",
|
|
121
|
-
retentionLabel: "Daily log retention (days)",
|
|
122
|
-
retentionHint: "Older logs are migrated into MEMORY.md then removed",
|
|
123
|
-
retentionHintHybrid: "Not effective in hybrid mode: daily logs are maintained by the memory sub-agent and never expire (kept intact as an evidence layer).",
|
|
124
110
|
userBudgetLabel: "User budget (chars)",
|
|
125
|
-
userBudgetHint: "
|
|
111
|
+
userBudgetHint: "Length cap when the user-level MEMORY.md is injected via the E projection. This caps EACH file independently — it is not a total across all memory files.",
|
|
126
112
|
wsBudgetLabel: "Workspace budget (chars)",
|
|
127
|
-
wsBudgetHint: "
|
|
128
|
-
summarizeLabel: "Auto-record at turn end",
|
|
129
|
-
summarizeHint: "The shared master gate for all three memory modes: when off, none of them writes any memory. In plugin mode it is the safety net when the 'agent proactive memory' main path fails (keeps raw text, no summarization); in smart mode it enables the LLM summarization path (summary + extraction); in hybrid mode the whole memory sub-agent stays idle (no fallback entry either).",
|
|
130
|
-
autoCaptureErrorsLabel: "Auto-record conversation errors",
|
|
131
|
-
autoCaptureErrorsHint: "On in-session errors, auto write the 'error' into the corresponding MEMORY.md (user/project); 'root cause / fix' is recorded proactively by the agent. On by default; off takes effect without restart.",
|
|
132
|
-
memoryModeLabel: "Memory mode",
|
|
133
|
-
memoryModeHintPlugin: "Plugin mode: memory-citizen instructions + turn-end light entries + error capture. Switching requires a dsh restart.",
|
|
134
|
-
memoryModeHintSmart: "Smart mode: LLM conversation summarization (summary -> daily log + durable -> MEMORY.md). Switching requires a dsh restart.",
|
|
135
|
-
memoryModeHintHybrid: "Hybrid mode (default): a memory sub-agent auto-maintains today's daily log (chaptered, dedupe by strikethrough); the agent proactively maintains MEMORY.md (chaptered writes, section replace, gated full reorganize). Switching requires a dsh restart.",
|
|
113
|
+
wsBudgetHint: "Workspace-side injection cap, applied to each file independently: the project MEMORY.md and today's daily log are each clipped by this value (they do not compete). It is also the reorganize gate threshold and the per-block cap for memory_read. When several dirs exist (dsh + bridged buddy dirs), each dir injects its own copy.",
|
|
136
114
|
reorgCooldownLabel: "Reorganize cooldown (days)",
|
|
137
|
-
reorgCooldownHint: "Cooldown days between full reorganizes of the project MEMORY.md; combined with 'over injection budget' both
|
|
115
|
+
reorgCooldownHint: "Cooldown days between full reorganizes of the project MEMORY.md; combined with the 'over injection budget' gate (file larger than the workspace budget) both must pass for memory_reorganize. Default 7.",
|
|
138
116
|
subagentLogBudgetLabel: "Sub-agent log feed budget (chars)",
|
|
139
117
|
subagentLogBudgetHint: "Max chars of today's daily log fed back to the memory sub-agent; beyond this only the chapter TOC is fed and the sub-agent reads sections on demand. Default 20000.",
|
|
140
118
|
summaryModelLabel: "Model",
|
|
141
|
-
summaryModelHint: "The model currently used by the memory plugin (shared by
|
|
119
|
+
summaryModelHint: "The model currently used by the memory plugin (shared by manual distillation and the memory sub-agent). Leave empty to reuse the current session's provider/model, or pin a cheap model (provider/model) to save tokens.",
|
|
142
120
|
expand: "Expand",
|
|
143
121
|
collapse: "Collapse",
|
|
144
122
|
save: "Save",
|
|
@@ -169,21 +147,21 @@ window.__ModuleLoader__.load({
|
|
|
169
147
|
dev: "Developer",
|
|
170
148
|
devDesc: "Distill debug log and timeout",
|
|
171
149
|
distillTimeoutLabel: "Distill timeout (s)",
|
|
172
|
-
distillTimeoutHint: "Timeout (in seconds) for a single distill LLM call; on timeout it fails and degrades. Covers
|
|
173
|
-
summaryMaxTokensLabel: "Session
|
|
174
|
-
summaryMaxTokensHint: "Final output soft budget (prompt constraint, thinking not limited; the actual hard cap is the model's own maxTokens). Default 2000; raise to fit more durable facts.",
|
|
150
|
+
distillTimeoutHint: "Timeout (in seconds) for a single distill LLM call; on timeout it fails and degrades. Covers manual distillation and the memory sub-agent. Default 60s.",
|
|
151
|
+
summaryMaxTokensLabel: "Session distill max tokens",
|
|
152
|
+
summaryMaxTokensHint: "Final output soft budget for 'Distill session' (prompt constraint, thinking not limited; the actual hard cap is the model's own maxTokens). Default 2000; raise to fit more durable facts.",
|
|
175
153
|
projectMaxTokensLabel: "Project distill max tokens",
|
|
176
154
|
projectMaxTokensHint: "Final output soft budget (prompt constraint, thinking not limited; actual hard cap is the model's own maxTokens). Default 8000.",
|
|
177
155
|
feedbackEnabledLabel: "Feed existing memory into distillation",
|
|
178
|
-
feedbackEnabledHint: "Feed the project-level + user-level memory in as reference on every distillation so the LLM can maintain existing memory incrementally (delete is only allowed via manual distillation).
|
|
156
|
+
feedbackEnabledHint: "Feed the project-level + user-level memory in as reference on every distillation so the LLM can maintain existing memory incrementally (delete is only allowed via manual distillation). Manual distillation only; the automatic path runs through the memory sub-agent, which feeds the log itself. Off by default.",
|
|
179
157
|
customLabel: "Custom instruction text",
|
|
180
158
|
customHint: "When non-empty it is injected into the system prompt right after the memory-plugin and memory-roles instructions. Applies to every session; leave empty to inject nothing.",
|
|
181
159
|
customPlaceholder: "e.g. Answer in Chinese; write code comments in English; use imperative commit subjects…"
|
|
182
160
|
};
|
|
183
161
|
|
|
184
162
|
|
|
185
|
-
const FIELD_NUMERIC = new Set(["
|
|
186
|
-
const FIELD_BOOL = new Set(["bridgeBuddyMemory", "
|
|
163
|
+
const FIELD_NUMERIC = new Set(["userBudgetChars", "workspaceBudgetChars", "summaryTimeoutMs", "summaryMaxTokens", "projectMaxTokens", "reorgCooldownDays", "subagentLogBudget"]);
|
|
164
|
+
const FIELD_BOOL = new Set(["bridgeBuddyMemory", "distillDebugLog", "feedbackEnabled"]);
|
|
187
165
|
|
|
188
166
|
function projectDraft(snap) {
|
|
189
167
|
const v = snap && snap.value ? snap.value : {};
|
|
@@ -194,14 +172,10 @@ window.__ModuleLoader__.load({
|
|
|
194
172
|
silentPresets: Array.isArray(v.silentPresets) ? v.silentPresets.join(", ") : "minimal",
|
|
195
173
|
userMemoryPath: v.userMemoryPath || "~/.deepseek-harness/MEMORY.md",
|
|
196
174
|
workspaceMemoryDir: v.workspaceMemoryDir || ".deepseek-harness/memory",
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
workspaceBudgetChars: v.workspaceBudgetChars != null ? String(v.workspaceBudgetChars) : "3000",
|
|
200
|
-
summarize: v.summarize === false ? "false" : "true",
|
|
201
|
-
autoCaptureErrors: v.autoCaptureErrors === false ? "false" : "true",
|
|
175
|
+
userBudgetChars: v.userBudgetChars != null ? String(v.userBudgetChars) : "8000",
|
|
176
|
+
workspaceBudgetChars: v.workspaceBudgetChars != null ? String(v.workspaceBudgetChars) : "6000",
|
|
202
177
|
distillDebugLog: v.distillDebugLog === false ? "false" : "true",
|
|
203
178
|
summaryTimeoutMs: v.summaryTimeoutMs != null ? String(Math.round((Number(v.summaryTimeoutMs) || 0) / 1000)) : "60",
|
|
204
|
-
memoryMode: v.memoryMode || "hybrid",
|
|
205
179
|
summaryModel: v.summaryModel || "",
|
|
206
180
|
summaryMaxTokens: v.summaryMaxTokens != null ? String(v.summaryMaxTokens) : "2000",
|
|
207
181
|
projectMaxTokens: v.projectMaxTokens != null ? String(v.projectMaxTokens) : "8000",
|
|
@@ -692,37 +666,18 @@ window.__ModuleLoader__.load({
|
|
|
692
666
|
}), "customInstructions")
|
|
693
667
|
]),
|
|
694
668
|
card("smartSummary", t("smartSummary"), t("smartSummaryDesc"), [
|
|
695
|
-
//
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
h("
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
style: selectStyle
|
|
708
|
-
}, [
|
|
709
|
-
h("option", { value: "plugin" }, "插件模式"),
|
|
710
|
-
h("option", { value: "smart" }, "智能模式"),
|
|
711
|
-
h("option", { value: "hybrid" }, "混合模式")
|
|
712
|
-
]), "memoryMode"),
|
|
713
|
-
draft.memoryMode === "hybrid"
|
|
714
|
-
? h("div", null, [
|
|
715
|
-
row(t("reorgCooldownLabel"), t("reorgCooldownHint"), h("input", num("reorgCooldownDays")), "reorgCooldownDays"),
|
|
716
|
-
row(t("subagentLogBudgetLabel"), t("subagentLogBudgetHint"), h("input", num("subagentLogBudget")), "subagentLogBudget")
|
|
717
|
-
])
|
|
718
|
-
: draft.memoryMode === "plugin"
|
|
719
|
-
? h("div", null, [
|
|
720
|
-
toggle(t("autoCaptureErrorsLabel"), t("autoCaptureErrorsHint"), "autoCaptureErrors")
|
|
721
|
-
])
|
|
722
|
-
: null,
|
|
723
|
-
// ---- v1.6.3:蒸馏/模型参数提为常显(三模式共用,不受 memoryMode 限制)----
|
|
724
|
-
// summaryModel 同时被智能摘要与 hybrid 记忆子代理读取(subagent resolveModel);
|
|
725
|
-
// summaryMaxTokens/projectMaxTokens/feedbackEnabled 覆盖自动摘要 + 手动蒸馏两条链路。
|
|
669
|
+
// ---- v1.8.0:本卡片内三处删除已落地——① 记忆写入总开关:写入恒定进行,停写只剩
|
|
670
|
+
// profile config 的 enabled=false 与静默预设(silentPresets,见「核心」卡片);
|
|
671
|
+
// ② 记忆模式下拉与模式条件块(随原 plugin / smart 两模式删除);
|
|
672
|
+
// ③ 错误自动记录、日志保留天数两项配置。
|
|
673
|
+
// 记忆子代理参数提为常显(先前包在 hybrid 条件块里)。
|
|
674
|
+
// 注意:本注释刻意不写已删配置的 key 字面量——client-smoke 有源码级负向断言守着。
|
|
675
|
+
h("div", null, [
|
|
676
|
+
row(t("reorgCooldownLabel"), t("reorgCooldownHint"), h("input", num("reorgCooldownDays")), "reorgCooldownDays"),
|
|
677
|
+
row(t("subagentLogBudgetLabel"), t("subagentLogBudgetHint"), h("input", num("subagentLogBudget")), "subagentLogBudget")
|
|
678
|
+
]),
|
|
679
|
+
// ---- v1.6.3:蒸馏/模型参数常显(v1.8.0 起 summaryModel 只被手动蒸馏与记忆子代理读取)----
|
|
680
|
+
// summaryMaxTokens/projectMaxTokens/feedbackEnabled 覆盖「蒸馏会话」+「蒸馏项目记忆」两条手动链路。
|
|
726
681
|
h("div", null, [
|
|
727
682
|
row(t("summaryModelLabel"), t("summaryModelHint"),
|
|
728
683
|
h("select", {
|
|
@@ -744,7 +699,7 @@ window.__ModuleLoader__.load({
|
|
|
744
699
|
card("storage", t("storage"), t("storageDesc"), [
|
|
745
700
|
row(t("userPathLabel"), t("userPathHint"), h("input", { ...num("userMemoryPath"), type: "text" }), "userMemoryPath"),
|
|
746
701
|
row(t("wsDirLabel"), t("wsDirHint"), h("input", { ...num("workspaceMemoryDir"), type: "text" }), "workspaceMemoryDir"),
|
|
747
|
-
|
|
702
|
+
// ---- v1.8.0:日志保留天数配置已删除 —— 日志由记忆子代理维护、永不过期不删 ----
|
|
748
703
|
row(t("userBudgetLabel"), t("userBudgetHint"), h("input", num("userBudgetChars")), "userBudgetChars"),
|
|
749
704
|
row(t("wsBudgetLabel"), t("wsBudgetHint"), h("input", num("workspaceBudgetChars")), "workspaceBudgetChars")
|
|
750
705
|
]),
|
|
@@ -784,7 +739,7 @@ window.__ModuleLoader__.load({
|
|
|
784
739
|
document.head.appendChild(style);
|
|
785
740
|
}
|
|
786
741
|
|
|
787
|
-
// ---- v1.
|
|
742
|
+
// ---- v1.7.2-alpha.2 设置面板 nav 图标(「记忆」条目)----
|
|
788
743
|
// 宿主 SettingsRoot.navIcon(id) 是**硬编码白名单**(account/models/agent-presets/plugins/archived-sessions),
|
|
789
744
|
// 未列出的第三方 section 一律回退齿轮图标,且 slots 契约(id/order/label)没开 nav 图标位、
|
|
790
745
|
// 官方文档亦无「从 manifest 取 nav 图标」的机制(manifest icon 只进插件管理面板的卡片/行)。
|
|
@@ -1046,7 +1001,7 @@ window.__ModuleLoader__.load({
|
|
|
1046
1001
|
// v1.1.3:设置读写走自有 route(/memory-palace/api),不再 bind settingsScope——
|
|
1047
1002
|
// 非 loopback 下 settingsScope persistence=memory(set() no-op),保存永不落盘。
|
|
1048
1003
|
const controller = new MemoryPalaceController(ctx);
|
|
1049
|
-
// v1.
|
|
1004
|
+
// v1.7.2-alpha.2:设置面板 nav 条目换成自家 sparkle-twinkle 星标——宿主无 nav 图标位,
|
|
1050
1005
|
// 走「label 传节点 + CSS 隐藏回退齿轮」两步(原理/失效面见 40-sparkle.js 的 ensureNavStarStyles)。
|
|
1051
1006
|
ensureNavStarStyles();
|
|
1052
1007
|
const navLabel = () =>
|
package/lib/common/prompts.mjs
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
// memory-palace
|
|
1
|
+
// memory-palace 共享常量:两个 LLM prompt(会话蒸馏 / 项目记忆蒸馏)。
|
|
2
2
|
// 纯常量模块,无状态、可被任意模块与单测直接引用。
|
|
3
|
+
// v1.8.0:SCENE_KEYWORDS(plugin 模式防闲聊闸门关键词)已随 plugin 模式删除。
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
export const SCENE_KEYWORDS = ["记住", "记一下", "remind", "偏好", "决定", "以后都", "约定", "采用", "根因", "修复"];
|
|
6
|
-
|
|
7
|
-
// 智能模式(memoryMode==="smart")的摘要提炼 prompt(v1.4.0 起为函数,支持回喂存量记忆)。
|
|
5
|
+
// 会话提炼 prompt(手动「蒸馏会话」按钮,distillSessionCore 使用)。
|
|
8
6
|
// 让 LLM 输出 {summary, durable:[{scope,fact}], memoryOps:[...]};memoryOps 用于基于编号的现有记忆做增量维护。
|
|
9
|
-
// allowDelete=true(手动蒸馏按钮):开放 add/replace/delete
|
|
10
|
-
// 注意:回喂是否实际发生由 distill.mjs 按 cfg().feedbackEnabled
|
|
11
|
-
// 此处仅声明能力边界——allowDelete 决定 prompt 是否允许 delete
|
|
7
|
+
// allowDelete=true(手动蒸馏按钮):开放 add/replace/delete。
|
|
8
|
+
// 注意:回喂是否实际发生由 distill.mjs 按 cfg().feedbackEnabled 决定;
|
|
9
|
+
// 此处仅声明能力边界——allowDelete 决定 prompt 是否允许 delete 指令。
|
|
12
10
|
export function SUMMARY_PROMPT({ allowDelete = false, outputBudget } = {}) {
|
|
13
11
|
const feedbackInstr = allowDelete
|
|
14
12
|
? "【维护现有记忆】若对话中提供了「项目级记忆 / 用户级记忆(逐行编号)」,你可在输出 memoryOps 中对现有记忆做增量维护:\n" +
|
package/lib/common/records.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
// memory-palace 记忆记录读写(去重追加 / 匹配删除 /
|
|
1
|
+
// memory-palace 记忆记录读写(去重追加 / 匹配删除 / 每日日志)。
|
|
2
2
|
// 纯函数直接导出;依赖配置/路径解析的写入类函数经 createRecords 工厂注入。
|
|
3
|
-
|
|
3
|
+
// v1.8.0:轻量条目(writeLightEntry)、错误捕获(captureError)与日志过期迁移(prune)
|
|
4
|
+
// 随 plugin 模式一并删除——日志由记忆子代理维护、永不过期不删,是证据层。
|
|
5
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
4
6
|
import { readFileSync } from "node:fs";
|
|
5
7
|
import { join, dirname } from "node:path";
|
|
6
|
-
import { todayISO,
|
|
8
|
+
import { todayISO, normLine, isStructural, stripSmartTag } from "./text.mjs";
|
|
7
9
|
|
|
8
10
|
// 追加一行记忆,若目标文件已包含相同内容则跳过(去重),返回是否实际写入。
|
|
9
11
|
export async function appendLineDedup(file, line) {
|
|
@@ -200,73 +202,10 @@ export function createRecords({ getConfig, paths }) {
|
|
|
200
202
|
const hasTitle = existing.split("\n").some((l) => l.trim() === todayTitle);
|
|
201
203
|
await writeFile(file, (hasTitle ? "" : `${todayTitle}\n\n`) + existing + entry, "utf8");
|
|
202
204
|
}
|
|
203
|
-
await prune(dir);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async function prune(dir) {
|
|
207
|
-
const c = cfg();
|
|
208
|
-
// v1.6.0:hybrid 模式下日志永不过期不删(dailyLogRetentionDays 不可用,定案)——
|
|
209
|
-
// 日志是子代理维护的证据层,过期并入 MEMORY.md 的旧逻辑在 hybrid 下也不应触达。
|
|
210
|
-
if (c.memoryMode === "hybrid") return;
|
|
211
|
-
const cutoff = Date.now() - c.dailyLogRetentionDays * 86400000;
|
|
212
|
-
let files = [];
|
|
213
|
-
try {
|
|
214
|
-
files = await readdir(dir);
|
|
215
|
-
} catch {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
const mem = paths.memoryFileOf(dir);
|
|
219
|
-
for (const f of files) {
|
|
220
|
-
const m = /^(\d{4}-\d{2}-\d{2})\.md$/.exec(f);
|
|
221
|
-
if (!m) continue;
|
|
222
|
-
if (new Date(m[1]).getTime() < cutoff) {
|
|
223
|
-
const old = join(dir, f);
|
|
224
|
-
const text = await readFile(old, "utf8").catch(() => "");
|
|
225
|
-
if (text) {
|
|
226
|
-
let cur = "";
|
|
227
|
-
try {
|
|
228
|
-
cur = readFileSync(mem, "utf8");
|
|
229
|
-
} catch {
|
|
230
|
-
/* 尚无 MEMORY.md */
|
|
231
|
-
}
|
|
232
|
-
await mkdir(dirname(mem), { recursive: true });
|
|
233
|
-
await writeFile(mem, `${cur}\n<!-- distilled from ${f} -->\n${text}`, "utf8");
|
|
234
|
-
}
|
|
235
|
-
await unlink(old).catch(() => {});
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// 轻量结构化条目(无 LLM):截断原始文本,错误带 [ERROR] 前缀。
|
|
241
|
-
async function writeLightEntry(dirs, turn, isError) {
|
|
242
|
-
const userText = turn.find((b) => b.role === "user")?.text ?? "";
|
|
243
|
-
const asstText = turn.filter((b) => b.role === "assistant").map((b) => b.text).join(" ");
|
|
244
|
-
const summary = (userText || asstText || "(no message captured)").slice(0, 200);
|
|
245
|
-
const tag = isError ? "[ERROR] " : "";
|
|
246
|
-
const entry = `\n${tag}${summary}\n\n`;
|
|
247
|
-
for (const dir of dirs) await appendDaily(dir, entry);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// 错误捕获(目标2):按 scope 落对应 MEMORY.md,条目仅含「错误现象」。
|
|
251
|
-
// (v0.7.1 起不再调 LLM 生成方案——「根因/绕过手法」由 agent 按记忆公民指令场景①主动调 memory_note 记。)
|
|
252
|
-
// dirs 由调用方(_settle,已按会话 cwd 解析)显式传入——不再自取 paths.writeDirs(),
|
|
253
|
-
// 消除多会话并发时闭包 activeCwd 串台;空 dirs 仍按原语义回落用户级。
|
|
254
|
-
async function captureError(turn, reason, dirs, cwd) {
|
|
255
|
-
const c = cfg();
|
|
256
|
-
if (!dirs.length && !expandHome(c.userMemoryPath)) return;
|
|
257
|
-
const scope = dirs.length ? "project" : "user";
|
|
258
|
-
const errText = (reason?.message || reason?.error?.message || "(in-session error, no message)")
|
|
259
|
-
.toString()
|
|
260
|
-
.slice(0, 300);
|
|
261
|
-
const line = `- [${new Date().toISOString().slice(0, 10)}] in-session 错误(${scope}):${errText}`;
|
|
262
|
-
const targets = dirs.length ? dirs : [expandHome(c.userMemoryPath)];
|
|
263
|
-
for (const dir of targets) {
|
|
264
|
-
const mem = paths.memoryFileOf(dir);
|
|
265
|
-
await appendLineDedup(mem, line).catch(() => {});
|
|
266
|
-
}
|
|
267
205
|
}
|
|
268
206
|
|
|
269
207
|
// v1.7.1:recentLogs 已删除 —— memory_read 的 scope='daily' 改为按日期(isoDaysAgo)直读,
|
|
270
208
|
// 不再需要"最近 N 份文件"语义(跨日跳空会取偏)。
|
|
271
|
-
|
|
209
|
+
// v1.8.0:prune / writeLightEntry / captureError 已删除(plugin 模式整体移除,日志永不过期)。
|
|
210
|
+
return { appendDaily };
|
|
272
211
|
}
|