claude-memory-layer 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.claude/settings.local.json +14 -0
  2. package/.history/package_20260201114632.json +46 -0
  3. package/dist/cli/index.js +360 -154
  4. package/dist/cli/index.js.map +4 -4
  5. package/dist/core/index.js +337 -161
  6. package/dist/core/index.js.map +3 -3
  7. package/dist/hooks/session-end.js +320 -130
  8. package/dist/hooks/session-end.js.map +4 -4
  9. package/dist/hooks/session-start.js +331 -138
  10. package/dist/hooks/session-start.js.map +4 -4
  11. package/dist/hooks/stop.js +320 -130
  12. package/dist/hooks/stop.js.map +4 -4
  13. package/dist/hooks/user-prompt-submit.js +320 -130
  14. package/dist/hooks/user-prompt-submit.js.map +4 -4
  15. package/dist/services/memory-service.js +349 -128
  16. package/dist/services/memory-service.js.map +4 -4
  17. package/package.json +2 -1
  18. package/src/cli/index.ts +84 -23
  19. package/src/core/consolidated-store.ts +33 -18
  20. package/src/core/continuity-manager.ts +12 -7
  21. package/src/core/db-wrapper.ts +112 -0
  22. package/src/core/edge-repo.ts +22 -13
  23. package/src/core/entity-repo.ts +23 -14
  24. package/src/core/event-store.ts +98 -72
  25. package/src/core/task/blocker-resolver.ts +17 -9
  26. package/src/core/task/task-matcher.ts +8 -6
  27. package/src/core/task/task-projector.ts +29 -16
  28. package/src/core/task/task-resolver.ts +17 -9
  29. package/src/core/vector-outbox.ts +29 -16
  30. package/src/core/vector-store.ts +23 -12
  31. package/src/core/vector-worker.ts +7 -4
  32. package/src/core/working-set-store.ts +31 -18
  33. package/src/hooks/session-end.ts +3 -2
  34. package/src/hooks/session-start.ts +12 -8
  35. package/src/hooks/stop.ts +3 -2
  36. package/src/hooks/user-prompt-submit.ts +3 -2
  37. package/src/services/memory-service.ts +158 -6
@@ -13,7 +13,6 @@ import * as fs from "fs";
13
13
  import * as crypto2 from "crypto";
14
14
 
15
15
  // src/core/event-store.ts
16
- import { Database } from "duckdb";
17
16
  import { randomUUID } from "crypto";
18
17
 
19
18
  // src/core/canonical-key.ts
@@ -39,11 +38,92 @@ function makeDedupeKey(content, sessionId) {
39
38
  return `${sessionId}:${contentHash}`;
40
39
  }
41
40
 
41
+ // src/core/db-wrapper.ts
42
+ import duckdb from "duckdb";
43
+ function convertBigInts(obj) {
44
+ if (obj === null || obj === void 0)
45
+ return obj;
46
+ if (typeof obj === "bigint")
47
+ return Number(obj);
48
+ if (obj instanceof Date)
49
+ return obj;
50
+ if (Array.isArray(obj))
51
+ return obj.map(convertBigInts);
52
+ if (typeof obj === "object") {
53
+ const result = {};
54
+ for (const [key, value] of Object.entries(obj)) {
55
+ result[key] = convertBigInts(value);
56
+ }
57
+ return result;
58
+ }
59
+ return obj;
60
+ }
61
+ function toDate(value) {
62
+ if (value instanceof Date)
63
+ return value;
64
+ if (typeof value === "string")
65
+ return new Date(value);
66
+ if (typeof value === "number")
67
+ return new Date(value);
68
+ return new Date(String(value));
69
+ }
70
+ function createDatabase(path2) {
71
+ return new duckdb.Database(path2);
72
+ }
73
+ function dbRun(db, sql, params = []) {
74
+ return new Promise((resolve2, reject) => {
75
+ if (params.length === 0) {
76
+ db.run(sql, (err) => {
77
+ if (err)
78
+ reject(err);
79
+ else
80
+ resolve2();
81
+ });
82
+ } else {
83
+ db.run(sql, ...params, (err) => {
84
+ if (err)
85
+ reject(err);
86
+ else
87
+ resolve2();
88
+ });
89
+ }
90
+ });
91
+ }
92
+ function dbAll(db, sql, params = []) {
93
+ return new Promise((resolve2, reject) => {
94
+ if (params.length === 0) {
95
+ db.all(sql, (err, rows) => {
96
+ if (err)
97
+ reject(err);
98
+ else
99
+ resolve2(convertBigInts(rows || []));
100
+ });
101
+ } else {
102
+ db.all(sql, ...params, (err, rows) => {
103
+ if (err)
104
+ reject(err);
105
+ else
106
+ resolve2(convertBigInts(rows || []));
107
+ });
108
+ }
109
+ });
110
+ }
111
+ function dbClose(db) {
112
+ return new Promise((resolve2, reject) => {
113
+ db.close((err) => {
114
+ if (err)
115
+ reject(err);
116
+ else
117
+ resolve2();
118
+ });
119
+ });
120
+ }
121
+
42
122
  // src/core/event-store.ts
