@akashabot/openclaw-mem 0.2.0 → 0.3.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 +111 -1
  2. package/package.json +2 -2
  3. package/src/cli.ts +127 -0
package/dist/cli.js CHANGED
@@ -3,7 +3,9 @@ import { Command } from 'commander';
3
3
  import fs from 'node:fs';
4
4
  import { v4 as uuidv4 } from 'uuid';
5
5
  import * as core from '@akashabot/openclaw-memory-offline-core';
6
- const { addItem, hybridSearch, hybridSearchFiltered, initSchema, openDb, runMigrations, searchItems, getMemoriesByEntity, getMemoriesBySession, getMemoriesByProcess, listEntities, listSessions, } = core;
6
+ const { addItem, hybridSearch, hybridSearchFiltered, initSchema, openDb, runMigrations, searchItems, getMemoriesByEntity, getMemoriesBySession, getMemoriesByProcess, listEntities, listSessions,
7
+ // Phase 2: Facts
8
+ insertFact, getFactsBySubject, getFactsByPredicate, searchFacts, getAllFacts, listSubjects, listPredicates, deleteFact, extractFactsSimple, } = core;
7
9
  const program = new Command();
8
10
  program
9
11
  .name('openclaw-mem')
@@ -204,4 +206,112 @@ program
204
206
  console.log(JSON.stringify({ ok: true, sessionId, count: items.length, items }));
205
207
  });
206
208
  });
209
+ // ============================================================================
210
+ // Phase 2: Fact commands
211
+ // ============================================================================
212
+ program
213
+ .command('add-fact <subject> <predicate> <object>')
214
+ .description('Add a structured fact (subject, predicate, object)')
215
+ .option('--confidence <n>', 'Confidence level 0-1 (default 0.7)', '0.7')
216
+ .option('--entity-id <entityId>', 'Who said/wrote this fact')
217
+ .option('--source-item-id <itemId>', 'Source memory item ID')
218
+ .action((subject, predicate, object, cmdOpts) => {
219
+ withDb((dbPath) => {
220
+ const db = openDb(dbPath);
221
+ initSchema(db);
222
+ const id = uuidv4();
223
+ const confidence = Math.max(0, Math.min(1, Number(cmdOpts.confidence ?? 0.7)));
224
+ const fact = insertFact(db, {
225
+ id,
226
+ subject,
227
+ predicate,
228
+ object,
229
+ confidence,
230
+ source_item_id: cmdOpts.sourceItemId ?? null,
231
+ entity_id: cmdOpts.entityId ?? null,
232
+ });
233
+ console.log(JSON.stringify({ ok: true, fact }));
234
+ });
235
+ });
236
+ program
237
+ .command('list-facts')
238
+ .description('List all facts (optionally filtered by entity)')
239
+ .option('--entity-id <entityId>', 'Filter by entity')
240
+ .option('--limit <n>', 'Max results (default 50)', '50')
241
+ .action((cmdOpts) => {
242
+ withDb((dbPath) => {
243
+ const db = openDb(dbPath);
244
+ initSchema(db);
245
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
246
+ const facts = getAllFacts(db, cmdOpts.entityId, limit);
247
+ console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
248
+ });
249
+ });
250
+ program
251
+ .command('get-facts-by-subject <subject>')
252
+ .description('Get all facts about a specific subject')
253
+ .option('--limit <n>', 'Max results (default 50)', '50')
254
+ .action((subject, cmdOpts) => {
255
+ withDb((dbPath) => {
256
+ const db = openDb(dbPath);
257
+ initSchema(db);
258
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
259
+ const facts = getFactsBySubject(db, subject, limit);
260
+ console.log(JSON.stringify({ ok: true, subject, count: facts.length, facts }));
261
+ });
262
+ });
263
+ program
264
+ .command('search-facts <query>')
265
+ .description('Search facts by subject, predicate, or object')
266
+ .option('--limit <n>', 'Max results (default 50)', '50')
267
+ .action((query, cmdOpts) => {
268
+ withDb((dbPath) => {
269
+ const db = openDb(dbPath);
270
+ initSchema(db);
271
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
272
+ const facts = searchFacts(db, query, limit);
273
+ console.log(JSON.stringify({ ok: true, query, count: facts.length, facts }));
274
+ });
275
+ });
276
+ program
277
+ .command('list-subjects')
278
+ .description('List all distinct subjects in the facts table')
279
+ .action(() => {
280
+ withDb((dbPath) => {
281
+ const db = openDb(dbPath);
282
+ initSchema(db);
283
+ const subjects = listSubjects(db);
284
+ console.log(JSON.stringify({ ok: true, subjects, count: subjects.length }));
285
+ });
286
+ });
287
+ program
288
+ .command('list-predicates')
289
+ .description('List all distinct predicates in the facts table')
290
+ .action(() => {
291
+ withDb((dbPath) => {
292
+ const db = openDb(dbPath);
293
+ initSchema(db);
294
+ const predicates = listPredicates(db);
295
+ console.log(JSON.stringify({ ok: true, predicates, count: predicates.length }));
296
+ });
297
+ });
298
+ program
299
+ .command('delete-fact <factId>')
300
+ .description('Delete a fact by ID')
301
+ .action((factId) => {
302
+ withDb((dbPath) => {
303
+ const db = openDb(dbPath);
304
+ initSchema(db);
305
+ const deleted = deleteFact(db, factId);
306
+ console.log(JSON.stringify({ ok: true, deleted, id: factId }));
307
+ });
308
+ });
309
+ program
310
+ .command('extract-facts [text]')
311
+ .description('Extract potential facts from text (pattern-based, does not store)')
312
+ .action((text) => {
313
+ const input = text ?? fs.readFileSync(0, 'utf-8');
314
+ const facts = extractFactsSimple(input);
315
+ console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
316
+ });
207
317
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akashabot/openclaw-mem",
3
- "version": "0.2.0",
3
+ "version": "0.3.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.2.0"
20
+ "@akashabot/openclaw-memory-offline-core": "^0.3.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/uuid": "^10.0.0"
package/src/cli.ts CHANGED
@@ -17,6 +17,16 @@ const {
17
17
  getMemoriesByProcess,
18
18
  listEntities,
19
19
  listSessions,
20
+ // Phase 2: Facts
21
+ insertFact,
22
+ getFactsBySubject,
23
+ getFactsByPredicate,
24
+ searchFacts,
25
+ getAllFacts,
26
+ listSubjects,
27
+ listPredicates,
28
+ deleteFact,
29
+ extractFactsSimple,
20
30
  } = core;
