@yun-zero/claw-memory 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.claude/settings.local.json +68 -0
  2. package/README.md +323 -0
  3. package/dist/config/llm.d.ts +13 -0
  4. package/dist/config/llm.d.ts.map +1 -0
  5. package/dist/config/llm.js +96 -0
  6. package/dist/config/llm.js.map +1 -0
  7. package/dist/config/plugin.d.ts +15 -0
  8. package/dist/config/plugin.d.ts.map +1 -0
  9. package/dist/config/plugin.js +32 -0
  10. package/dist/config/plugin.js.map +1 -0
  11. package/dist/db/entityRepository.d.ts +21 -0
  12. package/dist/db/entityRepository.d.ts.map +1 -0
  13. package/dist/db/entityRepository.js +55 -0
  14. package/dist/db/entityRepository.js.map +1 -0
  15. package/dist/db/repository.d.ts +22 -0
  16. package/dist/db/repository.d.ts.map +1 -0
  17. package/dist/db/repository.js +77 -0
  18. package/dist/db/repository.js.map +1 -0
  19. package/dist/db/schema.d.ts +5 -0
  20. package/dist/db/schema.d.ts.map +1 -0
  21. package/dist/db/schema.js +112 -0
  22. package/dist/db/schema.js.map +1 -0
  23. package/dist/db/todoRepository.d.ts +26 -0
  24. package/dist/db/todoRepository.d.ts.map +1 -0
  25. package/dist/db/todoRepository.js +54 -0
  26. package/dist/db/todoRepository.js.map +1 -0
  27. package/dist/hooks/bootstrap.d.ts +3 -0
  28. package/dist/hooks/bootstrap.d.ts.map +1 -0
  29. package/dist/hooks/bootstrap.js +28 -0
  30. package/dist/hooks/bootstrap.js.map +1 -0
  31. package/dist/hooks/message.d.ts +18 -0
  32. package/dist/hooks/message.d.ts.map +1 -0
  33. package/dist/hooks/message.js +52 -0
  34. package/dist/hooks/message.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +46 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/mcp/tools.d.ts +26 -0
  40. package/dist/mcp/tools.d.ts.map +1 -0
  41. package/dist/mcp/tools.js +360 -0
  42. package/dist/mcp/tools.js.map +1 -0
  43. package/dist/plugin.d.ts +18 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +62 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/services/entityGraphService.d.ts +87 -0
  48. package/dist/services/entityGraphService.d.ts.map +1 -0
  49. package/dist/services/entityGraphService.js +271 -0
  50. package/dist/services/entityGraphService.js.map +1 -0
  51. package/dist/services/memory.d.ts +26 -0
  52. package/dist/services/memory.d.ts.map +1 -0
  53. package/dist/services/memory.js +281 -0
  54. package/dist/services/memory.js.map +1 -0
  55. package/dist/services/memoryIndex.d.ts +34 -0
  56. package/dist/services/memoryIndex.d.ts.map +1 -0
  57. package/dist/services/memoryIndex.js +100 -0
  58. package/dist/services/memoryIndex.js.map +1 -0
  59. package/dist/services/metadataExtractor.d.ts +16 -0
  60. package/dist/services/metadataExtractor.d.ts.map +1 -0
  61. package/dist/services/metadataExtractor.js +75 -0
  62. package/dist/services/metadataExtractor.js.map +1 -0
  63. package/dist/services/retrieval.d.ts +24 -0
  64. package/dist/services/retrieval.d.ts.map +1 -0
  65. package/dist/services/retrieval.js +40 -0
  66. package/dist/services/retrieval.js.map +1 -0
  67. package/dist/services/scheduler.d.ts +122 -0
  68. package/dist/services/scheduler.d.ts.map +1 -0
  69. package/dist/services/scheduler.js +434 -0
  70. package/dist/services/scheduler.js.map +1 -0
  71. package/dist/services/summarizer.d.ts +43 -0
  72. package/dist/services/summarizer.d.ts.map +1 -0
  73. package/dist/services/summarizer.js +252 -0
  74. package/dist/services/summarizer.js.map +1 -0
  75. package/dist/services/tagService.d.ts +64 -0
  76. package/dist/services/tagService.d.ts.map +1 -0
  77. package/dist/services/tagService.js +281 -0
  78. package/dist/services/tagService.js.map +1 -0
  79. package/dist/tools/memory.d.ts +3 -0
  80. package/dist/tools/memory.d.ts.map +1 -0
  81. package/dist/tools/memory.js +114 -0
  82. package/dist/tools/memory.js.map +1 -0
  83. package/dist/types.d.ts +128 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +6 -0
  86. package/dist/types.js.map +1 -0
  87. package/docs/plans/2026-03-02-claw-memory-design.md +445 -0
  88. package/docs/plans/2026-03-02-incremental-summary-design.md +157 -0
  89. package/docs/plans/2026-03-02-incremental-summary-implementation.md +468 -0
  90. package/docs/plans/2026-03-02-memory-index-design.md +163 -0
  91. package/docs/plans/2026-03-02-memory-index-implementation.md +836 -0
  92. package/docs/plans/2026-03-02-mvp-implementation.md +1703 -0
  93. package/docs/plans/2026-03-02-testing-implementation.md +395 -0
  94. package/docs/plans/2026-03-02-testing-plan.md +93 -0
  95. package/docs/plans/2026-03-03-claw-memory-openclaw-plugin-design.md +285 -0
  96. package/docs/plans/2026-03-03-claw-memory-plugin-implementation.md +642 -0
  97. package/docs/plans/2026-03-03-entity-graph-design.md +121 -0
  98. package/docs/plans/2026-03-03-entity-graph-implementation.md +687 -0
  99. package/docs/plans/2026-03-03-llm-generic-config-design.md +43 -0
  100. package/docs/plans/2026-03-03-llm-generic-config-implementation.md +186 -0
  101. package/docs/plans/2026-03-03-memory-e2e-stress-test-design.md +110 -0
  102. package/docs/plans/2026-03-03-memory-e2e-stress-test-implementation.md +464 -0
  103. package/docs/plans/2026-03-03-minimax-llm-fix.md +156 -0
  104. package/docs/plans/2026-03-03-scheduler-design.md +165 -0
  105. package/docs/plans/2026-03-03-scheduler-implementation.md +777 -0
  106. package/docs/plans/2026-03-03-tags-visualization-design.md +73 -0
  107. package/docs/plans/2026-03-03-tags-visualization-implementation.md +539 -0
  108. package/openclaw.plugin.json +11 -0
  109. package/package.json +41 -0
  110. package/src/config/llm.ts +129 -0
  111. package/src/config/plugin.ts +47 -0
  112. package/src/db/entityRepository.ts +80 -0
  113. package/src/db/repository.ts +106 -0
  114. package/src/db/schema.ts +121 -0
  115. package/src/db/todoRepository.ts +76 -0
  116. package/src/hooks/bootstrap.ts +36 -0
  117. package/src/hooks/message.ts +84 -0
  118. package/src/index.ts +50 -0
  119. package/src/plugin.ts +85 -0
  120. package/src/services/entityGraphService.ts +367 -0
  121. package/src/services/memory.ts +338 -0
  122. package/src/services/memoryIndex.ts +140 -0
  123. package/src/services/metadataExtractor.ts +89 -0
  124. package/src/services/retrieval.ts +71 -0
  125. package/src/services/scheduler.ts +529 -0
  126. package/src/services/summarizer.ts +318 -0
  127. package/src/services/tagService.ts +335 -0
  128. package/src/tools/memory.ts +137 -0
  129. package/src/types.ts +139 -0
  130. package/tsconfig.json +20 -0
  131. package/vitest.config.ts +16 -0
