@membank/core 0.7.0 → 0.8.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/index.cjs CHANGED
@@ -49,7 +49,8 @@ var DatabaseError = class extends MembankError {
49
49
  //#endregion
50
50
  //#region src/db/manager.ts
51
51
  const DEFAULT_DB_PATH = (0, node_path.join)((0, node_os.homedir)(), ".membank", "memory.db");
52
- const MIGRATIONS$1 = [[1, `
52
+ const MIGRATIONS$1 = [
53
+ [1, `
53
54
  CREATE TABLE IF NOT EXISTS memories (
54
55
  id TEXT PRIMARY KEY,
55
56
  content TEXT NOT NULL,
@@ -67,7 +68,8 @@ CREATE TABLE IF NOT EXISTS memories (
67
68
  CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(
68
69
  embedding FLOAT[384]
69
70
  );
70
- `], [2, `
71
+ `],
72
+ [2, `
71
73
  CREATE TABLE IF NOT EXISTS projects (
72
74
  id TEXT PRIMARY KEY,
73
75
  name TEXT NOT NULL,
@@ -100,7 +102,25 @@ JOIN projects p ON p.scope_hash = m.scope
100
102
  WHERE m.scope != 'global';
101
103
 
102
104
  ALTER TABLE memories DROP COLUMN scope;
103
- `]];
105
+ `],
106
+ [3, `
107
+ CREATE TABLE IF NOT EXISTS memory_review_events (
108
+ id TEXT PRIMARY KEY,
109
+ memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
110
+ conflicting_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
111
+ similarity REAL NOT NULL,
112
+ conflict_content_snapshot TEXT NOT NULL,
113
+ reason TEXT NOT NULL,
114
+ created_at TEXT NOT NULL,
115
+ resolved_at TEXT
116
+ );
117
+
118
+ CREATE INDEX IF NOT EXISTS idx_review_events_memory_open
119
+ ON memory_review_events(memory_id) WHERE resolved_at IS NULL;
120
+
121
+ ALTER TABLE memories DROP COLUMN needs_review;
122
+ `]
123
+ ];
104
124
  var DatabaseManager = class DatabaseManager {
105
125
  #db;
106
126
  constructor(db) {
@@ -174,6 +194,27 @@ const ProjectSchema = zod.z.object({
174
194
  createdAt: zod.z.string(),
175
195
  updatedAt: zod.z.string()
176
196
  });
197
+ const ReviewReasonSchema = zod.z.enum(["similarity_dedup"]);
198
+ const ReviewEventSchema = zod.z.object({
199
+ id: zod.z.string(),
200
+ memoryId: zod.z.string(),
201
+ conflictingMemoryId: zod.z.string().nullable(),
202
+ similarity: zod.z.number(),
203
+ conflictContentSnapshot: zod.z.string(),
204
+ reason: ReviewReasonSchema,
205
+ createdAt: zod.z.string(),
206
+ resolvedAt: zod.z.string().nullable()
207
+ });
208
+ const ReviewEventRowSchema = zod.z.object({
209
+ id: zod.z.string(),
210
+ memory_id: zod.z.string(),
211
+ conflicting_memory_id: zod.z.string().nullable(),
212
+ similarity: zod.z.number(),
213
+ conflict_content_snapshot: zod.z.string(),
214
+ reason: ReviewReasonSchema,
215
+ created_at: zod.z.string(),
216
+ resolved_at: zod.z.string().nullable()
217
+ });
177
218
  const MemorySchema = zod.z.object({
178
219
  id: zod.z.string(),
179
220
  content: zod.z.string(),
@@ -183,7 +224,7 @@ const MemorySchema = zod.z.object({
183
224
  sourceHarness: zod.z.string().nullable(),
184
225
  accessCount: zod.z.number().int().nonnegative(),
185
226
  pinned: zod.z.boolean(),
186
- needsReview: zod.z.boolean(),
227
+ reviewEvents: zod.z.array(ReviewEventSchema),
187
228
  createdAt: zod.z.string(),
188
229
  updatedAt: zod.z.string()
189
230
  });
@@ -221,7 +262,6 @@ const MemoryRowSchema = zod.z.object({
221
262
  source: zod.z.string().nullable(),
222
263
  access_count: zod.z.number(),
223
264
  pinned: zod.z.number(),
224
- needs_review: zod.z.number(),
225
265
  created_at: zod.z.string(),
226
266
  updated_at: zod.z.string()
227
267
  });
@@ -234,7 +274,7 @@ const ProjectRowSchema = zod.z.object({
234
274
  });
235
275
  //#endregion
236
276
  //#region src/db/row-types.ts
237
- function rowToMemory(row, projects) {
277
+ function rowToMemory(row, projects, reviewEvents = []) {
238
278
  return {
239
279
  id: row.id,
240
280
  content: row.content,
@@ -244,11 +284,24 @@ function rowToMemory(row, projects) {
244
284
  sourceHarness: row.source,
245
285
  accessCount: row.access_count,
246
286
  pinned: row.pinned !== 0,
247
- needsReview: row.needs_review !== 0,
287
+ reviewEvents,
248
288
  createdAt: row.created_at,
249
289
  updatedAt: row.updated_at
250
290
  };
251
291
  }
292
+ function rowToReviewEvent(row) {
293
+ const parsed = ReviewEventRowSchema.parse(row);
294
+ return {
295
+ id: parsed.id,
296
+ memoryId: parsed.memory_id,
297
+ conflictingMemoryId: parsed.conflicting_memory_id,
298
+ similarity: parsed.similarity,
299
+ conflictContentSnapshot: parsed.conflict_content_snapshot,
300
+ reason: parsed.reason,
301
+ createdAt: parsed.created_at,
302
+ resolvedAt: parsed.resolved_at
303
+ };
304
+ }
252
305
  function rowToProject(row) {
253
306
  return {
254
307
  id: row.id,
@@ -314,18 +367,23 @@ var MemoryRepository = class {
314
367
  if (top !== void 0 && top.similarity > .92) {
315
368
  this.#db.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(content, now, top.id);
316
369
  this.#db.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(embeddingBlob, top.rowid);
317
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(top.id)), this.#projects.getProjectsForMemories([top.id]).get(top.id) ?? []);
370
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(top.id));
371
+ const projectMap = this.#projects.getProjectsForMemories([top.id]);
372
+ const events = this.#getEventsForMemories([top.id]);
373
+ return rowToMemory(updated, projectMap.get(top.id) ?? [], events.get(top.id) ?? []);
318
374
  }
319
- if (top !== void 0 && top.similarity >= .75) this.#db.db.prepare(`UPDATE memories SET needs_review = 1 WHERE id = ?`).run(top.id);
320
375
  const id = (0, node_crypto.randomUUID)();
321
- this.#db.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, needs_review, created_at, updated_at)
322
- VALUES (?, ?, ?, ?, ?, 0, 0, 0, ?, ?)`).run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);
376
+ this.#db.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
377
+ VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);
378
+ if (top !== void 0 && top.similarity >= .75) this.#db.db.prepare(`INSERT INTO memory_review_events
379
+ (id, memory_id, conflicting_memory_id, similarity, conflict_content_snapshot, reason, created_at)
380
+ VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run((0, node_crypto.randomUUID)(), top.id, id, top.similarity, content, now);
323
381
  this.#db.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(embeddingBlob, id);
324
382
  if (projectScope !== void 0) {
325
383
  const project = this.#projects.upsertByHash(projectScope.hash, projectScope.name);
326
384
  this.#projects.addAssociation(id, project.id);
327
385
  }
328
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
386
+ return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? [], []);
329
387
  }
330
388
  async update(id, patch) {
331
389
  const { content, tags } = MemoryPatchSchema.parse(patch);
@@ -349,7 +407,10 @@ var MemoryRepository = class {
349
407
  const embeddingBlob = Buffer.from(embedding.buffer);
350
408
  this.#db.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(embeddingBlob, existing.rowid);
351
409
  }
352
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
410
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id));
411
+ const projectMap = this.#projects.getProjectsForMemories([id]);
412
+ const events = this.#getEventsForMemories([id]);
413
+ return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);
353
414
  }
354
415
  delete(id) {
355
416
  const row = this.#db.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(id);
@@ -371,7 +432,45 @@ var MemoryRepository = class {
371
432
  if (rows.length === 0) return [];
372
433
  const ids = rows.map((r) => r.id);
373
434
  const projectMap = this.#projects.getProjectsForMemories(ids);
374
- return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? []));
435
+ const eventMap = this.#getEventsForMemories(ids);
436
+ return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? []));
437
+ }
438
+ listFlagged() {
439
+ const rows = this.#db.db.prepare(`SELECT * FROM memories
440
+ WHERE EXISTS (
441
+ SELECT 1 FROM memory_review_events e
442
+ WHERE e.memory_id = memories.id AND e.resolved_at IS NULL
443
+ )
444
+ ORDER BY created_at DESC`).all();
445
+ if (rows.length === 0) return [];
446
+ const ids = rows.map((r) => r.id);
447
+ const projectMap = this.#projects.getProjectsForMemories(ids);
448
+ const eventMap = this.#getEventsForMemories(ids, { unresolvedOnly: true });
449
+ return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? []));
450
+ }
451
+ listReviewEvents(memoryId, opts) {
452
+ const where = opts?.unresolvedOnly === true ? "WHERE memory_id = ? AND resolved_at IS NULL" : "WHERE memory_id = ?";
453
+ return this.#db.db.prepare(`SELECT * FROM memory_review_events ${where} ORDER BY created_at DESC`).all(memoryId).map((r) => rowToReviewEvent(ReviewEventRowSchema.parse(r)));
454
+ }
455
+ resolveReviewEvents(memoryId) {
456
+ const now = (/* @__PURE__ */ new Date()).toISOString();
457
+ this.#db.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(now, memoryId);
458
+ }
459
+ #getEventsForMemories(ids, opts) {
460
+ if (ids.length === 0) return /* @__PURE__ */ new Map();
461
+ const placeholders = ids.map(() => "?").join(", ");
462
+ const unresolvedClause = opts?.unresolvedOnly === true ? "AND resolved_at IS NULL" : "";
463
+ const rows = this.#db.db.prepare(`SELECT * FROM memory_review_events
464
+ WHERE memory_id IN (${placeholders}) ${unresolvedClause}
465
+ ORDER BY created_at DESC`).all(...ids);
466
+ const map = /* @__PURE__ */ new Map();
467
+ for (const row of rows) {
468
+ const event = rowToReviewEvent(ReviewEventRowSchema.parse(row));
469
+ const existing = map.get(event.memoryId) ?? [];
470
+ existing.push(event);
471
+ map.set(event.memoryId, existing);
472
+ }
473
+ return map;
375
474
  }
376
475
  stats() {
377
476
  const byType = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0]));
@@ -380,21 +479,22 @@ var MemoryRepository = class {
380
479
  const parsed = MemoryTypeSchema.safeParse(row.type);
381
480
  if (parsed.success) byType[parsed.data] = row.count;
382
481
  }
383
- const totals = this.#db.db.prepare(`SELECT COUNT(*) as total, SUM(needs_review) as needsReview FROM memories`).get() ?? {
384
- total: 0,
385
- needsReview: 0
386
- };
482
+ const totals = this.#db.db.prepare(`SELECT COUNT(*) as total FROM memories`).get() ?? { total: 0 };
483
+ const reviewRow = this.#db.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get() ?? { needsReview: 0 };
387
484
  return {
388
485
  byType,
389
486
  total: totals.total,
390
- needsReview: totals.needsReview ?? 0
487
+ needsReview: reviewRow.needsReview
391
488
  };
392
489
  }
393
490
  setPin(id, pinned) {
394
491
  if (this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id) === void 0) throw new Error(`Memory not found: ${id}`);
395
492
  const now = (/* @__PURE__ */ new Date()).toISOString();
396
493
  this.#db.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(pinned ? 1 : 0, now, id);
397
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
494
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id));
495
+ const projectMap = this.#projects.getProjectsForMemories([id]);
496
+ const events = this.#getEventsForMemories([id]);
497
+ return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);
398
498
  }
399
499
  incrementAccessCount(id) {
400
500
  this.#db.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(id);
@@ -625,6 +725,9 @@ exports.ProjectRowSchema = ProjectRowSchema;
625
725
  exports.ProjectSchema = ProjectSchema;
626
726
  exports.QueryEngine = QueryEngine;
627
727
  exports.QueryOptionsSchema = QueryOptionsSchema;
728
+ exports.ReviewEventRowSchema = ReviewEventRowSchema;
729
+ exports.ReviewEventSchema = ReviewEventSchema;
730
+ exports.ReviewReasonSchema = ReviewReasonSchema;
628
731
  exports.SaveOptionsSchema = SaveOptionsSchema;
629
732
  exports.SessionContextBuilder = SessionContextBuilder;
630
733
  exports.SessionContextSchema = SessionContextSchema;
package/dist/index.d.cts CHANGED
@@ -41,6 +41,36 @@ declare const ProjectSchema: z.ZodObject<{
41
41
  updatedAt: z.ZodString;
42
42
  }, z.core.$strip>;
43
43
  type Project = z.infer<typeof ProjectSchema>;
44
+ declare const ReviewReasonSchema: z.ZodEnum<{
45
+ similarity_dedup: "similarity_dedup";
46
+ }>;
47
+ type ReviewReason = z.infer<typeof ReviewReasonSchema>;
48
+ declare const ReviewEventSchema: z.ZodObject<{
49
+ id: z.ZodString;
50
+ memoryId: z.ZodString;
51
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
52
+ similarity: z.ZodNumber;
53
+ conflictContentSnapshot: z.ZodString;
54
+ reason: z.ZodEnum<{
55
+ similarity_dedup: "similarity_dedup";
56
+ }>;
57
+ createdAt: z.ZodString;
58
+ resolvedAt: z.ZodNullable<z.ZodString>;
59
+ }, z.core.$strip>;
60
+ type ReviewEvent = z.infer<typeof ReviewEventSchema>;
61
+ declare const ReviewEventRowSchema: z.ZodObject<{
62
+ id: z.ZodString;
63
+ memory_id: z.ZodString;
64
+ conflicting_memory_id: z.ZodNullable<z.ZodString>;
65
+ similarity: z.ZodNumber;
66
+ conflict_content_snapshot: z.ZodString;
67
+ reason: z.ZodEnum<{
68
+ similarity_dedup: "similarity_dedup";
69
+ }>;
70
+ created_at: z.ZodString;
71
+ resolved_at: z.ZodNullable<z.ZodString>;
72
+ }, z.core.$strip>;
73
+ type ReviewEventRow = z.infer<typeof ReviewEventRowSchema>;
44
74
  declare const MemorySchema: z.ZodObject<{
45
75
  id: z.ZodString;
46
76
  content: z.ZodString;
@@ -62,7 +92,18 @@ declare const MemorySchema: z.ZodObject<{
62
92
  sourceHarness: z.ZodNullable<z.ZodString>;
63
93
  accessCount: z.ZodNumber;
64
94
  pinned: z.ZodBoolean;
65
- needsReview: z.ZodBoolean;
95
+ reviewEvents: z.ZodArray<z.ZodObject<{
96
+ id: z.ZodString;
97
+ memoryId: z.ZodString;
98
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
99
+ similarity: z.ZodNumber;
100
+ conflictContentSnapshot: z.ZodString;
101
+ reason: z.ZodEnum<{
102
+ similarity_dedup: "similarity_dedup";
103
+ }>;
104
+ createdAt: z.ZodString;
105
+ resolvedAt: z.ZodNullable<z.ZodString>;
106
+ }, z.core.$strip>>;
66
107
  createdAt: z.ZodString;
67
108
  updatedAt: z.ZodString;
68
109
  }, z.core.$strip>;
@@ -132,7 +173,18 @@ declare const SessionContextSchema: z.ZodObject<{
132
173
  sourceHarness: z.ZodNullable<z.ZodString>;
133
174
  accessCount: z.ZodNumber;
134
175
  pinned: z.ZodBoolean;
135
- needsReview: z.ZodBoolean;
176
+ reviewEvents: z.ZodArray<z.ZodObject<{
177
+ id: z.ZodString;
178
+ memoryId: z.ZodString;
179
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
180
+ similarity: z.ZodNumber;
181
+ conflictContentSnapshot: z.ZodString;
182
+ reason: z.ZodEnum<{
183
+ similarity_dedup: "similarity_dedup";
184
+ }>;
185
+ createdAt: z.ZodString;
186
+ resolvedAt: z.ZodNullable<z.ZodString>;
187
+ }, z.core.$strip>>;
136
188
  createdAt: z.ZodString;
137
189
  updatedAt: z.ZodString;
138
190
  }, z.core.$strip>>;
@@ -157,7 +209,18 @@ declare const SessionContextSchema: z.ZodObject<{
157
209
  sourceHarness: z.ZodNullable<z.ZodString>;
158
210
  accessCount: z.ZodNumber;
159
211
  pinned: z.ZodBoolean;
160
- needsReview: z.ZodBoolean;
212
+ reviewEvents: z.ZodArray<z.ZodObject<{
213
+ id: z.ZodString;
214
+ memoryId: z.ZodString;
215
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
216
+ similarity: z.ZodNumber;
217
+ conflictContentSnapshot: z.ZodString;
218
+ reason: z.ZodEnum<{
219
+ similarity_dedup: "similarity_dedup";
220
+ }>;
221
+ createdAt: z.ZodString;
222
+ resolvedAt: z.ZodNullable<z.ZodString>;
223
+ }, z.core.$strip>>;
161
224
  createdAt: z.ZodString;
162
225
  updatedAt: z.ZodString;
163
226
  }, z.core.$strip>>;
@@ -171,7 +234,6 @@ declare const MemoryRowSchema: z.ZodObject<{
171
234
  source: z.ZodNullable<z.ZodString>;
172
235
  access_count: z.ZodNumber;
173
236
  pinned: z.ZodNumber;
174
- needs_review: z.ZodNumber;
175
237
  created_at: z.ZodString;
176
238
  updated_at: z.ZodString;
177
239
  }, z.core.$strip>;
@@ -186,7 +248,7 @@ declare const ProjectRowSchema: z.ZodObject<{
186
248
  type ProjectRow = z.infer<typeof ProjectRowSchema>;
187
249
  //#endregion
188
250
  //#region src/db/row-types.d.ts
189
- declare function rowToMemory(row: MemoryRow, projects: Project[]): Memory;
251
+ declare function rowToMemory(row: MemoryRow, projects: Project[], reviewEvents?: ReviewEvent[]): Memory;
190
252
  declare function rowToProject(row: ProjectRow): Project;
191
253
  //#endregion
192
254
  //#region src/embedding/service.d.ts
@@ -228,6 +290,11 @@ declare class MemoryRepository {
228
290
  type?: MemoryType;
229
291
  pinned?: boolean;
230
292
  }): Memory[];
293
+ listFlagged(): Memory[];
294
+ listReviewEvents(memoryId: string, opts?: {
295
+ unresolvedOnly?: boolean;
296
+ }): ReviewEvent[];
297
+ resolveReviewEvents(memoryId: string): void;
231
298
  stats(): {
232
299
  byType: Record<MemoryType, number>;
233
300
  total: number;
@@ -275,5 +342,5 @@ declare class SessionContextBuilder {
275
342
  getSessionContext(projectHash: string): SessionContext;
276
343
  }
277
344
  //#endregion
278
- export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, Memory, MemoryPatch, MemoryPatchSchema, MemoryRepository, MemoryRow, MemoryRowSchema, MemorySchema, MemoryType, MemoryTypeSchema, MigrationMeta, ProgressCallback, Project, ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptions, QueryOptionsSchema, SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, SessionContext, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
345
+ export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, Memory, MemoryPatch, MemoryPatchSchema, MemoryRepository, MemoryRow, MemoryRowSchema, MemorySchema, MemoryType, MemoryTypeSchema, MigrationMeta, ProgressCallback, Project, ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptions, QueryOptionsSchema, ReviewEvent, ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, ReviewReason, ReviewReasonSchema, SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, SessionContext, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
279
346
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/project/repository.ts","../src/memory/repository.ts","../src/migrations/index.ts","../src/query/engine.ts","../src/scope/resolver.ts","../src/session/builder.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/project/repository.ts","../src/memory/repository.ts","../src/migrations/index.ts","../src/query/engine.ts","../src/scope/resolver.ts","../src/session/builder.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -41,6 +41,36 @@ declare const ProjectSchema: z.ZodObject<{
41
41
  updatedAt: z.ZodString;
42
42
  }, z.core.$strip>;
43
43
  type Project = z.infer<typeof ProjectSchema>;
44
+ declare const ReviewReasonSchema: z.ZodEnum<{
45
+ similarity_dedup: "similarity_dedup";
46
+ }>;
47
+ type ReviewReason = z.infer<typeof ReviewReasonSchema>;
48
+ declare const ReviewEventSchema: z.ZodObject<{
49
+ id: z.ZodString;
50
+ memoryId: z.ZodString;
51
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
52
+ similarity: z.ZodNumber;
53
+ conflictContentSnapshot: z.ZodString;
54
+ reason: z.ZodEnum<{
55
+ similarity_dedup: "similarity_dedup";
56
+ }>;
57
+ createdAt: z.ZodString;
58
+ resolvedAt: z.ZodNullable<z.ZodString>;
59
+ }, z.core.$strip>;
60
+ type ReviewEvent = z.infer<typeof ReviewEventSchema>;
61
+ declare const ReviewEventRowSchema: z.ZodObject<{
62
+ id: z.ZodString;
63
+ memory_id: z.ZodString;
64
+ conflicting_memory_id: z.ZodNullable<z.ZodString>;
65
+ similarity: z.ZodNumber;
66
+ conflict_content_snapshot: z.ZodString;
67
+ reason: z.ZodEnum<{
68
+ similarity_dedup: "similarity_dedup";
69
+ }>;
70
+ created_at: z.ZodString;
71
+ resolved_at: z.ZodNullable<z.ZodString>;
72
+ }, z.core.$strip>;
73
+ type ReviewEventRow = z.infer<typeof ReviewEventRowSchema>;
44
74
  declare const MemorySchema: z.ZodObject<{
45
75
  id: z.ZodString;
46
76
  content: z.ZodString;
@@ -62,7 +92,18 @@ declare const MemorySchema: z.ZodObject<{
62
92
  sourceHarness: z.ZodNullable<z.ZodString>;
63
93
  accessCount: z.ZodNumber;
64
94
  pinned: z.ZodBoolean;
65
- needsReview: z.ZodBoolean;
95
+ reviewEvents: z.ZodArray<z.ZodObject<{
96
+ id: z.ZodString;
97
+ memoryId: z.ZodString;
98
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
99
+ similarity: z.ZodNumber;
100
+ conflictContentSnapshot: z.ZodString;
101
+ reason: z.ZodEnum<{
102
+ similarity_dedup: "similarity_dedup";
103
+ }>;
104
+ createdAt: z.ZodString;
105
+ resolvedAt: z.ZodNullable<z.ZodString>;
106
+ }, z.core.$strip>>;
66
107
  createdAt: z.ZodString;
67
108
  updatedAt: z.ZodString;
68
109
  }, z.core.$strip>;
@@ -132,7 +173,18 @@ declare const SessionContextSchema: z.ZodObject<{
132
173
  sourceHarness: z.ZodNullable<z.ZodString>;
133
174
  accessCount: z.ZodNumber;
134
175
  pinned: z.ZodBoolean;
135
- needsReview: z.ZodBoolean;
176
+ reviewEvents: z.ZodArray<z.ZodObject<{
177
+ id: z.ZodString;
178
+ memoryId: z.ZodString;
179
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
180
+ similarity: z.ZodNumber;
181
+ conflictContentSnapshot: z.ZodString;
182
+ reason: z.ZodEnum<{
183
+ similarity_dedup: "similarity_dedup";
184
+ }>;
185
+ createdAt: z.ZodString;
186
+ resolvedAt: z.ZodNullable<z.ZodString>;
187
+ }, z.core.$strip>>;
136
188
  createdAt: z.ZodString;
137
189
  updatedAt: z.ZodString;
138
190
  }, z.core.$strip>>;
@@ -157,7 +209,18 @@ declare const SessionContextSchema: z.ZodObject<{
157
209
  sourceHarness: z.ZodNullable<z.ZodString>;
158
210
  accessCount: z.ZodNumber;
159
211
  pinned: z.ZodBoolean;
160
- needsReview: z.ZodBoolean;
212
+ reviewEvents: z.ZodArray<z.ZodObject<{
213
+ id: z.ZodString;
214
+ memoryId: z.ZodString;
215
+ conflictingMemoryId: z.ZodNullable<z.ZodString>;
216
+ similarity: z.ZodNumber;
217
+ conflictContentSnapshot: z.ZodString;
218
+ reason: z.ZodEnum<{
219
+ similarity_dedup: "similarity_dedup";
220
+ }>;
221
+ createdAt: z.ZodString;
222
+ resolvedAt: z.ZodNullable<z.ZodString>;
223
+ }, z.core.$strip>>;
161
224
  createdAt: z.ZodString;
162
225
  updatedAt: z.ZodString;
163
226
  }, z.core.$strip>>;
@@ -171,7 +234,6 @@ declare const MemoryRowSchema: z.ZodObject<{
171
234
  source: z.ZodNullable<z.ZodString>;
172
235
  access_count: z.ZodNumber;
173
236
  pinned: z.ZodNumber;
174
- needs_review: z.ZodNumber;
175
237
  created_at: z.ZodString;
176
238
  updated_at: z.ZodString;
177
239
  }, z.core.$strip>;
@@ -186,7 +248,7 @@ declare const ProjectRowSchema: z.ZodObject<{
186
248
  type ProjectRow = z.infer<typeof ProjectRowSchema>;
187
249
  //#endregion
188
250
  //#region src/db/row-types.d.ts
189
- declare function rowToMemory(row: MemoryRow, projects: Project[]): Memory;
251
+ declare function rowToMemory(row: MemoryRow, projects: Project[], reviewEvents?: ReviewEvent[]): Memory;
190
252
  declare function rowToProject(row: ProjectRow): Project;
191
253
  //#endregion
192
254
  //#region src/embedding/service.d.ts
@@ -228,6 +290,11 @@ declare class MemoryRepository {
228
290
  type?: MemoryType;
229
291
  pinned?: boolean;
230
292
  }): Memory[];
293
+ listFlagged(): Memory[];
294
+ listReviewEvents(memoryId: string, opts?: {
295
+ unresolvedOnly?: boolean;
296
+ }): ReviewEvent[];
297
+ resolveReviewEvents(memoryId: string): void;
231
298
  stats(): {
232
299
  byType: Record<MemoryType, number>;
233
300
  total: number;
@@ -275,5 +342,5 @@ declare class SessionContextBuilder {
275
342
  getSessionContext(projectHash: string): SessionContext;
276
343
  }
277
344
  //#endregion
278
- export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, Memory, MemoryPatch, MemoryPatchSchema, MemoryRepository, MemoryRow, MemoryRowSchema, MemorySchema, MemoryType, MemoryTypeSchema, MigrationMeta, ProgressCallback, Project, ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptions, QueryOptionsSchema, SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, SessionContext, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
345
+ export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, Memory, MemoryPatch, MemoryPatchSchema, MemoryRepository, MemoryRow, MemoryRowSchema, MemorySchema, MemoryType, MemoryTypeSchema, MigrationMeta, ProgressCallback, Project, ProjectRepository, ProjectRow, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptions, QueryOptionsSchema, ReviewEvent, ReviewEventRow, ReviewEventRowSchema, ReviewEventSchema, ReviewReason, ReviewReasonSchema, SaveOptions, SaveOptionsSchema, ScopeToProjectsResult, SessionContext, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
279
346
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/project/repository.ts","../src/memory/repository.ts","../src/migrations/index.ts","../src/query/engine.ts","../src/scope/resolver.ts","../src/session/builder.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/project/repository.ts","../src/memory/repository.ts","../src/migrations/index.ts","../src/query/engine.ts","../src/scope/resolver.ts","../src/session/builder.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -24,7 +24,8 @@ var DatabaseError = class extends MembankError {
24
24
  //#endregion
25
25
  //#region src/db/manager.ts
26
26
  const DEFAULT_DB_PATH = join(homedir(), ".membank", "memory.db");
27
- const MIGRATIONS$1 = [[1, `
27
+ const MIGRATIONS$1 = [
28
+ [1, `
28
29
  CREATE TABLE IF NOT EXISTS memories (
29
30
  id TEXT PRIMARY KEY,
30
31
  content TEXT NOT NULL,
@@ -42,7 +43,8 @@ CREATE TABLE IF NOT EXISTS memories (
42
43
  CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(
43
44
  embedding FLOAT[384]
44
45
  );
45
- `], [2, `
46
+ `],
47
+ [2, `
46
48
  CREATE TABLE IF NOT EXISTS projects (
47
49
  id TEXT PRIMARY KEY,
48
50
  name TEXT NOT NULL,
@@ -75,7 +77,25 @@ JOIN projects p ON p.scope_hash = m.scope
75
77
  WHERE m.scope != 'global';
76
78
 
77
79
  ALTER TABLE memories DROP COLUMN scope;
78
- `]];
80
+ `],
81
+ [3, `
82
+ CREATE TABLE IF NOT EXISTS memory_review_events (
83
+ id TEXT PRIMARY KEY,
84
+ memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
85
+ conflicting_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
86
+ similarity REAL NOT NULL,
87
+ conflict_content_snapshot TEXT NOT NULL,
88
+ reason TEXT NOT NULL,
89
+ created_at TEXT NOT NULL,
90
+ resolved_at TEXT
91
+ );
92
+
93
+ CREATE INDEX IF NOT EXISTS idx_review_events_memory_open
94
+ ON memory_review_events(memory_id) WHERE resolved_at IS NULL;
95
+
96
+ ALTER TABLE memories DROP COLUMN needs_review;
97
+ `]
98
+ ];
79
99
  var DatabaseManager = class DatabaseManager {
80
100
  #db;
81
101
  constructor(db) {
@@ -149,6 +169,27 @@ const ProjectSchema = z.object({
149
169
  createdAt: z.string(),
150
170
  updatedAt: z.string()
151
171
  });
172
+ const ReviewReasonSchema = z.enum(["similarity_dedup"]);
173
+ const ReviewEventSchema = z.object({
174
+ id: z.string(),
175
+ memoryId: z.string(),
176
+ conflictingMemoryId: z.string().nullable(),
177
+ similarity: z.number(),
178
+ conflictContentSnapshot: z.string(),
179
+ reason: ReviewReasonSchema,
180
+ createdAt: z.string(),
181
+ resolvedAt: z.string().nullable()
182
+ });
183
+ const ReviewEventRowSchema = z.object({
184
+ id: z.string(),
185
+ memory_id: z.string(),
186
+ conflicting_memory_id: z.string().nullable(),
187
+ similarity: z.number(),
188
+ conflict_content_snapshot: z.string(),
189
+ reason: ReviewReasonSchema,
190
+ created_at: z.string(),
191
+ resolved_at: z.string().nullable()
192
+ });
152
193
  const MemorySchema = z.object({
153
194
  id: z.string(),
154
195
  content: z.string(),
@@ -158,7 +199,7 @@ const MemorySchema = z.object({
158
199
  sourceHarness: z.string().nullable(),
159
200
  accessCount: z.number().int().nonnegative(),
160
201
  pinned: z.boolean(),
161
- needsReview: z.boolean(),
202
+ reviewEvents: z.array(ReviewEventSchema),
162
203
  createdAt: z.string(),
163
204
  updatedAt: z.string()
164
205
  });
@@ -196,7 +237,6 @@ const MemoryRowSchema = z.object({
196
237
  source: z.string().nullable(),
197
238
  access_count: z.number(),
198
239
  pinned: z.number(),
199
- needs_review: z.number(),
200
240
  created_at: z.string(),
201
241
  updated_at: z.string()
202
242
  });
@@ -209,7 +249,7 @@ const ProjectRowSchema = z.object({
209
249
  });
210
250
  //#endregion
211
251
  //#region src/db/row-types.ts
212
- function rowToMemory(row, projects) {
252
+ function rowToMemory(row, projects, reviewEvents = []) {
213
253
  return {
214
254
  id: row.id,
215
255
  content: row.content,
@@ -219,11 +259,24 @@ function rowToMemory(row, projects) {
219
259
  sourceHarness: row.source,
220
260
  accessCount: row.access_count,
221
261
  pinned: row.pinned !== 0,
222
- needsReview: row.needs_review !== 0,
262
+ reviewEvents,
223
263
  createdAt: row.created_at,
224
264
  updatedAt: row.updated_at
225
265
  };
226
266
  }
267
+ function rowToReviewEvent(row) {
268
+ const parsed = ReviewEventRowSchema.parse(row);
269
+ return {
270
+ id: parsed.id,
271
+ memoryId: parsed.memory_id,
272
+ conflictingMemoryId: parsed.conflicting_memory_id,
273
+ similarity: parsed.similarity,
274
+ conflictContentSnapshot: parsed.conflict_content_snapshot,
275
+ reason: parsed.reason,
276
+ createdAt: parsed.created_at,
277
+ resolvedAt: parsed.resolved_at
278
+ };
279
+ }
227
280
  function rowToProject(row) {
228
281
  return {
229
282
  id: row.id,
@@ -289,18 +342,23 @@ var MemoryRepository = class {
289
342
  if (top !== void 0 && top.similarity > .92) {
290
343
  this.#db.db.prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`).run(content, now, top.id);
291
344
  this.#db.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(embeddingBlob, top.rowid);
292
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(top.id)), this.#projects.getProjectsForMemories([top.id]).get(top.id) ?? []);
345
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(top.id));
346
+ const projectMap = this.#projects.getProjectsForMemories([top.id]);
347
+ const events = this.#getEventsForMemories([top.id]);
348
+ return rowToMemory(updated, projectMap.get(top.id) ?? [], events.get(top.id) ?? []);
293
349
  }
