@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,464 @@
1
+ # Memory E2E & Stress Test Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Implement E2E and stress tests for claw-memory component with real conversation logs and batch LLM calls for retrieval accuracy evaluation.
6
+
7
+ **Architecture:** Create test infrastructure with fixtures, test runners, and evaluation utilities. Use batch LLM calls to reduce API usage during stress test.
8
+
9
+ **Tech Stack:** TypeScript, Vitest, better-sqlite3
10
+
11
+ ---
12
+
13
+ ## Task 1: Create Test Fixtures Directory and Sample Data
14
+
15
+ **Files:**
16
+ - Create: `test/fixtures/conversations.json`
17
+ - Create: `test/fixtures/ground-truth.json`
18
+
19
+ **Step 1: Create fixtures directory**
20
+
21
+ Run: `mkdir -p test/fixtures`
22
+
23
+ **Step 2: Create sample conversations JSON**
24
+
25
+ Write `test/fixtures/conversations.json`:
26
+
27
+ ```json
28
+ {
29
+ "conversations": [
30
+ {
31
+ "id": "conv-001",
32
+ "domain": "technology",
33
+ "messages": [
34
+ {
35
+ "role": "user",
36
+ "content": "How do I optimize React component re-renders?"
37
+ },
38
+ {
39
+ "role": "assistant",
40
+ "content": "Use React.memo, useMemo, and useCallback to prevent unnecessary re-renders. Also consider lifting state up or using context properly."
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "id": "conv-002",
46
+ "domain": "database",
47
+ "messages": [
48
+ {
49
+ "role": "user",
50
+ "content": "How to optimize PostgreSQL query performance?"
51
+ },
52
+ {
53
+ "role": "assistant",
54
+ "content": "Use EXPLAIN ANALYZE to identify slow queries, add indexes on frequently queried columns, and consider partitioning large tables."
55
+ }
56
+ ]
57
+ }
58
+ ]
59
+ }
60
+ ```
61
+
62
+ **Step 3: Create ground truth for retrieval evaluation**
63
+
64
+ Write `test/fixtures/ground-truth.json`:
65
+
66
+ ```json
67
+ {
68
+ "queries": [
69
+ {
70
+ "query": "React 组件优化",
71
+ "expected_domain": "technology",
72
+ "expected_conv_ids": ["conv-001"]
73
+ },
74
+ {
75
+ "query": "数据库性能",
76
+ "expected_domain": "database",
77
+ "expected_conv_ids": ["conv-002"]
78
+ }
79
+ ]
80
+ }
81
+ ```
82
+
83
+ **Step 4: Commit**
84
+
85
+ Run: `git add test/fixtures/ && git commit -m "test: add sample conversation fixtures"`
86
+
87
+ ---
88
+
89
+ ## Task 2: Create Test Utilities - Database Setup & Batch LLM
90
+
91
+ **Files:**
92
+ - Create: `test/utils/db.ts`
93
+ - Create: `test/utils/llm.ts`
94
+
95
+ **Step 1: Create test database utility**
96
+
97
+ Write `test/utils/db.ts`:
98
+
99
+ ```typescript
100
+ import Database from 'better-sqlite3';
101
+ import { getDatabase } from '../../src/db/schema.js';
102
+ import path from 'path';
103
+ import fs from 'fs';
104
+
105
+ const TEST_DB_DIR = path.join(process.cwd(), 'test', 'data');
106
+ const TEST_DB_PATH = path.join(TEST_DB_DIR, 'test-memory.db');
107
+
108
+ export function setupTestDB(): Database.Database {
109
+ if (!fs.existsSync(TEST_DB_DIR)) {
110
+ fs.mkdirSync(TEST_DB_DIR, { recursive: true });
111
+ }
112
+ if (fs.existsSync(TEST_DB_PATH)) {
113
+ fs.unlinkSync(TEST_DB_PATH);
114
+ }
115
+ return getDatabase(TEST_DB_PATH);
116
+ }
117
+
118
+ export function cleanupTestDB(): void {
119
+ if (fs.existsSync(TEST_DB_PATH)) {
120
+ fs.unlinkSync(TEST_DB_PATH);
121
+ }
122
+ }
123
+ ```
124
+
125
+ **Step 2: Create batch LLM utility**
126
+
127
+ Write `test/utils/llm.ts`:
128
+
129
+ ```typescript
130
+ import type { MemoryMetadata } from '../../src/types.js';
131
+
132
+ interface BatchExtractResult {
133
+ contents: string[];
134
+ metadatas: MemoryMetadata[];
135
+ }
136
+
137
+ export async function batchExtractMetadata(
138
+ contents: string[],
139
+ _llmClient: any
140
+ ): Promise<BatchExtractResult> {
141
+ // Placeholder: join contents and extract metadata in batch
142
+ // In real implementation, call LLM once with all contents
143
+ const metadatas: MemoryMetadata[] = contents.map((content) => ({
144
+ tags: [],
145
+ subjects: [],
146
+ keywords: [],
147
+ importance: 0.5,
148
+ summary: content.substring(0, 100)
149
+ }));
150
+
151
+ return { contents, metadatas };
152
+ }
153
+ ```
154
+
155
+ **Step 3: Commit**
156
+
157
+ Run: `git add test/utils/ && git commit -m "test: add test utilities for DB and batch LLM"`
158
+
159
+ ---
160
+
161
+ ## Task 3: Create E2E Test - Full Workflow
162
+
163
+ **Files:**
164
+ - Create: `test/e2e/memory-workflow.test.ts`
165
+
166
+ **Step 1: Write failing test**
167
+
168
+ Write `test/e2e/memory-workflow.test.ts`:
169
+
170
+ ```typescript
171
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
172
+ import { setupTestDB, cleanupTestDB } from '../utils/db.js';
173
+ import { MemoryService } from '../../src/services/memory.js';
174
+ import type { Database } from 'better-sqlite3';
175
+
176
+ describe('Memory E2E Workflow', () => {
177
+ let db: Database.Database;
178
+ let memoryService: MemoryService;
179
+ const dataDir = './test/data';
180
+
181
+ beforeEach(() => {
182
+ db = setupTestDB();
183
+ memoryService = new MemoryService(db, dataDir);
184
+ });
185
+
186
+ afterEach(() => {
187
+ cleanupTestDB();
188
+ });
189
+
190
+ it('should save memory and retrieve it', async () => {
191
+ // Save memory
192
+ const result = await memoryService.saveMemory({
193
+ content: 'React uses virtual DOM to optimize rendering',
194
+ metadata: {
195
+ tags: ['技术', '前端', 'React'],
196
+ subjects: ['React'],
197
+ keywords: ['virtual DOM', 'rendering'],
198
+ importance: 0.8,
199
+ summary: 'React rendering optimization'
200
+ }
201
+ });
202
+
203
+ expect(result.id).toBeDefined();
204
+
205
+ // Search memory
206
+ const searchResults = await memoryService.searchMemory({
207
+ query: 'React',
208
+ limit: 10,
209
+ timeRange: 'all'
210
+ });
211
+
212
+ expect(searchResults.length).toBeGreaterThan(0);
213
+ expect(searchResults[0].content).toContain('React');
214
+ });
215
+
216
+ it('should get context for query', async () => {
217
+ await memoryService.saveMemory({
218
+ content: 'Use React.memo to prevent unnecessary re-renders'
219
+ });
220
+
221
+ const context = await memoryService.getContext({
222
+ query: 'React optimization',
223
+ maxTokens: 1000
224
+ });
225
+
226
+ expect(context).toBeDefined();
227
+ });
228
+
229
+ it('should get summary for period', async () => {
230
+ await memoryService.saveMemory({
231
+ content: 'Meeting: discuss project timeline'
232
+ });
233
+
234
+ const summary = await memoryService.getSummary('day');
235
+ expect(summary).toBeDefined();
236
+ });
237
+ });
238
+ ```
239
+
240
+ **Step 2: Run test to verify it fails**
241
+
242
+ Run: `npm test -- test/e2e/memory-workflow.test.ts`
243
+ Expected: FAIL (file doesn't exist yet)
244
+
245
+ **Step 3: Create minimal implementation (if needed)**
246
+
247
+ The test should pass if MemoryService is properly implemented.
248
+
249
+ **Step 4: Run test to verify it passes**
250
+
251
+ Run: `npm test -- test/e2e/memory-workflow.test.ts`
252
+ Expected: PASS
253
+
254
+ **Step 5: Commit**
255
+
256
+ Run: `git add test/e2e/ && git commit -m "test: add E2E workflow test"`
257
+
258
+ ---
259
+
260
+ ## Task 4: Create Stress Test - Batch Write & Accuracy Evaluation
261
+
262
+ **Files:**
263
+ - Create: `test/stress/batch-write.test.ts`
264
+ - Create: `test/stress/accuracy-metrics.ts`
265
+
266
+ **Step 1: Write accuracy metrics utility**
267
+
268
+ Write `test/stress/accuracy-metrics.ts`:
269
+
270
+ ```typescript
271
+ interface EvaluationResult {
272
+ recall: number;
273
+ precision: number;
274
+ mrr: number;
275
+ ndcg: number;
276
+ }
277
+
278
+ interface QueryGroundTruth {
279
+ query: string;
280
+ expected_domain: string;
281
+ expected_conv_ids: string[];
282
+ }
283
+
284
+ export function calculateMetrics(
285
+ retrievedIds: string[],
286
+ groundTruth: QueryGroundTruth,
287
+ k: number = 10
288
+ ): EvaluationResult {
289
+ const topK = retrievedIds.slice(0, k);
290
+ const relevant = groundTruth.expected_conv_ids;
291
+
292
+ // Recall@K
293
+ const relevantRetrieved = topK.filter(id => relevant.includes(id)).length;
294
+ const recall = relevant.length > 0 ? relevantRetrieved / relevant.length : 0;
295
+
296
+ // Precision@K
297
+ const precision = topK.length > 0 ? relevantRetrieved / topK.length : 0;
298
+
299
+ // MRR
300
+ let rr = 0;
301
+ for (let i = 0; i < topK.length; i++) {
302
+ if (relevant.includes(topK[i])) {
303
+ rr = 1 / (i + 1);
304
+ break;
305
+ }
306
+ }
307
+ const mrr = rr;
308
+
309
+ // NDCG
310
+ let dcg = 0;
311
+ for (let i = 0; i < topK.length; i++) {
312
+ if (relevant.includes(topK[i])) {
313
+ dcg += 1 / Math.log2(i + 2);
314
+ }
315
+ }
316
+ const idcg = relevant.reduce((sum, _, i) => sum + 1 / Math.log2(i + 2), 0);
317
+ const ndcg = idcg > 0 ? dcg / idcg : 0;
318
+
319
+ return { recall, precision, mrr, ndcg };
320
+ }
321
+ ```
322
+
323
+ **Step 2: Write batch write stress test**
324
+
325
+ Write `test/stress/batch-write.test.ts`:
326
+
327
+ ```typescript
328
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
329
+ import { setupTestDB, cleanupTestDB } from '../utils/db.js';
330
+ import { MemoryService } from '../../src/services/memory.js';
331
+ import { calculateMetrics } from './accuracy-metrics.js';
332
+ import type { Database } from 'better-sqlite3';
333
+ import fs from 'fs';
334
+ import path from 'path';
335
+
336
+ describe('Stress Test: Batch Write & Retrieval', () => {
337
+ let db: Database.Database;
338
+ let memoryService: MemoryService;
339
+ const dataDir = './test/data';
340
+
341
+ beforeEach(() => {
342
+ db = setupTestDB();
343
+ memoryService = new MemoryService(db, dataDir);
344
+ });
345
+
346
+ afterEach(() => {
347
+ cleanupTestDB();
348
+ });
349
+
350
+ it('should batch write 1000 memories efficiently', async () => {
351
+ const domains = ['technology', 'database', 'product', 'office'];
352
+ const contents: string[] = [];
353
+
354
+ // Generate 1000 test memories
355
+ for (let i = 0; i < 1000; i++) {
356
+ const domain = domains[i % domains.length];
357
+ contents.push(`Test content ${i} for domain ${domain}`);
358
+ }
359
+
360
+ const startTime = Date.now();
361
+
362
+ // Batch save (in real impl, use batch LLM call)
363
+ for (const content of contents) {
364
+ await memoryService.saveMemory({ content });
365
+ }
366
+
367
+ const duration = Date.now() - startTime;
368
+ const throughput = (contents.length / duration) * 1000;
369
+
370
+ console.log(`Wrote ${contents.length} memories in ${duration}ms`);
371
+ console.log(`Throughput: ${throughput.toFixed(2)} ops/sec`);
372
+
373
+ expect(throughput).toBeGreaterThan(10); // At least 10 ops/sec
374
+ });
375
+
376
+ it('should evaluate retrieval accuracy', async () => {
377
+ // Save test memories
378
+ await memoryService.saveMemory({
379
+ content: 'React uses virtual DOM for efficient rendering',
380
+ metadata: { tags: ['tech', 'react'], importance: 0.8 }
381
+ });
382
+ await memoryService.saveMemory({
383
+ content: 'PostgreSQL supports JSON columns',
384
+ metadata: { tags: ['database', 'postgresql'], importance: 0.7 }
385
+ });
386
+
387
+ // Load ground truth
388
+ const groundTruthPath = path.join(process.cwd(), 'test', 'fixtures', 'ground-truth.json');
389
+ const groundTruth = JSON.parse(fs.readFileSync(groundTruthPath, 'utf-8'));
390
+
391
+ // Evaluate each query
392
+ const results = [];
393
+ for (const qt of groundTruth.queries) {
394
+ const searchResults = await memoryService.searchMemory({
395
+ query: qt.query,
396
+ limit: 10,
397
+ timeRange: 'all'
398
+ });
399
+
400
+ const retrievedIds = searchResults.map((r: any) => r.id);
401
+ const metrics = calculateMetrics(retrievedIds, qt, 10);
402
+ results.push({ query: qt.query, metrics });
403
+ }
404
+
405
+ // Check average metrics
406
+ const avgRecall = results.reduce((sum, r) => sum + r.metrics.recall, 0) / results.length;
407
+ console.log('Average Recall:', avgRecall);
408
+
409
+ expect(avgRecall).toBeGreaterThan(0.5);
410
+ });
411
+ });
412
+ ```
413
+
414
+ **Step 3: Run test to verify it fails**
415
+
416
+ Run: `npm test -- test/stress/batch-write.test.ts`
417
+ Expected: FAIL (file doesn't exist)
418
+
419
+ **Step 4: Commit**
420
+
421
+ Run: `git add test/stress/ && git commit -m "test: add stress test with batch write and accuracy metrics"`
422
+
423
+ ---
424
+
425
+ ## Task 5: Update package.json Test Scripts
426
+
427
+ **Files:**
428
+ - Modify: `package.json`
429
+
430
+ **Step 1: Add test scripts**
431
+
432
+ Edit `package.json` to add:
433
+
434
+ ```json
435
+ "scripts": {
436
+ "test:e2e": "vitest run test/e2e",
437
+ "test:stress": "vitest run test/stress",
438
+ "test:all": "vitest run"
439
+ }
440
+ ```
441
+
442
+ **Step 2: Commit**
443
+
444
+ Run: `git add package.json && git commit -m "test: add e2e and stress test scripts"`
445
+
446
+ ---
447
+
448
+ ## Summary
449
+
450
+ | Task | Description | Files |
451
+ |------|-------------|-------|
452
+ | 1 | Create test fixtures with sample conversations | `test/fixtures/` |
453
+ | 2 | Create test utilities (DB, batch LLM) | `test/utils/` |
454
+ | 3 | Create E2E workflow test | `test/e2e/memory-workflow.test.ts` |
455
+ | 4 | Create stress test with accuracy metrics | `test/stress/` |
456
+ | 5 | Update package.json test scripts | `package.json` |
457
+
458
+ **Plan complete and saved to `docs/plans/2026-03-03-memory-e2e-stress-test-implementation.md`. Two execution options:**
459
+
460
+ **1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration
461
+
462
+ **2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints
463
+
464
+ **Which approach?**
@@ -0,0 +1,156 @@
1
+ # MiniMax LLM 集成修复计划
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** 修复 MiniMax LLM 集成问题,使 E2E 测试通过
6
+
7
+ **Architecture:** MiniMax 使用 OpenAI 兼容格式而非 Anthropic 格式,需要调整 LLM 配置检测逻辑
8
+
9
+ **Tech Stack:** TypeScript, Vitest, MiniMax API
10
+
11
+ ---
12
+
13
+ ### Task 1: 修复 LLM 配置 - 使用 openai-compatible 格式
14
+
15
+ **Files:**
16
+ - Modify: `src/config/llm.ts:20-31`
17
+
18
+ **Step 1: 修改默认 format 为 openai-compatible**
19
+
20
+ 当前代码在 LLM_FORMAT=anthropic 时使用 Anthropic API 格式调用 MiniMax,但 MiniMax 返回 "Request not allowed"。
21
+
22
+ 修改 `getLLMConfig` 函数,使其在检测到 MiniMax baseUrl 时自动使用 openai-compatible 格式:
23
+
24
+ ```typescript
25
+ export function getLLMConfig(): LLMConfig {
26
+ let format = (process.env.LLM_FORMAT as LLMConfig['format']) || 'openai';
27
+ let baseUrl = process.env.LLM_BASE_URL || getDefaultBaseUrl(format);
28
+ const apiKey = process.env.LLM_API_KEY || process.env.OPENAI_API_KEY || '';
29
+ let model = process.env.LLM_MODEL || getDefaultModel(format);
30
+
31
+ // Auto-detect MiniMax and use openai-compatible format
32
+ if (baseUrl.includes('minimax')) {
33
+ format = 'openai-compatible';
34
+ if (!process.env.LLM_BASE_URL) {
35
+ baseUrl = 'https://api.minimax.chat/v1';
36
+ }
37
+ if (!process.env.LLM_MODEL) {
38
+ model = 'MiniMax-M2.5-highspeed';
39
+ }
40
+ }
41
+
42
+ if (!apiKey) {
43
+ throw new Error('No LLM API key configured. Set LLM_API_KEY environment variable.');
44
+ }
45
+
46
+ return { format, baseUrl, apiKey, model };
47
+ }
48
+ ```
49
+
50
+ **Step 2: 运行测试验证**
51
+
52
+ ```bash
53
+ export LLM_FORMAT=anthropic
54
+ export LLM_BASE_URL=https://api.minimaxi.com/anthropic
55
+ export LLM_API_KEY="sk-cp-44gTAYHU1drLe7TFzJagmg6E_FaliukdnORiRuo0MkqsZitz5kv81UkaQ8XVkLH0bCsWgfixWgcTo-VBDmL8FmgD7qJ2aiVSCRBC9k8m8UM2bI9gyHNo8Pw"
56
+ export LLM_MODEL="MiniMax-M2.5-highspeed"
57
+ npm test 2>&1
58
+ ```
59
+
60
+ Expected: 测试通过,不再报 "Request not allowed" 错误
61
+
62
+ **Step 3: Commit**
63
+
64
+ ```bash
65
+ git add src/config/llm.ts
66
+ git commit -m "fix: auto-detect MiniMax and use openai-compatible format"
67
+ ```
68
+
69
+ ---
70
+
71
+ ### Task 2: 增加批量写入测试超时时间
72
+
73
+ **Files:**
74
+ - Modify: `test/stress/batch-write.test.ts:1-30`
75
+
76
+ **Step 1: 查看当前测试代码**
77
+
78
+ ```typescript
79
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
80
+ import { setupTestDB, cleanupTestDB } from '../utils/db.js';
81
+
82
+ describe('Stress Test: Batch Write & Retrieval', () => {
83
+ const dataDir = './test/data';
84
+
85
+ beforeEach(() => {
86
+ setupTestDB();
87
+ });
88
+
89
+ afterEach(() => {
90
+ cleanupTestDB();
91
+ });
92
+
93
+ it('should batch write memories efficiently', async () => {
94
+ // 测试代码
95
+ }, 30000); // 增加超时到 30 秒
96
+ });
97
+ ```
98
+
99
+ **Step 2: 增加超时时间**
100
+
101
+ 在 `it` 函数的第二个参数位置添加超时配置:
102
+
103
+ ```typescript
104
+ it('should batch write memories efficiently', async () => {
105
+ // ... 测试代码
106
+ }, 30000); // 30秒超时
107
+ ```
108
+
109
+ **Step 3: 运行测试验证**
110
+
111
+ ```bash
112
+ npm test 2>&1
113
+ ```
114
+
115
+ Expected: 批量写入测试不再超时
116
+
117
+ **Step 4: Commit**
118
+
119
+ ```bash
120
+ git add test/stress/batch-write.test.ts
121
+ git commit -f "fix: increase batch write test timeout to 30s"
122
+ ```
123
+
124
+ ---
125
+
126
+ ### Task 3: 更新 bashrc 默认配置(可选)
127
+
128
+ **Files:**
129
+ - Modify: `~/.bashrc:124-127`
130
+
131
+ **Step 1: 将默认 LLM_FORMAT 改为 openai-compatible**
132
+
133
+ ```bash
134
+ #llm memory
135
+ export LLM_FORMAT=openai-compatible
136
+ export LLM_BASE_URL=https://api.minimax.chat/v1
137
+ export LLM_API_KEY=sk-cp-44gTAYHU1drLe7TFzJagmg6E_FaliukdnORiRuo0MkqsZitz5kv81UkaQ8XVkLH0bCsWgfixWgcTo-VBDmL8FmgD7qJ2aiVSCRBC9k8m8UM2bI9gyHNo8Pw
138
+ export LLM_MODEL=MiniMax-M2.5-highspeed
139
+ ```
140
+
141
+ **Step 2: Commit**
142
+
143
+ ```bash
144
+ git add ~/.bashrc
145
+ git commit -m "chore: update default LLM config to openai-compatible for MiniMax"
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Bug 分析总结
151
+
152
+ | 问题 | 原因 | 修复方案 |
153
+ |------|------|----------|
154
+ | "No LLM API key configured" | bashrc 变量未 export | 添加 export 关键字 |
155
+ | "Request not allowed" | LLM_FORMAT=anthropic 时使用 Anthropic API 格式调用 MiniMax | 自动检测 MiniMax 并使用 openai-compatible 格式 |
156
+ | 测试超时 | 默认 5 秒超时太短 | 增加超时到 30 秒 |