@akashabot/openclaw-mem 0.3.0 → 0.4.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 (3) hide show
  1. package/dist/cli.js +92 -1
  2. package/package.json +2 -2
  3. package/src/cli.ts +103 -0
package/dist/cli.js CHANGED
@@ -5,7 +5,9 @@ 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, } = core;
8
+ insertFact, getFactsBySubject, getFactsByPredicate, searchFacts, getAllFacts, listSubjects, listPredicates, deleteFact, extractFactsSimple,
9
+ // Phase 3: Knowledge Graph
10
+ getEntityGraph, getRelatedEntities, findPaths, getGraphStats, exportGraphJson, searchEntities, } = core;
9
11
  const program = new Command();
10
12
  program
11
13
  .name('openclaw-mem')
@@ -314,4 +316,93 @@ program
314
316
  const facts = extractFactsSimple(input);
315
317
  console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
316
318
  });
319
+ // ============================================================================
320
+ // Phase 3: Knowledge Graph commands
321
+ // ============================================================================
322
+ program
323
+ .command('graph-stats')
324
+ .description('Get statistics about the knowledge graph')
325
+ .action(() => {
326
+ withDb((dbPath) => {
327
+ const db = openDb(dbPath);
328
+ initSchema(db);
329
+ const stats = getGraphStats(db);
330
+ console.log(JSON.stringify({ ok: true, stats }, null, 2));
331
+ });
332
+ });
333
+ program
334
+ .command('graph-entity <entity>')
335
+ .description('Get all facts connected to an entity (as subject or object)')
336
+ .action((entity) => {
337
+ withDb((dbPath) => {
338
+ const db = openDb(dbPath);
339
+ initSchema(db);
340
+ const edges = getEntityGraph(db, entity);
341
+ console.log(JSON.stringify({ ok: true, entity, count: edges.length, edges }));
342
+ });
343
+ });
344
+ program
345
+ .command('graph-related <entity>')
346
+ .description('Get all entities directly connected to an entity')
347
+ .action((entity) => {
348
+ withDb((dbPath) => {
349
+ const db = openDb(dbPath);
350
+ initSchema(db);
351
+ const related = getRelatedEntities(db, entity);
352
+ console.log(JSON.stringify({ ok: true, entity, count: related.length, related }));
353
+ });
354
+ });
355
+ program
356
+ .command('graph-path <fromEntity> <toEntity>')
357
+ .description('Find paths between two entities in the knowledge graph')
358
+ .option('--max-depth <n>', 'Maximum path depth (default 4)', '4')
359
+ .option('--max-paths <n>', 'Maximum number of paths to return (default 5)', '5')
360
+ .action((fromEntity, toEntity, cmdOpts) => {
361
+ withDb((dbPath) => {
362
+ const db = openDb(dbPath);
363
+ initSchema(db);
364
+ const maxDepth = Math.max(1, Math.min(10, Number(cmdOpts.maxDepth ?? 4)));
365
+ const maxPaths = Math.max(1, Math.min(20, Number(cmdOpts.maxPaths ?? 5)));
366
+ const paths = findPaths(db, fromEntity, toEntity, maxDepth, maxPaths);
367
+ console.log(JSON.stringify({ ok: true, from: fromEntity, to: toEntity, count: paths.length, paths }));
368
+ });
369
+ });
370
+ program
371
+ .command('graph-export [outputFile]')
372
+ .description('Export the knowledge graph as JSON (for visualization)')
373
+ .option('--limit <n>', 'Max edges to export (default 1000)', '1000')
374
+ .option('--min-confidence <n>', 'Minimum confidence threshold (default 0)', '0')
375
+ .option('--entity <entity>', 'Export only subgraph around this entity')
376
+ .action((outputFile, cmdOpts) => {
377
+ withDb((dbPath) => {
378
+ const db = openDb(dbPath);
379
+ initSchema(db);
380
+ const graph = exportGraphJson(db, {
381
+ limit: Number(cmdOpts.limit ?? 1000),
382
+ minConfidence: Number(cmdOpts.minConfidence ?? 0),
383
+ entity: cmdOpts.entity,
384
+ });
385
+ const output = JSON.stringify({ ok: true, graph }, null, 2);
386
+ if (outputFile) {
387
+ fs.writeFileSync(outputFile, output);
388
+ console.log(JSON.stringify({ ok: true, file: outputFile, nodes: graph.nodes.length, edges: graph.edges.length }));
389
+ }
390
+ else {
391
+ console.log(output);
392
+ }
393
+ });
394
+ });
395
+ program
396
+ .command('search-entities <pattern>')
397
+ .description('Search for entities matching a pattern')
398
+ .option('--limit <n>', 'Max results (default 50)', '50')
399
+ .action((pattern, cmdOpts) => {
400
+ withDb((dbPath) => {
401
+ const db = openDb(dbPath);
402
+ initSchema(db);
403
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
404
+ const entities = searchEntities(db, pattern, limit);
405
+ console.log(JSON.stringify({ ok: true, pattern, count: entities.length, entities }));
406
+ });
407
+ });
317
408
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akashabot/openclaw-mem",
3
- "version": "0.3.0",
3
+ "version": "0.4.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.3.0"
20
+ "@akashabot/openclaw-memory-offline-core": "^0.4.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/uuid": "^10.0.0"
package/src/cli.ts CHANGED
@@ -27,6 +27,13 @@ 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,
30
37
  } = core;
