@akashabot/openclaw-mem 0.3.0 → 0.5.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.
- package/dist/cli.js +119 -1
- package/package.json +2 -2
- package/src/cli.ts +138 -0
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,11 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
5
5
|
import * as core from '@akashabot/openclaw-memory-offline-core';
|
|
6
6
|
const { addItem, hybridSearch, hybridSearchFiltered, initSchema, openDb, runMigrations, searchItems, getMemoriesByEntity, getMemoriesBySession, getMemoriesByProcess, listEntities, listSessions,
|
|
7
7
|
// Phase 2: Facts
|
|
8
|
-
insertFact, getFactsBySubject, getFactsByPredicate, searchFacts, getAllFacts, listSubjects, listPredicates, deleteFact, extractFactsSimple,
|
|
8
|
+
insertFact, getFactsBySubject, getFactsByPredicate, searchFacts, getAllFacts, listSubjects, listPredicates, deleteFact, extractFactsSimple,
|
|
9
|
+
// Phase 3: Knowledge Graph
|
|
10
|
+
getEntityGraph, getRelatedEntities, findPaths, getGraphStats, exportGraphJson, searchEntities,
|
|
11
|
+
// Phase 3: Embedding Optimizations
|
|
12
|
+
getEmbeddingStats, quantizeF32ToF16, dequantizeF16ToF32, cosineSimilarity, benchmarkCosineSimilarity, runEmbeddingBenchmark, } = core;
|
|
9
13
|
const program = new Command();
|
|
10
14
|
program
|
|
11
15
|
.name('openclaw-mem')
|
|
@@ -314,4 +318,118 @@ program
|
|
|
314
318
|
const facts = extractFactsSimple(input);
|
|
315
319
|
console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
|
|
316
320
|
});
|
|
321
|
+
// ============================================================================
|
|
322
|
+
// Phase 3: Knowledge Graph commands
|
|
323
|
+
// ============================================================================
|
|
324
|
+
program
|
|
325
|
+
.command('graph-stats')
|
|
326
|
+
.description('Get statistics about the knowledge graph')
|
|
327
|
+
.action(() => {
|
|
328
|
+
withDb((dbPath) => {
|
|
329
|
+
const db = openDb(dbPath);
|
|
330
|
+
initSchema(db);
|
|
331
|
+
const stats = getGraphStats(db);
|
|
332
|
+
console.log(JSON.stringify({ ok: true, stats }, null, 2));
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
program
|
|
336
|
+
.command('graph-entity <entity>')
|
|
337
|
+
.description('Get all facts connected to an entity (as subject or object)')
|
|
338
|
+
.action((entity) => {
|
|
339
|
+
withDb((dbPath) => {
|
|
340
|
+
const db = openDb(dbPath);
|
|
341
|
+
initSchema(db);
|
|
342
|
+
const edges = getEntityGraph(db, entity);
|
|
343
|
+
console.log(JSON.stringify({ ok: true, entity, count: edges.length, edges }));
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
program
|
|
347
|
+
.command('graph-related <entity>')
|
|
348
|
+
.description('Get all entities directly connected to an entity')
|
|
349
|
+
.action((entity) => {
|
|
350
|
+
withDb((dbPath) => {
|
|
351
|
+
const db = openDb(dbPath);
|
|
352
|
+
initSchema(db);
|
|
353
|
+
const related = getRelatedEntities(db, entity);
|
|
354
|
+
console.log(JSON.stringify({ ok: true, entity, count: related.length, related }));
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
program
|
|
358
|
+
.command('graph-path <fromEntity> <toEntity>')
|
|
359
|
+
.description('Find paths between two entities in the knowledge graph')
|
|
360
|
+
.option('--max-depth <n>', 'Maximum path depth (default 4)', '4')
|
|
361
|
+
.option('--max-paths <n>', 'Maximum number of paths to return (default 5)', '5')
|
|
362
|
+
.action((fromEntity, toEntity, cmdOpts) => {
|
|
363
|
+
withDb((dbPath) => {
|
|
364
|
+
const db = openDb(dbPath);
|
|
365
|
+
initSchema(db);
|
|
366
|
+
const maxDepth = Math.max(1, Math.min(10, Number(cmdOpts.maxDepth ?? 4)));
|
|
367
|
+
const maxPaths = Math.max(1, Math.min(20, Number(cmdOpts.maxPaths ?? 5)));
|
|
368
|
+
const paths = findPaths(db, fromEntity, toEntity, maxDepth, maxPaths);
|
|
369
|
+
console.log(JSON.stringify({ ok: true, from: fromEntity, to: toEntity, count: paths.length, paths }));
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
program
|
|
373
|
+
.command('graph-export [outputFile]')
|
|
374
|
+
.description('Export the knowledge graph as JSON (for visualization)')
|
|
375
|
+
.option('--limit <n>', 'Max edges to export (default 1000)', '1000')
|
|
376
|
+
.option('--min-confidence <n>', 'Minimum confidence threshold (default 0)', '0')
|
|
377
|
+
.option('--entity <entity>', 'Export only subgraph around this entity')
|
|
378
|
+
.action((outputFile, cmdOpts) => {
|
|
379
|
+
withDb((dbPath) => {
|
|
380
|
+
const db = openDb(dbPath);
|
|
381
|
+
initSchema(db);
|
|
382
|
+
const graph = exportGraphJson(db, {
|
|
383
|
+
limit: Number(cmdOpts.limit ?? 1000),
|
|
384
|
+
minConfidence: Number(cmdOpts.minConfidence ?? 0),
|
|
385
|
+
entity: cmdOpts.entity,
|
|
386
|
+
});
|
|
387
|
+
const output = JSON.stringify({ ok: true, graph }, null, 2);
|
|
388
|
+
if (outputFile) {
|
|
389
|
+
fs.writeFileSync(outputFile, output);
|
|
390
|
+
console.log(JSON.stringify({ ok: true, file: outputFile, nodes: graph.nodes.length, edges: graph.edges.length }));
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
console.log(output);
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
program
|
|
398
|
+
.command('search-entities <pattern>')
|
|
399
|
+
.description('Search for entities matching a pattern')
|
|
400
|
+
.option('--limit <n>', 'Max results (default 50)', '50')
|
|
401
|
+
.action((pattern, cmdOpts) => {
|
|
402
|
+
withDb((dbPath) => {
|
|
403
|
+
const db = openDb(dbPath);
|
|
404
|
+
initSchema(db);
|
|
405
|
+
const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
|
|
406
|
+
const entities = searchEntities(db, pattern, limit);
|
|
407
|
+
console.log(JSON.stringify({ ok: true, pattern, count: entities.length, entities }));
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
// ============================================================================
|
|
411
|
+
// Phase 3: Embedding Optimization commands
|
|
412
|
+
// ============================================================================
|
|
413
|
+
program
|
|
414
|
+
.command('embedding-stats')
|
|
415
|
+
.description('Get statistics about stored embeddings')
|
|
416
|
+
.action(() => {
|
|
417
|
+
withDb((dbPath) => {
|
|
418
|
+
const db = openDb(dbPath);
|
|
419
|
+
initSchema(db);
|
|
420
|
+
const stats = getEmbeddingStats(db);
|
|
421
|
+
const sizeMB = Math.round((stats.totalSizeBytes / (1024 * 1024)) * 100) / 100;
|
|
422
|
+
console.log(JSON.stringify({ ok: true, ...stats, sizeMB }, null, 2));
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
program
|
|
426
|
+
.command('benchmark')
|
|
427
|
+
.description('Run embedding operation benchmarks')
|
|
428
|
+
.option('--dims <n>', 'Vector dimensions (default 1024)', '1024')
|
|
429
|
+
.option('--iterations <n>', 'Iterations (default 5000)', '5000')
|
|
430
|
+
.action((cmdOpts) => {
|
|
431
|
+
console.log('Running embedding benchmarks...\n');
|
|
432
|
+
const results = runEmbeddingBenchmark();
|
|
433
|
+
console.log(JSON.stringify({ ok: true, benchmark: results }, null, 2));
|
|
434
|
+
});
|
|
317
435
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akashabot/openclaw-mem",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for OpenClaw Offline Memory (SQLite FTS + optional embeddings)",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"commander": "^12.1.0",
|
|
19
19
|
"uuid": "^10.0.0",
|
|
20
|
-
"@akashabot/openclaw-memory-offline-core": "^0.
|
|
20
|
+
"@akashabot/openclaw-memory-offline-core": "^0.5.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/uuid": "^10.0.0"
|
package/src/cli.ts
CHANGED
|
@@ -27,6 +27,20 @@ const {
|
|
|
27
27
|
listPredicates,
|
|
28
28
|
deleteFact,
|
|
29
29
|
extractFactsSimple,
|
|
30
|
+
// Phase 3: Knowledge Graph
|
|
31
|
+
getEntityGraph,
|
|
32
|
+
getRelatedEntities,
|
|
33
|
+
findPaths,
|
|
34
|
+
getGraphStats,
|
|
35
|
+
exportGraphJson,
|
|
36
|
+
searchEntities,
|
|
37
|
+
// Phase 3: Embedding Optimizations
|
|
38
|
+
getEmbeddingStats,
|
|
39
|
+
quantizeF32ToF16,
|
|
40
|
+
dequantizeF16ToF32,
|
|
41
|
+
cosineSimilarity,
|
|
42
|
+
benchmarkCosineSimilarity,
|
|
43
|
+
runEmbeddingBenchmark,
|
|
30
44
|
} = core;
|
|
31
45
|
|
|
32
46
|
const program = new Command();
|
|
@@ -381,4 +395,128 @@ program
|
|
|
381
395
|
console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
|
|
382
396
|
});
|
|
383
397
|
|
|
398
|
+
// ============================================================================
|
|
399
|
+
// Phase 3: Knowledge Graph commands
|
|
400
|
+
// ============================================================================
|
|
401
|
+
|
|
402
|
+
program
|
|
403
|
+
.command('graph-stats')
|
|
404
|
+
.description('Get statistics about the knowledge graph')
|
|
405
|
+
.action(() => {
|
|
406
|
+
withDb((dbPath) => {
|
|
407
|
+
const db = openDb(dbPath);
|
|
408
|
+
initSchema(db);
|
|
409
|
+
const stats = getGraphStats(db);
|
|
410
|
+
console.log(JSON.stringify({ ok: true, stats }, null, 2));
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
program
|
|
415
|
+
.command('graph-entity <entity>')
|
|
416
|
+
.description('Get all facts connected to an entity (as subject or object)')
|
|
417
|
+
.action((entity: string) => {
|
|
418
|
+
withDb((dbPath) => {
|
|
419
|
+
const db = openDb(dbPath);
|
|
420
|
+
initSchema(db);
|
|
421
|
+
const edges = getEntityGraph(db, entity);
|
|
422
|
+
console.log(JSON.stringify({ ok: true, entity, count: edges.length, edges }));
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
program
|
|
427
|
+
.command('graph-related <entity>')
|
|
428
|
+
.description('Get all entities directly connected to an entity')
|
|
429
|
+
.action((entity: string) => {
|
|
430
|
+
withDb((dbPath) => {
|
|
431
|
+
const db = openDb(dbPath);
|
|
432
|
+
initSchema(db);
|
|
433
|
+
const related = getRelatedEntities(db, entity);
|
|
434
|
+
console.log(JSON.stringify({ ok: true, entity, count: related.length, related }));
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
program
|
|
439
|
+
.command('graph-path <fromEntity> <toEntity>')
|
|
440
|
+
.description('Find paths between two entities in the knowledge graph')
|
|
441
|
+
.option('--max-depth <n>', 'Maximum path depth (default 4)', '4')
|
|
442
|
+
.option('--max-paths <n>', 'Maximum number of paths to return (default 5)', '5')
|
|
443
|
+
.action((fromEntity: string, toEntity: string, cmdOpts) => {
|
|
444
|
+
withDb((dbPath) => {
|
|
445
|
+
const db = openDb(dbPath);
|
|
446
|
+
initSchema(db);
|
|
447
|
+
const maxDepth = Math.max(1, Math.min(10, Number(cmdOpts.maxDepth ?? 4)));
|
|
448
|
+
const maxPaths = Math.max(1, Math.min(20, Number(cmdOpts.maxPaths ?? 5)));
|
|
449
|
+
const paths = findPaths(db, fromEntity, toEntity, maxDepth, maxPaths);
|
|
450
|
+
console.log(JSON.stringify({ ok: true, from: fromEntity, to: toEntity, count: paths.length, paths }));
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
program
|
|
455
|
+
.command('graph-export [outputFile]')
|
|
456
|
+
.description('Export the knowledge graph as JSON (for visualization)')
|
|
457
|
+
.option('--limit <n>', 'Max edges to export (default 1000)', '1000')
|
|
458
|
+
.option('--min-confidence <n>', 'Minimum confidence threshold (default 0)', '0')
|
|
459
|
+
.option('--entity <entity>', 'Export only subgraph around this entity')
|
|
460
|
+
.action((outputFile: string | undefined, cmdOpts) => {
|
|
461
|
+
withDb((dbPath) => {
|
|
462
|
+
const db = openDb(dbPath);
|
|
463
|
+
initSchema(db);
|
|
464
|
+
const graph = exportGraphJson(db, {
|
|
465
|
+
limit: Number(cmdOpts.limit ?? 1000),
|
|
466
|
+
minConfidence: Number(cmdOpts.minConfidence ?? 0),
|
|
467
|
+
entity: cmdOpts.entity,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
const output = JSON.stringify({ ok: true, graph }, null, 2);
|
|
471
|
+
if (outputFile) {
|
|
472
|
+
fs.writeFileSync(outputFile, output);
|
|
473
|
+
console.log(JSON.stringify({ ok: true, file: outputFile, nodes: graph.nodes.length, edges: graph.edges.length }));
|
|
474
|
+
} else {
|
|
475
|
+
console.log(output);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
program
|
|
481
|
+
.command('search-entities <pattern>')
|
|
482
|
+
.description('Search for entities matching a pattern')
|
|
483
|
+
.option('--limit <n>', 'Max results (default 50)', '50')
|
|
484
|
+
.action((pattern: string, cmdOpts) => {
|
|
485
|
+
withDb((dbPath) => {
|
|
486
|
+
const db = openDb(dbPath);
|
|
487
|
+
initSchema(db);
|
|
488
|
+
const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
|
|
489
|
+
const entities = searchEntities(db, pattern, limit);
|
|
490
|
+
console.log(JSON.stringify({ ok: true, pattern, count: entities.length, entities }));
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// ============================================================================
|
|
495
|
+
// Phase 3: Embedding Optimization commands
|
|
496
|
+
// ============================================================================
|
|
497
|
+
|
|
498
|
+
program
|
|
499
|
+
.command('embedding-stats')
|
|
500
|
+
.description('Get statistics about stored embeddings')
|
|
501
|
+
.action(() => {
|
|
502
|
+
withDb((dbPath) => {
|
|
503
|
+
const db = openDb(dbPath);
|
|
504
|
+
initSchema(db);
|
|
505
|
+
const stats = getEmbeddingStats(db);
|
|
506
|
+
const sizeMB = Math.round((stats.totalSizeBytes / (1024 * 1024)) * 100) / 100;
|
|
507
|
+
console.log(JSON.stringify({ ok: true, ...stats, sizeMB }, null, 2));
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
program
|
|
512
|
+
.command('benchmark')
|
|
513
|
+
.description('Run embedding operation benchmarks')
|
|
514
|
+
.option('--dims <n>', 'Vector dimensions (default 1024)', '1024')
|
|
515
|
+
.option('--iterations <n>', 'Iterations (default 5000)', '5000')
|
|
516
|
+
.action((cmdOpts) => {
|
|
517
|
+
console.log('Running embedding benchmarks...\n');
|
|
518
|
+
const results = runEmbeddingBenchmark();
|
|
519
|
+
console.log(JSON.stringify({ ok: true, benchmark: results }, null, 2));
|
|
520
|
+
});
|
|
521
|
+
|
|
384
522
|
program.parse();
|