@slorenzot/memento-core 2.0.0 → 2.0.1

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 (55) hide show
  1. package/dist/ConfigManager.d.ts +44 -59
  2. package/dist/ConfigManager.d.ts.map +1 -1
  3. package/dist/ConfigManager.js +78 -279
  4. package/dist/ConfigManager.js.map +1 -1
  5. package/dist/MemoryEngine.d.ts +30 -0
  6. package/dist/MemoryEngine.d.ts.map +1 -1
  7. package/dist/MemoryEngine.js +136 -11
  8. package/dist/MemoryEngine.js.map +1 -1
  9. package/dist/auth/device-flow-client.d.ts +48 -0
  10. package/dist/auth/device-flow-client.d.ts.map +1 -0
  11. package/dist/auth/device-flow-client.js +143 -0
  12. package/dist/auth/device-flow-client.js.map +1 -0
  13. package/dist/auth/index.d.ts +4 -0
  14. package/dist/auth/index.d.ts.map +1 -0
  15. package/dist/auth/index.js +9 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/auth/token-store.d.ts +46 -0
  18. package/dist/auth/token-store.d.ts.map +1 -0
  19. package/dist/auth/token-store.js +117 -0
  20. package/dist/auth/token-store.js.map +1 -0
  21. package/dist/auth/types.d.ts +83 -0
  22. package/dist/auth/types.d.ts.map +1 -0
  23. package/dist/auth/types.js +4 -0
  24. package/dist/auth/types.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +2 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/sync/conflict-resolution.d.ts +26 -0
  30. package/dist/sync/conflict-resolution.d.ts.map +1 -0
  31. package/dist/sync/conflict-resolution.js +64 -0
  32. package/dist/sync/conflict-resolution.js.map +1 -0
  33. package/dist/sync/index.d.ts +5 -0
  34. package/dist/sync/index.d.ts.map +1 -0
  35. package/dist/sync/index.js +12 -0
  36. package/dist/sync/index.js.map +1 -0
  37. package/dist/sync/sync-client.d.ts +41 -0
  38. package/dist/sync/sync-client.d.ts.map +1 -0
  39. package/dist/sync/sync-client.js +101 -0
  40. package/dist/sync/sync-client.js.map +1 -0
  41. package/dist/sync/sync-engine.d.ts +58 -0
  42. package/dist/sync/sync-engine.d.ts.map +1 -0
  43. package/dist/sync/sync-engine.js +370 -0
  44. package/dist/sync/sync-engine.js.map +1 -0
  45. package/dist/sync/types.d.ts +107 -0
  46. package/dist/sync/types.d.ts.map +1 -0
  47. package/dist/sync/types.js +20 -0
  48. package/dist/sync/types.js.map +1 -0
  49. package/dist/token-savings.d.ts +42 -0
  50. package/dist/token-savings.d.ts.map +1 -0
  51. package/dist/token-savings.js +104 -0
  52. package/dist/token-savings.js.map +1 -0
  53. package/dist/types.d.ts +3 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +1 -1
@@ -177,6 +177,11 @@ export declare class MemoryEngine {
177
177
  */
178
178
  unlockObservation(id: number): Promise<Observation>;
179
179
  private getObservationById;
180
+ /**
181
+ * Get an observation by UUID. Returns null if not found.
182
+ * Includes soft-deleted observations.
183
+ */
184
+ getObservationByUuid(uuid: string): Observation | null;
180
185
  private getSessionById;
181
186
  private getPromptById;
182
187
  private mapObservation;
@@ -198,6 +203,7 @@ export declare class MemoryEngine {
198
203
  }): Promise<{
199
204
  observations: Observation[];
200
205
  total: number;
206
+ estimatedTokensSaved?: number;
201
207
  }>;
