cogmem 3.7.1 → 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 +12 -0
- package/MEMORY_ATLAS.md +2 -2
- package/MEMORY_MODEL.md +1 -1
- package/README.md +6 -5
- package/RELEASE_CHECKLIST.md +5 -5
- package/dist/atlas/MemoryAtlasService.d.ts +1 -0
- package/dist/atlas/MemoryAtlasService.js +36 -4
- package/dist/atlas/MemoryAtlasTypes.d.ts +7 -0
- 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/mcp/server.js +1 -1
- 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/store/MemoryAtlasStore.d.ts +1 -0
- package/dist/store/MemoryAtlasStore.js +54 -0
- package/dist/types/ExtensionPoints.d.ts +3 -1
- package/dist/types/index.d.ts +1 -0
- package/examples/hermes-backend/AGENTS.md +1 -1
- package/examples/hermes-backend/README.md +1 -1
- package/examples/hermes-backend/SKILL.md +2 -2
- package/examples/hermes-backend/references/operations.md +2 -2
- package/examples/openclaw-backend/AGENTS.md +1 -1
- package/examples/openclaw-backend/README.md +1 -1
- package/examples/openclaw-backend/SKILL.md +2 -2
- package/examples/openclaw-backend/references/operations.md +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { normalizeEpisodeBoundaryConfig, resolveTrustedLocalDate } from './EpisodeBoundaryPolicy.js';
|
|
3
|
+
import { replayEpisodeBoundaries } from './EpisodeBoundaryReplayEngine.js';
|
|
4
|
+
import { validateEpisodeInvariants } from './EpisodeInvariantValidator.js';
|
|
5
|
+
export const EPISODE_SPLIT_PLANNER_VERSION = 'episode_split_preview.v1';
|
|
6
|
+
export class EpisodeSplitPlanner {
|
|
7
|
+
store;
|
|
8
|
+
resolveEvent;
|
|
9
|
+
liveBoundaryConfig;
|
|
10
|
+
liveConfigDiagnostics;
|
|
11
|
+
constructor(store, resolveEvent, liveBoundaryConfig = {}, liveConfigDiagnostics = []) {
|
|
12
|
+
this.store = store;
|
|
13
|
+
this.resolveEvent = resolveEvent;
|
|
14
|
+
this.liveBoundaryConfig = liveBoundaryConfig;
|
|
15
|
+
this.liveConfigDiagnostics = liveConfigDiagnostics;
|
|
16
|
+
}
|
|
17
|
+
plan(options) {
|
|
18
|
+
const episode = this.store.getEpisode(options.episodeId);
|
|
19
|
+
if (!episode || episode.projectId !== options.projectId)
|
|
20
|
+
throw new Error(`episode_project_mismatch:${options.episodeId}`);
|
|
21
|
+
const links = this.store.listEventLinks(options.episodeId);
|
|
22
|
+
const pairs = links.map((link) => ({ link, event: this.resolveEvent?.(link.eventId) || undefined }));
|
|
23
|
+
const events = pairs.map((item) => item.event).filter((event) => Boolean(event));
|
|
24
|
+
const missingRawEventIds = pairs.filter((item) => !item.event).map((item) => item.link.eventId);
|
|
25
|
+
const overrideWarnings = boundaryOverrideWarnings(options);
|
|
26
|
+
const normalized = normalizeEpisodeBoundaryConfig(configWithDefinedOverrides(this.liveBoundaryConfig, options));
|
|
27
|
+
const policy = {
|
|
28
|
+
enabled: normalized.config.enabled,
|
|
29
|
+
maxEvents: normalized.config.maxEvents,
|
|
30
|
+
maxDurationMs: normalized.config.maxDurationMs,
|
|
31
|
+
maxIdleGapMs: normalized.config.maxIdleGapMs,
|
|
32
|
+
splitOnTrustedLocalDateChange: normalized.config.splitOnTrustedLocalDateChange,
|
|
33
|
+
mode: normalized.config.mode,
|
|
34
|
+
applyToLive: normalized.config.applyToLive,
|
|
35
|
+
applyToImports: normalized.config.applyToImports,
|
|
36
|
+
policyVersion: normalized.config.policyVersion,
|
|
37
|
+
timezone: normalized.config.timezone,
|
|
38
|
+
};
|
|
39
|
+
const warnings = [...this.liveConfigDiagnostics.map((item) => item.code).filter((code) => code.startsWith('invalid_episode_boundary_')), ...overrideWarnings, ...normalized.diagnostics.map((item) => item.code)];
|
|
40
|
+
if (missingRawEventIds.length)
|
|
41
|
+
warnings.push('unresolved_raw_events');
|
|
42
|
+
if (events[0] && events[0].role !== 'user')
|
|
43
|
+
warnings.push('leading_non_user_event');
|
|
44
|
+
const userCount = events.filter((event) => event.role === 'user').length;
|
|
45
|
+
if (userCount === 0)
|
|
46
|
+
warnings.push('no_user_event_episode');
|
|
47
|
+
const replay = replayEpisodeBoundaries({ episode, pairs, config: normalized.config });
|
|
48
|
+
warnings.push(...replay.warnings, ...replay.structuralAnomalies);
|
|
49
|
+
const invariantViolations = validateEpisodeInvariants({
|
|
50
|
+
episode, pairs, timezone: normalized.config.timezone,
|
|
51
|
+
closureReceipts: this.store.listClosureReceipts({ episodeId: episode.episodeId, limit: 1 }),
|
|
52
|
+
dreamJobState: this.store.getDreamJobState(episode.episodeId),
|
|
53
|
+
});
|
|
54
|
+
warnings.push(...invariantViolations.map((violation) => violation.reason));
|
|
55
|
+
const proposedBoundaries = replay.detectedBoundaries.map((boundary) => ({
|
|
56
|
+
boundaryIndex: boundary.boundaryIndex,
|
|
57
|
+
beforeEventId: boundary.beforeEventId,
|
|
58
|
+
afterEventId: boundary.afterEventId,
|
|
59
|
+
primaryUserEventId: boundary.primaryUserEventId,
|
|
60
|
+
reason: boundary.reason,
|
|
61
|
+
relation: boundary.relation,
|
|
62
|
+
effective: boundary.effective,
|
|
63
|
+
disposition: boundary.disposition,
|
|
64
|
+
}));
|
|
65
|
+
const segments = segmentsFromBoundaries(pairs, replay.effectiveBoundaries, options.includeEventIds === true);
|
|
66
|
+
const fingerprint = sourceFingerprint(pairs, episode.startedAt, episode.status);
|
|
67
|
+
const canonicalSegments = segments.map((item) => ({
|
|
68
|
+
segmentIndex: item.segmentIndex,
|
|
69
|
+
eventIdsHash: item.eventIdsHash,
|
|
70
|
+
startEventId: item.startEventId,
|
|
71
|
+
endEventId: item.endEventId,
|
|
72
|
+
eventCount: item.eventCount,
|
|
73
|
+
reason: item.reason,
|
|
74
|
+
}));
|
|
75
|
+
const policyFingerprint = createHash('sha256').update(JSON.stringify(policy)).digest('hex');
|
|
76
|
+
const hash = createHash('sha256').update(JSON.stringify([
|
|
77
|
+
options.projectId,
|
|
78
|
+
options.episodeId,
|
|
79
|
+
fingerprint,
|
|
80
|
+
policyFingerprint,
|
|
81
|
+
policy,
|
|
82
|
+
canonicalSegments,
|
|
83
|
+
proposedBoundaries,
|
|
84
|
+
])).digest('hex');
|
|
85
|
+
return {
|
|
86
|
+
planId: `episode-split-plan-${hash.slice(0, 24)}`,
|
|
87
|
+
plannerVersion: EPISODE_SPLIT_PLANNER_VERSION,
|
|
88
|
+
projectId: options.projectId,
|
|
89
|
+
episodeId: options.episodeId,
|
|
90
|
+
sourceFingerprint: fingerprint,
|
|
91
|
+
policyFingerprint,
|
|
92
|
+
normalizedPolicy: policy,
|
|
93
|
+
proposedBoundaries,
|
|
94
|
+
impactInventory: impactInventory(pairs, policy.timezone),
|
|
95
|
+
segments,
|
|
96
|
+
warnings: [...new Set(warnings)].sort(),
|
|
97
|
+
unresolvedEventCount: missingRawEventIds.length,
|
|
98
|
+
missingRawEventIds: missingRawEventIds.slice(0, 50),
|
|
99
|
+
evidenceIntegrityStatus: missingRawEventIds.length ? 'missing_raw_events' : 'ok',
|
|
100
|
+
requiresManualReview: userCount === 0 || missingRawEventIds.length > 0 || replay.structuralAnomalies.length > 0 || replay.warnings.includes('invalid_trusted_local_date') || invariantViolations.some((violation) => violation.requiresManualReview),
|
|
101
|
+
applyableInCurrentVersion: false,
|
|
102
|
+
applyCommand: null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const MAX_RETURNED_EVENT_IDS = 500;
|
|
107
|
+
function segment(index, pairs, reason, includeEventIds) {
|
|
108
|
+
const eventIds = pairs.map((item) => item.link.eventId);
|
|
109
|
+
const returned = includeEventIds && eventIds.length <= MAX_RETURNED_EVENT_IDS ? eventIds : undefined;
|
|
110
|
+
const times = pairs.map((item) => item.event?.occurredAt).filter((value) => typeof value === 'number' && Number.isFinite(value));
|
|
111
|
+
const range = timeRange(times);
|
|
112
|
+
const counts = roleCounts(pairs);
|
|
113
|
+
return {
|
|
114
|
+
segmentIndex: index,
|
|
115
|
+
eventIds: returned,
|
|
116
|
+
eventIdsHash: createHash('sha256').update(JSON.stringify(eventIds)).digest('hex'),
|
|
117
|
+
eventIdsOmitted: returned ? 0 : eventIds.length,
|
|
118
|
+
startEventId: eventIds[0],
|
|
119
|
+
endEventId: eventIds.at(-1),
|
|
120
|
+
eventCount: eventIds.length,
|
|
121
|
+
reason,
|
|
122
|
+
startedAt: range?.min,
|
|
123
|
+
endedAt: range?.max,
|
|
124
|
+
...counts,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function sourceFingerprint(pairs, startedAt, status) {
|
|
128
|
+
const hash = createHash('sha256');
|
|
129
|
+
hash.update(JSON.stringify([startedAt, status]));
|
|
130
|
+
for (const { link, event } of pairs) {
|
|
131
|
+
hash.update(JSON.stringify([
|
|
132
|
+
link.eventId,
|
|
133
|
+
link.position,
|
|
134
|
+
link.relation,
|
|
135
|
+
event?.role,
|
|
136
|
+
event?.turnId,
|
|
137
|
+
event?.turnSeq,
|
|
138
|
+
event?.eventOrdinal,
|
|
139
|
+
event?.occurredAt,
|
|
140
|
+
event?.localDate,
|
|
141
|
+
event?.localDateSource,
|
|
142
|
+
isImportedEvent(event),
|
|
143
|
+
event?.contentHash,
|
|
144
|
+
]));
|
|
145
|
+
}
|
|
146
|
+
return hash.digest('hex');
|
|
147
|
+
}
|
|
148
|
+
function timeRange(values) {
|
|
149
|
+
let min;
|
|
150
|
+
let max;
|
|
151
|
+
for (const value of values) {
|
|
152
|
+
min = min === undefined ? value : Math.min(min, value);
|
|
153
|
+
max = max === undefined ? value : Math.max(max, value);
|
|
154
|
+
}
|
|
155
|
+
return min === undefined || max === undefined ? undefined : { min, max };
|
|
156
|
+
}
|
|
157
|
+
function trustedLocalDate(event, timezone) {
|
|
158
|
+
return resolveTrustedLocalDate(event, timezone).date;
|
|
159
|
+
}
|
|
160
|
+
function roleCounts(pairs) {
|
|
161
|
+
return {
|
|
162
|
+
userEventCount: pairs.filter((item) => item.event?.role === 'user').length,
|
|
163
|
+
assistantEventCount: pairs.filter((item) => item.event?.role === 'assistant' || item.event?.role === 'agent').length,
|
|
164
|
+
toolEventCount: pairs.filter((item) => item.event?.role === 'tool').length,
|
|
165
|
+
systemEventCount: pairs.filter((item) => item.event?.role === 'system').length,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function segmentsFromBoundaries(pairs, boundaries, includeEventIds) {
|
|
169
|
+
const segments = [];
|
|
170
|
+
let start = 0;
|
|
171
|
+
for (const boundary of boundaries) {
|
|
172
|
+
const nextIndex = boundary.afterEventId ? pairs.findIndex((pair) => pair.link.eventId === boundary.afterEventId) : -1;
|
|
173
|
+
if (nextIndex <= start)
|
|
174
|
+
continue;
|
|
175
|
+
segments.push(segment(segments.length, pairs.slice(start, nextIndex), boundary.reason, includeEventIds));
|
|
176
|
+
start = nextIndex;
|
|
177
|
+
}
|
|
178
|
+
if (start < pairs.length)
|
|
179
|
+
segments.push(segment(segments.length, pairs.slice(start), segments.length ? 'tail' : 'single_segment', includeEventIds));
|
|
180
|
+
return segments;
|
|
181
|
+
}
|
|
182
|
+
function isImportedEvent(event) {
|
|
183
|
+
const payload = event?.payload;
|
|
184
|
+
return payload?.metadata?.imported === true || payload?.metadata?.sourceRef !== undefined;
|
|
185
|
+
}
|
|
186
|
+
function impactInventory(pairs, timezone) {
|
|
187
|
+
const counts = roleCounts(pairs);
|
|
188
|
+
const dates = pairs
|
|
189
|
+
.filter((item) => item.event?.role === 'user')
|
|
190
|
+
.map((item) => trustedLocalDate(item.event, timezone))
|
|
191
|
+
.filter((value) => Boolean(value));
|
|
192
|
+
return {
|
|
193
|
+
eventCount: pairs.length,
|
|
194
|
+
...counts,
|
|
195
|
+
hardShiftCount: pairs.filter((item) => ['hard_topic_switch', 'starts_new_topic', 'switches_topic'].includes(item.link.relation)).length,
|
|
196
|
+
trustedLocalDates: [...new Set(dates)],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function configWithDefinedOverrides(base, overrides) {
|
|
200
|
+
const config = { ...base };
|
|
201
|
+
if (overrides.maxEvents !== undefined && validThreshold(overrides.maxEvents, 20, 500))
|
|
202
|
+
config.maxEvents = overrides.maxEvents;
|
|
203
|
+
if (overrides.maxDurationMs !== undefined && validThreshold(overrides.maxDurationMs, 300_000, 86_400_000))
|
|
204
|
+
config.maxDurationMs = overrides.maxDurationMs;
|
|
205
|
+
if (overrides.maxIdleGapMs !== undefined && validThreshold(overrides.maxIdleGapMs, 300_000, 86_400_000))
|
|
206
|
+
config.maxIdleGapMs = overrides.maxIdleGapMs;
|
|
207
|
+
if (typeof overrides.timezone === 'string' && overrides.timezone.trim())
|
|
208
|
+
config.timezone = overrides.timezone;
|
|
209
|
+
return config;
|
|
210
|
+
}
|
|
211
|
+
function validThreshold(value, min, max) {
|
|
212
|
+
return value !== undefined && Number.isFinite(value) && value >= min && value <= max;
|
|
213
|
+
}
|
|
214
|
+
function boundaryOverrideWarnings(overrides) {
|
|
215
|
+
const warnings = [];
|
|
216
|
+
if (overrides.maxEvents !== undefined && !validThreshold(overrides.maxEvents, 20, 500))
|
|
217
|
+
warnings.push('invalid_episode_boundary_max_events');
|
|
218
|
+
if (overrides.maxDurationMs !== undefined && !validThreshold(overrides.maxDurationMs, 300_000, 86_400_000))
|
|
219
|
+
warnings.push('invalid_episode_boundary_max_duration_ms');
|
|
220
|
+
if (overrides.maxIdleGapMs !== undefined && !validThreshold(overrides.maxIdleGapMs, 300_000, 86_400_000))
|
|
221
|
+
warnings.push('invalid_episode_boundary_max_idle_gap_ms');
|
|
222
|
+
if (overrides.timezone !== undefined && !overrides.timezone.trim())
|
|
223
|
+
warnings.push('invalid_episode_boundary_timezone');
|
|
224
|
+
return warnings;
|
|
225
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type Database from 'bun:sqlite';
|
|
2
2
|
import type { MemoryEvent } from '../types/index.js';
|
|
3
|
-
import type { EpisodeClosureMode, EpisodeClosureReasonCode, EpisodeClosureReceipt, EpisodeDreamStatus, EpisodeEventLink, EpisodeListOptions, EpisodeType, MemoryEpisode, TurnRelation } from './EpisodeTypes.js';
|
|
3
|
+
import type { EpisodeClosureMode, EpisodeClosureReasonCode, EpisodeClosureReceipt, EpisodeDreamState, EpisodeDreamStatus, EpisodeEventLink, EpisodeListOptions, EpisodeStatus, EpisodeType, MemoryEpisode, TurnRelation } from './EpisodeTypes.js';
|
|
4
|
+
import { type EpisodeBoundaryGuardResult } from './EpisodeBoundaryPolicy.js';
|
|
5
|
+
import type { TurnRelationDecision } from './TurnRelationClassifier.js';
|
|
4
6
|
interface CreateEpisodeInput {
|
|
5
7
|
projectId: string;
|
|
6
8
|
sessionId: string;
|
|
@@ -25,6 +27,41 @@ export interface ClaimedEpisodeDreamJob {
|
|
|
25
27
|
modeHint: 'micro' | 'normal' | 'deep';
|
|
26
28
|
attempts: number;
|
|
27
29
|
createdAt: number;
|
|
30
|
+
leaseUntil: number;
|
|
31
|
+
attemptGeneration: number;
|
|
32
|
+
}
|
|
33
|
+
export interface EpisodeBoundaryDecisionRecord {
|
|
34
|
+
decisionId: string;
|
|
35
|
+
projectId: string;
|
|
36
|
+
sessionId: string;
|
|
37
|
+
sourceAgent?: string;
|
|
38
|
+
threadId?: string;
|
|
39
|
+
primaryEventId: string;
|
|
40
|
+
previousEpisodeId?: string;
|
|
41
|
+
resultingEpisodeId?: string;
|
|
42
|
+
policyVersion: string;
|
|
43
|
+
mode: string;
|
|
44
|
+
guardAction: string;
|
|
45
|
+
guardCodes: string[];
|
|
46
|
+
metrics: EpisodeBoundaryGuardResult['metrics'];
|
|
47
|
+
cpuDecision: Partial<TurnRelationDecision>;
|
|
48
|
+
reviewerInvoked: boolean;
|
|
49
|
+
reviewerDecision?: Partial<TurnRelationDecision>;
|
|
50
|
+
finalDecision: Partial<TurnRelationDecision>;
|
|
51
|
+
warnings: EpisodeBoundaryGuardResult['warnings'];
|
|
52
|
+
createdAt: number;
|
|
53
|
+
}
|
|
54
|
+
export interface EpisodeBoundarySnapshot {
|
|
55
|
+
eventCount: number;
|
|
56
|
+
actualLinkCount: number;
|
|
57
|
+
storedEventCount: number;
|
|
58
|
+
eventCountMismatch: boolean;
|
|
59
|
+
startedAt?: number;
|
|
60
|
+
updatedAt?: number;
|
|
61
|
+
lastEventAt?: number;
|
|
62
|
+
lastTrustedUserLocalDate?: string;
|
|
63
|
+
lastTrustedLocalDate?: string;
|
|
64
|
+
trustedLocalDates: string[];
|
|
28
65
|
}
|
|
29
66
|
export declare class EpisodeStore {
|
|
30
67
|
private readonly db;
|
|
@@ -32,12 +69,22 @@ export declare class EpisodeStore {
|
|
|
32
69
|
constructor(db: Database, resolveEvent?: ((eventId: string) => MemoryEvent | null | undefined) | undefined, options?: {
|
|
33
70
|
initializeSchemaForTests?: boolean;
|
|
34
71
|
});
|
|
72
|
+
getDatabase(): Database;
|
|
35
73
|
createEpisode(input: CreateEpisodeInput): MemoryEpisode;
|
|
36
74
|
findActiveEpisode(projectId: string, sessionId: string, sourceAgent?: string, conversationThreadId?: string): MemoryEpisode | undefined;
|
|
37
75
|
private findActiveEpisodeRow;
|
|
38
76
|
claimLegacyEpisodeScope(episodeId: string, sourceAgent?: string, conversationThreadId?: string): MemoryEpisode | undefined;
|
|
39
77
|
getEpisode(episodeId: string): MemoryEpisode | undefined;
|
|
40
78
|
listEpisodes(options?: EpisodeListOptions): MemoryEpisode[];
|
|
79
|
+
listEpisodesForBoundaryAudit(options: {
|
|
80
|
+
projectId: string;
|
|
81
|
+
statuses?: EpisodeStatus[];
|
|
82
|
+
limit?: number;
|
|
83
|
+
cursor?: string;
|
|
84
|
+
}): {
|
|
85
|
+
episodes: MemoryEpisode[];
|
|
86
|
+
nextCursor?: string;
|
|
87
|
+
};
|
|
41
88
|
appendEvent(input: {
|
|
42
89
|
episodeId: string;
|
|
43
90
|
eventId: string;
|
|
@@ -54,6 +101,8 @@ export declare class EpisodeStore {
|
|
|
54
101
|
}): EpisodeEventLink;
|
|
55
102
|
getEventLink(eventId: string): EpisodeEventLink | undefined;
|
|
56
103
|
listEventLinks(episodeId: string): EpisodeEventLink[];
|
|
104
|
+
getBoundarySnapshot(episodeId: string, timezone?: string): EpisodeBoundarySnapshot;
|
|
105
|
+
transaction<T>(fn: () => T): T;
|
|
57
106
|
isEpisodeEmpty(episodeId: string): boolean;
|
|
58
107
|
addCrossReference(input: {
|
|
59
108
|
projectId: string;
|
|
@@ -84,8 +133,21 @@ export declare class EpisodeStore {
|
|
|
84
133
|
after: unknown;
|
|
85
134
|
now?: number;
|
|
86
135
|
}): string;
|
|
136
|
+
recordBoundaryDecision(input: Omit<EpisodeBoundaryDecisionRecord, 'decisionId' | 'createdAt'> & {
|
|
137
|
+
createdAt?: number;
|
|
138
|
+
}): {
|
|
139
|
+
recorded: boolean;
|
|
140
|
+
decisionId?: string;
|
|
141
|
+
status: 'inserted' | 'duplicate';
|
|
142
|
+
};
|
|
143
|
+
listBoundaryDecisions(options?: {
|
|
144
|
+
projectId?: string;
|
|
145
|
+
primaryEventId?: string;
|
|
146
|
+
limit?: number;
|
|
147
|
+
}): EpisodeBoundaryDecisionRecord[];
|
|
87
148
|
private invalidateEpisodeDerivedState;
|
|
88
149
|
private resequenceEpisode;
|
|
150
|
+
private deleteEmptyEpisode;
|
|
89
151
|
reopenSoftEpisode(episodeId: string, now: number): MemoryEpisode;
|
|
90
152
|
sealEpisode(episodeId: string, input: {
|
|
91
153
|
mode: EpisodeClosureMode;
|
|
@@ -125,7 +187,7 @@ export declare class EpisodeStore {
|
|
|
125
187
|
projectId?: string;
|
|
126
188
|
now?: number;
|
|
127
189
|
}): number;
|
|
128
|
-
completeDreamJob(episodeId: string, leaseId: string, candidateIds: string[], now: number): void;
|
|
190
|
+
completeDreamJob(episodeId: string, leaseId: string, candidateIds: string[], now: number, commitCandidates?: () => void): void;
|
|
129
191
|
failDreamJob(episodeId: string, leaseId: string, error: string, input: {
|
|
130
192
|
now: number;
|
|
131
193
|
failureCategory: string;
|
|
@@ -136,6 +198,7 @@ export declare class EpisodeStore {
|
|
|
136
198
|
private markEmptyEpisodeDreamSkipped;
|
|
137
199
|
private markEmptyEpisodeDreamSkippedMany;
|
|
138
200
|
getDreamStatus(projectId?: string): EpisodeDreamStatus;
|
|
201
|
+
getDreamJobState(episodeId: string): EpisodeDreamState | undefined;
|
|
139
202
|
countUnassignedRawEvents(projectId?: string): number;
|
|
140
203
|
markEventDisposition(input: {
|
|
141
204
|
eventId: string;
|
|
@@ -191,6 +254,8 @@ export declare class EpisodeStore {
|
|
|
191
254
|
deleteByProject(projectId: string): number;
|
|
192
255
|
private enqueueDreamJob;
|
|
193
256
|
private initializeSchema;
|
|
257
|
+
private initializeSchemaUnsafe;
|
|
258
|
+
private ensureEpisodeCompatibilityColumns;
|
|
194
259
|
}
|
|
195
260
|
export {};
|
|
196
261
|
//# sourceMappingURL=EpisodeStore.d.ts.map
|