@modelprofile.com/flexharness 10.24.0 → 10.24.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.flexharness.admission.d.ts +17 -0
- package/dist_ts/classes.flexharness.admission.js +263 -0
- package/dist_ts/classes.flexharness.callbacks.d.ts +38 -0
- package/dist_ts/classes.flexharness.callbacks.js +313 -0
- package/dist_ts/classes.flexharness.compaction.d.ts +25 -0
- package/dist_ts/classes.flexharness.compaction.js +87 -0
- package/dist_ts/classes.flexharness.configurations.d.ts +11 -0
- package/dist_ts/classes.flexharness.configurations.js +137 -0
- package/dist_ts/classes.flexharness.core.d.ts +143 -0
- package/dist_ts/classes.flexharness.core.js +1538 -0
- package/dist_ts/classes.flexharness.d.ts +2 -437
- package/dist_ts/classes.flexharness.deletion.d.ts +31 -0
- package/dist_ts/classes.flexharness.deletion.js +396 -0
- package/dist_ts/classes.flexharness.imports.d.ts +24 -0
- package/dist_ts/classes.flexharness.imports.js +345 -0
- package/dist_ts/classes.flexharness.js +119 -9776
- package/dist_ts/classes.flexharness.lifecycle.d.ts +47 -0
- package/dist_ts/classes.flexharness.lifecycle.js +625 -0
- package/dist_ts/classes.flexharness.permissions.d.ts +19 -0
- package/dist_ts/classes.flexharness.permissions.js +450 -0
- package/dist_ts/classes.flexharness.projects.d.ts +55 -0
- package/dist_ts/classes.flexharness.projects.js +575 -0
- package/dist_ts/classes.flexharness.prompts.d.ts +44 -0
- package/dist_ts/classes.flexharness.prompts.js +659 -0
- package/dist_ts/classes.flexharness.providers.d.ts +18 -0
- package/dist_ts/classes.flexharness.providers.js +267 -0
- package/dist_ts/classes.flexharness.results.d.ts +26 -0
- package/dist_ts/classes.flexharness.results.js +89 -0
- package/dist_ts/classes.flexharness.reversions.d.ts +52 -0
- package/dist_ts/classes.flexharness.reversions.js +1306 -0
- package/dist_ts/classes.flexharness.runs.d.ts +63 -0
- package/dist_ts/classes.flexharness.runs.js +1058 -0
- package/dist_ts/classes.flexharness.sessions.d.ts +20 -0
- package/dist_ts/classes.flexharness.sessions.js +381 -0
- package/dist_ts/classes.flexharness.slashcommands.d.ts +40 -0
- package/dist_ts/classes.flexharness.slashcommands.js +458 -0
- package/dist_ts/classes.flexharness.subagents.d.ts +31 -0
- package/dist_ts/classes.flexharness.subagents.js +690 -0
- package/dist_ts/classes.flexharness.tooldispatch.d.ts +53 -0
- package/dist_ts/classes.flexharness.tooldispatch.js +418 -0
- package/dist_ts/interfaces.flexharness.d.ts +455 -0
- package/dist_ts/interfaces.flexharness.js +2 -0
- package/dist_ts/utils.flexharness.d.ts +19 -0
- package/dist_ts/utils.flexharness.js +83 -0
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.flexharness.admission.ts +331 -0
- package/ts/classes.flexharness.callbacks.ts +352 -0
- package/ts/classes.flexharness.compaction.ts +167 -0
- package/ts/classes.flexharness.configurations.ts +167 -0
- package/ts/classes.flexharness.core.ts +1830 -0
- package/ts/classes.flexharness.deletion.ts +616 -0
- package/ts/classes.flexharness.imports.ts +414 -0
- package/ts/classes.flexharness.lifecycle.ts +786 -0
- package/ts/classes.flexharness.permissions.ts +535 -0
- package/ts/classes.flexharness.projects.ts +1006 -0
- package/ts/classes.flexharness.prompts.ts +857 -0
- package/ts/classes.flexharness.providers.ts +322 -0
- package/ts/classes.flexharness.results.ts +98 -0
- package/ts/classes.flexharness.reversions.ts +1684 -0
- package/ts/classes.flexharness.runs.ts +1204 -0
- package/ts/classes.flexharness.sessions.ts +483 -0
- package/ts/classes.flexharness.slashcommands.ts +705 -0
- package/ts/classes.flexharness.subagents.ts +860 -0
- package/ts/classes.flexharness.tooldispatch.ts +475 -0
- package/ts/classes.flexharness.ts +147 -12567
- package/ts/interfaces.flexharness.ts +517 -0
- package/ts/utils.flexharness.ts +121 -0
|
@@ -0,0 +1,1538 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { FlexHarnessAbortError, FlexHarnessClosedError, FlexHarnessExternalError, FlexHarnessImportedSessionError, FlexHarnessNotFoundError, FlexHarnessRunError, FlexHarnessSessionBusyError, FlexHarnessStoreConflictError, FlexHarnessStoreCommitUncertainError, FlexHarnessValidationError, modelLimitErrorInfo, } from './errors.js';
|
|
3
|
+
import { InMemoryFlexHarnessStores } from './classes.stores.js';
|
|
4
|
+
import { assertJsonSerializable, cloneSerializable, deepFreeze, resolveJsonLimits, } from './utils.json.js';
|
|
5
|
+
import { hydrateAgentMessages } from './utils.prompt.js';
|
|
6
|
+
import { normalizeAgentSessionPolicy, normalizeBuiltInTools, normalizeSlashCommands, normalizeToolCatalogOptions, normalizeSubagents, requireHarnessStores, resolveBoundedPositiveInteger, resolveCallbackLimits, resolvePromptQueueLimits, resolveReversionMaintenanceTimeoutMs, resolveReversionLimits, } from './utils.harnessoptions.js';
|
|
7
|
+
import { jsonBytes, maxMessagePageCursorBytes, maxTransferIdentifierBytes, publicSnapshot, requireTransferIdentifier, } from './utils.transfer.js';
|
|
8
|
+
import { resolveSessionImportLimits } from './utils.sessionimport.js';
|
|
9
|
+
import { validateIdentifier, validateProjectedErrorInfo } from './utils.validation.js';
|
|
10
|
+
import { createSessionMetricsOperation, createSessionMetricsState, } from './utils.sessionmetrics.js';
|
|
11
|
+
import { scopeRetirementMessage, externalErrorFallback, requireSessionGeneration, combineErrors, terminalActivityError, isAbortError, } from './utils.flexharness.js';
|
|
12
|
+
import { FlexHarnessResults } from './classes.flexharness.results.js';
|
|
13
|
+
import { FlexHarnessToolDispatch } from './classes.flexharness.tooldispatch.js';
|
|
14
|
+
import { FlexHarnessToolProviders } from './classes.flexharness.providers.js';
|
|
15
|
+
import { FlexHarnessCompaction } from './classes.flexharness.compaction.js';
|
|
16
|
+
import { FlexHarnessSessionConfigurations } from './classes.flexharness.configurations.js';
|
|
17
|
+
import { FlexHarnessPermissions } from './classes.flexharness.permissions.js';
|
|
18
|
+
import { FlexHarnessRunCallbacks } from './classes.flexharness.callbacks.js';
|
|
19
|
+
import { FlexHarnessDelegatedRunAdmission } from './classes.flexharness.admission.js';
|
|
20
|
+
import { FlexHarnessProjectManagement } from './classes.flexharness.projects.js';
|
|
21
|
+
import { FlexHarnessSessionImports } from './classes.flexharness.imports.js';
|
|
22
|
+
import { FlexHarnessSlashCommands } from './classes.flexharness.slashcommands.js';
|
|
23
|
+
import { FlexHarnessSubagents } from './classes.flexharness.subagents.js';
|
|
24
|
+
import { FlexHarnessPromptQueue } from './classes.flexharness.prompts.js';
|
|
25
|
+
import { FlexHarnessReversions } from './classes.flexharness.reversions.js';
|
|
26
|
+
import { FlexHarnessSessionDeletion } from './classes.flexharness.deletion.js';
|
|
27
|
+
import { FlexHarnessLifecycle } from './classes.flexharness.lifecycle.js';
|
|
28
|
+
import { FlexHarnessRuns } from './classes.flexharness.runs.js';
|
|
29
|
+
import { FlexHarnessSessions } from './classes.flexharness.sessions.js';
|
|
30
|
+
const defaultMaxSubagentDepth = 6;
|
|
31
|
+
const maximumMaxSubagentDepth = 8;
|
|
32
|
+
const defaultMaxSubagentCallsPerRun = 32;
|
|
33
|
+
const maximumMaxSubagentCallsPerRun = 128;
|
|
34
|
+
const repairCancellationMessage = 'The process stopped before this run completed.';
|
|
35
|
+
function deriveLegacySessionGenerationId(storageKey, sessionId, createdAt) {
|
|
36
|
+
const digest = plugins.crypto.createHash('sha256').update(JSON.stringify([
|
|
37
|
+
'flexharness-legacy-session-generation-v1',
|
|
38
|
+
storageKey,
|
|
39
|
+
sessionId,
|
|
40
|
+
createdAt,
|
|
41
|
+
])).digest('hex');
|
|
42
|
+
return `legacy_${digest}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The engine behind {@link FlexHarness}: its options, scope state, events and error projection, and
|
|
46
|
+
* the services that implement its API.
|
|
47
|
+
*/
|
|
48
|
+
export class FlexHarnessCore {
|
|
49
|
+
scopeResolver;
|
|
50
|
+
modelResolver;
|
|
51
|
+
sessionConfigurationResolver;
|
|
52
|
+
toolProvider;
|
|
53
|
+
resourceToolProviderResolver;
|
|
54
|
+
executionContextProvider;
|
|
55
|
+
delegatedRunAdmissionProvider;
|
|
56
|
+
stores;
|
|
57
|
+
agentSessionPolicy;
|
|
58
|
+
toolOutputLimits;
|
|
59
|
+
callbackLimits;
|
|
60
|
+
promptQueueLimits;
|
|
61
|
+
reversionLimits;
|
|
62
|
+
sessionImportLimits;
|
|
63
|
+
reversionMaintenanceTimeoutMs;
|
|
64
|
+
turnReversionProvider;
|
|
65
|
+
reversionPolicy;
|
|
66
|
+
externalErrorProjector;
|
|
67
|
+
subagents;
|
|
68
|
+
builtInTools;
|
|
69
|
+
toolCatalogOptions;
|
|
70
|
+
slashCommands;
|
|
71
|
+
maxSubagentDepth;
|
|
72
|
+
maxSubagentCallsPerRun;
|
|
73
|
+
stateLoads = new Map();
|
|
74
|
+
scopeAdmissions = new Map();
|
|
75
|
+
listeners = new Set();
|
|
76
|
+
trustedInternalErrors = new WeakSet();
|
|
77
|
+
sequence = 0;
|
|
78
|
+
closed = false;
|
|
79
|
+
results = new FlexHarnessResults(this);
|
|
80
|
+
toolDispatch = new FlexHarnessToolDispatch(this);
|
|
81
|
+
providers = new FlexHarnessToolProviders(this);
|
|
82
|
+
compaction = new FlexHarnessCompaction(this);
|
|
83
|
+
configurations = new FlexHarnessSessionConfigurations(this);
|
|
84
|
+
permissions = new FlexHarnessPermissions(this);
|
|
85
|
+
callbacks = new FlexHarnessRunCallbacks(this);
|
|
86
|
+
admission = new FlexHarnessDelegatedRunAdmission(this);
|
|
87
|
+
projects = new FlexHarnessProjectManagement(this);
|
|
88
|
+
imports = new FlexHarnessSessionImports(this);
|
|
89
|
+
commands = new FlexHarnessSlashCommands(this);
|
|
90
|
+
subagentTasks = new FlexHarnessSubagents(this);
|
|
91
|
+
prompts = new FlexHarnessPromptQueue(this);
|
|
92
|
+
reversions = new FlexHarnessReversions(this);
|
|
93
|
+
deletion = new FlexHarnessSessionDeletion(this);
|
|
94
|
+
lifecycle = new FlexHarnessLifecycle(this);
|
|
95
|
+
runs = new FlexHarnessRuns(this);
|
|
96
|
+
sessions = new FlexHarnessSessions(this);
|
|
97
|
+
constructor(options) {
|
|
98
|
+
if (!options || typeof options !== 'object') {
|
|
99
|
+
throw new FlexHarnessValidationError('FlexHarness options are required.');
|
|
100
|
+
}
|
|
101
|
+
this.scopeResolver = options.scopeResolver;
|
|
102
|
+
this.modelResolver = options.modelResolver;
|
|
103
|
+
this.sessionConfigurationResolver = options.sessionConfigurationResolver;
|
|
104
|
+
this.toolProvider = options.toolProvider;
|
|
105
|
+
this.resourceToolProviderResolver = options.resourceToolProviderResolver;
|
|
106
|
+
this.executionContextProvider = options.executionContextProvider;
|
|
107
|
+
this.delegatedRunAdmissionProvider = options.delegatedRunAdmissionProvider;
|
|
108
|
+
this.stores = requireHarnessStores(options.stores ?? new InMemoryFlexHarnessStores());
|
|
109
|
+
this.agentSessionPolicy = normalizeAgentSessionPolicy(options.agentSessionPolicy);
|
|
110
|
+
this.toolOutputLimits = resolveJsonLimits(options.toolOutputLimits);
|
|
111
|
+
this.callbackLimits = resolveCallbackLimits(options.callbackLimits);
|
|
112
|
+
this.promptQueueLimits = resolvePromptQueueLimits(options.promptQueueLimits);
|
|
113
|
+
this.reversionLimits = resolveReversionLimits(options.reversionLimits);
|
|
114
|
+
this.sessionImportLimits = resolveSessionImportLimits(options.sessionImportLimits);
|
|
115
|
+
this.reversionMaintenanceTimeoutMs = resolveReversionMaintenanceTimeoutMs(options);
|
|
116
|
+
this.turnReversionProvider = options.turnReversionProvider;
|
|
117
|
+
this.reversionPolicy = options.reversionPolicy ?? 'transcript-optional';
|
|
118
|
+
if (!['transcript-optional', 'workspace-required'].includes(this.reversionPolicy)) {
|
|
119
|
+
throw new FlexHarnessValidationError('reversionPolicy must be "transcript-optional" or "workspace-required".');
|
|
120
|
+
}
|
|
121
|
+
const protocolVersion = this.turnReversionProvider
|
|
122
|
+
&& 'protocolVersion' in this.turnReversionProvider
|
|
123
|
+
? this.turnReversionProvider.protocolVersion
|
|
124
|
+
: 1;
|
|
125
|
+
if (protocolVersion !== 1 && protocolVersion !== 2) {
|
|
126
|
+
throw new FlexHarnessValidationError('Turn reversion provider protocolVersion is invalid.');
|
|
127
|
+
}
|
|
128
|
+
if (this.reversionPolicy === 'workspace-required' && protocolVersion !== 2) {
|
|
129
|
+
throw new FlexHarnessValidationError('workspace-required reversion policy requires a protocolVersion 2 turn reversion provider.');
|
|
130
|
+
}
|
|
131
|
+
this.externalErrorProjector = options.externalErrorProjector;
|
|
132
|
+
this.subagents = normalizeSubagents(options.subagents);
|
|
133
|
+
this.builtInTools = normalizeBuiltInTools(options.builtInTools);
|
|
134
|
+
const toolCatalogOptions = normalizeToolCatalogOptions(options.toolCatalog);
|
|
135
|
+
this.toolCatalogOptions = Object.freeze({
|
|
136
|
+
declarations: toolCatalogOptions.declarations,
|
|
137
|
+
outputTypeDepth: toolCatalogOptions.outputTypeDepth,
|
|
138
|
+
describeTopMatch: toolCatalogOptions.describeTopMatch,
|
|
139
|
+
...(toolCatalogOptions.codeMode ? { codeMode: { limits: toolCatalogOptions.codeMode } } : {}),
|
|
140
|
+
});
|
|
141
|
+
this.slashCommands = normalizeSlashCommands(options.slashCommands);
|
|
142
|
+
this.maxSubagentDepth = resolveBoundedPositiveInteger(options.maxSubagentDepth, 'maxSubagentDepth', defaultMaxSubagentDepth, maximumMaxSubagentDepth);
|
|
143
|
+
this.maxSubagentCallsPerRun = resolveBoundedPositiveInteger(options.maxSubagentCallsPerRun, 'maxSubagentCallsPerRun', defaultMaxSubagentCallsPerRun, maximumMaxSubagentCallsPerRun);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Opens a section that changes what a view of the session shows and emits the events that
|
|
147
|
+
* describe the change. Closing is idempotent; close it once the events are emitted or the
|
|
148
|
+
* change is rolled back.
|
|
149
|
+
*/
|
|
150
|
+
openPublication(state, sessionId) {
|
|
151
|
+
let release;
|
|
152
|
+
const section = new Promise((resolve) => {
|
|
153
|
+
release = resolve;
|
|
154
|
+
});
|
|
155
|
+
let sections = state.publications.get(sessionId);
|
|
156
|
+
if (!sections) {
|
|
157
|
+
sections = new Set();
|
|
158
|
+
state.publications.set(sessionId, sections);
|
|
159
|
+
}
|
|
160
|
+
sections.add(section);
|
|
161
|
+
return () => {
|
|
162
|
+
const current = state.publications.get(sessionId);
|
|
163
|
+
if (!current?.delete(section))
|
|
164
|
+
return;
|
|
165
|
+
if (current.size === 0)
|
|
166
|
+
state.publications.delete(sessionId);
|
|
167
|
+
release();
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
subscribe(listener) {
|
|
171
|
+
this.assertOpen();
|
|
172
|
+
this.listeners.add(listener);
|
|
173
|
+
let subscribed = true;
|
|
174
|
+
return () => {
|
|
175
|
+
if (!subscribed)
|
|
176
|
+
return;
|
|
177
|
+
subscribed = false;
|
|
178
|
+
this.listeners.delete(listener);
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
projectExternalError(run, error, source) {
|
|
182
|
+
if ((typeof error === 'object' && error !== null) || typeof error === 'function') {
|
|
183
|
+
if (error === run.ownerCancellation
|
|
184
|
+
|| error === run.callbackError
|
|
185
|
+
|| this.trustedInternalErrors.has(error))
|
|
186
|
+
return error;
|
|
187
|
+
}
|
|
188
|
+
return this.projectOperationError(error, source, run.scopeId, run.sessionId, run.runId);
|
|
189
|
+
}
|
|
190
|
+
projectOperationError(error, source, scopeId, sessionId, runId) {
|
|
191
|
+
if ((typeof error === 'object' && error !== null) && this.trustedInternalErrors.has(error)) {
|
|
192
|
+
return error;
|
|
193
|
+
}
|
|
194
|
+
const defaultInfo = modelLimitErrorInfo(error) ?? externalErrorFallback;
|
|
195
|
+
let info = defaultInfo;
|
|
196
|
+
if (this.externalErrorProjector) {
|
|
197
|
+
try {
|
|
198
|
+
info = validateProjectedErrorInfo(this.externalErrorProjector(error, {
|
|
199
|
+
source,
|
|
200
|
+
scopeId,
|
|
201
|
+
sessionId,
|
|
202
|
+
runId,
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
info = defaultInfo;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return this.trustInternalError(new FlexHarnessExternalError(info));
|
|
210
|
+
}
|
|
211
|
+
trustInternalError(error) {
|
|
212
|
+
Object.freeze(error);
|
|
213
|
+
this.trustedInternalErrors.add(error);
|
|
214
|
+
return error;
|
|
215
|
+
}
|
|
216
|
+
canonicalOutcomes(events) {
|
|
217
|
+
const outcomes = new Map();
|
|
218
|
+
const remember = (generationId, outcome) => {
|
|
219
|
+
const existing = outcomes.get(generationId);
|
|
220
|
+
if (existing && existing !== outcome) {
|
|
221
|
+
throw new FlexHarnessValidationError(`Generation "${generationId}" has conflicting canonical outcomes.`);
|
|
222
|
+
}
|
|
223
|
+
outcomes.set(generationId, outcome);
|
|
224
|
+
};
|
|
225
|
+
for (const event of events) {
|
|
226
|
+
if (event.type === 'generation-outcome')
|
|
227
|
+
remember(event.generationId, event.outcome);
|
|
228
|
+
if (event.type === 'context-compaction') {
|
|
229
|
+
for (const transaction of event.archivedTransactions ?? []) {
|
|
230
|
+
remember(transaction.generationId, transaction.outcome);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return outcomes;
|
|
235
|
+
}
|
|
236
|
+
async durableCanonicalOutcomes(stored) {
|
|
237
|
+
const snapshot = await stored.eventStore.load(stored.session.sessionId);
|
|
238
|
+
return this.canonicalOutcomes(snapshot?.events ?? []);
|
|
239
|
+
}
|
|
240
|
+
async loadState(storageKey, scopeId, scope, compactorLifecycleController) {
|
|
241
|
+
const snapshot = cloneSerializable(await this.stores.scopes.load(storageKey) ?? {
|
|
242
|
+
schemaVersion: 1,
|
|
243
|
+
revision: 0,
|
|
244
|
+
sessions: [],
|
|
245
|
+
tombstones: [],
|
|
246
|
+
});
|
|
247
|
+
let scopeChanged = false;
|
|
248
|
+
const repairedGenerationSequence = snapshot.revision + 1;
|
|
249
|
+
for (const session of snapshot.sessions) {
|
|
250
|
+
if (session.sessionGenerationId !== undefined)
|
|
251
|
+
continue;
|
|
252
|
+
session.sessionGenerationId = deriveLegacySessionGenerationId(storageKey, session.sessionId, session.createdAt);
|
|
253
|
+
session.sessionGenerationSequence = repairedGenerationSequence;
|
|
254
|
+
scopeChanged = true;
|
|
255
|
+
}
|
|
256
|
+
for (const tombstone of snapshot.tombstones) {
|
|
257
|
+
if (tombstone.sessionGenerationId !== undefined)
|
|
258
|
+
continue;
|
|
259
|
+
tombstone.sessionGenerationId = deriveLegacySessionGenerationId(storageKey, tombstone.sessionId, tombstone.deletedAt);
|
|
260
|
+
tombstone.sessionGenerationSequence = repairedGenerationSequence;
|
|
261
|
+
scopeChanged = true;
|
|
262
|
+
}
|
|
263
|
+
const state = {
|
|
264
|
+
storageKey,
|
|
265
|
+
compactorLifecycleController,
|
|
266
|
+
scopeIdHint: scopeId,
|
|
267
|
+
scopeContext: { scopeId, scope },
|
|
268
|
+
revision: snapshot.revision,
|
|
269
|
+
sessions: new Map(),
|
|
270
|
+
retainedSessionCleanups: new Map(),
|
|
271
|
+
sessionDeletions: new Map(),
|
|
272
|
+
initializingSessions: new Set(),
|
|
273
|
+
sessionInitializations: new Map(),
|
|
274
|
+
sessionImports: new Map(),
|
|
275
|
+
tombstones: new Map(snapshot.tombstones.map((entry) => [entry.sessionId, entry])),
|
|
276
|
+
tombstoneCleanups: new Map(),
|
|
277
|
+
activeRuns: new Map(),
|
|
278
|
+
delegatedRunAdmissionOwners: new Set(),
|
|
279
|
+
pendingPermissions: new Map(),
|
|
280
|
+
publications: new Map(),
|
|
281
|
+
scopeQueue: Promise.resolve(),
|
|
282
|
+
lifecycle: 'active',
|
|
283
|
+
fenceInProgress: false,
|
|
284
|
+
fenceAdditionalErrors: [],
|
|
285
|
+
detachedCleanups: new Set(),
|
|
286
|
+
};
|
|
287
|
+
const loadedSessions = [];
|
|
288
|
+
try {
|
|
289
|
+
for (const metadata of snapshot.sessions) {
|
|
290
|
+
if (state.tombstones.has(metadata.sessionId))
|
|
291
|
+
continue;
|
|
292
|
+
const stored = await this.loadSessionRuntime(state, metadata, scopeId, scope);
|
|
293
|
+
state.sessions.set(metadata.sessionId, stored);
|
|
294
|
+
loadedSessions.push(stored);
|
|
295
|
+
scopeChanged = (await this.repairLoadedSession(state.storageKey, stored, state, scopeId, scope)) || scopeChanged;
|
|
296
|
+
await this.reversions.drainReversionReleases(state, stored, scopeId, scope, false);
|
|
297
|
+
if (stored.projectionRevision < 0)
|
|
298
|
+
throw new Error('Invalid projection revision.');
|
|
299
|
+
}
|
|
300
|
+
for (const stored of state.sessions.values()) {
|
|
301
|
+
let ancestorId = stored.session.parentSessionId;
|
|
302
|
+
const visited = new Set([stored.session.sessionId]);
|
|
303
|
+
while (ancestorId) {
|
|
304
|
+
if (visited.has(ancestorId)) {
|
|
305
|
+
throw new FlexHarnessValidationError(`Live session "${stored.session.sessionId}" has a cyclic ancestor chain.`);
|
|
306
|
+
}
|
|
307
|
+
visited.add(ancestorId);
|
|
308
|
+
if (state.tombstones.has(ancestorId)) {
|
|
309
|
+
throw new FlexHarnessValidationError(`Live session "${stored.session.sessionId}" descends from tombstoned ancestor "${ancestorId}".`);
|
|
310
|
+
}
|
|
311
|
+
ancestorId = state.sessions.get(ancestorId)?.session.parentSessionId;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const tombstoneRoots = this.deletion.orderTombstoneRootsChildFirst(state, [...new Set([...state.tombstones.values()].map((tombstone) => tombstone.rootSessionId ?? tombstone.sessionId))]);
|
|
315
|
+
for (const rootSessionId of tombstoneRoots) {
|
|
316
|
+
if (this.deletion.descendantTombstoneRoots(state, rootSessionId).length > 0)
|
|
317
|
+
continue;
|
|
318
|
+
try {
|
|
319
|
+
const group = this.deletion.tombstoneGroup(state, rootSessionId);
|
|
320
|
+
for (const tombstone of group) {
|
|
321
|
+
await this.reversions.releaseDeletedSessionReversions(state, storageKey, tombstone, scopeId, scope);
|
|
322
|
+
await this.deletion.cleanupSessionDomains(state, tombstone);
|
|
323
|
+
}
|
|
324
|
+
for (const tombstone of group)
|
|
325
|
+
state.tombstones.delete(tombstone.sessionId);
|
|
326
|
+
scopeChanged = true;
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
// A retained tombstone is retried by the next load or explicit delete call.
|
|
330
|
+
if (state.lifecycle === 'fenced') {
|
|
331
|
+
this.lifecycle.deferNamespaceDrain(state, error, { scopeId, scope });
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (scopeChanged) {
|
|
337
|
+
const next = this.createScopeSnapshot(state, state.revision + 1);
|
|
338
|
+
await this.stores.scopes.save(storageKey, next, state.revision);
|
|
339
|
+
state.revision = next.revision;
|
|
340
|
+
}
|
|
341
|
+
return state;
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
for (const rootSessionId of new Set([...state.tombstones.values()].map((tombstone) => tombstone.rootSessionId ?? tombstone.sessionId))) {
|
|
345
|
+
const key = JSON.stringify([storageKey, rootSessionId]);
|
|
346
|
+
this.lifecycle.orphanedTombstoneOwners.set(key, {
|
|
347
|
+
state,
|
|
348
|
+
rootSessionId,
|
|
349
|
+
scopeId,
|
|
350
|
+
scope,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
const closeResults = await Promise.allSettled(loadedSessions.map((stored) => this.lifecycle.closeStoredSession(stored)));
|
|
354
|
+
const errors = [error];
|
|
355
|
+
for (let index = 0; index < closeResults.length; index++) {
|
|
356
|
+
const result = closeResults[index];
|
|
357
|
+
if (result.status === 'rejected') {
|
|
358
|
+
if (!this.lifecycle.storedSessionCleanupCompleted(loadedSessions[index])) {
|
|
359
|
+
this.lifecycle.orphanedStoredSessions.add(loadedSessions[index]);
|
|
360
|
+
}
|
|
361
|
+
errors.push(result.reason);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
throw combineErrors(errors);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
createUninitializedStoredSession(session, storageKey, compactorLifecycleController = new AbortController()) {
|
|
368
|
+
const unavailable = new Proxy({}, {
|
|
369
|
+
get() {
|
|
370
|
+
throw new Error('AgentSession is not initialized.');
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
return {
|
|
374
|
+
storageKey,
|
|
375
|
+
session,
|
|
376
|
+
messages: [],
|
|
377
|
+
stagedTerminals: [],
|
|
378
|
+
reversionSegments: [],
|
|
379
|
+
revertCursor: 0,
|
|
380
|
+
excludedRunIds: [],
|
|
381
|
+
pendingReversionReleases: [],
|
|
382
|
+
projectionSchemaVersion: 3,
|
|
383
|
+
projectionReconciliationRequired: false,
|
|
384
|
+
projectionRevision: 0,
|
|
385
|
+
projectionQueue: Promise.resolve(),
|
|
386
|
+
metrics: createSessionMetricsState(false),
|
|
387
|
+
rememberedPermissionKeys: new Set(),
|
|
388
|
+
permissionRevision: 0,
|
|
389
|
+
permissionQueue: Promise.resolve(),
|
|
390
|
+
eventStore: undefined,
|
|
391
|
+
agentSession: unavailable,
|
|
392
|
+
agentSessionAbortCompleted: true,
|
|
393
|
+
agentSessionCloseCompleted: true,
|
|
394
|
+
agentEventStoreReleased: true,
|
|
395
|
+
executionContextCloseCompleted: true,
|
|
396
|
+
jobStoreReleased: true,
|
|
397
|
+
compactorLifecycleController,
|
|
398
|
+
promptQueue: [],
|
|
399
|
+
outstandingPromptsById: new Map(),
|
|
400
|
+
terminalPromptQueueEntries: new Map(),
|
|
401
|
+
outstandingPromptBytes: 0,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
async loadSessionRuntime(state, metadata, scopeId, scope, compactorLifecycleController = new AbortController(), newSession = false) {
|
|
405
|
+
const sessionId = metadata.sessionId;
|
|
406
|
+
const compactorContext = this.compaction.createCompactorContext(scopeId, scope, state.storageKey, sessionId);
|
|
407
|
+
const [projectionResult, permissionResult, eventStoreResult, jobStoreResult] = await Promise.allSettled([
|
|
408
|
+
this.stores.projections.load(state.storageKey, sessionId),
|
|
409
|
+
this.stores.permissions.load(state.storageKey, sessionId),
|
|
410
|
+
this.stores.agentEvents.getStore(state.storageKey, sessionId),
|
|
411
|
+
this.stores.jobs.getStore(state.storageKey, sessionId),
|
|
412
|
+
]);
|
|
413
|
+
const acquisitionErrors = [projectionResult, permissionResult, eventStoreResult, jobStoreResult]
|
|
414
|
+
.filter((result) => result.status === 'rejected')
|
|
415
|
+
.map((result) => result.reason);
|
|
416
|
+
if (projectionResult.status === 'rejected'
|
|
417
|
+
|| permissionResult.status === 'rejected'
|
|
418
|
+
|| eventStoreResult.status === 'rejected'
|
|
419
|
+
|| jobStoreResult.status === 'rejected') {
|
|
420
|
+
if (eventStoreResult.status === 'fulfilled') {
|
|
421
|
+
try {
|
|
422
|
+
await this.lifecycle.releasePartialProviderSession('agentEvents', state.storageKey, sessionId);
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
acquisitionErrors.push(error);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (jobStoreResult.status === 'fulfilled') {
|
|
429
|
+
try {
|
|
430
|
+
await this.lifecycle.releasePartialProviderSession('jobs', state.storageKey, sessionId);
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
acquisitionErrors.push(error);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
throw combineErrors(acquisitionErrors);
|
|
437
|
+
}
|
|
438
|
+
const projection = projectionResult.value;
|
|
439
|
+
const legacyProjection = projection?.schemaVersion === 2 ? projection : undefined;
|
|
440
|
+
const currentProjection = projection?.schemaVersion === 3 ? projection : undefined;
|
|
441
|
+
const reversionSegments = currentProjection
|
|
442
|
+
? cloneSerializable(currentProjection.reversionSegments)
|
|
443
|
+
: (legacyProjection?.reversionSegments ?? []).map((segment) => ({
|
|
444
|
+
...cloneSerializable(segment),
|
|
445
|
+
protocolVersion: 1,
|
|
446
|
+
provenance: segment.workspaceCaptured ? 'workspace' : 'transcript',
|
|
447
|
+
...(segment.workspaceCaptured
|
|
448
|
+
? { disposition: segment.status === 'capturing' ? 'pending' : 'revertible' }
|
|
449
|
+
: {}),
|
|
450
|
+
}));
|
|
451
|
+
const pendingReversion = currentProjection?.pendingReversion
|
|
452
|
+
?? (legacyProjection?.pendingReversion?.kind === 'capture'
|
|
453
|
+
? { ...legacyProjection.pendingReversion, protocolVersion: 1 }
|
|
454
|
+
: legacyProjection?.pendingReversion);
|
|
455
|
+
const pendingReversionReleases = currentProjection
|
|
456
|
+
? cloneSerializable(currentProjection.pendingReversionReleases)
|
|
457
|
+
: (legacyProjection?.pendingReversionReleases ?? []).map((release) => ({
|
|
458
|
+
...cloneSerializable(release),
|
|
459
|
+
protocolVersion: 1,
|
|
460
|
+
}));
|
|
461
|
+
const permission = permissionResult.value;
|
|
462
|
+
const eventStore = eventStoreResult.value;
|
|
463
|
+
const jobStore = jobStoreResult.value;
|
|
464
|
+
let executionContextHandle;
|
|
465
|
+
try {
|
|
466
|
+
if (this.executionContextProvider) {
|
|
467
|
+
executionContextHandle = await this.compaction.withCompactorContext(compactorContext, () => this.executionContextProvider.provideExecutionContext({
|
|
468
|
+
scopeId,
|
|
469
|
+
scope,
|
|
470
|
+
storageKey: state.storageKey,
|
|
471
|
+
sessionId,
|
|
472
|
+
jobStore,
|
|
473
|
+
}));
|
|
474
|
+
if (executionContextHandle
|
|
475
|
+
&& (!executionContextHandle.context
|
|
476
|
+
|| (executionContextHandle.close !== undefined && typeof executionContextHandle.close !== 'function'))) {
|
|
477
|
+
throw new FlexHarnessValidationError('Execution context provider returned an invalid handle.');
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const stored = {
|
|
481
|
+
storageKey: state.storageKey,
|
|
482
|
+
compactorContext,
|
|
483
|
+
session: cloneSerializable(metadata),
|
|
484
|
+
messages: cloneSerializable(projection?.messages ?? []),
|
|
485
|
+
stagedTerminals: cloneSerializable(projection?.stagedTerminals ?? []),
|
|
486
|
+
reversionSegments,
|
|
487
|
+
revertCursor: currentProjection?.revertCursor ?? legacyProjection?.revertCursor ?? 0,
|
|
488
|
+
excludedRunIds: cloneSerializable(currentProjection?.excludedRunIds ?? legacyProjection?.excludedRunIds ?? []),
|
|
489
|
+
...(pendingReversion === undefined
|
|
490
|
+
? {}
|
|
491
|
+
: { pendingReversion: cloneSerializable(pendingReversion) }),
|
|
492
|
+
pendingReversionReleases,
|
|
493
|
+
projectionSchemaVersion: projection?.schemaVersion ?? 3,
|
|
494
|
+
projectionReconciliationRequired: false,
|
|
495
|
+
...(projection
|
|
496
|
+
? { projectionBaseline: cloneSerializable(projection) }
|
|
497
|
+
: {}),
|
|
498
|
+
projectionRevision: projection?.revision ?? 0,
|
|
499
|
+
projectionQueue: Promise.resolve(),
|
|
500
|
+
metrics: cloneSerializable(currentProjection?.metrics ?? createSessionMetricsState(newSession)),
|
|
501
|
+
rememberedPermissionKeys: new Set(permission?.rememberedPermissionKeys ?? []),
|
|
502
|
+
permissionRevision: permission?.revision ?? 0,
|
|
503
|
+
permissionQueue: Promise.resolve(),
|
|
504
|
+
eventStore,
|
|
505
|
+
agentSession: undefined,
|
|
506
|
+
agentSessionAbortCompleted: false,
|
|
507
|
+
agentSessionCloseCompleted: false,
|
|
508
|
+
agentEventStoreReleased: this.stores.agentEvents.releaseSession === undefined,
|
|
509
|
+
executionContextHandle,
|
|
510
|
+
executionContextCloseCompleted: executionContextHandle?.close === undefined,
|
|
511
|
+
jobStoreReleased: this.stores.jobs.releaseSession === undefined,
|
|
512
|
+
jobs: executionContextHandle?.context.jobs,
|
|
513
|
+
compactorLifecycleController,
|
|
514
|
+
promptQueue: [],
|
|
515
|
+
outstandingPromptsById: new Map(),
|
|
516
|
+
terminalPromptQueueEntries: new Map(),
|
|
517
|
+
outstandingPromptBytes: 0,
|
|
518
|
+
};
|
|
519
|
+
if (currentProjection?.metrics === undefined
|
|
520
|
+
|| stored.metrics.pendingGenerationId !== undefined
|
|
521
|
+
|| stored.metrics.pendingCompactionId !== undefined
|
|
522
|
+
|| (metadata.origin !== undefined && stored.metrics.lifetimeUsageComplete)) {
|
|
523
|
+
await this.mutateProjection(state, stored, () => {
|
|
524
|
+
if (stored.metrics.pendingGenerationId !== undefined || stored.metrics.pendingCompactionId !== undefined
|
|
525
|
+
|| metadata.origin !== undefined) {
|
|
526
|
+
stored.metrics.lifetimeUsageComplete = false;
|
|
527
|
+
}
|
|
528
|
+
delete stored.metrics.pendingGenerationId;
|
|
529
|
+
delete stored.metrics.pendingCompactionId;
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
const { contextCompactor, ...agentSessionPolicy } = this.agentSessionPolicy;
|
|
533
|
+
const executionContext = executionContextHandle?.context;
|
|
534
|
+
const jobContext = executionContext?.jobs;
|
|
535
|
+
const contextualExecutionContext = executionContext && jobContext?.subscribe
|
|
536
|
+
? {
|
|
537
|
+
...executionContext,
|
|
538
|
+
jobs: {
|
|
539
|
+
start: jobContext.start.bind(jobContext),
|
|
540
|
+
get: jobContext.get.bind(jobContext),
|
|
541
|
+
list: jobContext.list.bind(jobContext),
|
|
542
|
+
...(jobContext.abort ? { abort: jobContext.abort.bind(jobContext) } : {}),
|
|
543
|
+
subscribe: (listener) => jobContext.subscribe((event) => this.compaction.withCompactorContext(compactorContext, () => listener(event))),
|
|
544
|
+
},
|
|
545
|
+
}
|
|
546
|
+
: executionContext;
|
|
547
|
+
const agentSessionOptions = {
|
|
548
|
+
...agentSessionPolicy,
|
|
549
|
+
sessionId,
|
|
550
|
+
eventStore,
|
|
551
|
+
executionContext: contextualExecutionContext,
|
|
552
|
+
contextBuilder: ({ events }) => hydrateAgentMessages((this.agentSessionPolicy.contextBuilder ?? ((options) => plugins.buildModelMessages(options.events)))({
|
|
553
|
+
events: this.reversions.filterReversionContextEvents(stored, events),
|
|
554
|
+
})),
|
|
555
|
+
...(contextCompactor
|
|
556
|
+
? {
|
|
557
|
+
contextCompactor: async (messages, events, options) => {
|
|
558
|
+
const ambientContext = this.compaction.compactorInvocationContext.getStore();
|
|
559
|
+
const invocationContext = ambientContext
|
|
560
|
+
? (this.compaction.deferredCompactorContexts.get(ambientContext) ?? ambientContext)
|
|
561
|
+
: undefined;
|
|
562
|
+
if (!ambientContext
|
|
563
|
+
|| !invocationContext
|
|
564
|
+
|| invocationContext.storageKey !== state.storageKey
|
|
565
|
+
|| invocationContext.sessionId !== sessionId) {
|
|
566
|
+
throw new Error('Agent context compaction is missing its exact FlexHarness invocation context.');
|
|
567
|
+
}
|
|
568
|
+
const { modelHint, ...invocation } = invocationContext;
|
|
569
|
+
const filteredEvents = this.reversions.filterReversionContextEvents(stored, events);
|
|
570
|
+
const filteredMessages = hydrateAgentMessages((this.agentSessionPolicy.contextBuilder
|
|
571
|
+
?? ((contextOptions) => plugins.buildModelMessages(contextOptions.events)))({
|
|
572
|
+
events: filteredEvents,
|
|
573
|
+
}));
|
|
574
|
+
const operation = createSessionMetricsOperation(plugins.crypto.randomUUID(), 'compaction');
|
|
575
|
+
try {
|
|
576
|
+
await this.mutateProjection(state, stored, () => {
|
|
577
|
+
if (stored.metrics.pendingCompactionId !== undefined || stored.metricsFailure !== undefined) {
|
|
578
|
+
throw new Error('Session metrics compaction ownership is unresolved.');
|
|
579
|
+
}
|
|
580
|
+
stored.metrics.pendingCompactionId = operation.id;
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
// No compactor ran. Reconcile a known committed reservation without inventing spend.
|
|
585
|
+
// Unknown outcomes remain fenced and are repaired conservatively on namespace reload.
|
|
586
|
+
if (state.lifecycle !== 'fenced' && stored.metrics.pendingCompactionId === operation.id) {
|
|
587
|
+
try {
|
|
588
|
+
await this.mutateProjection(state, stored, () => {
|
|
589
|
+
delete stored.metrics.pendingCompactionId;
|
|
590
|
+
}, true);
|
|
591
|
+
}
|
|
592
|
+
catch (cleanupError) {
|
|
593
|
+
stored.metricsFailure ??= cleanupError;
|
|
594
|
+
state.lifecycle = 'fenced';
|
|
595
|
+
throw combineErrors([error, cleanupError]);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
stored.metricsCompaction = operation;
|
|
601
|
+
try {
|
|
602
|
+
return await contextCompactor(filteredMessages, filteredEvents, {
|
|
603
|
+
...options,
|
|
604
|
+
...invocation,
|
|
605
|
+
scope: invocation.scope,
|
|
606
|
+
...this.compaction.compactionModel(state, sessionId, ambientContext, options.reason, modelHint),
|
|
607
|
+
abortSignal: options.abortSignal
|
|
608
|
+
? AbortSignal.any([
|
|
609
|
+
options.abortSignal,
|
|
610
|
+
state.compactorLifecycleController.signal,
|
|
611
|
+
stored.compactorLifecycleController.signal,
|
|
612
|
+
])
|
|
613
|
+
: AbortSignal.any([
|
|
614
|
+
state.compactorLifecycleController.signal,
|
|
615
|
+
stored.compactorLifecycleController.signal,
|
|
616
|
+
]),
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
finally {
|
|
620
|
+
try {
|
|
621
|
+
await this.callbacks.settleMetricsOperation(state, stored, operation);
|
|
622
|
+
}
|
|
623
|
+
finally {
|
|
624
|
+
delete stored.metricsCompaction;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
}
|
|
629
|
+
: {}),
|
|
630
|
+
transactionOutcomeErrorProjector: () => 'The model operation failed.',
|
|
631
|
+
onToken: (delta) => this.callbacks.onTextDelta(state, sessionId, delta),
|
|
632
|
+
onReasoningStart: (id) => this.callbacks.onReasoningStart(state, sessionId, id),
|
|
633
|
+
onReasoningDelta: (id, delta) => this.callbacks.onReasoningDelta(state, sessionId, id, delta),
|
|
634
|
+
onReasoningEnd: (id, text) => this.callbacks.onReasoningEnd(state, sessionId, id, text),
|
|
635
|
+
onToolCallStart: (event) => this.callbacks.onToolStart(state, sessionId, event),
|
|
636
|
+
onToolCallUpdate: (event) => this.callbacks.onToolUpdate(state, sessionId, event),
|
|
637
|
+
onToolCallFinish: (event) => this.callbacks.onToolFinish(state, sessionId, event),
|
|
638
|
+
onRetry: (event) => this.callbacks.onRetry(state, sessionId, event),
|
|
639
|
+
onUsage: (event) => this.callbacks.onModelCallUsage(state, stored, event),
|
|
640
|
+
};
|
|
641
|
+
stored.agentSession = await this.compaction.withCompactorContext(compactorContext, () => plugins.AgentSession.create(agentSessionOptions));
|
|
642
|
+
return stored;
|
|
643
|
+
}
|
|
644
|
+
catch (error) {
|
|
645
|
+
const cleanupErrors = [];
|
|
646
|
+
let executionContextClosed = true;
|
|
647
|
+
if (executionContextHandle && typeof executionContextHandle.close === 'function') {
|
|
648
|
+
try {
|
|
649
|
+
await executionContextHandle.close();
|
|
650
|
+
}
|
|
651
|
+
catch (closeError) {
|
|
652
|
+
executionContextClosed = false;
|
|
653
|
+
this.lifecycle.orphanedExecutionContexts.set(executionContextHandle, {
|
|
654
|
+
storageKey: state.storageKey,
|
|
655
|
+
sessionId,
|
|
656
|
+
});
|
|
657
|
+
cleanupErrors.push(closeError);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
try {
|
|
661
|
+
await this.lifecycle.releasePartialProviderSession('agentEvents', state.storageKey, sessionId);
|
|
662
|
+
}
|
|
663
|
+
catch (releaseError) {
|
|
664
|
+
cleanupErrors.push(releaseError);
|
|
665
|
+
}
|
|
666
|
+
if (executionContextClosed) {
|
|
667
|
+
try {
|
|
668
|
+
await this.lifecycle.releasePartialProviderSession('jobs', state.storageKey, sessionId);
|
|
669
|
+
}
|
|
670
|
+
catch (releaseError) {
|
|
671
|
+
cleanupErrors.push(releaseError);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
this.lifecycle.retainPartialProviderSession('jobs', state.storageKey, sessionId);
|
|
676
|
+
}
|
|
677
|
+
throw cleanupErrors.length === 0 ? error : combineErrors([error, ...cleanupErrors]);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
async repairLoadedSession(storageKey, stored, state, scopeId, scope) {
|
|
681
|
+
if (stored.session.origin !== undefined) {
|
|
682
|
+
this.assertImportedSessionState(stored);
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
const beforeProjection = JSON.stringify({
|
|
686
|
+
messages: stored.messages,
|
|
687
|
+
stagedTerminals: stored.stagedTerminals,
|
|
688
|
+
reversionSegments: stored.reversionSegments,
|
|
689
|
+
revertCursor: stored.revertCursor,
|
|
690
|
+
excludedRunIds: stored.excludedRunIds,
|
|
691
|
+
pendingReversion: stored.pendingReversion,
|
|
692
|
+
pendingReversionReleases: stored.pendingReversionReleases,
|
|
693
|
+
});
|
|
694
|
+
const beforeSession = JSON.stringify(stored.session);
|
|
695
|
+
if (!this.turnReversionProvider
|
|
696
|
+
&& (stored.reversionSegments.some((segment) => segment.captureId)
|
|
697
|
+
|| stored.pendingReversionReleases.length > 0
|
|
698
|
+
|| stored.pendingReversion?.kind === 'capture')) {
|
|
699
|
+
throw new FlexHarnessValidationError('Capture-backed session recovery requires its turn reversion provider.');
|
|
700
|
+
}
|
|
701
|
+
const requiredProtocols = new Set([
|
|
702
|
+
...stored.reversionSegments
|
|
703
|
+
.filter((segment) => segment.captureId !== undefined)
|
|
704
|
+
.map((segment) => segment.protocolVersion),
|
|
705
|
+
...stored.pendingReversionReleases.map((release) => release.protocolVersion),
|
|
706
|
+
...(stored.pendingReversion?.kind === 'capture'
|
|
707
|
+
? [stored.pendingReversion.protocolVersion]
|
|
708
|
+
: []),
|
|
709
|
+
]);
|
|
710
|
+
const providerProtocol = this.reversions.reversionProviderProtocolVersion();
|
|
711
|
+
if (requiredProtocols.size > 0 && (requiredProtocols.size !== 1
|
|
712
|
+
|| !requiredProtocols.has(providerProtocol ?? 0))) {
|
|
713
|
+
throw new FlexHarnessValidationError(`Capture-backed session recovery requires protocolVersion ${[...requiredProtocols].join(', ')}.`);
|
|
714
|
+
}
|
|
715
|
+
if (stored.pendingReversion?.kind === 'capture' && stored.pendingReversionReleases.length > 0) {
|
|
716
|
+
if (!state || scopeId === undefined || scope === undefined) {
|
|
717
|
+
throw new FlexHarnessValidationError('Pending capture recovery is missing its scope context.');
|
|
718
|
+
}
|
|
719
|
+
await this.reversions.drainReversionReleases(state, stored, scopeId, scope, false);
|
|
720
|
+
this.assertStateAcceptingWork(state);
|
|
721
|
+
}
|
|
722
|
+
const outcomes = this.canonicalOutcomes(stored.agentSession.getEvents());
|
|
723
|
+
const firstHiddenCandidate = this.reversions.completedReversionCandidates(stored)[stored.revertCursor];
|
|
724
|
+
const reversionVisibilityBoundary = firstHiddenCandidate
|
|
725
|
+
? stored.reversionSegments.findIndex((segment) => segment.runId === firstHiddenCandidate.runId)
|
|
726
|
+
: stored.reversionSegments.length;
|
|
727
|
+
const stages = new Map(stored.stagedTerminals.map((terminal) => [terminal.runId, terminal]));
|
|
728
|
+
const runIds = new Set([
|
|
729
|
+
...stored.messages.map((message) => message.runId),
|
|
730
|
+
...stored.stagedTerminals.map((terminal) => terminal.runId),
|
|
731
|
+
]);
|
|
732
|
+
let latestTerminal;
|
|
733
|
+
for (const runId of runIds) {
|
|
734
|
+
const outcome = outcomes.get(runId);
|
|
735
|
+
const stage = stages.get(runId);
|
|
736
|
+
if (outcome === 'accepted' && stage?.status === 'completed') {
|
|
737
|
+
this.runs.replaceVisibleRun(stored, stage);
|
|
738
|
+
latestTerminal = stage;
|
|
739
|
+
}
|
|
740
|
+
else if (outcome !== 'accepted') {
|
|
741
|
+
const visible = stored.messages.filter((message) => message.runId === runId);
|
|
742
|
+
if (visible.length > 0 || stage) {
|
|
743
|
+
const status = outcome === 'rejected' ? 'failed' : 'cancelled';
|
|
744
|
+
const terminal = this.repairTerminal(stored.session.sessionId, runId, visible, stage, status);
|
|
745
|
+
this.runs.replaceVisibleRun(stored, terminal);
|
|
746
|
+
latestTerminal = terminal;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
const visibleSuccess = stored.messages.some((message) => message.runId === runId && message.status === 'completed');
|
|
751
|
+
if (visibleSuccess) {
|
|
752
|
+
latestTerminal = this.repairTerminal(stored.session.sessionId, runId, stored.messages.filter((message) => message.runId === runId), undefined, 'completed');
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
stored.stagedTerminals = stored.stagedTerminals.filter((terminal) => !outcomes.has(terminal.runId));
|
|
757
|
+
if (stored.stagedTerminals.length > 0)
|
|
758
|
+
stored.stagedTerminals = [];
|
|
759
|
+
const activeEvents = stored.agentSession.getEvents();
|
|
760
|
+
const activeEventIds = new Set(activeEvents.map((event) => event.id));
|
|
761
|
+
for (let index = 0; index < stored.reversionSegments.length; index++) {
|
|
762
|
+
const segment = stored.reversionSegments[index];
|
|
763
|
+
if (segment.eventIds.length > 0 && !segment.eventIds.some((id) => activeEventIds.has(id))) {
|
|
764
|
+
segment.contextAvailable = false;
|
|
765
|
+
}
|
|
766
|
+
if (segment.status !== 'capturing') {
|
|
767
|
+
const outcome = outcomes.get(segment.runId);
|
|
768
|
+
if (outcome === 'accepted')
|
|
769
|
+
segment.status = 'completed';
|
|
770
|
+
else if (outcome === 'rejected')
|
|
771
|
+
segment.status = 'failed';
|
|
772
|
+
else if (outcome === 'interrupted' || segment.contextAvailable)
|
|
773
|
+
segment.status = 'cancelled';
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
stored.revertCursor = stored.reversionSegments
|
|
777
|
+
.slice(0, reversionVisibilityBoundary)
|
|
778
|
+
.filter((segment) => segment.status === 'completed')
|
|
779
|
+
.length;
|
|
780
|
+
this.reversions.commitArchivedHiddenBranchState(stored);
|
|
781
|
+
this.reversions.pruneReversionState(stored, false, true);
|
|
782
|
+
if (stored.pendingReversion?.kind === 'apply') {
|
|
783
|
+
if (!state || scopeId === undefined || scope === undefined) {
|
|
784
|
+
throw new FlexHarnessValidationError('Pending reversion recovery is missing its scope context.');
|
|
785
|
+
}
|
|
786
|
+
await this.reversions.resumePendingApply(state, stored, scopeId, scope);
|
|
787
|
+
}
|
|
788
|
+
else if (stored.pendingReversion?.kind === 'capture') {
|
|
789
|
+
if (!this.turnReversionProvider || !state || scopeId === undefined || scope === undefined) {
|
|
790
|
+
throw new FlexHarnessValidationError('Pending capture recovery requires its reversion provider.');
|
|
791
|
+
}
|
|
792
|
+
await this.reversions.recoverPendingCapture(state, stored, scopeId, scope, outcomes);
|
|
793
|
+
}
|
|
794
|
+
if (latestTerminal) {
|
|
795
|
+
const completedAt = latestTerminal.assistantMessage.completedAt ?? new Date().toISOString();
|
|
796
|
+
stored.session.status = latestTerminal.status === 'completed' ? 'idle' : latestTerminal.status;
|
|
797
|
+
stored.session.activity = {
|
|
798
|
+
runId: latestTerminal.runId,
|
|
799
|
+
status: latestTerminal.status === 'completed' ? 'idle' : latestTerminal.status,
|
|
800
|
+
completedAt,
|
|
801
|
+
...terminalActivityError(latestTerminal.assistantMessage),
|
|
802
|
+
};
|
|
803
|
+
stored.session.updatedAt = completedAt;
|
|
804
|
+
}
|
|
805
|
+
else if (['scheduled', 'running', 'waiting_permission'].includes(stored.session.status)) {
|
|
806
|
+
const timestamp = new Date().toISOString();
|
|
807
|
+
stored.session.status = 'cancelled';
|
|
808
|
+
stored.session.activity = {
|
|
809
|
+
...(stored.session.activity.runId ? { runId: stored.session.activity.runId } : {}),
|
|
810
|
+
status: 'cancelled',
|
|
811
|
+
completedAt: timestamp,
|
|
812
|
+
error: repairCancellationMessage,
|
|
813
|
+
};
|
|
814
|
+
stored.session.updatedAt = timestamp;
|
|
815
|
+
}
|
|
816
|
+
const projectionChanged = beforeProjection !== JSON.stringify({
|
|
817
|
+
messages: stored.messages,
|
|
818
|
+
stagedTerminals: stored.stagedTerminals,
|
|
819
|
+
reversionSegments: stored.reversionSegments,
|
|
820
|
+
revertCursor: stored.revertCursor,
|
|
821
|
+
excludedRunIds: stored.excludedRunIds,
|
|
822
|
+
pendingReversion: stored.pendingReversion,
|
|
823
|
+
pendingReversionReleases: stored.pendingReversionReleases,
|
|
824
|
+
});
|
|
825
|
+
if (projectionChanged) {
|
|
826
|
+
const expected = stored.projectionRevision;
|
|
827
|
+
const snapshot = this.createProjectionSnapshot(stored, expected + 1);
|
|
828
|
+
await this.stores.projections.save(storageKey, stored.session.sessionId, snapshot, expected);
|
|
829
|
+
stored.projectionSchemaVersion = 3;
|
|
830
|
+
delete stored.projectionBaseline;
|
|
831
|
+
stored.projectionReconciliationRequired = false;
|
|
832
|
+
stored.projectionRevision = snapshot.revision;
|
|
833
|
+
}
|
|
834
|
+
return beforeSession !== JSON.stringify(stored.session);
|
|
835
|
+
}
|
|
836
|
+
repairTerminal(sessionId, runId, visible, stage, status) {
|
|
837
|
+
const timestamp = new Date().toISOString();
|
|
838
|
+
// A steered run projects its prompt first and its steers after it; its last assistant
|
|
839
|
+
// message is the one that was still answering.
|
|
840
|
+
const sourceUser = stage?.userMessage
|
|
841
|
+
?? visible.find((message) => message.role === 'user' && message.steerId === undefined);
|
|
842
|
+
const sourceAssistant = stage?.assistantMessage
|
|
843
|
+
?? [...visible].reverse().find((message) => message.role === 'assistant');
|
|
844
|
+
const userMessage = cloneSerializable(sourceUser ?? {
|
|
845
|
+
messageId: plugins.crypto.randomUUID(),
|
|
846
|
+
sessionId,
|
|
847
|
+
runId,
|
|
848
|
+
role: 'user',
|
|
849
|
+
status,
|
|
850
|
+
createdAt: timestamp,
|
|
851
|
+
parts: [],
|
|
852
|
+
});
|
|
853
|
+
const assistantMessage = cloneSerializable(sourceAssistant ?? {
|
|
854
|
+
messageId: plugins.crypto.randomUUID(),
|
|
855
|
+
sessionId,
|
|
856
|
+
runId,
|
|
857
|
+
role: 'assistant',
|
|
858
|
+
status,
|
|
859
|
+
createdAt: timestamp,
|
|
860
|
+
parts: [],
|
|
861
|
+
});
|
|
862
|
+
userMessage.status = status;
|
|
863
|
+
assistantMessage.status = status;
|
|
864
|
+
userMessage.completedAt ??= timestamp;
|
|
865
|
+
assistantMessage.completedAt ??= timestamp;
|
|
866
|
+
for (const part of assistantMessage.parts) {
|
|
867
|
+
if (part.type === 'reasoning' && part.status === 'running') {
|
|
868
|
+
part.status = status === 'completed' ? 'completed' : 'cancelled';
|
|
869
|
+
part.completedAt = assistantMessage.completedAt;
|
|
870
|
+
}
|
|
871
|
+
if (part.type === 'tool' && part.status === 'running') {
|
|
872
|
+
part.status = status === 'cancelled' ? 'cancelled' : 'failed';
|
|
873
|
+
part.error = status === 'cancelled' ? repairCancellationMessage : externalErrorFallback.message;
|
|
874
|
+
part.completedAt = assistantMessage.completedAt;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (status !== 'completed') {
|
|
878
|
+
const message = status === 'cancelled' ? repairCancellationMessage : externalErrorFallback.message;
|
|
879
|
+
userMessage.error = message;
|
|
880
|
+
assistantMessage.error = message;
|
|
881
|
+
if (stage?.usage) {
|
|
882
|
+
assistantMessage.usage = cloneSerializable(stage.usage);
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
delete assistantMessage.usage;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return {
|
|
889
|
+
runId,
|
|
890
|
+
status,
|
|
891
|
+
userMessage,
|
|
892
|
+
assistantMessage,
|
|
893
|
+
...(status === 'completed' && stage?.model ? { model: stage.model } : {}),
|
|
894
|
+
...(stage?.usage ? { usage: stage.usage } : {}),
|
|
895
|
+
...(status === 'completed' && stage?.finishReason ? { finishReason: stage.finishReason } : {}),
|
|
896
|
+
...(status === 'completed' && stage?.steps !== undefined ? { steps: stage.steps } : {}),
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
withScopeMutationOwnership(state, operation) {
|
|
900
|
+
const owned = state.scopeQueue.then(async () => {
|
|
901
|
+
this.assertStateAcceptingWork(state);
|
|
902
|
+
return operation();
|
|
903
|
+
});
|
|
904
|
+
state.scopeQueue = owned.then(() => undefined, () => undefined);
|
|
905
|
+
return owned;
|
|
906
|
+
}
|
|
907
|
+
mutateScope(state, mutation, allowDuringDrain = false) {
|
|
908
|
+
const operation = state.scopeQueue.then(() => {
|
|
909
|
+
if (!allowDuringDrain)
|
|
910
|
+
this.assertStateAcceptingWork(state);
|
|
911
|
+
return this.mutateScopeOwned(state, mutation);
|
|
912
|
+
});
|
|
913
|
+
state.scopeQueue = operation.then(() => undefined, () => undefined);
|
|
914
|
+
return operation;
|
|
915
|
+
}
|
|
916
|
+
async mutateScopeOwned(state, mutation) {
|
|
917
|
+
const beforeRevision = state.revision;
|
|
918
|
+
const beforeSessions = new Map([...state.sessions].map(([id, stored]) => [id, {
|
|
919
|
+
stored,
|
|
920
|
+
metadata: cloneSerializable(stored.session),
|
|
921
|
+
}]));
|
|
922
|
+
const beforeTombstones = new Map([...state.tombstones].map(([id, value]) => [id, cloneSerializable(value)]));
|
|
923
|
+
const beforeRetainedCleanups = new Map(state.retainedSessionCleanups);
|
|
924
|
+
const beforeSnapshot = {
|
|
925
|
+
schemaVersion: 1,
|
|
926
|
+
revision: beforeRevision,
|
|
927
|
+
sessions: [...beforeSessions.values()]
|
|
928
|
+
.map((entry) => cloneSerializable(entry.metadata))
|
|
929
|
+
.sort((left, right) => left.sessionId.localeCompare(right.sessionId)),
|
|
930
|
+
tombstones: [...beforeTombstones.values()]
|
|
931
|
+
.map((value) => cloneSerializable(value))
|
|
932
|
+
.sort((left, right) => left.sessionId.localeCompare(right.sessionId)),
|
|
933
|
+
};
|
|
934
|
+
const restore = () => {
|
|
935
|
+
state.revision = beforeRevision;
|
|
936
|
+
state.sessions.clear();
|
|
937
|
+
for (const [id, entry] of beforeSessions) {
|
|
938
|
+
entry.stored.session = entry.metadata;
|
|
939
|
+
state.sessions.set(id, entry.stored);
|
|
940
|
+
}
|
|
941
|
+
state.tombstones.clear();
|
|
942
|
+
for (const [id, value] of beforeTombstones)
|
|
943
|
+
state.tombstones.set(id, value);
|
|
944
|
+
state.retainedSessionCleanups.clear();
|
|
945
|
+
for (const [id, retained] of beforeRetainedCleanups) {
|
|
946
|
+
state.retainedSessionCleanups.set(id, retained);
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
let result;
|
|
950
|
+
try {
|
|
951
|
+
result = mutation();
|
|
952
|
+
}
|
|
953
|
+
catch (error) {
|
|
954
|
+
restore();
|
|
955
|
+
throw error;
|
|
956
|
+
}
|
|
957
|
+
const snapshot = this.createScopeSnapshot(state, beforeRevision + 1);
|
|
958
|
+
try {
|
|
959
|
+
await this.stores.scopes.save(state.storageKey, snapshot, beforeRevision);
|
|
960
|
+
state.revision = snapshot.revision;
|
|
961
|
+
return result;
|
|
962
|
+
}
|
|
963
|
+
catch (error) {
|
|
964
|
+
if (error instanceof FlexHarnessStoreConflictError) {
|
|
965
|
+
restore();
|
|
966
|
+
throw error;
|
|
967
|
+
}
|
|
968
|
+
if (error instanceof FlexHarnessStoreCommitUncertainError) {
|
|
969
|
+
state.revision = snapshot.revision;
|
|
970
|
+
state.lifecycle = 'fenced';
|
|
971
|
+
throw error;
|
|
972
|
+
}
|
|
973
|
+
let current;
|
|
974
|
+
let reconciliationError;
|
|
975
|
+
try {
|
|
976
|
+
current = await this.stores.scopes.load(state.storageKey);
|
|
977
|
+
}
|
|
978
|
+
catch (loadError) {
|
|
979
|
+
reconciliationError = loadError;
|
|
980
|
+
}
|
|
981
|
+
if (current && JSON.stringify(current) === JSON.stringify(snapshot)) {
|
|
982
|
+
state.revision = snapshot.revision;
|
|
983
|
+
throw error;
|
|
984
|
+
}
|
|
985
|
+
if ((current === undefined && beforeRevision === 0)
|
|
986
|
+
|| (current !== undefined && JSON.stringify(current) === JSON.stringify(beforeSnapshot))) {
|
|
987
|
+
restore();
|
|
988
|
+
throw error;
|
|
989
|
+
}
|
|
990
|
+
state.revision = snapshot.revision;
|
|
991
|
+
state.lifecycle = 'fenced';
|
|
992
|
+
throw reconciliationError === undefined
|
|
993
|
+
? error
|
|
994
|
+
: combineErrors([error, reconciliationError]);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
mutateProjection(state, stored, mutation, _allowDuringDrain = false) {
|
|
998
|
+
const operation = stored.projectionQueue.then(async () => {
|
|
999
|
+
const beforeRevision = stored.projectionRevision;
|
|
1000
|
+
const beforeSchemaVersion = stored.projectionSchemaVersion;
|
|
1001
|
+
const beforeReconciliationRequired = stored.projectionReconciliationRequired;
|
|
1002
|
+
const beforeBaseline = stored.projectionBaseline === undefined
|
|
1003
|
+
? undefined
|
|
1004
|
+
: cloneSerializable(stored.projectionBaseline);
|
|
1005
|
+
const beforeMetrics = cloneSerializable(stored.metrics);
|
|
1006
|
+
const beforeMessages = cloneSerializable(stored.messages);
|
|
1007
|
+
const beforeStages = cloneSerializable(stored.stagedTerminals);
|
|
1008
|
+
const beforeSegments = cloneSerializable(stored.reversionSegments);
|
|
1009
|
+
const beforeCursor = stored.revertCursor;
|
|
1010
|
+
const beforeExcludedRunIds = cloneSerializable(stored.excludedRunIds);
|
|
1011
|
+
const beforePendingReversion = stored.pendingReversion === undefined
|
|
1012
|
+
? undefined
|
|
1013
|
+
: cloneSerializable(stored.pendingReversion);
|
|
1014
|
+
const beforePendingReversionReleases = cloneSerializable(stored.pendingReversionReleases);
|
|
1015
|
+
const beforeSnapshot = beforeBaseline ?? {
|
|
1016
|
+
schemaVersion: 3,
|
|
1017
|
+
revision: beforeRevision,
|
|
1018
|
+
metrics: cloneSerializable(beforeMetrics),
|
|
1019
|
+
messages: cloneSerializable(beforeMessages),
|
|
1020
|
+
stagedTerminals: cloneSerializable(beforeStages),
|
|
1021
|
+
reversionSegments: cloneSerializable(beforeSegments),
|
|
1022
|
+
revertCursor: beforeCursor,
|
|
1023
|
+
excludedRunIds: cloneSerializable(beforeExcludedRunIds),
|
|
1024
|
+
...(beforePendingReversion === undefined
|
|
1025
|
+
? {}
|
|
1026
|
+
: { pendingReversion: cloneSerializable(beforePendingReversion) }),
|
|
1027
|
+
pendingReversionReleases: cloneSerializable(beforePendingReversionReleases),
|
|
1028
|
+
};
|
|
1029
|
+
const restore = () => {
|
|
1030
|
+
stored.projectionSchemaVersion = beforeSchemaVersion;
|
|
1031
|
+
stored.projectionReconciliationRequired = beforeReconciliationRequired;
|
|
1032
|
+
if (beforeBaseline === undefined)
|
|
1033
|
+
delete stored.projectionBaseline;
|
|
1034
|
+
else
|
|
1035
|
+
stored.projectionBaseline = beforeBaseline;
|
|
1036
|
+
stored.projectionRevision = beforeRevision;
|
|
1037
|
+
stored.metrics = beforeMetrics;
|
|
1038
|
+
stored.messages = beforeMessages;
|
|
1039
|
+
stored.stagedTerminals = beforeStages;
|
|
1040
|
+
stored.reversionSegments = beforeSegments;
|
|
1041
|
+
stored.revertCursor = beforeCursor;
|
|
1042
|
+
stored.excludedRunIds = beforeExcludedRunIds;
|
|
1043
|
+
if (beforePendingReversion === undefined)
|
|
1044
|
+
delete stored.pendingReversion;
|
|
1045
|
+
else
|
|
1046
|
+
stored.pendingReversion = beforePendingReversion;
|
|
1047
|
+
stored.pendingReversionReleases = beforePendingReversionReleases;
|
|
1048
|
+
};
|
|
1049
|
+
let result;
|
|
1050
|
+
try {
|
|
1051
|
+
result = mutation();
|
|
1052
|
+
}
|
|
1053
|
+
catch (error) {
|
|
1054
|
+
restore();
|
|
1055
|
+
throw error;
|
|
1056
|
+
}
|
|
1057
|
+
const snapshot = this.createProjectionSnapshot(stored, beforeRevision + 1);
|
|
1058
|
+
try {
|
|
1059
|
+
await this.stores.projections.save(state.storageKey, stored.session.sessionId, snapshot, beforeRevision);
|
|
1060
|
+
stored.projectionSchemaVersion = 3;
|
|
1061
|
+
delete stored.projectionBaseline;
|
|
1062
|
+
stored.projectionReconciliationRequired = false;
|
|
1063
|
+
stored.projectionRevision = snapshot.revision;
|
|
1064
|
+
return result;
|
|
1065
|
+
}
|
|
1066
|
+
catch (error) {
|
|
1067
|
+
if (error instanceof FlexHarnessStoreConflictError) {
|
|
1068
|
+
restore();
|
|
1069
|
+
throw error;
|
|
1070
|
+
}
|
|
1071
|
+
if (error instanceof FlexHarnessStoreCommitUncertainError) {
|
|
1072
|
+
stored.projectionSchemaVersion = 3;
|
|
1073
|
+
stored.projectionReconciliationRequired = true;
|
|
1074
|
+
stored.projectionRevision = snapshot.revision;
|
|
1075
|
+
state.lifecycle = 'fenced';
|
|
1076
|
+
throw error;
|
|
1077
|
+
}
|
|
1078
|
+
let current;
|
|
1079
|
+
let reconciliationError;
|
|
1080
|
+
try {
|
|
1081
|
+
current = await this.stores.projections.load(state.storageKey, stored.session.sessionId);
|
|
1082
|
+
}
|
|
1083
|
+
catch (loadError) {
|
|
1084
|
+
reconciliationError = loadError;
|
|
1085
|
+
}
|
|
1086
|
+
if (current && JSON.stringify(current) === JSON.stringify(snapshot)) {
|
|
1087
|
+
stored.projectionSchemaVersion = 3;
|
|
1088
|
+
delete stored.projectionBaseline;
|
|
1089
|
+
stored.projectionReconciliationRequired = false;
|
|
1090
|
+
stored.projectionRevision = snapshot.revision;
|
|
1091
|
+
throw error;
|
|
1092
|
+
}
|
|
1093
|
+
if ((current === undefined && beforeRevision === 0)
|
|
1094
|
+
|| (current !== undefined && JSON.stringify(current) === JSON.stringify(beforeSnapshot))) {
|
|
1095
|
+
restore();
|
|
1096
|
+
throw error;
|
|
1097
|
+
}
|
|
1098
|
+
stored.projectionSchemaVersion = 3;
|
|
1099
|
+
stored.projectionReconciliationRequired = true;
|
|
1100
|
+
stored.projectionRevision = snapshot.revision;
|
|
1101
|
+
state.lifecycle = 'fenced';
|
|
1102
|
+
throw reconciliationError === undefined
|
|
1103
|
+
? error
|
|
1104
|
+
: combineErrors([error, reconciliationError]);
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
stored.projectionQueue = operation.then(() => undefined, () => undefined);
|
|
1108
|
+
return operation;
|
|
1109
|
+
}
|
|
1110
|
+
createScopeSnapshot(state, revision) {
|
|
1111
|
+
return {
|
|
1112
|
+
schemaVersion: 1,
|
|
1113
|
+
revision,
|
|
1114
|
+
sessions: [...state.sessions.values()]
|
|
1115
|
+
.map((stored) => cloneSerializable(stored.session))
|
|
1116
|
+
.sort((left, right) => left.sessionId.localeCompare(right.sessionId)),
|
|
1117
|
+
tombstones: [...state.tombstones.values()]
|
|
1118
|
+
.map((value) => cloneSerializable(value))
|
|
1119
|
+
.sort((left, right) => left.sessionId.localeCompare(right.sessionId)),
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
createProjectionSnapshot(stored, revision) {
|
|
1123
|
+
return {
|
|
1124
|
+
schemaVersion: 3,
|
|
1125
|
+
revision,
|
|
1126
|
+
metrics: cloneSerializable(stored.metrics),
|
|
1127
|
+
messages: cloneSerializable(stored.messages),
|
|
1128
|
+
stagedTerminals: cloneSerializable(stored.stagedTerminals),
|
|
1129
|
+
reversionSegments: cloneSerializable(stored.reversionSegments),
|
|
1130
|
+
revertCursor: stored.revertCursor,
|
|
1131
|
+
excludedRunIds: cloneSerializable(stored.excludedRunIds),
|
|
1132
|
+
...(stored.pendingReversion === undefined
|
|
1133
|
+
? {}
|
|
1134
|
+
: { pendingReversion: cloneSerializable(stored.pendingReversion) }),
|
|
1135
|
+
pendingReversionReleases: cloneSerializable(stored.pendingReversionReleases),
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
upgradeProjectionSnapshot(projection) {
|
|
1139
|
+
if (projection.schemaVersion === 3)
|
|
1140
|
+
return cloneSerializable(projection);
|
|
1141
|
+
if (projection.schemaVersion === 1) {
|
|
1142
|
+
return {
|
|
1143
|
+
schemaVersion: 3,
|
|
1144
|
+
revision: projection.revision,
|
|
1145
|
+
messages: cloneSerializable(projection.messages),
|
|
1146
|
+
stagedTerminals: cloneSerializable(projection.stagedTerminals),
|
|
1147
|
+
reversionSegments: [],
|
|
1148
|
+
revertCursor: 0,
|
|
1149
|
+
excludedRunIds: [],
|
|
1150
|
+
pendingReversionReleases: [],
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
return {
|
|
1154
|
+
schemaVersion: 3,
|
|
1155
|
+
revision: projection.revision,
|
|
1156
|
+
messages: cloneSerializable(projection.messages),
|
|
1157
|
+
stagedTerminals: cloneSerializable(projection.stagedTerminals),
|
|
1158
|
+
reversionSegments: projection.reversionSegments.map((segment) => ({
|
|
1159
|
+
...cloneSerializable(segment),
|
|
1160
|
+
protocolVersion: 1,
|
|
1161
|
+
provenance: segment.workspaceCaptured ? 'workspace' : 'transcript',
|
|
1162
|
+
...(segment.workspaceCaptured
|
|
1163
|
+
? { disposition: segment.status === 'capturing' ? 'pending' : 'revertible' }
|
|
1164
|
+
: {}),
|
|
1165
|
+
})),
|
|
1166
|
+
revertCursor: projection.revertCursor,
|
|
1167
|
+
excludedRunIds: cloneSerializable(projection.excludedRunIds),
|
|
1168
|
+
...(projection.pendingReversion === undefined
|
|
1169
|
+
? {}
|
|
1170
|
+
: {
|
|
1171
|
+
pendingReversion: projection.pendingReversion.kind === 'capture'
|
|
1172
|
+
? { ...cloneSerializable(projection.pendingReversion), protocolVersion: 1 }
|
|
1173
|
+
: cloneSerializable(projection.pendingReversion),
|
|
1174
|
+
}),
|
|
1175
|
+
pendingReversionReleases: projection.pendingReversionReleases.map((release) => ({
|
|
1176
|
+
...cloneSerializable(release),
|
|
1177
|
+
protocolVersion: 1,
|
|
1178
|
+
})),
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
async reconcileProjectionFromStore(stored) {
|
|
1182
|
+
if (!stored.projectionReconciliationRequired)
|
|
1183
|
+
return;
|
|
1184
|
+
const projection = await this.stores.projections.load(stored.storageKey, stored.session.sessionId);
|
|
1185
|
+
if (!projection) {
|
|
1186
|
+
throw new FlexHarnessValidationError('Uncertain projection persistence could not be reloaded.');
|
|
1187
|
+
}
|
|
1188
|
+
const current = this.upgradeProjectionSnapshot(projection);
|
|
1189
|
+
stored.messages = current.messages;
|
|
1190
|
+
stored.stagedTerminals = current.stagedTerminals;
|
|
1191
|
+
stored.reversionSegments = current.reversionSegments;
|
|
1192
|
+
stored.revertCursor = current.revertCursor;
|
|
1193
|
+
stored.excludedRunIds = current.excludedRunIds;
|
|
1194
|
+
if (current.pendingReversion === undefined)
|
|
1195
|
+
delete stored.pendingReversion;
|
|
1196
|
+
else
|
|
1197
|
+
stored.pendingReversion = current.pendingReversion;
|
|
1198
|
+
stored.pendingReversionReleases = current.pendingReversionReleases;
|
|
1199
|
+
if (projection.schemaVersion === 3)
|
|
1200
|
+
delete stored.projectionBaseline;
|
|
1201
|
+
else
|
|
1202
|
+
stored.projectionBaseline = cloneSerializable(projection);
|
|
1203
|
+
stored.projectionSchemaVersion = projection.schemaVersion;
|
|
1204
|
+
stored.projectionRevision = projection.revision;
|
|
1205
|
+
stored.projectionReconciliationRequired = false;
|
|
1206
|
+
}
|
|
1207
|
+
sessionsAreDependencyRelated(state, leftSessionId, rightSessionId) {
|
|
1208
|
+
return this.isSessionAncestor(state, leftSessionId, rightSessionId)
|
|
1209
|
+
|| this.isSessionAncestor(state, rightSessionId, leftSessionId);
|
|
1210
|
+
}
|
|
1211
|
+
isSessionAncestor(state, ancestorSessionId, descendantSessionId) {
|
|
1212
|
+
const visited = new Set();
|
|
1213
|
+
let currentId = descendantSessionId;
|
|
1214
|
+
while (currentId) {
|
|
1215
|
+
if (visited.has(currentId))
|
|
1216
|
+
return false;
|
|
1217
|
+
visited.add(currentId);
|
|
1218
|
+
const parentSessionId = this.sessionParentSessionId(state, currentId);
|
|
1219
|
+
if (parentSessionId === ancestorSessionId)
|
|
1220
|
+
return true;
|
|
1221
|
+
currentId = parentSessionId;
|
|
1222
|
+
}
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
sessionAncestryDepth(state, sessionId) {
|
|
1226
|
+
const visited = new Set();
|
|
1227
|
+
let currentId = sessionId;
|
|
1228
|
+
let depth = 0;
|
|
1229
|
+
while (currentId) {
|
|
1230
|
+
if (visited.has(currentId))
|
|
1231
|
+
return depth;
|
|
1232
|
+
visited.add(currentId);
|
|
1233
|
+
const parentSessionId = this.sessionParentSessionId(state, currentId);
|
|
1234
|
+
if (!parentSessionId)
|
|
1235
|
+
return depth;
|
|
1236
|
+
depth++;
|
|
1237
|
+
currentId = parentSessionId;
|
|
1238
|
+
}
|
|
1239
|
+
return depth;
|
|
1240
|
+
}
|
|
1241
|
+
sessionParentSessionId(state, sessionId) {
|
|
1242
|
+
return this.sessionMetadata(state, sessionId)?.parentSessionId
|
|
1243
|
+
?? state.tombstones.get(sessionId)?.parentSessionId;
|
|
1244
|
+
}
|
|
1245
|
+
sessionMetadata(state, sessionId) {
|
|
1246
|
+
return state.sessions.get(sessionId)?.session
|
|
1247
|
+
?? state.retainedSessionCleanups.get(sessionId)?.stored.session;
|
|
1248
|
+
}
|
|
1249
|
+
appendUnexpectedErrors(target, error) {
|
|
1250
|
+
if (error instanceof FlexHarnessRunError) {
|
|
1251
|
+
for (const nested of error.errors)
|
|
1252
|
+
this.appendUnexpectedErrors(target, nested);
|
|
1253
|
+
}
|
|
1254
|
+
else if (!isAbortError(error))
|
|
1255
|
+
target.push(error);
|
|
1256
|
+
}
|
|
1257
|
+
async resolveState(scopeId) {
|
|
1258
|
+
this.assertOpen();
|
|
1259
|
+
validateIdentifier(scopeId, 'scopeId');
|
|
1260
|
+
const admission = this.getScopeAdmission(scopeId);
|
|
1261
|
+
if (admission.retiring)
|
|
1262
|
+
throw this.createScopeRetirementError();
|
|
1263
|
+
const generation = admission.generation;
|
|
1264
|
+
admission.inFlightResolvers++;
|
|
1265
|
+
try {
|
|
1266
|
+
const scope = await this.scopeResolver.resolveScope(scopeId);
|
|
1267
|
+
this.assertOpen();
|
|
1268
|
+
if (admission.retiring || admission.generation !== generation)
|
|
1269
|
+
throw this.createScopeRetirementError();
|
|
1270
|
+
validateIdentifier(scope.storageKey, 'resolved storageKey');
|
|
1271
|
+
if (this.lifecycle.storageDrains.has(scope.storageKey))
|
|
1272
|
+
throw this.createScopeRetirementError();
|
|
1273
|
+
let stateLoad = this.stateLoads.get(scope.storageKey);
|
|
1274
|
+
if (!stateLoad) {
|
|
1275
|
+
const orphanErrors = await this.lifecycle.closeOrphanedResources(scope.storageKey);
|
|
1276
|
+
if (orphanErrors.length > 0)
|
|
1277
|
+
throw combineErrors(orphanErrors);
|
|
1278
|
+
this.assertOpen();
|
|
1279
|
+
if (admission.retiring
|
|
1280
|
+
|| admission.generation !== generation
|
|
1281
|
+
|| this.lifecycle.storageDrains.has(scope.storageKey))
|
|
1282
|
+
throw this.createScopeRetirementError();
|
|
1283
|
+
stateLoad = this.stateLoads.get(scope.storageKey);
|
|
1284
|
+
if (!stateLoad) {
|
|
1285
|
+
const compactorLifecycleController = new AbortController();
|
|
1286
|
+
this.lifecycle.storageCompactorLifecycleControllers.set(scope.storageKey, compactorLifecycleController);
|
|
1287
|
+
stateLoad = this.loadState(scope.storageKey, scopeId, scope.scope, compactorLifecycleController);
|
|
1288
|
+
this.stateLoads.set(scope.storageKey, stateLoad);
|
|
1289
|
+
void stateLoad.catch(() => {
|
|
1290
|
+
if (this.stateLoads.get(scope.storageKey) === stateLoad) {
|
|
1291
|
+
this.stateLoads.delete(scope.storageKey);
|
|
1292
|
+
if (this.lifecycle.storageCompactorLifecycleControllers.get(scope.storageKey)
|
|
1293
|
+
=== compactorLifecycleController)
|
|
1294
|
+
this.lifecycle.storageCompactorLifecycleControllers.delete(scope.storageKey);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
const state = await stateLoad;
|
|
1300
|
+
this.assertOpen();
|
|
1301
|
+
if (state.lifecycle === 'fenced') {
|
|
1302
|
+
const drain = this.lifecycle.storageDrains.get(scope.storageKey) ?? this.lifecycle.drainStorage(scope.storageKey, stateLoad, this.trustInternalError(new FlexHarnessAbortError('The session namespace was fenced.')), { scopeId, scope: scope.scope });
|
|
1303
|
+
if (this.commands.ambientSlashCommandOwner({ storageKey: scope.storageKey })) {
|
|
1304
|
+
throw this.createScopeRetirementError();
|
|
1305
|
+
}
|
|
1306
|
+
try {
|
|
1307
|
+
await drain;
|
|
1308
|
+
}
|
|
1309
|
+
catch {
|
|
1310
|
+
// Fenced cleanup ownership remains available to explicit retirement or disposal.
|
|
1311
|
+
}
|
|
1312
|
+
throw this.createScopeRetirementError();
|
|
1313
|
+
}
|
|
1314
|
+
if (admission.retiring
|
|
1315
|
+
|| admission.generation !== generation
|
|
1316
|
+
|| this.lifecycle.storageDrains.has(scope.storageKey)
|
|
1317
|
+
|| state.lifecycle !== 'active')
|
|
1318
|
+
throw this.createScopeRetirementError();
|
|
1319
|
+
return { scope, state };
|
|
1320
|
+
}
|
|
1321
|
+
finally {
|
|
1322
|
+
admission.inFlightResolvers--;
|
|
1323
|
+
this.pruneScopeAdmission(scopeId, admission);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
getScopeAdmission(scopeId) {
|
|
1327
|
+
let admission = this.scopeAdmissions.get(scopeId);
|
|
1328
|
+
if (!admission) {
|
|
1329
|
+
admission = { generation: 0, inFlightResolvers: 0, retiring: false };
|
|
1330
|
+
this.scopeAdmissions.set(scopeId, admission);
|
|
1331
|
+
}
|
|
1332
|
+
return admission;
|
|
1333
|
+
}
|
|
1334
|
+
pruneScopeAdmission(scopeId, admission) {
|
|
1335
|
+
if (!admission.retiring
|
|
1336
|
+
&& admission.inFlightResolvers === 0
|
|
1337
|
+
&& this.scopeAdmissions.get(scopeId) === admission)
|
|
1338
|
+
this.scopeAdmissions.delete(scopeId);
|
|
1339
|
+
}
|
|
1340
|
+
createScopeRetirementError() {
|
|
1341
|
+
return this.trustInternalError(new FlexHarnessAbortError(scopeRetirementMessage));
|
|
1342
|
+
}
|
|
1343
|
+
assertStateAcceptingWork(state) {
|
|
1344
|
+
if (state.lifecycle !== 'active' || this.lifecycle.storageDrains.has(state.storageKey)) {
|
|
1345
|
+
throw this.createScopeRetirementError();
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
requireSession(state, sessionId) {
|
|
1349
|
+
validateIdentifier(sessionId, 'sessionId');
|
|
1350
|
+
requireTransferIdentifier(sessionId, 'sessionId');
|
|
1351
|
+
if (state.tombstones.has(sessionId))
|
|
1352
|
+
throw new FlexHarnessNotFoundError('Session', sessionId);
|
|
1353
|
+
if (state.initializingSessions.has(sessionId)) {
|
|
1354
|
+
throw new FlexHarnessSessionBusyError(sessionId, 'is still being initialized');
|
|
1355
|
+
}
|
|
1356
|
+
const stored = state.sessions.get(sessionId);
|
|
1357
|
+
if (!stored)
|
|
1358
|
+
throw new FlexHarnessNotFoundError('Session', sessionId);
|
|
1359
|
+
return stored;
|
|
1360
|
+
}
|
|
1361
|
+
visibleMessages(stored) {
|
|
1362
|
+
const firstHiddenSegment = this.reversions.reversionGroups(stored)[stored.revertCursor]?.segments[0];
|
|
1363
|
+
if (!firstHiddenSegment)
|
|
1364
|
+
return stored.messages;
|
|
1365
|
+
const boundary = stored.messages.findIndex((message) => message.runId === firstHiddenSegment.runId);
|
|
1366
|
+
return boundary < 0 ? stored.messages : stored.messages.slice(0, boundary);
|
|
1367
|
+
}
|
|
1368
|
+
requireMutableSession(state, sessionId) {
|
|
1369
|
+
const stored = this.requireSession(state, sessionId);
|
|
1370
|
+
const pending = [...state.pendingPermissions.values()].some((entry) => !entry.settled && entry.request.sessionId === sessionId);
|
|
1371
|
+
if (stored.outstandingPromptsById.size > 0 || pending) {
|
|
1372
|
+
throw new FlexHarnessSessionBusyError(sessionId, 'cannot be changed while it has an outstanding prompt or pending permission');
|
|
1373
|
+
}
|
|
1374
|
+
return stored;
|
|
1375
|
+
}
|
|
1376
|
+
/** Refuses an operation that would change an imported session's history or model context. */
|
|
1377
|
+
assertSessionWritable(stored) {
|
|
1378
|
+
if (stored.session.origin !== undefined) {
|
|
1379
|
+
throw this.trustInternalError(new FlexHarnessImportedSessionError(stored.session.sessionId));
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
/** An imported session never ran here, so it has no hidden stage and no reversion state. */
|
|
1383
|
+
assertImportedSessionState(stored) {
|
|
1384
|
+
if (stored.stagedTerminals.length > 0
|
|
1385
|
+
|| stored.reversionSegments.length > 0
|
|
1386
|
+
|| stored.excludedRunIds.length > 0
|
|
1387
|
+
|| stored.pendingReversion !== undefined
|
|
1388
|
+
|| stored.pendingReversionReleases.length > 0
|
|
1389
|
+
|| stored.messages.some((message) => message.status === 'streaming')) {
|
|
1390
|
+
throw new FlexHarnessValidationError(`Imported session "${stored.session.sessionId}" has run state it cannot have.`);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
requireMessage(stored, messageId) {
|
|
1394
|
+
const message = this.visibleMessages(stored).find((entry) => entry.messageId === messageId);
|
|
1395
|
+
if (!message)
|
|
1396
|
+
throw new FlexHarnessNotFoundError('Message', messageId);
|
|
1397
|
+
return message;
|
|
1398
|
+
}
|
|
1399
|
+
isTombstoned(run) {
|
|
1400
|
+
return run.state.tombstones.has(run.sessionId) || run.state.sessions.get(run.sessionId) !== run.stored;
|
|
1401
|
+
}
|
|
1402
|
+
emitPartEvent(run, type, part) {
|
|
1403
|
+
const { messageIndex, partIndex } = this.partEventCoordinates(run, part.partId);
|
|
1404
|
+
this.emitEvent(run.scopeId, run.stored.session, {
|
|
1405
|
+
type,
|
|
1406
|
+
runId: run.runId,
|
|
1407
|
+
messageId: run.assistantMessageId,
|
|
1408
|
+
messageIndex,
|
|
1409
|
+
partId: part.partId,
|
|
1410
|
+
partIndex,
|
|
1411
|
+
part: publicSnapshot(part),
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
emitPartDeltaEvent(run, part, delta, accounting) {
|
|
1415
|
+
const { messageIndex, partIndex } = this.partEventCoordinates(run, part.partId);
|
|
1416
|
+
this.emitEvent(run.scopeId, run.stored.session, {
|
|
1417
|
+
type: 'part.delta',
|
|
1418
|
+
runId: run.runId,
|
|
1419
|
+
messageId: run.assistantMessageId,
|
|
1420
|
+
messageIndex,
|
|
1421
|
+
partId: part.partId,
|
|
1422
|
+
partIndex,
|
|
1423
|
+
partType: part.type,
|
|
1424
|
+
delta,
|
|
1425
|
+
...accounting,
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
partEventCoordinates(run, partId) {
|
|
1429
|
+
const messageIndex = run.stored.messages.findIndex((message) => message.messageId === run.assistantMessageId);
|
|
1430
|
+
const partIndex = run.callbackParts.findIndex((entry) => entry.partId === partId);
|
|
1431
|
+
if (messageIndex < 0
|
|
1432
|
+
|| run.stored.messages[messageIndex]?.messageId !== run.assistantMessageId
|
|
1433
|
+
|| partIndex < 0
|
|
1434
|
+
|| run.callbackParts[partIndex]?.partId !== partId)
|
|
1435
|
+
throw new Error('Flex part event source coordinates are unavailable.');
|
|
1436
|
+
return { messageIndex, partIndex };
|
|
1437
|
+
}
|
|
1438
|
+
emitEvent(scopeId, sourceSession, details) {
|
|
1439
|
+
const generation = requireSessionGeneration(sourceSession);
|
|
1440
|
+
const event = deepFreeze(cloneSerializable({
|
|
1441
|
+
eventId: plugins.crypto.randomUUID(),
|
|
1442
|
+
sequence: ++this.sequence,
|
|
1443
|
+
timestamp: new Date().toISOString(),
|
|
1444
|
+
scopeId,
|
|
1445
|
+
...details,
|
|
1446
|
+
sessionId: sourceSession.sessionId,
|
|
1447
|
+
...generation,
|
|
1448
|
+
}));
|
|
1449
|
+
for (const listener of this.listeners) {
|
|
1450
|
+
try {
|
|
1451
|
+
listener(event);
|
|
1452
|
+
}
|
|
1453
|
+
catch {
|
|
1454
|
+
// Public listener failures are isolated from persistence and run ownership.
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
validateRuntimeEvent(event) {
|
|
1459
|
+
try {
|
|
1460
|
+
assertJsonSerializable(event, '$event');
|
|
1461
|
+
}
|
|
1462
|
+
catch {
|
|
1463
|
+
throw new FlexHarnessValidationError('Runtime event must be JSON-serializable.');
|
|
1464
|
+
}
|
|
1465
|
+
if (!event || typeof event !== 'object' || Array.isArray(event)) {
|
|
1466
|
+
throw new FlexHarnessValidationError('Runtime event must be a plain JSON object.');
|
|
1467
|
+
}
|
|
1468
|
+
validateIdentifier(event.type, 'runtime event type');
|
|
1469
|
+
if (jsonBytes(event) > this.toolOutputLimits.maxBytes) {
|
|
1470
|
+
throw new FlexHarnessValidationError('Runtime event exceeds the byte limit.');
|
|
1471
|
+
}
|
|
1472
|
+
const visit = (value, depth) => {
|
|
1473
|
+
if (!value || typeof value !== 'object')
|
|
1474
|
+
return;
|
|
1475
|
+
if (depth > this.toolOutputLimits.maxDepth) {
|
|
1476
|
+
throw new FlexHarnessValidationError('Runtime event exceeds the depth limit.');
|
|
1477
|
+
}
|
|
1478
|
+
for (const entry of Array.isArray(value) ? value : Object.values(value))
|
|
1479
|
+
visit(entry, depth + 1);
|
|
1480
|
+
};
|
|
1481
|
+
visit(event, 0);
|
|
1482
|
+
}
|
|
1483
|
+
boundedIdentifier(value, name) {
|
|
1484
|
+
validateIdentifier(value, name);
|
|
1485
|
+
requireTransferIdentifier(value, name);
|
|
1486
|
+
return value;
|
|
1487
|
+
}
|
|
1488
|
+
messageCursorNamespace(storageKey) {
|
|
1489
|
+
return plugins.crypto.createHash('sha256').update(storageKey).digest('base64url');
|
|
1490
|
+
}
|
|
1491
|
+
createMessageCursor(namespace, sessionId, anchorMessageId) {
|
|
1492
|
+
const cursor = Buffer.from(JSON.stringify({
|
|
1493
|
+
version: 1,
|
|
1494
|
+
namespace,
|
|
1495
|
+
sessionId,
|
|
1496
|
+
anchorMessageId,
|
|
1497
|
+
})).toString('base64url');
|
|
1498
|
+
if (Buffer.byteLength(cursor, 'utf8') > maxMessagePageCursorBytes) {
|
|
1499
|
+
throw new FlexHarnessValidationError('Message page cursor exceeds its transfer limit.');
|
|
1500
|
+
}
|
|
1501
|
+
return cursor;
|
|
1502
|
+
}
|
|
1503
|
+
parseMessageCursor(cursor) {
|
|
1504
|
+
let parsed;
|
|
1505
|
+
try {
|
|
1506
|
+
const decoded = Buffer.from(cursor, 'base64url');
|
|
1507
|
+
if (decoded.toString('base64url') !== cursor)
|
|
1508
|
+
throw new Error('non-canonical cursor');
|
|
1509
|
+
parsed = JSON.parse(decoded.toString('utf8'));
|
|
1510
|
+
}
|
|
1511
|
+
catch {
|
|
1512
|
+
throw new FlexHarnessValidationError('Message page cursor is invalid.');
|
|
1513
|
+
}
|
|
1514
|
+
if (!parsed
|
|
1515
|
+
|| typeof parsed !== 'object'
|
|
1516
|
+
|| Array.isArray(parsed)
|
|
1517
|
+
|| Object.keys(parsed).length !== 4
|
|
1518
|
+
|| parsed.version !== 1
|
|
1519
|
+
|| typeof parsed.namespace !== 'string'
|
|
1520
|
+
|| typeof parsed.sessionId !== 'string'
|
|
1521
|
+
|| typeof parsed.anchorMessageId !== 'string')
|
|
1522
|
+
throw new FlexHarnessValidationError('Message page cursor is invalid.');
|
|
1523
|
+
const result = parsed;
|
|
1524
|
+
if (!result.namespace
|
|
1525
|
+
|| !result.sessionId
|
|
1526
|
+
|| !result.anchorMessageId
|
|
1527
|
+
|| Buffer.byteLength(result.namespace, 'utf8') > 128
|
|
1528
|
+
|| Buffer.byteLength(result.sessionId, 'utf8') > maxTransferIdentifierBytes
|
|
1529
|
+
|| Buffer.byteLength(result.anchorMessageId, 'utf8') > maxTransferIdentifierBytes)
|
|
1530
|
+
throw new FlexHarnessValidationError('Message page cursor is invalid.');
|
|
1531
|
+
return result;
|
|
1532
|
+
}
|
|
1533
|
+
assertOpen() {
|
|
1534
|
+
if (this.closed)
|
|
1535
|
+
throw new FlexHarnessClosedError();
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mbGV4aGFybmVzcy5jb3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5mbGV4aGFybmVzcy5jb3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsc0JBQXNCLEVBQ3RCLHdCQUF3QixFQUN4QiwrQkFBK0IsRUFDL0Isd0JBQXdCLEVBQ3hCLG1CQUFtQixFQUNuQiwyQkFBMkIsRUFDM0IsNkJBQTZCLEVBQzdCLG9DQUFvQyxFQUNwQywwQkFBMEIsRUFDMUIsbUJBQW1CLEdBQ3BCLE1BQU0sYUFBYSxDQUFDO0FBOEJyQixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRSxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGlCQUFpQixFQUNqQixVQUFVLEVBQ1YsaUJBQWlCLEdBQ2xCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDekQsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixxQkFBcUIsRUFDckIsc0JBQXNCLEVBQ3RCLDJCQUEyQixFQUMzQixrQkFBa0IsRUFDbEIsb0JBQW9CLEVBQ3BCLDZCQUE2QixFQUM3QixxQkFBcUIsRUFDckIsd0JBQXdCLEVBQ3hCLG9DQUFvQyxFQUNwQyxzQkFBc0IsR0FHdkIsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsU0FBUyxFQUNULHlCQUF5QixFQUN6QiwwQkFBMEIsRUFDMUIsY0FBYyxFQUNkLHlCQUF5QixHQUMxQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZGLE9BQU8s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
|