31
38
 
32
39
  const program = new Command();
@@ -381,4 +388,100 @@ program
381
388
  console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
382
389
  });
383
390
 
391
+ // ============================================================================
392
+ // Phase 3: Knowledge Graph commands
393
+ // ============================================================================
394
+
395
+ program
396
+ .command('graph-stats')
397
+ .description('Get statistics about the knowledge graph')
398
+ .action(() => {
399
+ withDb((dbPath) => {
400
+ const db = openDb(dbPath);
401
+ initSchema(db);
402
+ const stats = getGraphStats(db);
403
+ console.log(JSON.stringify({ ok: true, stats }, null, 2));
404
+ });
405
+ });
406
+
407
+ program
408
+ .command('graph-entity <entity>')
409
+ .description('Get all facts connected to an entity (as subject or object)')
410
+ .action((entity: string) => {
411
+ withDb((dbPath) => {
412
+ const db = openDb(dbPath);
413
+ initSchema(db);
414
+ const edges = getEntityGraph(db, entity);
415
+ console.log(JSON.stringify({ ok: true, entity, count: edges.length, edges }));
416
+ });
417
+ });
418
+
419
+ program
420
+ .command('graph-related <entity>')
421
+ .description('Get all entities directly connected to an entity')
422
+ .action((entity: string) => {
423
+ withDb((dbPath) => {
424
+ const db = openDb(dbPath);
425
+ initSchema(db);
426
+ const related = getRelatedEntities(db, entity);
427
+ console.log(JSON.stringify({ ok: true, entity, count: related.length, related }));
428
+ });
429
+ });
430
+
431
+ program
432
+ .command('graph-path <fromEntity> <toEntity>')
433
+ .description('Find paths between two entities in the knowledge graph')
434
+ .option('--max-depth <n>', 'Maximum path depth (default 4)', '4')
435
+ .option('--max-paths <n>', 'Maximum number of paths to return (default 5)', '5')
436
+ .action((fromEntity: string, toEntity: string, cmdOpts) => {
437
+ withDb((dbPath) => {
438
+ const db = openDb(dbPath);
439
+ initSchema(db);
440
+ const maxDepth = Math.max(1, Math.min(10, Number(cmdOpts.maxDepth ?? 4)));
441
+ const maxPaths = Math.max(1, Math.min(20, Number(cmdOpts.maxPaths ?? 5)));
442
+ const paths = findPaths(db, fromEntity, toEntity, maxDepth, maxPaths);
443
+ console.log(JSON.stringify({ ok: true, from: fromEntity, to: toEntity, count: paths.length, paths }));
444
+ });
445
+ });
446
+
447
+ program
448
+ .command('graph-export [outputFile]')
449
+ .description('Export the knowledge graph as JSON (for visualization)')
450
+ .option('--limit <n>', 'Max edges to export (default 1000)', '1000')
451
+ .option('--min-confidence <n>', 'Minimum confidence threshold (default 0)', '0')
452
+ .option('--entity <entity>', 'Export only subgraph around this entity')
453
+ .action((outputFile: string | undefined, cmdOpts) => {
454
+ withDb((dbPath) => {
455
+ const db = openDb(dbPath);
456
+ initSchema(db);
457
+ const graph = exportGraphJson(db, {
458
+ limit: Number(cmdOpts.limit ?? 1000),
459
+ minConfidence: Number(cmdOpts.minConfidence ?? 0),
460
+ entity: cmdOpts.entity,
461
+ });
462
+
463
+ const output = JSON.stringify({ ok: true, graph }, null, 2);
464
+ if (outputFile) {
465
+ fs.writeFileSync(outputFile, output);
466
+ console.log(JSON.stringify({ ok: true, file: outputFile, nodes: graph.nodes.length, edges: graph.edges.length }));
467
+ } else {
468
+ console.log(output);
469
+ }
470
+ });
471
+ });
472
+
473
+ program
474
+ .command('search-entities <pattern>')
475
+ .description('Search for entities matching a pattern')
476
+ .option('--limit <n>', 'Max results (default 50)', '50')
477
+ .action((pattern: string, cmdOpts) => {
478
+ withDb((dbPath) => {
479
+ const db = openDb(dbPath);
480
+ initSchema(db);
481
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
482
+ const entities = searchEntities(db, pattern, limit);
483
+ console.log(JSON.stringify({ ok: true, pattern, count: entities.length, entities }));
484
+ });
485
+ });
486
+
384
487
  program.parse();