@oyasmi/pipiclaw 0.5.2 → 0.5.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 (216) hide show
  1. package/README.md +308 -209
  2. package/dist/agent/channel-runner.d.ts +3 -2
  3. package/dist/agent/channel-runner.js +22 -14
  4. package/dist/{command-extension.d.ts → agent/command-extension.d.ts} +0 -1
  5. package/dist/{command-extension.js → agent/command-extension.js} +1 -2
  6. package/dist/{commands.d.ts → agent/commands.d.ts} +0 -1
  7. package/dist/{commands.js → agent/commands.js} +0 -1
  8. package/dist/agent/index.d.ts +0 -1
  9. package/dist/agent/index.js +0 -1
  10. package/dist/agent/progress-formatter.d.ts +0 -1
  11. package/dist/agent/progress-formatter.js +0 -1
  12. package/dist/{prompt-builder.d.ts → agent/prompt-builder.d.ts} +1 -2
  13. package/dist/{prompt-builder.js → agent/prompt-builder.js} +0 -1
  14. package/dist/agent/run-queue.d.ts +0 -1
  15. package/dist/agent/run-queue.js +0 -1
  16. package/dist/agent/runner-factory.d.ts +0 -1
  17. package/dist/agent/runner-factory.js +0 -1
  18. package/dist/agent/session-events.d.ts +0 -1
  19. package/dist/agent/session-events.js +0 -1
  20. package/dist/agent/session-resource-gate.d.ts +10 -0
  21. package/dist/agent/session-resource-gate.js +44 -0
  22. package/dist/agent/type-guards.d.ts +0 -1
  23. package/dist/agent/type-guards.js +1 -2
  24. package/dist/agent/types.d.ts +1 -2
  25. package/dist/agent/types.js +0 -1
  26. package/dist/{config-loader.d.ts → agent/workspace-resources.d.ts} +3 -10
  27. package/dist/{config-loader.js → agent/workspace-resources.js} +3 -19
  28. package/dist/index.d.ts +9 -9
  29. package/dist/index.js +9 -9
  30. package/dist/log.d.ts +0 -1
  31. package/dist/log.js +0 -1
  32. package/dist/main.d.ts +0 -1
  33. package/dist/main.js +0 -1
  34. package/dist/memory/bootstrap.d.ts +0 -1
  35. package/dist/memory/bootstrap.js +0 -1
  36. package/dist/memory/candidates.d.ts +0 -1
  37. package/dist/memory/candidates.js +0 -1
  38. package/dist/memory/chinese-words.d.ts +0 -1
  39. package/dist/memory/chinese-words.js +64 -1
  40. package/dist/memory/consolidation.d.ts +0 -1
  41. package/dist/memory/consolidation.js +2 -3
  42. package/dist/memory/files.d.ts +0 -1
  43. package/dist/memory/files.js +0 -1
  44. package/dist/memory/lifecycle.d.ts +1 -2
  45. package/dist/memory/lifecycle.js +0 -1
  46. package/dist/memory/recall.d.ts +1 -1
  47. package/dist/memory/recall.js +77 -11
  48. package/dist/memory/session.d.ts +0 -1
  49. package/dist/memory/session.js +2 -3
  50. package/dist/{sidecar-worker.d.ts → memory/sidecar-worker.d.ts} +0 -1
  51. package/dist/{sidecar-worker.js → memory/sidecar-worker.js} +1 -2
  52. package/dist/models/api-keys.d.ts +7 -0
  53. package/dist/models/api-keys.js +16 -0
  54. package/dist/{model-utils.d.ts → models/utils.d.ts} +1 -2
  55. package/dist/{model-utils.js → models/utils.js} +0 -1
  56. package/dist/paths.d.ts +0 -1
  57. package/dist/paths.js +0 -1
  58. package/dist/runtime/bootstrap.d.ts +0 -1
  59. package/dist/runtime/bootstrap.js +2 -3
  60. package/dist/runtime/delivery.d.ts +0 -1
  61. package/dist/runtime/delivery.js +0 -1
  62. package/dist/runtime/dingtalk.d.ts +0 -1
  63. package/dist/runtime/dingtalk.js +1 -2
  64. package/dist/runtime/events.d.ts +0 -1
  65. package/dist/runtime/events.js +0 -1
  66. package/dist/runtime/store.d.ts +0 -1
  67. package/dist/runtime/store.js +0 -1
  68. package/dist/sandbox.d.ts +0 -1
  69. package/dist/sandbox.js +1 -2
  70. package/dist/{context.d.ts → settings.d.ts} +1 -2
  71. package/dist/{context.js → settings.js} +1 -2
  72. package/dist/{llm-json.d.ts → shared/llm-json.d.ts} +0 -1
  73. package/dist/{llm-json.js → shared/llm-json.js} +0 -1
  74. package/dist/shared/markdown-sections.d.ts +0 -1
  75. package/dist/shared/markdown-sections.js +0 -1
  76. package/dist/{shell-escape.d.ts → shared/shell-escape.d.ts} +0 -1
  77. package/dist/{shell-escape.js → shared/shell-escape.js} +0 -1
  78. package/dist/shared/text-utils.d.ts +0 -1
  79. package/dist/shared/text-utils.js +0 -1
  80. package/dist/shared/type-guards.d.ts +0 -1
  81. package/dist/shared/type-guards.js +0 -1
  82. package/dist/shared/types.d.ts +0 -1
  83. package/dist/shared/types.js +0 -1
  84. package/dist/subagents/discovery.d.ts +0 -1
  85. package/dist/subagents/discovery.js +1 -2
  86. package/dist/subagents/tool.d.ts +1 -2
  87. package/dist/subagents/tool.js +1 -2
  88. package/dist/tools/attach.d.ts +0 -1
  89. package/dist/tools/attach.js +0 -1
  90. package/dist/tools/bash.d.ts +0 -1
  91. package/dist/tools/bash.js +0 -1
  92. package/dist/tools/edit.d.ts +0 -1
  93. package/dist/tools/edit.js +1 -2
  94. package/dist/tools/index.d.ts +1 -2
  95. package/dist/tools/index.js +0 -1
  96. package/dist/tools/read.d.ts +0 -1
  97. package/dist/tools/read.js +1 -2
  98. package/dist/tools/truncate.d.ts +0 -1
  99. package/dist/tools/truncate.js +0 -1
  100. package/dist/tools/write-content.d.ts +0 -1
  101. package/dist/tools/write-content.js +1 -2
  102. package/dist/tools/write.d.ts +0 -1
  103. package/dist/tools/write.js +0 -1
  104. package/package.json +9 -3
  105. package/CHANGELOG.md +0 -47
  106. package/dist/agent/channel-runner.d.ts.map +0 -1
  107. package/dist/agent/channel-runner.js.map +0 -1
  108. package/dist/agent/index.d.ts.map +0 -1
  109. package/dist/agent/index.js.map +0 -1
  110. package/dist/agent/progress-formatter.d.ts.map +0 -1
  111. package/dist/agent/progress-formatter.js.map +0 -1
  112. package/dist/agent/run-queue.d.ts.map +0 -1
  113. package/dist/agent/run-queue.js.map +0 -1
  114. package/dist/agent/runner-factory.d.ts.map +0 -1
  115. package/dist/agent/runner-factory.js.map +0 -1
  116. package/dist/agent/session-events.d.ts.map +0 -1
  117. package/dist/agent/session-events.js.map +0 -1
  118. package/dist/agent/type-guards.d.ts.map +0 -1
  119. package/dist/agent/type-guards.js.map +0 -1
  120. package/dist/agent/types.d.ts.map +0 -1
  121. package/dist/agent/types.js.map +0 -1
  122. package/dist/agent.d.ts +0 -3
  123. package/dist/agent.d.ts.map +0 -1
  124. package/dist/agent.js +0 -2
  125. package/dist/agent.js.map +0 -1
  126. package/dist/command-extension.d.ts.map +0 -1
  127. package/dist/command-extension.js.map +0 -1
  128. package/dist/commands.d.ts.map +0 -1
  129. package/dist/commands.js.map +0 -1
  130. package/dist/config-loader.d.ts.map +0 -1
  131. package/dist/config-loader.js.map +0 -1
  132. package/dist/context.d.ts.map +0 -1
  133. package/dist/context.js.map +0 -1
  134. package/dist/index.d.ts.map +0 -1
  135. package/dist/index.js.map +0 -1
  136. package/dist/llm-json.d.ts.map +0 -1
  137. package/dist/llm-json.js.map +0 -1
  138. package/dist/log.d.ts.map +0 -1
  139. package/dist/log.js.map +0 -1
  140. package/dist/main.d.ts.map +0 -1
  141. package/dist/main.js.map +0 -1
  142. package/dist/memory/bootstrap.d.ts.map +0 -1
  143. package/dist/memory/bootstrap.js.map +0 -1
  144. package/dist/memory/candidates.d.ts.map +0 -1
  145. package/dist/memory/candidates.js.map +0 -1
  146. package/dist/memory/chinese-words.d.ts.map +0 -1
  147. package/dist/memory/chinese-words.js.map +0 -1
  148. package/dist/memory/consolidation.d.ts.map +0 -1
  149. package/dist/memory/consolidation.js.map +0 -1
  150. package/dist/memory/files.d.ts.map +0 -1
  151. package/dist/memory/files.js.map +0 -1
  152. package/dist/memory/lifecycle.d.ts.map +0 -1
  153. package/dist/memory/lifecycle.js.map +0 -1
  154. package/dist/memory/recall.d.ts.map +0 -1
  155. package/dist/memory/recall.js.map +0 -1
  156. package/dist/memory/session.d.ts.map +0 -1
  157. package/dist/memory/session.js.map +0 -1
  158. package/dist/model-utils.d.ts.map +0 -1
  159. package/dist/model-utils.js.map +0 -1
  160. package/dist/paths.d.ts.map +0 -1
  161. package/dist/paths.js.map +0 -1
  162. package/dist/prompt-builder.d.ts.map +0 -1
  163. package/dist/prompt-builder.js.map +0 -1
  164. package/dist/runtime/bootstrap.d.ts.map +0 -1
  165. package/dist/runtime/bootstrap.js.map +0 -1
  166. package/dist/runtime/delivery.d.ts.map +0 -1
  167. package/dist/runtime/delivery.js.map +0 -1
  168. package/dist/runtime/dingtalk.d.ts.map +0 -1
  169. package/dist/runtime/dingtalk.js.map +0 -1
  170. package/dist/runtime/events.d.ts.map +0 -1
  171. package/dist/runtime/events.js.map +0 -1
  172. package/dist/runtime/store.d.ts.map +0 -1
  173. package/dist/runtime/store.js.map +0 -1
  174. package/dist/sandbox.d.ts.map +0 -1
  175. package/dist/sandbox.js.map +0 -1
  176. package/dist/shared/markdown-sections.d.ts.map +0 -1
  177. package/dist/shared/markdown-sections.js.map +0 -1
  178. package/dist/shared/text-utils.d.ts.map +0 -1
  179. package/dist/shared/text-utils.js.map +0 -1
  180. package/dist/shared/type-guards.d.ts.map +0 -1
  181. package/dist/shared/type-guards.js.map +0 -1
  182. package/dist/shared/types.d.ts.map +0 -1
  183. package/dist/shared/types.js.map +0 -1
  184. package/dist/shell-escape.d.ts.map +0 -1
  185. package/dist/shell-escape.js.map +0 -1
  186. package/dist/sidecar-worker.d.ts.map +0 -1
  187. package/dist/sidecar-worker.js.map +0 -1
  188. package/dist/subagents/discovery.d.ts.map +0 -1
  189. package/dist/subagents/discovery.js.map +0 -1
  190. package/dist/subagents/tool.d.ts.map +0 -1
  191. package/dist/subagents/tool.js.map +0 -1
  192. package/dist/tools/attach.d.ts.map +0 -1
  193. package/dist/tools/attach.js.map +0 -1
  194. package/dist/tools/bash.d.ts.map +0 -1
  195. package/dist/tools/bash.js.map +0 -1
  196. package/dist/tools/edit.d.ts.map +0 -1
  197. package/dist/tools/edit.js.map +0 -1
  198. package/dist/tools/index.d.ts.map +0 -1
  199. package/dist/tools/index.js.map +0 -1
  200. package/dist/tools/read.d.ts.map +0 -1
  201. package/dist/tools/read.js.map +0 -1
  202. package/dist/tools/truncate.d.ts.map +0 -1
  203. package/dist/tools/truncate.js.map +0 -1
  204. package/dist/tools/write-content.d.ts.map +0 -1
  205. package/dist/tools/write-content.js.map +0 -1
  206. package/dist/tools/write.d.ts.map +0 -1
  207. package/dist/tools/write.js.map +0 -1
  208. package/docs/memory-audit.md +0 -330
  209. package/docs/memory-optimization-round2.md +0 -319
  210. package/docs/specs/001-implement-memory/memory-rfc.md +0 -297
  211. package/docs/specs/002-subagent/pi-subagent-analyse.txt +0 -190
  212. package/docs/specs/002-subagent/pi-subagent-design.txt +0 -266
  213. package/docs/specs/002-subagent/pi-subagent-phase1-plan.txt +0 -529
  214. package/docs/specs/003-improve-memory/design.md +0 -537
  215. package/docs/specs/003-improve-memory/interfaces-and-tests.md +0 -473
  216. package/docs/specs/003-improve-memory/spec.md +0 -357