43
123
  var EventStore = class {
44
124
  constructor(dbPath) {
45
125
  this.dbPath = dbPath;
46
- this.db = new Database(dbPath);
126
+ this.db = createDatabase(dbPath);
47
127
  }
48
128
  db;
49
129
  initialized = false;
@@ -53,7 +133,7 @@ var EventStore = class {
53
133
  async initialize() {
54
134
  if (this.initialized)
55
135
  return;
56
- await this.db.run(`
136
+ await dbRun(this.db, `
57
137
  CREATE TABLE IF NOT EXISTS events (
58
138
  id VARCHAR PRIMARY KEY,
59
139
  event_type VARCHAR NOT NULL,
@@ -65,14 +145,14 @@ var EventStore = class {
65
145
  metadata JSON
66
146
  )
67
147
  `);
68
- await this.db.run(`
148
+ await dbRun(this.db, `
69
149
  CREATE TABLE IF NOT EXISTS event_dedup (
70
150
  dedupe_key VARCHAR PRIMARY KEY,
71
151
  event_id VARCHAR NOT NULL,
72
152
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
73
153
  )
74
154
  `);
75
- await this.db.run(`
155
+ await dbRun(this.db, `
76
156
  CREATE TABLE IF NOT EXISTS sessions (
77
157
  id VARCHAR PRIMARY KEY,
78
158
  started_at TIMESTAMP NOT NULL,
@@ -82,7 +162,7 @@ var EventStore = class {
82
162
  tags JSON
83
163
  )
84
164
  `);
85
- await this.db.run(`
165
+ await dbRun(this.db, `
86
166
  CREATE TABLE IF NOT EXISTS insights (
87
167
  id VARCHAR PRIMARY KEY,
88
168
  insight_type VARCHAR NOT NULL,
@@ -94,7 +174,7 @@ var EventStore = class {
94
174
  last_updated TIMESTAMP
95
175
  )
96
176
  `);
97
- await this.db.run(`
177
+ await dbRun(this.db, `
98
178
  CREATE TABLE IF NOT EXISTS embedding_outbox (
99
179
  id VARCHAR PRIMARY KEY,
100
180
  event_id VARCHAR NOT NULL,
@@ -106,7 +186,7 @@ var EventStore = class {
106
186
  error_message TEXT
107
187
  )
108
188
  `);
109
- await this.db.run(`
189
+ await dbRun(this.db, `
110
190
  CREATE TABLE IF NOT EXISTS projection_offsets (
111
191
  projection_name VARCHAR PRIMARY KEY,
112
192
  last_event_id VARCHAR,
@@ -114,14 +194,14 @@ var EventStore = class {
114
194
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
115
195
  )
116
196
  `);
117
- await this.db.run(`
197
+ await dbRun(this.db, `
118
198
  CREATE TABLE IF NOT EXISTS memory_levels (
119
199
  event_id VARCHAR PRIMARY KEY,
120
200
  level VARCHAR NOT NULL DEFAULT 'L0',
121
201
  promoted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
122
202
  )
123
203
  `);
124
- await this.db.run(`
204
+ await dbRun(this.db, `
125
205
  CREATE TABLE IF NOT EXISTS entries (
126
206
  entry_id VARCHAR PRIMARY KEY,
127
207
  created_ts TIMESTAMP NOT NULL,
@@ -137,7 +217,7 @@ var EventStore = class {
137
217
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
138
218
  )
139
219
  `);
140
- await this.db.run(`
220
+ await dbRun(this.db, `
141
221
  CREATE TABLE IF NOT EXISTS entities (
142
222
  entity_id VARCHAR PRIMARY KEY,
143
223
  entity_type VARCHAR NOT NULL,
@@ -152,7 +232,7 @@ var EventStore = class {
152
232
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
153
233
  )
154
234
  `);
155
- await this.db.run(`
235
+ await dbRun(this.db, `
156
236
  CREATE TABLE IF NOT EXISTS entity_aliases (
157
237
  entity_type VARCHAR NOT NULL,
158
238
  canonical_key VARCHAR NOT NULL,
@@ -162,7 +242,7 @@ var EventStore = class {
162
242
  PRIMARY KEY(entity_type, canonical_key)
163
243
  )
164
244
  `);
165
- await this.db.run(`
245
+ await dbRun(this.db, `
166
246
  CREATE TABLE IF NOT EXISTS edges (
167
247
  edge_id VARCHAR PRIMARY KEY,
168
248
  src_type VARCHAR NOT NULL,
@@ -174,7 +254,7 @@ var EventStore = class {
174
254
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
175
255
  )
176
256
  `);
177
- await this.db.run(`
257
+ await dbRun(this.db, `
178
258
  CREATE TABLE IF NOT EXISTS vector_outbox (
179
259
  job_id VARCHAR PRIMARY KEY,
180
260
  item_kind VARCHAR NOT NULL,
@@ -188,7 +268,7 @@ var EventStore = class {
188
268
  UNIQUE(item_kind, item_id, embedding_version)
189
269
  )
190
270
  `);
191
- await this.db.run(`
271
+ await dbRun(this.db, `
192
272
  CREATE TABLE IF NOT EXISTS build_runs (
193
273
  build_id VARCHAR PRIMARY KEY,
194
274
  started_at TIMESTAMP NOT NULL,
@@ -203,7 +283,7 @@ var EventStore = class {
203
283
  error VARCHAR
204
284
  )
205
285
  `);
206
- await this.db.run(`
286
+ await dbRun(this.db, `
207
287
  CREATE TABLE IF NOT EXISTS pipeline_metrics (
208
288
  id VARCHAR PRIMARY KEY,
209
289
  ts TIMESTAMP NOT NULL,
@@ -214,7 +294,7 @@ var EventStore = class {
214
294
  session_id VARCHAR
215
295
  )
216
296
  `);
217
- await this.db.run(`
297
+ await dbRun(this.db, `
218
298
  CREATE TABLE IF NOT EXISTS working_set (
219
299
  id VARCHAR PRIMARY KEY,
220
300
  event_id VARCHAR NOT NULL,
@@ -224,7 +304,7 @@ var EventStore = class {
224
304
  expires_at TIMESTAMP
225
305
  )
226
306
  `);
227
- await this.db.run(`
307
+ await dbRun(this.db, `
228
308
  CREATE TABLE IF NOT EXISTS consolidated_memories (
229
309
  memory_id VARCHAR PRIMARY KEY,
230
310
  summary TEXT NOT NULL,
@@ -236,7 +316,7 @@ var EventStore = class {
236
316
  access_count INTEGER DEFAULT 0
237
317
  )
238
318
  `);
239
- await this.db.run(`
319
+ await dbRun(this.db, `
240
320
  CREATE TABLE IF NOT EXISTS continuity_log (
241
321
  log_id VARCHAR PRIMARY KEY,
242
322
  from_context_id VARCHAR,
@@ -246,26 +326,26 @@ var EventStore = class {
246
326
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
247
327
  )
248
328
  `);
249
- await this.db.run(`
329
+ await dbRun(this.db, `
250
330
  CREATE TABLE IF NOT EXISTS endless_config (
251
331
  key VARCHAR PRIMARY KEY,
252
332
  value JSON,
253
333
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
254
334
  )
255
335
  `);
256
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type)`);
257
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage)`);
258
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key)`);
259
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key)`);
260
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status)`);
261
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type)`);
262
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type)`);
263
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type)`);
264
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status)`);
265
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at)`);
266
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score DESC)`);
267
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence DESC)`);
268
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at)`);
336
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type)`);
337
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage)`);
338
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key)`);
339
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key)`);
340
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status)`);
341
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type)`);
342
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type)`);
343
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type)`);
344
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status)`);
345
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at)`);
346
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score DESC)`);
347
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence DESC)`);
348
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at)`);
269
349
  this.initialized = true;