21
31
 
22
32
  const program = new Command();
@@ -254,4 +264,121 @@ program
254
264
  });
255
265
  });
256
266
 
267
+ // ============================================================================
268
+ // Phase 2: Fact commands
269
+ // ============================================================================
270
+
271
+ program
272
+ .command('add-fact <subject> <predicate> <object>')
273
+ .description('Add a structured fact (subject, predicate, object)')
274
+ .option('--confidence <n>', 'Confidence level 0-1 (default 0.7)', '0.7')
275
+ .option('--entity-id <entityId>', 'Who said/wrote this fact')
276
+ .option('--source-item-id <itemId>', 'Source memory item ID')
277
+ .action((subject: string, predicate: string, object: string, cmdOpts) => {
278
+ withDb((dbPath) => {
279
+ const db = openDb(dbPath);
280
+ initSchema(db);
281
+ const id = uuidv4();
282
+ const confidence = Math.max(0, Math.min(1, Number(cmdOpts.confidence ?? 0.7)));
283
+ const fact = insertFact(db, {
284
+ id,
285
+ subject,
286
+ predicate,
287
+ object,
288
+ confidence,
289
+ source_item_id: cmdOpts.sourceItemId ?? null,
290
+ entity_id: cmdOpts.entityId ?? null,
291
+ });
292
+ console.log(JSON.stringify({ ok: true, fact }));
293
+ });
294
+ });
295
+
296
+ program
297
+ .command('list-facts')
298
+ .description('List all facts (optionally filtered by entity)')
299
+ .option('--entity-id <entityId>', 'Filter by entity')
300
+ .option('--limit <n>', 'Max results (default 50)', '50')
301
+ .action((cmdOpts) => {
302
+ withDb((dbPath) => {
303
+ const db = openDb(dbPath);
304
+ initSchema(db);
305
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
306
+ const facts = getAllFacts(db, cmdOpts.entityId, limit);
307
+ console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
308
+ });
309
+ });
310
+
311
+ program
312
+ .command('get-facts-by-subject <subject>')
313
+ .description('Get all facts about a specific subject')
314
+ .option('--limit <n>', 'Max results (default 50)', '50')
315
+ .action((subject: string, cmdOpts) => {
316
+ withDb((dbPath) => {
317
+ const db = openDb(dbPath);
318
+ initSchema(db);
319
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
320
+ const facts = getFactsBySubject(db, subject, limit);
321
+ console.log(JSON.stringify({ ok: true, subject, count: facts.length, facts }));
322
+ });
323
+ });
324
+
325
+ program
326
+ .command('search-facts <query>')
327
+ .description('Search facts by subject, predicate, or object')
328
+ .option('--limit <n>', 'Max results (default 50)', '50')
329
+ .action((query: string, cmdOpts) => {
330
+ withDb((dbPath) => {
331
+ const db = openDb(dbPath);
332
+ initSchema(db);
333
+ const limit = Math.max(1, Math.min(500, Number(cmdOpts.limit ?? 50)));
334
+ const facts = searchFacts(db, query, limit);
335
+ console.log(JSON.stringify({ ok: true, query, count: facts.length, facts }));
336
+ });
337
+ });
338
+
339
+ program
340
+ .command('list-subjects')
341
+ .description('List all distinct subjects in the facts table')
342
+ .action(() => {
343
+ withDb((dbPath) => {
344
+ const db = openDb(dbPath);
345
+ initSchema(db);
346
+ const subjects = listSubjects(db);
347
+ console.log(JSON.stringify({ ok: true, subjects, count: subjects.length }));
348
+ });
349
+ });
350
+
351
+ program
352
+ .command('list-predicates')
353
+ .description('List all distinct predicates in the facts table')
354
+ .action(() => {
355
+ withDb((dbPath) => {
356
+ const db = openDb(dbPath);
357
+ initSchema(db);
358
+ const predicates = listPredicates(db);
359
+ console.log(JSON.stringify({ ok: true, predicates, count: predicates.length }));
360
+ });
361
+ });
362
+
363
+ program
364
+ .command('delete-fact <factId>')
365
+ .description('Delete a fact by ID')
366
+ .action((factId: string) => {
367
+ withDb((dbPath) => {
368
+ const db = openDb(dbPath);
369
+ initSchema(db);
370
+ const deleted = deleteFact(db, factId);
371
+ console.log(JSON.stringify({ ok: true, deleted, id: factId }));
372
+ });
373
+ });
374
+
375
+ program
376
+ .command('extract-facts [text]')
377
+ .description('Extract potential facts from text (pattern-based, does not store)')
378
+ .action((text: string | undefined) => {
379
+ const input = text ?? fs.readFileSync(0, 'utf-8');
380
+ const facts = extractFactsSimple(input);
381
+ console.log(JSON.stringify({ ok: true, count: facts.length, facts }));
382
+ });
383
+
257
384
  program.parse();