@modelprofile.com/flexharness 10.24.0 → 11.0.0
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 +2 -2
- package/dist_ts/classes.codesandbox.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/classes.stores.js +1 -1
- package/dist_ts/classes.toolcatalog.js +1 -1
- package/dist_ts/errors.js +1 -1
- package/dist_ts/functions.toolpermissions.js +1 -1
- package/dist_ts/interfaces.d.ts +3 -3
- 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/dist_ts/utils.harnessoptions.js +1 -1
- package/dist_ts/utils.json.js +1 -1
- package/dist_ts/utils.schemadeclarations.js +1 -1
- package/dist_ts/utils.sessionimport.js +1 -1
- package/dist_ts/utils.sessionmetrics.d.ts +1 -1
- package/dist_ts_chat/classes.chatsession.js +1 -1
- package/dist_ts_chat_harness/classes.transcript.js +1 -1
- package/dist_ts_chat_harness/functions.intents.js +1 -1
- package/dist_ts_chat_harness/functions.mapping.d.ts +1 -1
- package/dist_ts_chat_harness/functions.mapping.js +1 -1
- package/dist_ts_chat_harness_server/classes.chathub.d.ts +18 -7
- package/dist_ts_chat_harness_server/classes.chathub.js +65 -62
- package/dist_ts_chat_harness_server/classes.chatsubscription.d.ts +5 -3
- package/dist_ts_chat_harness_server/classes.chatsubscription.js +4 -4
- package/dist_ts_chat_harness_server/classes.scopedirectory.d.ts +17 -0
- package/dist_ts_chat_harness_server/classes.scopedirectory.js +49 -0
- package/dist_ts_chat_harness_server/classes.sessionlists.d.ts +3 -5
- package/dist_ts_chat_harness_server/classes.sessionlists.js +11 -12
- package/dist_ts_chat_harness_server/classes.turngate.d.ts +8 -2
- package/dist_ts_chat_harness_server/classes.turngate.js +22 -21
- package/dist_ts_chat_harness_server/functions.errorprojector.js +1 -1
- package/dist_ts_chat_harness_server/index.d.ts +3 -2
- package/dist_ts_chat_harness_server/index.js +3 -2
- package/dist_ts_chat_harness_server/interfaces.d.ts +35 -2
- package/dist_ts_chat_harness_server/plugins.d.ts +1 -1
- package/dist_ts_chat_harness_typedsocket/classes.clienttransport.d.ts +28 -3
- package/dist_ts_chat_harness_typedsocket/classes.clienttransport.js +71 -15
- package/dist_ts_chat_harness_typedsocket/classes.serverbinding.d.ts +5 -3
- package/dist_ts_chat_harness_typedsocket/classes.serverbinding.js +79 -16
- package/dist_ts_chat_harness_typedsocket/index.d.ts +2 -2
- package/dist_ts_chat_harness_typedsocket/index.js +1 -1
- package/dist_ts_chat_harness_typedsocket/interfaces.requests.d.ts +20 -11
- package/dist_ts_chat_web/flexchat-input.js +1 -1
- package/dist_ts_chat_web/flexchat-message.js +1 -1
- package/dist_ts_chat_web/flexchat-window.js +1 -1
- package/dist_ts_compaction/smartagent.compaction.js +1 -1
- package/dist_ts_kvm/ocr.js +1 -1
- package/dist_ts_ocr/classes.imageocr.js +1 -1
- package/dist_ts_ocr/ocr.mistral.js +1 -1
- package/dist_ts_stores_nosqldb/classes.nosqldbstores.js +1 -1
- package/dist_ts_tools/tool.browser.js +1 -1
- package/dist_ts_tools/tool.filesystem.js +1 -1
- package/dist_ts_tools/tool.shell.js +1 -1
- package/dist_ts_tools_node/tool.context.js +1 -1
- package/dist_ts_typedrequest/catalog.d.ts +2 -2
- package/dist_ts_typedrequest/catalog.js +1 -1
- 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
- package/ts_chat_harness_server/classes.chathub.ts +68 -61
- package/ts_chat_harness_server/classes.chatsubscription.ts +7 -5
- package/ts_chat_harness_server/classes.scopedirectory.ts +67 -0
- package/ts_chat_harness_server/classes.sessionlists.ts +11 -19
- package/ts_chat_harness_server/classes.turngate.ts +28 -21
- package/ts_chat_harness_server/index.ts +4 -5
- package/ts_chat_harness_server/interfaces.ts +35 -2
- package/ts_chat_harness_server/plugins.ts +0 -3
- package/ts_chat_harness_server/readme.md +6 -4
- package/ts_chat_harness_typedsocket/classes.clienttransport.ts +92 -23
- package/ts_chat_harness_typedsocket/classes.serverbinding.ts +88 -16
- package/ts_chat_harness_typedsocket/index.ts +4 -2
- package/ts_chat_harness_typedsocket/interfaces.requests.ts +15 -11
- package/ts_chat_harness_typedsocket/readme.md +7 -3
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { FlexHarnessAbortError, FlexHarnessNotFoundError, FlexHarnessQueueFullError, FlexHarnessSessionBusyError, FlexHarnessValidationError, } from './errors.js';
|
|
3
|
+
import { FLEX_SESSION_IMPORT_MAX_DEPTH, } from './interfaces.js';
|
|
4
|
+
import { cloneSerializable } from './utils.json.js';
|
|
5
|
+
import { publicSnapshot } from './utils.transfer.js';
|
|
6
|
+
import { normalizeBeginSessionImportOptions, normalizeImportedRunPage, sessionImportIdentity, validateSessionImportHandle, } from './utils.sessionimport.js';
|
|
7
|
+
import { createSessionMetricsState } from './utils.sessionmetrics.js';
|
|
8
|
+
import { createSessionGenerationId, requireSessionGeneration, combineErrors, } from './utils.flexharness.js';
|
|
9
|
+
/** Staged imports of finished conversations as read-only sessions. */
|
|
10
|
+
export class FlexHarnessSessionImports {
|
|
11
|
+
core;
|
|
12
|
+
stagedSessionImports = new Map();
|
|
13
|
+
constructor(core) {
|
|
14
|
+
this.core = core;
|
|
15
|
+
}
|
|
16
|
+
async beginSessionImport(scopeId, options) {
|
|
17
|
+
this.core.assertOpen();
|
|
18
|
+
const normalized = normalizeBeginSessionImportOptions(options);
|
|
19
|
+
const { scope, state } = await this.core.resolveState(scopeId);
|
|
20
|
+
await state.scopeQueue;
|
|
21
|
+
this.core.assertOpen();
|
|
22
|
+
this.core.assertStateAcceptingWork(state);
|
|
23
|
+
const { sessionId } = normalized;
|
|
24
|
+
const identity = sessionImportIdentity(normalized.origin);
|
|
25
|
+
for (const staged of state.sessionImports.values()) {
|
|
26
|
+
if (staged.sessionId === sessionId || staged.identity === identity) {
|
|
27
|
+
throw new FlexHarnessSessionBusyError(staged.sessionId, 'is already being imported');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
for (const stored of state.sessions.values()) {
|
|
31
|
+
const origin = stored.session.origin;
|
|
32
|
+
if (origin === undefined || sessionImportIdentity(origin) !== identity)
|
|
33
|
+
continue;
|
|
34
|
+
const existing = {
|
|
35
|
+
status: origin.digest === normalized.origin.digest ? 'already_imported' : 'digest_mismatch',
|
|
36
|
+
session: stored.session,
|
|
37
|
+
};
|
|
38
|
+
return publicSnapshot(existing);
|
|
39
|
+
}
|
|
40
|
+
if (state.sessions.has(sessionId)
|
|
41
|
+
|| state.tombstones.has(sessionId)
|
|
42
|
+
|| state.initializingSessions.has(sessionId)) {
|
|
43
|
+
throw new FlexHarnessValidationError(`Session "${sessionId}" already exists or is being deleted.`);
|
|
44
|
+
}
|
|
45
|
+
if (normalized.parent)
|
|
46
|
+
this.requireImportParent(state, sessionId, normalized.parent);
|
|
47
|
+
if (this.stagedSessionImports.size >= this.core.sessionImportLimits.maxOpenImports) {
|
|
48
|
+
throw new FlexHarnessQueueFullError('FlexHarness has reached its open session import limit.');
|
|
49
|
+
}
|
|
50
|
+
const staged = {
|
|
51
|
+
importId: `import_${plugins.crypto.randomUUID()}`,
|
|
52
|
+
scopeId,
|
|
53
|
+
state,
|
|
54
|
+
scope: scope.scope,
|
|
55
|
+
sessionId,
|
|
56
|
+
options: normalized,
|
|
57
|
+
identity,
|
|
58
|
+
runs: [],
|
|
59
|
+
runIds: new Set(),
|
|
60
|
+
messageIds: new Set(),
|
|
61
|
+
messageCount: 0,
|
|
62
|
+
bytes: 0,
|
|
63
|
+
phase: 'staging',
|
|
64
|
+
};
|
|
65
|
+
this.stagedSessionImports.set(staged.importId, staged);
|
|
66
|
+
this.armStagedImportIdleTimer(staged);
|
|
67
|
+
state.sessionImports.set(sessionId, staged);
|
|
68
|
+
state.initializingSessions.add(sessionId);
|
|
69
|
+
const started = {
|
|
70
|
+
status: 'started',
|
|
71
|
+
handle: { importId: staged.importId, scopeId, sessionId },
|
|
72
|
+
};
|
|
73
|
+
return publicSnapshot(started);
|
|
74
|
+
}
|
|
75
|
+
async appendImportedRuns(handle, runs) {
|
|
76
|
+
const staged = this.requireStagedSessionImport(handle);
|
|
77
|
+
this.core.assertOpen();
|
|
78
|
+
this.core.assertStateAcceptingWork(staged.state);
|
|
79
|
+
const page = normalizeImportedRunPage(runs, staged.sessionId, this.core.sessionImportLimits.maxPageBytes);
|
|
80
|
+
const runIds = new Set();
|
|
81
|
+
const messageIds = new Set();
|
|
82
|
+
for (const run of page.runs) {
|
|
83
|
+
if (staged.runIds.has(run.user.runId) || runIds.has(run.user.runId)) {
|
|
84
|
+
throw new FlexHarnessValidationError(`Imported run "${run.user.runId}" is not unique.`);
|
|
85
|
+
}
|
|
86
|
+
runIds.add(run.user.runId);
|
|
87
|
+
for (const message of [run.user, run.assistant]) {
|
|
88
|
+
if (staged.messageIds.has(message.messageId) || messageIds.has(message.messageId)) {
|
|
89
|
+
throw new FlexHarnessValidationError(`Imported message "${message.messageId}" is not unique.`);
|
|
90
|
+
}
|
|
91
|
+
messageIds.add(message.messageId);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const messageCount = staged.messageCount + page.runs.length * 2;
|
|
95
|
+
if (messageCount > this.core.sessionImportLimits.maxMessagesPerSession) {
|
|
96
|
+
throw new FlexHarnessValidationError(`An imported session holds at most ${this.core.sessionImportLimits.maxMessagesPerSession} messages.`);
|
|
97
|
+
}
|
|
98
|
+
const bytes = staged.bytes + page.bytes;
|
|
99
|
+
if (bytes > this.core.sessionImportLimits.maxSessionBytes) {
|
|
100
|
+
throw new FlexHarnessValidationError(`An imported session holds at most ${this.core.sessionImportLimits.maxSessionBytes} message bytes.`);
|
|
101
|
+
}
|
|
102
|
+
staged.runs.push(...page.runs);
|
|
103
|
+
for (const runId of runIds)
|
|
104
|
+
staged.runIds.add(runId);
|
|
105
|
+
for (const messageId of messageIds)
|
|
106
|
+
staged.messageIds.add(messageId);
|
|
107
|
+
staged.messageCount = messageCount;
|
|
108
|
+
staged.bytes = bytes;
|
|
109
|
+
this.armStagedImportIdleTimer(staged);
|
|
110
|
+
return publicSnapshot({ runs: staged.runs.length, messages: messageCount, bytes });
|
|
111
|
+
}
|
|
112
|
+
async commitSessionImport(handle) {
|
|
113
|
+
const staged = this.requireStagedSessionImport(handle);
|
|
114
|
+
this.core.assertOpen();
|
|
115
|
+
const { state, scopeId, sessionId, options } = staged;
|
|
116
|
+
this.core.assertStateAcceptingWork(state);
|
|
117
|
+
if (staged.runs.length === 0) {
|
|
118
|
+
throw new FlexHarnessValidationError('A session import needs at least one run before it is committed.');
|
|
119
|
+
}
|
|
120
|
+
staged.phase = 'committing';
|
|
121
|
+
this.clearStagedImportIdleTimer(staged);
|
|
122
|
+
const scope = staged.scope;
|
|
123
|
+
let resolveInitialization;
|
|
124
|
+
const initialization = new Promise((resolve) => {
|
|
125
|
+
resolveInitialization = resolve;
|
|
126
|
+
});
|
|
127
|
+
let initializationCompleted = false;
|
|
128
|
+
const completeInitialization = () => {
|
|
129
|
+
if (initializationCompleted)
|
|
130
|
+
return;
|
|
131
|
+
initializationCompleted = true;
|
|
132
|
+
if (state.sessionInitializations.get(sessionId) === initialization) {
|
|
133
|
+
state.sessionInitializations.delete(sessionId);
|
|
134
|
+
}
|
|
135
|
+
resolveInitialization();
|
|
136
|
+
};
|
|
137
|
+
state.sessionInitializations.set(sessionId, initialization);
|
|
138
|
+
const importedAt = new Date().toISOString();
|
|
139
|
+
const origin = {
|
|
140
|
+
kind: 'import',
|
|
141
|
+
...cloneSerializable(options.origin),
|
|
142
|
+
importedAt,
|
|
143
|
+
};
|
|
144
|
+
let metadata;
|
|
145
|
+
let reserved = false;
|
|
146
|
+
let loaded;
|
|
147
|
+
try {
|
|
148
|
+
// A tombstone reserves the id while the projection is written, so a crash before the session
|
|
149
|
+
// is published leaves only data that the next load or deletion cleans up.
|
|
150
|
+
await this.core.mutateScope(state, () => {
|
|
151
|
+
if (state.sessions.has(sessionId) || state.tombstones.has(sessionId)) {
|
|
152
|
+
throw this.core.trustInternalError(new FlexHarnessValidationError(`Session "${sessionId}" already exists or is being deleted.`));
|
|
153
|
+
}
|
|
154
|
+
const parent = options.parent
|
|
155
|
+
? this.requireImportParent(state, sessionId, options.parent)
|
|
156
|
+
: undefined;
|
|
157
|
+
metadata = {
|
|
158
|
+
scopeId,
|
|
159
|
+
sessionId,
|
|
160
|
+
sessionGenerationId: createSessionGenerationId(),
|
|
161
|
+
sessionGenerationSequence: state.revision + 1,
|
|
162
|
+
...(parent?.session.configurationRef === undefined
|
|
163
|
+
? {}
|
|
164
|
+
: { configurationRef: parent.session.configurationRef }),
|
|
165
|
+
...(options.title === undefined ? {} : { title: options.title }),
|
|
166
|
+
createdAt: options.createdAt,
|
|
167
|
+
updatedAt: options.updatedAt,
|
|
168
|
+
archivedAt: importedAt,
|
|
169
|
+
status: 'idle',
|
|
170
|
+
activity: { status: 'idle' },
|
|
171
|
+
...(options.parent === undefined
|
|
172
|
+
? {}
|
|
173
|
+
: {
|
|
174
|
+
parentSessionId: options.parent.sessionId,
|
|
175
|
+
parentRunId: options.parent.runId,
|
|
176
|
+
parentToolCallId: options.parent.toolCallId,
|
|
177
|
+
agent: options.parent.agent,
|
|
178
|
+
}),
|
|
179
|
+
depth: parent === undefined ? 0 : (parent.session.depth ?? 0) + 1,
|
|
180
|
+
origin,
|
|
181
|
+
};
|
|
182
|
+
state.tombstones.set(sessionId, {
|
|
183
|
+
sessionId,
|
|
184
|
+
...requireSessionGeneration(metadata),
|
|
185
|
+
deletedAt: importedAt,
|
|
186
|
+
rootSessionId: sessionId,
|
|
187
|
+
depth: 0,
|
|
188
|
+
imported: true,
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
reserved = true;
|
|
192
|
+
await this.core.stores.projections.save(state.storageKey, sessionId, {
|
|
193
|
+
schemaVersion: 3,
|
|
194
|
+
revision: 1,
|
|
195
|
+
metrics: createSessionMetricsState(false),
|
|
196
|
+
messages: staged.runs.flatMap((run) => [run.user, run.assistant]),
|
|
197
|
+
stagedTerminals: [],
|
|
198
|
+
reversionSegments: [],
|
|
199
|
+
revertCursor: 0,
|
|
200
|
+
excludedRunIds: [],
|
|
201
|
+
pendingReversionReleases: [],
|
|
202
|
+
}, 0);
|
|
203
|
+
const runtime = await this.core.loadSessionRuntime(state, metadata, scopeId, scope);
|
|
204
|
+
loaded = runtime;
|
|
205
|
+
await this.core.mutateScope(state, () => {
|
|
206
|
+
if (state.sessions.has(sessionId)
|
|
207
|
+
|| state.tombstones.get(sessionId)?.sessionGenerationId !== metadata.sessionGenerationId) {
|
|
208
|
+
throw this.core.trustInternalError(new FlexHarnessAbortError('The session import lost its reservation before it was committed.'));
|
|
209
|
+
}
|
|
210
|
+
if (options.parent)
|
|
211
|
+
this.requireImportParent(state, sessionId, options.parent);
|
|
212
|
+
state.tombstones.delete(sessionId);
|
|
213
|
+
state.sessions.set(sessionId, runtime);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
const projected = this.core.projectOperationError(error, 'persistence', scopeId, sessionId, 'session-import');
|
|
218
|
+
const errors = [projected];
|
|
219
|
+
if (loaded && state.sessions.get(sessionId) !== loaded) {
|
|
220
|
+
try {
|
|
221
|
+
await this.core.lifecycle.closeStoredSession(loaded);
|
|
222
|
+
}
|
|
223
|
+
catch (closeError) {
|
|
224
|
+
this.core.lifecycle.orphanedStoredSessions.add(loaded);
|
|
225
|
+
errors.push(closeError);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// A fenced namespace cannot tell whether its last save was persisted; its next load resolves
|
|
229
|
+
// the reservation instead: a surviving tombstone is cleaned up, a published session is kept.
|
|
230
|
+
if (reserved && state.tombstones.has(sessionId) && state.lifecycle !== 'fenced') {
|
|
231
|
+
completeInitialization();
|
|
232
|
+
try {
|
|
233
|
+
await this.core.deletion.finishTombstoneCleanup(state, sessionId, scopeId, { scopeId, scope });
|
|
234
|
+
}
|
|
235
|
+
catch (cleanupError) {
|
|
236
|
+
errors.push(this.core.projectOperationError(cleanupError, 'persistence', scopeId, sessionId, 'session-import-cleanup'));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
throw combineErrors(errors);
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
this.releaseStagedSessionImport(staged);
|
|
243
|
+
completeInitialization();
|
|
244
|
+
}
|
|
245
|
+
const result = publicSnapshot(metadata);
|
|
246
|
+
this.core.emitEvent(scopeId, metadata, { type: 'session.created', session: result });
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
async abortSessionImport(handle) {
|
|
250
|
+
const staged = this.findStagedSessionImport(handle);
|
|
251
|
+
if (!staged)
|
|
252
|
+
return;
|
|
253
|
+
if (staged.phase === 'committing') {
|
|
254
|
+
throw new FlexHarnessSessionBusyError(staged.sessionId, 'is being committed');
|
|
255
|
+
}
|
|
256
|
+
this.releaseStagedSessionImport(staged);
|
|
257
|
+
}
|
|
258
|
+
assertNoCommittingSessionImport(state, sessionId) {
|
|
259
|
+
if (state.sessionImports.get(sessionId)?.phase === 'committing') {
|
|
260
|
+
throw new FlexHarnessSessionBusyError(sessionId, 'is being imported');
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
findStagedSessionImport(handle) {
|
|
264
|
+
const validated = validateSessionImportHandle(handle);
|
|
265
|
+
const staged = this.stagedSessionImports.get(validated.importId);
|
|
266
|
+
if (staged
|
|
267
|
+
&& (staged.scopeId !== validated.scopeId || staged.sessionId !== validated.sessionId)) {
|
|
268
|
+
throw new FlexHarnessValidationError('The session import handle does not match its import.');
|
|
269
|
+
}
|
|
270
|
+
return staged;
|
|
271
|
+
}
|
|
272
|
+
requireStagedSessionImport(handle) {
|
|
273
|
+
const staged = this.findStagedSessionImport(handle);
|
|
274
|
+
if (!staged)
|
|
275
|
+
throw new FlexHarnessNotFoundError('Session import', handle.importId);
|
|
276
|
+
if (staged.phase !== 'staging') {
|
|
277
|
+
throw new FlexHarnessSessionBusyError(staged.sessionId, 'is being committed');
|
|
278
|
+
}
|
|
279
|
+
return staged;
|
|
280
|
+
}
|
|
281
|
+
armStagedImportIdleTimer(staged) {
|
|
282
|
+
this.clearStagedImportIdleTimer(staged);
|
|
283
|
+
const timer = setTimeout(() => {
|
|
284
|
+
if (staged.idleTimer !== timer)
|
|
285
|
+
return;
|
|
286
|
+
delete staged.idleTimer;
|
|
287
|
+
if (staged.phase === 'staging')
|
|
288
|
+
this.releaseStagedSessionImport(staged);
|
|
289
|
+
}, this.core.sessionImportLimits.stagedImportIdleTimeoutMs);
|
|
290
|
+
timer.unref();
|
|
291
|
+
staged.idleTimer = timer;
|
|
292
|
+
}
|
|
293
|
+
clearStagedImportIdleTimer(staged) {
|
|
294
|
+
if (staged.idleTimer === undefined)
|
|
295
|
+
return;
|
|
296
|
+
clearTimeout(staged.idleTimer);
|
|
297
|
+
delete staged.idleTimer;
|
|
298
|
+
}
|
|
299
|
+
releaseStagedSessionImport(staged) {
|
|
300
|
+
this.clearStagedImportIdleTimer(staged);
|
|
301
|
+
if (this.stagedSessionImports.get(staged.importId) === staged) {
|
|
302
|
+
this.stagedSessionImports.delete(staged.importId);
|
|
303
|
+
}
|
|
304
|
+
if (staged.state.sessionImports.get(staged.sessionId) === staged) {
|
|
305
|
+
staged.state.sessionImports.delete(staged.sessionId);
|
|
306
|
+
staged.state.initializingSessions.delete(staged.sessionId);
|
|
307
|
+
}
|
|
308
|
+
staged.runs = [];
|
|
309
|
+
staged.runIds.clear();
|
|
310
|
+
staged.messageIds.clear();
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* An imported child session belongs to a committed imported parent whose run `parent.runId` holds
|
|
314
|
+
* the tool call `parent.toolCallId` naming the child, and no other session claims that tool call.
|
|
315
|
+
*/
|
|
316
|
+
requireImportParent(state, sessionId, parent) {
|
|
317
|
+
const parentStored = state.initializingSessions.has(parent.sessionId)
|
|
318
|
+
|| state.tombstones.has(parent.sessionId)
|
|
319
|
+
? undefined
|
|
320
|
+
: state.sessions.get(parent.sessionId);
|
|
321
|
+
if (!parentStored?.session.origin) {
|
|
322
|
+
throw this.core.trustInternalError(new FlexHarnessValidationError(`The parent of imported session "${sessionId}" must be a committed imported session.`));
|
|
323
|
+
}
|
|
324
|
+
if ((parentStored.session.depth ?? 0) + 1 > FLEX_SESSION_IMPORT_MAX_DEPTH) {
|
|
325
|
+
throw this.core.trustInternalError(new FlexHarnessValidationError(`Imported sessions nest at most ${FLEX_SESSION_IMPORT_MAX_DEPTH} levels deep.`));
|
|
326
|
+
}
|
|
327
|
+
const referenced = parentStored.messages.some((message) => message.role === 'assistant'
|
|
328
|
+
&& message.runId === parent.runId
|
|
329
|
+
&& message.parts.some((part) => part.type === 'tool'
|
|
330
|
+
&& part.toolCallId === parent.toolCallId
|
|
331
|
+
&& part.childSessionId === sessionId));
|
|
332
|
+
if (!referenced) {
|
|
333
|
+
throw this.core.trustInternalError(new FlexHarnessValidationError(`Parent run "${parent.runId}" has no tool call "${parent.toolCallId}" whose childSessionId is "${sessionId}".`));
|
|
334
|
+
}
|
|
335
|
+
for (const stored of state.sessions.values()) {
|
|
336
|
+
if (stored.session.parentSessionId === parent.sessionId
|
|
337
|
+
&& stored.session.parentRunId === parent.runId
|
|
338
|
+
&& stored.session.parentToolCallId === parent.toolCallId) {
|
|
339
|
+
throw this.core.trustInternalError(new FlexHarnessValidationError(`Session "${stored.session.sessionId}" already belongs to tool call "${parent.toolCallId}".`));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return parentStored;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mbGV4aGFybmVzcy5pbXBvcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5mbGV4aGFybmVzcy5pbXBvcnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsd0JBQXdCLEVBQ3hCLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0IsMEJBQTBCLEdBQzNCLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFDTCw2QkFBNkIsR0FROUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUNMLGtDQUFrQyxFQUNsQyx3QkFBd0IsRUFDeEIscUJBQXFCLEVBQ3JCLDJCQUEyQixHQUU1QixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBTXRFLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsd0JBQXdCLEVBQ3hCLGFBQWEsR0FDZCxNQUFNLHdCQUF3QixDQUFDO0FBR2hDLHNFQUFzRTtBQUN0RSxNQUFNLE9BQU8seUJBQXlCO0lBR1AsSUFBSTtJQUZoQixvQkFBb0IsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztJQUVoRixZQUE2QixJQUE2QjtvQkFBN0IsSUFBSTtJQUE0QixDQUFDO0lBRXZELEtBQUssQ0FBQyxrQkFBa0IsQ0FDN0IsT0FBZSxFQUNmLE9BQXVDO1FBRXZDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDdkIsTUFBTSxVQUFVLEdBQUcsa0NBQWtDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0QsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVB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
|