270
350
  }
271
351
  /**
@@ -276,7 +356,8 @@ var EventStore = class {
276
356
  await this.initialize();
277
357
  const canonicalKey = makeCanonicalKey(input.content);
278
358
  const dedupeKey = makeDedupeKey(input.content, input.sessionId);
279
- const existing = await this.db.all(
359
+ const existing = await dbAll(
360
+ this.db,
280
361
  `SELECT event_id FROM event_dedup WHERE dedupe_key = ?`,
281
362
  [dedupeKey]
282
363
  );
@@ -290,7 +371,8 @@ var EventStore = class {
290
371
  const id = randomUUID();
291
372
  const timestamp = input.timestamp.toISOString();
292
373
  try {
293
- await this.db.run(
374
+ await dbRun(
375
+ this.db,
294
376
  `INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata)
295
377
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
296
378
  [
@@ -304,11 +386,13 @@ var EventStore = class {
304
386
  JSON.stringify(input.metadata || {})
305
387
  ]
306
388
  );
307
- await this.db.run(
389
+ await dbRun(
390
+ this.db,
308
391
  `INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)`,
309
392
  [dedupeKey, id]
310
393
  );
311
- await this.db.run(
394
+ await dbRun(
395
+ this.db,
312
396
  `INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')`,
313
397
  [id]
314
398
  );
@@ -325,7 +409,8 @@ var EventStore = class {
325
409
  */
