@modelprofile.com/flexharness 10.23.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.
Files changed (83) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/classes.flexharness.admission.d.ts +17 -0
  3. package/dist_ts/classes.flexharness.admission.js +263 -0
  4. package/dist_ts/classes.flexharness.callbacks.d.ts +38 -0
  5. package/dist_ts/classes.flexharness.callbacks.js +313 -0
  6. package/dist_ts/classes.flexharness.compaction.d.ts +25 -0
  7. package/dist_ts/classes.flexharness.compaction.js +87 -0
  8. package/dist_ts/classes.flexharness.configurations.d.ts +11 -0
  9. package/dist_ts/classes.flexharness.configurations.js +137 -0
  10. package/dist_ts/classes.flexharness.core.d.ts +143 -0
  11. package/dist_ts/classes.flexharness.core.js +1538 -0
  12. package/dist_ts/classes.flexharness.d.ts +2 -437
  13. package/dist_ts/classes.flexharness.deletion.d.ts +31 -0
  14. package/dist_ts/classes.flexharness.deletion.js +396 -0
  15. package/dist_ts/classes.flexharness.imports.d.ts +24 -0
  16. package/dist_ts/classes.flexharness.imports.js +345 -0
  17. package/dist_ts/classes.flexharness.js +119 -9776
  18. package/dist_ts/classes.flexharness.lifecycle.d.ts +47 -0
  19. package/dist_ts/classes.flexharness.lifecycle.js +625 -0
  20. package/dist_ts/classes.flexharness.permissions.d.ts +19 -0
  21. package/dist_ts/classes.flexharness.permissions.js +450 -0
  22. package/dist_ts/classes.flexharness.projects.d.ts +55 -0
  23. package/dist_ts/classes.flexharness.projects.js +575 -0
  24. package/dist_ts/classes.flexharness.prompts.d.ts +44 -0
  25. package/dist_ts/classes.flexharness.prompts.js +659 -0
  26. package/dist_ts/classes.flexharness.providers.d.ts +18 -0
  27. package/dist_ts/classes.flexharness.providers.js +267 -0
  28. package/dist_ts/classes.flexharness.results.d.ts +26 -0
  29. package/dist_ts/classes.flexharness.results.js +89 -0
  30. package/dist_ts/classes.flexharness.reversions.d.ts +52 -0
  31. package/dist_ts/classes.flexharness.reversions.js +1306 -0
  32. package/dist_ts/classes.flexharness.runs.d.ts +63 -0
  33. package/dist_ts/classes.flexharness.runs.js +1058 -0
  34. package/dist_ts/classes.flexharness.sessions.d.ts +20 -0
  35. package/dist_ts/classes.flexharness.sessions.js +381 -0
  36. package/dist_ts/classes.flexharness.slashcommands.d.ts +40 -0
  37. package/dist_ts/classes.flexharness.slashcommands.js +458 -0
  38. package/dist_ts/classes.flexharness.subagents.d.ts +31 -0
  39. package/dist_ts/classes.flexharness.subagents.js +690 -0
  40. package/dist_ts/classes.flexharness.tooldispatch.d.ts +53 -0
  41. package/dist_ts/classes.flexharness.tooldispatch.js +418 -0
  42. package/dist_ts/interfaces.flexharness.d.ts +455 -0
  43. package/dist_ts/interfaces.flexharness.js +2 -0
  44. package/dist_ts/utils.flexharness.d.ts +19 -0
  45. package/dist_ts/utils.flexharness.js +83 -0
  46. package/dist_ts_compaction/plugins.d.ts +2 -2
  47. package/dist_ts_compaction/plugins.js +3 -3
  48. package/dist_ts_compaction/smartagent.compaction.js +6 -5
  49. package/dist_ts_stores_nosqldb/classes.nosqldbstores.d.ts +9 -0
  50. package/dist_ts_stores_nosqldb/classes.nosqldbstores.js +13 -1
  51. package/dist_ts_stores_nosqldb/classes.recordstore.d.ts +2 -2
  52. package/dist_ts_stores_nosqldb/classes.recordstore.js +3 -3
  53. package/package.json +3 -3
  54. package/readme.md +1 -1
  55. package/ts/00_commitinfo_data.ts +1 -1
  56. package/ts/classes.flexharness.admission.ts +331 -0
  57. package/ts/classes.flexharness.callbacks.ts +352 -0
  58. package/ts/classes.flexharness.compaction.ts +167 -0
  59. package/ts/classes.flexharness.configurations.ts +167 -0
  60. package/ts/classes.flexharness.core.ts +1830 -0
  61. package/ts/classes.flexharness.deletion.ts +616 -0
  62. package/ts/classes.flexharness.imports.ts +414 -0
  63. package/ts/classes.flexharness.lifecycle.ts +786 -0
  64. package/ts/classes.flexharness.permissions.ts +535 -0
  65. package/ts/classes.flexharness.projects.ts +1006 -0
  66. package/ts/classes.flexharness.prompts.ts +857 -0
  67. package/ts/classes.flexharness.providers.ts +322 -0
  68. package/ts/classes.flexharness.results.ts +98 -0
  69. package/ts/classes.flexharness.reversions.ts +1684 -0
  70. package/ts/classes.flexharness.runs.ts +1204 -0
  71. package/ts/classes.flexharness.sessions.ts +483 -0
  72. package/ts/classes.flexharness.slashcommands.ts +705 -0
  73. package/ts/classes.flexharness.subagents.ts +860 -0
  74. package/ts/classes.flexharness.tooldispatch.ts +475 -0
  75. package/ts/classes.flexharness.ts +147 -12567
  76. package/ts/interfaces.flexharness.ts +517 -0
  77. package/ts/readme.md +1 -1
  78. package/ts/utils.flexharness.ts +121 -0
  79. package/ts_compaction/plugins.ts +2 -2
  80. package/ts_compaction/smartagent.compaction.ts +5 -4
  81. package/ts_stores_nosqldb/classes.nosqldbstores.ts +13 -0
  82. package/ts_stores_nosqldb/classes.recordstore.ts +5 -5
  83. package/ts_stores_nosqldb/readme.md +7 -0
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mbGV4aGFybmVzcy5pbXBvcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5mbGV4aGFybmVzcy5pbXBvcnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsd0JBQXdCLEVBQ3hCLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0IsMEJBQTBCLEdBQzNCLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFDTCw2QkFBNkIsR0FROUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUNMLGtDQUFrQyxFQUNsQyx3QkFBd0IsRUFDeEIscUJBQXFCLEVBQ3JCLDJCQUEyQixHQUU1QixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBTXRFLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsd0JBQXdCLEVBQ3hCLGFBQWEsR0FDZCxNQUFNLHdCQUF3QixDQUFDO0FBR2hDLHNFQUFzRTtBQUN0RSxNQUFNLE9BQU8seUJBQXlCO0lBR1A7SUFGWixvQkFBb0IsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztJQUVoRixZQUE2QixJQUE2QjtRQUE3QixTQUFJLEdBQUosSUFBSSxDQUF5QjtJQUFHLENBQUM7SUFFdkQsS0FBSyxDQUFDLGtCQUFrQixDQUM3QixPQUFlLEVBQ2YsT0FBdUM7UUFFdkMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN2QixNQUFNLFVBQVUsR0FBRyxrQ0FBa0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvRCxNQUFNLEVBQUUsS0FBSyxFQUFF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