@agent-native/core 0.14.4 → 0.14.6
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/agent/thread-data-builder.d.ts +11 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +133 -50
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/store.d.ts +6 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +109 -40
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +8 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +72 -5
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +2 -2
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +18 -5
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +8 -45
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareButton.spec.js +13 -31
- package/dist/client/sharing/ShareButton.spec.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +6 -0
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +35 -2
- package/dist/server/ssr-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,6 +32,12 @@ export declare function buildAssistantMessage(events: RunEvent[], runId?: string
|
|
|
32
32
|
};
|
|
33
33
|
metadata: Record<string, unknown>;
|
|
34
34
|
} | null;
|
|
35
|
+
/**
|
|
36
|
+
* Convert legacy/partially merged thread data into assistant-ui's exported
|
|
37
|
+
* repository shape and repair parent links so `threadRuntime.import()` cannot
|
|
38
|
+
* fail with "Parent message not found".
|
|
39
|
+
*/
|
|
40
|
+
export declare function normalizeThreadRepository(repo: any): any;
|
|
35
41
|
/**
|
|
36
42
|
* Merge an incoming client-side full-thread save over the current SQL copy.
|
|
37
43
|
*
|
|
@@ -41,7 +47,11 @@ export declare function buildAssistantMessage(events: RunEvent[], runId?: string
|
|
|
41
47
|
* reconstructed from run events. Preserve server-only messages while still
|
|
42
48
|
* accepting client-only messages and metadata.
|
|
43
49
|
*/
|
|
44
|
-
export
|
|
50
|
+
export interface MergeThreadDataOptions {
|
|
51
|
+
preserveExistingQueuedMessages?: boolean;
|
|
52
|
+
preserveExistingTopLevelKeys?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export declare function mergeThreadDataForClientSave(existingRepo: any, incomingRepo: any, options?: MergeThreadDataOptions): any;
|
|
45
55
|
export declare function buildUserMessage(opts: {
|
|
46
56
|
text: string;
|
|
47
57
|
attachments?: AgentChatAttachment[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-data-builder.d.ts","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEhE,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,4BAA4B;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"thread-data-builder.d.ts","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEhE,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,4BAA4B;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAwCvD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC;IACD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,EACF;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACpC;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,IAAI,CA2HP;AA8ID;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAqCxD;AAaD;;;;;;;;GAQG;AACH,MAAM,WAAW,sBAAsB;IACrC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,GAAG,EACjB,YAAY,EAAE,GAAG,EACjB,OAAO,GAAE,sBAA2B,OAkFrC;AAqFD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,GAAG;IACF,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAcA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,GAAG,GAAG,CAetE;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,gBAAgB,GAC7B,GAAG,CA0BL;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAyBA"}
|
|
@@ -2,8 +2,9 @@ const MAX_STORED_ATTACHMENT_CHARS = 60_000;
|
|
|
2
2
|
function isInternalContinuationError(event) {
|
|
3
3
|
const code = String(event.errorCode ?? "").toLowerCase();
|
|
4
4
|
const msg = event.error.toLowerCase();
|
|
5
|
+
if (code === "builder_gateway_error")
|
|
6
|
+
return false;
|
|
5
7
|
return (event.recoverable === true ||
|
|
6
|
-
code === "builder_gateway_error" ||
|
|
7
8
|
code === "builder_gateway_timeout" ||
|
|
8
9
|
code === "stale_run" ||
|
|
9
10
|
code === "timeout" ||
|
|
@@ -18,7 +19,6 @@ function isInternalContinuationError(event) {
|
|
|
18
19
|
code === "too_many_concurrent_requests" ||
|
|
19
20
|
code === "overloaded_error" ||
|
|
20
21
|
msg.includes("timeout") ||
|
|
21
|
-
msg.includes("gateway error") ||
|
|
22
22
|
msg.includes("gateway timeout") ||
|
|
23
23
|
msg.includes("inactivity timeout") ||
|
|
24
24
|
msg.includes("stream ended") ||
|
|
@@ -143,6 +143,19 @@ export function buildAssistantMessage(events, runId, options = {}) {
|
|
|
143
143
|
function getStoredMessage(entry) {
|
|
144
144
|
return entry?.message ?? entry;
|
|
145
145
|
}
|
|
146
|
+
function getStoredParentId(entry) {
|
|
147
|
+
return typeof entry?.parentId === "string" || entry?.parentId === null
|
|
148
|
+
? entry.parentId
|
|
149
|
+
: undefined;
|
|
150
|
+
}
|
|
151
|
+
function getStoredRunConfig(entry) {
|
|
152
|
+
return entry && typeof entry === "object" && "runConfig" in entry
|
|
153
|
+
? entry.runConfig
|
|
154
|
+
: undefined;
|
|
155
|
+
}
|
|
156
|
+
function messageId(message) {
|
|
157
|
+
return typeof message?.id === "string" && message.id ? message.id : undefined;
|
|
158
|
+
}
|
|
146
159
|
function getMessageRunId(message) {
|
|
147
160
|
const meta = message?.metadata;
|
|
148
161
|
const direct = meta?.runId;
|
|
@@ -176,7 +189,7 @@ function isTerminalAssistantStatus(status) {
|
|
|
176
189
|
return type === "complete" || type === "incomplete";
|
|
177
190
|
}
|
|
178
191
|
function normalizeAttachmentIdentity(attachments) {
|
|
179
|
-
if (!Array.isArray(attachments))
|
|
192
|
+
if (!Array.isArray(attachments) || attachments.length === 0)
|
|
180
193
|
return undefined;
|
|
181
194
|
return attachments.map((att) => ({
|
|
182
195
|
type: att?.type,
|
|
@@ -192,11 +205,22 @@ function messageIdentityKeys(message) {
|
|
|
192
205
|
const runId = getMessageRunId(message);
|
|
193
206
|
if (runId)
|
|
194
207
|
keys.push(`run:${runId}`);
|
|
208
|
+
// Normalize attachments through `normalizeAttachmentIdentity` so an
|
|
209
|
+
// explicit empty `[]` (assistant-ui's default for messages with no
|
|
210
|
+
// attachments) and an omitted/undefined `attachments` field hash to the
|
|
211
|
+
// same fingerprint. Without this, every user message ended up duplicated
|
|
212
|
+
// in `chat_threads`: one copy from `saveThreadData` (runtime export
|
|
213
|
+
// includes `attachments: []`) and one from `persistSubmittedUserMessage`
|
|
214
|
+
// → `buildUserMessage` (omits the field entirely). The merge couldn't
|
|
215
|
+
// dedupe them because their fingerprints differed by exactly one
|
|
216
|
+
// `[]` vs `undefined`. (Repro on slides prod: every user turn produced
|
|
217
|
+
// a `client_user → assistant → server_user` triple instead of a
|
|
218
|
+
// `user → assistant` pair.)
|
|
195
219
|
try {
|
|
196
220
|
keys.push(`fingerprint:${JSON.stringify({
|
|
197
221
|
role: message?.role,
|
|
198
222
|
content: message?.content,
|
|
199
|
-
attachments: message?.attachments,
|
|
223
|
+
attachments: normalizeAttachmentIdentity(message?.attachments),
|
|
200
224
|
})}`);
|
|
201
225
|
}
|
|
202
226
|
catch {
|
|
@@ -231,25 +255,92 @@ function chooseMergedMessageEntry(existingEntry, incomingEntry) {
|
|
|
231
255
|
}
|
|
232
256
|
return incomingEntry;
|
|
233
257
|
}
|
|
258
|
+
function normalizeMessageEntry(entry, parentId) {
|
|
259
|
+
const message = getStoredMessage(entry);
|
|
260
|
+
if (!messageId(message))
|
|
261
|
+
return null;
|
|
262
|
+
const runConfig = getStoredRunConfig(entry);
|
|
263
|
+
return {
|
|
264
|
+
message,
|
|
265
|
+
parentId,
|
|
266
|
+
...(runConfig !== undefined ? { runConfig } : {}),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
234
269
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* completion save lands first, an older browser export can otherwise replace
|
|
239
|
-
* `thread_data` wholesale and delete the assistant message the server just
|
|
240
|
-
* reconstructed from run events. Preserve server-only messages while still
|
|
241
|
-
* accepting client-only messages and metadata.
|
|
270
|
+
* Convert legacy/partially merged thread data into assistant-ui's exported
|
|
271
|
+
* repository shape and repair parent links so `threadRuntime.import()` cannot
|
|
272
|
+
* fail with "Parent message not found".
|
|
242
273
|
*/
|
|
243
|
-
export function
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
274
|
+
export function normalizeThreadRepository(repo) {
|
|
275
|
+
const normalized = repo && typeof repo === "object" ? { ...repo } : {};
|
|
276
|
+
const sourceMessages = Array.isArray(repo?.messages) ? repo.messages : [];
|
|
277
|
+
const messages = [];
|
|
278
|
+
const seenIds = new Set();
|
|
279
|
+
let previousId = null;
|
|
280
|
+
for (const entry of sourceMessages) {
|
|
281
|
+
const message = getStoredMessage(entry);
|
|
282
|
+
const id = messageId(message);
|
|
283
|
+
if (!id)
|
|
284
|
+
continue;
|
|
285
|
+
const requestedParentId = getStoredParentId(entry);
|
|
286
|
+
const parentId = requestedParentId === null
|
|
287
|
+
? null
|
|
288
|
+
: requestedParentId && seenIds.has(requestedParentId)
|
|
289
|
+
? requestedParentId
|
|
290
|
+
: previousId;
|
|
291
|
+
const normalizedEntry = normalizeMessageEntry(entry, parentId);
|
|
292
|
+
if (!normalizedEntry)
|
|
293
|
+
continue;
|
|
294
|
+
messages.push(normalizedEntry);
|
|
295
|
+
seenIds.add(id);
|
|
296
|
+
previousId = id;
|
|
297
|
+
}
|
|
298
|
+
normalized.messages = messages;
|
|
299
|
+
const headId = typeof repo?.headId === "string" ? repo.headId : undefined;
|
|
300
|
+
normalized.headId =
|
|
301
|
+
headId && seenIds.has(headId) ? headId : (previousId ?? null);
|
|
302
|
+
return normalized;
|
|
303
|
+
}
|
|
304
|
+
function rewriteEntryParentId(entry, idRewrites) {
|
|
305
|
+
const parentId = getStoredParentId(entry);
|
|
306
|
+
if (!parentId)
|
|
307
|
+
return entry;
|
|
308
|
+
const rewritten = idRewrites.get(parentId);
|
|
309
|
+
if (!rewritten)
|
|
310
|
+
return entry;
|
|
311
|
+
return { ...entry, parentId: rewritten };
|
|
312
|
+
}
|
|
313
|
+
export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options = {}) {
|
|
314
|
+
const preserveExistingQueuedMessages = options.preserveExistingQueuedMessages ?? true;
|
|
315
|
+
const preserveExistingTopLevelKeys = options.preserveExistingTopLevelKeys ?? true;
|
|
316
|
+
const existingNormalized = normalizeThreadRepository(existingRepo);
|
|
317
|
+
const incomingNormalized = normalizeThreadRepository(incomingRepo);
|
|
318
|
+
const merged = incomingNormalized && typeof incomingNormalized === "object"
|
|
319
|
+
? { ...incomingNormalized }
|
|
320
|
+
: {};
|
|
321
|
+
if (preserveExistingTopLevelKeys &&
|
|
322
|
+
existingNormalized &&
|
|
323
|
+
typeof existingNormalized === "object") {
|
|
324
|
+
for (const [key, value] of Object.entries(existingNormalized)) {
|
|
325
|
+
if (key === "messages" || key === "headId")
|
|
326
|
+
continue;
|
|
327
|
+
if (key === "queuedMessages" && !preserveExistingQueuedMessages) {
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (!(key in merged)) {
|
|
331
|
+
merged[key] = value;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else if (preserveExistingQueuedMessages &&
|
|
336
|
+
existingNormalized &&
|
|
337
|
+
typeof existingNormalized === "object" &&
|
|
338
|
+
existingNormalized.queuedMessages !== undefined &&
|
|
248
339
|
merged.queuedMessages === undefined) {
|
|
249
|
-
merged.queuedMessages =
|
|
340
|
+
merged.queuedMessages = existingNormalized.queuedMessages;
|
|
250
341
|
}
|
|
251
|
-
const existingMessages = Array.isArray(
|
|
252
|
-
?
|
|
342
|
+
const existingMessages = Array.isArray(existingNormalized?.messages)
|
|
343
|
+
? existingNormalized.messages
|
|
253
344
|
: null;
|
|
254
345
|
const incomingMessages = Array.isArray(merged.messages)
|
|
255
346
|
? merged.messages
|
|
@@ -259,6 +350,7 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo) {
|
|
|
259
350
|
const incomingKeySets = incomingMessages.map((entry) => new Set(messageIdentityKeys(getStoredMessage(entry))));
|
|
260
351
|
const usedIncoming = new Set();
|
|
261
352
|
const nextMessages = [];
|
|
353
|
+
const idRewrites = new Map();
|
|
262
354
|
for (const existingEntry of existingMessages) {
|
|
263
355
|
const existingKeys = messageIdentityKeys(getStoredMessage(existingEntry));
|
|
264
356
|
const incomingIndex = incomingKeySets.findIndex((keys, index) => !usedIncoming.has(index) && existingKeys.some((key) => keys.has(key)));
|
|
@@ -267,14 +359,21 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo) {
|
|
|
267
359
|
continue;
|
|
268
360
|
}
|
|
269
361
|
usedIncoming.add(incomingIndex);
|
|
270
|
-
|
|
362
|
+
const incomingEntry = incomingMessages[incomingIndex];
|
|
363
|
+
const chosen = chooseMergedMessageEntry(existingEntry, incomingEntry);
|
|
364
|
+
const existingId = messageId(getStoredMessage(existingEntry));
|
|
365
|
+
const chosenId = messageId(getStoredMessage(chosen));
|
|
366
|
+
if (existingId && chosenId && existingId !== chosenId) {
|
|
367
|
+
idRewrites.set(existingId, chosenId);
|
|
368
|
+
}
|
|
369
|
+
nextMessages.push(chosen);
|
|
271
370
|
}
|
|
272
371
|
for (let index = 0; index < incomingMessages.length; index++) {
|
|
273
372
|
if (!usedIncoming.has(index))
|
|
274
373
|
nextMessages.push(incomingMessages[index]);
|
|
275
374
|
}
|
|
276
|
-
merged.messages = nextMessages;
|
|
277
|
-
return merged;
|
|
375
|
+
merged.messages = nextMessages.map((entry) => rewriteEntryParentId(entry, idRewrites));
|
|
376
|
+
return normalizeThreadRepository(merged);
|
|
278
377
|
}
|
|
279
378
|
function escapeAttachmentAttribute(value) {
|
|
280
379
|
return value.replace(/&/g, "&").replace(/"/g, """);
|
|
@@ -363,23 +462,16 @@ export function buildUserMessage(opts) {
|
|
|
363
462
|
};
|
|
364
463
|
}
|
|
365
464
|
export function upsertUserMessage(repo, userMsg) {
|
|
366
|
-
const nextRepo = repo
|
|
367
|
-
if (!Array.isArray(nextRepo.messages))
|
|
368
|
-
nextRepo.messages = [];
|
|
465
|
+
const nextRepo = normalizeThreadRepository(repo);
|
|
369
466
|
const lastIndex = nextRepo.messages.length - 1;
|
|
370
467
|
const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;
|
|
371
468
|
const lastMsg = getStoredMessage(lastEntry);
|
|
372
469
|
if (lastMsg?.role === "user" && messagesMatch(lastMsg, userMsg)) {
|
|
373
470
|
return nextRepo;
|
|
374
471
|
}
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
nextRepo.messages.push({ message: userMsg, parentId });
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
nextRepo.messages.push(userMsg);
|
|
382
|
-
}
|
|
472
|
+
const parentId = lastIndex >= 0 ? (messageId(getStoredMessage(lastEntry)) ?? null) : null;
|
|
473
|
+
nextRepo.messages.push({ message: userMsg, parentId });
|
|
474
|
+
nextRepo.headId = userMsg.id;
|
|
383
475
|
return nextRepo;
|
|
384
476
|
}
|
|
385
477
|
function shouldReplaceLastAssistant(lastMessage, assistantMsg) {
|
|
@@ -420,31 +512,22 @@ function shouldReplaceLastAssistant(lastMessage, assistantMsg) {
|
|
|
420
512
|
* turn.
|
|
421
513
|
*/
|
|
422
514
|
export function upsertAssistantMessage(repo, assistantMsg) {
|
|
423
|
-
const nextRepo = repo
|
|
424
|
-
if (!Array.isArray(nextRepo.messages))
|
|
425
|
-
nextRepo.messages = [];
|
|
515
|
+
const nextRepo = normalizeThreadRepository(repo);
|
|
426
516
|
const lastIndex = nextRepo.messages.length - 1;
|
|
427
517
|
const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;
|
|
428
518
|
const lastMsg = getStoredMessage(lastEntry);
|
|
429
519
|
const lastRole = lastMsg?.role;
|
|
430
|
-
const isWrapped = Boolean(lastEntry && "message" in lastEntry);
|
|
431
520
|
if (lastRole === "assistant" &&
|
|
432
521
|
shouldReplaceLastAssistant(lastMsg, assistantMsg)) {
|
|
433
|
-
nextRepo.messages[lastIndex] =
|
|
434
|
-
|
|
435
|
-
: assistantMsg;
|
|
522
|
+
nextRepo.messages[lastIndex] = { ...lastEntry, message: assistantMsg };
|
|
523
|
+
nextRepo.headId = assistantMsg.id;
|
|
436
524
|
return nextRepo;
|
|
437
525
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
nextRepo.messages.push({ message: assistantMsg, parentId });
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
nextRepo.messages.push(assistantMsg);
|
|
447
|
-
}
|
|
526
|
+
const parentId = nextRepo.messages.length > 0
|
|
527
|
+
? (messageId(getStoredMessage(nextRepo.messages[nextRepo.messages.length - 1])) ?? null)
|
|
528
|
+
: null;
|
|
529
|
+
nextRepo.messages.push({ message: assistantMsg, parentId });
|
|
530
|
+
nextRepo.headId = assistantMsg.id;
|
|
448
531
|
return nextRepo;
|
|
449
532
|
}
|
|
450
533
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-data-builder.js","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentChatAttachment, RunEvent } from \"./types.js\";\n\ninterface ContentPart {\n type: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n argsText?: string;\n args?: Record<string, string>;\n result?: string;\n}\n\ninterface BuildAssistantMessageOptions {\n suppressInternalContinuation?: boolean;\n}\n\ntype AssistantMessage = NonNullable<ReturnType<typeof buildAssistantMessage>>;\ntype UserMessage = ReturnType<typeof buildUserMessage>;\n\nconst MAX_STORED_ATTACHMENT_CHARS = 60_000;\n\nfunction isInternalContinuationError(event: {\n error: string;\n errorCode?: string;\n recoverable?: boolean;\n}): boolean {\n const code = String(event.errorCode ?? \"\").toLowerCase();\n const msg = event.error.toLowerCase();\n return (\n event.recoverable === true ||\n code === \"builder_gateway_error\" ||\n code === \"builder_gateway_timeout\" ||\n code === \"stale_run\" ||\n code === \"timeout\" ||\n code === \"timeout_error\" ||\n code === \"http_408\" ||\n code === \"http_429\" ||\n code === \"http_500\" ||\n code === \"http_502\" ||\n code === \"http_503\" ||\n code === \"http_504\" ||\n code === \"rate_limited\" ||\n code === \"too_many_concurrent_requests\" ||\n code === \"overloaded_error\" ||\n msg.includes(\"timeout\") ||\n msg.includes(\"gateway error\") ||\n msg.includes(\"gateway timeout\") ||\n msg.includes(\"inactivity timeout\") ||\n msg.includes(\"stream ended\") ||\n msg.includes(\"stream closed\") ||\n msg.includes(\"temporarily unavailable\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\") ||\n msg.includes(\"529\")\n );\n}\n\n/**\n * Reconstruct an assistant-ui message from raw agent run events.\n * Mirrors the client-side processEvent logic so the server can persist\n * the assistant's response even if the frontend is disconnected.\n */\nexport function buildAssistantMessage(\n events: RunEvent[],\n runId?: string,\n options: BuildAssistantMessageOptions = {},\n): {\n id: string;\n createdAt: Date;\n role: \"assistant\";\n content: ContentPart[];\n status:\n | { type: \"complete\"; reason: \"stop\" }\n | { type: \"incomplete\"; reason: \"error\" };\n metadata: Record<string, unknown>;\n} | null {\n const content: ContentPart[] = [];\n let toolCallCounter = 0;\n let runError: {\n message: string;\n errorCode?: string;\n details?: string;\n recoverable?: boolean;\n } | null = null;\n let endedAtInternalContinuationBoundary = false;\n\n const appendText = (text: string) => {\n const last = content[content.length - 1];\n if (last && last.type === \"text\") {\n last.text = (last.text ?? \"\") + text;\n } else {\n content.push({ type: \"text\", text });\n }\n };\n\n for (const { event } of events) {\n if (event.type === \"clear\") {\n content.length = 0;\n toolCallCounter = 0;\n continue;\n }\n\n if (event.type === \"text\") {\n appendText(event.text ?? \"\");\n continue;\n }\n\n if (event.type === \"tool_start\") {\n const toolCallId = `tc_${++toolCallCounter}`;\n const args = (event.input ?? {}) as Record<string, string>;\n content.push({\n type: \"tool-call\",\n toolCallId,\n toolName: event.tool ?? \"unknown\",\n argsText: JSON.stringify(args),\n args,\n });\n continue;\n }\n\n if (event.type === \"tool_done\") {\n for (let i = content.length - 1; i >= 0; i--) {\n const part = content[i];\n if (\n part.type === \"tool-call\" &&\n part.toolName === event.tool &&\n part.result === undefined\n ) {\n part.result = event.result ?? \"\";\n break;\n }\n }\n continue;\n }\n\n if (event.type === \"loop_limit\") {\n // Older servers emitted this as a user-visible terminal event. Treat it\n // as an internal continuation boundary when rebuilding persisted turns.\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"auto_continue\") {\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"error\") {\n if (\n options.suppressInternalContinuation &&\n isInternalContinuationError(event)\n ) {\n endedAtInternalContinuationBoundary = true;\n continue;\n }\n if (event.errorCode === \"run_timeout\" && event.recoverable) {\n continue;\n }\n runError = {\n message: event.error,\n ...(event.errorCode ? { errorCode: event.errorCode } : {}),\n ...(event.details ? { details: event.details } : {}),\n ...(event.recoverable ? { recoverable: event.recoverable } : {}),\n };\n appendText(`${content.length > 0 ? \"\\n\\n\" : \"\"}Error: ${event.error}`);\n continue;\n }\n\n // done, missing_api_key — terminal signals, not content\n }\n\n if (content.length === 0 || endedAtInternalContinuationBoundary) return null;\n\n const metadata: Record<string, unknown> = {};\n if (runId) metadata.runId = runId;\n if (runError) {\n metadata.custom = {\n runError: {\n ...runError,\n ...(runId ? { runId } : {}),\n },\n };\n }\n\n return {\n id: `server-${runId ?? Date.now()}`,\n createdAt: new Date(),\n role: \"assistant\",\n content,\n status: runError\n ? { type: \"incomplete\" as const, reason: \"error\" as const }\n : { type: \"complete\" as const, reason: \"stop\" as const },\n metadata,\n };\n}\n\nfunction getStoredMessage(entry: any): any {\n return entry?.message ?? entry;\n}\n\nfunction getMessageRunId(message: any): string | undefined {\n const meta = message?.metadata;\n const direct = meta?.runId;\n const custom = meta?.custom?.runId;\n const errorRun = meta?.custom?.runError?.runId ?? meta?.runError?.runId;\n if (typeof direct === \"string\") return direct;\n if (typeof custom === \"string\") return custom;\n if (typeof errorRun === \"string\") return errorRun;\n return undefined;\n}\n\nfunction messageContentIsEmpty(content: unknown): boolean {\n if (Array.isArray(content)) return content.length === 0;\n return content == null || content === \"\";\n}\n\nfunction messageText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter(\n (part: any) => part?.type === \"text\" && typeof part.text === \"string\",\n )\n .map((part: any) => part.text)\n .join(\"\");\n}\n\nfunction isTerminalAssistantStatus(status: unknown): boolean {\n const type = (status as { type?: unknown } | undefined)?.type;\n return type === \"complete\" || type === \"incomplete\";\n}\n\nfunction normalizeAttachmentIdentity(attachments: unknown): unknown {\n if (!Array.isArray(attachments)) return undefined;\n return attachments.map((att: any) => ({\n type: att?.type,\n name: att?.name,\n contentType: att?.contentType,\n }));\n}\n\nfunction messageIdentityKeys(message: any): string[] {\n const keys: string[] = [];\n if (typeof message?.id === \"string\" && message.id) {\n keys.push(`id:${message.id}`);\n }\n const runId = getMessageRunId(message);\n if (runId) keys.push(`run:${runId}`);\n\n try {\n keys.push(\n `fingerprint:${JSON.stringify({\n role: message?.role,\n content: message?.content,\n attachments: message?.attachments,\n })}`,\n );\n } catch {\n // Best effort. id/runId usually exist for persisted assistant-ui rows.\n }\n if (message?.role === \"user\") {\n try {\n keys.push(\n `user-fingerprint:${JSON.stringify({\n role: message.role,\n content: message.content,\n attachments: normalizeAttachmentIdentity(message.attachments),\n })}`,\n );\n } catch {\n // Same best-effort behavior as the full fingerprint.\n }\n }\n return keys;\n}\n\nfunction messagesMatch(a: any, b: any): boolean {\n const bKeys = new Set(messageIdentityKeys(b));\n return messageIdentityKeys(a).some((key) => bKeys.has(key));\n}\n\nfunction chooseMergedMessageEntry(existingEntry: any, incomingEntry: any): any {\n const existing = getStoredMessage(existingEntry);\n const incoming = getStoredMessage(incomingEntry);\n if (\n existing?.role === \"assistant\" &&\n incoming?.role === \"assistant\" &&\n isTerminalAssistantStatus(existing?.status) &&\n !isTerminalAssistantStatus(incoming?.status)\n ) {\n return existingEntry;\n }\n return incomingEntry;\n}\n\n/**\n * Merge an incoming client-side full-thread save over the current SQL copy.\n *\n * The browser exports and PUTs the whole assistant-ui repository. If a server\n * completion save lands first, an older browser export can otherwise replace\n * `thread_data` wholesale and delete the assistant message the server just\n * reconstructed from run events. Preserve server-only messages while still\n * accepting client-only messages and metadata.\n */\nexport function mergeThreadDataForClientSave(\n existingRepo: any,\n incomingRepo: any,\n) {\n const merged =\n incomingRepo && typeof incomingRepo === \"object\" ? incomingRepo : {};\n if (\n existingRepo &&\n typeof existingRepo === \"object\" &&\n existingRepo.queuedMessages !== undefined &&\n merged.queuedMessages === undefined\n ) {\n merged.queuedMessages = existingRepo.queuedMessages;\n }\n\n const existingMessages = Array.isArray(existingRepo?.messages)\n ? existingRepo.messages\n : null;\n const incomingMessages = Array.isArray(merged.messages)\n ? merged.messages\n : null;\n if (!existingMessages || !incomingMessages) return merged;\n\n const incomingKeySets = incomingMessages.map(\n (entry: any) => new Set(messageIdentityKeys(getStoredMessage(entry))),\n );\n const usedIncoming = new Set<number>();\n const nextMessages: any[] = [];\n\n for (const existingEntry of existingMessages) {\n const existingKeys = messageIdentityKeys(getStoredMessage(existingEntry));\n const incomingIndex = incomingKeySets.findIndex(\n (keys, index) =>\n !usedIncoming.has(index) && existingKeys.some((key) => keys.has(key)),\n );\n\n if (incomingIndex === -1) {\n nextMessages.push(existingEntry);\n continue;\n }\n\n usedIncoming.add(incomingIndex);\n nextMessages.push(\n chooseMergedMessageEntry(existingEntry, incomingMessages[incomingIndex]),\n );\n }\n\n for (let index = 0; index < incomingMessages.length; index++) {\n if (!usedIncoming.has(index)) nextMessages.push(incomingMessages[index]);\n }\n\n merged.messages = nextMessages;\n return merged;\n}\n\nfunction escapeAttachmentAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction unwrapTextAttachmentEnvelope(text: string): string {\n const match = text.match(\n /^<attachment\\b[^>]*>\\n?([\\s\\S]*?)\\n?<\\/attachment>$/,\n );\n return match ? match[1] : text;\n}\n\nfunction truncateStoredAttachment(text: string): string {\n const unwrapped = unwrapTextAttachmentEnvelope(text);\n if (unwrapped.length <= MAX_STORED_ATTACHMENT_CHARS) return unwrapped;\n const omitted = unwrapped.length - MAX_STORED_ATTACHMENT_CHARS;\n return `${unwrapped.slice(0, MAX_STORED_ATTACHMENT_CHARS)}\\n\\n[Attachment truncated after ${MAX_STORED_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from persisted chat history.]`;\n}\n\nfunction textAttachmentEnvelope(\n att: AgentChatAttachment,\n text: string,\n): string {\n const attrs = [\n `name=\"${escapeAttachmentAttribute(att.name || \"attachment\")}\"`,\n att.contentType\n ? `contentType=\"${escapeAttachmentAttribute(att.contentType)}\"`\n : null,\n att.type ? `type=\"${escapeAttachmentAttribute(att.type)}\"` : null,\n ].filter(Boolean);\n return `<attachment ${attrs.join(\" \")}>\\n${truncateStoredAttachment(text)}\\n</attachment>`;\n}\n\nfunction buildStoredAttachments(\n attachments: AgentChatAttachment[] | undefined,\n runId: string | undefined,\n): any[] {\n return (attachments ?? [])\n .map((att, index) => {\n const id = `server-${runId ?? Date.now()}-attachment-${index}`;\n if (att.type === \"image\" && att.data) {\n return {\n id,\n type: \"image\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [{ type: \"image\", image: att.data }],\n };\n }\n if (att.data) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n {\n type: \"file\",\n data: att.data,\n mimeType: att.contentType,\n filename: att.name,\n },\n ],\n };\n }\n if (typeof att.text === \"string\" && att.text.length > 0) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n { type: \"text\", text: textAttachmentEnvelope(att, att.text) },\n ],\n };\n }\n return null;\n })\n .filter(Boolean);\n}\n\nexport function buildUserMessage(opts: {\n text: string;\n attachments?: AgentChatAttachment[];\n runId?: string;\n createdAt?: Date;\n}): {\n id: string;\n createdAt: Date;\n role: \"user\";\n content: ContentPart[];\n attachments?: any[];\n metadata: Record<string, unknown>;\n} {\n const attachments = buildStoredAttachments(opts.attachments, opts.runId);\n return {\n id: `server-user-${opts.runId ?? Date.now()}`,\n createdAt: opts.createdAt ?? new Date(),\n role: \"user\",\n content: [{ type: \"text\", text: opts.text }],\n ...(attachments.length > 0 ? { attachments } : {}),\n metadata: {\n custom: {\n submittedRunId: opts.runId,\n },\n },\n };\n}\n\nexport function upsertUserMessage(repo: any, userMsg: UserMessage): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n if (lastMsg?.role === \"user\" && messagesMatch(lastMsg, userMsg)) {\n return nextRepo;\n }\n\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n if (isWrapped) {\n const parentId =\n lastIndex >= 0 ? (getStoredMessage(lastEntry)?.id ?? null) : null;\n nextRepo.messages.push({ message: userMsg, parentId });\n } else {\n nextRepo.messages.push(userMsg);\n }\n return nextRepo;\n}\n\nfunction shouldReplaceLastAssistant(\n lastMessage: any,\n assistantMsg: AssistantMessage,\n): boolean {\n const lastContent = lastMessage?.content;\n if (messageContentIsEmpty(lastContent)) return true;\n\n const lastRunId = getMessageRunId(lastMessage);\n const nextRunId = getMessageRunId(assistantMsg);\n if (lastRunId && nextRunId && lastRunId === nextRunId) return true;\n if (lastRunId && nextRunId && lastRunId !== nextRunId) return false;\n\n const lastStatus = lastMessage?.status;\n if (lastStatus && !isTerminalAssistantStatus(lastStatus)) return true;\n\n try {\n if (JSON.stringify(lastContent) === JSON.stringify(assistantMsg.content)) {\n return true;\n }\n } catch {\n // Fall through to the text-prefix check.\n }\n\n const lastText = messageText(lastContent).trim();\n const nextText = messageText(assistantMsg.content).trim();\n if (isTerminalAssistantStatus(lastStatus)) return false;\n return Boolean(lastText && nextText && nextText.startsWith(lastText));\n}\n\n/**\n * Merge the server-reconstructed assistant message into persisted\n * assistant-ui thread data.\n *\n * The browser periodically saves thread data while a run is still streaming.\n * That can leave the last assistant message non-empty but partial/pending.\n * Completion must replace that same-run partial message instead of treating\n * any assistant content as proof that the frontend already saved the final\n * turn.\n */\nexport function upsertAssistantMessage(\n repo: any,\n assistantMsg: AssistantMessage,\n): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n const lastRole = lastMsg?.role;\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n\n if (\n lastRole === \"assistant\" &&\n shouldReplaceLastAssistant(lastMsg, assistantMsg)\n ) {\n nextRepo.messages[lastIndex] = isWrapped\n ? { ...lastEntry, message: assistantMsg }\n : assistantMsg;\n return nextRepo;\n }\n\n if (isWrapped) {\n const parentId =\n nextRepo.messages.length > 0\n ? (getStoredMessage(nextRepo.messages[nextRepo.messages.length - 1])\n ?.id ?? null)\n : null;\n nextRepo.messages.push({ message: assistantMsg, parentId });\n } else {\n nextRepo.messages.push(assistantMsg);\n }\n return nextRepo;\n}\n\n/**\n * Extract title and preview from a thread runtime export.\n * Isomorphic — works on both server and client.\n */\nexport function extractThreadMeta(repo: any): {\n title: string;\n preview: string;\n} {\n const msgs = repo?.messages;\n if (!Array.isArray(msgs) || msgs.length === 0)\n return { title: \"\", preview: \"\" };\n\n let title = \"\";\n let preview = \"\";\n for (const entry of msgs) {\n // Support both wrapped ({ message: { role, content } }) and flat ({ role, content }) formats\n const msg = entry?.message ?? entry;\n if (msg.role !== \"user\") continue;\n const textParts = Array.isArray(msg.content)\n ? msg.content\n .filter((p: any) => p.type === \"text\")\n .map((p: any) => p.text)\n .join(\" \")\n : typeof msg.content === \"string\"\n ? msg.content\n : \"\";\n if (textParts.trim()) {\n if (!title) title = textParts.trim().slice(0, 80);\n preview = textParts.trim().slice(0, 120);\n }\n }\n return { title, preview };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"thread-data-builder.js","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAmBA,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAE3C,SAAS,2BAA2B,CAAC,KAIpC;IACC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACtC,IAAI,IAAI,KAAK,uBAAuB;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,CACL,KAAK,CAAC,WAAW,KAAK,IAAI;QAC1B,IAAI,KAAK,yBAAyB;QAClC,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,SAAS;QAClB,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,cAAc;QACvB,IAAI,KAAK,8BAA8B;QACvC,IAAI,KAAK,kBAAkB;QAC3B,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvB,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/B,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC7B,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACvC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CACpB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAkB,EAClB,KAAc,EACd,UAAwC,EAAE;IAW1C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,QAAQ,GAKD,IAAI,CAAC;IAChB,IAAI,mCAAmC,GAAG,KAAK,CAAC;IAEhD,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACnB,eAAe,GAAG,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,MAAM,EAAE,eAAe,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAA2B,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW;gBACjB,UAAU;gBACV,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,SAAS;gBACjC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC9B,IAAI;aACL,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxB,IACE,IAAI,CAAC,IAAI,KAAK,WAAW;oBACzB,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI;oBAC5B,IAAI,CAAC,MAAM,KAAK,SAAS,EACzB,CAAC;oBACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;oBACjC,MAAM;gBACR,CAAC;YACH,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,wEAAwE;YACxE,wEAAwE;YACxE,IAAI,OAAO,CAAC,4BAA4B,EAAE,CAAC;gBACzC,mCAAmC,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACnC,IAAI,OAAO,CAAC,4BAA4B,EAAE,CAAC;gBACzC,mCAAmC,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IACE,OAAO,CAAC,4BAA4B;gBACpC,2BAA2B,CAAC,KAAK,CAAC,EAClC,CAAC;gBACD,mCAAmC,GAAG,IAAI,CAAC;gBAC3C,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC3D,SAAS;YACX,CAAC;YACD,QAAQ,GAAG;gBACT,OAAO,EAAE,KAAK,CAAC,KAAK;gBACpB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1D,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;YACF,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YACvE,SAAS;QACX,CAAC;QAED,wDAAwD;IAC1D,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,mCAAmC;QAAE,OAAO,IAAI,CAAC;IAE7E,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,KAAK;QAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;IAClC,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,MAAM,GAAG;YAChB,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5B;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,UAAU,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,MAAM,EAAE,QAAQ;YACd,CAAC,CAAC,EAAE,IAAI,EAAE,YAAqB,EAAE,MAAM,EAAE,OAAgB,EAAE;YAC3D,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,MAAM,EAAE,MAAe,EAAE;QAC1D,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAU;IAClC,OAAO,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC;AACjC,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAU;IACnC,OAAO,OAAO,KAAK,EAAE,QAAQ,KAAK,QAAQ,IAAI,KAAK,EAAE,QAAQ,KAAK,IAAI;QACpE,CAAC,CAAC,KAAK,CAAC,QAAQ;QAChB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAU;IACpC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,IAAI,KAAK;QAC/D,CAAC,CAAC,KAAK,CAAC,SAAS;QACjB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,OAAY;IAC7B,OAAO,OAAO,OAAO,EAAE,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,SAAS,eAAe,CAAC,OAAY;IACnC,MAAM,IAAI,GAAG,OAAO,EAAE,QAAQ,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC;IACxE,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IACxD,OAAO,OAAO,IAAI,IAAI,IAAI,OAAO,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,OAAgB;IACnC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACX,MAAM,CACL,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CACtE;SACA,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAe;IAChD,MAAM,IAAI,GAAI,MAAyC,EAAE,IAAI,CAAC;IAC9D,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,YAAY,CAAC;AACtD,CAAC;AAED,SAAS,2BAA2B,CAAC,WAAoB;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9E,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;QACpC,IAAI,EAAE,GAAG,EAAE,IAAI;QACf,IAAI,EAAE,GAAG,EAAE,IAAI;QACf,WAAW,EAAE,GAAG,EAAE,WAAW;KAC9B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAY;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,OAAO,EAAE,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IAErC,oEAAoE;IACpE,mEAAmE;IACnE,wEAAwE;IACxE,yEAAyE;IACzE,oEAAoE;IACpE,yEAAyE;IACzE,sEAAsE;IACtE,iEAAiE;IACjE,uEAAuE;IACvE,gEAAgE;IAChE,4BAA4B;IAC5B,IAAI,CAAC;QACH,IAAI,CAAC,IAAI,CACP,eAAe,IAAI,CAAC,SAAS,CAAC;YAC5B,IAAI,EAAE,OAAO,EAAE,IAAI;YACnB,OAAO,EAAE,OAAO,EAAE,OAAO;YACzB,WAAW,EAAE,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC;SAC/D,CAAC,EAAE,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;IACD,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CACP,oBAAoB,IAAI,CAAC,SAAS,CAAC;gBACjC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,WAAW,EAAE,2BAA2B,CAAC,OAAO,CAAC,WAAW,CAAC;aAC9D,CAAC,EAAE,CACL,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,CAAM,EAAE,CAAM;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,wBAAwB,CAAC,aAAkB,EAAE,aAAkB;IACtE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACjD,IACE,QAAQ,EAAE,IAAI,KAAK,WAAW;QAC9B,QAAQ,EAAE,IAAI,KAAK,WAAW;QAC9B,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC3C,CAAC,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC5C,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAU,EACV,QAAuB;IAEvB,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO;QACL,OAAO;QACP,QAAQ;QACR,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAS;IACjD,MAAM,UAAU,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,MAAM,QAAQ,GAIT,EAAE,CAAC;IACR,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,UAAU,GAAkB,IAAI,CAAC;IAErC,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,QAAQ,GACZ,iBAAiB,KAAK,IAAI;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;gBACnD,CAAC,CAAC,iBAAiB;gBACnB,CAAC,CAAC,UAAU,CAAC;QAEnB,MAAM,eAAe,GAAG,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,eAAe;YAAE,SAAS;QAE/B,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,UAAU,GAAG,EAAE,CAAC;IAClB,CAAC;IAED,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,UAAU,CAAC,MAAM;QACf,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;IAChE,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,oBAAoB,CAC3B,KAAU,EACV,UAA+B;IAE/B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC3C,CAAC;AAgBD,MAAM,UAAU,4BAA4B,CAC1C,YAAiB,EACjB,YAAiB,EACjB,UAAkC,EAAE;IAEpC,MAAM,8BAA8B,GAClC,OAAO,CAAC,8BAA8B,IAAI,IAAI,CAAC;IACjD,MAAM,4BAA4B,GAChC,OAAO,CAAC,4BAA4B,IAAI,IAAI,CAAC;IAC/C,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACnE,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACnE,MAAM,MAAM,GACV,kBAAkB,IAAI,OAAO,kBAAkB,KAAK,QAAQ;QAC1D,CAAC,CAAC,EAAE,GAAG,kBAAkB,EAAE;QAC3B,CAAC,CAAC,EAAE,CAAC;IACT,IACE,4BAA4B;QAC5B,kBAAkB;QAClB,OAAO,kBAAkB,KAAK,QAAQ,EACtC,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9D,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,QAAQ;gBAAE,SAAS;YACrD,IAAI,GAAG,KAAK,gBAAgB,IAAI,CAAC,8BAA8B,EAAE,CAAC;gBAChE,SAAS;YACX,CAAC;YACD,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IACL,8BAA8B;QAC9B,kBAAkB;QAClB,OAAO,kBAAkB,KAAK,QAAQ;QACtC,kBAAkB,CAAC,cAAc,KAAK,SAAS;QAC/C,MAAM,CAAC,cAAc,KAAK,SAAS,EACnC,CAAC;QACD,MAAM,CAAC,cAAc,GAAG,kBAAkB,CAAC,cAAc,CAAC;IAC5D,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC;QAClE,CAAC,CAAC,kBAAkB,CAAC,QAAQ;QAC7B,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QACrD,CAAC,CAAC,MAAM,CAAC,QAAQ;QACjB,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,CAAC,gBAAgB,IAAI,CAAC,gBAAgB;QAAE,OAAO,MAAM,CAAC;IAE1D,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAC1C,CAAC,KAAU,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CACtE,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,YAAY,GAAU,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE7C,KAAK,MAAM,aAAa,IAAI,gBAAgB,EAAE,CAAC;QAC7C,MAAM,YAAY,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;QAC1E,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAC7C,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CACxE,CAAC;QAEF,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QAED,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAChC,MAAM,aAAa,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,wBAAwB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QACrD,IAAI,UAAU,IAAI,QAAQ,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;YACtD,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3C,oBAAoB,CAAC,KAAK,EAAE,UAAU,CAAC,CACxC,CAAC;IACF,OAAO,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,4BAA4B,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACtB,qDAAqD,CACtD,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,MAAM,SAAS,GAAG,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,SAAS,CAAC,MAAM,IAAI,2BAA2B;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,2BAA2B,CAAC;IAC/D,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,mCAAmC,2BAA2B,CAAC,cAAc,EAAE,gBAAgB,OAAO,CAAC,cAAc,EAAE,mDAAmD,CAAC;AACtO,CAAC;AAED,SAAS,sBAAsB,CAC7B,GAAwB,EACxB,IAAY;IAEZ,MAAM,KAAK,GAAG;QACZ,SAAS,yBAAyB,CAAC,GAAG,CAAC,IAAI,IAAI,YAAY,CAAC,GAAG;QAC/D,GAAG,CAAC,WAAW;YACb,CAAC,CAAC,gBAAgB,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG;YAC/D,CAAC,CAAC,IAAI;QACR,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;KAClE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,eAAe,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,wBAAwB,CAAC,IAAI,CAAC,iBAAiB,CAAC;AAC7F,CAAC;AAED,SAAS,sBAAsB,CAC7B,WAA8C,EAC9C,KAAyB;IAEzB,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAClB,MAAM,EAAE,GAAG,UAAU,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,eAAe,KAAK,EAAE,CAAC;QAC/D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;aAC9C,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,QAAQ,EAAE,GAAG,CAAC,WAAW;wBACzB,QAAQ,EAAE,GAAG,CAAC,IAAI;qBACnB;iBACF;aACF,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;iBAC9D;aACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAKhC;IAQC,MAAM,WAAW,GAAG,sBAAsB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzE,OAAO;QACL,EAAE,EAAE,eAAe,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;QAC7C,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;QACvC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,QAAQ,EAAE;YACR,MAAM,EAAE;gBACN,cAAc,EAAE,IAAI,CAAC,KAAK;aAC3B;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAS,EAAE,OAAoB;IAC/D,MAAM,QAAQ,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;QAChE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GACZ,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvD,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,0BAA0B,CACjC,WAAgB,EAChB,YAA8B;IAE9B,MAAM,WAAW,GAAG,WAAW,EAAE,OAAO,CAAC;IACzC,IAAI,qBAAqB,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAEpE,MAAM,UAAU,GAAG,WAAW,EAAE,MAAM,CAAC;IACvC,IAAI,UAAU,IAAI,CAAC,yBAAyB,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,yBAAyB,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,OAAO,CAAC,QAAQ,IAAI,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAS,EACT,YAA8B;IAE9B,MAAM,QAAQ,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,EAAE,IAAI,CAAC;IAE/B,IACE,QAAQ,KAAK,WAAW;QACxB,0BAA0B,CAAC,OAAO,EAAE,YAAY,CAAC,EACjD,CAAC;QACD,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QACvE,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GACZ,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC1B,CAAC,CAAC,CAAC,SAAS,CACR,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAClE,IAAI,IAAI,CAAC;QACZ,CAAC,CAAC,IAAI,CAAC;IACX,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5D,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;IAClC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAS;IAIzC,MAAM,IAAI,GAAG,IAAI,EAAE,QAAQ,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAC3C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEpC,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,6FAA6F;QAC7F,MAAM,GAAG,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC1C,CAAC,CAAC,GAAG,CAAC,OAAO;iBACR,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBACrC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBACvB,IAAI,CAAC,GAAG,CAAC;YACd,CAAC,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC/B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,EAAE,CAAC;QACT,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK;gBAAE,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC","sourcesContent":["import type { AgentChatAttachment, RunEvent } from \"./types.js\";\n\ninterface ContentPart {\n type: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n argsText?: string;\n args?: Record<string, string>;\n result?: string;\n}\n\ninterface BuildAssistantMessageOptions {\n suppressInternalContinuation?: boolean;\n}\n\ntype AssistantMessage = NonNullable<ReturnType<typeof buildAssistantMessage>>;\ntype UserMessage = ReturnType<typeof buildUserMessage>;\n\nconst MAX_STORED_ATTACHMENT_CHARS = 60_000;\n\nfunction isInternalContinuationError(event: {\n error: string;\n errorCode?: string;\n recoverable?: boolean;\n}): boolean {\n const code = String(event.errorCode ?? \"\").toLowerCase();\n const msg = event.error.toLowerCase();\n if (code === \"builder_gateway_error\") return false;\n return (\n event.recoverable === true ||\n code === \"builder_gateway_timeout\" ||\n code === \"stale_run\" ||\n code === \"timeout\" ||\n code === \"timeout_error\" ||\n code === \"http_408\" ||\n code === \"http_429\" ||\n code === \"http_500\" ||\n code === \"http_502\" ||\n code === \"http_503\" ||\n code === \"http_504\" ||\n code === \"rate_limited\" ||\n code === \"too_many_concurrent_requests\" ||\n code === \"overloaded_error\" ||\n msg.includes(\"timeout\") ||\n msg.includes(\"gateway timeout\") ||\n msg.includes(\"inactivity timeout\") ||\n msg.includes(\"stream ended\") ||\n msg.includes(\"stream closed\") ||\n msg.includes(\"temporarily unavailable\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\") ||\n msg.includes(\"529\")\n );\n}\n\n/**\n * Reconstruct an assistant-ui message from raw agent run events.\n * Mirrors the client-side processEvent logic so the server can persist\n * the assistant's response even if the frontend is disconnected.\n */\nexport function buildAssistantMessage(\n events: RunEvent[],\n runId?: string,\n options: BuildAssistantMessageOptions = {},\n): {\n id: string;\n createdAt: Date;\n role: \"assistant\";\n content: ContentPart[];\n status:\n | { type: \"complete\"; reason: \"stop\" }\n | { type: \"incomplete\"; reason: \"error\" };\n metadata: Record<string, unknown>;\n} | null {\n const content: ContentPart[] = [];\n let toolCallCounter = 0;\n let runError: {\n message: string;\n errorCode?: string;\n details?: string;\n recoverable?: boolean;\n } | null = null;\n let endedAtInternalContinuationBoundary = false;\n\n const appendText = (text: string) => {\n const last = content[content.length - 1];\n if (last && last.type === \"text\") {\n last.text = (last.text ?? \"\") + text;\n } else {\n content.push({ type: \"text\", text });\n }\n };\n\n for (const { event } of events) {\n if (event.type === \"clear\") {\n content.length = 0;\n toolCallCounter = 0;\n continue;\n }\n\n if (event.type === \"text\") {\n appendText(event.text ?? \"\");\n continue;\n }\n\n if (event.type === \"tool_start\") {\n const toolCallId = `tc_${++toolCallCounter}`;\n const args = (event.input ?? {}) as Record<string, string>;\n content.push({\n type: \"tool-call\",\n toolCallId,\n toolName: event.tool ?? \"unknown\",\n argsText: JSON.stringify(args),\n args,\n });\n continue;\n }\n\n if (event.type === \"tool_done\") {\n for (let i = content.length - 1; i >= 0; i--) {\n const part = content[i];\n if (\n part.type === \"tool-call\" &&\n part.toolName === event.tool &&\n part.result === undefined\n ) {\n part.result = event.result ?? \"\";\n break;\n }\n }\n continue;\n }\n\n if (event.type === \"loop_limit\") {\n // Older servers emitted this as a user-visible terminal event. Treat it\n // as an internal continuation boundary when rebuilding persisted turns.\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"auto_continue\") {\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"error\") {\n if (\n options.suppressInternalContinuation &&\n isInternalContinuationError(event)\n ) {\n endedAtInternalContinuationBoundary = true;\n continue;\n }\n if (event.errorCode === \"run_timeout\" && event.recoverable) {\n continue;\n }\n runError = {\n message: event.error,\n ...(event.errorCode ? { errorCode: event.errorCode } : {}),\n ...(event.details ? { details: event.details } : {}),\n ...(event.recoverable ? { recoverable: event.recoverable } : {}),\n };\n appendText(`${content.length > 0 ? \"\\n\\n\" : \"\"}Error: ${event.error}`);\n continue;\n }\n\n // done, missing_api_key — terminal signals, not content\n }\n\n if (content.length === 0 || endedAtInternalContinuationBoundary) return null;\n\n const metadata: Record<string, unknown> = {};\n if (runId) metadata.runId = runId;\n if (runError) {\n metadata.custom = {\n runError: {\n ...runError,\n ...(runId ? { runId } : {}),\n },\n };\n }\n\n return {\n id: `server-${runId ?? Date.now()}`,\n createdAt: new Date(),\n role: \"assistant\",\n content,\n status: runError\n ? { type: \"incomplete\" as const, reason: \"error\" as const }\n : { type: \"complete\" as const, reason: \"stop\" as const },\n metadata,\n };\n}\n\nfunction getStoredMessage(entry: any): any {\n return entry?.message ?? entry;\n}\n\nfunction getStoredParentId(entry: any): string | null | undefined {\n return typeof entry?.parentId === \"string\" || entry?.parentId === null\n ? entry.parentId\n : undefined;\n}\n\nfunction getStoredRunConfig(entry: any): any {\n return entry && typeof entry === \"object\" && \"runConfig\" in entry\n ? entry.runConfig\n : undefined;\n}\n\nfunction messageId(message: any): string | undefined {\n return typeof message?.id === \"string\" && message.id ? message.id : undefined;\n}\n\nfunction getMessageRunId(message: any): string | undefined {\n const meta = message?.metadata;\n const direct = meta?.runId;\n const custom = meta?.custom?.runId;\n const errorRun = meta?.custom?.runError?.runId ?? meta?.runError?.runId;\n if (typeof direct === \"string\") return direct;\n if (typeof custom === \"string\") return custom;\n if (typeof errorRun === \"string\") return errorRun;\n return undefined;\n}\n\nfunction messageContentIsEmpty(content: unknown): boolean {\n if (Array.isArray(content)) return content.length === 0;\n return content == null || content === \"\";\n}\n\nfunction messageText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter(\n (part: any) => part?.type === \"text\" && typeof part.text === \"string\",\n )\n .map((part: any) => part.text)\n .join(\"\");\n}\n\nfunction isTerminalAssistantStatus(status: unknown): boolean {\n const type = (status as { type?: unknown } | undefined)?.type;\n return type === \"complete\" || type === \"incomplete\";\n}\n\nfunction normalizeAttachmentIdentity(attachments: unknown): unknown {\n if (!Array.isArray(attachments) || attachments.length === 0) return undefined;\n return attachments.map((att: any) => ({\n type: att?.type,\n name: att?.name,\n contentType: att?.contentType,\n }));\n}\n\nfunction messageIdentityKeys(message: any): string[] {\n const keys: string[] = [];\n if (typeof message?.id === \"string\" && message.id) {\n keys.push(`id:${message.id}`);\n }\n const runId = getMessageRunId(message);\n if (runId) keys.push(`run:${runId}`);\n\n // Normalize attachments through `normalizeAttachmentIdentity` so an\n // explicit empty `[]` (assistant-ui's default for messages with no\n // attachments) and an omitted/undefined `attachments` field hash to the\n // same fingerprint. Without this, every user message ended up duplicated\n // in `chat_threads`: one copy from `saveThreadData` (runtime export\n // includes `attachments: []`) and one from `persistSubmittedUserMessage`\n // → `buildUserMessage` (omits the field entirely). The merge couldn't\n // dedupe them because their fingerprints differed by exactly one\n // `[]` vs `undefined`. (Repro on slides prod: every user turn produced\n // a `client_user → assistant → server_user` triple instead of a\n // `user → assistant` pair.)\n try {\n keys.push(\n `fingerprint:${JSON.stringify({\n role: message?.role,\n content: message?.content,\n attachments: normalizeAttachmentIdentity(message?.attachments),\n })}`,\n );\n } catch {\n // Best effort. id/runId usually exist for persisted assistant-ui rows.\n }\n if (message?.role === \"user\") {\n try {\n keys.push(\n `user-fingerprint:${JSON.stringify({\n role: message.role,\n content: message.content,\n attachments: normalizeAttachmentIdentity(message.attachments),\n })}`,\n );\n } catch {\n // Same best-effort behavior as the full fingerprint.\n }\n }\n return keys;\n}\n\nfunction messagesMatch(a: any, b: any): boolean {\n const bKeys = new Set(messageIdentityKeys(b));\n return messageIdentityKeys(a).some((key) => bKeys.has(key));\n}\n\nfunction chooseMergedMessageEntry(existingEntry: any, incomingEntry: any): any {\n const existing = getStoredMessage(existingEntry);\n const incoming = getStoredMessage(incomingEntry);\n if (\n existing?.role === \"assistant\" &&\n incoming?.role === \"assistant\" &&\n isTerminalAssistantStatus(existing?.status) &&\n !isTerminalAssistantStatus(incoming?.status)\n ) {\n return existingEntry;\n }\n return incomingEntry;\n}\n\nfunction normalizeMessageEntry(\n entry: any,\n parentId: string | null,\n): { message: any; parentId: string | null; runConfig?: any } | null {\n const message = getStoredMessage(entry);\n if (!messageId(message)) return null;\n const runConfig = getStoredRunConfig(entry);\n return {\n message,\n parentId,\n ...(runConfig !== undefined ? { runConfig } : {}),\n };\n}\n\n/**\n * Convert legacy/partially merged thread data into assistant-ui's exported\n * repository shape and repair parent links so `threadRuntime.import()` cannot\n * fail with \"Parent message not found\".\n */\nexport function normalizeThreadRepository(repo: any): any {\n const normalized = repo && typeof repo === \"object\" ? { ...repo } : {};\n const sourceMessages = Array.isArray(repo?.messages) ? repo.messages : [];\n const messages: Array<{\n message: any;\n parentId: string | null;\n runConfig?: any;\n }> = [];\n const seenIds = new Set<string>();\n let previousId: string | null = null;\n\n for (const entry of sourceMessages) {\n const message = getStoredMessage(entry);\n const id = messageId(message);\n if (!id) continue;\n\n const requestedParentId = getStoredParentId(entry);\n const parentId =\n requestedParentId === null\n ? null\n : requestedParentId && seenIds.has(requestedParentId)\n ? requestedParentId\n : previousId;\n\n const normalizedEntry = normalizeMessageEntry(entry, parentId);\n if (!normalizedEntry) continue;\n\n messages.push(normalizedEntry);\n seenIds.add(id);\n previousId = id;\n }\n\n normalized.messages = messages;\n const headId = typeof repo?.headId === \"string\" ? repo.headId : undefined;\n normalized.headId =\n headId && seenIds.has(headId) ? headId : (previousId ?? null);\n return normalized;\n}\n\nfunction rewriteEntryParentId(\n entry: any,\n idRewrites: Map<string, string>,\n): any {\n const parentId = getStoredParentId(entry);\n if (!parentId) return entry;\n const rewritten = idRewrites.get(parentId);\n if (!rewritten) return entry;\n return { ...entry, parentId: rewritten };\n}\n\n/**\n * Merge an incoming client-side full-thread save over the current SQL copy.\n *\n * The browser exports and PUTs the whole assistant-ui repository. If a server\n * completion save lands first, an older browser export can otherwise replace\n * `thread_data` wholesale and delete the assistant message the server just\n * reconstructed from run events. Preserve server-only messages while still\n * accepting client-only messages and metadata.\n */\nexport interface MergeThreadDataOptions {\n preserveExistingQueuedMessages?: boolean;\n preserveExistingTopLevelKeys?: boolean;\n}\n\nexport function mergeThreadDataForClientSave(\n existingRepo: any,\n incomingRepo: any,\n options: MergeThreadDataOptions = {},\n) {\n const preserveExistingQueuedMessages =\n options.preserveExistingQueuedMessages ?? true;\n const preserveExistingTopLevelKeys =\n options.preserveExistingTopLevelKeys ?? true;\n const existingNormalized = normalizeThreadRepository(existingRepo);\n const incomingNormalized = normalizeThreadRepository(incomingRepo);\n const merged =\n incomingNormalized && typeof incomingNormalized === \"object\"\n ? { ...incomingNormalized }\n : {};\n if (\n preserveExistingTopLevelKeys &&\n existingNormalized &&\n typeof existingNormalized === \"object\"\n ) {\n for (const [key, value] of Object.entries(existingNormalized)) {\n if (key === \"messages\" || key === \"headId\") continue;\n if (key === \"queuedMessages\" && !preserveExistingQueuedMessages) {\n continue;\n }\n if (!(key in merged)) {\n merged[key] = value;\n }\n }\n } else if (\n preserveExistingQueuedMessages &&\n existingNormalized &&\n typeof existingNormalized === \"object\" &&\n existingNormalized.queuedMessages !== undefined &&\n merged.queuedMessages === undefined\n ) {\n merged.queuedMessages = existingNormalized.queuedMessages;\n }\n\n const existingMessages = Array.isArray(existingNormalized?.messages)\n ? existingNormalized.messages\n : null;\n const incomingMessages = Array.isArray(merged.messages)\n ? merged.messages\n : null;\n if (!existingMessages || !incomingMessages) return merged;\n\n const incomingKeySets = incomingMessages.map(\n (entry: any) => new Set(messageIdentityKeys(getStoredMessage(entry))),\n );\n const usedIncoming = new Set<number>();\n const nextMessages: any[] = [];\n const idRewrites = new Map<string, string>();\n\n for (const existingEntry of existingMessages) {\n const existingKeys = messageIdentityKeys(getStoredMessage(existingEntry));\n const incomingIndex = incomingKeySets.findIndex(\n (keys, index) =>\n !usedIncoming.has(index) && existingKeys.some((key) => keys.has(key)),\n );\n\n if (incomingIndex === -1) {\n nextMessages.push(existingEntry);\n continue;\n }\n\n usedIncoming.add(incomingIndex);\n const incomingEntry = incomingMessages[incomingIndex];\n const chosen = chooseMergedMessageEntry(existingEntry, incomingEntry);\n const existingId = messageId(getStoredMessage(existingEntry));\n const chosenId = messageId(getStoredMessage(chosen));\n if (existingId && chosenId && existingId !== chosenId) {\n idRewrites.set(existingId, chosenId);\n }\n nextMessages.push(chosen);\n }\n\n for (let index = 0; index < incomingMessages.length; index++) {\n if (!usedIncoming.has(index)) nextMessages.push(incomingMessages[index]);\n }\n\n merged.messages = nextMessages.map((entry) =>\n rewriteEntryParentId(entry, idRewrites),\n );\n return normalizeThreadRepository(merged);\n}\n\nfunction escapeAttachmentAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction unwrapTextAttachmentEnvelope(text: string): string {\n const match = text.match(\n /^<attachment\\b[^>]*>\\n?([\\s\\S]*?)\\n?<\\/attachment>$/,\n );\n return match ? match[1] : text;\n}\n\nfunction truncateStoredAttachment(text: string): string {\n const unwrapped = unwrapTextAttachmentEnvelope(text);\n if (unwrapped.length <= MAX_STORED_ATTACHMENT_CHARS) return unwrapped;\n const omitted = unwrapped.length - MAX_STORED_ATTACHMENT_CHARS;\n return `${unwrapped.slice(0, MAX_STORED_ATTACHMENT_CHARS)}\\n\\n[Attachment truncated after ${MAX_STORED_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from persisted chat history.]`;\n}\n\nfunction textAttachmentEnvelope(\n att: AgentChatAttachment,\n text: string,\n): string {\n const attrs = [\n `name=\"${escapeAttachmentAttribute(att.name || \"attachment\")}\"`,\n att.contentType\n ? `contentType=\"${escapeAttachmentAttribute(att.contentType)}\"`\n : null,\n att.type ? `type=\"${escapeAttachmentAttribute(att.type)}\"` : null,\n ].filter(Boolean);\n return `<attachment ${attrs.join(\" \")}>\\n${truncateStoredAttachment(text)}\\n</attachment>`;\n}\n\nfunction buildStoredAttachments(\n attachments: AgentChatAttachment[] | undefined,\n runId: string | undefined,\n): any[] {\n return (attachments ?? [])\n .map((att, index) => {\n const id = `server-${runId ?? Date.now()}-attachment-${index}`;\n if (att.type === \"image\" && att.data) {\n return {\n id,\n type: \"image\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [{ type: \"image\", image: att.data }],\n };\n }\n if (att.data) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n {\n type: \"file\",\n data: att.data,\n mimeType: att.contentType,\n filename: att.name,\n },\n ],\n };\n }\n if (typeof att.text === \"string\" && att.text.length > 0) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n { type: \"text\", text: textAttachmentEnvelope(att, att.text) },\n ],\n };\n }\n return null;\n })\n .filter(Boolean);\n}\n\nexport function buildUserMessage(opts: {\n text: string;\n attachments?: AgentChatAttachment[];\n runId?: string;\n createdAt?: Date;\n}): {\n id: string;\n createdAt: Date;\n role: \"user\";\n content: ContentPart[];\n attachments?: any[];\n metadata: Record<string, unknown>;\n} {\n const attachments = buildStoredAttachments(opts.attachments, opts.runId);\n return {\n id: `server-user-${opts.runId ?? Date.now()}`,\n createdAt: opts.createdAt ?? new Date(),\n role: \"user\",\n content: [{ type: \"text\", text: opts.text }],\n ...(attachments.length > 0 ? { attachments } : {}),\n metadata: {\n custom: {\n submittedRunId: opts.runId,\n },\n },\n };\n}\n\nexport function upsertUserMessage(repo: any, userMsg: UserMessage): any {\n const nextRepo = normalizeThreadRepository(repo);\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n if (lastMsg?.role === \"user\" && messagesMatch(lastMsg, userMsg)) {\n return nextRepo;\n }\n\n const parentId =\n lastIndex >= 0 ? (messageId(getStoredMessage(lastEntry)) ?? null) : null;\n nextRepo.messages.push({ message: userMsg, parentId });\n nextRepo.headId = userMsg.id;\n return nextRepo;\n}\n\nfunction shouldReplaceLastAssistant(\n lastMessage: any,\n assistantMsg: AssistantMessage,\n): boolean {\n const lastContent = lastMessage?.content;\n if (messageContentIsEmpty(lastContent)) return true;\n\n const lastRunId = getMessageRunId(lastMessage);\n const nextRunId = getMessageRunId(assistantMsg);\n if (lastRunId && nextRunId && lastRunId === nextRunId) return true;\n if (lastRunId && nextRunId && lastRunId !== nextRunId) return false;\n\n const lastStatus = lastMessage?.status;\n if (lastStatus && !isTerminalAssistantStatus(lastStatus)) return true;\n\n try {\n if (JSON.stringify(lastContent) === JSON.stringify(assistantMsg.content)) {\n return true;\n }\n } catch {\n // Fall through to the text-prefix check.\n }\n\n const lastText = messageText(lastContent).trim();\n const nextText = messageText(assistantMsg.content).trim();\n if (isTerminalAssistantStatus(lastStatus)) return false;\n return Boolean(lastText && nextText && nextText.startsWith(lastText));\n}\n\n/**\n * Merge the server-reconstructed assistant message into persisted\n * assistant-ui thread data.\n *\n * The browser periodically saves thread data while a run is still streaming.\n * That can leave the last assistant message non-empty but partial/pending.\n * Completion must replace that same-run partial message instead of treating\n * any assistant content as proof that the frontend already saved the final\n * turn.\n */\nexport function upsertAssistantMessage(\n repo: any,\n assistantMsg: AssistantMessage,\n): any {\n const nextRepo = normalizeThreadRepository(repo);\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n const lastRole = lastMsg?.role;\n\n if (\n lastRole === \"assistant\" &&\n shouldReplaceLastAssistant(lastMsg, assistantMsg)\n ) {\n nextRepo.messages[lastIndex] = { ...lastEntry, message: assistantMsg };\n nextRepo.headId = assistantMsg.id;\n return nextRepo;\n }\n\n const parentId =\n nextRepo.messages.length > 0\n ? (messageId(\n getStoredMessage(nextRepo.messages[nextRepo.messages.length - 1]),\n ) ?? null)\n : null;\n nextRepo.messages.push({ message: assistantMsg, parentId });\n nextRepo.headId = assistantMsg.id;\n return nextRepo;\n}\n\n/**\n * Extract title and preview from a thread runtime export.\n * Isomorphic — works on both server and client.\n */\nexport function extractThreadMeta(repo: any): {\n title: string;\n preview: string;\n} {\n const msgs = repo?.messages;\n if (!Array.isArray(msgs) || msgs.length === 0)\n return { title: \"\", preview: \"\" };\n\n let title = \"\";\n let preview = \"\";\n for (const entry of msgs) {\n // Support both wrapped ({ message: { role, content } }) and flat ({ role, content }) formats\n const msg = entry?.message ?? entry;\n if (msg.role !== \"user\") continue;\n const textParts = Array.isArray(msg.content)\n ? msg.content\n .filter((p: any) => p.type === \"text\")\n .map((p: any) => p.text)\n .join(\" \")\n : typeof msg.content === \"string\"\n ? msg.content\n : \"\";\n if (textParts.trim()) {\n if (!title) title = textParts.trim().slice(0, 80);\n preview = textParts.trim().slice(0, 120);\n }\n }\n return { title, preview };\n}\n"]}
|
|
@@ -27,7 +27,12 @@ export declare function forkThread(sourceId: string, ownerEmail: string, opts?:
|
|
|
27
27
|
}): Promise<ChatThread | null>;
|
|
28
28
|
export declare function listThreads(ownerEmail: string, limit?: number, offset?: number): Promise<ChatThreadSummary[]>;
|
|
29
29
|
export declare function searchThreads(ownerEmail: string, query: string, limit?: number): Promise<ChatThreadSummary[]>;
|
|
30
|
-
export
|
|
30
|
+
export interface UpdateThreadDataOptions {
|
|
31
|
+
preserveExistingQueuedMessages?: boolean;
|
|
32
|
+
preserveExistingTopLevelKeys?: boolean;
|
|
33
|
+
maxAttempts?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function updateThreadData(id: string, threadData: string, title: string, preview: string, messageCount: number, options?: UpdateThreadDataOptions): Promise<void>;
|
|
31
36
|
export interface ThreadEngineMeta {
|
|
32
37
|
engineName: string;
|
|
33
38
|
model: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"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"}
|