326
410
  async getSessionEvents(sessionId) {
327
411
  await this.initialize();
328
- const rows = await this.db.all(
412
+ const rows = await dbAll(
413
+ this.db,
329
414
  `SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
330
415
  [sessionId]
331
416
  );
@@ -336,7 +421,8 @@ var EventStore = class {
336
421
  */
337
422
  async getRecentEvents(limit = 100) {
338
423
  await this.initialize();
339
- const rows = await this.db.all(
424
+ const rows = await dbAll(
425
+ this.db,
340
426
  `SELECT * FROM events ORDER BY timestamp DESC LIMIT ?`,
341
427
  [limit]
342
428
  );
@@ -347,7 +433,8 @@ var EventStore = class {
347
433
  */
348
434
  async getEvent(id) {
349
435
  await this.initialize();
350
- const rows = await this.db.all(
436
+ const rows = await dbAll(
437
+ this.db,
351
438
  `SELECT * FROM events WHERE id = ?`,
352
439
  [id]
353
440
  );
@@ -360,12 +447,14 @@ var EventStore = class {
360
447
  */
361
448
  async upsertSession(session) {
362
449
  await this.initialize();
363
- const existing = await this.db.all(
450
+ const existing = await dbAll(
451
+ this.db,
364
452
  `SELECT id FROM sessions WHERE id = ?`,
365
453
  [session.id]
366
454
  );
367
455
  if (existing.length === 0) {
368
- await this.db.run(
456
+ await dbRun(
457
+ this.db,
369
458
  `INSERT INTO sessions (id, started_at, project_path, tags)
370
459
  VALUES (?, ?, ?, ?)`,
371
460
  [
@@ -392,7 +481,8 @@ var EventStore = class {
392
481
  }
393
482
  if (updates.length > 0) {
394
483
  values.push(session.id);
395
- await this.db.run(
484
+ await dbRun(
485
+ this.db,
396
486
  `UPDATE sessions SET ${updates.join(", ")} WHERE id = ?`,
397
487
  values
398
488
  );
@@ -404,7 +494,8 @@ var EventStore = class {
404
494
  */
405
495
  async getSession(id) {
406
496
  await this.initialize();
407
- const rows = await this.db.all(
497
+ const rows = await dbAll(
498
+ this.db,
408
499
  `SELECT * FROM sessions WHERE id = ?`,
409
500
  [id]
410
501
  );
@@ -413,8 +504,8 @@ var EventStore = class {
413
504
  const row = rows[0];
414
505
  return {
415
506
  id: row.id,
416
- startedAt: new Date(row.started_at),
417
- endedAt: row.ended_at ? new Date(row.ended_at) : void 0,
507
+ startedAt: toDate(row.started_at),
508
+ endedAt: row.ended_at ? toDate(row.ended_at) : void 0,
418
509
  projectPath: row.project_path,
419
510
  summary: row.summary,
420
511
  tags: row.tags ? JSON.parse(row.tags) : void 0
@@ -426,7 +517,8 @@ var EventStore = class {
426
517
  async enqueueForEmbedding(eventId, content) {
427
518
  await this.initialize();
428
519
  const id = randomUUID();
429
- await this.db.run(
520
+ await dbRun(
521
+ this.db,
430
522
  `INSERT INTO embedding_outbox (id, event_id, content, status, retry_count)
431
523
  VALUES (?, ?, ?, 'pending', 0)`,
432
524
  [id, eventId, content]
@@ -438,25 +530,30 @@ var EventStore = class {
438
530
  */
439
531
  async getPendingOutboxItems(limit = 32) {
440
532
  await this.initialize();
441
- const rows = await this.db.all(
442
- `UPDATE embedding_outbox
443
- SET status = 'processing'
444
- WHERE id IN (
445
- SELECT id FROM embedding_outbox
446
- WHERE status = 'pending'
447
- ORDER BY created_at
448
- LIMIT ?
449
- )
450
- RETURNING *`,
533
+ const pending = await dbAll(
534
+ this.db,
535
+ `SELECT * FROM embedding_outbox
536
+ WHERE status = 'pending'
537
+ ORDER BY created_at
538
+ LIMIT ?`,
451
539
  [limit]
452
540
  );
453
- return rows.map((row) => ({
541
+ if (pending.length === 0)
542
+ return [];
543
+ const ids = pending.map((r) => r.id);
544
+ const placeholders = ids.map(() => "?").join(",");
545
+ await dbRun(
546
+ this.db,
547
+ `UPDATE embedding_outbox SET status = 'processing' WHERE id IN (${placeholders})`,
548
+ ids
549
+ );
550
+ return pending.map((row) => ({
454
551
  id: row.id,
455
552
  eventId: row.event_id,
456
553
  content: row.content,
457
- status: row.status,
554
+ status: "processing",
458
555
  retryCount: row.retry_count,
459
- createdAt: new Date(row.created_at),
556
+ createdAt: toDate(row.created_at),
460
557
  errorMessage: row.error_message
461
558
  }));
462
559
  }
@@ -467,7 +564,8 @@ var EventStore = class {
467
564
  if (ids.length === 0)
468
565
  return;
469
566
  const placeholders = ids.map(() => "?").join(",");
470
- await this.db.run(
567
+ await dbRun(
568
+ this.db,
471
569
  `DELETE FROM embedding_outbox WHERE id IN (${placeholders})`,
472
570
  ids
473
571
  );
@@ -479,7 +577,8 @@ var EventStore = class {
479
577
  if (ids.length === 0)
480
578
  return;
481
579
  const placeholders = ids.map(() => "?").join(",");
482
- await this.db.run(
580
+ await dbRun(
581
+ this.db,
483
582
  `UPDATE embedding_outbox
484
583
  SET status = CASE WHEN retry_count >= 3 THEN 'failed' ELSE 'pending' END,
485
584
  retry_count = retry_count + 1,
@@ -493,7 +592,8 @@ var EventStore = class {
493
592
  */
494
593
  async updateMemoryLevel(eventId, level) {
495
594
  await this.initialize();
496
- await this.db.run(
595
+ await dbRun(
596
+ this.db,
497
597
  `UPDATE memory_levels SET level = ?, promoted_at = CURRENT_TIMESTAMP WHERE event_id = ?`,
498
598
  [level, eventId]
499
599
  );
@@ -503,7 +603,8 @@ var EventStore = class {
503
603
  */
504
604
  async getLevelStats() {
505
605
  await this.initialize();
506
- const rows = await this.db.all(
606
+ const rows = await dbAll(
607
+ this.db,
507
608
  `SELECT level, COUNT(*) as count FROM memory_levels GROUP BY level`
508
609
  );
509
610
  return rows;
@@ -522,7 +623,8 @@ var EventStore = class {
522
623
  */
523
624
  async getEndlessConfig(key) {
524
625
  await this.initialize();
525
- const rows = await this.db.all(
626
+ const rows = await dbAll(
627
+ this.db,
526
628
  `SELECT value FROM endless_config WHERE key = ?`,
527
629
  [key]
528
630
  );
@@ -535,7 +637,8 @@ var EventStore = class {
535
637
  */
536
638
  async setEndlessConfig(key, value) {
537
639
  await this.initialize();
538
- await this.db.run(
640
+ await dbRun(
641
+ this.db,
539
642
  `INSERT OR REPLACE INTO endless_config (key, value, updated_at)
540
643
  VALUES (?, ?, CURRENT_TIMESTAMP)`,
541
644
  [key, JSON.stringify(value)]
@@ -546,13 +649,14 @@ var EventStore = class {
546
649
  */
547
650
  async getAllSessions() {
548
651
  await this.initialize();
549
- const rows = await this.db.all(
652
+ const rows = await dbAll(
653
+ this.db,
550
654
  `SELECT * FROM sessions ORDER BY started_at DESC`
551
655
  );
552
656
  return rows.map((row) => ({
553
657
  id: row.id,
554
- startedAt: new Date(row.started_at),
555
- endedAt: row.ended_at ? new Date(row.ended_at) : void 0,
658
+ startedAt: toDate(row.started_at),
659
+ endedAt: row.ended_at ? toDate(row.ended_at) : void 0,
556
660
  projectPath: row.project_path,
557
661
  summary: row.summary,
558
662
  tags: row.tags ? JSON.parse(row.tags) : void 0
@@ -562,7 +666,7 @@ var EventStore = class {
562
666
  * Close database connection
563
667
  */
564
668
  async close() {
565
- await this.db.close();
669
+ await dbClose(this.db);
566
670
  }
567
671
  /**
568
672
  * Convert database row to MemoryEvent
@@ -572,7 +676,7 @@ var EventStore = class {
572
676
  id: row.id,
573
677
  eventType: row.event_type,
574
678
  sessionId: row.session_id,
575
- timestamp: new Date(row.timestamp),
679
+ timestamp: toDate(row.timestamp),
576
680
  content: row.content,
577
681
  canonicalKey: row.canonical_key,
578
682
  dedupeKey: row.dedupe_key,
@@ -665,23 +769,28 @@ var VectorStore = class {
665
769
  return [];
666
770
  }
667
771
  const { limit = 5, minScore = 0.7, sessionId } = options;
668
- let query = this.table.search(queryVector).limit(limit * 2);
772
+ let query = this.table.search(queryVector).distanceType("cosine").limit(limit * 2);
669
773
  if (sessionId) {
670
774
  query = query.where(`sessionId = '${sessionId}'`);
671
775
  }
672
776
  const results = await query.toArray();
673
777
  return results.filter((r) => {
674
- const score = 1 - (r._distance || 0);
778
+ const distance = r._distance || 0;
779
+ const score = 1 - distance / 2;
675
780
  return score >= minScore;
676
- }).slice(0, limit).map((r) => ({
677
- id: r.id,
678
- eventId: r.eventId,
679
- content: r.content,
680
- score: 1 - (r._distance || 0),
681
- sessionId: r.sessionId,
682
- eventType: r.eventType,
683
- timestamp: r.timestamp
684
- }));
781
+ }).slice(0, limit).map((r) => {
782
+ const distance = r._distance || 0;
783
+ const score = 1 - distance / 2;
784
+ return {
785
+ id: r.id,
786
+ eventId: r.eventId,
787
+ content: r.content,
788
+ score,
789
+ sessionId: r.sessionId,
790
+ eventType: r.eventType,
791
+ timestamp: r.timestamp
792
+ };
793
+ });
685
794
  }
686
795
  /**
687
796
  * Delete vector by event ID
@@ -1507,7 +1616,8 @@ var WorkingSetStore = class {
1507
1616
  const expiresAt = new Date(
1508
1617
  Date.now() + this.config.workingSet.timeWindowHours * 60 * 60 * 1e3
1509
1618
  );
1510
- await this.db.run(
1619
+ await dbRun(
1620
+ this.db,
1511
1621
  `INSERT OR REPLACE INTO working_set (id, event_id, added_at, relevance_score, topics, expires_at)
1512
1622
  VALUES (?, ?, CURRENT_TIMESTAMP, ?, ?, ?)`,
1513
1623
  [
@@ -1525,7 +1635,8 @@ var WorkingSetStore = class {
1525
1635
  */
1526
1636
  async get() {
1527
1637
  await this.cleanup();
1528
- const rows = await this.db.all(
1638
+ const rows = await dbAll(
1639
+ this.db,
1529
1640
  `SELECT ws.*, e.*
1530
1641
  FROM working_set ws
1531
1642
  JOIN events e ON ws.event_id = e.id
@@ -1537,7 +1648,7 @@ var WorkingSetStore = class {
1537
1648
  id: row.id,
1538
1649
  eventType: row.event_type,
1539
1650
  sessionId: row.session_id,
1540
- timestamp: new Date(row.timestamp),
1651
+ timestamp: toDate(row.timestamp),
1541
1652
  content: row.content,
1542
1653
  canonicalKey: row.canonical_key,
1543
1654
  dedupeKey: row.dedupe_key,
@@ -1553,23 +1664,25 @@ var WorkingSetStore = class {
1553
1664
  * Get working set items (metadata only)
1554
1665
  */
1555
1666
  async getItems() {
1556
- const rows = await this.db.all(
1667
+ const rows = await dbAll(
1668
+ this.db,
1557
1669
  `SELECT * FROM working_set ORDER BY relevance_score DESC, added_at DESC`
1558
1670
  );
1559
1671
  return rows.map((row) => ({
1560
1672
  id: row.id,
1561
1673
  eventId: row.event_id,
1562
- addedAt: new Date(row.added_at),
1674
+ addedAt: toDate(row.added_at),
1563
1675
  relevanceScore: row.relevance_score,
1564
1676
  topics: row.topics ? JSON.parse(row.topics) : void 0,
1565
- expiresAt: new Date(row.expires_at)
1677
+ expiresAt: toDate(row.expires_at)
1566
1678
  }));
1567
1679
  }
1568
1680
  /**
1569
1681
  * Update relevance score for an event
1570
1682
  */
1571
1683
  async updateRelevance(eventId, score) {
1572
- await this.db.run(
1684
+ await dbRun(
1685
+ this.db,
1573
1686
  `UPDATE working_set SET relevance_score = ? WHERE event_id = ?`,
1574
1687
  [score, eventId]
1575
1688
  );
@@ -1581,7 +1694,8 @@ var WorkingSetStore = class {
1581
1694
  if (eventIds.length === 0)
1582
1695
  return;
1583
1696
  const placeholders = eventIds.map(() => "?").join(",");
1584
- await this.db.run(
1697
+ await dbRun(
1698
+ this.db,
1585
1699
  `DELETE FROM working_set WHERE event_id IN (${placeholders})`,
1586
1700
  eventIds
1587
1701
  );
@@ -1590,7 +1704,8 @@ var WorkingSetStore = class {
1590
1704
  * Get the count of items in working set
1591
1705
  */
1592
1706
  async count() {
1593
- const result = await this.db.all(
1707
+ const result = await dbAll(
1708
+ this.db,
1594
1709
  `SELECT COUNT(*) as count FROM working_set`
1595
1710
  );
1596
1711
  return result[0]?.count || 0;
@@ -1599,13 +1714,14 @@ var WorkingSetStore = class {
1599
1714
  * Clear the entire working set
1600
1715
  */
1601
1716
  async clear() {
1602
- await this.db.run(`DELETE FROM working_set`);
1717
+ await dbRun(this.db, `DELETE FROM working_set`);
1603
1718
  }
1604
1719
  /**
1605
1720
  * Check if an event is in the working set
1606
1721
  */
1607
1722
  async contains(eventId) {
1608
- const result = await this.db.all(
1723
+ const result = await dbAll(
1724
+ this.db,
1609
1725
  `SELECT COUNT(*) as count FROM working_set WHERE event_id = ?`,
1610
1726
  [eventId]
1611
1727
  );
@@ -1618,7 +1734,8 @@ var WorkingSetStore = class {
1618
1734
  const newExpiresAt = new Date(
1619
1735
  Date.now() + this.config.workingSet.timeWindowHours * 60 * 60 * 1e3
1620
1736
  );
1621
- await this.db.run(
1737
+ await dbRun(
1738
+ this.db,
1622
1739
  `UPDATE working_set SET expires_at = ? WHERE event_id = ?`,
1623
1740
  [newExpiresAt.toISOString(), eventId]
1624
1741
  );
@@ -1627,7 +1744,8 @@ var WorkingSetStore = class {
1627
1744
  * Clean up expired items
1628
1745
  */
1629
1746
  async cleanup() {
1630
- await this.db.run(
1747
+ await dbRun(
1748
+ this.db,
1631
1749
  `DELETE FROM working_set WHERE expires_at < datetime('now')`
1632
1750
  );
1633
1751
  }
@@ -1637,7 +1755,8 @@ var WorkingSetStore = class {
1637
1755
  */
1638
1756
  async enforceLimit() {
1639
1757
  const maxEvents = this.config.workingSet.maxEvents;
1640
- const keepIds = await this.db.all(
1758
+ const keepIds = await dbAll(
1759
+ this.db,
1641
1760
  `SELECT id FROM working_set
1642
1761
  ORDER BY relevance_score DESC, added_at DESC
1643
1762
  LIMIT ?`,
@@ -1647,7 +1766,8 @@ var WorkingSetStore = class {
1647
1766
  return;
1648
1767
  const keepIdList = keepIds.map((r) => r.id);
1649
1768
  const placeholders = keepIdList.map(() => "?").join(",");
1650
- await this.db.run(
1769
+ await dbRun(
1770
+ this.db,
1651
1771
  `DELETE FROM working_set WHERE id NOT IN (${placeholders})`,
1652
1772
  keepIdList
1653
1773
  );
@@ -1656,7 +1776,8 @@ var WorkingSetStore = class {
1656
1776
  * Calculate continuity score based on recent context transitions
1657
1777
  */
1658
1778
  async calculateContinuityScore() {
1659
- const result = await this.db.all(
1779
+ const result = await dbAll(
1780
+ this.db,
1660
1781
  `SELECT AVG(continuity_score) as avg_score
1661
1782
  FROM continuity_log
1662
1783
  WHERE created_at > datetime('now', '-1 hour')`
@@ -1667,7 +1788,8 @@ var WorkingSetStore = class {
1667
1788
  * Get topics from current working set for context matching
1668
1789
  */
1669
1790
  async getActiveTopics() {
1670
- const rows = await this.db.all(
1791
+ const rows = await dbAll(
1792
+ this.db,
1671
1793
  `SELECT topics FROM working_set WHERE topics IS NOT NULL`
1672
1794
  );
1673
1795
  const allTopics = /* @__PURE__ */ new Set();
@@ -1696,7 +1818,8 @@ var ConsolidatedStore = class {
1696
1818
  */
1697
1819
  async create(input) {
1698
1820
  const memoryId = randomUUID3();
1699
- await this.db.run(
1821
+ await dbRun(
1822
+ this.db,
1700
1823
  `INSERT INTO consolidated_memories
1701
1824
  (memory_id, summary, topics, source_events, confidence, created_at)
1702
1825
  VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,
@@ -1714,7 +1837,8 @@ var ConsolidatedStore = class {
1714
1837
  * Get a consolidated memory by ID
1715
1838
  */
1716
1839
  async get(memoryId) {
1717
- const rows = await this.db.all(
1840
+ const rows = await dbAll(
1841
+ this.db,
1718
1842
  `SELECT * FROM consolidated_memories WHERE memory_id = ?`,
1719
1843
  [memoryId]
1720
1844
  );
@@ -1727,7 +1851,8 @@ var ConsolidatedStore = class {
1727
1851
  */
1728
1852
  async search(query, options) {
1729
1853
  const topK = options?.topK || 5;
1730
- const rows = await this.db.all(
1854
+ const rows = await dbAll(
1855
+ this.db,
1731
1856
  `SELECT * FROM consolidated_memories
1732
1857
  WHERE summary LIKE ?
1733
1858
  ORDER BY confidence DESC
@@ -1743,7 +1868,8 @@ var ConsolidatedStore = class {
1743
1868
  const topK = options?.topK || 5;
1744
1869
  const topicConditions = topics.map(() => `topics LIKE ?`).join(" OR ");
1745
1870
  const topicParams = topics.map((t) => `%"${t}"%`);
1746
- const rows = await this.db.all(
1871
+ const rows = await dbAll(
1872
+ this.db,
1747
1873
  `SELECT * FROM consolidated_memories
1748
1874
  WHERE ${topicConditions}
1749
1875
  ORDER BY confidence DESC
@@ -1757,7 +1883,8 @@ var ConsolidatedStore = class {
1757
1883
  */
1758
1884
  async getAll(options) {
1759
1885
  const limit = options?.limit || 100;
1760
- const rows = await this.db.all(
1886
+ const rows = await dbAll(
1887
+ this.db,
1761
1888
  `SELECT * FROM consolidated_memories
1762
1889
  ORDER BY confidence DESC, created_at DESC
1763
1890
  LIMIT ?`,
@@ -1771,7 +1898,8 @@ var ConsolidatedStore = class {
1771
1898
  async getRecent(options) {
1772
1899
  const limit = options?.limit || 10;
1773
1900
  const hours = options?.hours || 24;
1774
- const rows = await this.db.all(
1901
+ const rows = await dbAll(
1902
+ this.db,
1775
1903
  `SELECT * FROM consolidated_memories
1776
1904
  WHERE created_at > datetime('now', '-${hours} hours')
1777
1905
  ORDER BY created_at DESC
@@ -1784,7 +1912,8 @@ var ConsolidatedStore = class {
1784
1912
  * Mark a memory as accessed (tracks usage for importance scoring)
1785
1913
  */
1786
1914
  async markAccessed(memoryId) {
1787
- await this.db.run(
1915
+ await dbRun(
1916
+ this.db,
1788
1917
  `UPDATE consolidated_memories
1789
1918
  SET accessed_at = CURRENT_TIMESTAMP,
1790
1919
  access_count = access_count + 1
@@ -1796,7 +1925,8 @@ var ConsolidatedStore = class {
1796
1925
  * Update confidence score for a memory
1797
1926
  */
1798
1927
  async updateConfidence(memoryId, confidence) {
1799
- await this.db.run(
1928
+ await dbRun(
1929
+ this.db,
1800
1930
  `UPDATE consolidated_memories
1801
1931
  SET confidence = ?
1802
1932
  WHERE memory_id = ?`,
@@ -1807,7 +1937,8 @@ var ConsolidatedStore = class {
1807
1937
  * Delete a consolidated memory
1808
1938
  */
1809
1939
  async delete(memoryId) {
1810
- await this.db.run(
1940
+ await dbRun(
1941
+ this.db,
1811
1942
  `DELETE FROM consolidated_memories WHERE memory_id = ?`,
1812
1943
  [memoryId]
1813
1944
  );
@@ -1816,7 +1947,8 @@ var ConsolidatedStore = class {
1816
1947
  * Get count of consolidated memories
1817
1948
  */
1818
1949
  async count() {
1819
- const result = await this.db.all(
1950
+ const result = await dbAll(
1951
+ this.db,
1820
1952
  `SELECT COUNT(*) as count FROM consolidated_memories`
1821
1953
  );
1822
1954
  return result[0]?.count || 0;
@@ -1825,7 +1957,8 @@ var ConsolidatedStore = class {
1825
1957
  * Get most accessed memories (for importance scoring)
1826
1958
  */
1827
1959
  async getMostAccessed(limit = 10) {
1828
- const rows = await this.db.all(
1960
+ const rows = await dbAll(
1961
+ this.db,
1829
1962
  `SELECT * FROM consolidated_memories
1830
1963
  WHERE access_count > 0
1831
1964
  ORDER BY access_count DESC
@@ -1839,11 +1972,13 @@ var ConsolidatedStore = class {
1839
1972
  */
1840
1973
  async getStats() {
1841
1974
  const total = await this.count();
1842
- const avgResult = await this.db.all(
1975
+ const avgResult = await dbAll(
1976
+ this.db,
1843
1977
  `SELECT AVG(confidence) as avg FROM consolidated_memories`
1844
1978
  );
1845
1979
  const averageConfidence = avgResult[0]?.avg || 0;
1846
- const recentResult = await this.db.all(
1980
+ const recentResult = await dbAll(
1981
+ this.db,
1847
1982
  `SELECT COUNT(*) as count FROM consolidated_memories
1848
1983
  WHERE created_at > datetime('now', '-24 hours')`
1849
1984
  );
@@ -1867,7 +2002,8 @@ var ConsolidatedStore = class {
1867
2002
  */
1868
2003
  async isAlreadyConsolidated(eventIds) {
1869
2004
  for (const eventId of eventIds) {
1870
- const result = await this.db.all(
2005
+ const result = await dbAll(
2006
+ this.db,
1871
2007
  `SELECT COUNT(*) as count FROM consolidated_memories
1872
2008
  WHERE source_events LIKE ?`,
1873
2009
  [`%"${eventId}"%`]
@@ -1881,7 +2017,8 @@ var ConsolidatedStore = class {
1881
2017
  * Get the last consolidation time
1882
2018
  */
1883
2019
  async getLastConsolidationTime() {
1884
- const result = await this.db.all(
2020
+ const result = await dbAll(
2021
+ this.db,
1885
2022
  `SELECT created_at FROM consolidated_memories
1886
2023
  ORDER BY created_at DESC
1887
2024
  LIMIT 1`
@@ -1900,8 +2037,8 @@ var ConsolidatedStore = class {
1900
2037
  topics: JSON.parse(row.topics || "[]"),
1901
2038
  sourceEvents: JSON.parse(row.source_events || "[]"),
1902
2039
  confidence: row.confidence,
1903
- createdAt: new Date(row.created_at),
1904
- accessedAt: row.accessed_at ? new Date(row.accessed_at) : void 0,
2040
+ createdAt: toDate(row.created_at),
2041
+ accessedAt: row.accessed_at ? toDate(row.accessed_at) : void 0,
1905
2042
  accessCount: row.access_count || 0
1906
2043
  };
1907
2044
  }
@@ -2267,7 +2404,8 @@ var ContinuityManager = class {
2267
2404
  * Get recent continuity logs
2268
2405
  */
2269
2406
  async getRecentLogs(limit = 10) {
2270
- const rows = await this.db.all(
2407
+ const rows = await dbAll(
2408
+ this.db,
2271
2409
  `SELECT * FROM continuity_log
2272
2410
  ORDER BY created_at DESC
2273
2411
  LIMIT ?`,
@@ -2279,14 +2417,15 @@ var ContinuityManager = class {
2279
2417
  toContextId: row.to_context_id,
2280
2418
  continuityScore: row.continuity_score,
2281
2419
  transitionType: row.transition_type,
2282
- createdAt: new Date(row.created_at)
2420
+ createdAt: toDate(row.created_at)
2283
2421
  }));
2284
2422
  }
2285
2423
  /**
2286
2424
  * Get average continuity score over time period
2287
2425
  */
2288
2426
  async getAverageScore(hours = 1) {
2289
- const result = await this.db.all(
2427
+ const result = await dbAll(
2428
+ this.db,
2290
2429
  `SELECT AVG(continuity_score) as avg_score
2291
2430
  FROM continuity_log
2292
2431
  WHERE created_at > datetime('now', '-${hours} hours')`
@@ -2297,7 +2436,8 @@ var ContinuityManager = class {
2297
2436
  * Get transition type distribution
2298
2437
  */
2299
2438
  async getTransitionStats(hours = 24) {
2300
- const rows = await this.db.all(
2439
+ const rows = await dbAll(
2440
+ this.db,
2301
2441
  `SELECT transition_type, COUNT(*) as count
2302
2442
  FROM continuity_log
2303
2443
  WHERE created_at > datetime('now', '-${hours} hours')
@@ -2317,7 +2457,8 @@ var ContinuityManager = class {
2317
2457
  * Clear old continuity logs
2318
2458
  */
2319
2459
  async cleanup(olderThanDays = 7) {
2320
- const result = await this.db.all(
2460
+ const result = await dbAll(
2461
+ this.db,
2321
2462
  `DELETE FROM continuity_log
2322
2463
  WHERE created_at < datetime('now', '-${olderThanDays} days')
2323
2464
  RETURNING COUNT(*) as changes`
@@ -2352,7 +2493,8 @@ var ContinuityManager = class {
2352
2493
  * Log a context transition
2353
2494
  */
2354
2495
  async logTransition(current, previous, score, type) {
2355
- await this.db.run(
2496
+ await dbRun(
2497
+ this.db,
2356
2498
  `INSERT INTO continuity_log
2357
2499
  (log_id, from_context_id, to_context_id, continuity_score, transition_type, created_at)
2358
2500
  VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,
@@ -2465,6 +2607,38 @@ function createContinuityManager(eventStore, config) {
2465
2607
  }
2466
2608
 
2467
2609
  // src/services/memory-service.ts
2610
+ function normalizePath(projectPath) {
2611
+ const expanded = projectPath.startsWith("~") ? path.join(os.homedir(), projectPath.slice(1)) : projectPath;
2612
+ try {
2613
+ return fs.realpathSync(expanded);
2614
+ } catch {
2615
+ return path.resolve(expanded);
2616
+ }
2617
+ }
2618
+ function hashProjectPath(projectPath) {
2619
+ const normalizedPath = normalizePath(projectPath);
2620
+ return crypto2.createHash("sha256").update(normalizedPath).digest("hex").slice(0, 8);
2621
+ }
2622
+ function getProjectStoragePath(projectPath) {
2623
+ const hash = hashProjectPath(projectPath);
2624
+ return path.join(os.homedir(), ".claude-code", "memory", "projects", hash);
2625
+ }
2626
+ var REGISTRY_PATH = path.join(os.homedir(), ".claude-code", "memory", "session-registry.json");
2627
+ function loadSessionRegistry() {
2628
+ try {
2629
+ if (fs.existsSync(REGISTRY_PATH)) {
2630
+ const data = fs.readFileSync(REGISTRY_PATH, "utf-8");
2631
+ return JSON.parse(data);
2632
+ }
2633
+ } catch (error) {
2634
+ console.error("Failed to load session registry:", error);
2635
+ }
2636
+ return { version: 1, sessions: {} };
2637
+ }
2638
+ function getSessionProject(sessionId) {
2639
+ const registry = loadSessionRegistry();
2640
+ return registry.sessions[sessionId] || null;
2641
+ }
2468
2642
  var MemoryService = class {
2469
2643
  eventStore;
2470
2644
  vectorStore;
@@ -2912,21 +3086,37 @@ var MemoryService = class {
2912
3086
  return p;
2913
3087
  }
2914
3088
  };
2915
- var defaultService = null;
3089
+ var serviceCache = /* @__PURE__ */ new Map();
3090
+ var GLOBAL_KEY = "__global__";
2916
3091
  function getDefaultMemoryService() {
2917
- if (!defaultService) {
2918
- defaultService = new MemoryService({
3092
+ if (!serviceCache.has(GLOBAL_KEY)) {
3093
+ serviceCache.set(GLOBAL_KEY, new MemoryService({
2919
3094
  storagePath: "~/.claude-code/memory"
2920
- });
3095
+ }));
3096
+ }
3097
+ return serviceCache.get(GLOBAL_KEY);
3098
+ }
3099
+ function getMemoryServiceForProject(projectPath) {
3100
+ const hash = hashProjectPath(projectPath);
3101
+ if (!serviceCache.has(hash)) {
3102
+ const storagePath = getProjectStoragePath(projectPath);
3103
+ serviceCache.set(hash, new MemoryService({ storagePath }));
3104
+ }
3105
+ return serviceCache.get(hash);
3106
+ }
3107
+ function getMemoryServiceForSession(sessionId) {
3108
+ const projectInfo = getSessionProject(sessionId);
3109
+ if (projectInfo) {
3110
+ return getMemoryServiceForProject(projectInfo.projectPath);
2921
3111
  }
2922
- return defaultService;
3112
+ return getDefaultMemoryService();
2923
3113
  }
2924
3114
 
2925
3115
  // src/hooks/session-end.ts
2926
3116
  async function main() {
2927
3117
  const inputData = await readStdin();
2928
3118
  const input = JSON.parse(inputData);
2929
- const memoryService = getDefaultMemoryService();
3119
+ const memoryService = getMemoryServiceForSession(input.session_id);
2930
3120
  try {
2931
3121
  const sessionEvents = await memoryService.getSessionHistory(input.session_id);
2932
3122
  if (sessionEvents.length > 0) {
@@ -2956,14 +3146,14 @@ function generateSummary(events) {
2956
3146
  return parts.join("\n");
2957
3147
  }
2958
3148
  function readStdin() {
2959
- return new Promise((resolve) => {
3149
+ return new Promise((resolve2) => {
2960
3150
  let data = "";
2961
3151
  process.stdin.setEncoding("utf8");
2962
3152
  process.stdin.on("data", (chunk) => {
2963
3153
  data += chunk;
2964
3154
  });
2965
3155
  process.stdin.on("end", () => {
2966
- resolve(data);
3156
+ resolve2(data);
2967
3157
  });
2968
3158
  });
2969
3159
  }