202
208
  listSessions(params: {
203
209
  projectId?: string;
@@ -282,6 +288,30 @@ export declare class MemoryEngine {
282
288
  prompts: number;
283
289
  sessions: number;
284
290
  }>;
291
+ /**
292
+ * Get a preview of what will be deleted for a project.
293
+ * Used by the UI to show counts in the delete confirmation dialog.
294
+ */
295
+ getProjectDeletionPreview(projectId: string): {
296
+ project: string;
297
+ observations: number;
298
+ sessions: number;
299
+ prompts: number;
300
+ journalEntries: number;
301
+ hasRegistration: boolean;
302
+ };
303
+ /**
304
+ * Permanently delete ALL data for a project.
305
+ * Order: dependents first (FTS5, journal_tags), then tables, then registration.
306
+ * Returns counts of everything deleted.
307
+ */
308
+ deleteProject(projectId: string): {
309
+ observations: number;
310
+ sessions: number;
311
+ prompts: number;
312
+ journalEntries: number;
313
+ projectRegistration: boolean;
314
+ };
285
315
  writeJournal(data: WriteJournalParams): Promise<JournalEntry>;
286
316
  readJournal(id: number): Promise<JournalEntry | null>;
287
317
  searchJournal(params: JournalSearchParams): Promise<JournalSearchResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"MemoryEngine.d.ts","sourceRoot":"","sources":["../src/MemoryEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MemoryEngine.d.ts","sourceRoot":"","sources":["../src/MemoryEngine.ts"],"names":[],"mappings":"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"}
@@ -45,7 +45,12 @@ class MemoryEngine {
45
45
  dbPath;
46
46
  initError = null;
47
47
  embeddingService;
48
- constructor(dbPath = './data/memento.db') {
48
+ constructor(dbPath) {
49
+ // Default to centralized DB at ~/.memento/memento.db
50
+ if (!dbPath) {
51
+ const { resolveDbPath } = require('./ConfigManager');
52
+ dbPath = resolveDbPath();
53
+ }
49
54
  this.dbPath = (0, path_1.resolve)(dbPath);
50
55
  this.embeddingService = new EmbeddingService_js_1.EmbeddingService();
51
56
  try {
@@ -230,6 +235,22 @@ class MemoryEngine {
230
235
  catch {
231
236
  // Table may not have topic_key column yet
232
237
  }
238
+ // Migrate: add updated_at column (Issue #209 — sync support)
239
+ try {
240
+ this.db.exec('SELECT updated_at FROM observations LIMIT 0');
241
+ }
242
+ catch {
243
+ try {
244
+ this.db.exec('ALTER TABLE observations ADD COLUMN updated_at INTEGER NOT NULL DEFAULT 0');
245
+ // Backfill: set updated_at = created_at for existing rows
246
+ this.db.exec('UPDATE observations SET updated_at = created_at WHERE updated_at = 0');
247
+ console.error('✓ Migration: added updated_at column to observations');
248
+ }
249
+ catch {
250
+ // Column may already exist in a concurrent scenario
251
+ }
252
+ }
253
+ this.db.exec('CREATE INDEX IF NOT EXISTS idx_observations_updated ON observations(updated_at)');
233
254
  // FTS5 — standalone mode (no content= parameter).
234
255
  // FTS5 owns its own data copy, supports full CRUD (INSERT, DELETE, UPDATE),
235
256
  // and avoids SQLITE_CORRUPT_VTAB that occurred with content='observations' mode
@@ -353,8 +374,9 @@ class MemoryEngine {
353
374
  const readOnly = data.readOnly ? 1 : 0;
354
375
  const id = await this.withRetry(() => {
355
376
  const result = this.db
356
- .prepare(`INSERT INTO observations (uuid, session_id, title, content, type, topic_key, project_id, created_at, deleted_at, metadata, scope, pinned, read_only) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)`)
357
- .run(uuid, data.sessionId, data.title, data.content, data.type, data.topicKey ?? null, data.projectId, createdAt.getTime(), metadata, scope, pinned, readOnly);
377
+ .prepare(`INSERT INTO observations (uuid, session_id, title, content, type, topic_key, project_id, created_at, updated_at, deleted_at, metadata, scope, pinned, read_only) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)`)
378
+ .run(uuid, data.sessionId, data.title, data.content, data.type, data.topicKey ?? null, data.projectId, createdAt.getTime(), createdAt.getTime(), // updated_at = created_at on insert
379
+ metadata, scope, pinned, readOnly);
358
380
  const insertId = typeof result.lastInsertRowid === 'bigint'
359
381
  ? Number(result.lastInsertRowid)
360
382
  : result.lastInsertRowid;
@@ -417,6 +439,8 @@ class MemoryEngine {
417
439
  if (fields.length === 0)
418
440
  return current;
419
441
  fields.push('revision_count = revision_count + 1');
442
+ fields.push('updated_at = ?');
443
+ values.push(Date.now());
420
444
  values.push(id);
421
445
  // Check if any FTS5-indexed fields changed
422
446
  const hasFtsUpdate = updates.title !== undefined ||
@@ -470,15 +494,15 @@ class MemoryEngine {
470
494
  const meta = { ...obs.metadata, deleteReason: reason };
471
495
  await this.withRetry(() => {
472
496
  this.db
473
- .prepare('UPDATE observations SET deleted_at = ?, metadata = ? WHERE id = ?')
474
- .run(now, this.serialize(meta), id);
497
+ .prepare('UPDATE observations SET deleted_at = ?, updated_at = ?, metadata = ? WHERE id = ?')
498
+ .run(now, now, this.serialize(meta), id);
475
499
  // Application-level FTS5 sync (was trigger observations_soft_delete)
476
500
  this.db.prepare('DELETE FROM observations_fts WHERE rowid = ?').run(id);
477
501
  });
478
502
  }
479
503
  else {
480
504
  await this.withRetry(() => {
481
- this.db.prepare('UPDATE observations SET deleted_at = ? WHERE id = ?').run(now, id);
505
+ this.db.prepare('UPDATE observations SET deleted_at = ?, updated_at = ? WHERE id = ?').run(now, now, id);
482
506
  // Application-level FTS5 sync (was trigger observations_soft_delete)
483
507
  this.db.prepare('DELETE FROM observations_fts WHERE rowid = ?').run(id);
484
508
  });
@@ -492,7 +516,8 @@ class MemoryEngine {
492
516
  if (!obs.deletedAt)
493
517
  throw new Error('Observation is not deleted');
494
518
  await this.withRetry(() => {
495
- this.db.prepare('UPDATE observations SET deleted_at = NULL WHERE id = ?').run(id);
519
+ const now = Date.now();
520
+ this.db.prepare('UPDATE observations SET deleted_at = NULL, updated_at = ? WHERE id = ?').run(now, id);
496
521
  // Application-level FTS5 sync (was trigger observations_undelete)
497
522
  const row = this.db
498
523
  .prepare('SELECT title, content, topic_key, project_id FROM observations WHERE id = ?')
@@ -870,15 +895,27 @@ class MemoryEngine {
870
895
  // Fall back to keyword mode if no query provided
871
896
  return this.searchKeyword(params);
872
897
  }
898
+ let result;
873
899
  switch (mode) {
874
900
  case 'semantic':
875
- return this.searchSemantic(params);
901
+ result = await this.searchSemantic(params);
902
+ break;
876
903
  case 'hybrid':
877
- return this.searchHybrid(params);
904
+ result = await this.searchHybrid(params);
905
+ break;
878
906
  case 'keyword':
879
907
  default:
880
- return this.searchKeyword(params);
908
+ result = await this.searchKeyword(params);
909
+ break;
910
+ }
911
+ // Add token savings estimation
912
+ const { isTokenSavingsEnabled } = require('./ConfigManager');
913
+ if (isTokenSavingsEnabled() && result.observations.length > 0) {
914
+ const { estimateTotalSavings } = require('./token-savings');
915
+ const savings = estimateTotalSavings(result.observations);
916
+ result.estimatedTokensSaved = savings.estimatedTokensSaved;
881
917
  }
918
+ return result;
882
919
  }
883
920
  /**
884
921
  * Keyword search using existing FTS5 (unchanged behavior).
@@ -1416,6 +1453,17 @@ class MemoryEngine {
1416
1453
  }
1417
1454
  return observation;
1418
1455
  }
1456
+ /**
1457
+ * Get an observation by UUID. Returns null if not found.
1458
+ * Includes soft-deleted observations.
1459
+ */
1460
+ getObservationByUuid(uuid) {
1461
+ this.checkHealth();
1462
+ const row = this.db.prepare('SELECT * FROM observations WHERE uuid = ?').get(uuid);
1463
+ if (!row)
1464
+ return null;
1465
+ return this.mapObservation(row);
1466
+ }
1419
1467
  async getSessionById(id) {
1420
1468
  const row = this.db.prepare('SELECT * FROM sessions WHERE id = ?').get(id);
1421
1469
  if (!row)
@@ -1440,6 +1488,7 @@ class MemoryEngine {
1440
1488
  topicKey: r.topic_key,
1441
1489
  projectId: r.project_id,
1442
1490
  createdAt: new Date(r.created_at),
1491
+ updatedAt: new Date(r.updated_at ?? r.created_at),
1443
1492
  deletedAt: r.deleted_at ? new Date(r.deleted_at) : null,
1444
1493
  metadata: this.deserialize(r.metadata),
1445
1494
  scope: r.scope || 'project',
@@ -1521,7 +1570,15 @@ class MemoryEngine {
1521
1570
  }
1522
1571
  const countResult = this.db.prepare(countSql).get(...countValues);
1523
1572
  const total = countResult?.count ?? 0;
1524
- return { observations, total };
1573
+ // Token savings estimation
1574
+ let estimatedTokensSaved;
1575
+ const { isTokenSavingsEnabled } = require('./ConfigManager');
1576
+ if (isTokenSavingsEnabled() && observations.length > 0) {
1577
+ const { estimateTotalSavings } = require('./token-savings');
1578
+ const savings = estimateTotalSavings(observations);
1579
+ estimatedTokensSaved = savings.estimatedTokensSaved;
1580
+ }
1581
+ return { observations, total, estimatedTokensSaved };
1525
1582
  }
1526
1583
  // ─── TUI Explorer API ──────────────────────────────────────
1527
1584
  async listSessions(params) {
@@ -2113,6 +2170,74 @@ class MemoryEngine {
2113
2170
  sessions: sessionCount.count,
2114
2171
  };
2115
2172
  }
2173
+ /**
2174
+ * Get a preview of what will be deleted for a project.
2175
+ * Used by the UI to show counts in the delete confirmation dialog.
2176
+ */
2177
+ getProjectDeletionPreview(projectId) {
2178
+ this.checkHealth();
2179
+ const count = (table, column = 'project_id') => (this.db
2180
+ .prepare(`SELECT COUNT(*) as count FROM ${table} WHERE ${column} = ?`)
2181
+ .get(projectId).count);
2182
+ const hasReg = this.db
2183
+ .prepare('SELECT COUNT(*) as count FROM projects WHERE name = ?')
2184
+ .get(projectId);
2185
+ return {
2186
+ project: projectId,
2187
+ observations: count('observations'),
2188
+ sessions: count('sessions'),
2189
+ prompts: count('prompts'),
2190
+ journalEntries: count('journal'),
2191
+ hasRegistration: hasReg.count > 0,
2192
+ };
2193
+ }
2194
+ /**
2195
+ * Permanently delete ALL data for a project.
2196
+ * Order: dependents first (FTS5, journal_tags), then tables, then registration.
2197
+ * Returns counts of everything deleted.
2198
+ */
2199
+ deleteProject(projectId) {
2200
+ this.checkHealth();
2201
+ // Capture counts before deleting
2202
+ const count = (table, column = 'project_id') => (this.db
2203
+ .prepare(`SELECT COUNT(*) as count FROM ${table} WHERE ${column} = ?`)
2204
+ .get(projectId).count);
2205
+ const obsCount = count('observations');
2206
+ const sessionCount = count('sessions');
2207
+ const promptCount = count('prompts');
2208
+ const journalCount = count('journal');
2209
+ const hasReg = count('projects', 'name') > 0;
2210
+ // Delete in dependency order: FTS + tags first, then main tables, then registration
2211
+ // 1. observations_fts (by observation ids for this project)
2212
+ this.db
2213
+ .prepare('DELETE FROM observations_fts WHERE rowid IN (SELECT id FROM observations WHERE project_id = ?)')
2214
+ .run(projectId);
2215
+ // 2. journal_fts (by journal ids for this project)
2216
+ this.db
2217
+ .prepare('DELETE FROM journal_fts WHERE rowid IN (SELECT id FROM journal WHERE project_id = ?)')
2218
+ .run(projectId);
2219
+ // 3. journal_tags (by journal ids for this project)
2220
+ this.db
2221
+ .prepare('DELETE FROM journal_tags WHERE journal_id IN (SELECT id FROM journal WHERE project_id = ?)')
2222
+ .run(projectId);
2223
+ // 4. observations
2224
+ this.db.prepare('DELETE FROM observations WHERE project_id = ?').run(projectId);
2225
+ // 5. prompts
2226
+ this.db.prepare('DELETE FROM prompts WHERE project_id = ?').run(projectId);
2227
+ // 6. sessions
2228
+ this.db.prepare('DELETE FROM sessions WHERE project_id = ?').run(projectId);
2229
+ // 7. journal
2230
+ this.db.prepare('DELETE FROM journal WHERE project_id = ?').run(projectId);
2231
+ // 8. project registration
2232
+ this.db.prepare('DELETE FROM projects WHERE name = ?').run(projectId);
2233
+ return {
2234
+ observations: obsCount,
2235
+ sessions: sessionCount,
2236
+ prompts: promptCount,
2237
+ journalEntries: journalCount,
2238
+ projectRegistration: hasReg,
2239
+ };
2240
+ }
2116
2241
  // ─── Journal (append-only evidence) ──────────────────────────
2117
2242
  async writeJournal(data) {
2118
2243
  this.checkHealth();