@@ -1,319 +0,0 @@
1
- # Memory 子系统第二轮优化计划
2
-
3
- > **Date**: 2026-04-02
4
- > **Base**: 第一轮优化后 (commit 845de82)
5
- > **Input**: memory-audit.md 审计报告 + 第一轮优化质量评估
6
-
7
- ---
8
-
9
- ## 一、第一轮优化回顾
10
-
11
- ### 已落地(保留不动)
12
-
13
- | 方案 | 实施质量 | 说明 |
14
- |------|---------|------|
15
- | 空闲触发 consolidation | A | 60s idle timer + snapshot + 自动重调度,设计精良 |
16
- | 中文分词改进 | A | 正向最大匹配 + bigram 兜底 + 130 词表 |
17
- | Rerank 参数提升 | A | timeout 8s, content clip 800 |
18
- | 降低 maintenance 阈值 | A | memory 5K/4块, history 8K/5块/保留3 |
19
- | Query Intent Detection | A | 6 种意图,中英双语,超出审计建议的创新 |
20
- | Consolidation prompt 强化 | B- | 仅加了"prefer"措辞,未加 few-shot |
21
-
22
- ### 未落地或需改进
23
-
24
- | 方案 | 状态 | 本轮处理 |
25
- |------|------|---------|
26
- | Recall 默认配置调优 | 未实施 | 本轮实施 |
27
- | 评分算法仍有 priority 主导倾向 | 部分改善 | 本轮精炼 |
28
- | Intent seeding 可能注入无关候选 | 新发现 | 本轮修复 |
29
- | 运算符优先级不清晰 | 新发现 | 本轮修复 |
30
- | 中文词表覆盖不足 | 新发现 | 本轮扩充 |
31
- | 排序逻辑重复 | 新发现 | 本轮提取 |
32
-
33
- ---
34
-
35
- ## 二、本轮优化内容
36
-
37
- ### 2.1 [P0] 首轮强制注入 MEMORY.md(新策略)
38
-
39
- **动机**:当前召回依赖 token overlap + intent matching,但 session 首轮对话中用户可能只说了一句模糊的话(如"你好"、"帮我看看那个问题"),几乎不会命中任何 memory 候选。LLM 在冷启动时对频道上下文完全遗忘。
40
-
41
- **策略**:在每个 session 的第一轮对话中,无条件将 MEMORY.md 的前 3K 字符拼入 prompt,独立于召回机制。
42
-
43
- **实现要点**:
44
-
45
- 1. 在 `ChannelRunner` 中新增 `isFirstUserTurn` 状态标记:
46
-
47
- ```typescript
48
- // channel-runner.ts
49
- private isFirstUserTurn = true;
50
-
51
- // 在 run() 方法中,recall 之后:
52
- if (this.isFirstUserTurn) {
53
- const memorySnapshot = await this.buildFirstTurnMemorySnapshot();
54
- if (memorySnapshot) {
55
- promptText = `${memorySnapshot}\n\n${promptText}`;
56
- }
57
- this.isFirstUserTurn = false;
58
- }
59
- ```
60
-
61
- 2. 构建注入文本:
62
-
63
- ```typescript
64
- private async buildFirstTurnMemorySnapshot(): Promise<string> {
65
- const memoryPath = getChannelMemoryPath(this.channelDir);
66
- const raw = await readOptionalFile(memoryPath);
67
- if (!raw.trim()) return "";
68
-
69
- // 如果 recall 已返回 channel-memory 候选,跳过注入避免重复
70
- // (由调用方判断,此处只负责构建文本)
71
-
72
- const clipped = clipText(raw, 3000, { headRatio: 1.0 }); // 纯取头部
73
- return [
74
- "<channel_memory_snapshot>",
75
- "Below is the first 3K of this channel's durable memory (MEMORY.md).",
76
- "Use it as background context for this conversation.",
77
- "",
78
- clipped,
79
- "</channel_memory_snapshot>",
80
- ].join("\n");
81
- }
82
- ```
83
-
84
- 3. 与 recall 去重:如果 recall 结果已包含 `channel-memory` 来源的候选,则跳过强制注入。
85
-
86
- **优势**:
87
- - 解决冷启动遗忘问题,LLM 从第一句话就"记得"频道核心上下文
88
- - 实现极简(约 20 行),几乎零风险
89
- - MEMORY.md 头部经过 cleanup LLM 整理,天然是高价值信息(Identity/Preferences/Constraints)
90
- - 与 recall 互补而非冲突:recall 解决"针对具体问题找相关记忆",强制注入解决"确保基础上下文始终在场"
91
-
92
- **风险与缓解**:
93
- - Token 预算占用约 1K-1.5K tokens — 钉钉短问答场景中上下文窗口充裕,影响可忽略
94
- - 与 recall 结果重复 — 通过检查 recall 是否已返回 channel-memory 候选来去重
95
-
96
- ---
97
-
98
- ### 2.2 [P0] 实施 Recall 默认配置调优
99
-
100
- **动机**:第一轮审计明确建议但未实施。当前默认值过于保守。
101
-
102
- **改动位置**:`src/agent/channel-runner.ts` 中的 `recallRelevantMemory()` 调用参数,以及 `src/context.ts` 中的 `PipiclawMemoryRecallSettings` 默认值。
103
-
104
- | 参数 | 当前值 | 目标值 | 理由 |
105
- |------|-------|-------|------|
106
- | maxCandidates | 8 | 12 | 给 reranker 更多候选,提升选择质量 |
107
- | maxInjected | 3 | 5 | 注入更多上下文,覆盖更多相关信息 |
108
- | maxChars | 3500 | 5000 | 允许更长的回忆文本 |
109
- | rerankWithModel | false | true | 默认开启 LLM rerank,显著提升中文召回质量 |
110
-
111
- ---
112
-
113
- ### 2.3 [P1] 评分算法精炼
114
-
115
- **问题**:当前 priority 范围 4-18,lexical 最高约 96。session(priority=18)和 history(priority=4)差距 14 分。当 query 与两个候选的词汇匹配度相同时,session 始终胜出。真正的"相关性优先"尚未实现。
116
-
117
- **方案**:改为乘法加权,structural 作为调节因子而非独立加分项。
118
-
119
- ```typescript
120
- function scoreCandidate(...): ScoredCandidate | null {
121
- // ... 计算 lexicalScore 和 structuralScore 同现有逻辑 ...
122
-
123
- if (matchedTokens.size === 0 && exactBoost === 0 && intentBoost === 0) {
124
- return null;
125
- }
126
-
127
- // 乘法加权:lexical 为主,structural 为调节
128
- // structural 最高约 34(priority 18 + intent 10 + recency 6)
129
- // 乘数范围约 1.0 ~ 1.34
130
- const score = lexicalScore * (1 + structuralScore / 100);
131
-
132
- return { candidate, score, lexicalMatchCount: matchedTokens.size, intentBoost };
133
- }
134
- ```
135
-
136
- **效果**:
137
- - 当 lexical = 0 时,score = 0 — 无词汇匹配的候选不会仅靠 structural 上位
138
- - 当 lexical 相同时,structural 提供约 0-34% 的微调 — session 仍有优势但不再碾压
139
- - 当 history 候选 lexical 远高于 session 候选时,history 可以反超
140
-
141
- **注意**:`seedIntentCandidates()` 中 intentBoost > 0 但 lexicalMatchCount = 0 的候选,在乘法模式下 score 会变为 0。需要调整 seeding 逻辑(见 2.4)。
142
-
143
- ---
144
-
145
- ### 2.4 [P1] 约束 Intent Seeding
146
-
147
- **问题**:`seedIntentCandidates()` 可注入 lexicalMatchCount=0 的候选。在 2.3 改为乘法加权后,这些候选 score 为 0,会被自然淘汰。但即使不改为乘法,纯 intent 注入也可能挤掉更相关的候选。
148
-
149
- **方案**:对 intent seeding 增加最低门槛。
150
-
151
- ```typescript
152
- function seedIntentCandidates(
153
- request: RecallRequest,
154
- candidates: MemoryCandidate[],
155
- existing: ScoredCandidate[],
156
- intents: Set<QueryIntent>,
157
- queryTokens: string[], // 新增参数
158
- ): ScoredCandidate[] {
159
- // ...
160
- for (const { candidate, intentBoost } of intentCandidates) {
161
- // 至少需要 1 个 query token 匹配,才允许 intent 注入
162
- const matched = collectMatchingQueryTokens(
163
- queryTokens,
164
- [candidate.title, candidate.searchText ?? candidate.content],
165
- );
166
- if (matched.size === 0) continue;
167
-
168
- seeded.push({ ... });
169
- }
170
- // ...
171
- }
172
- ```
173
-
174
- **效果**:意图匹配 + 至少 1 个词汇匹配 = 允许注入。纯意图匹配但内容完全无关 = 不注入。
175
-
176
- ---
177
-
178
- ### 2.5 [P1] 扩充中文词表
179
-
180
- **问题**:当前 130 词中包含较多 pipiclaw 内部术语("召回排序"、"排序失真"、"主导权重"),缺少大量通用技术词汇。
181
-
182
- **方案**:
183
-
184
- 1. **移除**过于特定的内部术语(约 20 个),如"排序失真"、"主导权重"、"轻量词表"等
185
- 2. **新增**通用技术词汇(约 200 个),覆盖以下领域:
186
-
187
- ```
188
- 基础设施: 服务器、数据库、缓存、队列、网络、集群、容器、网关、负载均衡
189
- 编程概念: 函数、变量、接口、类型、模块、组件、依赖、注入、继承、多态
190
- 开发流程: 需求、设计、实现、测试、部署、发布、回滚、监控、告警、日志
191
- Web/API: 请求、响应、认证、授权、会话、路由、中间件、过滤器、拦截器
192
- 数据: 查询、索引、事务、迁移、备份、恢复、同步、异步、并发、锁
193
- 工具: 编辑器、终端、浏览器、调试器、编译器、构建、打包、压缩
194
- ```
195
-
196
- 3. 目标词表规模约 300 个,保持文件 < 300 行
197
-
198
- ---
199
-
200
- ### 2.6 [P1] 修复代码质量问题
201
-
202
- #### 2.6.1 运算符优先级明确化
203
-
204
- **位置**:`src/memory/lifecycle.ts:109-113`
205
-
206
- ```typescript
207
- // 当前(行为正确但意图不清晰)
208
- if (
209
- canTriggerThresholdRefresh &&
210
- this.turnsSinceSessionUpdate >= settings.minTurnsBetweenUpdate ||
211
- (canTriggerThresholdRefresh && this.toolCallsSinceSessionUpdate >= settings.minToolCallsBetweenUpdate)
212
- )
213
-
214
- // 修改为
215
- if (
216
- canTriggerThresholdRefresh &&
217
- (this.turnsSinceSessionUpdate >= settings.minTurnsBetweenUpdate ||
218
- this.toolCallsSinceSessionUpdate >= settings.minToolCallsBetweenUpdate)
219
- )
220
- ```
221
-
222
- #### 2.6.2 提取排序比较器
223
-
224
- **位置**:`src/memory/recall.ts:487-501`
225
-
226
- ```typescript
227
- function compareScoredCandidates(a: ScoredCandidate, b: ScoredCandidate): number {
228
- return (
229
- b.score - a.score ||
230
- b.lexicalMatchCount - a.lexicalMatchCount ||
231
- b.candidate.priority - a.candidate.priority ||
232
- a.candidate.title.localeCompare(b.candidate.title)
233
- );
234
- }
235
-
236
- // 使用
237
- const scored = filteredCandidates.map(...).filter(...).sort(compareScoredCandidates);
238
- const shortlist = seedIntentCandidates(...).sort(compareScoredCandidates).slice(...);
239
- ```
240
-
241
- ---
242
-
243
- ### 2.7 [P2] Consolidation prompt 强化
244
-
245
- **问题**:当前 prompt 对 historyBlock 仅用"prefer"措辞,LLM 在短对话时仍可能返回空值。
246
-
247
- **方案**:添加 few-shot 示例到 system prompt。
248
-
249
- ```
250
- Rules:
251
- ...
252
- - historyBlock: concise Markdown summarizing the conversation chunk for later recovery.
253
- - For any conversation with at least one meaningful user question and assistant answer,
254
- you MUST return a non-empty historyBlock with at least one bullet summarizing the exchange.
255
- - Prefer short bullets and short paragraphs.
256
-
257
- Example output for a short Q&A conversation:
258
- {
259
- "memoryEntries": ["User prefers dark mode in the dashboard"],
260
- "historyBlock": "- User asked how to toggle dashboard theme; confirmed dark mode preference."
261
- }
262
- ```
263
-
264
- ---
265
-
266
- ### 2.8 [P2] Sidecar Token 追踪
267
-
268
- **问题**:memory 系统通过 sidecar 发起的 LLM 调用(session memory update、inline consolidation、memory cleanup、history folding、LLM rerank)没有 token 使用量统计,无法评估实际 API 开销。
269
-
270
- **方案**:
271
-
272
- 1. `runSidecarTask` 返回值中增加 `usage?: { inputTokens: number; outputTokens: number }`
273
- 2. `MemoryLifecycle` 中累计追踪每类操作的 token 消耗
274
- 3. 在 background maintenance 日志中输出累计 token 消耗
275
-
276
- ---
277
-
278
- ## 三、实施顺序
279
-
280
- ```
281
- Phase 1(核心功能)
282
- 2.1 首轮强制注入 MEMORY.md
283
- 2.2 Recall 默认配置调优
284
- 2.6 代码质量修复(运算符优先级 + 排序提取)
285
-
286
- Phase 2(评分优化)
287
- 2.3 评分乘法加权
288
- 2.4 Intent seeding 约束
289
- 2.5 中文词表扩充
290
-
291
- Phase 3(可靠性)
292
- 2.7 Consolidation prompt 强化
293
- 2.8 Sidecar token 追踪
294
- ```
295
-
296
- ---
297
-
298
- ## 四、验证标准
299
-
300
- ### 功能验证
301
-
302
- - [ ] 首轮对话发送模糊消息(如"你好"),prompt 中应包含 `<channel_memory_snapshot>` 标签
303
- - [ ] 第二轮对话不再包含强制注入内容
304
- - [ ] 当 recall 已返回 channel-memory 候选时,跳过强制注入
305
- - [ ] rerankWithModel 默认启用,中文查询自动触发 rerank
306
-
307
- ### 评分验证
308
-
309
- - [ ] history 候选在 lexical 高度匹配时可以排在不相关 session 候选之前
310
- - [ ] lexical = 0 的候选不会仅靠 structural 上位(乘法加权后)
311
- - [ ] intent seeding 不会注入与 query 零词汇匹配的候选
312
-
313
- ### 回归验证
314
-
315
- - [ ] 全部现有测试通过
316
- - [ ] 新增首轮注入的单元测试
317
- - [ ] 新增 scoreCandidate 乘法加权的单元测试
318
- - [ ] 新增中文短查询(2-3 字)的召回集成测试
319
-
@@ -1,297 +0,0 @@
1
- # Pipiclaw Memory Model RFC
2
-
3
- ## Status
4
-
5
- Superseded in part by [`docs/improve-memory/spec.md`](/Users/oyasmi/projects/pipiclaw/docs/improve-memory/spec.md) and [`docs/improve-memory/design.md`](/Users/oyasmi/projects/pipiclaw/docs/improve-memory/design.md).
6
-
7
- This RFC remains useful for the original file-based memory rationale, but it no longer fully describes the current design because the runtime now introduces:
8
-
9
- 1. `SESSION.md` as a distinct channel working-memory layer
10
- 2. proactive relevant-memory injection
11
- 3. a revised lifecycle between `SESSION.md`, `MEMORY.md`, and `HISTORY.md`
12
-
13
- ## Goals
14
-
15
- 1. Define a minimal memory model for `pipiclaw` aligned with the `nanobot` style.
16
- 2. Make memory flow explicit: record, read, consolidate, and reuse.
17
- 3. Keep raw transport/session files cold and separate from memory.
18
- 4. Limit what is loaded into session context by default.
19
- 5. Preserve simple file-based operations and avoid introducing a dedicated memory database or memory-specific tools.
20
-
21
- ## Non-Goals
22
-
23
- 1. No OpenClaw-style vector retrieval, embedding index, or memory plugins.
24
- 2. No `memory_search` or `memory_get` tool.
25
- 3. No automatic runtime mutation of workspace-level `MEMORY.md`, `SOUL.md`, or `AGENTS.md`.
26
- 4. No automatic loading or scanning of `log.jsonl` or `context.jsonl` as part of memory behavior.
27
-
28
- ## Design Summary
29
-
30
- Pipiclaw memory is split into two channel-level files plus one workspace-level admin file:
31
-
32
- - `workspace/MEMORY.md`
33
- - Stable, admin-managed, shared background memory.
34
- - Not automatically updated by runtime consolidation.
35
- - `<channel>/MEMORY.md`
36
- - Durable channel memory.
37
- - Updated automatically by consolidation.
38
- - May also be updated manually by the agent.
39
- - `<channel>/HISTORY.md`
40
- - Channel history summaries.
41
- - Updated automatically by consolidation only.
42
- - Not intended for direct manual maintenance by the agent.
43
-
44
- Raw storage remains separate:
45
-
46
- - `<channel>/log.jsonl`
47
- - Raw message log only.
48
- - Cold storage.
49
- - Not proactively loaded or scanned by runtime.
50
- - `<channel>/context.jsonl`
51
- - Raw session persistence only.
52
- - Cold storage.
53
- - Not proactively loaded or scanned by runtime for memory purposes.
54
-
55
- ## File Model
56
-
57
- ### Workspace-Level Files
58
-
59
- - `SOUL.md`
60
- - Loaded into session context at session start.
61
- - Read-only from the agent's perspective unless a human explicitly changes it.
62
- - `AGENTS.md`
63
- - Loaded into session context at session start.
64
- - Read-only from the agent's perspective unless a human explicitly changes it.
65
- - `MEMORY.md`
66
- - Not loaded by default.
67
- - Listed in the system prompt with its role and path.
68
- - Intended to be read on demand by the agent.
69
- - Stable and admin-managed.
70
-
71
- ### Channel-Level Files
72
-
73
- - `MEMORY.md`
74
- - Not loaded by default.
75
- - Listed in the system prompt with its role and path.
76
- - Intended to be read on demand by the agent.
77
- - Primary durable memory for the channel.
78
- - `HISTORY.md`
79
- - Not loaded by default.
80
- - Listed in the system prompt with its role and path.
81
- - Intended to be read on demand by the agent.
82
- - Append-oriented summary history for older context.
83
- - `log.jsonl`
84
- - Raw archive only.
85
- - Not memory.
86
- - Runtime must not proactively load or scan it.
87
- - `context.jsonl`
88
- - Raw session archive only.
89
- - Not memory.
90
- - Runtime must not proactively load or scan it.
91
-
92
- ## Default Context Loading
93
-
94
- At session start, runtime loads the following into session context:
95
-
96
- 1. Workspace-level `SOUL.md`
97
- 2. Workspace-level `AGENTS.md`
98
- 3. Built-in tool descriptions
99
- 4. Summaries of both workspace-level and channel-level skills
100
-
101
- At session start, runtime does not load the following by default:
102
-
103
- 1. Workspace-level `MEMORY.md`
104
- 2. Channel-level `MEMORY.md`
105
- 3. Channel-level `HISTORY.md`
106
- 4. `<channel>/log.jsonl`
107
- 5. `<channel>/context.jsonl`
108
-
109
- The system prompt must explicitly tell the agent:
110
-
111
- 1. Where `workspace/MEMORY.md`, `<channel>/MEMORY.md`, and `<channel>/HISTORY.md` live.
112
- 2. What each file is for.
113
- 3. That these files are not preloaded.
114
- 4. That the agent is encouraged to read them on demand when memory or history is relevant.
115
-
116
- Changes to workspace-level `SOUL.md` and `AGENTS.md` take effect on new sessions. They are not reloaded on every turn.
117
-
118
- ## Agent Read/Write Rules
119
-
120
- ### Reads
121
-
122
- The agent should prefer:
123
-
124
- 1. `<channel>/MEMORY.md` for durable channel facts, decisions, preferences, and ongoing state.
125
- 2. `<channel>/HISTORY.md` for older summarized context.
126
- 3. `workspace/MEMORY.md` for stable shared background.
127
-
128
- The agent should not treat `log.jsonl` or `context.jsonl` as normal memory sources. Those files are for raw recovery, debugging, or explicit transcript-level investigation only.
129
-
130
- ### Writes
131
-
132
- The agent may:
133
-
134
- 1. Read `workspace/MEMORY.md`
135
- 2. Read `<channel>/MEMORY.md`
136
- 3. Read `<channel>/HISTORY.md`
137
- 4. Manually update `<channel>/MEMORY.md` when necessary
138
-
139
- The agent should not manually maintain `<channel>/HISTORY.md` during normal operation. `HISTORY.md` is runtime-managed.
140
-
141
- The runtime must never automatically update:
142
-
143
- 1. `workspace/SOUL.md`
144
- 2. `workspace/AGENTS.md`
145
- 3. `workspace/MEMORY.md`
146
-
147
- ## Consolidation
148
-
149
- Consolidation is the primary mechanism that keeps memory moving.
150
-
151
- Consolidation takes recent session material and produces two outputs:
152
-
153
- 1. Durable facts and live channel state in `<channel>/MEMORY.md`
154
- 2. Older summarized history in `<channel>/HISTORY.md`
155
-
156
- Consolidation must not write to workspace-level `MEMORY.md`.
157
-
158
- ### Trigger Model
159
-
160
- Runtime should run consolidation automatically only when a session is about to compact or trim context.
161
-
162
- There is no separate turn-count trigger, token-watermark trigger, or per-turn memory-dirty trigger in this RFC.
163
-
164
- ### Consolidation Input
165
-
166
- Consolidation operates on recent session material already in the active session state. It does not scan `log.jsonl` or `context.jsonl`.
167
-
168
- ### Consolidation Output Rules
169
-
170
- `<channel>/MEMORY.md` should contain:
171
-
172
- 1. Durable facts about the channel, user, project, preferences, constraints, and long-lived open threads.
173
- 2. Current state that matters across turns.
174
- 3. Cleaned and deduplicated entries.
175
- 4. Structured sections rather than free-form prose.
176
-
177
- `<channel>/HISTORY.md` should contain:
178
-
179
- 1. Append-oriented summaries of older conversation chunks.
180
- 2. Resolved decisions and notable milestones.
181
- 3. Enough context for later recovery without replaying raw transcripts.
182
-
183
- ### Consolidation Semantics
184
-
185
- Consolidation should:
186
-
187
- 1. Extract durable facts from recent session material.
188
- 2. Append new channel-memory entries into `<channel>/MEMORY.md` during normal operation.
189
- 3. Periodically clean up `<channel>/MEMORY.md` with a larger sweep that removes outdated entries, merges duplicates, and tightens wording.
190
- 4. Append or roll forward summarized older material into `<channel>/HISTORY.md`.
191
- 5. Periodically fold older `HISTORY.md` blocks into coarser summaries while keeping newer blocks more detailed.
192
- 6. Remove redundancy between the two files.
193
- 7. Prefer stable facts in `MEMORY.md` and narrative progression in `HISTORY.md`.
194
-
195
- This RFC adopts an append-first strategy for `MEMORY.md`, with periodic cleanup passes rather than full rewrite on every consolidation.
196
-
197
- Consolidation should not:
198
-
199
- 1. Dump raw message transcripts into `HISTORY.md`
200
- 2. Copy large blocks from `context.jsonl` or `log.jsonl`
201
- 3. Preserve outdated facts just because they were once true
202
-
203
- ## Suggested File Semantics
204
-
205
- `<channel>/MEMORY.md` should be organized as stable sections such as:
206
-
207
- 1. `## Identity / Participants`
208
- 2. `## Preferences`
209
- 3. `## Ongoing Work`
210
- 4. `## Constraints`
211
- 5. `## Decisions`
212
- 6. `## Open Loops`
213
-
214
- `<channel>/HISTORY.md` should be organized as chronological summary blocks such as:
215
-
216
- 1. Dated headings
217
- 2. Short summaries of work periods
218
- 3. Key decisions and outcomes
219
-
220
- Exact formatting can evolve, but the split between durable memory and summarized history should remain stable.
221
-
222
- ## Consolidation Execution Model
223
-
224
- Consolidation uses a two-phase execution model:
225
-
226
- 1. Inline phase
227
- - Runs synchronously when a compaction or trim is about to happen.
228
- - Responsible for producing the minimum safe memory updates needed before context is reduced.
229
- 2. Background phase
230
- - Runs later as a per-channel queued maintenance pass.
231
- - Responsible for larger cleanup work, including `MEMORY.md` cleanup sweeps and `HISTORY.md` folding.
232
-
233
- The background phase must not replace the inline phase for compaction safety. It is an additional maintenance pass, not the primary durability guarantee.
234
-
235
- ## Compaction And Trimming Contract
236
-
237
- Consolidation is hard-gated before compaction or trim.
238
-
239
- This means:
240
-
241
- 1. If a compaction or trim would discard context, runtime must first run inline consolidation.
242
- 2. If inline consolidation fails, compaction or trim must not proceed.
243
- 3. After successful inline consolidation, the runtime may compact or trim.
244
-
245
- This RFC does not allow trim-first or compact-first behavior when memory durability depends on consolidation.
246
-
247
- ## Runtime Responsibilities
248
-
249
- Runtime is responsible for:
250
-
251
- 1. Loading only the default context described in this RFC.
252
- 2. Exposing file locations and roles clearly in the system prompt.
253
- 3. Running automatic consolidation.
254
- 4. Updating `<channel>/MEMORY.md` and `<channel>/HISTORY.md` during consolidation.
255
- 5. Keeping `log.jsonl` and `context.jsonl` cold.
256
-
257
- Runtime is not responsible for:
258
-
259
- 1. Auto-loading memory files into every turn
260
- 2. Indexing memory into a vector database
261
- 3. Providing special memory-only tools
262
-
263
- ## Session Model
264
-
265
- Session context is warm.
266
-
267
- Memory files are warm-on-demand.
268
-
269
- `log.jsonl` and `context.jsonl` are cold.
270
-
271
- The intended flow is:
272
-
273
- 1. Session starts with `SOUL.md`, `AGENTS.md`, built-in tool descriptions, and skill summaries.
274
- 2. Agent reads channel or workspace memory files if the task needs them.
275
- 3. Conversation progresses in session state.
276
- 4. Runtime consolidates session material into `<channel>/MEMORY.md` and `<channel>/HISTORY.md`.
277
- 5. Older raw storage remains available but is not part of ordinary memory behavior.
278
-
279
- ## Migration Impact
280
-
281
- This RFC implies the following behavior changes from the current implementation:
282
-
283
- 1. `workspace/MEMORY.md` and `<channel>/MEMORY.md` are no longer injected into the system prompt by default.
284
- 2. `SOUL.md` and `AGENTS.md` are no longer reloaded on every turn.
285
- 3. `log.jsonl` is no longer scanned to rebuild context as part of normal turn processing.
286
- 4. `context.jsonl` is no longer treated as a memory source.
287
- 5. Consolidation becomes the main persistence path for channel memory.
288
-
289
- ## Fixed Decisions
290
-
291
- This RFC fixes the following design choices:
292
-
293
- 1. Consolidation triggers only before compaction or trim.
294
- 2. `<channel>/MEMORY.md` uses append-first updates with periodic cleanup sweeps.
295
- 3. `<channel>/HISTORY.md` uses append-first updates with periodic folding of older blocks.
296
- 4. Consolidation uses a two-phase execution model: inline for safety, background for maintenance.
297
- 5. Consolidation is hard-gated before compaction or trim.