@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.
- package/dist/cli.js +111 -1
- package/package.json +2 -2
- 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,
|
|
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.
|
|
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.
|
|
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();
|