cogmem 3.7.2 → 3.7.3
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/CHANGELOG.md +6 -0
- package/MEMORY_MODEL.md +1 -1
- package/README.md +5 -4
- package/RELEASE_CHECKLIST.md +5 -5
- package/dist/belief/BeliefStore.d.ts +3 -1
- package/dist/belief/BeliefStore.js +10 -2
- package/dist/bin/episode.js +107 -16
- package/dist/bin/import-support.js +28 -11
- package/dist/config/CogmemConfig.d.ts +1 -0
- package/dist/config/CogmemConfig.js +45 -0
- package/dist/core/MemoryGraph.js +25 -8
- package/dist/dream/DreamScheduler.d.ts +6 -1
- package/dist/dream/DreamScheduler.js +36 -6
- package/dist/engine/CognitiveGraphCompiler.js +1 -1
- package/dist/engine/ConsolidationPipeline.js +4 -4
- package/dist/engine/DeepWritePromotionPolicy.d.ts +2 -0
- package/dist/engine/DeepWritePromotionPolicy.js +25 -4
- package/dist/engine/DreamCuratorWorker.d.ts +3 -0
- package/dist/engine/DreamCuratorWorker.js +18 -3
- package/dist/engine/FactCompiler.js +2 -2
- package/dist/entity/EntityGovernanceService.js +1 -1
- package/dist/episode/EpisodeActiveScopeGuard.d.ts +3 -0
- package/dist/episode/EpisodeActiveScopeGuard.js +46 -0
- package/dist/episode/EpisodeAssembler.d.ts +20 -2
- package/dist/episode/EpisodeAssembler.js +458 -98
- package/dist/episode/EpisodeBoundaryAuditService.d.ts +70 -0
- package/dist/episode/EpisodeBoundaryAuditService.js +276 -0
- package/dist/episode/EpisodeBoundaryPolicy.d.ts +75 -0
- package/dist/episode/EpisodeBoundaryPolicy.js +189 -0
- package/dist/episode/EpisodeBoundaryReplayEngine.d.ts +65 -0
- package/dist/episode/EpisodeBoundaryReplayEngine.js +272 -0
- package/dist/episode/EpisodeImportIdentity.d.ts +1 -0
- package/dist/episode/EpisodeImportIdentity.js +1 -0
- package/dist/episode/EpisodeInvariantValidator.d.ts +16 -0
- package/dist/episode/EpisodeInvariantValidator.js +99 -0
- package/dist/episode/EpisodeSplitPlanner.d.ts +89 -0
- package/dist/episode/EpisodeSplitPlanner.js +225 -0
- package/dist/episode/EpisodeStore.d.ts +67 -2
- package/dist/episode/EpisodeStore.js +443 -59
- package/dist/episode/EpisodeTypes.d.ts +2 -2
- package/dist/episode/TurnRelationClassifier.d.ts +9 -0
- package/dist/episode/TurnRelationClassifier.js +42 -12
- package/dist/episode/index.d.ts +3 -0
- package/dist/episode/index.js +3 -0
- package/dist/factory.d.ts +62 -3
- package/dist/factory.js +308 -58
- package/dist/mcp/CoreMcpTools.js +103 -8
- package/dist/migrations/0028_episode_boundary_guardrails.d.ts +3 -0
- package/dist/migrations/0028_episode_boundary_guardrails.js +47 -0
- package/dist/migrations/0029_episode_active_scope_guard.d.ts +3 -0
- package/dist/migrations/0029_episode_active_scope_guard.js +16 -0
- package/dist/migrations/0030_memory_event_local_date_source.d.ts +3 -0
- package/dist/migrations/0030_memory_event_local_date_source.js +111 -0
- package/dist/migrations/0031_episode_boundary_integrity_repair.d.ts +7 -0
- package/dist/migrations/0031_episode_boundary_integrity_repair.js +124 -0
- package/dist/migrations/SchemaMigrationRunner.d.ts +2 -0
- package/dist/migrations/SchemaMigrationRunner.js +46 -15
- package/dist/migrations/index.d.ts +6 -1
- package/dist/migrations/index.js +15 -1
- package/dist/public.d.ts +1 -1
- package/dist/public.js +1 -1
- package/dist/recall/BrainRecall.js +1 -1
- package/dist/store/DeepWriteCandidateStore.d.ts +21 -3
- package/dist/store/DeepWriteCandidateStore.js +118 -11
- package/dist/store/EntityStore.d.ts +4 -0
- package/dist/store/EntityStore.js +24 -12
- package/dist/store/EventStore.d.ts +7 -2
- package/dist/store/EventStore.js +144 -23
- package/dist/store/FactStore.js +6 -5
- package/dist/types/ExtensionPoints.d.ts +3 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/store/EventStore.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash, randomUUID } from 'crypto';
|
|
|
3
3
|
const MEMORY_EVENT_COLUMNS = `
|
|
4
4
|
event_id, global_seq, stream_id, stream_type, event_type, raw_event_type, event_version, project_id,
|
|
5
5
|
workspace_id, actor_id, causation_id, correlation_id, source_neuron_id, source_id,
|
|
6
|
-
content_hash, thread_id, session_id, local_date, thread_seq, turn_id, turn_seq,
|
|
6
|
+
content_hash, thread_id, session_id, local_date, local_date_source, thread_seq, turn_id, turn_seq,
|
|
7
7
|
event_ordinal, role, parent_event_id, prev_event_id, next_event_id, causality_type,
|
|
8
8
|
source_offset, line_start, line_end, char_start, char_end, ordering_confidence,
|
|
9
9
|
occurred_at, payload_json, payload_hash, created_at
|
|
@@ -11,9 +11,16 @@ const MEMORY_EVENT_COLUMNS = `
|
|
|
11
11
|
export class EventStore {
|
|
12
12
|
encryptionProvider;
|
|
13
13
|
db;
|
|
14
|
+
ownsDb = true;
|
|
14
15
|
constructor(dbPath = ':memory:', encryptionProvider) {
|
|
15
16
|
this.encryptionProvider = encryptionProvider;
|
|
16
|
-
|
|
17
|
+
if (dbPath instanceof Database) {
|
|
18
|
+
this.db = dbPath;
|
|
19
|
+
this.ownsDb = false;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.db = new Database(dbPath);
|
|
23
|
+
}
|
|
17
24
|
this.initializeSchema();
|
|
18
25
|
}
|
|
19
26
|
initializeSchema() {
|
|
@@ -37,6 +44,7 @@ export class EventStore {
|
|
|
37
44
|
thread_id TEXT,
|
|
38
45
|
session_id TEXT,
|
|
39
46
|
local_date TEXT,
|
|
47
|
+
local_date_source TEXT NOT NULL DEFAULT 'legacy_unknown',
|
|
40
48
|
thread_seq INTEGER,
|
|
41
49
|
turn_id TEXT,
|
|
42
50
|
turn_seq INTEGER,
|
|
@@ -115,6 +123,7 @@ export class EventStore {
|
|
|
115
123
|
addColumn('thread_id', 'thread_id TEXT');
|
|
116
124
|
addColumn('session_id', 'session_id TEXT');
|
|
117
125
|
addColumn('local_date', 'local_date TEXT');
|
|
126
|
+
addColumn('local_date_source', "local_date_source TEXT NOT NULL DEFAULT 'legacy_unknown'");
|
|
118
127
|
addColumn('thread_seq', 'thread_seq INTEGER');
|
|
119
128
|
addColumn('turn_id', 'turn_id TEXT');
|
|
120
129
|
addColumn('turn_seq', 'turn_seq INTEGER');
|
|
@@ -134,6 +143,17 @@ export class EventStore {
|
|
|
134
143
|
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_memory_events_thread_order ON memory_events(thread_id, thread_seq, event_ordinal, global_seq);`);
|
|
135
144
|
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_memory_events_parent ON memory_events(parent_event_id);`);
|
|
136
145
|
this.db.exec(`
|
|
146
|
+
CREATE TABLE IF NOT EXISTS import_source_anchors (
|
|
147
|
+
project_id TEXT NOT NULL,
|
|
148
|
+
source_id TEXT NOT NULL,
|
|
149
|
+
import_anchor TEXT NOT NULL,
|
|
150
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
151
|
+
content_hash TEXT NOT NULL,
|
|
152
|
+
created_at INTEGER NOT NULL,
|
|
153
|
+
PRIMARY KEY (project_id, source_id, import_anchor)
|
|
154
|
+
);
|
|
155
|
+
`);
|
|
156
|
+
this.db.exec(`
|
|
137
157
|
CREATE VIRTUAL TABLE IF NOT EXISTS memory_events_fts USING fts5(
|
|
138
158
|
event_id UNINDEXED,
|
|
139
159
|
text,
|
|
@@ -149,9 +169,11 @@ export class EventStore {
|
|
|
149
169
|
`);
|
|
150
170
|
this.rebuildRawEventFtsIfNeeded();
|
|
151
171
|
}
|
|
152
|
-
append(input) {
|
|
172
|
+
append(input, retry = 0) {
|
|
153
173
|
const eventVersion = input.eventVersion ?? this.getNextEventVersion(input.streamId);
|
|
154
174
|
const occurredAt = input.occurredAt ?? Date.now();
|
|
175
|
+
if (!Number.isFinite(occurredAt) || Math.abs(occurredAt) > 8_640_000_000_000_000)
|
|
176
|
+
throw new Error('invalid_event_timestamp');
|
|
155
177
|
const payloadJson = JSON.stringify(input.payload);
|
|
156
178
|
const storedPayloadJson = this.encodePayload(payloadJson);
|
|
157
179
|
const payloadHash = createHash('sha256').update(payloadJson).digest('hex');
|
|
@@ -159,6 +181,14 @@ export class EventStore {
|
|
|
159
181
|
const threadSeq = input.threadSeq ?? (threadId ? this.getNextThreadSeq(threadId) : undefined);
|
|
160
182
|
const globalSeq = this.getNextGlobalSeq();
|
|
161
183
|
const createdAt = Date.now();
|
|
184
|
+
const localDateSource = input.localDateSource ?? (input.localDate ? 'explicit' : 'generated_utc');
|
|
185
|
+
if (localDateSource !== 'explicit' && localDateSource !== 'generated_utc' && localDateSource !== 'legacy_unknown')
|
|
186
|
+
throw new Error('invalid_local_date_source');
|
|
187
|
+
if (localDateSource === 'explicit' && !input.localDate)
|
|
188
|
+
throw new Error('explicit_local_date_required');
|
|
189
|
+
const generatedUtcDate = new Date(occurredAt).toISOString().slice(0, 10);
|
|
190
|
+
if (localDateSource === 'generated_utc' && input.localDate && input.localDate !== generatedUtcDate)
|
|
191
|
+
throw new Error('generated_utc_local_date_mismatch');
|
|
162
192
|
const event = {
|
|
163
193
|
eventId: input.eventId || `evt-${randomUUID()}`,
|
|
164
194
|
globalSeq,
|
|
@@ -178,6 +208,7 @@ export class EventStore {
|
|
|
178
208
|
threadId,
|
|
179
209
|
sessionId: input.sessionId,
|
|
180
210
|
localDate: input.localDate ?? new Date(occurredAt).toISOString().slice(0, 10),
|
|
211
|
+
localDateSource,
|
|
181
212
|
threadSeq,
|
|
182
213
|
turnId: input.turnId,
|
|
183
214
|
turnSeq: input.turnSeq,
|
|
@@ -192,25 +223,80 @@ export class EventStore {
|
|
|
192
223
|
lineEnd: input.lineEnd,
|
|
193
224
|
charStart: input.charStart,
|
|
194
225
|
charEnd: input.charEnd,
|
|
195
|
-
orderingConfidence: input.orderingConfidence ?? (threadSeq || input.eventOrdinal ? 'high' : 'low'),
|
|
226
|
+
orderingConfidence: input.orderingConfidence ?? (threadSeq !== undefined || input.eventOrdinal !== undefined || input.sourceOffset !== undefined || input.lineStart !== undefined ? 'high' : 'low'),
|
|
196
227
|
occurredAt,
|
|
197
228
|
payload: input.payload,
|
|
198
229
|
payloadHash,
|
|
199
230
|
createdAt,
|
|
200
231
|
ingestedAt: createdAt
|
|
201
232
|
};
|
|
202
|
-
this.db.prepare(`
|
|
233
|
+
const insert = () => this.db.prepare(`
|
|
203
234
|
INSERT INTO memory_events (
|
|
204
235
|
event_id, global_seq, stream_id, stream_type, event_type, raw_event_type, event_version, project_id,
|
|
205
236
|
workspace_id, actor_id, causation_id, correlation_id, source_neuron_id, source_id,
|
|
206
|
-
content_hash, thread_id, session_id, local_date, thread_seq, turn_id, turn_seq,
|
|
237
|
+
content_hash, thread_id, session_id, local_date, local_date_source, thread_seq, turn_id, turn_seq,
|
|
207
238
|
event_ordinal, role, parent_event_id, prev_event_id, next_event_id, causality_type,
|
|
208
239
|
source_offset, line_start, line_end, char_start, char_end, ordering_confidence,
|
|
209
240
|
occurred_at, payload_json, payload_hash, created_at
|
|
210
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
211
|
-
`).run(event.eventId, event.globalSeq ?? null, event.streamId, event.streamType, event.eventType, event.rawEventType || null, event.eventVersion, event.projectId || null, event.workspaceId || null, event.actorId || null, event.causationId || null, event.correlationId || null, event.sourceNeuronId || null, event.sourceId || null, event.contentHash || null, event.threadId || null, event.sessionId || null, event.localDate || null, event.
|
|
212
|
-
|
|
213
|
-
|
|
241
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
242
|
+
`).run(event.eventId, event.globalSeq ?? null, event.streamId, event.streamType, event.eventType, event.rawEventType || null, event.eventVersion, event.projectId || null, event.workspaceId || null, event.actorId || null, event.causationId || null, event.correlationId || null, event.sourceNeuronId || null, event.sourceId || null, event.contentHash || null, event.threadId || null, event.sessionId || null, event.localDate || null, event.localDateSource || 'legacy_unknown', event.threadSeq ?? null, event.turnId || null, event.turnSeq ?? null, event.eventOrdinal ?? null, event.role || null, event.parentEventId || null, event.prevEventId || null, event.nextEventId || null, event.causalityType || null, event.sourceOffset ?? null, event.lineStart ?? null, event.lineEnd ?? null, event.charStart ?? null, event.charEnd ?? null, event.orderingConfidence || null, event.occurredAt, storedPayloadJson, event.payloadHash, event.createdAt);
|
|
243
|
+
try {
|
|
244
|
+
this.db.transaction(() => {
|
|
245
|
+
insert();
|
|
246
|
+
this.upsertImportAnchor(event);
|
|
247
|
+
this.upsertRawEventFts(event);
|
|
248
|
+
})();
|
|
249
|
+
return event;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
253
|
+
const streamConflict = /UNIQUE constraint failed: memory_events\.(stream_id|global_seq)/.test(message);
|
|
254
|
+
const anchorConflict = message === 'import_anchor_already_exists';
|
|
255
|
+
const autoEventVersion = input.eventVersion === undefined;
|
|
256
|
+
const autoThreadSeq = input.threadSeq === undefined;
|
|
257
|
+
if ((streamConflict || message.includes('database is locked')) && autoEventVersion && retry < 5) {
|
|
258
|
+
return this.append({ ...input, eventVersion: undefined, threadSeq: autoThreadSeq ? undefined : input.threadSeq }, retry + 1);
|
|
259
|
+
}
|
|
260
|
+
if (!anchorConflict)
|
|
261
|
+
throw error;
|
|
262
|
+
const metadata = event.payload?.metadata;
|
|
263
|
+
const anchor = typeof metadata?.importAnchor === 'string' ? metadata.importAnchor : undefined;
|
|
264
|
+
const existing = anchor && event.projectId && event.sourceId
|
|
265
|
+
? this.findImportedEventAnchor(event.projectId, event.sourceId, anchor)
|
|
266
|
+
: null;
|
|
267
|
+
if (!existing)
|
|
268
|
+
throw error;
|
|
269
|
+
if (existing.contentHash !== event.contentHash)
|
|
270
|
+
throw new Error(`import_anchor_content_conflict:${anchor}`);
|
|
271
|
+
return existing;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
upsertImportAnchor(event) {
|
|
275
|
+
const metadata = event.payload?.metadata;
|
|
276
|
+
const anchor = typeof metadata?.importAnchor === 'string' ? metadata.importAnchor : undefined;
|
|
277
|
+
if (!anchor || !event.projectId || !event.sourceId || !event.contentHash)
|
|
278
|
+
return;
|
|
279
|
+
this.db.prepare(`
|
|
280
|
+
INSERT INTO import_source_anchors (project_id, source_id, import_anchor, event_id, content_hash, created_at)
|
|
281
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
282
|
+
ON CONFLICT(project_id, source_id, import_anchor) DO NOTHING
|
|
283
|
+
`).run(event.projectId, event.sourceId, anchor, event.eventId, event.contentHash, event.createdAt);
|
|
284
|
+
const inserted = this.db.prepare(`SELECT event_id FROM import_source_anchors WHERE project_id = ? AND source_id = ? AND import_anchor = ?`)
|
|
285
|
+
.get(event.projectId, event.sourceId, anchor);
|
|
286
|
+
if (inserted?.event_id !== event.eventId) {
|
|
287
|
+
const existingEvent = inserted?.event_id
|
|
288
|
+
? this.db.prepare(`SELECT 1 FROM memory_events WHERE event_id = ?`).get(inserted.event_id)
|
|
289
|
+
: null;
|
|
290
|
+
if (!existingEvent) {
|
|
291
|
+
this.db.prepare(`
|
|
292
|
+
UPDATE import_source_anchors
|
|
293
|
+
SET event_id = ?, content_hash = ?, created_at = ?
|
|
294
|
+
WHERE project_id = ? AND source_id = ? AND import_anchor = ?
|
|
295
|
+
`).run(event.eventId, event.contentHash, event.createdAt, event.projectId, event.sourceId, anchor);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
throw new Error('import_anchor_already_exists');
|
|
299
|
+
}
|
|
214
300
|
}
|
|
215
301
|
getNextGlobalSeq() {
|
|
216
302
|
const row = this.db.prepare(`
|
|
@@ -249,9 +335,18 @@ export class EventStore {
|
|
|
249
335
|
FROM memory_events
|
|
250
336
|
WHERE (? IS NULL OR occurred_at > ?)
|
|
251
337
|
ORDER BY COALESCE(global_seq, 0) ASC, occurred_at ASC, event_id ASC
|
|
252
|
-
`).all(lastEventTime
|
|
338
|
+
`).all(lastEventTime ?? null, lastEventTime ?? null);
|
|
253
339
|
return rows.map((row) => this.mapRow(row));
|
|
254
340
|
}
|
|
341
|
+
findImportedEventAnchor(projectId, sourceId, importAnchor) {
|
|
342
|
+
const row = this.db.prepare(`
|
|
343
|
+
SELECT ${qualifiedMemoryEventColumns('e')}
|
|
344
|
+
FROM import_source_anchors a
|
|
345
|
+
JOIN memory_events e ON e.event_id = a.event_id
|
|
346
|
+
WHERE a.project_id = ? AND a.source_id = ? AND a.import_anchor = ?
|
|
347
|
+
`).get(projectId, sourceId, importAnchor);
|
|
348
|
+
return row ? this.mapRow(row) : null;
|
|
349
|
+
}
|
|
255
350
|
getLatestEvent() {
|
|
256
351
|
const row = this.db.prepare(`
|
|
257
352
|
SELECT ${MEMORY_EVENT_COLUMNS}
|
|
@@ -430,9 +525,10 @@ export class EventStore {
|
|
|
430
525
|
conditions.push('local_date = ?');
|
|
431
526
|
params.push(options.localDate);
|
|
432
527
|
}
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
528
|
+
const boundedLimit = options.limit === undefined ? undefined : Math.max(1, Math.min(Math.trunc(options.limit), 10_000));
|
|
529
|
+
const limitSql = boundedLimit === undefined ? '' : 'LIMIT ?';
|
|
530
|
+
if (boundedLimit !== undefined)
|
|
531
|
+
params.push(boundedLimit);
|
|
436
532
|
const rows = this.db.prepare(`
|
|
437
533
|
SELECT ${MEMORY_EVENT_COLUMNS}
|
|
438
534
|
FROM memory_events
|
|
@@ -564,7 +660,8 @@ export class EventStore {
|
|
|
564
660
|
`).run(checkpoint.projectionName, checkpoint.lastEventId || null, checkpoint.lastEventTime || null, checkpoint.lastRebuildAt || null, checkpoint.lastFullCount, checkpoint.lastChecksum || null, checkpoint.status, checkpoint.metadata ? JSON.stringify(checkpoint.metadata) : null);
|
|
565
661
|
}
|
|
566
662
|
close() {
|
|
567
|
-
this.
|
|
663
|
+
if (this.ownsDb)
|
|
664
|
+
this.db.close();
|
|
568
665
|
}
|
|
569
666
|
mapRow(row) {
|
|
570
667
|
return {
|
|
@@ -586,20 +683,21 @@ export class EventStore {
|
|
|
586
683
|
threadId: row.thread_id || (row.stream_type === 'thread' ? row.stream_id : undefined),
|
|
587
684
|
sessionId: row.session_id || undefined,
|
|
588
685
|
localDate: row.local_date || undefined,
|
|
589
|
-
|
|
686
|
+
localDateSource: row.local_date_source || legacyLocalDateSource(row.payload_json),
|
|
687
|
+
threadSeq: row.thread_seq ?? undefined,
|
|
590
688
|
turnId: row.turn_id || undefined,
|
|
591
|
-
turnSeq: row.turn_seq
|
|
592
|
-
eventOrdinal: row.event_ordinal
|
|
689
|
+
turnSeq: row.turn_seq ?? undefined,
|
|
690
|
+
eventOrdinal: row.event_ordinal ?? undefined,
|
|
593
691
|
role: row.role || undefined,
|
|
594
692
|
parentEventId: row.parent_event_id || undefined,
|
|
595
693
|
prevEventId: row.prev_event_id || undefined,
|
|
596
694
|
nextEventId: row.next_event_id || undefined,
|
|
597
695
|
causalityType: row.causality_type || undefined,
|
|
598
|
-
sourceOffset: row.source_offset
|
|
599
|
-
lineStart: row.line_start
|
|
600
|
-
lineEnd: row.line_end
|
|
601
|
-
charStart: row.char_start
|
|
602
|
-
charEnd: row.char_end
|
|
696
|
+
sourceOffset: row.source_offset ?? undefined,
|
|
697
|
+
lineStart: row.line_start ?? undefined,
|
|
698
|
+
lineEnd: row.line_end ?? undefined,
|
|
699
|
+
charStart: row.char_start ?? undefined,
|
|
700
|
+
charEnd: row.char_end ?? undefined,
|
|
603
701
|
orderingConfidence: row.ordering_confidence || undefined,
|
|
604
702
|
occurredAt: row.occurred_at,
|
|
605
703
|
payload: JSON.parse(this.decodePayload(row.payload_json)),
|
|
@@ -720,6 +818,29 @@ export class EventStore {
|
|
|
720
818
|
return this.encryptionProvider?.decrypt(payloadJson) ?? payloadJson;
|
|
721
819
|
}
|
|
722
820
|
}
|
|
821
|
+
function qualifiedMemoryEventColumns(alias) {
|
|
822
|
+
return MEMORY_EVENT_COLUMNS.split(',').map((column) => `${alias}.${column.trim()}`).join(', ');
|
|
823
|
+
}
|
|
723
824
|
function escapeSqlLike(value) {
|
|
724
825
|
return value.replace(/[\\%_]/g, (character) => `\\${character}`);
|
|
725
826
|
}
|
|
827
|
+
function validCalendarDate(value) {
|
|
828
|
+
if (!/^\d{4}-\d{2}-\d{2}$/u.test(value))
|
|
829
|
+
return false;
|
|
830
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
831
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
832
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
833
|
+
}
|
|
834
|
+
function legacyLocalDateSource(payloadJson) {
|
|
835
|
+
try {
|
|
836
|
+
const payload = JSON.parse(payloadJson);
|
|
837
|
+
if (payload.metadata?.localDateSource === 'event_store_utc_default')
|
|
838
|
+
return 'generated_utc';
|
|
839
|
+
if (payload.metadata?.localDateSource === 'explicit')
|
|
840
|
+
return 'explicit';
|
|
841
|
+
}
|
|
842
|
+
catch {
|
|
843
|
+
return 'legacy_unknown';
|
|
844
|
+
}
|
|
845
|
+
return 'legacy_unknown';
|
|
846
|
+
}
|
package/dist/store/FactStore.js
CHANGED
|
@@ -122,7 +122,7 @@ export class FactStore {
|
|
|
122
122
|
const rows = this.db.prepare(`
|
|
123
123
|
SELECT *
|
|
124
124
|
FROM facts
|
|
125
|
-
WHERE neuron_id IN (${placeholders})
|
|
125
|
+
WHERE neuron_id IN (${placeholders}) AND status IN ('provisional', 'provisional_enriched', 'verified')
|
|
126
126
|
ORDER BY valid_from DESC, fact_id DESC
|
|
127
127
|
LIMIT ?
|
|
128
128
|
`).all(...neuronIds, limit);
|
|
@@ -139,14 +139,15 @@ export class FactStore {
|
|
|
139
139
|
SELECT *
|
|
140
140
|
FROM facts
|
|
141
141
|
WHERE entity_id IN (${entityPlaceholders})
|
|
142
|
+
AND status IN ('provisional', 'provisional_enriched', 'verified')
|
|
142
143
|
AND predicate_family IN (${predicateFamilies.map(() => '?').join(', ')})
|
|
143
144
|
ORDER BY valid_from DESC, fact_id DESC
|
|
144
145
|
LIMIT ?
|
|
145
146
|
`).all(...entityIds, ...predicateFamilies, limit)
|
|
146
147
|
: this.db.prepare(`
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
SELECT *
|
|
149
|
+
FROM facts
|
|
150
|
+
WHERE entity_id IN (${entityPlaceholders}) AND status IN ('provisional', 'provisional_enriched', 'verified')
|
|
150
151
|
ORDER BY valid_from DESC, fact_id DESC
|
|
151
152
|
LIMIT ?
|
|
152
153
|
`).all(...entityIds, limit);
|
|
@@ -159,7 +160,7 @@ export class FactStore {
|
|
|
159
160
|
const rows = this.db.prepare(`
|
|
160
161
|
SELECT DISTINCT neuron_id
|
|
161
162
|
FROM facts
|
|
162
|
-
WHERE entity_id IN (${placeholders})
|
|
163
|
+
WHERE entity_id IN (${placeholders}) AND status IN ('provisional', 'provisional_enriched', 'verified')
|
|
163
164
|
ORDER BY valid_from DESC
|
|
164
165
|
LIMIT ?
|
|
165
166
|
`).all(...entityIds, limit);
|
|
@@ -106,9 +106,11 @@ export interface GraphEdgeRecordLike {
|
|
|
106
106
|
status?: string;
|
|
107
107
|
}
|
|
108
108
|
export interface GraphEdgeStoreLike {
|
|
109
|
+
getDatabase(): import('bun:sqlite').default;
|
|
109
110
|
list?(options?: unknown): GraphEdgeRecordLike[];
|
|
110
111
|
listActiveNeighborEdges?(entityIds: string[], edgeTypes?: string[], limit?: number): GraphEdgeRecordLike[];
|
|
111
|
-
appendEdge
|
|
112
|
+
appendEdge(input: unknown): GraphEdgeRecordLike;
|
|
113
|
+
invalidateEdge(edgeRecordId: string, metadata?: Record<string, unknown>): boolean;
|
|
112
114
|
}
|
|
113
115
|
export interface ProposalLedgerLike {
|
|
114
116
|
append?(items: unknown[]): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -277,6 +277,7 @@ export interface MemoryEvent<TPayload = Record<string, unknown>> {
|
|
|
277
277
|
threadId?: string;
|
|
278
278
|
sessionId?: string;
|
|
279
279
|
localDate?: string;
|
|
280
|
+
localDateSource?: 'explicit' | 'generated_utc' | 'legacy_unknown';
|
|
280
281
|
threadSeq?: number;
|
|
281
282
|
turnId?: string;
|
|
282
283
|
turnSeq?: number;
|