claude-flow 2.7.2 ā 2.7.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/bin/claude-flow +1 -1
- package/dist/src/cli/commands/memory.js +208 -32
- package/dist/src/cli/commands/memory.js.map +1 -1
- package/dist/src/cli/help-formatter.js +5 -3
- package/dist/src/cli/help-formatter.js.map +1 -1
- package/dist/src/cli/simple-cli.js +172 -182
- package/dist/src/cli/simple-cli.js.map +1 -1
- package/dist/src/cli/simple-commands/config.js.map +1 -1
- package/dist/src/cli/simple-commands/memory.js +13 -1
- package/dist/src/cli/simple-commands/memory.js.map +1 -1
- package/dist/src/memory/swarm-memory.js +340 -421
- package/dist/src/memory/swarm-memory.js.map +1 -1
- package/dist/src/utils/key-redactor.js.map +1 -1
- package/dist/src/utils/metrics-reader.js +29 -41
- package/dist/src/utils/metrics-reader.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/memory.ts +252 -34
- package/src/cli/simple-commands/memory.js +19 -3
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
/**
|
|
3
3
|
* Memory management commands
|
|
4
|
+
*
|
|
5
|
+
* Default: Uses SQLite (.swarm/memory.db) with AgentDB/ReasoningBank for:
|
|
6
|
+
* - 150x faster vector search
|
|
7
|
+
* - Semantic understanding
|
|
8
|
+
* - 56% memory reduction
|
|
9
|
+
* - Advanced AI features (consolidation, learning, pattern recognition)
|
|
10
|
+
*
|
|
11
|
+
* Fallback: Uses JSON (./memory/memory-store.json) if SQLite unavailable
|
|
4
12
|
*/
|
|
5
13
|
|
|
6
14
|
import { Command } from '../commander-fix.js';
|
|
@@ -12,6 +20,159 @@ interface MemoryEntry {
|
|
|
12
20
|
value: string;
|
|
13
21
|
namespace: string;
|
|
14
22
|
timestamp: number;
|
|
23
|
+
confidence?: number;
|
|
24
|
+
usage_count?: number;
|
|
25
|
+
created_at?: string;
|
|
26
|
+
id?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Memory backend type
|
|
30
|
+
type MemoryBackend = 'sqlite' | 'json';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Unified Memory Manager - tries SQLite first, falls back to JSON
|
|
34
|
+
*/
|
|
35
|
+
export class UnifiedMemoryManager {
|
|
36
|
+
private backend: MemoryBackend = 'sqlite';
|
|
37
|
+
private sqliteManager: any = null;
|
|
38
|
+
private jsonManager: SimpleMemoryManager | null = null;
|
|
39
|
+
|
|
40
|
+
async getBackend(): Promise<MemoryBackend> {
|
|
41
|
+
if (this.backend === 'sqlite' && !this.sqliteManager) {
|
|
42
|
+
try {
|
|
43
|
+
// Try to initialize SQLite backend
|
|
44
|
+
const { initializeReasoningBank, storeMemory, queryMemories, listMemories, getStatus } =
|
|
45
|
+
await import('../../reasoningbank/reasoningbank-adapter.js');
|
|
46
|
+
|
|
47
|
+
await initializeReasoningBank();
|
|
48
|
+
this.sqliteManager = { storeMemory, queryMemories, listMemories, getStatus };
|
|
49
|
+
console.log(chalk.gray('šļø Using SQLite backend (.swarm/memory.db)'));
|
|
50
|
+
return 'sqlite';
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.log(chalk.yellow('ā ļø SQLite unavailable, falling back to JSON'));
|
|
53
|
+
console.log(chalk.gray(` Reason: ${(error as Error).message}`));
|
|
54
|
+
this.backend = 'json';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (this.backend === 'json' && !this.jsonManager) {
|
|
59
|
+
this.jsonManager = new SimpleMemoryManager();
|
|
60
|
+
console.log(chalk.gray('š Using JSON backend (./memory/memory-store.json)'));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return this.backend;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async store(key: string, value: string, namespace: string = 'default') {
|
|
67
|
+
const backend = await this.getBackend();
|
|
68
|
+
|
|
69
|
+
if (backend === 'sqlite' && this.sqliteManager) {
|
|
70
|
+
const id = await this.sqliteManager.storeMemory(key, value, { namespace });
|
|
71
|
+
return { backend: 'sqlite', id };
|
|
72
|
+
} else if (this.jsonManager) {
|
|
73
|
+
await this.jsonManager.store(key, value, namespace);
|
|
74
|
+
return { backend: 'json' };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
throw new Error('No memory backend available');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async query(search: string, namespace?: string, limit: number = 10) {
|
|
81
|
+
const backend = await this.getBackend();
|
|
82
|
+
|
|
83
|
+
if (backend === 'sqlite' && this.sqliteManager) {
|
|
84
|
+
const results = await this.sqliteManager.queryMemories(search, { namespace, limit });
|
|
85
|
+
return results;
|
|
86
|
+
} else if (this.jsonManager) {
|
|
87
|
+
const results = await this.jsonManager.query(search, namespace);
|
|
88
|
+
return results.slice(0, limit);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async list(namespace?: string, limit: number = 10) {
|
|
95
|
+
const backend = await this.getBackend();
|
|
96
|
+
|
|
97
|
+
if (backend === 'sqlite' && this.sqliteManager) {
|
|
98
|
+
const results = await this.sqliteManager.listMemories({ namespace, limit });
|
|
99
|
+
return results;
|
|
100
|
+
} else if (this.jsonManager) {
|
|
101
|
+
const stats = await this.jsonManager.getStats();
|
|
102
|
+
|
|
103
|
+
// Convert to list format
|
|
104
|
+
await this.jsonManager.load();
|
|
105
|
+
const entries: MemoryEntry[] = [];
|
|
106
|
+
|
|
107
|
+
for (const [ns, nsEntries] of Object.entries(this.jsonManager['data'])) {
|
|
108
|
+
if (!namespace || ns === namespace) {
|
|
109
|
+
entries.push(...nsEntries);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return entries.slice(0, limit);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async getStats() {
|
|
120
|
+
const backend = await this.getBackend();
|
|
121
|
+
|
|
122
|
+
if (backend === 'sqlite' && this.sqliteManager) {
|
|
123
|
+
const status = await this.sqliteManager.getStatus();
|
|
124
|
+
return {
|
|
125
|
+
backend: 'sqlite',
|
|
126
|
+
totalEntries: status.total_memories,
|
|
127
|
+
namespaces: status.total_categories,
|
|
128
|
+
database: status.database_path,
|
|
129
|
+
performance: '150x faster vector search',
|
|
130
|
+
features: 'Semantic search, learning, consolidation'
|
|
131
|
+
};
|
|
132
|
+
} else if (this.jsonManager) {
|
|
133
|
+
const stats = await this.jsonManager.getStats();
|
|
134
|
+
return {
|
|
135
|
+
backend: 'json',
|
|
136
|
+
totalEntries: stats.totalEntries,
|
|
137
|
+
namespaces: stats.namespaces,
|
|
138
|
+
sizeBytes: stats.sizeBytes,
|
|
139
|
+
namespaceStats: stats.namespaceStats
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { backend: 'none', totalEntries: 0 };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async cleanup(daysOld: number = 30) {
|
|
147
|
+
const backend = await this.getBackend();
|
|
148
|
+
|
|
149
|
+
if (backend === 'json' && this.jsonManager) {
|
|
150
|
+
return await this.jsonManager.cleanup(daysOld);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// SQLite cleanup would go here
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async exportData(filePath: string) {
|
|
158
|
+
const backend = await this.getBackend();
|
|
159
|
+
|
|
160
|
+
if (backend === 'json' && this.jsonManager) {
|
|
161
|
+
return await this.jsonManager.exportData(filePath);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
throw new Error('Export not yet implemented for SQLite backend');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async importData(filePath: string) {
|
|
168
|
+
const backend = await this.getBackend();
|
|
169
|
+
|
|
170
|
+
if (backend === 'json' && this.jsonManager) {
|
|
171
|
+
return await this.jsonManager.importData(filePath);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
throw new Error('Import not yet implemented for SQLite backend');
|
|
175
|
+
}
|
|
15
176
|
}
|
|
16
177
|
|
|
17
178
|
export class SimpleMemoryManager {
|
|
@@ -130,58 +291,103 @@ export const memoryCommand = new Command()
|
|
|
130
291
|
// Store command
|
|
131
292
|
memoryCommand
|
|
132
293
|
.command('store')
|
|
133
|
-
.description('Store information in memory')
|
|
294
|
+
.description('Store information in memory (uses SQLite by default)')
|
|
134
295
|
.arguments('<key> <value>')
|
|
135
296
|
.option('-n, --namespace <namespace>', 'Target namespace', 'default')
|
|
136
297
|
.action(async (key: string, value: string, options: any) => {
|
|
137
298
|
try {
|
|
138
|
-
const memory = new
|
|
139
|
-
await memory.store(key, value, options.namespace);
|
|
299
|
+
const memory = new UnifiedMemoryManager();
|
|
300
|
+
const result = await memory.store(key, value, options.namespace);
|
|
140
301
|
console.log(chalk.green('ā
Stored successfully'));
|
|
141
302
|
console.log(`š Key: ${key}`);
|
|
142
303
|
console.log(`š¦ Namespace: ${options.namespace}`);
|
|
143
304
|
console.log(`š¾ Size: ${new TextEncoder().encode(value).length} bytes`);
|
|
305
|
+
if (result.id) {
|
|
306
|
+
console.log(chalk.gray(`š ID: ${result.id}`));
|
|
307
|
+
}
|
|
144
308
|
} catch (error) {
|
|
145
|
-
console.error(chalk.red('Failed to store:'), (error as Error).message);
|
|
309
|
+
console.error(chalk.red('ā Failed to store:'), (error as Error).message);
|
|
146
310
|
}
|
|
147
311
|
});
|
|
148
312
|
|
|
149
313
|
// Query command
|
|
150
314
|
memoryCommand
|
|
151
315
|
.command('query')
|
|
152
|
-
.description('Search memory entries')
|
|
316
|
+
.description('Search memory entries (semantic search with SQLite)')
|
|
153
317
|
.arguments('<search>')
|
|
154
318
|
.option('-n, --namespace <namespace>', 'Filter by namespace')
|
|
155
319
|
.option('-l, --limit <limit>', 'Limit results', '10')
|
|
156
320
|
.action(async (search: string, options: any) => {
|
|
157
321
|
try {
|
|
158
|
-
const memory = new
|
|
159
|
-
const results = await memory.query(search, options.namespace);
|
|
322
|
+
const memory = new UnifiedMemoryManager();
|
|
323
|
+
const results = await memory.query(search, options.namespace, parseInt(options.limit));
|
|
160
324
|
|
|
161
325
|
if (results.length === 0) {
|
|
162
|
-
console.log(chalk.yellow('No results found'));
|
|
326
|
+
console.log(chalk.yellow('ā ļø No results found'));
|
|
163
327
|
return;
|
|
164
328
|
}
|
|
165
329
|
|
|
166
|
-
console.log(chalk.green(`ā
Found ${results.length} results
|
|
330
|
+
console.log(chalk.green(`ā
Found ${results.length} results:\n`));
|
|
167
331
|
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
console.log(chalk.blue(`\nš ${entry.key}`));
|
|
332
|
+
for (const entry of results) {
|
|
333
|
+
console.log(chalk.blue(`š ${entry.key}`));
|
|
171
334
|
console.log(` Namespace: ${entry.namespace}`);
|
|
172
335
|
console.log(
|
|
173
336
|
` Value: ${entry.value.substring(0, 100)}${entry.value.length > 100 ? '...' : ''}`,
|
|
174
337
|
);
|
|
175
|
-
|
|
338
|
+
const timestamp = entry.created_at || entry.timestamp;
|
|
339
|
+
if (timestamp) {
|
|
340
|
+
const date = typeof timestamp === 'number' ? new Date(timestamp) : new Date(timestamp);
|
|
341
|
+
console.log(` Stored: ${date.toLocaleString()}`);
|
|
342
|
+
}
|
|
343
|
+
if (entry.confidence) {
|
|
344
|
+
console.log(chalk.gray(` Confidence: ${(entry.confidence * 100).toFixed(0)}%`));
|
|
345
|
+
}
|
|
346
|
+
console.log('');
|
|
176
347
|
}
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error(chalk.red('ā Failed to query:'), (error as Error).message);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
177
352
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
353
|
+
// List command
|
|
354
|
+
memoryCommand
|
|
355
|
+
.command('list')
|
|
356
|
+
.description('List all memory entries')
|
|
357
|
+
.option('-n, --namespace <namespace>', 'Filter by namespace')
|
|
358
|
+
.option('-l, --limit <limit>', 'Limit results', '10')
|
|
359
|
+
.action(async (options: any) => {
|
|
360
|
+
try {
|
|
361
|
+
const memory = new UnifiedMemoryManager();
|
|
362
|
+
const results = await memory.list(options.namespace, parseInt(options.limit));
|
|
363
|
+
|
|
364
|
+
if (results.length === 0) {
|
|
365
|
+
console.log(chalk.yellow('ā ļø No memories found'));
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Group by namespace
|
|
370
|
+
const byNamespace: Record<string, MemoryEntry[]> = {};
|
|
371
|
+
for (const entry of results) {
|
|
372
|
+
if (!byNamespace[entry.namespace]) {
|
|
373
|
+
byNamespace[entry.namespace] = [];
|
|
374
|
+
}
|
|
375
|
+
byNamespace[entry.namespace].push(entry);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
console.log(chalk.green(`š Memory Bank (${results.length} entries):\n`));
|
|
379
|
+
|
|
380
|
+
if (Object.keys(byNamespace).length === 0) {
|
|
381
|
+
console.log(chalk.yellow('ā ļø No namespaces found'));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
console.log(chalk.green('ā
Available namespaces:'));
|
|
386
|
+
for (const [ns, entries] of Object.entries(byNamespace)) {
|
|
387
|
+
console.log(` ${ns} (${entries.length} entries)`);
|
|
182
388
|
}
|
|
183
389
|
} catch (error) {
|
|
184
|
-
console.error(chalk.red('Failed to
|
|
390
|
+
console.error(chalk.red('ā Failed to list:'), (error as Error).message);
|
|
185
391
|
}
|
|
186
392
|
});
|
|
187
393
|
|
|
@@ -192,15 +398,17 @@ memoryCommand
|
|
|
192
398
|
.arguments('<file>')
|
|
193
399
|
.action(async (file: string, options: any) => {
|
|
194
400
|
try {
|
|
195
|
-
const memory = new
|
|
401
|
+
const memory = new UnifiedMemoryManager();
|
|
196
402
|
await memory.exportData(file);
|
|
197
403
|
const stats = await memory.getStats();
|
|
198
404
|
console.log(chalk.green('ā
Memory exported successfully'));
|
|
199
405
|
console.log(`š File: ${file}`);
|
|
200
406
|
console.log(`š Entries: ${stats.totalEntries}`);
|
|
201
|
-
|
|
407
|
+
if (stats.sizeBytes) {
|
|
408
|
+
console.log(`š¾ Size: ${(stats.sizeBytes / 1024).toFixed(2)} KB`);
|
|
409
|
+
}
|
|
202
410
|
} catch (error) {
|
|
203
|
-
console.error(chalk.red('Failed to export:'), (error as Error).message);
|
|
411
|
+
console.error(chalk.red('ā Failed to export:'), (error as Error).message);
|
|
204
412
|
}
|
|
205
413
|
});
|
|
206
414
|
|
|
@@ -211,7 +419,7 @@ memoryCommand
|
|
|
211
419
|
.arguments('<file>')
|
|
212
420
|
.action(async (file: string, options: any) => {
|
|
213
421
|
try {
|
|
214
|
-
const memory = new
|
|
422
|
+
const memory = new UnifiedMemoryManager();
|
|
215
423
|
await memory.importData(file);
|
|
216
424
|
const stats = await memory.getStats();
|
|
217
425
|
console.log(chalk.green('ā
Memory imported successfully'));
|
|
@@ -219,32 +427,42 @@ memoryCommand
|
|
|
219
427
|
console.log(`š Entries: ${stats.totalEntries}`);
|
|
220
428
|
console.log(`šļø Namespaces: ${stats.namespaces}`);
|
|
221
429
|
} catch (error) {
|
|
222
|
-
console.error(chalk.red('Failed to import:'), (error as Error).message);
|
|
430
|
+
console.error(chalk.red('ā Failed to import:'), (error as Error).message);
|
|
223
431
|
}
|
|
224
432
|
});
|
|
225
433
|
|
|
226
434
|
// Stats command
|
|
227
435
|
memoryCommand
|
|
228
436
|
.command('stats')
|
|
229
|
-
.description('Show memory statistics')
|
|
437
|
+
.description('Show memory statistics and backend info')
|
|
230
438
|
.action(async () => {
|
|
231
439
|
try {
|
|
232
|
-
const memory = new
|
|
440
|
+
const memory = new UnifiedMemoryManager();
|
|
233
441
|
const stats = await memory.getStats();
|
|
234
442
|
|
|
235
|
-
console.log(chalk.green('š Memory Bank Statistics
|
|
443
|
+
console.log(chalk.green('\nš Memory Bank Statistics:\n'));
|
|
444
|
+
console.log(chalk.cyan(` Backend: ${stats.backend}`));
|
|
236
445
|
console.log(` Total Entries: ${stats.totalEntries}`);
|
|
237
446
|
console.log(` Namespaces: ${stats.namespaces}`);
|
|
238
|
-
console.log(` Size: ${(stats.sizeBytes / 1024).toFixed(2)} KB`);
|
|
239
447
|
|
|
240
|
-
if (stats.
|
|
241
|
-
console.log(chalk.
|
|
242
|
-
|
|
243
|
-
|
|
448
|
+
if (stats.backend === 'sqlite') {
|
|
449
|
+
console.log(chalk.gray(` Database: ${stats.database}`));
|
|
450
|
+
console.log(chalk.green(` Performance: ${stats.performance}`));
|
|
451
|
+
console.log(chalk.blue(` Features: ${stats.features}`));
|
|
452
|
+
} else if (stats.sizeBytes) {
|
|
453
|
+
console.log(` Size: ${(stats.sizeBytes / 1024).toFixed(2)} KB`);
|
|
454
|
+
|
|
455
|
+
if (stats.namespaceStats && Object.keys(stats.namespaceStats).length > 0) {
|
|
456
|
+
console.log(chalk.blue('\nš Namespace Breakdown:'));
|
|
457
|
+
for (const [namespace, count] of Object.entries(stats.namespaceStats)) {
|
|
458
|
+
console.log(` ${namespace}: ${count} entries`);
|
|
459
|
+
}
|
|
244
460
|
}
|
|
245
461
|
}
|
|
462
|
+
|
|
463
|
+
console.log('');
|
|
246
464
|
} catch (error) {
|
|
247
|
-
console.error(chalk.red('Failed to get stats:'), (error as Error).message);
|
|
465
|
+
console.error(chalk.red('ā Failed to get stats:'), (error as Error).message);
|
|
248
466
|
}
|
|
249
467
|
});
|
|
250
468
|
|
|
@@ -255,12 +473,12 @@ memoryCommand
|
|
|
255
473
|
.option('-d, --days <days>', 'Entries older than n days', '30')
|
|
256
474
|
.action(async (options: any) => {
|
|
257
475
|
try {
|
|
258
|
-
const memory = new
|
|
476
|
+
const memory = new UnifiedMemoryManager();
|
|
259
477
|
const removed = await memory.cleanup(parseInt(options.days));
|
|
260
478
|
console.log(chalk.green('ā
Cleanup completed'));
|
|
261
479
|
console.log(`šļø Removed: ${removed} entries older than ${options.days} days`);
|
|
262
480
|
} catch (error) {
|
|
263
|
-
console.error(chalk.red('Failed to cleanup:'), (error as Error).message);
|
|
481
|
+
console.error(chalk.red('ā Failed to cleanup:'), (error as Error).message);
|
|
264
482
|
}
|
|
265
483
|
});
|
|
266
484
|
|
|
@@ -407,10 +407,26 @@ async function detectMemoryMode(flags, subArgs) {
|
|
|
407
407
|
return 'basic';
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
// Default: AUTO MODE
|
|
411
|
-
//
|
|
410
|
+
// Default: AUTO MODE with SQLite preference
|
|
411
|
+
// Try to use ReasoningBank (SQLite) by default, initialize if needed
|
|
412
412
|
const initialized = await isReasoningBankInitialized();
|
|
413
|
-
|
|
413
|
+
|
|
414
|
+
if (initialized) {
|
|
415
|
+
return 'reasoningbank';
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Not initialized yet - try to auto-initialize on first use
|
|
419
|
+
try {
|
|
420
|
+
const { initializeReasoningBank } = await import('../../reasoningbank/reasoningbank-adapter.js');
|
|
421
|
+
await initializeReasoningBank();
|
|
422
|
+
printInfo('šļø Initialized SQLite backend (.swarm/memory.db)');
|
|
423
|
+
return 'reasoningbank';
|
|
424
|
+
} catch (error) {
|
|
425
|
+
// SQLite initialization failed - fall back to JSON
|
|
426
|
+
printWarning(`ā ļø SQLite unavailable, using JSON fallback`);
|
|
427
|
+
printWarning(` Reason: ${error.message}`);
|
|
428
|
+
return 'basic';
|
|
429
|
+
}
|
|
414
430
|
}
|
|
415
431
|
|
|
416
432
|
// NEW: Check if ReasoningBank is initialized
|