294
- if (top !== void 0 && top.similarity >= .75) this.#db.db.prepare(`UPDATE memories SET needs_review = 1 WHERE id = ?`).run(top.id);
295
350
  const id = randomUUID();
296
- this.#db.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, needs_review, created_at, updated_at)
297
- VALUES (?, ?, ?, ?, ?, 0, 0, 0, ?, ?)`).run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);
351
+ this.#db.db.prepare(`INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)
352
+ VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`).run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);
353
+ if (top !== void 0 && top.similarity >= .75) this.#db.db.prepare(`INSERT INTO memory_review_events
354
+ (id, memory_id, conflicting_memory_id, similarity, conflict_content_snapshot, reason, created_at)
355
+ VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`).run(randomUUID(), top.id, id, top.similarity, content, now);
298
356
  this.#db.db.prepare(`INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`).run(embeddingBlob, id);
299
357
  if (projectScope !== void 0) {
300
358
  const project = this.#projects.upsertByHash(projectScope.hash, projectScope.name);
301
359
  this.#projects.addAssociation(id, project.id);
302
360
  }
303
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
361
+ return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? [], []);
304
362
  }
305
363
  async update(id, patch) {
306
364
  const { content, tags } = MemoryPatchSchema.parse(patch);
@@ -324,7 +382,10 @@ var MemoryRepository = class {
324
382
  const embeddingBlob = Buffer.from(embedding.buffer);
325
383
  this.#db.db.prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`).run(embeddingBlob, existing.rowid);
