@modelprofile.com/flexharness 2.1.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +66 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.flexharness.d.ts +86 -30
- package/dist_ts/classes.flexharness.js +2593 -1131
- package/dist_ts/classes.stores.d.ts +19 -20
- package/dist_ts/classes.stores.js +968 -75
- package/dist_ts/errors.d.ts +5 -0
- package/dist_ts/errors.js +11 -1
- package/dist_ts/interfaces.d.ts +130 -23
- package/dist_ts/plugins.d.ts +3 -3
- package/dist_ts/plugins.js +3 -3
- package/dist_ts/utils.json.d.ts +4 -2
- package/dist_ts/utils.json.js +283 -140
- package/dist_ts/utils.prompt.d.ts +1 -2
- package/dist_ts/utils.prompt.js +3 -26
- package/dist_ts_migration/index.d.ts +1 -0
- package/dist_ts_migration/index.js +2 -0
- package/dist_ts_migration/v3_legacyflexharness.d.ts +17 -0
- package/dist_ts_migration/v3_legacyflexharness.js +426 -0
- package/package.json +17 -3
- package/readme.hints.md +13 -11
- package/readme.md +94 -27
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.flexharness.ts +2966 -1421
- package/ts/classes.stores.ts +1226 -97
- package/ts/errors.ts +20 -0
- package/ts/interfaces.ts +168 -22
- package/ts/plugins.ts +46 -3
- package/ts/utils.json.ts +341 -154
- package/ts/utils.prompt.ts +6 -27
- package/ts_migration/index.ts +1 -0
- package/ts_migration/v3_legacyflexharness.ts +620 -0
|
@@ -1,24 +1,249 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
-
import { FlexHarnessStoreConflictError, FlexHarnessStoreFormatError, FlexHarnessValidationError, } from './errors.js';
|
|
3
|
-
import {
|
|
4
|
-
function
|
|
5
|
-
|
|
2
|
+
import { FlexHarnessStoreCommitUncertainError, FlexHarnessStoreConflictError, FlexHarnessStoreFormatError, FlexHarnessValidationError, } from './errors.js';
|
|
3
|
+
import { assertFlexPermissionSnapshot, assertFlexProjectionSnapshot, assertFlexScopeSnapshot, assertJsonSerializable, cloneSerializable, } from './utils.json.js';
|
|
4
|
+
function validateIdentifier(value, name) {
|
|
5
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
6
|
+
throw new FlexHarnessValidationError(`${name} must be a non-empty string.`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function validateExpectedRevision(expectedRevision) {
|
|
6
10
|
if (!Number.isSafeInteger(expectedRevision) || expectedRevision < 0) {
|
|
7
11
|
throw new FlexHarnessValidationError('expectedRevision must be a non-negative integer.');
|
|
8
12
|
}
|
|
13
|
+
}
|
|
14
|
+
function validateSnapshotSave(snapshot, expectedRevision, validator) {
|
|
15
|
+
validator(snapshot);
|
|
16
|
+
validateExpectedRevision(expectedRevision);
|
|
9
17
|
if (snapshot.revision !== expectedRevision + 1) {
|
|
10
18
|
throw new FlexHarnessStoreFormatError(`Snapshot revision ${snapshot.revision} must equal expected revision ${expectedRevision} plus one.`);
|
|
11
19
|
}
|
|
12
20
|
return cloneSerializable(snapshot);
|
|
13
21
|
}
|
|
14
|
-
|
|
22
|
+
function providerKey(storageKey, sessionId) {
|
|
23
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
24
|
+
validateIdentifier(sessionId, 'sessionId');
|
|
25
|
+
return JSON.stringify([storageKey, sessionId]);
|
|
26
|
+
}
|
|
27
|
+
function assertProjectionSession(snapshot, sessionId) {
|
|
28
|
+
for (const message of snapshot.messages) {
|
|
29
|
+
if (message.sessionId !== sessionId) {
|
|
30
|
+
throw new FlexHarnessStoreFormatError(`Projection message "${message.messageId}" does not belong to session "${sessionId}".`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const terminal of snapshot.stagedTerminals) {
|
|
34
|
+
if (terminal.userMessage.sessionId !== sessionId
|
|
35
|
+
|| terminal.assistantMessage.sessionId !== sessionId) {
|
|
36
|
+
throw new FlexHarnessStoreFormatError(`Staged terminal "${terminal.runId}" does not belong to session "${sessionId}".`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function normalizeJsonObjectUndefined(value, path = '$') {
|
|
41
|
+
const seen = new WeakSet();
|
|
42
|
+
const visit = (current, currentPath) => {
|
|
43
|
+
if (current === null
|
|
44
|
+
|| typeof current === 'string'
|
|
45
|
+
|| typeof current === 'boolean')
|
|
46
|
+
return current;
|
|
47
|
+
if (typeof current === 'number') {
|
|
48
|
+
if (!Number.isFinite(current)) {
|
|
49
|
+
throw new FlexHarnessStoreFormatError(`${currentPath} contains a non-finite number.`);
|
|
50
|
+
}
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
if (typeof current !== 'object') {
|
|
54
|
+
throw new FlexHarnessStoreFormatError(`${currentPath} contains ${typeof current}, which is not JSON-safe.`);
|
|
55
|
+
}
|
|
56
|
+
if (seen.has(current)) {
|
|
57
|
+
throw new FlexHarnessStoreFormatError(`${currentPath} contains a circular reference.`);
|
|
58
|
+
}
|
|
59
|
+
const prototype = Object.getPrototypeOf(current);
|
|
60
|
+
if (!Array.isArray(current) && prototype !== Object.prototype && prototype !== null) {
|
|
61
|
+
throw new FlexHarnessStoreFormatError(`${currentPath} contains a non-plain object.`);
|
|
62
|
+
}
|
|
63
|
+
if (Object.getOwnPropertySymbols(current).length > 0) {
|
|
64
|
+
throw new FlexHarnessStoreFormatError(`${currentPath} contains a symbol-keyed property.`);
|
|
65
|
+
}
|
|
66
|
+
seen.add(current);
|
|
67
|
+
if (Array.isArray(current)) {
|
|
68
|
+
const result = current.map((entry, index) => {
|
|
69
|
+
if (!(index in current) || entry === undefined) {
|
|
70
|
+
throw new FlexHarnessStoreFormatError(`${currentPath}[${index}] is not JSON-safe.`);
|
|
71
|
+
}
|
|
72
|
+
return visit(entry, `${currentPath}[${index}]`);
|
|
73
|
+
});
|
|
74
|
+
seen.delete(current);
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const key of Object.getOwnPropertyNames(current)) {
|
|
79
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
80
|
+
if (!descriptor.enumerable || !('value' in descriptor)) {
|
|
81
|
+
throw new FlexHarnessStoreFormatError(`${currentPath}.${key} is not a plain JSON property.`);
|
|
82
|
+
}
|
|
83
|
+
if (descriptor.value !== undefined) {
|
|
84
|
+
result[key] = visit(descriptor.value, `${currentPath}.${key}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
seen.delete(current);
|
|
88
|
+
return result;
|
|
89
|
+
};
|
|
90
|
+
const normalized = visit(value, path);
|
|
91
|
+
assertJsonSerializable(normalized, path);
|
|
92
|
+
return normalized;
|
|
93
|
+
}
|
|
94
|
+
function assertNonEmptyString(value, path) {
|
|
95
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
96
|
+
throw new FlexHarnessStoreFormatError(`${path} must be a non-empty string.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function assertNonNegativeInteger(value, path) {
|
|
100
|
+
if (!Number.isSafeInteger(value) || Number(value) < 0) {
|
|
101
|
+
throw new FlexHarnessStoreFormatError(`${path} must be a non-negative integer.`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function assertExactKeys(value, keys, path) {
|
|
105
|
+
const invalidKey = Object.keys(value).find((key) => !keys.includes(key));
|
|
106
|
+
if (invalidKey) {
|
|
107
|
+
throw new FlexHarnessStoreFormatError(`${path}.${invalidKey} is not supported.`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function assertRecord(value, path) {
|
|
111
|
+
if (!value
|
|
112
|
+
|| typeof value !== 'object'
|
|
113
|
+
|| Array.isArray(value)
|
|
114
|
+
|| (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)) {
|
|
115
|
+
throw new FlexHarnessStoreFormatError(`${path} must be a plain object.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function createAgentEventSnapshot(sessionId, events, revision) {
|
|
119
|
+
return {
|
|
120
|
+
schemaVersion: 2,
|
|
121
|
+
sessionId,
|
|
122
|
+
revision,
|
|
123
|
+
updatedAt: events.reduce((latest, event) => Math.max(latest, event.timestamp), 0),
|
|
124
|
+
events: normalizeJsonObjectUndefined([...events], '$events'),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function validateAgentEventSnapshot(value, sessionId) {
|
|
128
|
+
assertJsonSerializable(value, '$snapshot');
|
|
129
|
+
try {
|
|
130
|
+
return plugins.validateAgentEventSnapshotV2(value, sessionId);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
throw new FlexHarnessStoreFormatError(`$snapshot is not a canonical schema-2 Agent event snapshot: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function validateAgentEventArchive(value, sessionId, archiveId) {
|
|
137
|
+
assertJsonSerializable(value, '$archive');
|
|
138
|
+
try {
|
|
139
|
+
return plugins.validateAgentEventArchiveV2(value, sessionId, archiveId);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new FlexHarnessStoreFormatError(`$archive is not a canonical schema-2 Agent event archive: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function validateToolJobSnapshot(value) {
|
|
146
|
+
assertJsonSerializable(value, '$snapshot');
|
|
147
|
+
assertRecord(value, '$snapshot');
|
|
148
|
+
assertExactKeys(value, ['schemaVersion', 'revision', 'updatedAt', 'jobs'], '$snapshot');
|
|
149
|
+
if (value.schemaVersion !== 1) {
|
|
150
|
+
throw new FlexHarnessStoreFormatError('Tool job snapshot schemaVersion must be 1.');
|
|
151
|
+
}
|
|
152
|
+
assertNonNegativeInteger(value.revision, '$snapshot.revision');
|
|
153
|
+
assertNonNegativeInteger(value.updatedAt, '$snapshot.updatedAt');
|
|
154
|
+
if (!Array.isArray(value.jobs)) {
|
|
155
|
+
throw new FlexHarnessStoreFormatError('$snapshot.jobs must be an array.');
|
|
156
|
+
}
|
|
157
|
+
const executionIds = new Set();
|
|
158
|
+
for (let index = 0; index < value.jobs.length; index++) {
|
|
159
|
+
const path = `$snapshot.jobs[${index}]`;
|
|
160
|
+
assertRecord(value.jobs[index], path);
|
|
161
|
+
const job = value.jobs[index];
|
|
162
|
+
assertExactKeys(job, [
|
|
163
|
+
'executionId',
|
|
164
|
+
'type',
|
|
165
|
+
'state',
|
|
166
|
+
'request',
|
|
167
|
+
'exitCode',
|
|
168
|
+
'stdout',
|
|
169
|
+
'stderr',
|
|
170
|
+
'signal',
|
|
171
|
+
'startedAt',
|
|
172
|
+
'updatedAt',
|
|
173
|
+
'finishedAt',
|
|
174
|
+
], path);
|
|
175
|
+
assertNonEmptyString(job.executionId, `${path}.executionId`);
|
|
176
|
+
if (executionIds.has(job.executionId)) {
|
|
177
|
+
throw new FlexHarnessStoreFormatError(`$snapshot.jobs contains duplicate job "${job.executionId}".`);
|
|
178
|
+
}
|
|
179
|
+
executionIds.add(job.executionId);
|
|
180
|
+
assertNonEmptyString(job.type, `${path}.type`);
|
|
181
|
+
if (!['running', 'finished', 'failed', 'aborted'].includes(String(job.state))) {
|
|
182
|
+
throw new FlexHarnessStoreFormatError(`${path}.state is invalid.`);
|
|
183
|
+
}
|
|
184
|
+
if (job.request !== undefined) {
|
|
185
|
+
const requestPath = `${path}.request`;
|
|
186
|
+
assertRecord(job.request, requestPath);
|
|
187
|
+
assertExactKeys(job.request, ['type', 'command', 'cwd', 'timeoutMs', 'metadata'], requestPath);
|
|
188
|
+
assertNonEmptyString(job.request.type, `${requestPath}.type`);
|
|
189
|
+
if (job.request.command !== undefined) {
|
|
190
|
+
const commandPath = `${requestPath}.command`;
|
|
191
|
+
assertRecord(job.request.command, commandPath);
|
|
192
|
+
assertExactKeys(job.request.command, ['executable', 'args'], commandPath);
|
|
193
|
+
assertNonEmptyString(job.request.command.executable, `${commandPath}.executable`);
|
|
194
|
+
if (!Array.isArray(job.request.command.args)) {
|
|
195
|
+
throw new FlexHarnessStoreFormatError(`${commandPath}.args must be an array.`);
|
|
196
|
+
}
|
|
197
|
+
for (let argumentIndex = 0; argumentIndex < job.request.command.args.length; argumentIndex++) {
|
|
198
|
+
if (typeof job.request.command.args[argumentIndex] !== 'string') {
|
|
199
|
+
throw new FlexHarnessStoreFormatError(`${commandPath}.args[${argumentIndex}] must be a string.`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (job.request.cwd !== undefined && typeof job.request.cwd !== 'string') {
|
|
204
|
+
throw new FlexHarnessStoreFormatError(`${requestPath}.cwd must be a string.`);
|
|
205
|
+
}
|
|
206
|
+
if (job.request.timeoutMs !== undefined) {
|
|
207
|
+
assertNonNegativeInteger(job.request.timeoutMs, `${requestPath}.timeoutMs`);
|
|
208
|
+
}
|
|
209
|
+
if (job.request.metadata !== undefined) {
|
|
210
|
+
assertRecord(job.request.metadata, `${requestPath}.metadata`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (job.exitCode !== undefined && job.exitCode !== null && !Number.isSafeInteger(job.exitCode)) {
|
|
214
|
+
throw new FlexHarnessStoreFormatError(`${path}.exitCode must be an integer or null.`);
|
|
215
|
+
}
|
|
216
|
+
for (const key of ['stdout', 'stderr', 'signal']) {
|
|
217
|
+
if (job[key] !== undefined && typeof job[key] !== 'string') {
|
|
218
|
+
throw new FlexHarnessStoreFormatError(`${path}.${key} must be a string.`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const key of ['startedAt', 'updatedAt', 'finishedAt']) {
|
|
222
|
+
if (job[key] !== undefined)
|
|
223
|
+
assertNonNegativeInteger(job[key], `${path}.${key}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return value;
|
|
227
|
+
}
|
|
228
|
+
function createToolJobSnapshot(jobs, revision) {
|
|
229
|
+
const snapshot = {
|
|
230
|
+
schemaVersion: 1,
|
|
231
|
+
revision,
|
|
232
|
+
updatedAt: Date.now(),
|
|
233
|
+
jobs: normalizeJsonObjectUndefined([...jobs], '$jobs'),
|
|
234
|
+
};
|
|
235
|
+
return validateToolJobSnapshot(snapshot);
|
|
236
|
+
}
|
|
237
|
+
class InMemoryScopeStore {
|
|
15
238
|
snapshots = new Map();
|
|
16
239
|
async load(storageKey) {
|
|
240
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
17
241
|
const snapshot = this.snapshots.get(storageKey);
|
|
18
242
|
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
19
243
|
}
|
|
20
244
|
async save(storageKey, snapshot, expectedRevision) {
|
|
21
|
-
|
|
245
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
246
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexScopeSnapshot);
|
|
22
247
|
const actualRevision = this.snapshots.get(storageKey)?.revision ?? 0;
|
|
23
248
|
if (actualRevision !== expectedRevision) {
|
|
24
249
|
throw new FlexHarnessStoreConflictError(storageKey, expectedRevision, actualRevision);
|
|
@@ -26,86 +251,392 @@ export class InMemoryFlexHarnessStore {
|
|
|
26
251
|
this.snapshots.set(storageKey, validated);
|
|
27
252
|
}
|
|
28
253
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
254
|
+
class InMemoryProjectionStore {
|
|
255
|
+
snapshots = new Map();
|
|
256
|
+
async load(storageKey, sessionId) {
|
|
257
|
+
const key = providerKey(storageKey, sessionId);
|
|
258
|
+
const snapshot = this.snapshots.get(key);
|
|
259
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
260
|
+
}
|
|
261
|
+
async save(storageKey, sessionId, snapshot, expectedRevision) {
|
|
262
|
+
const key = providerKey(storageKey, sessionId);
|
|
263
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexProjectionSnapshot);
|
|
264
|
+
assertProjectionSession(validated, sessionId);
|
|
265
|
+
const actualRevision = this.snapshots.get(key)?.revision ?? 0;
|
|
266
|
+
if (actualRevision !== expectedRevision) {
|
|
267
|
+
throw new FlexHarnessStoreConflictError(key, expectedRevision, actualRevision);
|
|
39
268
|
}
|
|
40
|
-
this.
|
|
269
|
+
this.snapshots.set(key, validated);
|
|
41
270
|
}
|
|
42
|
-
async
|
|
43
|
-
|
|
44
|
-
return JsonFileFlexHarnessStore.inFileQueue(filePath, async () => {
|
|
45
|
-
await this.preparePath(filePath);
|
|
46
|
-
return this.readSnapshot(filePath);
|
|
47
|
-
});
|
|
271
|
+
async deleteSession(storageKey, sessionId) {
|
|
272
|
+
this.snapshots.delete(providerKey(storageKey, sessionId));
|
|
48
273
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
274
|
+
}
|
|
275
|
+
class InMemoryPermissionStore {
|
|
276
|
+
snapshots = new Map();
|
|
277
|
+
async load(storageKey, sessionId) {
|
|
278
|
+
const snapshot = this.snapshots.get(providerKey(storageKey, sessionId));
|
|
279
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
280
|
+
}
|
|
281
|
+
async save(storageKey, sessionId, snapshot, expectedRevision) {
|
|
282
|
+
const key = providerKey(storageKey, sessionId);
|
|
283
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexPermissionSnapshot);
|
|
284
|
+
const actualRevision = this.snapshots.get(key)?.revision ?? 0;
|
|
285
|
+
if (actualRevision !== expectedRevision) {
|
|
286
|
+
throw new FlexHarnessStoreConflictError(key, expectedRevision, actualRevision);
|
|
287
|
+
}
|
|
288
|
+
this.snapshots.set(key, validated);
|
|
289
|
+
}
|
|
290
|
+
async deleteSession(storageKey, sessionId) {
|
|
291
|
+
this.snapshots.delete(providerKey(storageKey, sessionId));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
class InMemoryAgentEventStore {
|
|
295
|
+
sessionId;
|
|
296
|
+
eventSchemaVersion = 2;
|
|
297
|
+
snapshot;
|
|
298
|
+
archives = new Map();
|
|
299
|
+
constructor(sessionId) {
|
|
300
|
+
this.sessionId = sessionId;
|
|
301
|
+
}
|
|
302
|
+
assertSession(sessionId) {
|
|
303
|
+
if (sessionId !== this.sessionId) {
|
|
304
|
+
throw new FlexHarnessValidationError(`Agent event store is bound to session "${this.sessionId}", not "${sessionId}".`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
async load(sessionId) {
|
|
308
|
+
this.assertSession(sessionId);
|
|
309
|
+
return this.snapshot ? cloneSerializable(this.snapshot) : undefined;
|
|
310
|
+
}
|
|
311
|
+
async save(sessionId, events, expectedRevision) {
|
|
312
|
+
this.assertSession(sessionId);
|
|
313
|
+
validateExpectedRevision(expectedRevision);
|
|
314
|
+
const snapshot = createAgentEventSnapshot(sessionId, events, expectedRevision + 1);
|
|
315
|
+
validateAgentEventSnapshot(snapshot, sessionId);
|
|
316
|
+
const actualRevision = this.snapshot?.revision ?? 0;
|
|
317
|
+
if (actualRevision !== expectedRevision) {
|
|
318
|
+
throw new plugins.AgentEventStoreConflictError(sessionId, expectedRevision, actualRevision);
|
|
319
|
+
}
|
|
320
|
+
this.snapshot = cloneSerializable(snapshot);
|
|
321
|
+
return snapshot.revision;
|
|
322
|
+
}
|
|
323
|
+
async archive(archive) {
|
|
324
|
+
this.assertSession(archive.sessionId);
|
|
325
|
+
const normalized = normalizeJsonObjectUndefined(archive, '$archive');
|
|
326
|
+
const validated = validateAgentEventArchive(normalized, this.sessionId, archive.archiveId);
|
|
327
|
+
const existing = this.archives.get(archive.archiveId);
|
|
328
|
+
if (existing) {
|
|
329
|
+
if (JSON.stringify(existing.events.map((event) => event.id))
|
|
330
|
+
!== JSON.stringify(validated.events.map((event) => event.id))) {
|
|
331
|
+
throw new Error(`Archive "${archive.archiveId}" already exists with different events.`);
|
|
58
332
|
}
|
|
59
|
-
|
|
60
|
-
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
this.archives.set(archive.archiveId, cloneSerializable(validated));
|
|
336
|
+
}
|
|
337
|
+
async loadArchive(sessionId, archiveId) {
|
|
338
|
+
this.assertSession(sessionId);
|
|
339
|
+
validateIdentifier(archiveId, 'archiveId');
|
|
340
|
+
const archive = this.archives.get(archiveId);
|
|
341
|
+
return archive ? cloneSerializable(archive) : undefined;
|
|
342
|
+
}
|
|
343
|
+
clear() {
|
|
344
|
+
this.snapshot = undefined;
|
|
345
|
+
this.archives.clear();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
class InMemoryAgentEventStoreProvider {
|
|
349
|
+
stores = new Map();
|
|
350
|
+
getStore(storageKey, sessionId) {
|
|
351
|
+
const key = providerKey(storageKey, sessionId);
|
|
352
|
+
let store = this.stores.get(key);
|
|
353
|
+
if (!store) {
|
|
354
|
+
store = new InMemoryAgentEventStore(sessionId);
|
|
355
|
+
this.stores.set(key, store);
|
|
356
|
+
}
|
|
357
|
+
return store;
|
|
358
|
+
}
|
|
359
|
+
async deleteSession(storageKey, sessionId) {
|
|
360
|
+
const key = providerKey(storageKey, sessionId);
|
|
361
|
+
const store = this.stores.get(key);
|
|
362
|
+
if (!store)
|
|
363
|
+
return;
|
|
364
|
+
store.clear();
|
|
365
|
+
this.stores.delete(key);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
class InMemoryToolJobStore {
|
|
369
|
+
snapshot;
|
|
370
|
+
async load(abortSignal) {
|
|
371
|
+
abortSignal?.throwIfAborted();
|
|
372
|
+
return this.snapshot ? cloneSerializable(this.snapshot) : undefined;
|
|
373
|
+
}
|
|
374
|
+
async save(jobs, expectedRevision, abortSignal) {
|
|
375
|
+
abortSignal?.throwIfAborted();
|
|
376
|
+
validateExpectedRevision(expectedRevision);
|
|
377
|
+
const snapshot = createToolJobSnapshot(jobs, expectedRevision + 1);
|
|
378
|
+
const actualRevision = this.snapshot?.revision ?? 0;
|
|
379
|
+
if (actualRevision !== expectedRevision) {
|
|
380
|
+
throw new plugins.ToolJobStoreConflictError(expectedRevision, actualRevision);
|
|
381
|
+
}
|
|
382
|
+
this.snapshot = cloneSerializable(snapshot);
|
|
383
|
+
return snapshot.revision;
|
|
384
|
+
}
|
|
385
|
+
clear() {
|
|
386
|
+
this.snapshot = undefined;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
class InMemoryToolJobStoreProvider {
|
|
390
|
+
stores = new Map();
|
|
391
|
+
getStore(storageKey, sessionId) {
|
|
392
|
+
const key = providerKey(storageKey, sessionId);
|
|
393
|
+
let store = this.stores.get(key);
|
|
394
|
+
if (!store) {
|
|
395
|
+
store = new InMemoryToolJobStore();
|
|
396
|
+
this.stores.set(key, store);
|
|
397
|
+
}
|
|
398
|
+
return store;
|
|
399
|
+
}
|
|
400
|
+
async deleteSession(storageKey, sessionId) {
|
|
401
|
+
const key = providerKey(storageKey, sessionId);
|
|
402
|
+
const store = this.stores.get(key);
|
|
403
|
+
if (!store)
|
|
404
|
+
return;
|
|
405
|
+
store.clear();
|
|
406
|
+
this.stores.delete(key);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
export class InMemoryFlexHarnessStores {
|
|
410
|
+
scopes = new InMemoryScopeStore();
|
|
411
|
+
projections = new InMemoryProjectionStore();
|
|
412
|
+
permissions = new InMemoryPermissionStore();
|
|
413
|
+
agentEvents = new InMemoryAgentEventStoreProvider();
|
|
414
|
+
jobs = new InMemoryToolJobStoreProvider();
|
|
415
|
+
}
|
|
416
|
+
const jsonDomains = ['scopes', 'projections', 'permissions', 'events', 'archives', 'jobs'];
|
|
417
|
+
function aggregateStoreErrors(errors, message) {
|
|
418
|
+
return errors.length === 1 ? errors[0] : new AggregateError(errors, message);
|
|
419
|
+
}
|
|
420
|
+
class JsonFileRoot {
|
|
421
|
+
static fileQueues = new Map();
|
|
422
|
+
directory;
|
|
423
|
+
retainedFileHandles = new Set();
|
|
424
|
+
fileHandleClosures = new Map();
|
|
425
|
+
constructor(directory) {
|
|
426
|
+
this.directory = plugins.path.resolve(directory);
|
|
61
427
|
}
|
|
62
|
-
static
|
|
63
|
-
const previous =
|
|
428
|
+
static inQueue(key, operation) {
|
|
429
|
+
const previous = JsonFileRoot.fileQueues.get(key) ?? Promise.resolve();
|
|
64
430
|
const result = previous.catch(() => undefined).then(operation);
|
|
65
431
|
const barrier = result.then(() => undefined, () => undefined);
|
|
66
|
-
|
|
432
|
+
JsonFileRoot.fileQueues.set(key, barrier);
|
|
67
433
|
void barrier.then(() => {
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
}
|
|
434
|
+
if (JsonFileRoot.fileQueues.get(key) === barrier)
|
|
435
|
+
JsonFileRoot.fileQueues.delete(key);
|
|
71
436
|
});
|
|
72
437
|
return result;
|
|
73
438
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
439
|
+
digest(value) {
|
|
440
|
+
return plugins.crypto.createHash('sha256').update(value).digest('hex');
|
|
441
|
+
}
|
|
442
|
+
scopePath(domain, storageKey) {
|
|
443
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
444
|
+
return plugins.path.join(this.directory, domain, `${this.digest(storageKey)}.json`);
|
|
445
|
+
}
|
|
446
|
+
sessionPath(domain, storageKey, sessionId) {
|
|
447
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
448
|
+
validateIdentifier(sessionId, 'sessionId');
|
|
449
|
+
return plugins.path.join(this.directory, domain, this.digest(storageKey), `${this.digest(sessionId)}.json`);
|
|
450
|
+
}
|
|
451
|
+
archivePath(storageKey, sessionId, archiveId) {
|
|
452
|
+
validateIdentifier(archiveId, 'archiveId');
|
|
453
|
+
return plugins.path.join(this.archiveSessionPath(storageKey, sessionId), `${this.digest(archiveId)}.json`);
|
|
77
454
|
}
|
|
78
|
-
|
|
455
|
+
archiveSessionPath(storageKey, sessionId) {
|
|
456
|
+
validateIdentifier(storageKey, 'storageKey');
|
|
457
|
+
validateIdentifier(sessionId, 'sessionId');
|
|
458
|
+
return plugins.path.join(this.directory, 'archives', this.digest(storageKey), this.digest(sessionId));
|
|
459
|
+
}
|
|
460
|
+
eventQueueKey(storageKey, sessionId) {
|
|
461
|
+
return `event:${this.sessionPath('events', storageKey, sessionId)}`;
|
|
462
|
+
}
|
|
463
|
+
async prepareRoot() {
|
|
464
|
+
await this.retryRetainedFileHandles();
|
|
79
465
|
await plugins.fs.mkdir(this.directory, { recursive: true, mode: 0o700 });
|
|
80
466
|
await plugins.fs.chmod(this.directory, 0o700);
|
|
81
|
-
await
|
|
467
|
+
await Promise.all(jsonDomains.map(async (domain) => {
|
|
468
|
+
const path = plugins.path.join(this.directory, domain);
|
|
469
|
+
await plugins.fs.mkdir(path, { recursive: true, mode: 0o700 });
|
|
470
|
+
await plugins.fs.chmod(path, 0o700);
|
|
471
|
+
}));
|
|
472
|
+
}
|
|
473
|
+
closeFileHandle(handle) {
|
|
474
|
+
const existing = this.fileHandleClosures.get(handle);
|
|
475
|
+
if (existing)
|
|
476
|
+
return existing;
|
|
477
|
+
let closure;
|
|
478
|
+
closure = handle.close().then(() => {
|
|
479
|
+
this.retainedFileHandles.delete(handle);
|
|
480
|
+
}, (error) => {
|
|
481
|
+
this.retainedFileHandles.add(handle);
|
|
482
|
+
throw error;
|
|
483
|
+
}).finally(() => {
|
|
484
|
+
if (this.fileHandleClosures.get(handle) === closure) {
|
|
485
|
+
this.fileHandleClosures.delete(handle);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
this.fileHandleClosures.set(handle, closure);
|
|
489
|
+
return closure;
|
|
490
|
+
}
|
|
491
|
+
async retryRetainedFileHandles() {
|
|
492
|
+
const results = await Promise.allSettled([...this.retainedFileHandles].map((handle) => this.closeFileHandle(handle)));
|
|
493
|
+
const errors = results
|
|
494
|
+
.filter((result) => result.status === 'rejected')
|
|
495
|
+
.map((result) => result.reason);
|
|
496
|
+
if (errors.length > 0) {
|
|
497
|
+
throw aggregateStoreErrors(errors, 'Failed to close retained JSON store file handles.');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
async dispose() {
|
|
501
|
+
await Promise.allSettled([...this.fileHandleClosures.values()]);
|
|
502
|
+
await this.retryRetainedFileHandles();
|
|
503
|
+
}
|
|
504
|
+
async prepareDirectory(directory) {
|
|
505
|
+
await this.prepareRoot();
|
|
506
|
+
await plugins.fs.mkdir(directory, { recursive: true, mode: 0o700 });
|
|
507
|
+
let current = directory;
|
|
508
|
+
while (current !== this.directory && current.startsWith(`${this.directory}${plugins.path.sep}`)) {
|
|
509
|
+
await plugins.fs.chmod(current, 0o700);
|
|
510
|
+
current = plugins.path.dirname(current);
|
|
511
|
+
}
|
|
82
512
|
}
|
|
83
513
|
async cleanupTemps(filePath) {
|
|
514
|
+
const directory = plugins.path.dirname(filePath);
|
|
84
515
|
const prefix = `${plugins.path.basename(filePath)}.`;
|
|
85
|
-
const entries = await plugins.fs.readdir(
|
|
86
|
-
await Promise.
|
|
516
|
+
const entries = await plugins.fs.readdir(directory, { withFileTypes: true });
|
|
517
|
+
const cleanupResults = await Promise.allSettled(entries
|
|
87
518
|
.filter((entry) => entry.isFile() && entry.name.startsWith(prefix) && entry.name.endsWith('.tmp'))
|
|
88
519
|
.map(async (entry) => {
|
|
89
520
|
try {
|
|
90
|
-
await plugins.fs.unlink(plugins.path.join(
|
|
521
|
+
await plugins.fs.unlink(plugins.path.join(directory, entry.name));
|
|
91
522
|
}
|
|
92
523
|
catch (error) {
|
|
93
|
-
if (error.code !== 'ENOENT')
|
|
524
|
+
if (error.code !== 'ENOENT')
|
|
94
525
|
throw error;
|
|
95
|
-
}
|
|
96
526
|
}
|
|
97
527
|
}));
|
|
528
|
+
const cleanupErrors = cleanupResults
|
|
529
|
+
.filter((result) => result.status === 'rejected')
|
|
530
|
+
.map((result) => result.reason);
|
|
531
|
+
if (cleanupErrors.length > 0) {
|
|
532
|
+
throw aggregateStoreErrors(cleanupErrors, `Failed to clean temporary files for ${filePath}.`);
|
|
533
|
+
}
|
|
98
534
|
}
|
|
99
|
-
async
|
|
535
|
+
async attemptDirectorySync(directory) {
|
|
536
|
+
let handle;
|
|
537
|
+
let syncError;
|
|
538
|
+
let closeError;
|
|
539
|
+
try {
|
|
540
|
+
handle = await plugins.fs.open(directory, 'r');
|
|
541
|
+
await handle.sync();
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
syncError = error;
|
|
545
|
+
}
|
|
546
|
+
if (handle) {
|
|
547
|
+
try {
|
|
548
|
+
await this.closeFileHandle(handle);
|
|
549
|
+
}
|
|
550
|
+
catch (error) {
|
|
551
|
+
closeError = error;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return { syncError, closeError };
|
|
555
|
+
}
|
|
556
|
+
async writeExact(handle, serialized) {
|
|
557
|
+
let offset = 0;
|
|
558
|
+
while (offset < serialized.length) {
|
|
559
|
+
const { bytesWritten } = await handle.write(serialized, offset, serialized.length - offset, offset);
|
|
560
|
+
if (bytesWritten === 0) {
|
|
561
|
+
throw new Error('Writing the store temporary file made no progress.');
|
|
562
|
+
}
|
|
563
|
+
offset += bytesWritten;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
async syncParentAfterWrite(filePath, serialized) {
|
|
567
|
+
const directory = plugins.path.dirname(filePath);
|
|
568
|
+
const firstAttempt = await this.attemptDirectorySync(directory);
|
|
569
|
+
if (firstAttempt.syncError === undefined && firstAttempt.closeError === undefined)
|
|
570
|
+
return;
|
|
571
|
+
let comparisonError;
|
|
572
|
+
try {
|
|
573
|
+
const persisted = await plugins.fs.readFile(filePath);
|
|
574
|
+
if (!persisted.equals(serialized)) {
|
|
575
|
+
throw new Error(`Destination bytes at ${filePath} do not match the committed write.`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
comparisonError = error;
|
|
580
|
+
}
|
|
581
|
+
const retryAttempt = await this.attemptDirectorySync(directory);
|
|
582
|
+
if (comparisonError === undefined
|
|
583
|
+
&& retryAttempt.syncError === undefined
|
|
584
|
+
&& firstAttempt.closeError === undefined
|
|
585
|
+
&& retryAttempt.closeError === undefined)
|
|
586
|
+
return;
|
|
587
|
+
const errors = [
|
|
588
|
+
firstAttempt.syncError,
|
|
589
|
+
firstAttempt.closeError,
|
|
590
|
+
comparisonError,
|
|
591
|
+
retryAttempt.syncError,
|
|
592
|
+
retryAttempt.closeError,
|
|
593
|
+
].filter((error) => error !== undefined);
|
|
594
|
+
throw new FlexHarnessStoreCommitUncertainError(filePath, 'write', {
|
|
595
|
+
cause: aggregateStoreErrors(errors, `Could not confirm the store write at ${filePath}.`),
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
async syncParentAfterDelete(deletedPath, operation) {
|
|
599
|
+
const directory = plugins.path.dirname(deletedPath);
|
|
600
|
+
const firstAttempt = await this.attemptDirectorySync(directory);
|
|
601
|
+
if (firstAttempt.syncError === undefined && firstAttempt.closeError === undefined)
|
|
602
|
+
return;
|
|
603
|
+
let comparisonError;
|
|
604
|
+
try {
|
|
605
|
+
await plugins.fs.stat(deletedPath);
|
|
606
|
+
comparisonError = new Error(`Deleted path ${deletedPath} still exists.`);
|
|
607
|
+
}
|
|
608
|
+
catch (error) {
|
|
609
|
+
if (error.code !== 'ENOENT')
|
|
610
|
+
comparisonError = error;
|
|
611
|
+
}
|
|
612
|
+
const retryAttempt = await this.attemptDirectorySync(directory);
|
|
613
|
+
if (comparisonError === undefined
|
|
614
|
+
&& retryAttempt.syncError === undefined
|
|
615
|
+
&& firstAttempt.closeError === undefined
|
|
616
|
+
&& retryAttempt.closeError === undefined)
|
|
617
|
+
return;
|
|
618
|
+
const errors = [
|
|
619
|
+
firstAttempt.syncError,
|
|
620
|
+
firstAttempt.closeError,
|
|
621
|
+
comparisonError,
|
|
622
|
+
retryAttempt.syncError,
|
|
623
|
+
retryAttempt.closeError,
|
|
624
|
+
]
|
|
625
|
+
.filter((error) => error !== undefined);
|
|
626
|
+
throw new FlexHarnessStoreCommitUncertainError(deletedPath, operation, {
|
|
627
|
+
cause: aggregateStoreErrors(errors, `Could not confirm the store deletion at ${deletedPath}.`),
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
async read(filePath, validate) {
|
|
631
|
+
await this.prepareDirectory(plugins.path.dirname(filePath));
|
|
100
632
|
let serialized;
|
|
101
633
|
try {
|
|
102
634
|
await plugins.fs.chmod(filePath, 0o600);
|
|
103
635
|
serialized = await plugins.fs.readFile(filePath, 'utf8');
|
|
104
636
|
}
|
|
105
637
|
catch (error) {
|
|
106
|
-
if (error.code === 'ENOENT')
|
|
638
|
+
if (error.code === 'ENOENT')
|
|
107
639
|
return undefined;
|
|
108
|
-
}
|
|
109
640
|
throw error;
|
|
110
641
|
}
|
|
111
642
|
let parsed;
|
|
@@ -113,44 +644,406 @@ export class JsonFileFlexHarnessStore {
|
|
|
113
644
|
parsed = JSON.parse(serialized);
|
|
114
645
|
}
|
|
115
646
|
catch (error) {
|
|
116
|
-
throw new FlexHarnessStoreFormatError(`Malformed JSON
|
|
117
|
-
cause: error,
|
|
118
|
-
});
|
|
647
|
+
throw new FlexHarnessStoreFormatError(`Malformed JSON at ${filePath}.`, { cause: error });
|
|
119
648
|
}
|
|
120
649
|
try {
|
|
121
|
-
|
|
650
|
+
return validate(parsed);
|
|
122
651
|
}
|
|
123
652
|
catch (error) {
|
|
124
653
|
if (error instanceof FlexHarnessStoreFormatError) {
|
|
125
|
-
throw new FlexHarnessStoreFormatError(`Invalid
|
|
654
|
+
throw new FlexHarnessStoreFormatError(`Invalid JSON at ${filePath}: ${error.message}`, {
|
|
126
655
|
cause: error,
|
|
127
656
|
});
|
|
128
657
|
}
|
|
129
658
|
throw error;
|
|
130
659
|
}
|
|
131
|
-
return cloneSerializable(parsed);
|
|
132
660
|
}
|
|
133
|
-
async
|
|
661
|
+
async write(filePath, value) {
|
|
662
|
+
assertJsonSerializable(value);
|
|
663
|
+
const serialized = Buffer.from(`${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
664
|
+
const directory = plugins.path.dirname(filePath);
|
|
665
|
+
await this.prepareDirectory(directory);
|
|
666
|
+
await this.cleanupTemps(filePath);
|
|
134
667
|
const tempPath = `${filePath}.${process.pid}.${plugins.crypto.randomUUID()}.tmp`;
|
|
135
|
-
let
|
|
668
|
+
let handle;
|
|
669
|
+
let operationError;
|
|
670
|
+
let operationFailed = false;
|
|
671
|
+
let renamed = false;
|
|
136
672
|
try {
|
|
137
|
-
|
|
138
|
-
await
|
|
139
|
-
await
|
|
140
|
-
await
|
|
141
|
-
|
|
142
|
-
await plugins.fs.chmod(tempPath, 0o600);
|
|
673
|
+
handle = await plugins.fs.open(tempPath, 'wx', 0o600);
|
|
674
|
+
await this.writeExact(handle, serialized);
|
|
675
|
+
await handle.sync();
|
|
676
|
+
await this.closeFileHandle(handle);
|
|
677
|
+
handle = undefined;
|
|
143
678
|
await plugins.fs.rename(tempPath, filePath);
|
|
144
|
-
|
|
679
|
+
renamed = true;
|
|
680
|
+
await this.syncParentAfterWrite(filePath, serialized);
|
|
145
681
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
682
|
+
catch (error) {
|
|
683
|
+
operationError = error;
|
|
684
|
+
operationFailed = true;
|
|
685
|
+
}
|
|
686
|
+
const cleanupErrors = [];
|
|
687
|
+
if (handle) {
|
|
688
|
+
try {
|
|
689
|
+
await this.closeFileHandle(handle);
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
cleanupErrors.push(error);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
try {
|
|
696
|
+
await plugins.fs.unlink(tempPath);
|
|
697
|
+
}
|
|
698
|
+
catch (error) {
|
|
699
|
+
if (error.code !== 'ENOENT')
|
|
700
|
+
cleanupErrors.push(error);
|
|
701
|
+
}
|
|
702
|
+
if (!operationFailed && cleanupErrors.length === 0)
|
|
703
|
+
return;
|
|
704
|
+
if (renamed
|
|
705
|
+
&& operationError instanceof FlexHarnessStoreCommitUncertainError
|
|
706
|
+
&& cleanupErrors.length === 0) {
|
|
707
|
+
throw operationError;
|
|
708
|
+
}
|
|
709
|
+
const errors = [];
|
|
710
|
+
if (operationFailed)
|
|
711
|
+
errors.push(operationError);
|
|
712
|
+
errors.push(...cleanupErrors);
|
|
713
|
+
const cause = aggregateStoreErrors(errors, `Store write or cleanup failed at ${filePath}.`);
|
|
714
|
+
if (renamed) {
|
|
715
|
+
throw new FlexHarnessStoreCommitUncertainError(filePath, 'write', { cause });
|
|
716
|
+
}
|
|
717
|
+
throw cause;
|
|
718
|
+
}
|
|
719
|
+
async deleteFile(filePath) {
|
|
720
|
+
await this.prepareDirectory(plugins.path.dirname(filePath));
|
|
721
|
+
try {
|
|
722
|
+
await plugins.fs.unlink(filePath);
|
|
723
|
+
}
|
|
724
|
+
catch (error) {
|
|
725
|
+
if (error.code !== 'ENOENT')
|
|
726
|
+
throw error;
|
|
727
|
+
}
|
|
728
|
+
await this.syncParentAfterDelete(filePath, 'delete-file');
|
|
729
|
+
}
|
|
730
|
+
async deleteDirectory(directory) {
|
|
731
|
+
await this.prepareDirectory(plugins.path.dirname(directory));
|
|
732
|
+
await plugins.fs.rm(directory, { recursive: true, force: true });
|
|
733
|
+
await this.syncParentAfterDelete(directory, 'delete-directory');
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
class JsonScopeStore {
|
|
737
|
+
root;
|
|
738
|
+
constructor(root) {
|
|
739
|
+
this.root = root;
|
|
740
|
+
}
|
|
741
|
+
async load(storageKey) {
|
|
742
|
+
const filePath = this.root.scopePath('scopes', storageKey);
|
|
743
|
+
return JsonFileRoot.inQueue(filePath, async () => {
|
|
744
|
+
const snapshot = await this.root.read(filePath, (value) => {
|
|
745
|
+
assertFlexScopeSnapshot(value);
|
|
746
|
+
return value;
|
|
747
|
+
});
|
|
748
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
async save(storageKey, snapshot, expectedRevision) {
|
|
752
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexScopeSnapshot);
|
|
753
|
+
const filePath = this.root.scopePath('scopes', storageKey);
|
|
754
|
+
await JsonFileRoot.inQueue(filePath, async () => {
|
|
755
|
+
const current = await this.root.read(filePath, (value) => {
|
|
756
|
+
assertFlexScopeSnapshot(value);
|
|
757
|
+
return value;
|
|
152
758
|
});
|
|
759
|
+
const actualRevision = current?.revision ?? 0;
|
|
760
|
+
if (actualRevision !== expectedRevision) {
|
|
761
|
+
throw new FlexHarnessStoreConflictError(storageKey, expectedRevision, actualRevision);
|
|
762
|
+
}
|
|
763
|
+
await this.root.write(filePath, validated);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
class JsonProjectionStore {
|
|
768
|
+
root;
|
|
769
|
+
constructor(root) {
|
|
770
|
+
this.root = root;
|
|
771
|
+
}
|
|
772
|
+
async load(storageKey, sessionId) {
|
|
773
|
+
const filePath = this.root.sessionPath('projections', storageKey, sessionId);
|
|
774
|
+
return JsonFileRoot.inQueue(filePath, async () => {
|
|
775
|
+
const snapshot = await this.root.read(filePath, (value) => {
|
|
776
|
+
assertFlexProjectionSnapshot(value);
|
|
777
|
+
assertProjectionSession(value, sessionId);
|
|
778
|
+
return value;
|
|
779
|
+
});
|
|
780
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
async save(storageKey, sessionId, snapshot, expectedRevision) {
|
|
784
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexProjectionSnapshot);
|
|
785
|
+
assertProjectionSession(validated, sessionId);
|
|
786
|
+
const filePath = this.root.sessionPath('projections', storageKey, sessionId);
|
|
787
|
+
await JsonFileRoot.inQueue(filePath, async () => {
|
|
788
|
+
const current = await this.root.read(filePath, (value) => {
|
|
789
|
+
assertFlexProjectionSnapshot(value);
|
|
790
|
+
assertProjectionSession(value, sessionId);
|
|
791
|
+
return value;
|
|
792
|
+
});
|
|
793
|
+
const actualRevision = current?.revision ?? 0;
|
|
794
|
+
if (actualRevision !== expectedRevision) {
|
|
795
|
+
throw new FlexHarnessStoreConflictError(providerKey(storageKey, sessionId), expectedRevision, actualRevision);
|
|
796
|
+
}
|
|
797
|
+
await this.root.write(filePath, validated);
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
async deleteSession(storageKey, sessionId) {
|
|
801
|
+
const filePath = this.root.sessionPath('projections', storageKey, sessionId);
|
|
802
|
+
await JsonFileRoot.inQueue(filePath, () => this.root.deleteFile(filePath));
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
class JsonPermissionStore {
|
|
806
|
+
root;
|
|
807
|
+
constructor(root) {
|
|
808
|
+
this.root = root;
|
|
809
|
+
}
|
|
810
|
+
async load(storageKey, sessionId) {
|
|
811
|
+
const filePath = this.root.sessionPath('permissions', storageKey, sessionId);
|
|
812
|
+
return JsonFileRoot.inQueue(filePath, async () => {
|
|
813
|
+
const snapshot = await this.root.read(filePath, (value) => {
|
|
814
|
+
assertFlexPermissionSnapshot(value);
|
|
815
|
+
return value;
|
|
816
|
+
});
|
|
817
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
async save(storageKey, sessionId, snapshot, expectedRevision) {
|
|
821
|
+
const validated = validateSnapshotSave(snapshot, expectedRevision, assertFlexPermissionSnapshot);
|
|
822
|
+
const filePath = this.root.sessionPath('permissions', storageKey, sessionId);
|
|
823
|
+
await JsonFileRoot.inQueue(filePath, async () => {
|
|
824
|
+
const current = await this.root.read(filePath, (value) => {
|
|
825
|
+
assertFlexPermissionSnapshot(value);
|
|
826
|
+
return value;
|
|
827
|
+
});
|
|
828
|
+
const actualRevision = current?.revision ?? 0;
|
|
829
|
+
if (actualRevision !== expectedRevision) {
|
|
830
|
+
throw new FlexHarnessStoreConflictError(providerKey(storageKey, sessionId), expectedRevision, actualRevision);
|
|
831
|
+
}
|
|
832
|
+
await this.root.write(filePath, validated);
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
async deleteSession(storageKey, sessionId) {
|
|
836
|
+
const filePath = this.root.sessionPath('permissions', storageKey, sessionId);
|
|
837
|
+
await JsonFileRoot.inQueue(filePath, () => this.root.deleteFile(filePath));
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
async function clearJsonAgentEventSession(root, storageKey, sessionId) {
|
|
841
|
+
const filePath = root.sessionPath('events', storageKey, sessionId);
|
|
842
|
+
const archiveDirectory = root.archiveSessionPath(storageKey, sessionId);
|
|
843
|
+
await JsonFileRoot.inQueue(root.eventQueueKey(storageKey, sessionId), async () => {
|
|
844
|
+
await root.deleteFile(filePath);
|
|
845
|
+
await root.deleteDirectory(archiveDirectory);
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
class JsonAgentEventStore {
|
|
849
|
+
root;
|
|
850
|
+
storageKey;
|
|
851
|
+
sessionId;
|
|
852
|
+
eventSchemaVersion = 2;
|
|
853
|
+
constructor(root, storageKey, sessionId) {
|
|
854
|
+
this.root = root;
|
|
855
|
+
this.storageKey = storageKey;
|
|
856
|
+
this.sessionId = sessionId;
|
|
857
|
+
}
|
|
858
|
+
assertSession(sessionId) {
|
|
859
|
+
if (sessionId !== this.sessionId) {
|
|
860
|
+
throw new FlexHarnessValidationError(`Agent event store is bound to session "${this.sessionId}", not "${sessionId}".`);
|
|
153
861
|
}
|
|
154
862
|
}
|
|
863
|
+
async load(sessionId) {
|
|
864
|
+
this.assertSession(sessionId);
|
|
865
|
+
const filePath = this.root.sessionPath('events', this.storageKey, this.sessionId);
|
|
866
|
+
return JsonFileRoot.inQueue(this.root.eventQueueKey(this.storageKey, this.sessionId), async () => {
|
|
867
|
+
const snapshot = await this.root.read(filePath, (value) => validateAgentEventSnapshot(value, this.sessionId));
|
|
868
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
async save(sessionId, events, expectedRevision) {
|
|
872
|
+
this.assertSession(sessionId);
|
|
873
|
+
validateExpectedRevision(expectedRevision);
|
|
874
|
+
const snapshot = createAgentEventSnapshot(sessionId, events, expectedRevision + 1);
|
|
875
|
+
validateAgentEventSnapshot(snapshot, sessionId);
|
|
876
|
+
const filePath = this.root.sessionPath('events', this.storageKey, this.sessionId);
|
|
877
|
+
return JsonFileRoot.inQueue(this.root.eventQueueKey(this.storageKey, this.sessionId), async () => {
|
|
878
|
+
const current = await this.root.read(filePath, (value) => validateAgentEventSnapshot(value, this.sessionId));
|
|
879
|
+
const actualRevision = current?.revision ?? 0;
|
|
880
|
+
if (actualRevision !== expectedRevision) {
|
|
881
|
+
throw new plugins.AgentEventStoreConflictError(sessionId, expectedRevision, actualRevision);
|
|
882
|
+
}
|
|
883
|
+
await this.root.write(filePath, snapshot);
|
|
884
|
+
return snapshot.revision;
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
async archive(archive) {
|
|
888
|
+
this.assertSession(archive.sessionId);
|
|
889
|
+
const normalized = normalizeJsonObjectUndefined(archive, '$archive');
|
|
890
|
+
const validated = validateAgentEventArchive(normalized, this.sessionId, archive.archiveId);
|
|
891
|
+
const filePath = this.root.archivePath(this.storageKey, this.sessionId, archive.archiveId);
|
|
892
|
+
await JsonFileRoot.inQueue(this.root.eventQueueKey(this.storageKey, this.sessionId), async () => {
|
|
893
|
+
const current = await this.root.read(filePath, (value) => validateAgentEventArchive(value, this.sessionId, archive.archiveId));
|
|
894
|
+
if (current) {
|
|
895
|
+
if (JSON.stringify(current.events.map((event) => event.id))
|
|
896
|
+
!== JSON.stringify(validated.events.map((event) => event.id))) {
|
|
897
|
+
throw new Error(`Archive "${archive.archiveId}" already exists with different events.`);
|
|
898
|
+
}
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
await this.root.write(filePath, validated);
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
async loadArchive(sessionId, archiveId) {
|
|
905
|
+
this.assertSession(sessionId);
|
|
906
|
+
const filePath = this.root.archivePath(this.storageKey, this.sessionId, archiveId);
|
|
907
|
+
return JsonFileRoot.inQueue(this.root.eventQueueKey(this.storageKey, this.sessionId), async () => {
|
|
908
|
+
const archive = await this.root.read(filePath, (value) => validateAgentEventArchive(value, this.sessionId, archiveId));
|
|
909
|
+
return archive ? cloneSerializable(archive) : undefined;
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
async clear() {
|
|
913
|
+
await clearJsonAgentEventSession(this.root, this.storageKey, this.sessionId);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
class JsonAgentEventStoreProvider {
|
|
917
|
+
root;
|
|
918
|
+
stores = new Map();
|
|
919
|
+
constructor(root) {
|
|
920
|
+
this.root = root;
|
|
921
|
+
}
|
|
922
|
+
getStore(storageKey, sessionId) {
|
|
923
|
+
const key = providerKey(storageKey, sessionId);
|
|
924
|
+
let store = this.stores.get(key);
|
|
925
|
+
if (!store) {
|
|
926
|
+
store = new JsonAgentEventStore(this.root, storageKey, sessionId);
|
|
927
|
+
this.stores.set(key, store);
|
|
928
|
+
}
|
|
929
|
+
return store;
|
|
930
|
+
}
|
|
931
|
+
releaseSession(storageKey, sessionId) {
|
|
932
|
+
this.stores.delete(providerKey(storageKey, sessionId));
|
|
933
|
+
}
|
|
934
|
+
async deleteSession(storageKey, sessionId) {
|
|
935
|
+
const key = providerKey(storageKey, sessionId);
|
|
936
|
+
const store = this.stores.get(key);
|
|
937
|
+
if (store) {
|
|
938
|
+
await store.clear();
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
await clearJsonAgentEventSession(this.root, storageKey, sessionId);
|
|
942
|
+
}
|
|
943
|
+
this.stores.delete(key);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
async function clearJsonToolJobSession(root, storageKey, sessionId) {
|
|
947
|
+
const filePath = root.sessionPath('jobs', storageKey, sessionId);
|
|
948
|
+
await JsonFileRoot.inQueue(filePath, () => root.deleteFile(filePath));
|
|
949
|
+
}
|
|
950
|
+
class JsonToolJobStore {
|
|
951
|
+
root;
|
|
952
|
+
storageKey;
|
|
953
|
+
sessionId;
|
|
954
|
+
constructor(root, storageKey, sessionId) {
|
|
955
|
+
this.root = root;
|
|
956
|
+
this.storageKey = storageKey;
|
|
957
|
+
this.sessionId = sessionId;
|
|
958
|
+
}
|
|
959
|
+
filePath() {
|
|
960
|
+
return this.root.sessionPath('jobs', this.storageKey, this.sessionId);
|
|
961
|
+
}
|
|
962
|
+
async load(abortSignal) {
|
|
963
|
+
abortSignal?.throwIfAborted();
|
|
964
|
+
const filePath = this.filePath();
|
|
965
|
+
return JsonFileRoot.inQueue(filePath, async () => {
|
|
966
|
+
abortSignal?.throwIfAborted();
|
|
967
|
+
const snapshot = await this.root.read(filePath, validateToolJobSnapshot);
|
|
968
|
+
abortSignal?.throwIfAborted();
|
|
969
|
+
return snapshot ? cloneSerializable(snapshot) : undefined;
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
async save(jobs, expectedRevision, abortSignal) {
|
|
973
|
+
abortSignal?.throwIfAborted();
|
|
974
|
+
validateExpectedRevision(expectedRevision);
|
|
975
|
+
const snapshot = createToolJobSnapshot(jobs, expectedRevision + 1);
|
|
976
|
+
const filePath = this.filePath();
|
|
977
|
+
return JsonFileRoot.inQueue(filePath, async () => {
|
|
978
|
+
abortSignal?.throwIfAborted();
|
|
979
|
+
const current = await this.root.read(filePath, validateToolJobSnapshot);
|
|
980
|
+
const actualRevision = current?.revision ?? 0;
|
|
981
|
+
if (actualRevision !== expectedRevision) {
|
|
982
|
+
throw new plugins.ToolJobStoreConflictError(expectedRevision, actualRevision);
|
|
983
|
+
}
|
|
984
|
+
abortSignal?.throwIfAborted();
|
|
985
|
+
await this.root.write(filePath, snapshot);
|
|
986
|
+
return snapshot.revision;
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
async clear() {
|
|
990
|
+
await clearJsonToolJobSession(this.root, this.storageKey, this.sessionId);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
class JsonToolJobStoreProvider {
|
|
994
|
+
root;
|
|
995
|
+
stores = new Map();
|
|
996
|
+
constructor(root) {
|
|
997
|
+
this.root = root;
|
|
998
|
+
}
|
|
999
|
+
getStore(storageKey, sessionId) {
|
|
1000
|
+
const key = providerKey(storageKey, sessionId);
|
|
1001
|
+
let store = this.stores.get(key);
|
|
1002
|
+
if (!store) {
|
|
1003
|
+
store = new JsonToolJobStore(this.root, storageKey, sessionId);
|
|
1004
|
+
this.stores.set(key, store);
|
|
1005
|
+
}
|
|
1006
|
+
return store;
|
|
1007
|
+
}
|
|
1008
|
+
releaseSession(storageKey, sessionId) {
|
|
1009
|
+
this.stores.delete(providerKey(storageKey, sessionId));
|
|
1010
|
+
}
|
|
1011
|
+
async deleteSession(storageKey, sessionId) {
|
|
1012
|
+
const key = providerKey(storageKey, sessionId);
|
|
1013
|
+
const store = this.stores.get(key);
|
|
1014
|
+
if (store) {
|
|
1015
|
+
await store.clear();
|
|
1016
|
+
}
|
|
1017
|
+
else {
|
|
1018
|
+
await clearJsonToolJobSession(this.root, storageKey, sessionId);
|
|
1019
|
+
}
|
|
1020
|
+
this.stores.delete(key);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Atomic and CAS-safe across instances in this process. No operating-system lock
|
|
1025
|
+
* is held, so this store intentionally does not claim cross-process safety.
|
|
1026
|
+
*/
|
|
1027
|
+
export class JsonFileFlexHarnessStores {
|
|
1028
|
+
scopes;
|
|
1029
|
+
projections;
|
|
1030
|
+
permissions;
|
|
1031
|
+
agentEvents;
|
|
1032
|
+
jobs;
|
|
1033
|
+
root;
|
|
1034
|
+
constructor(options) {
|
|
1035
|
+
if (!options?.directory?.trim()) {
|
|
1036
|
+
throw new FlexHarnessValidationError('JsonFileFlexHarnessStores requires a directory.');
|
|
1037
|
+
}
|
|
1038
|
+
this.root = new JsonFileRoot(options.directory);
|
|
1039
|
+
this.scopes = new JsonScopeStore(this.root);
|
|
1040
|
+
this.projections = new JsonProjectionStore(this.root);
|
|
1041
|
+
this.permissions = new JsonPermissionStore(this.root);
|
|
1042
|
+
this.agentEvents = new JsonAgentEventStoreProvider(this.root);
|
|
1043
|
+
this.jobs = new JsonToolJobStoreProvider(this.root);
|
|
1044
|
+
}
|
|
1045
|
+
dispose() {
|
|
1046
|
+
return this.root.dispose();
|
|
1047
|
+
}
|
|
155
1048
|
}
|
|
156
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9yZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN0b3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLDJCQUEyQixFQUMzQiwwQkFBMEIsR0FDM0IsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFL0UsU0FBUyxZQUFZLENBQ25CLFFBQThCLEVBQzlCLGdCQUF3QjtJQUV4Qix5QkFBeUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLGdCQUFnQixHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BFLE1BQU0sSUFBSSwwQkFBMEIsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssZ0JBQWdCLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLDJCQUEyQixDQUNuQyxxQkFBcUIsUUFBUSxDQUFDLFFBQVEsaUNBQWlDLGdCQUFnQixZQUFZLENBQ3BHLENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNyQyxDQUFDO0FBRUQsTUFBTSxPQUFPLHdCQUF3QjtJQUNsQixTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFFOUQsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFrQjtRQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMs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
|
|
1049
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9yZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN0b3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsb0NBQW9DLEVBQ3BDLDZCQUE2QixFQUM3QiwyQkFBMkIsRUFDM0IsMEJBQTBCLEdBQzNCLE1BQU0sYUFBYSxDQUFDO0FBWXJCLE9BQU8sRUFDTCw0QkFBNEIsRUFDNUIsNEJBQTRCLEVBQzVCLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsaUJBQWlCLEdBQ2xCLE1BQU0saUJBQWlCLENBQUM7QUFPekIsU0FBUyxrQkFBa0IsQ0FBQyxLQUFhLEVBQUUsSUFBWTtJQUNyRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSwwQkFBMEIsQ0FBQyxHQUFHLElBQUksOEJBQThCLENBQUMsQ0FBQztJQUM5RSxDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsZ0JBQXdCO0lBQ3hELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLElBQUksZ0JBQWdCLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDcEUsTUFBTSxJQUFJLDBCQUEwQixDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDM0YsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLG9CQUFvQixDQUMzQixRQUF3QixFQUN4QixnQkFBd0IsRUFDeEIsU0FBNkM7SUFFN0MsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BCLHdCQUF3QixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDM0MsSUFBSSxRQUFRLENBQUMsUUFBUSxLQUFLLGdCQUFnQixHQUFHLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSwyQkFBMkIsQ0FDbkMs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
|