@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.
- package/README.md +308 -209
- package/dist/agent/channel-runner.d.ts +3 -2
- package/dist/agent/channel-runner.js +22 -14
- package/dist/{command-extension.d.ts → agent/command-extension.d.ts} +0 -1
- package/dist/{command-extension.js → agent/command-extension.js} +1 -2
- package/dist/{commands.d.ts → agent/commands.d.ts} +0 -1
- package/dist/{commands.js → agent/commands.js} +0 -1
- package/dist/agent/index.d.ts +0 -1
- package/dist/agent/index.js +0 -1
- package/dist/agent/progress-formatter.d.ts +0 -1
- package/dist/agent/progress-formatter.js +0 -1
- package/dist/{prompt-builder.d.ts → agent/prompt-builder.d.ts} +1 -2
- package/dist/{prompt-builder.js → agent/prompt-builder.js} +0 -1
- package/dist/agent/run-queue.d.ts +0 -1
- package/dist/agent/run-queue.js +0 -1
- package/dist/agent/runner-factory.d.ts +0 -1
- package/dist/agent/runner-factory.js +0 -1
- package/dist/agent/session-events.d.ts +0 -1
- package/dist/agent/session-events.js +0 -1
- package/dist/agent/session-resource-gate.d.ts +10 -0
- package/dist/agent/session-resource-gate.js +44 -0
- package/dist/agent/type-guards.d.ts +0 -1
- package/dist/agent/type-guards.js +1 -2
- package/dist/agent/types.d.ts +1 -2
- package/dist/agent/types.js +0 -1
- package/dist/{config-loader.d.ts → agent/workspace-resources.d.ts} +3 -10
- package/dist/{config-loader.js → agent/workspace-resources.js} +3 -19
- package/dist/index.d.ts +9 -9
- package/dist/index.js +9 -9
- package/dist/log.d.ts +0 -1
- package/dist/log.js +0 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.js +0 -1
- package/dist/memory/bootstrap.d.ts +0 -1
- package/dist/memory/bootstrap.js +0 -1
- package/dist/memory/candidates.d.ts +0 -1
- package/dist/memory/candidates.js +0 -1
- package/dist/memory/chinese-words.d.ts +0 -1
- package/dist/memory/chinese-words.js +64 -1
- package/dist/memory/consolidation.d.ts +0 -1
- package/dist/memory/consolidation.js +2 -3
- package/dist/memory/files.d.ts +0 -1
- package/dist/memory/files.js +0 -1
- package/dist/memory/lifecycle.d.ts +1 -2
- package/dist/memory/lifecycle.js +0 -1
- package/dist/memory/recall.d.ts +1 -1
- package/dist/memory/recall.js +77 -11
- package/dist/memory/session.d.ts +0 -1
- package/dist/memory/session.js +2 -3
- package/dist/{sidecar-worker.d.ts → memory/sidecar-worker.d.ts} +0 -1
- package/dist/{sidecar-worker.js → memory/sidecar-worker.js} +1 -2
- package/dist/models/api-keys.d.ts +7 -0
- package/dist/models/api-keys.js +16 -0
- package/dist/{model-utils.d.ts → models/utils.d.ts} +1 -2
- package/dist/{model-utils.js → models/utils.js} +0 -1
- package/dist/paths.d.ts +0 -1
- package/dist/paths.js +0 -1
- package/dist/runtime/bootstrap.d.ts +0 -1
- package/dist/runtime/bootstrap.js +2 -3
- package/dist/runtime/delivery.d.ts +0 -1
- package/dist/runtime/delivery.js +0 -1
- package/dist/runtime/dingtalk.d.ts +0 -1
- package/dist/runtime/dingtalk.js +1 -2
- package/dist/runtime/events.d.ts +0 -1
- package/dist/runtime/events.js +0 -1
- package/dist/runtime/store.d.ts +0 -1
- package/dist/runtime/store.js +0 -1
- package/dist/sandbox.d.ts +0 -1
- package/dist/sandbox.js +1 -2
- package/dist/{context.d.ts → settings.d.ts} +1 -2
- package/dist/{context.js → settings.js} +1 -2
- package/dist/{llm-json.d.ts → shared/llm-json.d.ts} +0 -1
- package/dist/{llm-json.js → shared/llm-json.js} +0 -1
- package/dist/shared/markdown-sections.d.ts +0 -1
- package/dist/shared/markdown-sections.js +0 -1
- package/dist/{shell-escape.d.ts → shared/shell-escape.d.ts} +0 -1
- package/dist/{shell-escape.js → shared/shell-escape.js} +0 -1
- package/dist/shared/text-utils.d.ts +0 -1
- package/dist/shared/text-utils.js +0 -1
- package/dist/shared/type-guards.d.ts +0 -1
- package/dist/shared/type-guards.js +0 -1
- package/dist/shared/types.d.ts +0 -1
- package/dist/shared/types.js +0 -1
- package/dist/subagents/discovery.d.ts +0 -1
- package/dist/subagents/discovery.js +1 -2
- package/dist/subagents/tool.d.ts +1 -2
- package/dist/subagents/tool.js +1 -2
- package/dist/tools/attach.d.ts +0 -1
- package/dist/tools/attach.js +0 -1
- package/dist/tools/bash.d.ts +0 -1
- package/dist/tools/bash.js +0 -1
- package/dist/tools/edit.d.ts +0 -1
- package/dist/tools/edit.js +1 -2
- package/dist/tools/index.d.ts +1 -2
- package/dist/tools/index.js +0 -1
- package/dist/tools/read.d.ts +0 -1
- package/dist/tools/read.js +1 -2
- package/dist/tools/truncate.d.ts +0 -1
- package/dist/tools/truncate.js +0 -1
- package/dist/tools/write-content.d.ts +0 -1
- package/dist/tools/write-content.js +1 -2
- package/dist/tools/write.d.ts +0 -1
- package/dist/tools/write.js +0 -1
- package/package.json +9 -3
- package/CHANGELOG.md +0 -47
- package/dist/agent/channel-runner.d.ts.map +0 -1
- package/dist/agent/channel-runner.js.map +0 -1
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/progress-formatter.d.ts.map +0 -1
- package/dist/agent/progress-formatter.js.map +0 -1
- package/dist/agent/run-queue.d.ts.map +0 -1
- package/dist/agent/run-queue.js.map +0 -1
- package/dist/agent/runner-factory.d.ts.map +0 -1
- package/dist/agent/runner-factory.js.map +0 -1
- package/dist/agent/session-events.d.ts.map +0 -1
- package/dist/agent/session-events.js.map +0 -1
- package/dist/agent/type-guards.d.ts.map +0 -1
- package/dist/agent/type-guards.js.map +0 -1
- package/dist/agent/types.d.ts.map +0 -1
- package/dist/agent/types.js.map +0 -1
- package/dist/agent.d.ts +0 -3
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -2
- package/dist/agent.js.map +0 -1
- package/dist/command-extension.d.ts.map +0 -1
- package/dist/command-extension.js.map +0 -1
- package/dist/commands.d.ts.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js.map +0 -1
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/llm-json.d.ts.map +0 -1
- package/dist/llm-json.js.map +0 -1
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js.map +0 -1
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/memory/bootstrap.d.ts.map +0 -1
- package/dist/memory/bootstrap.js.map +0 -1
- package/dist/memory/candidates.d.ts.map +0 -1
- package/dist/memory/candidates.js.map +0 -1
- package/dist/memory/chinese-words.d.ts.map +0 -1
- package/dist/memory/chinese-words.js.map +0 -1
- package/dist/memory/consolidation.d.ts.map +0 -1
- package/dist/memory/consolidation.js.map +0 -1
- package/dist/memory/files.d.ts.map +0 -1
- package/dist/memory/files.js.map +0 -1
- package/dist/memory/lifecycle.d.ts.map +0 -1
- package/dist/memory/lifecycle.js.map +0 -1
- package/dist/memory/recall.d.ts.map +0 -1
- package/dist/memory/recall.js.map +0 -1
- package/dist/memory/session.d.ts.map +0 -1
- package/dist/memory/session.js.map +0 -1
- package/dist/model-utils.d.ts.map +0 -1
- package/dist/model-utils.js.map +0 -1
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/prompt-builder.d.ts.map +0 -1
- package/dist/prompt-builder.js.map +0 -1
- package/dist/runtime/bootstrap.d.ts.map +0 -1
- package/dist/runtime/bootstrap.js.map +0 -1
- package/dist/runtime/delivery.d.ts.map +0 -1
- package/dist/runtime/delivery.js.map +0 -1
- package/dist/runtime/dingtalk.d.ts.map +0 -1
- package/dist/runtime/dingtalk.js.map +0 -1
- package/dist/runtime/events.d.ts.map +0 -1
- package/dist/runtime/events.js.map +0 -1
- package/dist/runtime/store.d.ts.map +0 -1
- package/dist/runtime/store.js.map +0 -1
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js.map +0 -1
- package/dist/shared/markdown-sections.d.ts.map +0 -1
- package/dist/shared/markdown-sections.js.map +0 -1
- package/dist/shared/text-utils.d.ts.map +0 -1
- package/dist/shared/text-utils.js.map +0 -1
- package/dist/shared/type-guards.d.ts.map +0 -1
- package/dist/shared/type-guards.js.map +0 -1
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/types.js.map +0 -1
- package/dist/shell-escape.d.ts.map +0 -1
- package/dist/shell-escape.js.map +0 -1
- package/dist/sidecar-worker.d.ts.map +0 -1
- package/dist/sidecar-worker.js.map +0 -1
- package/dist/subagents/discovery.d.ts.map +0 -1
- package/dist/subagents/discovery.js.map +0 -1
- package/dist/subagents/tool.d.ts.map +0 -1
- package/dist/subagents/tool.js.map +0 -1
- package/dist/tools/attach.d.ts.map +0 -1
- package/dist/tools/attach.js.map +0 -1
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/edit.d.ts.map +0 -1
- package/dist/tools/edit.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/read.d.ts.map +0 -1
- package/dist/tools/read.js.map +0 -1
- package/dist/tools/truncate.d.ts.map +0 -1
- package/dist/tools/truncate.js.map +0 -1
- package/dist/tools/write-content.d.ts.map +0 -1
- package/dist/tools/write-content.js.map +0 -1
- package/dist/tools/write.d.ts.map +0 -1
- package/dist/tools/write.js.map +0 -1
- package/docs/memory-audit.md +0 -330
- package/docs/memory-optimization-round2.md +0 -319
- package/docs/specs/001-implement-memory/memory-rfc.md +0 -297
- package/docs/specs/002-subagent/pi-subagent-analyse.txt +0 -190
- package/docs/specs/002-subagent/pi-subagent-design.txt +0 -266
- package/docs/specs/002-subagent/pi-subagent-phase1-plan.txt +0 -529
- package/docs/specs/003-improve-memory/design.md +0 -537
- package/docs/specs/003-improve-memory/interfaces-and-tests.md +0 -473
- 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.
|