326
384
  }
327
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
385
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id));
386
+ const projectMap = this.#projects.getProjectsForMemories([id]);
387
+ const events = this.#getEventsForMemories([id]);
388
+ return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);
328
389
  }
329
390
  delete(id) {
330
391
  const row = this.#db.db.prepare(`SELECT rowid FROM memories WHERE id = ?`).get(id);
@@ -346,7 +407,45 @@ var MemoryRepository = class {
346
407
  if (rows.length === 0) return [];
347
408
  const ids = rows.map((r) => r.id);
348
409
  const projectMap = this.#projects.getProjectsForMemories(ids);
349
- return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? []));
410
+ const eventMap = this.#getEventsForMemories(ids);
411
+ return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? []));
412
+ }
413
+ listFlagged() {
414
+ const rows = this.#db.db.prepare(`SELECT * FROM memories
415
+ WHERE EXISTS (
416
+ SELECT 1 FROM memory_review_events e
417
+ WHERE e.memory_id = memories.id AND e.resolved_at IS NULL
418
+ )
419
+ ORDER BY created_at DESC`).all();
420
+ if (rows.length === 0) return [];
421
+ const ids = rows.map((r) => r.id);
422
+ const projectMap = this.#projects.getProjectsForMemories(ids);
423
+ const eventMap = this.#getEventsForMemories(ids, { unresolvedOnly: true });
424
+ return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? []));
425
+ }
426
+ listReviewEvents(memoryId, opts) {
427
+ const where = opts?.unresolvedOnly === true ? "WHERE memory_id = ? AND resolved_at IS NULL" : "WHERE memory_id = ?";
428
+ return this.#db.db.prepare(`SELECT * FROM memory_review_events ${where} ORDER BY created_at DESC`).all(memoryId).map((r) => rowToReviewEvent(ReviewEventRowSchema.parse(r)));
429
+ }
430
+ resolveReviewEvents(memoryId) {
431
+ const now = (/* @__PURE__ */ new Date()).toISOString();
432
+ this.#db.db.prepare(`UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`).run(now, memoryId);
433
+ }
434
+ #getEventsForMemories(ids, opts) {
435
+ if (ids.length === 0) return /* @__PURE__ */ new Map();
436
+ const placeholders = ids.map(() => "?").join(", ");
437
+ const unresolvedClause = opts?.unresolvedOnly === true ? "AND resolved_at IS NULL" : "";
438
+ const rows = this.#db.db.prepare(`SELECT * FROM memory_review_events
439
+ WHERE memory_id IN (${placeholders}) ${unresolvedClause}
440
+ ORDER BY created_at DESC`).all(...ids);
441
+ const map = /* @__PURE__ */ new Map();
442
+ for (const row of rows) {
443
+ const event = rowToReviewEvent(ReviewEventRowSchema.parse(row));
444
+ const existing = map.get(event.memoryId) ?? [];
445
+ existing.push(event);
446
+ map.set(event.memoryId, existing);
447
+ }
448
+ return map;
350
449
  }
351
450
  stats() {
352
451
  const byType = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0]));
@@ -355,21 +454,22 @@ var MemoryRepository = class {
355
454
  const parsed = MemoryTypeSchema.safeParse(row.type);
356
455
  if (parsed.success) byType[parsed.data] = row.count;
357
456
  }
358
- const totals = this.#db.db.prepare(`SELECT COUNT(*) as total, SUM(needs_review) as needsReview FROM memories`).get() ?? {
359
- total: 0,
360
- needsReview: 0
361
- };
457
+ const totals = this.#db.db.prepare(`SELECT COUNT(*) as total FROM memories`).get() ?? { total: 0 };
458
+ const reviewRow = this.#db.db.prepare(`SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`).get() ?? { needsReview: 0 };
362
459
  return {
363
460
  byType,
364
461
  total: totals.total,
365
- needsReview: totals.needsReview ?? 0
462
+ needsReview: reviewRow.needsReview
366
463
  };
367
464
  }
368
465
  setPin(id, pinned) {
369
466
  if (this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id) === void 0) throw new Error(`Memory not found: ${id}`);
370
467
  const now = (/* @__PURE__ */ new Date()).toISOString();
371
468
  this.#db.db.prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`).run(pinned ? 1 : 0, now, id);