@@ -0,0 +1,468 @@
1
+ # 增量更新整体记忆摘要实现计划
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** 在会话结束时,一次 LLM 调用同时提取当前会话元数据并整合整体摘要,后续查询直接返回缓存摘要。
6
+
7
+ **Architecture:** 修改 memories 表添加 integrated_summary 字段,更新 MetadataExtractor prompt 支持传入已有摘要,修改 MemoryService 在保存时获取和更新摘要。
8
+
9
+ **Tech Stack:** TypeScript, better-sqlite3, LLM API
10
+
11
+ ---
12
+
13
+ ## Task 1: 添加 integrated_summary 字段到数据库
14
+
15
+ **Files:**
16
+ - Modify: `src/db/schema.ts:6-20`
17
+ - Test: `tests/db/schema.test.ts`
18
+
19
+ **Step 1: 修改 schema 添加字段**
20
+
21
+ ```typescript
22
+ // src/db/schema.ts memories 表中添加
23
+ db.exec(`
24
+ CREATE TABLE IF NOT EXISTS memories (
25
+ id TEXT PRIMARY KEY,
26
+ content_path TEXT NOT NULL,
27
+ summary TEXT,
28
+ integrated_summary JSON, -- 新增
29
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
30
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
31
+ token_count INTEGER DEFAULT 0,
32
+ importance REAL DEFAULT 0.5,
33
+ access_count INTEGER DEFAULT 0,
34
+ last_accessed_at TIMESTAMP,
35
+ is_archived BOOLEAN DEFAULT FALSE,
36
+ is_duplicate BOOLEAN DEFAULT FALSE,
37
+ duplicate_of TEXT
38
+ )
39
+ `);
40
+ ```
41
+
42
+ **Step 2: 运行测试验证**
43
+
44
+ ```bash
45
+ npm test tests/db/schema.test.ts
46
+ ```
47
+ Expected: PASS
48
+
49
+ **Step 3: 提交**
50
+
51
+ ```bash
52
+ git add src/db/schema.ts
53
+ git commit -m "feat: add integrated_summary field to memories table"
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Task 2: 更新 TypeScript 类型定义
59
+
60
+ **Files:**
61
+ - Modify: `src/types.ts:6-19`
62
+
63
+ **Step 1: 添加 IntegratedSummary 接口和字段**
64
+
65
+ ```typescript
66
+ // src/types.ts
67
+
68
+ export interface IntegratedSummary {
69
+ active_areas: string[];
70
+ key_topics: string[];
71
+ recent_summary: string;
72
+ }
73
+
74
+ export interface Memory {
75
+ id: string;
76
+ contentPath: string;
77
+ summary: string | null;
78
+ integratedSummary: IntegratedSummary | null; // 新增
79
+ createdAt: Date;
80
+ updatedAt: Date;
81
+ tokenCount: number;
82
+ importance: number;
83
+ accessCount: number;
84
+ lastAccessedAt: Date | null;
85
+ isArchived: boolean;
86
+ isDuplicate: boolean;
87
+ duplicateOf: string | null;
88
+ }
89
+ ```
90
+
91
+ **Step 2: 运行构建验证**
92
+
93
+ ```bash
94
+ npm run build
95
+ ```
96
+ Expected: PASS
97
+
98
+ **Step 3: 提交**
99
+
100
+ ```bash
101
+ git add src/types.ts
102
+ git commit -m "feat: add IntegratedSummary type definition"
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Task 3: 更新 Repository 支持 integrated_summary
108
+
109
+ **Files:**
110
+ - Modify: `src/db/repository.ts`
111
+ - Test: `tests/db/repository.test.ts`
112
+
113
+ **Step 1: 更新 CreateMemoryInput 和 insert**
114
+
115
+ ```typescript
116
+ // src/db/repository.ts
117
+
118
+ export interface CreateMemoryInput {
119
+ contentPath: string;
120
+ summary?: string;
121
+ integratedSummary?: IntegratedSummary; // 新增
122
+ importance?: number;
123
+ tokenCount?: number;
124
+ }
125
+
126
+ // create 方法中
127
+ this.db.prepare(`
128
+ INSERT INTO memories (id, content_path, summary, integrated_summary, importance, token_count, created_at, updated_at)
129
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
130
+ `).run(
131
+ id,
132
+ input.contentPath,
133
+ input.summary || null,
134
+ input.integratedSummary ? JSON.stringify(input.integratedSummary) : null, // 新增
135
+ input.importance ?? 0.5,
136
+ input.tokenCount ?? 0,
137
+ now.toISOString(),
138
+ now.toISOString()
139
+ );
140
+ ```
141
+
142
+ **Step 2: 更新 mapRowToMemory**
143
+
144
+ ```typescript
145
+ // mapRowToMemory 方法中添加
146
+ integratedSummary: row.integrated_summary ? JSON.parse(row.integrated_summary) : null,
147
+ ```
148
+
149
+ **Step 3: 添加测试**
150
+
151
+ ```typescript
152
+ // tests/db/repository.test.ts
153
+ it('should save and retrieve integrated summary', () => {
154
+ const memory = repo.create({
155
+ contentPath: '/test/path.md',
156
+ summary: 'Test summary',
157
+ integratedSummary: {
158
+ active_areas: ['技术/AI (5)'],
159
+ key_topics: ['React', 'OpenClaw'],
160
+ recent_summary: '本周讨论了AI技术'
161
+ }
162
+ });
163
+
164
+ const found = repo.findById(memory.id);
165
+ expect(found.integratedSummary).toEqual({
166
+ active_areas: ['技术/AI (5)'],
167
+ key_topics: ['React', 'OpenClaw'],
168
+ recent_summary: '本周讨论了AI技术'
169
+ });
170
+ });
171
+ ```
172
+
173
+ **Step 4: 运行测试**
174
+
175
+ ```bash
176
+ npm test tests/db/repository.test.ts
177
+ ```
178
+ Expected: PASS
179
+
180
+ **Step 5: 提交**
181
+
182
+ ```bash
183
+ git add src/db/repository.ts tests/db/repository.test.ts
184
+ git commit -m "feat: support integrated_summary in repository"
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Task 4: 更新 MetadataExtractor 支持已有摘要
190
+
191
+ **Files:**
192
+ - Modify: `src/services/metadataExtractor.ts`
193
+
194
+ **Step 1: 更新 extract 方法签名和 prompt**
195
+
196
+ ```typescript
197
+ // src/services/metadataExtractor.ts
198
+
199
+ export interface ExtractedMetadata {
200
+ tags: string[];
201
+ keywords: string[];
202
+ subjects: string[];
203
+ importance: number;
204
+ summary: string;
205
+ integratedSummary: IntegratedSummary;
206
+ }
207
+
208
+ const EXTRACTION_PROMPT = `请从以下对话内容中提取结构化元数据,并整合已有的整体摘要:
209
+
210
+ 当前对话内容:
211
+ {content}
212
+
213
+ 已有整体摘要(请在此基础上增量更新):
214
+ {existing_summary}
215
+
216
+ 请以 JSON 格式返回:
217
+ {
218
+ "tags": ["一级分类/二级分类"],
219
+ "keywords": ["关键词1", "关键词2"],
220
+ "subjects": ["主题1"],
221
+ "importance": 0.0-1.0,
222
+ "summary": "当前对话的一句话摘要",
223
+ "integrated_summary": {
224
+ "active_areas": ["领域名 (出现次数)"],
225
+ "key_topics": ["主题1", "主题2"],
226
+ "recent_summary": "整体摘要自然语言描述"
227
+ }
228
+ }
229
+
230
+ 注意:
231
+ - tags 使用层级结构
232
+ - integrated_summary 需整合历史信息,在已有基础上增加新领域
233
+ - 只返回 JSON,不要其他内容`;
234
+
235
+ export class MetadataExtractor {
236
+ async extract(content: string, existingSummary?: IntegratedSummary): Promise<ExtractedMetadata> {
237
+ let existingSummaryText = '无';
238
+ if (existingSummary) {
239
+ existingSummaryText = `活跃领域: ${existingSummary.active_areas.join(', ')}\n关键词: ${existingSummary.key_topics.join(', ')}\n近期摘要: ${existingSummary.recent_summary}`;
240
+ }
241
+
242
+ const prompt = EXTRACTION_PROMPT
243
+ .replace('{content}', content)
244
+ .replace('{existing_summary}', existingSummaryText);
245
+
246
+ try {
247
+ const response = await generateSummaryWithLLM(prompt);
248
+ return this.parseLLMResponse(response);
249
+ } catch (error) {
250
+ console.warn('LLM extraction failed:', error);
251
+ return this.fallbackExtract(content);
252
+ }
253
+ }
254
+
255
+ private fallbackExtract(content: string): ExtractedMetadata {
256
+ return {
257
+ tags: [],
258
+ keywords: [],
259
+ subjects: [],
260
+ importance: 0.5,
261
+ summary: content.substring(0, 100),
262
+ integratedSummary: {
263
+ active_areas: [],
264
+ key_topics: [],
265
+ recent_summary: ''
266
+ }
267
+ };
268
+ }
269
+ }
270
+ ```
271
+
272
+ **Step 2: 运行测试**
273
+
274
+ ```bash
275
+ npm test tests/services/metadataExtractor.test.ts
276
+ ```
277
+ Expected: PASS
278
+
279
+ **Step 3: 提交**
280
+
281
+ ```bash
282
+ git add src/services/metadataExtractor.ts
283
+ git commit -m "feat: support existing summary in metadata extraction"
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Task 5: 修改 MemoryService 集成摘要更新
289
+
290
+ **Files:**
291
+ - Modify: `src/services/memory.ts`
292
+
293
+ **Step 1: 添加获取最新摘要的方法**
294
+
295
+ ```typescript
296
+ // src/services/memory.ts
297
+
298
+ // 在 MemoryService 类中添加
299
+ async getLatestIntegratedSummary(): Promise<IntegratedSummary | null> {
300
+ const memories = this.memoryRepo.findAll(1);
301
+ if (memories.length === 0) return null;
302
+ return memories[0].integratedSummary;
303
+ }
304
+ ```
305
+
306
+ **Step 2: 修改 saveMemory 方法**
307
+
308
+ ```typescript
309
+ async saveMemory(input: SaveMemoryInput): Promise<Memory> {
310
+ const { content, metadata } = input;
311
+
312
+ // ... 现有代码:文件保存 ...
313
+
314
+ // 获取已有的整体摘要
315
+ const existingSummary = await this.getLatestIntegratedSummary();
316
+
317
+ // 调用 LLM 提取元数据(传入已有摘要)
318
+ const extracted = content.trim()
319
+ ? await this.extractor.extract(content, existingSummary || undefined)
320
+ : { tags: [], keywords: [], subjects: [], importance: 0.5, summary: '', integratedSummary: existingSummary || { active_areas: [], key_topics: [], recent_summary: '' } };
321
+
322
+ // 合并元数据
323
+ const mergedMetadata = {
324
+ tags: extracted.tags,
325
+ keywords: extracted.keywords,
326
+ subjects: extracted.subjects,
327
+ importance: extracted.importance,
328
+ summary: extracted.summary,
329
+ ...metadata
330
+ };
331
+
332
+ // 创建记忆记录(包含 integrated_summary)
333
+ const memoryInput: CreateMemoryInput = {
334
+ contentPath,
335
+ summary: mergedMetadata.summary || undefined,
336
+ integratedSummary: extracted.integratedSummary, // 新增
337
+ importance: clampedImportance ?? 0.5,
338
+ tokenCount: this.estimateTokens(content)
339
+ };
340
+
341
+ const memory = this.memoryRepo.create(memoryInput);
342
+
343
+ // ... 现有代码:实体处理 ...
344
+
345
+ return memory;
346
+ }
347
+ ```
348
+
349
+ **Step 3: 运行测试**
350
+
351
+ ```bash
352
+ npm test tests/services/memory.test.ts
353
+ ```
354
+ Expected: PASS
355
+
356
+ **Step 4: 提交**
357
+
358
+ ```bash
359
+ git add src/services/memory.ts
360
+ git commit -m "feat: integrate summary update in saveMemory"
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Task 6: 更新 get_memory_index 返回缓存摘要
366
+
367
+ **Files:**
368
+ - Modify: `src/services/memoryIndex.ts`
369
+ - Test: `tests/mcp/memoryIndex.test.ts`
370
+
371
+ **Step 1: 修改 getMemoryIndex 函数**
372
+
373
+ ```typescript
374
+ // src/services/memoryIndex.ts
375
+
376
+ export async function getMemoryIndex(db: Database.Database, options: MemoryIndexOptions): Promise<MemoryIndex> {
377
+ const { startDate, endDate } = calculatePeriodRange(options.period, options.date);
378
+
379
+ // ... 现有代码:获取 tags, keywords ...
380
+
381
+ // 获取缓存的整体摘要(从最新的 memory)
382
+ const memoryRepo = new MemoryRepository(db);
383
+ const latestMemory = memoryRepo.findAll(1)[0];
384
+ const integratedSummary = latestMemory?.integratedSummary || null;
385
+
386
+ return {
387
+ period: { start: startDate, end: endDate },
388
+ activeAreas: { tags, keywords },
389
+ todos,
390
+ recentActivity,
391
+ integratedSummary // 新增
392
+ };
393
+ }
394
+ ```
395
+
396
+ **Step 2: 更新接口定义**
397
+
398
+ ```typescript
399
+ export interface MemoryIndex {
400
+ period: { start: string; end: string };
401
+ activeAreas: {
402
+ tags: { name: string; count: number }[];
403
+ keywords: string[];
404
+ };
405
+ todos: { id: string; content: string; period: string }[];
406
+ recentActivity: { date: string; summary: string }[];
407
+ integratedSummary?: { // 新增
408
+ active_areas: string[];
409
+ key_topics: string[];
410
+ recent_summary: string;
411
+ };
412
+ }
413
+ ```
414
+
415
+ **Step 3: 添加测试**
416
+
417
+ ```typescript
418
+ // tests/mcp/memoryIndex.test.ts
419
+ it('should return integrated summary from latest memory', async () => {
420
+ // 先保存一个带 integrated_summary 的 memory
421
+ const memoryService = new MemoryService(db, './test_memories');
422
+ await memoryService.saveMemory({
423
+ content: 'Test content',
424
+ metadata: { summary: 'Test' }
425
+ });
426
+
427
+ const result = await getMemoryIndex(db, { period: 'week' });
428
+ expect(result.integratedSummary).toBeDefined();
429
+ });
430
+ ```
431
+
432
+ **Step 4: 运行测试**
433
+
434
+ ```bash
435
+ npm test tests/mcp/memoryIndex.test.ts
436
+ ```
437
+ Expected: PASS
438
+
439
+ **Step 5: 提交**
440
+
441
+ ```bash
442
+ git add src/services/memoryIndex.ts tests/mcp/memoryIndex.test.ts
443
+ git commit -m "feat: return cached integrated summary in getMemoryIndex"
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Task 7: 完整测试验证
449
+
450
+ **Step 1: 运行所有测试**
451
+
452
+ ```bash
453
+ npm test
454
+ ```
455
+ Expected: PASS (所有测试)
456
+
457
+ **Step 2: 提交**
458
+
459
+ ```bash
460
+ git add -A
461
+ git commit -m "feat: implement incremental summary update
462
+
463
+ - Add integrated_summary field to memories table
464
+ - Update MetadataExtractor to accept existing summary
465
+ - Integrate summary update in saveMemory
466
+ - Return cached summary in getMemoryIndex"
467
+
468
+ ---
@@ -0,0 +1,163 @@
1
+ # 记忆索引摘要与自动提取功能设计
2
+
3
+ **日期**: 2026-03-02
4
+
5
+ ## 背景
6
+
7
+ 当前 claw-memory 系统存在以下问题:
8
+ 1. 标签和实体关系需要调用方手动传入,无法自动提取
9
+ 2. OpenClaw/Claude Code 不知道数据库中有什么记忆,对话开始时无法利用历史信息
10
+ 3. 缺少待办事项功能
11
+
12
+ ## 目标
13
+
14
+ 1. LLM 自动从 content 中提取 metadata(tags, keywords, subjects, importance, summary)
15
+ 2. 提供记忆索引摘要 API,供 OpenClaw Hook 在对话开始时获取
16
+ 3. 支持周期性待办事项(day/week/month)
17
+
18
+ ---
19
+
20
+ ## 功能设计
21
+
22
+ ### 1. LLM 自动提取元数据
23
+
24
+ #### 实现方式
25
+ - 在 `saveMemory` 时调用 LLM 提取完整 metadata
26
+ - 无论是否传入 metadata,都使用 LLM 提取的结果
27
+
28
+ #### 数据分层
29
+ ```
30
+ ┌─────────────────────────────────────────┐
31
+ │ 周期性总结数据 │
32
+ │ (time_buckets 表) │
33
+ ├─────────────────────────────────────────┤
34
+ │ LLM 提取的关系性数据 │
35
+ │ (memory_entities, entities 表) │
36
+ ├─────────────────────────────────────────┤
37
+ │ 原始对话数据 │
38
+ │ (memories.content_path 文件) │
39
+ └─────────────────────────────────────────┘
40
+ ```
41
+
42
+ #### 好处
43
+ - 原始数据永不丢失
44
+ - LLM 失败不影响基本功能
45
+ - 支持后续重新提取和修正
46
+
47
+ ### 2. 记忆索引摘要 API
48
+
49
+ #### 数据分层(按变化频率排序)
50
+ ```
51
+ 1. 时间范围 ─────── 固定(查询时确定)
52
+ 2. 活跃领域 ─────── 变化较慢(周/月)
53
+ 3. 待办事项 ─────── 变化中等(随时添加/完成)
54
+ 4. 最近动态 ─────── 变化频繁(每次对话)
55
+ ```
56
+
57
+ #### 摘要输出示例
58
+ ```
59
+ === 记忆索引 (2026-02-24 ~ 2026-03-02) ===
60
+
61
+ 【活跃领域】
62
+ - 技术/前端 (5), 项目/AI (3), 生活/旅行 (2)
63
+ - 关键词: React, TypeScript, Claude Code, OpenClaw
64
+
65
+ 【待办事项】
66
+ - [ ] 完成 OpenClaw 记忆系统集成
67
+ - [ ] 配置 MCP Webhook 触发规则
68
+ - [ ] 学习 React Server Components
69
+
70
+ 【最近动态】
71
+ - 今天: 讨论了 OpenClaw Hooks 机制
72
+ - 昨天: 保存了 React 组件设计笔记
73
+ - 前天: 查询了 Claude Code 使用文档
74
+ ```
75
+
76
+ #### MCP 工具
77
+ ```typescript
78
+ {
79
+ name: "get_memory_index",
80
+ params: {
81
+ period: "week", // day | week | month
82
+ date?: "2026-03-02", // 可选,默认今天
83
+ includeTodos: true, // 是否包含待办
84
+ includeRecent: true, // 是否包含最近动态
85
+ recentLimit: 5 // 最近动态数量
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### 3. 待办事项功能
91
+
92
+ #### 数据库设计
93
+ ```sql
94
+ CREATE TABLE todos (
95
+ id TEXT PRIMARY KEY,
96
+ content TEXT NOT NULL,
97
+ period TEXT, -- 'day' | 'week' | 'month'
98
+ period_date TEXT, -- 关联的日期
99
+ created_at TEXT,
100
+ completed_at TEXT,
101
+ memory_id TEXT -- 可选,关联到某个记忆
102
+ );
103
+ ```
104
+
105
+ #### MCP 工具
106
+ ```typescript
107
+ // 添加待办
108
+ {
109
+ name: "add_todo",
110
+ params: {
111
+ content: "完成某事",
112
+ period: "week",
113
+ period_date: "2026-03-02"
114
+ }
115
+ }
116
+
117
+ // 标记完成
118
+ {
119
+ name: "complete_todo",
120
+ params: {
121
+ id: "todo_id"
122
+ }
123
+ }
124
+
125
+ // 列出待办
126
+ {
127
+ name: "list_todos",
128
+ params: {
129
+ period: "week",
130
+ includeCompleted: false
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### 4. OpenClaw Hook 集成
136
+
137
+ ```typescript
138
+ // hook-session-memory 调用
139
+ await callTool("get_memory_index", {
140
+ period: "week",
141
+ includeTodos: true,
142
+ includeRecent: true
143
+ });
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 实现计划
149
+
150
+ ### Phase 1: LLM 自动提取
151
+ 1. 新增 `src/services/metadataExtractor.ts`
152
+ 2. 修改 `src/services/memory.ts` 集成 LLM 提取
153
+
154
+ ### Phase 2: 记忆索引 API
155
+ 1. 新增 todos 表 schema
156
+ 2. 新增 `TodoRepository`
157
+ 3. 新增 `get_memory_index` MCP 工具
158
+
159
+ ### Phase 3: 待办事项 MCP 工具
160
+ 1. 新增 `add_todo`, `complete_todo`, `list_todos` 工具
161
+
162
+ ### Phase 4: OpenClaw Hook(可选)
163
+ 1. 提供自定义 Hook 示例代码