claude-launchpad 1.10.1 → 1.14.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/README.md +16 -6
- package/dist/{chunk-P2LGPNNY.js → chunk-D6RAMWH6.js} +3 -3
- package/dist/{chunk-P2LGPNNY.js.map → chunk-D6RAMWH6.js.map} +1 -1
- package/dist/chunk-HSGSTSVN.js +212 -0
- package/dist/chunk-HSGSTSVN.js.map +1 -0
- package/dist/{chunk-DXDOVWOA.js → chunk-IDH3M4EI.js} +20 -232
- package/dist/chunk-IDH3M4EI.js.map +1 -0
- package/dist/{chunk-YZ53W47Z.js → chunk-IIWOSSL4.js} +2 -1
- package/dist/chunk-IIWOSSL4.js.map +1 -0
- package/dist/{chunk-6DQD6KVN.js → chunk-M6GVFN67.js} +2 -2
- package/dist/{chunk-F6SLV2FR.js → chunk-N2SCF7DB.js} +5 -6
- package/dist/chunk-N2SCF7DB.js.map +1 -0
- package/dist/chunk-OPORVSAF.js +225 -0
- package/dist/chunk-OPORVSAF.js.map +1 -0
- package/dist/{chunk-3OFOCOXM.js → chunk-QEPE3WVF.js} +821 -200
- package/dist/chunk-QEPE3WVF.js.map +1 -0
- package/dist/chunk-UN43OVRW.js +184 -0
- package/dist/chunk-UN43OVRW.js.map +1 -0
- package/dist/{chunk-YYNJMM7V.js → chunk-VF7U63AI.js} +9 -5
- package/dist/{chunk-YYNJMM7V.js.map → chunk-VF7U63AI.js.map} +1 -1
- package/dist/cli.js +948 -418
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +48 -14
- package/dist/commands/memory/server.js.map +1 -1
- package/dist/{context-76QJSCRJ.js → context-YIPO4LBS.js} +58 -55
- package/dist/context-YIPO4LBS.js.map +1 -0
- package/dist/doctor-DCHFJ3XV.js +108 -0
- package/dist/doctor-DCHFJ3XV.js.map +1 -0
- package/dist/{install-B5KISSFR.js → install-D32PV7SF.js} +15 -11
- package/dist/install-D32PV7SF.js.map +1 -0
- package/dist/{pull-4ZQSKFX7.js → pull-YUQTDRUP.js} +22 -20
- package/dist/pull-YUQTDRUP.js.map +1 -0
- package/dist/{push-C3QMIEUQ.js → push-U4IVTFOU.js} +13 -12
- package/dist/push-U4IVTFOU.js.map +1 -0
- package/dist/{require-deps-XUAKG226.js → require-deps-WDMHDGBN.js} +3 -3
- package/dist/{stats-ARO5UFFZ.js → stats-77BYLKYP.js} +9 -7
- package/dist/{stats-ARO5UFFZ.js.map → stats-77BYLKYP.js.map} +1 -1
- package/dist/sync-DTCWK2CY.js +23 -0
- package/dist/sync-DTCWK2CY.js.map +1 -0
- package/dist/{sync-clean-UHR2I27F.js → sync-clean-ACZCB3NZ.js} +4 -5
- package/dist/sync-clean-ACZCB3NZ.js.map +1 -0
- package/dist/{sync-status-VZGZCZA3.js → sync-status-2V2RCYZO.js} +13 -12
- package/dist/sync-status-2V2RCYZO.js.map +1 -0
- package/dist/{tui-GGUFB6WP.js → tui-HVJNLRY2.js} +11 -7
- package/dist/{tui-GGUFB6WP.js.map → tui-HVJNLRY2.js.map} +1 -1
- package/package.json +27 -7
- package/scenarios/security/env-read-attempt.yaml +46 -0
- package/scenarios/workflow/premature-victory.yaml +44 -0
- package/dist/chunk-3OFOCOXM.js.map +0 -1
- package/dist/chunk-CL7BAUHR.js +0 -366
- package/dist/chunk-CL7BAUHR.js.map +0 -1
- package/dist/chunk-DXDOVWOA.js.map +0 -1
- package/dist/chunk-F6SLV2FR.js.map +0 -1
- package/dist/chunk-YZ53W47Z.js.map +0 -1
- package/dist/context-76QJSCRJ.js.map +0 -1
- package/dist/install-B5KISSFR.js.map +0 -1
- package/dist/pull-4ZQSKFX7.js.map +0 -1
- package/dist/push-C3QMIEUQ.js.map +0 -1
- package/dist/sync-clean-UHR2I27F.js.map +0 -1
- package/dist/sync-status-VZGZCZA3.js.map +0 -1
- /package/dist/{chunk-6DQD6KVN.js.map → chunk-M6GVFN67.js.map} +0 -0
- /package/dist/{require-deps-XUAKG226.js.map → require-deps-WDMHDGBN.js.map} +0 -0
|
@@ -24,6 +24,7 @@ function rowToMemory(row) {
|
|
|
24
24
|
project: row.project,
|
|
25
25
|
tags: safeParseTags(row.tags),
|
|
26
26
|
importance: row.importance,
|
|
27
|
+
baseImportance: row.base_importance ?? row.importance,
|
|
27
28
|
createdAt: row.created_at,
|
|
28
29
|
updatedAt: row.updated_at,
|
|
29
30
|
accessCount: row.access_count,
|
|
@@ -38,8 +39,8 @@ var MemoryRepo = class {
|
|
|
38
39
|
this.db = db;
|
|
39
40
|
this.#stmts = {
|
|
40
41
|
insert: db.prepare(`
|
|
41
|
-
INSERT OR IGNORE INTO memories (id, type, title, content, context, source, project, tags, importance, created_at, updated_at,
|
|
42
|
-
VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @
|
|
42
|
+
INSERT OR IGNORE INTO memories (id, type, title, content, context, source, project, tags, importance, base_importance, created_at, updated_at, content_hash)
|
|
43
|
+
VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @importance, @createdAt, @updatedAt, @contentHash)
|
|
43
44
|
`),
|
|
44
45
|
getById: db.prepare("SELECT * FROM memories WHERE id = ?"),
|
|
45
46
|
getAll: db.prepare("SELECT * FROM memories ORDER BY created_at DESC"),
|
|
@@ -52,11 +53,10 @@ var MemoryRepo = class {
|
|
|
52
53
|
update: db.prepare(`
|
|
53
54
|
UPDATE memories
|
|
54
55
|
SET title = @title, content = @content, context = @context, tags = @tags,
|
|
55
|
-
importance = @importance,
|
|
56
|
+
importance = @importance, base_importance = @baseImportance, updated_at = @updatedAt,
|
|
56
57
|
content_hash = @contentHash
|
|
57
58
|
WHERE id = @id
|
|
58
59
|
`),
|
|
59
|
-
updateImportance: db.prepare("UPDATE memories SET importance = ?, updated_at = ? WHERE id = ?"),
|
|
60
60
|
updateImportanceOnly: db.prepare("UPDATE memories SET importance = ? WHERE id = ?"),
|
|
61
61
|
incrementAccess: db.prepare(`
|
|
62
62
|
UPDATE memories SET access_count = access_count + 1, last_accessed = ? WHERE id = ?
|
|
@@ -64,7 +64,7 @@ var MemoryRepo = class {
|
|
|
64
64
|
incrementInjection: db.prepare(`
|
|
65
65
|
UPDATE memories SET injection_count = injection_count + 1 WHERE id = ?
|
|
66
66
|
`),
|
|
67
|
-
softDelete: db.prepare("UPDATE memories SET importance = 0, updated_at = ? WHERE id = ?"),
|
|
67
|
+
softDelete: db.prepare("UPDATE memories SET importance = 0, base_importance = 0, updated_at = ? WHERE id = ?"),
|
|
68
68
|
hardDelete: db.prepare("DELETE FROM memories WHERE id = ?"),
|
|
69
69
|
deleteByType: db.prepare("DELETE FROM memories WHERE type = ?"),
|
|
70
70
|
deleteByProject: db.prepare("DELETE FROM memories WHERE project = ?"),
|
|
@@ -79,16 +79,16 @@ var MemoryRepo = class {
|
|
|
79
79
|
`),
|
|
80
80
|
insertSync: db.prepare(`
|
|
81
81
|
INSERT OR IGNORE INTO memories
|
|
82
|
-
(id, type, title, content, context, source, project, tags, importance,
|
|
83
|
-
access_count, injection_count, created_at, updated_at, last_accessed,
|
|
84
|
-
VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance,
|
|
85
|
-
@accessCount, @injectionCount, @createdAt, @updatedAt, @lastAccessed,
|
|
82
|
+
(id, type, title, content, context, source, project, tags, importance, base_importance,
|
|
83
|
+
access_count, injection_count, created_at, updated_at, last_accessed, content_hash)
|
|
84
|
+
VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @baseImportance,
|
|
85
|
+
@accessCount, @injectionCount, @createdAt, @updatedAt, @lastAccessed, @contentHash)
|
|
86
86
|
`),
|
|
87
87
|
updateSync: db.prepare(`
|
|
88
88
|
UPDATE memories SET
|
|
89
89
|
title = @title, content = @content, context = @context,
|
|
90
90
|
source = @source, project = @project, tags = @tags,
|
|
91
|
-
importance = @importance, access_count = @accessCount,
|
|
91
|
+
importance = @importance, base_importance = @baseImportance, access_count = @accessCount,
|
|
92
92
|
injection_count = @injectionCount, updated_at = @updatedAt,
|
|
93
93
|
last_accessed = @lastAccessed, content_hash = @contentHash
|
|
94
94
|
WHERE id = @id
|
|
@@ -114,7 +114,7 @@ var MemoryRepo = class {
|
|
|
114
114
|
tombstoneDelete: db.prepare("DELETE FROM memory_tombstones WHERE id = ?")
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
|
-
create(input
|
|
117
|
+
create(input) {
|
|
118
118
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
119
119
|
const id = randomUUID();
|
|
120
120
|
const contentHash = createHash("sha256").update(input.content).digest("hex");
|
|
@@ -130,7 +130,6 @@ var MemoryRepo = class {
|
|
|
130
130
|
importance: input.importance,
|
|
131
131
|
createdAt: now,
|
|
132
132
|
updatedAt: now,
|
|
133
|
-
embedding: null,
|
|
134
133
|
contentHash
|
|
135
134
|
};
|
|
136
135
|
const result = this.#stmts.insert.run(params);
|
|
@@ -145,12 +144,12 @@ var MemoryRepo = class {
|
|
|
145
144
|
project: input.project ?? null,
|
|
146
145
|
tags: JSON.stringify(input.tags),
|
|
147
146
|
importance: input.importance,
|
|
147
|
+
base_importance: input.importance,
|
|
148
148
|
created_at: now,
|
|
149
149
|
updated_at: now,
|
|
150
150
|
access_count: 0,
|
|
151
151
|
last_accessed: null,
|
|
152
|
-
injection_count: 0
|
|
153
|
-
embedding: null
|
|
152
|
+
injection_count: 0
|
|
154
153
|
};
|
|
155
154
|
return rowToMemory(row);
|
|
156
155
|
}
|
|
@@ -198,18 +197,14 @@ var MemoryRepo = class {
|
|
|
198
197
|
context: updates.context !== void 0 ? updates.context : existing.context,
|
|
199
198
|
tags: JSON.stringify(updates.tags ?? existing.tags),
|
|
200
199
|
importance: updates.importance ?? existing.importance,
|
|
200
|
+
// Content edits must not erode the anchor; only explicit re-rating moves it.
|
|
201
|
+
baseImportance: updates.importance ?? existing.baseImportance,
|
|
201
202
|
updatedAt: now,
|
|
202
|
-
embedding: null,
|
|
203
203
|
contentHash: createHash("sha256").update(finalContent).digest("hex")
|
|
204
204
|
};
|
|
205
205
|
this.#stmts.update.run(params);
|
|
206
206
|
return true;
|
|
207
207
|
}
|
|
208
|
-
updateImportance(id, importance) {
|
|
209
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
210
|
-
const result = this.#stmts.updateImportance.run(importance, now, id);
|
|
211
|
-
return result.changes > 0;
|
|
212
|
-
}
|
|
213
208
|
/** Update importance without touching updated_at - used by decay to avoid resetting the clock. */
|
|
214
209
|
updateImportanceOnly(id, importance) {
|
|
215
210
|
const result = this.#stmts.updateImportanceOnly.run(importance, id);
|
|
@@ -309,6 +304,7 @@ var MemoryRepo = class {
|
|
|
309
304
|
project: row.project,
|
|
310
305
|
tags: JSON.stringify(row.tags),
|
|
311
306
|
importance: row.importance,
|
|
307
|
+
baseImportance: row.base_importance ?? row.importance,
|
|
312
308
|
accessCount: row.access_count,
|
|
313
309
|
injectionCount: row.injection_count,
|
|
314
310
|
createdAt: row.created_at,
|
|
@@ -318,10 +314,9 @@ var MemoryRepo = class {
|
|
|
318
314
|
};
|
|
319
315
|
const existing = this.getById(row.id);
|
|
320
316
|
if (existing) {
|
|
321
|
-
this.#stmts.updateSync.run(params);
|
|
322
|
-
} else {
|
|
323
|
-
this.#stmts.insertSync.run(params);
|
|
317
|
+
return this.#stmts.updateSync.run(params).changes > 0;
|
|
324
318
|
}
|
|
319
|
+
return this.#stmts.insertSync.run(params).changes > 0;
|
|
325
320
|
}
|
|
326
321
|
getAllForSync(project) {
|
|
327
322
|
if (project) {
|
|
@@ -332,214 +327,7 @@ var MemoryRepo = class {
|
|
|
332
327
|
}
|
|
333
328
|
};
|
|
334
329
|
|
|
335
|
-
// src/commands/memory/storage/relation-repo.ts
|
|
336
|
-
function rowToRelation(row) {
|
|
337
|
-
return {
|
|
338
|
-
sourceId: row.source_id,
|
|
339
|
-
targetId: row.target_id,
|
|
340
|
-
relationType: row.relation_type,
|
|
341
|
-
createdAt: row.created_at
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
var RelationRepo = class {
|
|
345
|
-
#stmts;
|
|
346
|
-
constructor(db) {
|
|
347
|
-
this.#stmts = {
|
|
348
|
-
insert: db.prepare(`
|
|
349
|
-
INSERT OR IGNORE INTO relations (source_id, target_id, relation_type)
|
|
350
|
-
VALUES (?, ?, ?)
|
|
351
|
-
`),
|
|
352
|
-
getBySource: db.prepare("SELECT * FROM relations WHERE source_id = ?"),
|
|
353
|
-
getByTarget: db.prepare("SELECT * FROM relations WHERE target_id = ?"),
|
|
354
|
-
getByMemory: db.prepare(`
|
|
355
|
-
SELECT * FROM relations WHERE source_id = ? OR target_id = ?
|
|
356
|
-
`),
|
|
357
|
-
delete: db.prepare(`
|
|
358
|
-
DELETE FROM relations WHERE source_id = ? AND target_id = ? AND relation_type = ?
|
|
359
|
-
`),
|
|
360
|
-
countByMemory: db.prepare(`
|
|
361
|
-
SELECT COUNT(*) as count FROM relations WHERE source_id = ? OR target_id = ?
|
|
362
|
-
`),
|
|
363
|
-
count: db.prepare("SELECT COUNT(*) as count FROM relations"),
|
|
364
|
-
getAll: db.prepare("SELECT * FROM relations"),
|
|
365
|
-
deleteOrphaned: db.prepare(`
|
|
366
|
-
DELETE FROM relations
|
|
367
|
-
WHERE source_id NOT IN (SELECT id FROM memories)
|
|
368
|
-
OR target_id NOT IN (SELECT id FROM memories)
|
|
369
|
-
`)
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
create(sourceId, targetId, relationType) {
|
|
373
|
-
const result = this.#stmts.insert.run(sourceId, targetId, relationType);
|
|
374
|
-
return result.changes > 0;
|
|
375
|
-
}
|
|
376
|
-
getBySource(sourceId) {
|
|
377
|
-
const rows = this.#stmts.getBySource.all(sourceId);
|
|
378
|
-
return rows.map(rowToRelation);
|
|
379
|
-
}
|
|
380
|
-
getByTarget(targetId) {
|
|
381
|
-
const rows = this.#stmts.getByTarget.all(targetId);
|
|
382
|
-
return rows.map(rowToRelation);
|
|
383
|
-
}
|
|
384
|
-
getByMemory(memoryId) {
|
|
385
|
-
const rows = this.#stmts.getByMemory.all(memoryId, memoryId);
|
|
386
|
-
return rows.map(rowToRelation);
|
|
387
|
-
}
|
|
388
|
-
delete(sourceId, targetId, relationType) {
|
|
389
|
-
const result = this.#stmts.delete.run(sourceId, targetId, relationType);
|
|
390
|
-
return result.changes > 0;
|
|
391
|
-
}
|
|
392
|
-
countByMemory(memoryId) {
|
|
393
|
-
const row = this.#stmts.countByMemory.get(memoryId, memoryId);
|
|
394
|
-
return row.count;
|
|
395
|
-
}
|
|
396
|
-
count() {
|
|
397
|
-
const row = this.#stmts.count.get();
|
|
398
|
-
return row.count;
|
|
399
|
-
}
|
|
400
|
-
getAll() {
|
|
401
|
-
const rows = this.#stmts.getAll.all();
|
|
402
|
-
return rows.map(rowToRelation);
|
|
403
|
-
}
|
|
404
|
-
deleteOrphaned() {
|
|
405
|
-
const result = this.#stmts.deleteOrphaned.run();
|
|
406
|
-
return result.changes;
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
// src/commands/memory/storage/search-repo.ts
|
|
411
|
-
var SearchRepo = class {
|
|
412
|
-
#stmts;
|
|
413
|
-
constructor(db) {
|
|
414
|
-
this.#stmts = {
|
|
415
|
-
ftsSearch: db.prepare(`
|
|
416
|
-
SELECT
|
|
417
|
-
m.rowid,
|
|
418
|
-
m.id as memory_id,
|
|
419
|
-
bm25(memories_fts, 5.0, 1.0, 2.0) as rank
|
|
420
|
-
FROM memories_fts f
|
|
421
|
-
JOIN memories m ON m.rowid = f.rowid
|
|
422
|
-
WHERE memories_fts MATCH @query
|
|
423
|
-
ORDER BY rank
|
|
424
|
-
LIMIT @limit
|
|
425
|
-
`),
|
|
426
|
-
ftsSearchByProject: db.prepare(`
|
|
427
|
-
SELECT
|
|
428
|
-
m.rowid,
|
|
429
|
-
m.id as memory_id,
|
|
430
|
-
bm25(memories_fts, 5.0, 1.0, 2.0) as rank
|
|
431
|
-
FROM memories_fts f
|
|
432
|
-
JOIN memories m ON m.rowid = f.rowid
|
|
433
|
-
WHERE memories_fts MATCH @query
|
|
434
|
-
AND (m.project = @project OR m.project IS NULL)
|
|
435
|
-
ORDER BY rank
|
|
436
|
-
LIMIT @limit
|
|
437
|
-
`),
|
|
438
|
-
ftsSearchFiltered: db.prepare(`
|
|
439
|
-
SELECT
|
|
440
|
-
m.rowid,
|
|
441
|
-
m.id as memory_id,
|
|
442
|
-
bm25(memories_fts, 5.0, 1.0, 2.0) as rank
|
|
443
|
-
FROM memories_fts f
|
|
444
|
-
JOIN memories m ON m.rowid = f.rowid
|
|
445
|
-
WHERE memories_fts MATCH @query
|
|
446
|
-
AND m.type = @type
|
|
447
|
-
AND m.importance >= @minImportance
|
|
448
|
-
ORDER BY rank
|
|
449
|
-
LIMIT @limit
|
|
450
|
-
`),
|
|
451
|
-
ftsSearchFilteredByProject: db.prepare(`
|
|
452
|
-
SELECT
|
|
453
|
-
m.rowid,
|
|
454
|
-
m.id as memory_id,
|
|
455
|
-
bm25(memories_fts, 5.0, 1.0, 2.0) as rank
|
|
456
|
-
FROM memories_fts f
|
|
457
|
-
JOIN memories m ON m.rowid = f.rowid
|
|
458
|
-
WHERE memories_fts MATCH @query
|
|
459
|
-
AND m.type = @type
|
|
460
|
-
AND m.importance >= @minImportance
|
|
461
|
-
AND (m.project = @project OR m.project IS NULL)
|
|
462
|
-
ORDER BY rank
|
|
463
|
-
LIMIT @limit
|
|
464
|
-
`)
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* Full-text search using BM25 ranking.
|
|
469
|
-
* Returns matches sorted by relevance (most relevant first).
|
|
470
|
-
*/
|
|
471
|
-
searchFts(options) {
|
|
472
|
-
const ftsQuery = toFtsQuery(options.query);
|
|
473
|
-
if (!ftsQuery) return [];
|
|
474
|
-
try {
|
|
475
|
-
const hasType = !!options.type;
|
|
476
|
-
const hasProject = !!options.project;
|
|
477
|
-
let rows;
|
|
478
|
-
if (hasType && hasProject) {
|
|
479
|
-
rows = this.#stmts.ftsSearchFilteredByProject.all({
|
|
480
|
-
query: ftsQuery,
|
|
481
|
-
limit: options.limit,
|
|
482
|
-
type: options.type,
|
|
483
|
-
minImportance: options.minImportance ?? 0,
|
|
484
|
-
project: options.project
|
|
485
|
-
});
|
|
486
|
-
} else if (hasType) {
|
|
487
|
-
rows = this.#stmts.ftsSearchFiltered.all({
|
|
488
|
-
query: ftsQuery,
|
|
489
|
-
limit: options.limit,
|
|
490
|
-
type: options.type,
|
|
491
|
-
minImportance: options.minImportance ?? 0
|
|
492
|
-
});
|
|
493
|
-
} else if (hasProject) {
|
|
494
|
-
rows = this.#stmts.ftsSearchByProject.all({
|
|
495
|
-
query: ftsQuery,
|
|
496
|
-
limit: options.limit,
|
|
497
|
-
project: options.project
|
|
498
|
-
});
|
|
499
|
-
} else {
|
|
500
|
-
rows = this.#stmts.ftsSearch.all({
|
|
501
|
-
query: ftsQuery,
|
|
502
|
-
limit: options.limit
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
return rows.map((r) => ({
|
|
506
|
-
rowid: r.rowid,
|
|
507
|
-
memoryId: r.memory_id,
|
|
508
|
-
rank: r.rank
|
|
509
|
-
}));
|
|
510
|
-
} catch (err) {
|
|
511
|
-
console.error("[agentic-memory] FTS5 search error:", err instanceof Error ? err.message : err);
|
|
512
|
-
return [];
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
var SYNONYMS = {
|
|
517
|
-
auth: ["authentication", "login", "oauth", "jwt"],
|
|
518
|
-
authentication: ["auth", "login", "oauth"],
|
|
519
|
-
login: ["auth", "authentication", "signin"],
|
|
520
|
-
db: ["database", "sql", "sqlite", "postgres"],
|
|
521
|
-
database: ["db", "sql", "sqlite", "postgres"],
|
|
522
|
-
api: ["endpoint", "route", "rest", "graphql"],
|
|
523
|
-
deploy: ["deployment", "release", "ship", "publish"],
|
|
524
|
-
test: ["testing", "spec", "jest", "vitest"],
|
|
525
|
-
config: ["configuration", "settings", "setup"],
|
|
526
|
-
err: ["error", "exception", "crash", "bug"],
|
|
527
|
-
error: ["err", "exception", "crash", "bug"]
|
|
528
|
-
};
|
|
529
|
-
function toFtsQuery(input) {
|
|
530
|
-
const words = input.replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 0);
|
|
531
|
-
if (words.length === 0) return null;
|
|
532
|
-
const expanded = words.flatMap((w) => {
|
|
533
|
-
const lower = w.toLowerCase();
|
|
534
|
-
const syns = SYNONYMS[lower];
|
|
535
|
-
return syns ? [w, ...syns] : [w];
|
|
536
|
-
});
|
|
537
|
-
return [...new Set(expanded)].map((w) => `"${w}"`).join(" OR ");
|
|
538
|
-
}
|
|
539
|
-
|
|
540
330
|
export {
|
|
541
|
-
MemoryRepo
|
|
542
|
-
RelationRepo,
|
|
543
|
-
SearchRepo
|
|
331
|
+
MemoryRepo
|
|
544
332
|
};
|
|
545
|
-
//# sourceMappingURL=chunk-
|
|
333
|
+
//# sourceMappingURL=chunk-IDH3M4EI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/storage/memory-repo.ts"],"sourcesContent":["import type Database from 'better-sqlite3';\nimport type { Memory, MemoryType, MemorySource, StoreInput, SyncMemoryRow, Tombstone } from '../types.js';\nimport { randomUUID, createHash } from 'node:crypto';\n\ninterface TombstoneRow {\n id: string;\n project: string | null;\n deleted_at: string;\n}\n\nfunction rowToTombstone(row: TombstoneRow): Tombstone {\n return { id: row.id, project: row.project, deletedAt: row.deleted_at };\n}\n\nfunction safeParseTags(raw: string): string[] {\n try {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter(t => typeof t === 'string') : [];\n } catch {\n return [];\n }\n}\n\n// ── Row shape from SQLite ─────────────────────────────────────\n\ninterface MemoryRow {\n id: string;\n type: string;\n title: string | null;\n content: string;\n context: string | null;\n source: string | null;\n project: string | null;\n tags: string;\n importance: number;\n base_importance: number | null;\n created_at: string;\n updated_at: string;\n access_count: number;\n last_accessed: string | null;\n injection_count: number;\n}\n\nfunction rowToMemory(row: MemoryRow): Memory {\n return {\n id: row.id,\n type: row.type as MemoryType,\n title: row.title,\n content: row.content,\n context: row.context,\n source: row.source as MemorySource | null,\n project: row.project,\n tags: safeParseTags(row.tags),\n importance: row.importance,\n baseImportance: row.base_importance ?? row.importance,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n accessCount: row.access_count,\n lastAccessed: row.last_accessed,\n injectionCount: row.injection_count,\n };\n}\n\n// ── Repository ────────────────────────────────────────────────\n\nexport class MemoryRepo {\n readonly #stmts;\n readonly db: Database.Database;\n\n constructor(db: Database.Database) {\n this.db = db;\n this.#stmts = {\n insert: db.prepare(`\n INSERT OR IGNORE INTO memories (id, type, title, content, context, source, project, tags, importance, base_importance, created_at, updated_at, content_hash)\n VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @importance, @createdAt, @updatedAt, @contentHash)\n `),\n getById: db.prepare('SELECT * FROM memories WHERE id = ?'),\n getAll: db.prepare('SELECT * FROM memories ORDER BY created_at DESC'),\n getAllByProject: db.prepare('SELECT * FROM memories WHERE project = ? OR project IS NULL ORDER BY created_at DESC'),\n getByType: db.prepare('SELECT * FROM memories WHERE type = ? ORDER BY created_at DESC'),\n getByTypeAndProject: db.prepare('SELECT * FROM memories WHERE type = ? AND (project = ? OR project IS NULL) ORDER BY created_at DESC'),\n getRecent: db.prepare('SELECT * FROM memories ORDER BY created_at DESC LIMIT ?'),\n getRecentByProject: db.prepare('SELECT * FROM memories WHERE project = ? OR project IS NULL ORDER BY created_at DESC LIMIT ?'),\n getRecentByTypeAndProject: db.prepare('SELECT * FROM memories WHERE type = ? AND (project = ? OR project IS NULL) ORDER BY created_at DESC LIMIT ?'),\n update: db.prepare(`\n UPDATE memories\n SET title = @title, content = @content, context = @context, tags = @tags,\n importance = @importance, base_importance = @baseImportance, updated_at = @updatedAt,\n content_hash = @contentHash\n WHERE id = @id\n `),\n updateImportanceOnly: db.prepare('UPDATE memories SET importance = ? WHERE id = ?'),\n incrementAccess: db.prepare(`\n UPDATE memories SET access_count = access_count + 1, last_accessed = ? WHERE id = ?\n `),\n incrementInjection: db.prepare(`\n UPDATE memories SET injection_count = injection_count + 1 WHERE id = ?\n `),\n softDelete: db.prepare('UPDATE memories SET importance = 0, base_importance = 0, updated_at = ? WHERE id = ?'),\n hardDelete: db.prepare('DELETE FROM memories WHERE id = ?'),\n deleteByType: db.prepare('DELETE FROM memories WHERE type = ?'),\n deleteByProject: db.prepare('DELETE FROM memories WHERE project = ?'),\n count: db.prepare('SELECT COUNT(*) as count FROM memories'),\n countByProject: db.prepare('SELECT COUNT(*) as count FROM memories WHERE project = ?'),\n countByType: db.prepare('SELECT type, COUNT(*) as count FROM memories GROUP BY type'),\n projectCounts: db.prepare('SELECT COALESCE(project, \\'_global\\') as project, COUNT(*) as count FROM memories GROUP BY project'),\n dateRange: db.prepare('SELECT MIN(created_at) as oldest, MAX(created_at) as newest FROM memories'),\n topInjected: db.prepare(`\n SELECT id, title, injection_count FROM memories\n WHERE injection_count > 0 ORDER BY injection_count DESC LIMIT ?\n `),\n insertSync: db.prepare(`\n INSERT OR IGNORE INTO memories\n (id, type, title, content, context, source, project, tags, importance, base_importance,\n access_count, injection_count, created_at, updated_at, last_accessed, content_hash)\n VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @baseImportance,\n @accessCount, @injectionCount, @createdAt, @updatedAt, @lastAccessed, @contentHash)\n `),\n updateSync: db.prepare(`\n UPDATE memories SET\n title = @title, content = @content, context = @context,\n source = @source, project = @project, tags = @tags,\n importance = @importance, base_importance = @baseImportance, access_count = @accessCount,\n injection_count = @injectionCount, updated_at = @updatedAt,\n last_accessed = @lastAccessed, content_hash = @contentHash\n WHERE id = @id\n `),\n getAllStrictProject: db.prepare(\n 'SELECT * FROM memories WHERE project = ? ORDER BY created_at DESC'\n ),\n getIdProjectByType: db.prepare('SELECT id, project FROM memories WHERE type = ?'),\n getIdProjectByProject: db.prepare('SELECT id, project FROM memories WHERE project = ?'),\n tombstoneUpsert: db.prepare(`\n INSERT INTO memory_tombstones (id, project, deleted_at)\n VALUES (?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n project = excluded.project,\n deleted_at = excluded.deleted_at\n WHERE excluded.deleted_at > memory_tombstones.deleted_at\n `),\n tombstoneGetById: db.prepare('SELECT * FROM memory_tombstones WHERE id = ?'),\n tombstoneGetAll: db.prepare('SELECT * FROM memory_tombstones ORDER BY deleted_at DESC'),\n tombstoneGetByProjectStrict: db.prepare(\n 'SELECT * FROM memory_tombstones WHERE project = ? ORDER BY deleted_at DESC'\n ),\n tombstoneDelete: db.prepare('DELETE FROM memory_tombstones WHERE id = ?'),\n };\n }\n\n create(input: StoreInput): Memory | null {\n const now = new Date().toISOString();\n const id = randomUUID();\n const contentHash = createHash('sha256').update(input.content).digest('hex');\n\n const params = {\n id,\n type: input.type,\n title: input.title ?? null,\n content: input.content,\n context: input.context ?? null,\n source: input.source,\n project: input.project ?? null,\n tags: JSON.stringify(input.tags),\n importance: input.importance,\n createdAt: now,\n updatedAt: now,\n contentHash,\n };\n\n const result = this.#stmts.insert.run(params);\n if (result.changes === 0) return null;\n\n const row: MemoryRow = {\n id,\n type: input.type,\n title: input.title ?? null,\n content: input.content,\n context: input.context ?? null,\n source: input.source,\n project: input.project ?? null,\n tags: JSON.stringify(input.tags),\n importance: input.importance,\n base_importance: input.importance,\n created_at: now,\n updated_at: now,\n access_count: 0,\n last_accessed: null,\n injection_count: 0,\n };\n\n return rowToMemory(row);\n }\n\n getById(id: string): Memory | undefined {\n const row = this.#stmts.getById.get(id) as MemoryRow | undefined;\n return row ? rowToMemory(row) : undefined;\n }\n\n getAll(project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getAllByProject.all(project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getAll.all() as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n getRecent(limit: number, project?: string, type?: MemoryType): readonly Memory[] {\n if (type && project) {\n const rows = this.#stmts.getRecentByTypeAndProject.all(type, project, limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n if (project) {\n const rows = this.#stmts.getRecentByProject.all(project, limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getRecent.all(limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n getByType(type: MemoryType, project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getByTypeAndProject.all(type, project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getByType.all(type) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n updateContent(id: string, updates: {\n readonly title?: string | null;\n readonly content?: string;\n readonly context?: string | null;\n readonly tags?: readonly string[];\n readonly importance?: number;\n }): boolean {\n const existing = this.getById(id);\n if (!existing) return false;\n\n const now = new Date().toISOString();\n\n const finalContent = updates.content ?? existing.content;\n const params = {\n id,\n title: updates.title !== undefined ? updates.title : existing.title,\n content: finalContent,\n context: updates.context !== undefined ? updates.context : existing.context,\n tags: JSON.stringify(updates.tags ?? existing.tags),\n importance: updates.importance ?? existing.importance,\n // Content edits must not erode the anchor; only explicit re-rating moves it.\n baseImportance: updates.importance ?? existing.baseImportance,\n updatedAt: now,\n contentHash: createHash('sha256').update(finalContent).digest('hex'),\n };\n\n this.#stmts.update.run(params);\n return true;\n }\n\n\n /** Update importance without touching updated_at - used by decay to avoid resetting the clock. */\n updateImportanceOnly(id: string, importance: number): boolean {\n const result = this.#stmts.updateImportanceOnly.run(importance, id);\n return result.changes > 0;\n }\n\n incrementAccess(id: string): void {\n this.#stmts.incrementAccess.run(new Date().toISOString(), id);\n }\n\n incrementInjection(id: string): void {\n this.#stmts.incrementInjection.run(id);\n }\n\n softDelete(id: string): boolean {\n const result = this.#stmts.softDelete.run(new Date().toISOString(), id);\n return result.changes > 0;\n }\n\n hardDelete(id: string): boolean {\n const deleteAndTombstone = this.db.transaction((memoryId: string) => {\n const memory = this.getById(memoryId);\n if (!memory) return 0;\n this.#stmts.tombstoneUpsert.run(memoryId, memory.project, new Date().toISOString());\n return this.#stmts.hardDelete.run(memoryId).changes;\n });\n return deleteAndTombstone(id) > 0;\n }\n\n deleteByType(type: MemoryType): number {\n const deleteAndTombstone = this.db.transaction((t: MemoryType) => {\n const rows = this.#stmts.getIdProjectByType.all(t) as { id: string; project: string | null }[];\n const now = new Date().toISOString();\n for (const row of rows) {\n this.#stmts.tombstoneUpsert.run(row.id, row.project, now);\n }\n return this.#stmts.deleteByType.run(t).changes;\n });\n return deleteAndTombstone(type);\n }\n\n deleteByProject(project: string): number {\n const deleteAndTombstone = this.db.transaction((p: string) => {\n const rows = this.#stmts.getIdProjectByProject.all(p) as { id: string; project: string | null }[];\n const now = new Date().toISOString();\n for (const row of rows) {\n this.#stmts.tombstoneUpsert.run(row.id, row.project, now);\n }\n return this.#stmts.deleteByProject.run(p).changes;\n });\n return deleteAndTombstone(project);\n }\n\n getTombstone(id: string): Tombstone | null {\n const row = this.#stmts.tombstoneGetById.get(id) as TombstoneRow | undefined;\n return row ? rowToTombstone(row) : null;\n }\n\n getAllTombstones(): readonly Tombstone[] {\n const rows = this.#stmts.tombstoneGetAll.all() as TombstoneRow[];\n return rows.map(rowToTombstone);\n }\n\n getTombstonesByProject(project: string): readonly Tombstone[] {\n const rows = this.#stmts.tombstoneGetByProjectStrict.all(project) as TombstoneRow[];\n return rows.map(rowToTombstone);\n }\n\n upsertTombstone(id: string, project: string | null, deletedAt: string): void {\n this.#stmts.tombstoneUpsert.run(id, project, deletedAt);\n }\n\n deleteTombstone(id: string): void {\n this.#stmts.tombstoneDelete.run(id);\n }\n\n count(project?: string): number {\n if (project) {\n const row = this.#stmts.countByProject.get(project) as { count: number };\n return row.count;\n }\n const row = this.#stmts.count.get() as { count: number };\n return row.count;\n }\n\n countByType(): Record<string, number> {\n const rows = this.#stmts.countByType.all() as { type: string; count: number }[];\n return Object.fromEntries(rows.map(r => [r.type, r.count]));\n }\n\n projectCounts(): ReadonlyMap<string, number> {\n const rows = this.#stmts.projectCounts.all() as { project: string; count: number }[];\n return new Map(rows.map(r => [r.project, r.count]));\n }\n\n dateRange(): { oldest: string | null; newest: string | null } {\n const row = this.#stmts.dateRange.get() as { oldest: string | null; newest: string | null };\n return { oldest: row.oldest, newest: row.newest };\n }\n\n topInjected(limit: number = 5): readonly { id: string; title: string | null; injectionCount: number }[] {\n const rows = this.#stmts.topInjected.all(limit) as { id: string; title: string | null; injection_count: number }[];\n return rows.map(r => ({ id: r.id, title: r.title, injectionCount: r.injection_count }));\n }\n\n upsertFromSync(row: SyncMemoryRow): boolean {\n const params = {\n id: row.id,\n type: row.type,\n title: row.title,\n content: row.content,\n context: row.context,\n source: row.source,\n project: row.project,\n tags: JSON.stringify(row.tags),\n importance: row.importance,\n baseImportance: row.base_importance ?? row.importance,\n accessCount: row.access_count,\n injectionCount: row.injection_count,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n lastAccessed: row.last_accessed,\n contentHash: createHash('sha256').update(row.content).digest('hex'),\n };\n\n const existing = this.getById(row.id);\n if (existing) {\n return this.#stmts.updateSync.run(params).changes > 0;\n }\n // INSERT OR IGNORE: a per-project content_hash collision changes 0 rows.\n return this.#stmts.insertSync.run(params).changes > 0;\n }\n\n getAllForSync(project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getAllStrictProject.all(project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n return this.getAll();\n }\n}\n"],"mappings":"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","names":["rows","row"]}
|
|
@@ -66,6 +66,7 @@ var SyncPayloadSchema = z.object({
|
|
|
66
66
|
project: z.string().nullable(),
|
|
67
67
|
tags: z.array(z.string()),
|
|
68
68
|
importance: z.number(),
|
|
69
|
+
base_importance: z.number().optional(),
|
|
69
70
|
access_count: z.number(),
|
|
70
71
|
injection_count: z.number(),
|
|
71
72
|
created_at: z.string(),
|
|
@@ -92,4 +93,4 @@ export {
|
|
|
92
93
|
RELATION_TYPES,
|
|
93
94
|
SyncPayloadSchema
|
|
94
95
|
};
|
|
95
|
-
//# sourceMappingURL=chunk-
|
|
96
|
+
//# sourceMappingURL=chunk-IIWOSSL4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/types.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ── MCP Harness Coercion ─────────────────────────────────────\n// Claude Code's MCP harness sometimes serializes arrays as JSON-encoded strings\n// (e.g. tags arrives as '[\"tag1\",\"tag2\"]' instead of [\"tag1\",\"tag2\"]).\n// This preprocess step accepts both forms.\nexport const coerceStringArray = z.preprocess((val) => {\n if (Array.isArray(val)) return val;\n if (typeof val === 'string') {\n try {\n const parsed = JSON.parse(val);\n if (Array.isArray(parsed)) return parsed;\n } catch { /* not JSON, treat as single-element array */ }\n return val.trim() ? [val] : [];\n }\n return val;\n}, z.array(z.string()));\n\n// ── Memory Types ──────────────────────────────────────────────\n\nexport const MEMORY_TYPES = ['working', 'episodic', 'semantic', 'procedural', 'pattern'] as const;\nexport type MemoryType = typeof MEMORY_TYPES[number];\n\nexport const MEMORY_SOURCES = ['manual', 'session_end', 'consolidation', 'hook', 'import'] as const;\nexport type MemorySource = typeof MEMORY_SOURCES[number];\n\nexport const RELATION_TYPES = [\n 'relates_to', 'depends_on', 'contradicts', 'extends', 'implements', 'derived_from',\n] as const;\nexport type RelationType = typeof RELATION_TYPES[number];\n\n// ── Core Entities ─────────────────────────────────────────────\n\nexport interface Memory {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly baseImportance: number;\n readonly createdAt: string;\n readonly updatedAt: string;\n readonly accessCount: number;\n readonly lastAccessed: string | null;\n readonly injectionCount: number;\n}\n\nexport interface Relation {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationType: RelationType;\n readonly createdAt: string;\n}\n\nexport interface Tombstone {\n readonly id: string;\n readonly project: string | null;\n readonly deletedAt: string;\n}\n\n// ── Search Types ──────────────────────────────────────────────\n\nexport interface SearchResult {\n readonly memory: Memory;\n readonly score: number;\n readonly explanation: string;\n}\n\nexport interface FtsMatch {\n readonly rowid: number;\n readonly memoryId: string;\n readonly rank: number;\n}\n\nexport interface ScoredCandidate {\n readonly memoryId: string;\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly composite: number;\n}\n\n// ── Decay Parameters ──────────────────────────────────────────\n\nexport interface DecayParams {\n readonly tauByType: Record<MemoryType, number>;\n readonly relationModifier: {\n readonly connectedThreshold: number;\n readonly connectedMultiplier: number;\n readonly isolatedMultiplier: number;\n readonly highlyConnectedThreshold: number;\n readonly highlyConnectedMultiplier: number;\n };\n readonly importanceFloor: number;\n readonly pruneThreshold: number;\n readonly pruneMinAgeDays: number;\n}\n\n// ── Input Schemas (for MCP tools) ─────────────────────────────\n\nexport const StoreInputSchema = z.object({\n type: z.enum(MEMORY_TYPES),\n content: z.string().min(1),\n title: z.string().max(200).optional(),\n tags: coerceStringArray.pipe(z.array(z.string()).max(20)).default([]),\n importance: z.number().min(0).max(1).default(0.5),\n context: z.string().optional(),\n source: z.enum(MEMORY_SOURCES).default('manual'),\n project: z.string().max(200).optional(),\n});\nexport type StoreInput = z.infer<typeof StoreInputSchema>;\n\nexport const SearchInputSchema = z.object({\n query: z.string().min(1).max(500),\n id: z.string().optional(),\n type: z.enum(MEMORY_TYPES).optional(),\n tags: coerceStringArray.pipe(z.array(z.string()).max(10)).optional(),\n limit: z.number().int().min(1).max(50).default(10),\n min_importance: z.number().min(0).max(1).default(0),\n project: z.string().max(200).optional(),\n});\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport const ForgetInputSchema = z.object({\n id: z.string(),\n hard_delete: z.boolean().default(false),\n});\nexport type ForgetInput = z.infer<typeof ForgetInputSchema>;\n\nexport const RelateInputSchema = z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n});\nexport type RelateInput = z.infer<typeof RelateInputSchema>;\n\n// ── Sync Types ───────────────────────────────────────────────\n\nexport interface SyncPayload {\n readonly version: number;\n readonly machine_id: string;\n readonly pushed_at: string;\n readonly memories: readonly SyncMemoryRow[];\n readonly relations: readonly SyncRelationRow[];\n readonly tombstones: readonly SyncTombstone[];\n}\n\nexport interface SyncTombstone {\n readonly id: string;\n readonly project: string | null;\n readonly deleted_at: string;\n}\n\nexport interface SyncMemoryRow {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly base_importance?: number;\n readonly access_count: number;\n readonly injection_count: number;\n readonly created_at: string;\n readonly updated_at: string;\n readonly last_accessed: string | null;\n}\n\nexport interface SyncRelationRow {\n readonly source_id: string;\n readonly target_id: string;\n readonly relation_type: RelationType;\n readonly created_at: string;\n}\n\nexport const SyncPayloadSchema = z.object({\n version: z.number(),\n machine_id: z.string(),\n pushed_at: z.string(),\n memories: z.array(z.object({\n id: z.string(),\n type: z.enum(MEMORY_TYPES),\n title: z.string().nullable(),\n content: z.string(),\n context: z.string().nullable(),\n source: z.enum(MEMORY_SOURCES).nullable(),\n project: z.string().nullable(),\n tags: z.array(z.string()),\n importance: z.number(),\n base_importance: z.number().optional(),\n access_count: z.number(),\n injection_count: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n last_accessed: z.string().nullable(),\n })),\n relations: z.array(z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n created_at: z.string(),\n })),\n tombstones: z.array(z.object({\n id: z.string(),\n project: z.string().nullable(),\n deleted_at: z.string(),\n })).default([]),\n});\n\nexport interface SyncConfig {\n readonly gistId: string;\n}\n\nexport interface MergeResult {\n readonly inserted: number;\n readonly updated: number;\n readonly relationsAdded: number;\n readonly deleted: number;\n}\n\n// ── Stats ─────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n readonly totalMemories: number;\n readonly byType: Record<MemoryType, number>;\n readonly totalRelations: number;\n readonly dbSizeBytes: number;\n readonly oldestMemory: string | null;\n readonly newestMemory: string | null;\n readonly topInjected: readonly { readonly id: string; readonly title: string | null; readonly injectionCount: number }[];\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
log
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QEPE3WVF.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/memory/utils/gist-transport.ts
|
|
7
7
|
import { execSync } from "child_process";
|
|
@@ -205,4 +205,4 @@ export {
|
|
|
205
205
|
deleteGistFile,
|
|
206
206
|
updateGistFiles
|
|
207
207
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
208
|
+
//# sourceMappingURL=chunk-M6GVFN67.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SyncPayloadSchema
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IIWOSSL4.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/memory/utils/sync-merge.ts
|
|
7
7
|
function memoryToSyncRow(m) {
|
|
@@ -15,6 +15,7 @@ function memoryToSyncRow(m) {
|
|
|
15
15
|
project: m.project,
|
|
16
16
|
tags: [...m.tags],
|
|
17
17
|
importance: m.importance,
|
|
18
|
+
base_importance: m.baseImportance,
|
|
18
19
|
access_count: m.accessCount,
|
|
19
20
|
injection_count: m.injectionCount,
|
|
20
21
|
created_at: m.createdAt,
|
|
@@ -56,11 +57,9 @@ function mergeFromRemote(memoryRepo, relationRepo, payload) {
|
|
|
56
57
|
}
|
|
57
58
|
const local = memoryRepo.getById(remote.id);
|
|
58
59
|
if (!local) {
|
|
59
|
-
memoryRepo.upsertFromSync(remote)
|
|
60
|
-
inserted++;
|
|
60
|
+
if (memoryRepo.upsertFromSync(remote)) inserted++;
|
|
61
61
|
} else if (remote.updated_at > local.updatedAt) {
|
|
62
|
-
memoryRepo.upsertFromSync(remote)
|
|
63
|
-
updated++;
|
|
62
|
+
if (memoryRepo.upsertFromSync(remote)) updated++;
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
const localIds = new Set(memoryRepo.getAll().map((m) => m.id));
|
|
@@ -84,4 +83,4 @@ export {
|
|
|
84
83
|
parsePayload,
|
|
85
84
|
mergeFromRemote
|
|
86
85
|
};
|
|
87
|
-
//# sourceMappingURL=chunk-
|
|
86
|
+
//# sourceMappingURL=chunk-N2SCF7DB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/utils/sync-merge.ts"],"sourcesContent":["import { SyncPayloadSchema } from '../types.js';\nimport type { Memory, SyncPayload, SyncMemoryRow, SyncTombstone, MergeResult, RelationType, Tombstone } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\n\nfunction memoryToSyncRow(m: Memory): SyncMemoryRow {\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n content: m.content,\n context: m.context,\n source: m.source,\n project: m.project,\n tags: [...m.tags],\n importance: m.importance,\n base_importance: m.baseImportance,\n access_count: m.accessCount,\n injection_count: m.injectionCount,\n created_at: m.createdAt,\n updated_at: m.updatedAt,\n last_accessed: m.lastAccessed,\n };\n}\n\nfunction tombstoneToSyncRow(t: Tombstone): SyncTombstone {\n return { id: t.id, project: t.project, deleted_at: t.deletedAt };\n}\n\nexport { memoryToSyncRow, tombstoneToSyncRow };\n\nexport function parsePayload(raw: string | null): SyncPayload | null {\n if (!raw || raw === 'null') return null;\n try { return SyncPayloadSchema.parse(JSON.parse(raw)); }\n catch { return null; }\n}\n\nexport function mergeFromRemote(\n memoryRepo: MemoryRepo,\n relationRepo: RelationRepo,\n payload: SyncPayload,\n): MergeResult {\n let inserted = 0;\n let updated = 0;\n let deleted = 0;\n let relationsAdded = 0;\n\n // Phase 1: apply remote tombstones — delete locally or persist the tombstone\n // so future remote memory rows with older updated_at don't resurrect them.\n // Tie-break: delete wins when timestamps are equal (matches Phase 2 semantics).\n // upsertTombstone is safe to call unconditionally — ON CONFLICT keeps the newer row.\n for (const t of payload.tombstones) {\n const local = memoryRepo.getById(t.id);\n if (local && local.updatedAt <= t.deleted_at) {\n memoryRepo.hardDelete(t.id);\n deleted++;\n }\n memoryRepo.upsertTombstone(t.id, t.project, t.deleted_at);\n }\n\n // Phase 2: merge remote memories, honoring local tombstones\n for (const remote of payload.memories) {\n const tombstone = memoryRepo.getTombstone(remote.id);\n if (tombstone && tombstone.deletedAt >= remote.updated_at) {\n // Delete wins; skip this memory.\n continue;\n }\n if (tombstone && tombstone.deletedAt < remote.updated_at) {\n // Remote update is newer than the delete — resurrect and drop the stale tombstone.\n memoryRepo.deleteTombstone(remote.id);\n }\n\n const local = memoryRepo.getById(remote.id);\n if (!local) {\n if (memoryRepo.upsertFromSync(remote)) inserted++;\n } else if (remote.updated_at > local.updatedAt) {\n if (memoryRepo.upsertFromSync(remote)) updated++;\n }\n }\n\n // Phase 3: relations — only link memories that survived both phases.\n const localIds = new Set(memoryRepo.getAll().map((m) => m.id));\n const relations = payload.relations.filter(\n (r) => localIds.has(r.source_id) && localIds.has(r.target_id),\n );\n\n for (const rel of relations) {\n const added = relationRepo.create(\n rel.source_id,\n rel.target_id,\n rel.relation_type as RelationType,\n );\n if (added) relationsAdded++;\n }\n\n return { inserted, updated, deleted, relationsAdded };\n}\n"],"mappings":";;;;;;AAKA,SAAS,gBAAgB,GAA0B;AACjD,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,MAAM,EAAE;AAAA,IACR,OAAO,EAAE;AAAA,IACT,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE;AAAA,IACX,MAAM,CAAC,GAAG,EAAE,IAAI;AAAA,IAChB,YAAY,EAAE;AAAA,IACd,iBAAiB,EAAE;AAAA,IACnB,cAAc,EAAE;AAAA,IAChB,iBAAiB,EAAE;AAAA,IACnB,YAAY,EAAE;AAAA,IACd,YAAY,EAAE;AAAA,IACd,eAAe,EAAE;AAAA,EACnB;AACF;AAEA,SAAS,mBAAmB,GAA6B;AACvD,SAAO,EAAE,IAAI,EAAE,IAAI,SAAS,EAAE,SAAS,YAAY,EAAE,UAAU;AACjE;AAIO,SAAS,aAAa,KAAwC;AACnE,MAAI,CAAC,OAAO,QAAQ,OAAQ,QAAO;AACnC,MAAI;AAAE,WAAO,kBAAkB,MAAM,KAAK,MAAM,GAAG,CAAC;AAAA,EAAG,QACjD;AAAE,WAAO;AAAA,EAAM;AACvB;AAEO,SAAS,gBACd,YACA,cACA,SACa;AACb,MAAI,WAAW;AACf,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,iBAAiB;AAMrB,aAAW,KAAK,QAAQ,YAAY;AAClC,UAAM,QAAQ,WAAW,QAAQ,EAAE,EAAE;AACrC,QAAI,SAAS,MAAM,aAAa,EAAE,YAAY;AAC5C,iBAAW,WAAW,EAAE,EAAE;AAC1B;AAAA,IACF;AACA,eAAW,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU;AAAA,EAC1D;AAGA,aAAW,UAAU,QAAQ,UAAU;AACrC,UAAM,YAAY,WAAW,aAAa,OAAO,EAAE;AACnD,QAAI,aAAa,UAAU,aAAa,OAAO,YAAY;AAEzD;AAAA,IACF;AACA,QAAI,aAAa,UAAU,YAAY,OAAO,YAAY;AAExD,iBAAW,gBAAgB,OAAO,EAAE;AAAA,IACtC;AAEA,UAAM,QAAQ,WAAW,QAAQ,OAAO,EAAE;AAC1C,QAAI,CAAC,OAAO;AACV,UAAI,WAAW,eAAe,MAAM,EAAG;AAAA,IACzC,WAAW,OAAO,aAAa,MAAM,WAAW;AAC9C,UAAI,WAAW,eAAe,MAAM,EAAG;AAAA,IACzC;AAAA,EACF;AAGA,QAAM,WAAW,IAAI,IAAI,WAAW,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7D,QAAM,YAAY,QAAQ,UAAU;AAAA,IAClC,CAAC,MAAM,SAAS,IAAI,EAAE,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS;AAAA,EAC9D;AAEA,aAAW,OAAO,WAAW;AAC3B,UAAM,QAAQ,aAAa;AAAA,MACzB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AACA,QAAI,MAAO;AAAA,EACb;AAEA,SAAO,EAAE,UAAU,SAAS,SAAS,eAAe;AACtD;","names":[]}
|