@modelprofile.com/flexharness 10.17.1 → 10.18.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 +1 -1
- package/dist_ts/errors.d.ts +4 -0
- package/dist_ts/errors.js +9 -1
- package/dist_ts/functions.toolpermissions.d.ts +24 -0
- package/dist_ts/functions.toolpermissions.js +38 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/plugins.d.ts +1 -1
- package/dist_ts/plugins.js +1 -1
- package/dist_ts_chat_harness/classes.chatclient.d.ts +95 -0
- package/dist_ts_chat_harness/classes.chatclient.js +263 -0
- package/dist_ts_chat_harness/classes.chatrequesterror.d.ts +4 -0
- package/dist_ts_chat_harness/classes.chatrequesterror.js +8 -0
- package/dist_ts_chat_harness/classes.transcript.d.ts +1 -1
- package/dist_ts_chat_harness/classes.transcript.js +1 -1
- package/dist_ts_chat_harness/functions.intents.d.ts +1 -2
- 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/index.d.ts +3 -0
- package/dist_ts_chat_harness/index.js +3 -1
- package/dist_ts_chat_harness/interfaces.chat.d.ts +136 -0
- package/dist_ts_chat_harness/interfaces.chat.js +2 -0
- package/dist_ts_chat_harness/plugins.js +1 -1
- package/dist_ts_chat_harness_server/classes.chathub.d.ts +78 -0
- package/dist_ts_chat_harness_server/classes.chathub.js +332 -0
- package/dist_ts_chat_harness_server/classes.chatsubscription.d.ts +55 -0
- package/dist_ts_chat_harness_server/classes.chatsubscription.js +236 -0
- package/dist_ts_chat_harness_server/classes.sessionlists.d.ts +21 -0
- package/dist_ts_chat_harness_server/classes.sessionlists.js +70 -0
- package/dist_ts_chat_harness_server/classes.turngate.d.ts +38 -0
- package/dist_ts_chat_harness_server/classes.turngate.js +207 -0
- package/dist_ts_chat_harness_server/errors.d.ts +5 -0
- package/dist_ts_chat_harness_server/errors.js +9 -0
- package/dist_ts_chat_harness_server/functions.errorprojector.d.ts +11 -0
- package/dist_ts_chat_harness_server/functions.errorprojector.js +32 -0
- package/dist_ts_chat_harness_server/functions.validation.d.ts +18 -0
- package/dist_ts_chat_harness_server/functions.validation.js +88 -0
- package/dist_ts_chat_harness_server/index.d.ts +4 -0
- package/dist_ts_chat_harness_server/index.js +4 -0
- package/dist_ts_chat_harness_server/interfaces.d.ts +67 -0
- package/dist_ts_chat_harness_server/interfaces.js +2 -0
- package/dist_ts_chat_harness_server/plugins.d.ts +7 -0
- package/dist_ts_chat_harness_server/plugins.js +6 -0
- package/dist_ts_chat_harness_typedsocket/classes.clienttransport.d.ts +22 -0
- package/dist_ts_chat_harness_typedsocket/classes.clienttransport.js +55 -0
- package/dist_ts_chat_harness_typedsocket/classes.serverbinding.d.ts +46 -0
- package/dist_ts_chat_harness_typedsocket/classes.serverbinding.js +110 -0
- package/dist_ts_chat_harness_typedsocket/index.d.ts +3 -0
- package/dist_ts_chat_harness_typedsocket/index.js +3 -0
- package/dist_ts_chat_harness_typedsocket/interfaces.requests.d.ts +38 -0
- package/dist_ts_chat_harness_typedsocket/interfaces.requests.js +2 -0
- package/dist_ts_chat_harness_typedsocket/plugins.d.ts +9 -0
- package/dist_ts_chat_harness_typedsocket/plugins.js +8 -0
- package/dist_ts_tools/tool.filesystem.d.ts +2 -0
- package/dist_ts_tools/tool.filesystem.js +42 -1
- package/dist_ts_tools_node/classes.workspacereversion.d.ts +48 -0
- package/dist_ts_tools_node/classes.workspacereversion.js +202 -0
- package/dist_ts_tools_node/functions.fileimages.d.ts +22 -0
- package/dist_ts_tools_node/functions.fileimages.js +87 -0
- package/dist_ts_tools_node/index.d.ts +3 -1
- package/dist_ts_tools_node/index.js +2 -1
- package/dist_ts_tools_node/plugins.d.ts +1 -0
- package/dist_ts_tools_node/tool.context.d.ts +20 -0
- package/dist_ts_tools_node/tool.context.js +25 -4
- package/package.json +28 -4
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/errors.ts +10 -0
- package/ts/functions.toolpermissions.ts +60 -0
- package/ts/index.ts +6 -0
- package/ts/plugins.ts +1 -0
- package/ts_chat_harness/classes.chatclient.ts +343 -0
- package/ts_chat_harness/classes.chatrequesterror.ts +7 -0
- package/ts_chat_harness/classes.transcript.ts +1 -1
- package/ts_chat_harness/functions.intents.ts +2 -2
- package/ts_chat_harness/functions.mapping.ts +1 -1
- package/ts_chat_harness/index.ts +20 -0
- package/ts_chat_harness/interfaces.chat.ts +108 -0
- package/ts_chat_harness/readme.md +24 -0
- package/ts_chat_harness_server/classes.chathub.ts +400 -0
- package/ts_chat_harness_server/classes.chatsubscription.ts +257 -0
- package/ts_chat_harness_server/classes.sessionlists.ts +90 -0
- package/ts_chat_harness_server/classes.turngate.ts +247 -0
- package/ts_chat_harness_server/errors.ts +9 -0
- package/ts_chat_harness_server/functions.errorprojector.ts +40 -0
- package/ts_chat_harness_server/functions.validation.ts +104 -0
- package/ts_chat_harness_server/index.ts +19 -0
- package/ts_chat_harness_server/interfaces.ts +92 -0
- package/ts_chat_harness_server/plugins.ts +62 -0
- package/ts_chat_harness_server/readme.md +91 -0
- package/ts_chat_harness_typedsocket/classes.clienttransport.ts +87 -0
- package/ts_chat_harness_typedsocket/classes.serverbinding.ts +172 -0
- package/ts_chat_harness_typedsocket/index.ts +17 -0
- package/ts_chat_harness_typedsocket/interfaces.requests.ts +40 -0
- package/ts_chat_harness_typedsocket/plugins.ts +28 -0
- package/ts_chat_harness_typedsocket/readme.md +57 -0
- package/ts_tools/readme.md +10 -0
- package/ts_tools/tool.filesystem.ts +55 -0
- package/ts_tools_node/classes.workspacereversion.ts +255 -0
- package/ts_tools_node/functions.fileimages.ts +89 -0
- package/ts_tools_node/index.ts +7 -1
- package/ts_tools_node/plugins.ts +11 -0
- package/ts_tools_node/readme.md +27 -0
- package/ts_tools_node/tool.context.ts +49 -3
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { FlexHarnessChatSessionLists } from './classes.sessionlists.js';
|
|
3
|
+
import { FlexHarnessChatSubscription } from './classes.chatsubscription.js';
|
|
4
|
+
import { FlexHarnessChatTurnGate } from './classes.turngate.js';
|
|
5
|
+
import { FlexHarnessChatRequestError, FlexHarnessChatTabUnavailableError } from './errors.js';
|
|
6
|
+
import { BAD_REQUEST_MESSAGE, STOPPED_MESSAGE, isSameTab, readRandomId, tabKey, readSendDetail, readSessionId, readTitle, titleFromMessage, } from './functions.validation.js';
|
|
7
|
+
const NOT_FOUND_MESSAGE = 'This conversation does not exist.';
|
|
8
|
+
const READ_ONLY_MESSAGE = 'This conversation was imported and can only be read. Start a new conversation to continue.';
|
|
9
|
+
const DECISIONS = ['once', 'always', 'reject'];
|
|
10
|
+
export const defaultFlexHarnessChatLimits = Object.freeze({
|
|
11
|
+
turnTimeoutMs: 10 * 60 * 1000,
|
|
12
|
+
admissionWaitMs: 30 * 1000,
|
|
13
|
+
toolTimeoutMs: 2 * 60 * 1000,
|
|
14
|
+
maxPendingDeltas: 2_000,
|
|
15
|
+
maxMessageChars: 100_000,
|
|
16
|
+
maxAttachments: 16,
|
|
17
|
+
maxAttachmentChars: 8 * 1024 * 1024,
|
|
18
|
+
maxTitleChars: 200,
|
|
19
|
+
sweepIntervalMs: 5 * 60 * 1000,
|
|
20
|
+
});
|
|
21
|
+
/** A conversation as a session list shows it; an imported one says so. */
|
|
22
|
+
export const flexHarnessChatSessionMeta = (sessionArg) => ({
|
|
23
|
+
...plugins.flexSessionToHarnessMeta(sessionArg),
|
|
24
|
+
...(sessionArg.origin?.kind === 'import' ? { statusLabel: 'Imported' } : {}),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Serves `dees-harness-chat` conversations of one FlexHarness to browser tabs, over any transport:
|
|
28
|
+
* a tab attaches, follows one conversation through numbered updates, sends messages that start or
|
|
29
|
+
* steer a turn, stops turns, answers permission requests, undoes and redoes turns, and renames and
|
|
30
|
+
* deletes conversations. A turn runs the tools the host gives it; `runClientTool()` runs one in the
|
|
31
|
+
* tab that started the turn.
|
|
32
|
+
*
|
|
33
|
+
* The host authenticates every request and names its caller: the tab and the scope it may reach. A
|
|
34
|
+
* session of another scope reads as not found. `stop()` stops the turns the hub started, its
|
|
35
|
+
* subscriptions and its timers; the harness stays the host's.
|
|
36
|
+
*/
|
|
37
|
+
export class FlexHarnessChatHub {
|
|
38
|
+
limits;
|
|
39
|
+
harness;
|
|
40
|
+
peers;
|
|
41
|
+
readContext;
|
|
42
|
+
titleOf;
|
|
43
|
+
gate;
|
|
44
|
+
sessionLists;
|
|
45
|
+
subscriptions = new Map();
|
|
46
|
+
unsubscribe;
|
|
47
|
+
sweepTimer;
|
|
48
|
+
/** the requests under way that may start a turn or a subscription; `stop()` waits for them */
|
|
49
|
+
requestsUnderWay = new Set();
|
|
50
|
+
/** the sequence of the last harness event the hub received */
|
|
51
|
+
lastSequence;
|
|
52
|
+
stopped = false;
|
|
53
|
+
constructor(optionsArg) {
|
|
54
|
+
this.limits = Object.freeze({ ...defaultFlexHarnessChatLimits, ...optionsArg.limits });
|
|
55
|
+
this.harness = optionsArg.harness;
|
|
56
|
+
this.peers = optionsArg.peers;
|
|
57
|
+
this.readContext = optionsArg.readContext;
|
|
58
|
+
this.titleOf = optionsArg.titleOf ?? titleFromMessage;
|
|
59
|
+
this.gate = new FlexHarnessChatTurnGate(this.harness, this.limits);
|
|
60
|
+
this.sessionLists = new FlexHarnessChatSessionLists(this.peers, flexHarnessChatSessionMeta);
|
|
61
|
+
this.unsubscribe = this.harness.subscribe((eventArg) => this.takeEvent(eventArg));
|
|
62
|
+
this.sweepTimer = setInterval(() => void this.forgetClosedTabs(), this.limits.sweepIntervalMs);
|
|
63
|
+
this.sweepTimer.unref?.();
|
|
64
|
+
}
|
|
65
|
+
// ---------------- requests ----------------
|
|
66
|
+
/** Attaches a tab: it follows nothing until it opens a conversation again. */
|
|
67
|
+
async attach(callerArg) {
|
|
68
|
+
this.assertRunning();
|
|
69
|
+
this.closeSubscriptionsOf(callerArg);
|
|
70
|
+
this.sessionLists.attach(callerArg);
|
|
71
|
+
const sessions = await this.call(() => this.harness.listSessions(callerArg.scopeId));
|
|
72
|
+
return {
|
|
73
|
+
sessions: sessions
|
|
74
|
+
.filter((session) => !session.parentSessionId)
|
|
75
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))
|
|
76
|
+
.map(flexHarnessChatSessionMeta),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
open(callerArg, requestArg) {
|
|
80
|
+
return this.underWay(() => this.openUnderWay(callerArg, requestArg));
|
|
81
|
+
}
|
|
82
|
+
async openUnderWay(callerArg, requestArg) {
|
|
83
|
+
this.assertRunning();
|
|
84
|
+
const subscriptionId = readRandomId(requestArg?.subscriptionId);
|
|
85
|
+
const session = await this.requireSession(callerArg, requestArg.sessionId);
|
|
86
|
+
this.assertRunning();
|
|
87
|
+
if (this.subscriptions.has(subscriptionId))
|
|
88
|
+
throw new FlexHarnessChatRequestError(BAD_REQUEST_MESSAGE);
|
|
89
|
+
this.closeSubscriptionsOf(callerArg);
|
|
90
|
+
const subscription = new FlexHarnessChatSubscription({
|
|
91
|
+
id: subscriptionId,
|
|
92
|
+
tabId: callerArg.tabId,
|
|
93
|
+
scopeId: callerArg.scopeId,
|
|
94
|
+
sessionId: session.sessionId,
|
|
95
|
+
harness: this.harness,
|
|
96
|
+
peers: this.peers,
|
|
97
|
+
limits: this.limits,
|
|
98
|
+
onClosed: (closedArg) => this.forgetSubscription(closedArg),
|
|
99
|
+
});
|
|
100
|
+
// subscribed before the session is read: what changes meanwhile is buffered, not lost
|
|
101
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
102
|
+
try {
|
|
103
|
+
await subscription.load();
|
|
104
|
+
this.assertRunning();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
this.closeSubscription(subscription);
|
|
108
|
+
throw this.toRequestError(error);
|
|
109
|
+
}
|
|
110
|
+
return { session: flexHarnessChatSessionMeta(session), readOnly: session.origin?.kind === 'import' };
|
|
111
|
+
}
|
|
112
|
+
async close(callerArg, requestArg) {
|
|
113
|
+
const subscription = this.subscriptions.get(requestArg?.subscriptionId);
|
|
114
|
+
if (subscription && isSameTab(subscription, callerArg))
|
|
115
|
+
this.closeSubscription(subscription);
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
send(callerArg, requestArg) {
|
|
119
|
+
// the wait for a turn that is ending counts from here
|
|
120
|
+
const deadline = Date.now() + this.limits.admissionWaitMs;
|
|
121
|
+
return this.underWay(() => this.sendUnderWay(callerArg, requestArg, deadline));
|
|
122
|
+
}
|
|
123
|
+
async sendUnderWay(callerArg, requestArg, deadlineArg) {
|
|
124
|
+
this.assertRunning();
|
|
125
|
+
const send = readSendDetail(requestArg?.send, this.limits);
|
|
126
|
+
const context = this.readSendContext(requestArg.context);
|
|
127
|
+
let sessionId;
|
|
128
|
+
let created = false;
|
|
129
|
+
if (requestArg.sessionId === undefined) {
|
|
130
|
+
sessionId = (await this.call(() => this.harness.createSession(callerArg.scopeId, { title: this.titleOf(send) }))).sessionId;
|
|
131
|
+
created = true;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const session = await this.requireSession(callerArg, requestArg.sessionId);
|
|
135
|
+
if (session.origin?.kind === 'import')
|
|
136
|
+
throw new FlexHarnessChatRequestError(READ_ONLY_MESSAGE);
|
|
137
|
+
sessionId = session.sessionId;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
// the hub may have stopped while the conversation was read or created
|
|
141
|
+
this.assertRunning();
|
|
142
|
+
return await this.gate.admit(callerArg, sessionId, send, context, deadlineArg);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
// a conversation created for this message that never got it is not kept
|
|
146
|
+
if (created && !(error instanceof plugins.FlexHarnessClosedError)) {
|
|
147
|
+
await this.harness.deleteSession(callerArg.scopeId, sessionId).catch(() => undefined);
|
|
148
|
+
}
|
|
149
|
+
throw this.toRequestError(error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async abort(callerArg, requestArg) {
|
|
153
|
+
const session = await this.requireSession(callerArg, requestArg?.sessionId);
|
|
154
|
+
await this.call(() => this.harness.abort(callerArg.scopeId, session.sessionId));
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
async respondToPermission(callerArg, requestArg) {
|
|
158
|
+
const session = await this.requireSession(callerArg, requestArg?.sessionId);
|
|
159
|
+
if (typeof requestArg.permissionId !== 'string' || !DECISIONS.includes(requestArg.decision)) {
|
|
160
|
+
throw new FlexHarnessChatRequestError(BAD_REQUEST_MESSAGE);
|
|
161
|
+
}
|
|
162
|
+
await this.call(() => this.harness.respondToPermission(callerArg.scopeId, session.sessionId, requestArg.permissionId, requestArg.decision));
|
|
163
|
+
return {};
|
|
164
|
+
}
|
|
165
|
+
async moveHistory(callerArg, requestArg) {
|
|
166
|
+
const session = await this.requireSession(callerArg, requestArg?.sessionId);
|
|
167
|
+
if (requestArg.direction === 'undo') {
|
|
168
|
+
const result = await this.call(() => this.harness.undoSession(callerArg.scopeId, session.sessionId));
|
|
169
|
+
return { runId: result.revertedRunId };
|
|
170
|
+
}
|
|
171
|
+
if (requestArg.direction === 'redo') {
|
|
172
|
+
const result = await this.call(() => this.harness.redoSession(callerArg.scopeId, session.sessionId));
|
|
173
|
+
return { runId: result.restoredRunId };
|
|
174
|
+
}
|
|
175
|
+
throw new FlexHarnessChatRequestError(BAD_REQUEST_MESSAGE);
|
|
176
|
+
}
|
|
177
|
+
async renameSession(callerArg, requestArg) {
|
|
178
|
+
const title = readTitle(requestArg?.title, this.limits);
|
|
179
|
+
const session = await this.requireSession(callerArg, requestArg.sessionId);
|
|
180
|
+
const updated = await this.call(() => this.harness.updateSession(callerArg.scopeId, session.sessionId, { title }));
|
|
181
|
+
return { session: flexHarnessChatSessionMeta(updated) };
|
|
182
|
+
}
|
|
183
|
+
async deleteSession(callerArg, requestArg) {
|
|
184
|
+
const session = await this.requireSession(callerArg, requestArg?.sessionId);
|
|
185
|
+
await this.call(() => this.harness.deleteSession(callerArg.scopeId, session.sessionId));
|
|
186
|
+
return {};
|
|
187
|
+
}
|
|
188
|
+
// ---------------- turns ----------------
|
|
189
|
+
/** The running turn of a conversation; the host's model resolver and tool provider read it. */
|
|
190
|
+
turnOf(scopeIdArg, sessionIdArg) {
|
|
191
|
+
return this.gate.turnOf(scopeIdArg, sessionIdArg);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Runs a tool of the turn in the tab that started it and answers with the tab's output. Fails with
|
|
195
|
+
* `FlexHarnessChatTabUnavailableError` when the tab is gone or does not answer in time.
|
|
196
|
+
*/
|
|
197
|
+
async runClientTool(turnArg, requestArg, optionsArg = {}) {
|
|
198
|
+
const peer = await this.peers.find({ tabId: turnArg.tabId, scopeId: turnArg.scopeId });
|
|
199
|
+
if (!peer)
|
|
200
|
+
throw new FlexHarnessChatTabUnavailableError();
|
|
201
|
+
try {
|
|
202
|
+
return await peer.runTool(requestArg, {
|
|
203
|
+
timeoutMs: optionsArg.timeoutMs ?? this.limits.toolTimeoutMs,
|
|
204
|
+
...(optionsArg.abortSignal ? { abortSignal: optionsArg.abortSignal } : {}),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
if (optionsArg.abortSignal?.aborted)
|
|
209
|
+
throw error;
|
|
210
|
+
throw new FlexHarnessChatTabUnavailableError({ cause: error });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ---------------- tabs and lifecycle ----------------
|
|
214
|
+
/** Forgets a tab that is gone: its conversation list and the conversation it followed. */
|
|
215
|
+
forgetTab(tabArg) {
|
|
216
|
+
this.closeSubscriptionsOf(tabArg);
|
|
217
|
+
this.sessionLists.forget(tabArg);
|
|
218
|
+
}
|
|
219
|
+
/** Stops the turns the hub started and waits until they ended; clears subscriptions and timers. */
|
|
220
|
+
async stop() {
|
|
221
|
+
if (this.stopped)
|
|
222
|
+
return;
|
|
223
|
+
this.stopped = true;
|
|
224
|
+
clearInterval(this.sweepTimer);
|
|
225
|
+
this.unsubscribe();
|
|
226
|
+
for (const subscription of [...this.subscriptions.values()])
|
|
227
|
+
this.closeSubscription(subscription);
|
|
228
|
+
this.sessionLists.clear();
|
|
229
|
+
// requests under way refuse at their next step; the gate refuses and cancels what reaches it
|
|
230
|
+
await Promise.all([this.gate.stop(), ...this.requestsUnderWay]);
|
|
231
|
+
}
|
|
232
|
+
/** Runs a request that may start a turn or a subscription, so that `stop()` can wait for it. */
|
|
233
|
+
underWay(requestArg) {
|
|
234
|
+
const request = requestArg();
|
|
235
|
+
const settled = request.then(() => undefined, () => undefined);
|
|
236
|
+
this.requestsUnderWay.add(settled);
|
|
237
|
+
void settled.then(() => this.requestsUnderWay.delete(settled));
|
|
238
|
+
return request;
|
|
239
|
+
}
|
|
240
|
+
takeEvent(eventArg) {
|
|
241
|
+
const preceding = this.lastSequence;
|
|
242
|
+
this.lastSequence = eventArg.sequence;
|
|
243
|
+
this.gate.takeEvent(eventArg);
|
|
244
|
+
for (const subscription of this.subscriptions.values())
|
|
245
|
+
subscription.takeEvent(eventArg, preceding);
|
|
246
|
+
if (eventArg.type === 'session.created' || eventArg.type === 'session.updated' || eventArg.type === 'session.deleted') {
|
|
247
|
+
if (!eventArg.session.parentSessionId)
|
|
248
|
+
this.sessionLists.publish(eventArg);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** Forgets the tabs that are gone and run no turn; runs every `sweepIntervalMs` on its own. */
|
|
252
|
+
async forgetClosedTabs() {
|
|
253
|
+
const tabs = new Map();
|
|
254
|
+
for (const tab of [...this.sessionLists.tabs, ...this.subscriptions.values()]) {
|
|
255
|
+
tabs.set(tabKey(tab), { tabId: tab.tabId, scopeId: tab.scopeId });
|
|
256
|
+
}
|
|
257
|
+
for (const tab of tabs.values()) {
|
|
258
|
+
if (this.stopped)
|
|
259
|
+
return;
|
|
260
|
+
if (this.gate.hasTurnOf(tab))
|
|
261
|
+
continue;
|
|
262
|
+
const peer = await this.peers.find(tab).catch(() => null);
|
|
263
|
+
if (!peer && !this.gate.hasTurnOf(tab))
|
|
264
|
+
this.forgetTab(tab);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
closeSubscriptionsOf(tabArg) {
|
|
268
|
+
for (const subscription of [...this.subscriptions.values()]) {
|
|
269
|
+
if (isSameTab(subscription, tabArg))
|
|
270
|
+
this.closeSubscription(subscription);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
closeSubscription(subscriptionArg) {
|
|
274
|
+
subscriptionArg.close();
|
|
275
|
+
this.forgetSubscription(subscriptionArg);
|
|
276
|
+
}
|
|
277
|
+
forgetSubscription(subscriptionArg) {
|
|
278
|
+
if (this.subscriptions.get(subscriptionArg.id) === subscriptionArg)
|
|
279
|
+
this.subscriptions.delete(subscriptionArg.id);
|
|
280
|
+
}
|
|
281
|
+
// ---------------- checks and errors ----------------
|
|
282
|
+
assertRunning() {
|
|
283
|
+
if (this.stopped)
|
|
284
|
+
throw new FlexHarnessChatRequestError(STOPPED_MESSAGE);
|
|
285
|
+
}
|
|
286
|
+
readSendContext(valueArg) {
|
|
287
|
+
try {
|
|
288
|
+
return this.readContext(valueArg ?? null);
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
if (error instanceof FlexHarnessChatRequestError)
|
|
292
|
+
throw error;
|
|
293
|
+
throw new FlexHarnessChatRequestError(BAD_REQUEST_MESSAGE);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/** A root session of the caller's scope; another scope's session id reads as not found. */
|
|
297
|
+
async requireSession(callerArg, sessionIdArg) {
|
|
298
|
+
const sessionId = readSessionId(sessionIdArg, NOT_FOUND_MESSAGE);
|
|
299
|
+
let session;
|
|
300
|
+
try {
|
|
301
|
+
session = await this.harness.getSession(callerArg.scopeId, sessionId);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
if (error instanceof plugins.FlexHarnessNotFoundError || error instanceof plugins.FlexHarnessValidationError) {
|
|
305
|
+
throw new FlexHarnessChatRequestError(NOT_FOUND_MESSAGE);
|
|
306
|
+
}
|
|
307
|
+
throw this.toRequestError(error);
|
|
308
|
+
}
|
|
309
|
+
if (session.parentSessionId)
|
|
310
|
+
throw new FlexHarnessChatRequestError(NOT_FOUND_MESSAGE);
|
|
311
|
+
return session;
|
|
312
|
+
}
|
|
313
|
+
async call(fnArg) {
|
|
314
|
+
try {
|
|
315
|
+
return await fnArg();
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
throw this.toRequestError(error);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/** FlexHarness states its refusals for people; anything else stays an internal error. */
|
|
322
|
+
toRequestError(errorArg) {
|
|
323
|
+
if (errorArg instanceof FlexHarnessChatRequestError)
|
|
324
|
+
return errorArg;
|
|
325
|
+
if (errorArg instanceof plugins.FlexHarnessClosedError)
|
|
326
|
+
return new FlexHarnessChatRequestError(STOPPED_MESSAGE);
|
|
327
|
+
if (errorArg instanceof plugins.FlexHarnessError)
|
|
328
|
+
return new FlexHarnessChatRequestError(errorArg.message);
|
|
329
|
+
return errorArg;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jaGF0aHViLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY2hhdF9oYXJuZXNzX3NlcnZlci9jbGFzc2VzLmNoYXRodWIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDNUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLGtDQUFrQyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzlGLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsZUFBZSxFQUNmLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLGNBQWMsRUFDZCxhQUFhLEVBQ2IsU0FBUyxFQUNULGdCQUFnQixHQUNqQixNQUFNLDJCQUEyQixDQUFDO0FBYW5DLE1BQU0saUJBQWlCLEdBQUcsbUNBQW1DLENBQUM7QUFDOUQsTUFBTSxpQkFBaUIsR0FBRyw0RkFBNEYsQ0FBQztBQUN2SCxNQUFNLFNBQVMsR0FBc0IsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRWxFLE1BQU0sQ0FBQyxNQUFNLDRCQUE0QixHQUFxQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQzFGLGFBQWEsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUk7SUFDN0IsZUFBZSxFQUFFLEVBQUUsR0FBRyxJQUFJO0lBQzFCLGFBQWEsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUk7SUFDNUIsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixlQUFlLEVBQUUsT0FBTztJQUN4QixjQUFjLEVBQUUsRUFBRTtJQUNsQixrQkFBa0IsRUFBRSxDQUFDLEdBQUcsSUFBSSxHQUFHLElBQUk7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
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import type { IFlexHarnessChatLimits, IFlexHarnessChatPeers } from './interfaces.js';
|
|
3
|
+
/** The harness reads a subscription makes. */
|
|
4
|
+
export type TFlexHarnessChatSubscriptionHarness = Pick<plugins.FlexHarness<unknown>, 'getSessionView' | 'getSessionReversionInfo'>;
|
|
5
|
+
export interface IFlexHarnessChatSubscriptionOptions {
|
|
6
|
+
id: string;
|
|
7
|
+
tabId: string;
|
|
8
|
+
scopeId: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
harness: TFlexHarnessChatSubscriptionHarness;
|
|
11
|
+
peers: IFlexHarnessChatPeers;
|
|
12
|
+
limits: IFlexHarnessChatLimits;
|
|
13
|
+
/** called once when the subscription closes itself: its tab is gone or its session unreadable */
|
|
14
|
+
onClosed: (subscriptionArg: FlexHarnessChatSubscription) => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* One tab following one conversation. A `FlexHarnessTranscript` takes every event of the harness
|
|
18
|
+
* instance; what changed reaches the tab as numbered updates, one at a time. A transcript that
|
|
19
|
+
* loses track, or an update the tab does not acknowledge, makes the next update a `reset`.
|
|
20
|
+
*/
|
|
21
|
+
export declare class FlexHarnessChatSubscription {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly tabId: string;
|
|
24
|
+
readonly scopeId: string;
|
|
25
|
+
readonly sessionId: string;
|
|
26
|
+
private readonly harness;
|
|
27
|
+
private readonly peers;
|
|
28
|
+
private readonly limits;
|
|
29
|
+
private readonly onClosed;
|
|
30
|
+
private readonly transcript;
|
|
31
|
+
/** `loading` buffers events until the transcript holds the session's state */
|
|
32
|
+
private state;
|
|
33
|
+
private buffered;
|
|
34
|
+
private seq;
|
|
35
|
+
/** the rows as the tab last received them, as JSON, by id */
|
|
36
|
+
private sentRows;
|
|
37
|
+
private pending;
|
|
38
|
+
private sending;
|
|
39
|
+
private closed;
|
|
40
|
+
constructor(optionsArg: IFlexHarnessChatSubscriptionOptions);
|
|
41
|
+
/** Takes one event of the harness instance, in the order the harness emitted them. */
|
|
42
|
+
takeEvent(eventArg: plugins.TFlexHarnessEvent, precedingArg: number | undefined): void;
|
|
43
|
+
/** Reads the session into the transcript, replays what changed meanwhile and sends a reset. */
|
|
44
|
+
load(): Promise<void>;
|
|
45
|
+
/** Stops following; nothing more reaches the tab. */
|
|
46
|
+
close(): void;
|
|
47
|
+
private applyEvent;
|
|
48
|
+
/** The transcript lost track of the session: read it again; the tab gets a reset. */
|
|
49
|
+
private reload;
|
|
50
|
+
/** Sends what is pending, one update at a time, in seq order. */
|
|
51
|
+
private pump;
|
|
52
|
+
private takeUpdate;
|
|
53
|
+
private readHistory;
|
|
54
|
+
private closeSelf;
|
|
55
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
const emptyPending = () => ({
|
|
3
|
+
reset: false,
|
|
4
|
+
rows: false,
|
|
5
|
+
deltas: [],
|
|
6
|
+
status: false,
|
|
7
|
+
usage: false,
|
|
8
|
+
permissions: false,
|
|
9
|
+
history: false,
|
|
10
|
+
steers: [],
|
|
11
|
+
});
|
|
12
|
+
const hasPending = (pendingArg) => pendingArg.reset
|
|
13
|
+
|| pendingArg.rows
|
|
14
|
+
|| pendingArg.deltas.length > 0
|
|
15
|
+
|| pendingArg.status
|
|
16
|
+
|| pendingArg.usage
|
|
17
|
+
|| pendingArg.permissions
|
|
18
|
+
|| pendingArg.history
|
|
19
|
+
|| pendingArg.steers.length > 0;
|
|
20
|
+
/**
|
|
21
|
+
* One tab following one conversation. A `FlexHarnessTranscript` takes every event of the harness
|
|
22
|
+
* instance; what changed reaches the tab as numbered updates, one at a time. A transcript that
|
|
23
|
+
* loses track, or an update the tab does not acknowledge, makes the next update a `reset`.
|
|
24
|
+
*/
|
|
25
|
+
export class FlexHarnessChatSubscription {
|
|
26
|
+
id;
|
|
27
|
+
tabId;
|
|
28
|
+
scopeId;
|
|
29
|
+
sessionId;
|
|
30
|
+
harness;
|
|
31
|
+
peers;
|
|
32
|
+
limits;
|
|
33
|
+
onClosed;
|
|
34
|
+
transcript;
|
|
35
|
+
/** `loading` buffers events until the transcript holds the session's state */
|
|
36
|
+
state = 'loading';
|
|
37
|
+
buffered = [];
|
|
38
|
+
seq = 0;
|
|
39
|
+
/** the rows as the tab last received them, as JSON, by id */
|
|
40
|
+
sentRows = new Map();
|
|
41
|
+
pending = emptyPending();
|
|
42
|
+
sending = false;
|
|
43
|
+
closed = false;
|
|
44
|
+
constructor(optionsArg) {
|
|
45
|
+
this.id = optionsArg.id;
|
|
46
|
+
this.tabId = optionsArg.tabId;
|
|
47
|
+
this.scopeId = optionsArg.scopeId;
|
|
48
|
+
this.sessionId = optionsArg.sessionId;
|
|
49
|
+
this.harness = optionsArg.harness;
|
|
50
|
+
this.peers = optionsArg.peers;
|
|
51
|
+
this.limits = optionsArg.limits;
|
|
52
|
+
this.onClosed = optionsArg.onClosed;
|
|
53
|
+
this.transcript = new plugins.FlexHarnessTranscript({ scopeId: this.scopeId, sessionId: this.sessionId });
|
|
54
|
+
}
|
|
55
|
+
/** Takes one event of the harness instance, in the order the harness emitted them. */
|
|
56
|
+
takeEvent(eventArg, precedingArg) {
|
|
57
|
+
if (this.closed)
|
|
58
|
+
return;
|
|
59
|
+
if (this.state === 'loading')
|
|
60
|
+
this.buffered.push({ event: eventArg, preceding: precedingArg });
|
|
61
|
+
else
|
|
62
|
+
this.applyEvent(eventArg, precedingArg);
|
|
63
|
+
}
|
|
64
|
+
/** Reads the session into the transcript, replays what changed meanwhile and sends a reset. */
|
|
65
|
+
async load() {
|
|
66
|
+
this.state = 'loading';
|
|
67
|
+
this.buffered = [];
|
|
68
|
+
const view = await this.harness.getSessionView(this.scopeId, this.sessionId);
|
|
69
|
+
if (this.closed)
|
|
70
|
+
return;
|
|
71
|
+
this.transcript.load({
|
|
72
|
+
messages: view.messages,
|
|
73
|
+
permissions: view.pendingPermissions,
|
|
74
|
+
session: view.session,
|
|
75
|
+
sequence: view.sequence,
|
|
76
|
+
});
|
|
77
|
+
const buffered = this.buffered;
|
|
78
|
+
this.buffered = [];
|
|
79
|
+
this.state = 'live';
|
|
80
|
+
this.pending = { ...emptyPending(), reset: true, steers: this.pending.steers };
|
|
81
|
+
for (const entry of buffered) {
|
|
82
|
+
if (this.state !== 'live') {
|
|
83
|
+
this.buffered.push(entry);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
this.applyEvent(entry.event, entry.preceding);
|
|
87
|
+
}
|
|
88
|
+
void this.pump();
|
|
89
|
+
}
|
|
90
|
+
/** Stops following; nothing more reaches the tab. */
|
|
91
|
+
close() {
|
|
92
|
+
this.closed = true;
|
|
93
|
+
this.buffered = [];
|
|
94
|
+
}
|
|
95
|
+
applyEvent(eventArg, precedingArg) {
|
|
96
|
+
const change = this.transcript.applyEvent(eventArg, { precedingSequence: precedingArg });
|
|
97
|
+
if (change.reload) {
|
|
98
|
+
void this.reload();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const pending = this.pending;
|
|
102
|
+
if (eventArg.scopeId === this.scopeId && eventArg.sessionId === this.sessionId) {
|
|
103
|
+
if (eventArg.type === 'prompt.steer.applied') {
|
|
104
|
+
pending.steers.push({ steerId: eventArg.steerId, outcome: 'applied' });
|
|
105
|
+
}
|
|
106
|
+
else if (eventArg.type === 'run.finished') {
|
|
107
|
+
for (const steerId of eventArg.unappliedSteerIds)
|
|
108
|
+
pending.steers.push({ steerId, outcome: 'unapplied' });
|
|
109
|
+
pending.history = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (change.messages) {
|
|
113
|
+
// the rows are read when the update is sent; they hold every delta up to then
|
|
114
|
+
pending.rows = true;
|
|
115
|
+
pending.deltas = [];
|
|
116
|
+
}
|
|
117
|
+
else if (change.deltas.length && !pending.rows) {
|
|
118
|
+
pending.deltas.push(...change.deltas);
|
|
119
|
+
if (pending.deltas.length > this.limits.maxPendingDeltas) {
|
|
120
|
+
pending.rows = true;
|
|
121
|
+
pending.deltas = [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (change.status)
|
|
125
|
+
pending.status = true;
|
|
126
|
+
if (change.usage)
|
|
127
|
+
pending.usage = true;
|
|
128
|
+
if (change.permissions)
|
|
129
|
+
pending.permissions = true;
|
|
130
|
+
if (hasPending(pending))
|
|
131
|
+
void this.pump();
|
|
132
|
+
}
|
|
133
|
+
/** The transcript lost track of the session: read it again; the tab gets a reset. */
|
|
134
|
+
async reload() {
|
|
135
|
+
if (this.state === 'loading' || this.closed)
|
|
136
|
+
return;
|
|
137
|
+
try {
|
|
138
|
+
await this.load();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// the session is gone or unreadable; the tab sees it in its list and opens another
|
|
142
|
+
this.closeSelf();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Sends what is pending, one update at a time, in seq order. */
|
|
146
|
+
async pump() {
|
|
147
|
+
if (this.sending)
|
|
148
|
+
return;
|
|
149
|
+
this.sending = true;
|
|
150
|
+
let inFlight = null;
|
|
151
|
+
try {
|
|
152
|
+
while (!this.closed && this.state === 'live' && hasPending(this.pending)) {
|
|
153
|
+
const peer = await this.peers.find({ tabId: this.tabId, scopeId: this.scopeId });
|
|
154
|
+
if (!peer) {
|
|
155
|
+
this.closeSelf();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (this.closed || this.state !== 'live')
|
|
159
|
+
return;
|
|
160
|
+
inFlight = await this.takeUpdate();
|
|
161
|
+
await peer.update(inFlight);
|
|
162
|
+
inFlight = null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// the tab may have missed an update; it starts over with a reset at the next change
|
|
167
|
+
this.pending = {
|
|
168
|
+
...emptyPending(),
|
|
169
|
+
reset: true,
|
|
170
|
+
steers: [...(inFlight?.steers ?? []), ...this.pending.steers],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
this.sending = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async takeUpdate() {
|
|
178
|
+
const pending = this.pending;
|
|
179
|
+
this.pending = emptyPending();
|
|
180
|
+
const update = { subscriptionId: this.id, seq: ++this.seq };
|
|
181
|
+
const reset = pending.reset;
|
|
182
|
+
const view = reset || pending.rows || pending.status || pending.usage || pending.permissions
|
|
183
|
+
? this.transcript.view()
|
|
184
|
+
: null;
|
|
185
|
+
if (reset) {
|
|
186
|
+
update.reset = true;
|
|
187
|
+
this.sentRows.clear();
|
|
188
|
+
}
|
|
189
|
+
if (view && (reset || pending.rows)) {
|
|
190
|
+
const sent = new Map();
|
|
191
|
+
const upserts = [];
|
|
192
|
+
for (const row of view.messages) {
|
|
193
|
+
const json = JSON.stringify(row);
|
|
194
|
+
if (this.sentRows.get(row.id) !== json)
|
|
195
|
+
upserts.push(row);
|
|
196
|
+
sent.set(row.id, json);
|
|
197
|
+
}
|
|
198
|
+
this.sentRows = sent;
|
|
199
|
+
update.rows = { upserts, order: view.messages.map((row) => row.id) };
|
|
200
|
+
}
|
|
201
|
+
else if (pending.deltas.length) {
|
|
202
|
+
update.deltas = pending.deltas;
|
|
203
|
+
}
|
|
204
|
+
if (view && (reset || pending.status))
|
|
205
|
+
update.status = view.status;
|
|
206
|
+
if (view && (reset || pending.usage))
|
|
207
|
+
update.usage = view.usage;
|
|
208
|
+
if (view && (reset || pending.permissions))
|
|
209
|
+
update.permissions = view.permissions;
|
|
210
|
+
if (reset || pending.history) {
|
|
211
|
+
const history = await this.readHistory();
|
|
212
|
+
if (history)
|
|
213
|
+
update.history = history;
|
|
214
|
+
}
|
|
215
|
+
if (pending.steers.length)
|
|
216
|
+
update.steers = pending.steers;
|
|
217
|
+
return update;
|
|
218
|
+
}
|
|
219
|
+
async readHistory() {
|
|
220
|
+
try {
|
|
221
|
+
const info = await this.harness.getSessionReversionInfo(this.scopeId, this.sessionId);
|
|
222
|
+
return { undoAvailable: info.undoAvailable, redoAvailable: info.redoAvailable };
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// the session is being deleted; its next state reaches the tab through the session list
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
closeSelf() {
|
|
230
|
+
if (this.closed)
|
|
231
|
+
return;
|
|
232
|
+
this.close();
|
|
233
|
+
this.onClosed(this);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jaGF0c3Vic2NyaXB0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY2hhdF9oYXJuZXNzX3NlcnZlci9jbGFzc2VzLmNoYXRzdWJzY3JpcHRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFpQnhDLE1BQU0sWUFBWSxHQUFHLEdBQW1CLEVBQUUsQ0FBQyxDQUFDO0lBQzFDLEtBQUssRUFBRSxLQUFLO0lBQ1osSUFBSSxFQUFFLEtBQUs7SUFDWCxNQUFNLEVBQUUsRUFBRTtJQUNWLE1BQU0sRUFBRSxLQUFLO0lBQ2IsS0FBSyxFQUFFLEtBQUs7SUFDWixXQUFXLEVBQUUsS0FBSztJQUNsQixPQUFPLEVBQUUsS0FBSztJQUNkLE1BQU0sRUFBRSxFQUFFO0NBQ1gsQ0FBQyxDQUFDO0FBRUgsTUFBTSxVQUFVLEdBQUcsQ0FBQyxVQUEwQixFQUFXLEVBQUUsQ0FDekQsVUFBVSxDQUFDLEtBQUs7T0FDYixVQUFVLENBQUMsSUFBSTtPQUNmLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7T0FDNUIsVUFBVSxDQUFDLE1BQU07T0FDakIsVUFBVSxDQUFDLEtBQUs7T0FDaEIsVUFBVSxDQUFDLFdBQVc7T0FDdEIsVUFBVSxDQUFDLE9BQU87T0FDbEIsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBb0JsQzs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLDJCQUEyQjtJQUN0QixFQUFFLENBQVM7SUFDWCxLQUFLLENBQVM7SUFDZCxPQUFPLENBQVM7SUFDaEIsU0FBUyxDQUFTO0lBRWpCLE9BQU8sQ0FBc0M7SUFDN0MsS0FBSyxDQUF3QjtJQUM3QixNQUFNLENBQXlCO0lBQy9CLFFBQVEsQ0FBeUQ7SUFDakUsVUFBVSxDQUFnQztJQUMzRCw4RUFBOEU7SUFDdEUsS0FBSyxHQUF1QixTQUFTLENBQUM7SUFDdEMsUUFBUSxH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
|