372
- return rowToMemory(MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id)), this.#projects.getProjectsForMemories([id]).get(id) ?? []);
469
+ const updated = MemoryRowSchema.parse(this.#db.db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id));
470
+ const projectMap = this.#projects.getProjectsForMemories([id]);
471
+ const events = this.#getEventsForMemories([id]);
472
+ return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);
373
473
  }
374
474
  incrementAccessCount(id) {
375
475
  this.#db.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(id);
@@ -584,6 +684,6 @@ var SessionContextBuilder = class {
584
684
  }
585
685
  };
586
686
  //#endregion
587
- export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, MemoryPatchSchema, MemoryRepository, MemoryRowSchema, MemorySchema, MemoryTypeSchema, ProjectRepository, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptionsSchema, SaveOptionsSchema, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
687
+ export { DatabaseError, DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MembankError, MemoryPatchSchema, MemoryRepository, MemoryRowSchema, MemorySchema, MemoryTypeSchema, ProjectRepository, ProjectRowSchema, ProjectSchema, QueryEngine, QueryOptionsSchema, ReviewEventRowSchema, ReviewEventSchema, ReviewReasonSchema, SaveOptionsSchema, SessionContextBuilder, SessionContextSchema, TagsJsonSchema, listMemoryTypes, resolveProject, resolveScope, rowToMemory, rowToProject, runScopeToProjectsMigration };
588
688
 
