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.
- package/.claude/settings.local.json +14 -0
- package/.history/package_20260201114632.json +46 -0
- package/dist/cli/index.js +360 -154
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +337 -161
- package/dist/core/index.js.map +3 -3
- package/dist/hooks/session-end.js +320 -130
- package/dist/hooks/session-end.js.map +4 -4
- package/dist/hooks/session-start.js +331 -138
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +320 -130
- package/dist/hooks/stop.js.map +4 -4
- package/dist/hooks/user-prompt-submit.js +320 -130
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/services/memory-service.js +349 -128
- package/dist/services/memory-service.js.map +4 -4
- package/package.json +2 -1
- package/src/cli/index.ts +84 -23
- package/src/core/consolidated-store.ts +33 -18
- package/src/core/continuity-manager.ts +12 -7
- package/src/core/db-wrapper.ts +112 -0
- package/src/core/edge-repo.ts +22 -13
- package/src/core/entity-repo.ts +23 -14
- package/src/core/event-store.ts +98 -72
- package/src/core/task/blocker-resolver.ts +17 -9
- package/src/core/task/task-matcher.ts +8 -6
- package/src/core/task/task-projector.ts +29 -16
- package/src/core/task/task-resolver.ts +17 -9
- package/src/core/vector-outbox.ts +29 -16
- package/src/core/vector-store.ts +23 -12
- package/src/core/vector-worker.ts +7 -4
- package/src/core/working-set-store.ts +31 -18
- package/src/hooks/session-end.ts +3 -2
- package/src/hooks/session-start.ts +12 -8
- package/src/hooks/stop.ts +3 -2
- package/src/hooks/user-prompt-submit.ts +3 -2
- package/src/services/memory-service.ts +158 -6
package/dist/hooks/stop.js
CHANGED
|
@@ -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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
257
|
-
await this.db
|
|
258
|
-
await this.db
|
|
259
|
-
await this.db
|
|
260
|
-
await this.db
|
|
261
|
-
await this.db
|
|
262
|
-
await this.db
|
|
263
|
-
await this.db
|
|
264
|
-
await this.db
|
|
265
|
-
await this.db
|
|
266
|
-
await this.db
|
|
267
|
-
await this.db
|
|
268
|
-
await this.db
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
417
|
-
endedAt: row.ended_at ?
|
|
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
|
|
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
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
WHERE
|
|
445
|
-
|
|
446
|
-
|
|
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
|
-
|
|
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:
|
|
554
|
+
status: "processing",
|
|
458
555
|
retryCount: row.retry_count,
|
|
459
|
-
createdAt:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
555
|
-
endedAt: row.ended_at ?
|
|
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
|
|
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:
|
|
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
|
|
778
|
+
const distance = r._distance || 0;
|
|
779
|
+
const score = 1 - distance / 2;
|
|
675
780
|
return score >= minScore;
|
|
676
|
-
}).slice(0, limit).map((r) =>
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
1904
|
-
accessedAt: row.accessed_at ?
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,14 +3086,30 @@ var MemoryService = class {
|
|
|
2912
3086
|
return p;
|
|
2913
3087
|
}
|
|
2914
3088
|
};
|
|
2915
|
-
var
|
|
3089
|
+
var serviceCache = /* @__PURE__ */ new Map();
|
|
3090
|
+
var GLOBAL_KEY = "__global__";
|
|
2916
3091
|
function getDefaultMemoryService() {
|
|
2917
|
-
if (!
|
|
2918
|
-
|
|
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
|
|
3112
|
+
return getDefaultMemoryService();
|
|
2923
3113
|
}
|
|
2924
3114
|
|
|
2925
3115
|
// src/core/privacy/tag-parser.ts
|
|
@@ -3081,7 +3271,7 @@ var DEFAULT_PRIVACY_CONFIG = {
|
|
|
3081
3271
|
async function main() {
|
|
3082
3272
|
const inputData = await readStdin();
|
|
3083
3273
|
const input = JSON.parse(inputData);
|
|
3084
|
-
const memoryService =
|
|
3274
|
+
const memoryService = getMemoryServiceForSession(input.session_id);
|
|
3085
3275
|
try {
|
|
3086
3276
|
for (const message of input.messages) {
|
|
3087
3277
|
if (message.role === "assistant" && message.content) {
|
|
@@ -3108,14 +3298,14 @@ async function main() {
|
|
|
3108
3298
|
}
|
|
3109
3299
|
}
|
|
3110
3300
|
function readStdin() {
|
|
3111
|
-
return new Promise((
|
|
3301
|
+
return new Promise((resolve2) => {
|
|
3112
3302
|
let data = "";
|
|
3113
3303
|
process.stdin.setEncoding("utf8");
|
|
3114
3304
|
process.stdin.on("data", (chunk) => {
|
|
3115
3305
|
data += chunk;
|
|
3116
3306
|
});
|
|
3117
3307
|
process.stdin.on("end", () => {
|
|
3118
|
-
|
|
3308
|
+
resolve2(data);
|
|
3119
3309
|
});
|
|
3120
3310
|
});
|
|
3121
3311
|
}
|