589
689
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["MIGRATIONS","#db","#init","#initInMemory","#runMigrations","#db","#embedding","#projects","#db","#db","#embedding","#repo","#computeScore","#db"],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/memory/repository.ts","../src/scope/resolver.ts","../src/migrations/index.ts","../src/project/repository.ts","../src/query/engine.ts","../src/session/builder.ts"],"sourcesContent":["export class MembankError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"MembankError\";\n }\n}\n\nexport class DatabaseError extends MembankError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"DatabaseError\";\n }\n}\n","import { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport BetterSqlite3 from \"better-sqlite3\";\nimport * as sqliteVec from \"sqlite-vec\";\nimport { DatabaseError } from \"./errors.js\";\n\nconst DEFAULT_DB_PATH = join(homedir(), \".membank\", \"memory.db\");\n\ntype VecLoader = (db: BetterSqlite3.Database) => void;\n\nconst MIGRATIONS: [number, string][] = [\n [\n 1,\n `\nCREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n type TEXT NOT NULL,\n tags TEXT NOT NULL DEFAULT '[]',\n scope TEXT NOT NULL,\n source TEXT,\n access_count INTEGER NOT NULL DEFAULT 0,\n pinned INTEGER NOT NULL DEFAULT 0,\n needs_review INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(\n embedding FLOAT[384]\n);\n`,\n ],\n [\n 2,\n `\nCREATE TABLE IF NOT EXISTS projects (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n scope_hash TEXT NOT NULL UNIQUE,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS memory_projects (\n memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n PRIMARY KEY (memory_id, project_id)\n);\n\nINSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at)\nSELECT\n lower(hex(randomblob(16))),\n 'project-' || substr(scope, 1, 8),\n scope,\n datetime('now'),\n datetime('now')\nFROM memories\nWHERE scope != 'global'\nGROUP BY scope;\n\nINSERT OR IGNORE INTO memory_projects (memory_id, project_id)\nSELECT m.id, p.id\nFROM memories m\nJOIN projects p ON p.scope_hash = m.scope\nWHERE m.scope != 'global';\n\nALTER TABLE memories DROP COLUMN scope;\n`,\n ],\n];\n\nexport class DatabaseManager {\n readonly #db: BetterSqlite3.Database;\n\n private constructor(db: BetterSqlite3.Database) {\n this.#db = db;\n }\n\n static open(dbPath?: string): DatabaseManager {\n const resolvedPath = dbPath ?? DEFAULT_DB_PATH;\n mkdirSync(dirname(resolvedPath), { recursive: true });\n const db = new BetterSqlite3(resolvedPath);\n return DatabaseManager.#init(db, sqliteVec.load);\n }\n\n static openInMemory(): DatabaseManager {\n return DatabaseManager.#initInMemory(sqliteVec.load);\n }\n\n /** For testing: inject a custom vec loader (e.g. a throwing stub). */\n static _openInMemoryWithLoader(loader: VecLoader): DatabaseManager {\n return DatabaseManager.#initInMemory(loader);\n }\n\n static #initInMemory(loader: VecLoader): DatabaseManager {\n const db = new BetterSqlite3(\":memory:\");\n return DatabaseManager.#init(db, loader);\n }\n\n static #init(db: BetterSqlite3.Database, loader: VecLoader): DatabaseManager {\n try {\n loader(db);\n } catch (err) {\n throw new DatabaseError(\"Failed to load sqlite-vec extension\", {\n cause: err,\n });\n }\n\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"foreign_keys = ON\");\n\n const manager = new DatabaseManager(db);\n manager.#runMigrations();\n return manager;\n }\n\n #runMigrations(): void {\n // Bootstrap the meta table before reading schema_version from it\n this.#db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n const row = this.#db\n .prepare<[], { value: string }>(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get();\n\n const currentVersion = row ? Number.parseInt(row.value, 10) : 0;\n\n for (const [targetVersion, sql] of MIGRATIONS) {\n if (currentVersion < targetVersion) {\n this.#db.exec(sql);\n this.#db\n .prepare(\"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\")\n .run(String(targetVersion));\n }\n }\n }\n\n get db(): BetterSqlite3.Database {\n return this.#db;\n }\n\n close(): void {\n this.#db.close();\n }\n}\n","import { z } from \"zod\";\n\nexport const MEMORY_TYPE_VALUES = [\n \"correction\",\n \"preference\",\n \"decision\",\n \"learning\",\n \"fact\",\n] as const;\n\nexport const MemoryTypeSchema = z.enum(MEMORY_TYPE_VALUES);\nexport type MemoryType = z.infer<typeof MemoryTypeSchema>;\n\nexport const TagsJsonSchema = z.array(z.string());\n\nexport const ProjectSchema = z.object({\n id: z.string(),\n name: z.string(),\n scopeHash: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type Project = z.infer<typeof ProjectSchema>;\n\nexport const MemorySchema = z.object({\n id: z.string(),\n content: z.string(),\n type: MemoryTypeSchema,\n tags: z.array(z.string()),\n projects: z.array(ProjectSchema),\n sourceHarness: z.string().nullable(),\n accessCount: z.number().int().nonnegative(),\n pinned: z.boolean(),\n needsReview: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type Memory = z.infer<typeof MemorySchema>;\n\nexport const QueryOptionsSchema = z.object({\n query: z.string().min(1),\n type: MemoryTypeSchema.optional(),\n projectHash: z.string().optional(),\n limit: z.number().int().positive().optional(),\n includePinned: z.boolean().optional(),\n});\nexport type QueryOptions = z.infer<typeof QueryOptionsSchema>;\n\nexport const SaveOptionsSchema = z.object({\n content: z.string().min(1),\n type: MemoryTypeSchema,\n tags: z.array(z.string()).optional(),\n projectScope: z.object({ hash: z.string(), name: z.string() }).optional(),\n sourceHarness: z.string().optional(),\n});\nexport type SaveOptions = z.infer<typeof SaveOptionsSchema>;\n\nexport const MemoryPatchSchema = z.object({\n content: z.string().min(1).optional(),\n tags: z.array(z.string()).optional(),\n});\nexport type MemoryPatch = z.infer<typeof MemoryPatchSchema>;\n\nexport const SessionContextSchema = z.object({\n stats: z.record(MemoryTypeSchema, z.number()),\n pinnedGlobal: z.array(MemorySchema),\n pinnedProject: z.array(MemorySchema),\n});\nexport type SessionContext = z.infer<typeof SessionContextSchema>;\n\nexport const MemoryRowSchema = z.object({\n id: z.string(),\n content: z.string(),\n type: z.string(),\n tags: z.string(),\n source: z.string().nullable(),\n access_count: z.number(),\n pinned: z.number(),\n needs_review: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type MemoryRow = z.infer<typeof MemoryRowSchema>;\n\nexport const ProjectRowSchema = z.object({\n id: z.string(),\n name: z.string(),\n scope_hash: z.string(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type ProjectRow = z.infer<typeof ProjectRowSchema>;\n","import { MemoryTypeSchema, TagsJsonSchema } from \"../schemas.js\";\nimport type { Memory, MemoryRow, Project, ProjectRow } from \"../types.js\";\n\nexport function rowToMemory(row: MemoryRow, projects: Project[]): Memory {\n return {\n id: row.id,\n content: row.content,\n type: MemoryTypeSchema.parse(row.type),\n tags: TagsJsonSchema.parse(JSON.parse(row.tags)),\n projects,\n sourceHarness: row.source,\n accessCount: row.access_count,\n pinned: row.pinned !== 0,\n needsReview: row.needs_review !== 0,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function rowToProject(row: ProjectRow): Project {\n return {\n id: row.id,\n name: row.name,\n scopeHash: row.scope_hash,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pipeline } from \"@huggingface/transformers\";\n\nexport type ProgressCallback = (progress: { status: string; progress?: number }) => void;\n\nexport class EmbeddingService {\n private readonly modelCachePath: string;\n private readonly onProgress: ProgressCallback | undefined;\n private pipelineInstance: Awaited<ReturnType<typeof pipeline>> | null = null;\n\n constructor(modelCachePath?: string, onProgress?: ProgressCallback) {\n this.modelCachePath = modelCachePath ?? join(homedir(), \".membank\", \"models\");\n this.onProgress = onProgress;\n }\n\n private async getPipeline(): Promise<Awaited<ReturnType<typeof pipeline>>> {\n if (this.pipelineInstance === null) {\n this.pipelineInstance = await pipeline(\"feature-extraction\", \"Xenova/bge-small-en-v1.5\", {\n cache_dir: this.modelCachePath,\n progress_callback: this.onProgress,\n });\n }\n return this.pipelineInstance;\n }\n\n async embed(text: string): Promise<Float32Array> {\n const pipe = await this.getPipeline();\n // Shape: [1, seq_len, 384]. Cast to any to bypass the non-unified pipeline union signature.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const output = await (\n pipe as (input: string, opts: Record<string, unknown>) => Promise<unknown>\n )(text, { pooling: \"mean\", normalize: true });\n\n // @huggingface/transformers Tensor has a .data property with the flat array\n const tensor = output as { data: Float32Array | number[] };\n const flat = tensor.data;\n\n return flat instanceof Float32Array ? flat : new Float32Array(flat);\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory } from \"../db/row-types.js\";\nimport type { EmbeddingService } from \"../embedding/service.js\";\nimport type { ProjectRepository } from \"../project/repository.js\";\nimport {\n MEMORY_TYPE_VALUES,\n MemoryPatchSchema,\n MemoryRowSchema,\n MemoryTypeSchema,\n SaveOptionsSchema,\n} from \"../schemas.js\";\nimport type { Memory, MemoryPatch, MemoryRow, MemoryType, SaveOptions } from \"../types.js\";\n\ninterface SimilarityRow extends MemoryRow {\n rowid: number;\n similarity: number;\n}\n\nexport class MemoryRepository {\n readonly #db: DatabaseManager;\n readonly #embedding: EmbeddingService;\n readonly #projects: ProjectRepository;\n\n constructor(\n db: DatabaseManager,\n embeddingService: EmbeddingService,\n projects: ProjectRepository\n ) {\n this.#db = db;\n this.#embedding = embeddingService;\n this.#projects = projects;\n }\n\n async save(options: SaveOptions): Promise<Memory> {\n const {\n content,\n type,\n tags = [],\n projectScope,\n sourceHarness,\n } = SaveOptionsSchema.parse(options);\n\n const embedding = await this.#embedding.embed(content);\n const embeddingBlob = Buffer.from(embedding.buffer);\n\n // Dedup: find similar memory in same context\n let top: SimilarityRow | undefined;\n if (projectScope !== undefined) {\n top = this.#db.db\n .prepare<[Buffer, string, string], SimilarityRow>(\n `SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n JOIN memory_projects mp ON mp.memory_id = m.id\n JOIN projects p ON p.id = mp.project_id\n WHERE m.type = ? AND p.scope_hash = ?\n ORDER BY similarity DESC LIMIT 1`\n )\n .get(embeddingBlob, type, projectScope.hash);\n } else {\n top = this.#db.db\n .prepare<[Buffer, string], SimilarityRow>(\n `SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n WHERE m.type = ?\n AND m.id NOT IN (SELECT memory_id FROM memory_projects)\n ORDER BY similarity DESC LIMIT 1`\n )\n .get(embeddingBlob, type);\n }\n\n const now = new Date().toISOString();\n\n if (top !== undefined && top.similarity > 0.92) {\n this.#db.db\n .prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`)\n .run(content, now, top.id);\n this.#db.db\n .prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`)\n .run(embeddingBlob, top.rowid);\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(top.id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([top.id]);\n return rowToMemory(updated, projectMap.get(top.id) ?? []);\n }\n\n if (top !== undefined && top.similarity >= 0.75) {\n this.#db.db.prepare(`UPDATE memories SET needs_review = 1 WHERE id = ?`).run(top.id);\n }\n\n const id = randomUUID();\n this.#db.db\n .prepare(\n `INSERT INTO memories (id, content, type, tags, source, access_count, pinned, needs_review, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, 0, 0, 0, ?, ?)`\n )\n .run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);\n\n this.#db.db\n .prepare(\n `INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`\n )\n .run(embeddingBlob, id);\n\n if (projectScope !== undefined) {\n const project = this.#projects.upsertByHash(projectScope.hash, projectScope.name);\n this.#projects.addAssociation(id, project.id);\n }\n\n const row = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n return rowToMemory(row, projectMap.get(id) ?? []);\n }\n\n async update(id: string, patch: MemoryPatch): Promise<Memory> {\n const { content, tags } = MemoryPatchSchema.parse(patch);\n\n const existing = this.#db.db\n .prepare<[string], MemoryRow & { rowid: number }>(\n `SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`\n )\n .get(id);\n\n if (existing === undefined) {\n throw new Error(`Memory not found: ${id}`);\n }\n\n const now = new Date().toISOString();\n const sets: string[] = [\"updated_at = ?\"];\n const values: string[] = [now];\n\n if (content !== undefined) {\n sets.push(\"content = ?\");\n values.push(content);\n }\n\n if (tags !== undefined) {\n sets.push(\"tags = ?\");\n values.push(JSON.stringify(tags));\n }\n\n values.push(id);\n this.#db.db.prepare(`UPDATE memories SET ${sets.join(\", \")} WHERE id = ?`).run(...values);\n\n if (content !== undefined) {\n const embedding = await this.#embedding.embed(content);\n const embeddingBlob = Buffer.from(embedding.buffer);\n this.#db.db\n .prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`)\n .run(embeddingBlob, existing.rowid);\n }\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n return rowToMemory(updated, projectMap.get(id) ?? []);\n }\n\n delete(id: string): Promise<void> {\n const row = this.#db.db\n .prepare<[string], { rowid: number }>(`SELECT rowid FROM memories WHERE id = ?`)\n .get(id);\n\n if (row !== undefined) {\n this.#db.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(row.rowid);\n }\n\n this.#db.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(id);\n this.#db.db.prepare(`DELETE FROM memories WHERE id = ?`).run(id);\n\n return Promise.resolve();\n }\n\n list(opts?: { type?: MemoryType; pinned?: boolean }): Memory[] {\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (opts?.type !== undefined) {\n conditions.push(\"type = ?\");\n params.push(opts.type);\n }\n\n if (opts?.pinned === true) {\n conditions.push(\"pinned = 1\");\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n const rows = this.#db.db\n .prepare<(string | number)[], MemoryRow>(\n `SELECT * FROM memories ${where} ORDER BY created_at DESC`\n )\n .all(...params);\n\n if (rows.length === 0) return [];\n\n const ids = rows.map((r) => r.id);\n const projectMap = this.#projects.getProjectsForMemories(ids);\n return rows.map((row) => rowToMemory(row, projectMap.get(row.id) ?? []));\n }\n\n stats(): { byType: Record<MemoryType, number>; total: number; needsReview: number } {\n const byType = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0])) as Record<\n MemoryType,\n number\n >;\n\n const typeRows = this.#db.db\n .prepare<[], { type: string; count: number }>(\n `SELECT type, COUNT(*) as count FROM memories GROUP BY type`\n )\n .all();\n\n for (const row of typeRows) {\n const parsed = MemoryTypeSchema.safeParse(row.type);\n if (parsed.success) {\n byType[parsed.data] = row.count;\n }\n }\n\n const totals = this.#db.db\n .prepare<[], { total: number; needsReview: number }>(\n `SELECT COUNT(*) as total, SUM(needs_review) as needsReview FROM memories`\n )\n .get() ?? { total: 0, needsReview: 0 };\n\n return {\n byType,\n total: totals.total,\n needsReview: totals.needsReview ?? 0,\n };\n }\n\n setPin(id: string, pinned: boolean): Memory {\n const existing = this.#db.db\n .prepare<[string], MemoryRow>(`SELECT * FROM memories WHERE id = ?`)\n .get(id);\n\n if (existing === undefined) {\n throw new Error(`Memory not found: ${id}`);\n }\n\n const now = new Date().toISOString();\n this.#db.db\n .prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`)\n .run(pinned ? 1 : 0, now, id);\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n return rowToMemory(updated, projectMap.get(id) ?? []);\n }\n\n incrementAccessCount(id: string): void {\n this.#db.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(id);\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nfunction sha256Truncated(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\").slice(0, 16);\n}\n\nexport async function resolveProject(): Promise<{ hash: string; name: string }> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"]);\n const url = stdout.trim();\n if (url) {\n const hash = sha256Truncated(url);\n // parse last path segment, strip .git suffix\n const name =\n url\n .split(\"/\")\n .pop()\n ?.replace(/\\.git$/, \"\") ?? hash.slice(0, 8);\n return { hash, name };\n }\n } catch {\n // fall through\n }\n\n const cwd = process.cwd();\n const hash = sha256Truncated(cwd);\n const name = cwd.split(/[/\\\\]/).filter(Boolean).pop() ?? hash.slice(0, 8);\n return { hash, name };\n}\n\nexport async function resolveScope(): Promise<string> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"]);\n const url = stdout.trim();\n if (url) {\n return sha256Truncated(url);\n }\n } catch {\n // git not available, not a repo, or no remote — fall through to cwd fallback\n }\n\n return sha256Truncated(process.cwd());\n}\n","import type { ProjectRepository } from \"../project/index.js\";\nimport { resolveProject } from \"../scope/index.js\";\n\nexport interface MigrationMeta {\n name: string;\n description: string;\n}\n\nexport interface ScopeToProjectsResult {\n migration: \"scope-to-projects\";\n oldName: string;\n newName: string;\n memoryCount: number;\n}\n\nexport const MIGRATIONS: MigrationMeta[] = [\n {\n name: \"scope-to-projects\",\n description:\n \"Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.\",\n },\n];\n\nexport async function runScopeToProjectsMigration(\n projects: ProjectRepository\n): Promise<ScopeToProjectsResult | null> {\n const resolved = await resolveProject();\n const project = projects.getByHash(resolved.hash);\n\n if (project === undefined) {\n return null;\n }\n\n const oldName = project.name;\n const memoryCount = projects.countMemories(project.id);\n projects.rename(project.id, resolved.name);\n\n return {\n migration: \"scope-to-projects\",\n oldName,\n newName: resolved.name,\n memoryCount,\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToProject } from \"../db/row-types.js\";\nimport { ProjectRowSchema } from \"../schemas.js\";\nimport type { Project, ProjectRow } from \"../types.js\";\n\ninterface ProjectMemoryRow extends ProjectRow {\n memory_id: string;\n}\n\nexport class ProjectRepository {\n readonly #db: DatabaseManager;\n\n constructor(db: DatabaseManager) {\n this.#db = db;\n }\n\n upsertByHash(hash: string, name: string): Project {\n const now = new Date().toISOString();\n const id = randomUUID();\n this.#db.db\n .prepare(\n `INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`\n )\n .run(id, name, hash, now, now);\n\n const row = ProjectRowSchema.parse(\n this.#db.db\n .prepare<[string], unknown>(`SELECT * FROM projects WHERE scope_hash = ?`)\n .get(hash)\n );\n\n return rowToProject(row);\n }\n\n rename(id: string, name: string): Project {\n const now = new Date().toISOString();\n this.#db.db\n .prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`)\n .run(name, now, id);\n\n const row = this.#db.db\n .prepare<[string], ProjectRow>(`SELECT * FROM projects WHERE id = ?`)\n .get(id);\n\n if (row === undefined) throw new Error(`Project not found: ${id}`);\n return rowToProject(row);\n }\n\n list(): Project[] {\n return this.#db.db\n .prepare<[], ProjectRow>(`SELECT * FROM projects ORDER BY name ASC`)\n .all()\n .map(rowToProject);\n }\n\n getByHash(hash: string): Project | undefined {\n const row = this.#db.db\n .prepare<[string], ProjectRow>(`SELECT * FROM projects WHERE scope_hash = ?`)\n .get(hash);\n return row !== undefined ? rowToProject(row) : undefined;\n }\n\n addAssociation(memoryId: string, projectId: string): void {\n this.#db.db\n .prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`)\n .run(memoryId, projectId);\n }\n\n removeAssociation(memoryId: string, projectId: string): void {\n this.#db.db\n .prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`)\n .run(memoryId, projectId);\n }\n\n countMemories(projectId: string): number {\n const row = this.#db.db\n .prepare<[string], { count: number }>(\n `SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`\n )\n .get(projectId);\n return row?.count ?? 0;\n }\n\n getProjectsForMemories(memoryIds: string[]): Map<string, Project[]> {\n if (memoryIds.length === 0) return new Map();\n const placeholders = memoryIds.map(() => \"?\").join(\",\");\n const rows = this.#db.db\n .prepare<string[], ProjectMemoryRow>(\n `SELECT p.*, mp.memory_id FROM projects p\n JOIN memory_projects mp ON mp.project_id = p.id\n WHERE mp.memory_id IN (${placeholders})`\n )\n .all(...memoryIds);\n\n const result = new Map<string, Project[]>();\n for (const row of rows) {\n const list = result.get(row.memory_id) ?? [];\n list.push(rowToProject(row));\n result.set(row.memory_id, list);\n }\n return result;\n }\n}\n","import type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory } from \"../db/row-types.js\";\nimport type { EmbeddingService } from \"../embedding/service.js\";\nimport type { MemoryRepository } from \"../memory/repository.js\";\nimport { QueryOptionsSchema } from \"../schemas.js\";\nimport type { Memory, MemoryRow, MemoryType, QueryOptions } from \"../types.js\";\n\ninterface QueryMemoryRow extends MemoryRow {\n cosine_sim: number;\n}\n\nconst TYPE_WEIGHTS = {\n correction: 1.0,\n preference: 0.8,\n decision: 0.6,\n learning: 0.4,\n fact: 0.2,\n} satisfies Record<MemoryType, number>;\n\nexport class QueryEngine {\n readonly #db: DatabaseManager;\n readonly #embedding: EmbeddingService;\n readonly #repo: MemoryRepository;\n\n constructor(db: DatabaseManager, embeddingService: EmbeddingService, repo: MemoryRepository) {\n this.#db = db;\n this.#embedding = embeddingService;\n this.#repo = repo;\n }\n\n async query(options: QueryOptions): Promise<Array<Memory & { score: number }>> {\n const {\n query,\n type,\n projectHash,\n limit = 10,\n includePinned,\n } = QueryOptionsSchema.parse(options);\n\n const queryEmbedding = await this.#embedding.embed(query);\n const queryBlob = Buffer.from(queryEmbedding.buffer);\n\n const whereClauses: string[] = [];\n const params: unknown[] = [queryBlob];\n let joinClause = \"\";\n\n if (!includePinned) {\n whereClauses.push(\"m.pinned = 0\");\n }\n\n if (type !== undefined) {\n whereClauses.push(\"m.type = ?\");\n params.push(type);\n }\n\n if (projectHash !== undefined) {\n joinClause =\n \"LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id\";\n whereClauses.push(\"p.scope_hash = ?\");\n params.push(projectHash);\n }\n\n const whereSQL = whereClauses.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\";\n\n const sql = `\n SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n ${joinClause}\n ${whereSQL}\n `;\n\n const rows = this.#db.db.prepare<unknown[], QueryMemoryRow>(sql).all(...params);\n\n const now = Date.now();\n\n const scored = rows\n .filter((row) => row.cosine_sim > 0)\n .map((row) => {\n const memory = rowToMemory(row, []);\n const score = this.#computeScore(memory, now);\n return { ...memory, score };\n });\n\n scored.sort((a, b) => b.score - a.score);\n\n const results = scored.slice(0, limit);\n\n for (const result of results) {\n this.#repo.incrementAccessCount(result.id);\n }\n\n return results;\n }\n\n #computeScore(memory: Memory, now: number): number {\n const typeWeight = TYPE_WEIGHTS[memory.type];\n const accessCountNorm = memory.accessCount / (memory.accessCount + 10);\n const daysSinceUpdate = (now - new Date(memory.updatedAt).getTime()) / 86400000;\n const recencyNorm = 1 / (1 + daysSinceUpdate);\n const pinned = memory.pinned ? 1.0 : 0.0;\n\n return typeWeight * 0.4 + accessCountNorm * 0.3 + recencyNorm * 0.2 + pinned * 0.1;\n }\n}\n","import type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory } from \"../db/row-types.js\";\nimport { MEMORY_TYPE_VALUES, MemoryTypeSchema } from \"../schemas.js\";\nimport type { MemoryRow, MemoryType, SessionContext } from \"../types.js\";\n\ninterface TypeCountRow {\n type: string;\n count: number;\n}\n\nexport function listMemoryTypes(): MemoryType[] {\n return [...MEMORY_TYPE_VALUES];\n}\n\nexport class SessionContextBuilder {\n readonly #db: DatabaseManager;\n\n constructor(db: DatabaseManager) {\n this.#db = db;\n }\n\n getSessionContext(projectHash: string): SessionContext {\n const pinnedGlobal = this.#db.db\n .prepare<[], MemoryRow>(\n `SELECT * FROM memories\n WHERE id NOT IN (SELECT memory_id FROM memory_projects)\n AND pinned = 1`\n )\n .all()\n .map((row) => rowToMemory(row, []));\n\n const pinnedProject = this.#db.db\n .prepare<[string], MemoryRow>(\n `SELECT m.* FROM memories m\n JOIN memory_projects mp ON mp.memory_id = m.id\n JOIN projects p ON p.id = mp.project_id\n WHERE p.scope_hash = ? AND m.pinned = 1`\n )\n .all(projectHash)\n .map((row) => rowToMemory(row, []));\n\n const typeCounts = this.#db.db\n .prepare<[], TypeCountRow>(\"SELECT type, COUNT(*) as count FROM memories GROUP BY type\")\n .all();\n\n const stats = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0])) as Record<\n MemoryType,\n number\n >;\n for (const row of typeCounts) {\n const parsed = MemoryTypeSchema.safeParse(row.type);\n if (parsed.success) {\n stats[parsed.data] = row.count;\n }\n }\n\n return { stats, pinnedGlobal, pinnedProject };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["MIGRATIONS","#db","#init","#initInMemory","#runMigrations","#db","#embedding","#projects","#getEventsForMemories","#db","#db","#embedding","#repo","#computeScore","#db"],"sources":["../src/db/errors.ts","../src/db/manager.ts","../src/schemas.ts","../src/db/row-types.ts","../src/embedding/service.ts","../src/memory/repository.ts","../src/scope/resolver.ts","../src/migrations/index.ts","../src/project/repository.ts","../src/query/engine.ts","../src/session/builder.ts"],"sourcesContent":["export class MembankError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"MembankError\";\n }\n}\n\nexport class DatabaseError extends MembankError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"DatabaseError\";\n }\n}\n","import { mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport BetterSqlite3 from \"better-sqlite3\";\nimport * as sqliteVec from \"sqlite-vec\";\nimport { DatabaseError } from \"./errors.js\";\n\nconst DEFAULT_DB_PATH = join(homedir(), \".membank\", \"memory.db\");\n\ntype VecLoader = (db: BetterSqlite3.Database) => void;\n\nconst MIGRATIONS: [number, string][] = [\n [\n 1,\n `\nCREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n type TEXT NOT NULL,\n tags TEXT NOT NULL DEFAULT '[]',\n scope TEXT NOT NULL,\n source TEXT,\n access_count INTEGER NOT NULL DEFAULT 0,\n pinned INTEGER NOT NULL DEFAULT 0,\n needs_review INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(\n embedding FLOAT[384]\n);\n`,\n ],\n [\n 2,\n `\nCREATE TABLE IF NOT EXISTS projects (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n scope_hash TEXT NOT NULL UNIQUE,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS memory_projects (\n memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,\n project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,\n PRIMARY KEY (memory_id, project_id)\n);\n\nINSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at)\nSELECT\n lower(hex(randomblob(16))),\n 'project-' || substr(scope, 1, 8),\n scope,\n datetime('now'),\n datetime('now')\nFROM memories\nWHERE scope != 'global'\nGROUP BY scope;\n\nINSERT OR IGNORE INTO memory_projects (memory_id, project_id)\nSELECT m.id, p.id\nFROM memories m\nJOIN projects p ON p.scope_hash = m.scope\nWHERE m.scope != 'global';\n\nALTER TABLE memories DROP COLUMN scope;\n`,\n ],\n [\n 3,\n `\nCREATE TABLE IF NOT EXISTS memory_review_events (\n id TEXT PRIMARY KEY,\n memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,\n conflicting_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,\n similarity REAL NOT NULL,\n conflict_content_snapshot TEXT NOT NULL,\n reason TEXT NOT NULL,\n created_at TEXT NOT NULL,\n resolved_at TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_review_events_memory_open\n ON memory_review_events(memory_id) WHERE resolved_at IS NULL;\n\nALTER TABLE memories DROP COLUMN needs_review;\n`,\n ],\n];\n\nexport class DatabaseManager {\n readonly #db: BetterSqlite3.Database;\n\n private constructor(db: BetterSqlite3.Database) {\n this.#db = db;\n }\n\n static open(dbPath?: string): DatabaseManager {\n const resolvedPath = dbPath ?? DEFAULT_DB_PATH;\n mkdirSync(dirname(resolvedPath), { recursive: true });\n const db = new BetterSqlite3(resolvedPath);\n return DatabaseManager.#init(db, sqliteVec.load);\n }\n\n static openInMemory(): DatabaseManager {\n return DatabaseManager.#initInMemory(sqliteVec.load);\n }\n\n /** For testing: inject a custom vec loader (e.g. a throwing stub). */\n static _openInMemoryWithLoader(loader: VecLoader): DatabaseManager {\n return DatabaseManager.#initInMemory(loader);\n }\n\n static #initInMemory(loader: VecLoader): DatabaseManager {\n const db = new BetterSqlite3(\":memory:\");\n return DatabaseManager.#init(db, loader);\n }\n\n static #init(db: BetterSqlite3.Database, loader: VecLoader): DatabaseManager {\n try {\n loader(db);\n } catch (err) {\n throw new DatabaseError(\"Failed to load sqlite-vec extension\", {\n cause: err,\n });\n }\n\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"foreign_keys = ON\");\n\n const manager = new DatabaseManager(db);\n manager.#runMigrations();\n return manager;\n }\n\n #runMigrations(): void {\n // Bootstrap the meta table before reading schema_version from it\n this.#db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n const row = this.#db\n .prepare<[], { value: string }>(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get();\n\n const currentVersion = row ? Number.parseInt(row.value, 10) : 0;\n\n for (const [targetVersion, sql] of MIGRATIONS) {\n if (currentVersion < targetVersion) {\n this.#db.exec(sql);\n this.#db\n .prepare(\"INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)\")\n .run(String(targetVersion));\n }\n }\n }\n\n get db(): BetterSqlite3.Database {\n return this.#db;\n }\n\n close(): void {\n this.#db.close();\n }\n}\n","import { z } from \"zod\";\n\nexport const MEMORY_TYPE_VALUES = [\n \"correction\",\n \"preference\",\n \"decision\",\n \"learning\",\n \"fact\",\n] as const;\n\nexport const MemoryTypeSchema = z.enum(MEMORY_TYPE_VALUES);\nexport type MemoryType = z.infer<typeof MemoryTypeSchema>;\n\nexport const TagsJsonSchema = z.array(z.string());\n\nexport const ProjectSchema = z.object({\n id: z.string(),\n name: z.string(),\n scopeHash: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type Project = z.infer<typeof ProjectSchema>;\n\nexport const ReviewReasonSchema = z.enum([\"similarity_dedup\"]);\nexport type ReviewReason = z.infer<typeof ReviewReasonSchema>;\n\nexport const ReviewEventSchema = z.object({\n id: z.string(),\n memoryId: z.string(),\n conflictingMemoryId: z.string().nullable(),\n similarity: z.number(),\n conflictContentSnapshot: z.string(),\n reason: ReviewReasonSchema,\n createdAt: z.string(),\n resolvedAt: z.string().nullable(),\n});\nexport type ReviewEvent = z.infer<typeof ReviewEventSchema>;\n\nexport const ReviewEventRowSchema = z.object({\n id: z.string(),\n memory_id: z.string(),\n conflicting_memory_id: z.string().nullable(),\n similarity: z.number(),\n conflict_content_snapshot: z.string(),\n reason: ReviewReasonSchema,\n created_at: z.string(),\n resolved_at: z.string().nullable(),\n});\nexport type ReviewEventRow = z.infer<typeof ReviewEventRowSchema>;\n\nexport const MemorySchema = z.object({\n id: z.string(),\n content: z.string(),\n type: MemoryTypeSchema,\n tags: z.array(z.string()),\n projects: z.array(ProjectSchema),\n sourceHarness: z.string().nullable(),\n accessCount: z.number().int().nonnegative(),\n pinned: z.boolean(),\n reviewEvents: z.array(ReviewEventSchema),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type Memory = z.infer<typeof MemorySchema>;\n\nexport const QueryOptionsSchema = z.object({\n query: z.string().min(1),\n type: MemoryTypeSchema.optional(),\n projectHash: z.string().optional(),\n limit: z.number().int().positive().optional(),\n includePinned: z.boolean().optional(),\n});\nexport type QueryOptions = z.infer<typeof QueryOptionsSchema>;\n\nexport const SaveOptionsSchema = z.object({\n content: z.string().min(1),\n type: MemoryTypeSchema,\n tags: z.array(z.string()).optional(),\n projectScope: z.object({ hash: z.string(), name: z.string() }).optional(),\n sourceHarness: z.string().optional(),\n});\nexport type SaveOptions = z.infer<typeof SaveOptionsSchema>;\n\nexport const MemoryPatchSchema = z.object({\n content: z.string().min(1).optional(),\n tags: z.array(z.string()).optional(),\n});\nexport type MemoryPatch = z.infer<typeof MemoryPatchSchema>;\n\nexport const SessionContextSchema = z.object({\n stats: z.record(MemoryTypeSchema, z.number()),\n pinnedGlobal: z.array(MemorySchema),\n pinnedProject: z.array(MemorySchema),\n});\nexport type SessionContext = z.infer<typeof SessionContextSchema>;\n\nexport const MemoryRowSchema = z.object({\n id: z.string(),\n content: z.string(),\n type: z.string(),\n tags: z.string(),\n source: z.string().nullable(),\n access_count: z.number(),\n pinned: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type MemoryRow = z.infer<typeof MemoryRowSchema>;\n\nexport const ProjectRowSchema = z.object({\n id: z.string(),\n name: z.string(),\n scope_hash: z.string(),\n created_at: z.string(),\n updated_at: z.string(),\n});\nexport type ProjectRow = z.infer<typeof ProjectRowSchema>;\n","import { MemoryTypeSchema, ReviewEventRowSchema, TagsJsonSchema } from \"../schemas.js\";\nimport type {\n Memory,\n MemoryRow,\n Project,\n ProjectRow,\n ReviewEvent,\n ReviewEventRow,\n} from \"../types.js\";\n\nexport function rowToMemory(\n row: MemoryRow,\n projects: Project[],\n reviewEvents: ReviewEvent[] = []\n): Memory {\n return {\n id: row.id,\n content: row.content,\n type: MemoryTypeSchema.parse(row.type),\n tags: TagsJsonSchema.parse(JSON.parse(row.tags)),\n projects,\n sourceHarness: row.source,\n accessCount: row.access_count,\n pinned: row.pinned !== 0,\n reviewEvents,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function rowToReviewEvent(row: ReviewEventRow): ReviewEvent {\n const parsed = ReviewEventRowSchema.parse(row);\n return {\n id: parsed.id,\n memoryId: parsed.memory_id,\n conflictingMemoryId: parsed.conflicting_memory_id,\n similarity: parsed.similarity,\n conflictContentSnapshot: parsed.conflict_content_snapshot,\n reason: parsed.reason,\n createdAt: parsed.created_at,\n resolvedAt: parsed.resolved_at,\n };\n}\n\nexport function rowToProject(row: ProjectRow): Project {\n return {\n id: row.id,\n name: row.name,\n scopeHash: row.scope_hash,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pipeline } from \"@huggingface/transformers\";\n\nexport type ProgressCallback = (progress: { status: string; progress?: number }) => void;\n\nexport class EmbeddingService {\n private readonly modelCachePath: string;\n private readonly onProgress: ProgressCallback | undefined;\n private pipelineInstance: Awaited<ReturnType<typeof pipeline>> | null = null;\n\n constructor(modelCachePath?: string, onProgress?: ProgressCallback) {\n this.modelCachePath = modelCachePath ?? join(homedir(), \".membank\", \"models\");\n this.onProgress = onProgress;\n }\n\n private async getPipeline(): Promise<Awaited<ReturnType<typeof pipeline>>> {\n if (this.pipelineInstance === null) {\n this.pipelineInstance = await pipeline(\"feature-extraction\", \"Xenova/bge-small-en-v1.5\", {\n cache_dir: this.modelCachePath,\n progress_callback: this.onProgress,\n });\n }\n return this.pipelineInstance;\n }\n\n async embed(text: string): Promise<Float32Array> {\n const pipe = await this.getPipeline();\n // Shape: [1, seq_len, 384]. Cast to any to bypass the non-unified pipeline union signature.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const output = await (\n pipe as (input: string, opts: Record<string, unknown>) => Promise<unknown>\n )(text, { pooling: \"mean\", normalize: true });\n\n // @huggingface/transformers Tensor has a .data property with the flat array\n const tensor = output as { data: Float32Array | number[] };\n const flat = tensor.data;\n\n return flat instanceof Float32Array ? flat : new Float32Array(flat);\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory, rowToReviewEvent } from \"../db/row-types.js\";\nimport type { EmbeddingService } from \"../embedding/service.js\";\nimport type { ProjectRepository } from \"../project/repository.js\";\nimport {\n MEMORY_TYPE_VALUES,\n MemoryPatchSchema,\n MemoryRowSchema,\n MemoryTypeSchema,\n ReviewEventRowSchema,\n SaveOptionsSchema,\n} from \"../schemas.js\";\nimport type {\n Memory,\n MemoryPatch,\n MemoryRow,\n MemoryType,\n ReviewEvent,\n ReviewEventRow,\n SaveOptions,\n} from \"../types.js\";\n\ninterface SimilarityRow extends MemoryRow {\n rowid: number;\n similarity: number;\n}\n\nexport class MemoryRepository {\n readonly #db: DatabaseManager;\n readonly #embedding: EmbeddingService;\n readonly #projects: ProjectRepository;\n\n constructor(\n db: DatabaseManager,\n embeddingService: EmbeddingService,\n projects: ProjectRepository\n ) {\n this.#db = db;\n this.#embedding = embeddingService;\n this.#projects = projects;\n }\n\n async save(options: SaveOptions): Promise<Memory> {\n const {\n content,\n type,\n tags = [],\n projectScope,\n sourceHarness,\n } = SaveOptionsSchema.parse(options);\n\n const embedding = await this.#embedding.embed(content);\n const embeddingBlob = Buffer.from(embedding.buffer);\n\n // Dedup: find similar memory in same context\n let top: SimilarityRow | undefined;\n if (projectScope !== undefined) {\n top = this.#db.db\n .prepare<[Buffer, string, string], SimilarityRow>(\n `SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n JOIN memory_projects mp ON mp.memory_id = m.id\n JOIN projects p ON p.id = mp.project_id\n WHERE m.type = ? AND p.scope_hash = ?\n ORDER BY similarity DESC LIMIT 1`\n )\n .get(embeddingBlob, type, projectScope.hash);\n } else {\n top = this.#db.db\n .prepare<[Buffer, string], SimilarityRow>(\n `SELECT m.rowid, m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS similarity\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n WHERE m.type = ?\n AND m.id NOT IN (SELECT memory_id FROM memory_projects)\n ORDER BY similarity DESC LIMIT 1`\n )\n .get(embeddingBlob, type);\n }\n\n const now = new Date().toISOString();\n\n if (top !== undefined && top.similarity > 0.92) {\n this.#db.db\n .prepare(`UPDATE memories SET content = ?, updated_at = ? WHERE id = ?`)\n .run(content, now, top.id);\n this.#db.db\n .prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`)\n .run(embeddingBlob, top.rowid);\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(top.id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([top.id]);\n const events = this.#getEventsForMemories([top.id]);\n return rowToMemory(updated, projectMap.get(top.id) ?? [], events.get(top.id) ?? []);\n }\n\n const id = randomUUID();\n\n this.#db.db\n .prepare(\n `INSERT INTO memories (id, content, type, tags, source, access_count, pinned, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, 0, 0, ?, ?)`\n )\n .run(id, content, type, JSON.stringify(tags), sourceHarness ?? null, now, now);\n\n if (top !== undefined && top.similarity >= 0.75) {\n this.#db.db\n .prepare(\n `INSERT INTO memory_review_events\n (id, memory_id, conflicting_memory_id, similarity, conflict_content_snapshot, reason, created_at)\n VALUES (?, ?, ?, ?, ?, 'similarity_dedup', ?)`\n )\n .run(randomUUID(), top.id, id, top.similarity, content, now);\n }\n\n this.#db.db\n .prepare(\n `INSERT INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`\n )\n .run(embeddingBlob, id);\n\n if (projectScope !== undefined) {\n const project = this.#projects.upsertByHash(projectScope.hash, projectScope.name);\n this.#projects.addAssociation(id, project.id);\n }\n\n const row = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n return rowToMemory(row, projectMap.get(id) ?? [], []);\n }\n\n async update(id: string, patch: MemoryPatch): Promise<Memory> {\n const { content, tags } = MemoryPatchSchema.parse(patch);\n\n const existing = this.#db.db\n .prepare<[string], MemoryRow & { rowid: number }>(\n `SELECT m.rowid, m.* FROM memories m WHERE m.id = ?`\n )\n .get(id);\n\n if (existing === undefined) {\n throw new Error(`Memory not found: ${id}`);\n }\n\n const now = new Date().toISOString();\n const sets: string[] = [\"updated_at = ?\"];\n const values: string[] = [now];\n\n if (content !== undefined) {\n sets.push(\"content = ?\");\n values.push(content);\n }\n\n if (tags !== undefined) {\n sets.push(\"tags = ?\");\n values.push(JSON.stringify(tags));\n }\n\n values.push(id);\n this.#db.db.prepare(`UPDATE memories SET ${sets.join(\", \")} WHERE id = ?`).run(...values);\n\n if (content !== undefined) {\n const embedding = await this.#embedding.embed(content);\n const embeddingBlob = Buffer.from(embedding.buffer);\n this.#db.db\n .prepare(`UPDATE embeddings SET embedding = ? WHERE rowid = ?`)\n .run(embeddingBlob, existing.rowid);\n }\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n const events = this.#getEventsForMemories([id]);\n return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);\n }\n\n delete(id: string): Promise<void> {\n const row = this.#db.db\n .prepare<[string], { rowid: number }>(`SELECT rowid FROM memories WHERE id = ?`)\n .get(id);\n\n if (row !== undefined) {\n this.#db.db.prepare(`DELETE FROM embeddings WHERE rowid = ?`).run(row.rowid);\n }\n\n this.#db.db.prepare(`DELETE FROM memory_projects WHERE memory_id = ?`).run(id);\n this.#db.db.prepare(`DELETE FROM memories WHERE id = ?`).run(id);\n\n return Promise.resolve();\n }\n\n list(opts?: { type?: MemoryType; pinned?: boolean }): Memory[] {\n const conditions: string[] = [];\n const params: (string | number)[] = [];\n\n if (opts?.type !== undefined) {\n conditions.push(\"type = ?\");\n params.push(opts.type);\n }\n\n if (opts?.pinned === true) {\n conditions.push(\"pinned = 1\");\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n const rows = this.#db.db\n .prepare<(string | number)[], MemoryRow>(\n `SELECT * FROM memories ${where} ORDER BY created_at DESC`\n )\n .all(...params);\n\n if (rows.length === 0) return [];\n\n const ids = rows.map((r) => r.id);\n const projectMap = this.#projects.getProjectsForMemories(ids);\n const eventMap = this.#getEventsForMemories(ids);\n return rows.map((row) =>\n rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? [])\n );\n }\n\n listFlagged(): Memory[] {\n const rows = this.#db.db\n .prepare<[], MemoryRow>(\n `SELECT * FROM memories\n WHERE EXISTS (\n SELECT 1 FROM memory_review_events e\n WHERE e.memory_id = memories.id AND e.resolved_at IS NULL\n )\n ORDER BY created_at DESC`\n )\n .all();\n\n if (rows.length === 0) return [];\n\n const ids = rows.map((r) => r.id);\n const projectMap = this.#projects.getProjectsForMemories(ids);\n const eventMap = this.#getEventsForMemories(ids, { unresolvedOnly: true });\n return rows.map((row) =>\n rowToMemory(row, projectMap.get(row.id) ?? [], eventMap.get(row.id) ?? [])\n );\n }\n\n listReviewEvents(memoryId: string, opts?: { unresolvedOnly?: boolean }): ReviewEvent[] {\n const where =\n opts?.unresolvedOnly === true\n ? \"WHERE memory_id = ? AND resolved_at IS NULL\"\n : \"WHERE memory_id = ?\";\n\n const rows = this.#db.db\n .prepare<[string], ReviewEventRow>(\n `SELECT * FROM memory_review_events ${where} ORDER BY created_at DESC`\n )\n .all(memoryId);\n\n return rows.map((r) => rowToReviewEvent(ReviewEventRowSchema.parse(r)));\n }\n\n resolveReviewEvents(memoryId: string): void {\n const now = new Date().toISOString();\n this.#db.db\n .prepare(\n `UPDATE memory_review_events SET resolved_at = ? WHERE memory_id = ? AND resolved_at IS NULL`\n )\n .run(now, memoryId);\n }\n\n #getEventsForMemories(\n ids: string[],\n opts?: { unresolvedOnly?: boolean }\n ): Map<string, ReviewEvent[]> {\n if (ids.length === 0) return new Map();\n\n const placeholders = ids.map(() => \"?\").join(\", \");\n const unresolvedClause = opts?.unresolvedOnly === true ? \"AND resolved_at IS NULL\" : \"\";\n const rows = this.#db.db\n .prepare<string[], ReviewEventRow>(\n `SELECT * FROM memory_review_events\n WHERE memory_id IN (${placeholders}) ${unresolvedClause}\n ORDER BY created_at DESC`\n )\n .all(...ids);\n\n const map = new Map<string, ReviewEvent[]>();\n for (const row of rows) {\n const event = rowToReviewEvent(ReviewEventRowSchema.parse(row));\n const existing = map.get(event.memoryId) ?? [];\n existing.push(event);\n map.set(event.memoryId, existing);\n }\n return map;\n }\n\n stats(): { byType: Record<MemoryType, number>; total: number; needsReview: number } {\n const byType = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0])) as Record<\n MemoryType,\n number\n >;\n\n const typeRows = this.#db.db\n .prepare<[], { type: string; count: number }>(\n `SELECT type, COUNT(*) as count FROM memories GROUP BY type`\n )\n .all();\n\n for (const row of typeRows) {\n const parsed = MemoryTypeSchema.safeParse(row.type);\n if (parsed.success) {\n byType[parsed.data] = row.count;\n }\n }\n\n const totals = this.#db.db\n .prepare<[], { total: number }>(`SELECT COUNT(*) as total FROM memories`)\n .get() ?? { total: 0 };\n\n const reviewRow = this.#db.db\n .prepare<[], { needsReview: number }>(\n `SELECT COUNT(DISTINCT memory_id) as needsReview FROM memory_review_events WHERE resolved_at IS NULL`\n )\n .get() ?? { needsReview: 0 };\n\n return {\n byType,\n total: totals.total,\n needsReview: reviewRow.needsReview,\n };\n }\n\n setPin(id: string, pinned: boolean): Memory {\n const existing = this.#db.db\n .prepare<[string], MemoryRow>(`SELECT * FROM memories WHERE id = ?`)\n .get(id);\n\n if (existing === undefined) {\n throw new Error(`Memory not found: ${id}`);\n }\n\n const now = new Date().toISOString();\n this.#db.db\n .prepare(`UPDATE memories SET pinned = ?, updated_at = ? WHERE id = ?`)\n .run(pinned ? 1 : 0, now, id);\n\n const updated = MemoryRowSchema.parse(\n this.#db.db.prepare<[string], unknown>(`SELECT * FROM memories WHERE id = ?`).get(id)\n );\n\n const projectMap = this.#projects.getProjectsForMemories([id]);\n const events = this.#getEventsForMemories([id]);\n return rowToMemory(updated, projectMap.get(id) ?? [], events.get(id) ?? []);\n }\n\n incrementAccessCount(id: string): void {\n this.#db.db.prepare(`UPDATE memories SET access_count = access_count + 1 WHERE id = ?`).run(id);\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nfunction sha256Truncated(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\").slice(0, 16);\n}\n\nexport async function resolveProject(): Promise<{ hash: string; name: string }> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"]);\n const url = stdout.trim();\n if (url) {\n const hash = sha256Truncated(url);\n // parse last path segment, strip .git suffix\n const name =\n url\n .split(\"/\")\n .pop()\n ?.replace(/\\.git$/, \"\") ?? hash.slice(0, 8);\n return { hash, name };\n }\n } catch {\n // fall through\n }\n\n const cwd = process.cwd();\n const hash = sha256Truncated(cwd);\n const name = cwd.split(/[/\\\\]/).filter(Boolean).pop() ?? hash.slice(0, 8);\n return { hash, name };\n}\n\nexport async function resolveScope(): Promise<string> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"]);\n const url = stdout.trim();\n if (url) {\n return sha256Truncated(url);\n }\n } catch {\n // git not available, not a repo, or no remote — fall through to cwd fallback\n }\n\n return sha256Truncated(process.cwd());\n}\n","import type { ProjectRepository } from \"../project/index.js\";\nimport { resolveProject } from \"../scope/index.js\";\n\nexport interface MigrationMeta {\n name: string;\n description: string;\n}\n\nexport interface ScopeToProjectsResult {\n migration: \"scope-to-projects\";\n oldName: string;\n newName: string;\n memoryCount: number;\n}\n\nexport const MIGRATIONS: MigrationMeta[] = [\n {\n name: \"scope-to-projects\",\n description:\n \"Rename the auto-migrated project for the current directory from its generic hash-derived name to the resolved repo/directory name.\",\n },\n];\n\nexport async function runScopeToProjectsMigration(\n projects: ProjectRepository\n): Promise<ScopeToProjectsResult | null> {\n const resolved = await resolveProject();\n const project = projects.getByHash(resolved.hash);\n\n if (project === undefined) {\n return null;\n }\n\n const oldName = project.name;\n const memoryCount = projects.countMemories(project.id);\n projects.rename(project.id, resolved.name);\n\n return {\n migration: \"scope-to-projects\",\n oldName,\n newName: resolved.name,\n memoryCount,\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToProject } from \"../db/row-types.js\";\nimport { ProjectRowSchema } from \"../schemas.js\";\nimport type { Project, ProjectRow } from \"../types.js\";\n\ninterface ProjectMemoryRow extends ProjectRow {\n memory_id: string;\n}\n\nexport class ProjectRepository {\n readonly #db: DatabaseManager;\n\n constructor(db: DatabaseManager) {\n this.#db = db;\n }\n\n upsertByHash(hash: string, name: string): Project {\n const now = new Date().toISOString();\n const id = randomUUID();\n this.#db.db\n .prepare(\n `INSERT OR IGNORE INTO projects (id, name, scope_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`\n )\n .run(id, name, hash, now, now);\n\n const row = ProjectRowSchema.parse(\n this.#db.db\n .prepare<[string], unknown>(`SELECT * FROM projects WHERE scope_hash = ?`)\n .get(hash)\n );\n\n return rowToProject(row);\n }\n\n rename(id: string, name: string): Project {\n const now = new Date().toISOString();\n this.#db.db\n .prepare(`UPDATE projects SET name = ?, updated_at = ? WHERE id = ?`)\n .run(name, now, id);\n\n const row = this.#db.db\n .prepare<[string], ProjectRow>(`SELECT * FROM projects WHERE id = ?`)\n .get(id);\n\n if (row === undefined) throw new Error(`Project not found: ${id}`);\n return rowToProject(row);\n }\n\n list(): Project[] {\n return this.#db.db\n .prepare<[], ProjectRow>(`SELECT * FROM projects ORDER BY name ASC`)\n .all()\n .map(rowToProject);\n }\n\n getByHash(hash: string): Project | undefined {\n const row = this.#db.db\n .prepare<[string], ProjectRow>(`SELECT * FROM projects WHERE scope_hash = ?`)\n .get(hash);\n return row !== undefined ? rowToProject(row) : undefined;\n }\n\n addAssociation(memoryId: string, projectId: string): void {\n this.#db.db\n .prepare(`INSERT OR IGNORE INTO memory_projects (memory_id, project_id) VALUES (?, ?)`)\n .run(memoryId, projectId);\n }\n\n removeAssociation(memoryId: string, projectId: string): void {\n this.#db.db\n .prepare(`DELETE FROM memory_projects WHERE memory_id = ? AND project_id = ?`)\n .run(memoryId, projectId);\n }\n\n countMemories(projectId: string): number {\n const row = this.#db.db\n .prepare<[string], { count: number }>(\n `SELECT COUNT(*) AS count FROM memory_projects WHERE project_id = ?`\n )\n .get(projectId);\n return row?.count ?? 0;\n }\n\n getProjectsForMemories(memoryIds: string[]): Map<string, Project[]> {\n if (memoryIds.length === 0) return new Map();\n const placeholders = memoryIds.map(() => \"?\").join(\",\");\n const rows = this.#db.db\n .prepare<string[], ProjectMemoryRow>(\n `SELECT p.*, mp.memory_id FROM projects p\n JOIN memory_projects mp ON mp.project_id = p.id\n WHERE mp.memory_id IN (${placeholders})`\n )\n .all(...memoryIds);\n\n const result = new Map<string, Project[]>();\n for (const row of rows) {\n const list = result.get(row.memory_id) ?? [];\n list.push(rowToProject(row));\n result.set(row.memory_id, list);\n }\n return result;\n }\n}\n","import type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory } from \"../db/row-types.js\";\nimport type { EmbeddingService } from \"../embedding/service.js\";\nimport type { MemoryRepository } from \"../memory/repository.js\";\nimport { QueryOptionsSchema } from \"../schemas.js\";\nimport type { Memory, MemoryRow, MemoryType, QueryOptions } from \"../types.js\";\n\ninterface QueryMemoryRow extends MemoryRow {\n cosine_sim: number;\n}\n\nconst TYPE_WEIGHTS = {\n correction: 1.0,\n preference: 0.8,\n decision: 0.6,\n learning: 0.4,\n fact: 0.2,\n} satisfies Record<MemoryType, number>;\n\nexport class QueryEngine {\n readonly #db: DatabaseManager;\n readonly #embedding: EmbeddingService;\n readonly #repo: MemoryRepository;\n\n constructor(db: DatabaseManager, embeddingService: EmbeddingService, repo: MemoryRepository) {\n this.#db = db;\n this.#embedding = embeddingService;\n this.#repo = repo;\n }\n\n async query(options: QueryOptions): Promise<Array<Memory & { score: number }>> {\n const {\n query,\n type,\n projectHash,\n limit = 10,\n includePinned,\n } = QueryOptionsSchema.parse(options);\n\n const queryEmbedding = await this.#embedding.embed(query);\n const queryBlob = Buffer.from(queryEmbedding.buffer);\n\n const whereClauses: string[] = [];\n const params: unknown[] = [queryBlob];\n let joinClause = \"\";\n\n if (!includePinned) {\n whereClauses.push(\"m.pinned = 0\");\n }\n\n if (type !== undefined) {\n whereClauses.push(\"m.type = ?\");\n params.push(type);\n }\n\n if (projectHash !== undefined) {\n joinClause =\n \"LEFT JOIN memory_projects mp ON mp.memory_id = m.id LEFT JOIN projects p ON p.id = mp.project_id\";\n whereClauses.push(\"p.scope_hash = ?\");\n params.push(projectHash);\n }\n\n const whereSQL = whereClauses.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\";\n\n const sql = `\n SELECT m.*, (1 - vec_distance_cosine(e.embedding, ?)) AS cosine_sim\n FROM memories m JOIN embeddings e ON e.rowid = m.rowid\n ${joinClause}\n ${whereSQL}\n `;\n\n const rows = this.#db.db.prepare<unknown[], QueryMemoryRow>(sql).all(...params);\n\n const now = Date.now();\n\n const scored = rows\n .filter((row) => row.cosine_sim > 0)\n .map((row) => {\n const memory = rowToMemory(row, []);\n const score = this.#computeScore(memory, now);\n return { ...memory, score };\n });\n\n scored.sort((a, b) => b.score - a.score);\n\n const results = scored.slice(0, limit);\n\n for (const result of results) {\n this.#repo.incrementAccessCount(result.id);\n }\n\n return results;\n }\n\n #computeScore(memory: Memory, now: number): number {\n const typeWeight = TYPE_WEIGHTS[memory.type];\n const accessCountNorm = memory.accessCount / (memory.accessCount + 10);\n const daysSinceUpdate = (now - new Date(memory.updatedAt).getTime()) / 86400000;\n const recencyNorm = 1 / (1 + daysSinceUpdate);\n const pinned = memory.pinned ? 1.0 : 0.0;\n\n return typeWeight * 0.4 + accessCountNorm * 0.3 + recencyNorm * 0.2 + pinned * 0.1;\n }\n}\n","import type { DatabaseManager } from \"../db/manager.js\";\nimport { rowToMemory } from \"../db/row-types.js\";\nimport { MEMORY_TYPE_VALUES, MemoryTypeSchema } from \"../schemas.js\";\nimport type { MemoryRow, MemoryType, SessionContext } from \"../types.js\";\n\ninterface TypeCountRow {\n type: string;\n count: number;\n}\n\nexport function listMemoryTypes(): MemoryType[] {\n return [...MEMORY_TYPE_VALUES];\n}\n\nexport class SessionContextBuilder {\n readonly #db: DatabaseManager;\n\n constructor(db: DatabaseManager) {\n this.#db = db;\n }\n\n getSessionContext(projectHash: string): SessionContext {\n const pinnedGlobal = this.#db.db\n .prepare<[], MemoryRow>(\n `SELECT * FROM memories\n WHERE id NOT IN (SELECT memory_id FROM memory_projects)\n AND pinned = 1`\n )\n .all()\n .map((row) => rowToMemory(row, []));\n\n const pinnedProject = this.#db.db\n .prepare<[string], MemoryRow>(\n `SELECT m.* FROM memories m\n JOIN memory_projects mp ON mp.memory_id = m.id\n JOIN projects p ON p.id = mp.project_id\n WHERE p.scope_hash = ? AND m.pinned = 1`\n )\n .all(projectHash)\n .map((row) => rowToMemory(row, []));\n\n const typeCounts = this.#db.db\n .prepare<[], TypeCountRow>(\"SELECT type, COUNT(*) as count FROM memories GROUP BY type\")\n .all();\n\n const stats = Object.fromEntries(MEMORY_TYPE_VALUES.map((t) => [t, 0])) as Record<\n MemoryType,\n number\n >;\n for (const row of typeCounts) {\n const parsed = MemoryTypeSchema.safeParse(row.type);\n if (parsed.success) {\n stats[parsed.data] = row.count;\n }\n }\n\n return { stats, pinnedGlobal, pinnedProject };\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@membank/core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",