@agent-native/core 0.12.24 → 0.12.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/agent/production-agent.d.ts +9 -2
  2. package/dist/agent/production-agent.d.ts.map +1 -1
  3. package/dist/agent/production-agent.js +56 -37
  4. package/dist/agent/production-agent.js.map +1 -1
  5. package/dist/agent/thread-data-builder.d.ts +16 -1
  6. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  7. package/dist/agent/thread-data-builder.js +132 -0
  8. package/dist/agent/thread-data-builder.js.map +1 -1
  9. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  10. package/dist/client/AgentTaskCard.js +16 -3
  11. package/dist/client/AgentTaskCard.js.map +1 -1
  12. package/dist/client/AssistantChat.d.ts.map +1 -1
  13. package/dist/client/AssistantChat.js +22 -12
  14. package/dist/client/AssistantChat.js.map +1 -1
  15. package/dist/client/IframeEmbed.d.ts.map +1 -1
  16. package/dist/client/IframeEmbed.js +2 -2
  17. package/dist/client/IframeEmbed.js.map +1 -1
  18. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  19. package/dist/client/agent-chat-adapter.js +77 -12
  20. package/dist/client/agent-chat-adapter.js.map +1 -1
  21. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  22. package/dist/client/composer/ComposerPlusMenu.js +1 -1
  23. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  24. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  25. package/dist/client/composer/PromptComposer.js +8 -7
  26. package/dist/client/composer/PromptComposer.js.map +1 -1
  27. package/dist/client/composer/attachment-accept.d.ts +7 -0
  28. package/dist/client/composer/attachment-accept.d.ts.map +1 -0
  29. package/dist/client/composer/attachment-accept.js +36 -0
  30. package/dist/client/composer/attachment-accept.js.map +1 -0
  31. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  32. package/dist/client/progress/RunsTray.js +3 -1
  33. package/dist/client/progress/RunsTray.js.map +1 -1
  34. package/dist/client/sse-event-processor.d.ts.map +1 -1
  35. package/dist/client/sse-event-processor.js +12 -1
  36. package/dist/client/sse-event-processor.js.map +1 -1
  37. package/dist/db/client.d.ts +3 -0
  38. package/dist/db/client.d.ts.map +1 -1
  39. package/dist/db/client.js +70 -34
  40. package/dist/db/client.js.map +1 -1
  41. package/dist/db/create-get-db.d.ts.map +1 -1
  42. package/dist/db/create-get-db.js +30 -7
  43. package/dist/db/create-get-db.js.map +1 -1
  44. package/dist/deploy/build.js +64 -0
  45. package/dist/deploy/build.js.map +1 -1
  46. package/dist/onboarding/default-steps.d.ts.map +1 -1
  47. package/dist/onboarding/default-steps.js +8 -1
  48. package/dist/onboarding/default-steps.js.map +1 -1
  49. package/dist/scripts/db/exec.d.ts.map +1 -1
  50. package/dist/scripts/db/exec.js +3 -6
  51. package/dist/scripts/db/exec.js.map +1 -1
  52. package/dist/scripts/db/patch.d.ts.map +1 -1
  53. package/dist/scripts/db/patch.js +3 -6
  54. package/dist/scripts/db/patch.js.map +1 -1
  55. package/dist/scripts/db/query.d.ts.map +1 -1
  56. package/dist/scripts/db/query.js +3 -6
  57. package/dist/scripts/db/query.js.map +1 -1
  58. package/dist/scripts/db/schema.d.ts.map +1 -1
  59. package/dist/scripts/db/schema.js +3 -6
  60. package/dist/scripts/db/schema.js.map +1 -1
  61. package/dist/scripts/db/sqlite-client.d.ts +15 -0
  62. package/dist/scripts/db/sqlite-client.d.ts.map +1 -0
  63. package/dist/scripts/db/sqlite-client.js +51 -0
  64. package/dist/scripts/db/sqlite-client.js.map +1 -0
  65. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  66. package/dist/server/agent-chat-plugin.js +53 -2
  67. package/dist/server/agent-chat-plugin.js.map +1 -1
  68. package/dist/server/better-auth-instance.js +4 -3
  69. package/dist/server/better-auth-instance.js.map +1 -1
  70. package/dist/server/credential-provider.d.ts +2 -2
  71. package/dist/server/credential-provider.d.ts.map +1 -1
  72. package/dist/server/credential-provider.js +22 -1
  73. package/dist/server/credential-provider.js.map +1 -1
  74. package/dist/server/google-oauth.js +1 -1
  75. package/dist/server/google-oauth.js.map +1 -1
  76. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import type { RunEvent } from "./types.js";
1
+ import type { AgentChatAttachment, RunEvent } from "./types.js";
2
2
  interface ContentPart {
3
3
  type: string;
4
4
  text?: string;
@@ -12,6 +12,7 @@ interface BuildAssistantMessageOptions {
12
12
  suppressInternalContinuation?: boolean;
13
13
  }
14
14
  type AssistantMessage = NonNullable<ReturnType<typeof buildAssistantMessage>>;
15
+ type UserMessage = ReturnType<typeof buildUserMessage>;
15
16
  /**
16
17
  * Reconstruct an assistant-ui message from raw agent run events.
17
18
  * Mirrors the client-side processEvent logic so the server can persist
@@ -41,6 +42,20 @@ export declare function buildAssistantMessage(events: RunEvent[], runId?: string
41
42
  * accepting client-only messages and metadata.
42
43
  */
43
44
  export declare function mergeThreadDataForClientSave(existingRepo: any, incomingRepo: any): any;
45
+ export declare function buildUserMessage(opts: {
46
+ text: string;
47
+ attachments?: AgentChatAttachment[];
48
+ runId?: string;
49
+ createdAt?: Date;
50
+ }): {
51
+ id: string;
52
+ createdAt: Date;
53
+ role: "user";
54
+ content: ContentPart[];
55
+ attachments?: any[];
56
+ metadata: Record<string, unknown>;
57
+ };
58
+ export declare function upsertUserMessage(repo: any, userMsg: UserMessage): any;
44
59
  /**
45
60
  * Merge the server-reconstructed assistant message into persisted
46
61
  * assistant-ui thread data.
@@ -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,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,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;AAuC9E;;;;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;AA0ED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,GAAG,EACjB,YAAY,EAAE,GAAG,OAmDlB;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,gBAAgB,GAC7B,GAAG,CA+BL;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAyBA"}
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;AAyCvD;;;;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;AAqGD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,GAAG,EACjB,YAAY,EAAE,GAAG,OAmDlB;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,CAoBtE;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,gBAAgB,GAC7B,GAAG,CA+BL;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAyBA"}
@@ -1,3 +1,4 @@
1
+ const MAX_STORED_ATTACHMENT_CHARS = 60_000;
1
2
  function isInternalContinuationError(event) {
2
3
  const code = String(event.errorCode ?? "").toLowerCase();
3
4
  const msg = event.error.toLowerCase();
@@ -174,6 +175,15 @@ function isTerminalAssistantStatus(status) {
174
175
  const type = status?.type;
175
176
  return type === "complete" || type === "incomplete";
176
177
  }
178
+ function normalizeAttachmentIdentity(attachments) {
179
+ if (!Array.isArray(attachments))
180
+ return undefined;
181
+ return attachments.map((att) => ({
182
+ type: att?.type,
183
+ name: att?.name,
184
+ contentType: att?.contentType,
185
+ }));
186
+ }
177
187
  function messageIdentityKeys(message) {
178
188
  const keys = [];
179
189
  if (typeof message?.id === "string" && message.id) {
@@ -192,8 +202,24 @@ function messageIdentityKeys(message) {
192
202
  catch {
193
203
  // Best effort. id/runId usually exist for persisted assistant-ui rows.
194
204
  }
205
+ if (message?.role === "user") {
206
+ try {
207
+ keys.push(`user-fingerprint:${JSON.stringify({
208
+ role: message.role,
209
+ content: message.content,
210
+ attachments: normalizeAttachmentIdentity(message.attachments),
211
+ })}`);
212
+ }
213
+ catch {
214
+ // Same best-effort behavior as the full fingerprint.
215
+ }
216
+ }
195
217
  return keys;
196
218
  }
219
+ function messagesMatch(a, b) {
220
+ const bKeys = new Set(messageIdentityKeys(b));
221
+ return messageIdentityKeys(a).some((key) => bKeys.has(key));
222
+ }
197
223
  function chooseMergedMessageEntry(existingEntry, incomingEntry) {
198
224
  const existing = getStoredMessage(existingEntry);
199
225
  const incoming = getStoredMessage(incomingEntry);
@@ -250,6 +276,112 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo) {
250
276
  merged.messages = nextMessages;
251
277
  return merged;
252
278
  }
279
+ function escapeAttachmentAttribute(value) {
280
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
281
+ }
282
+ function unwrapTextAttachmentEnvelope(text) {
283
+ const match = text.match(/^<attachment\b[^>]*>\n?([\s\S]*?)\n?<\/attachment>$/);
284
+ return match ? match[1] : text;
285
+ }
286
+ function truncateStoredAttachment(text) {
287
+ const unwrapped = unwrapTextAttachmentEnvelope(text);
288
+ if (unwrapped.length <= MAX_STORED_ATTACHMENT_CHARS)
289
+ return unwrapped;
290
+ const omitted = unwrapped.length - MAX_STORED_ATTACHMENT_CHARS;
291
+ 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.]`;
292
+ }
293
+ function textAttachmentEnvelope(att, text) {
294
+ const attrs = [
295
+ `name="${escapeAttachmentAttribute(att.name || "attachment")}"`,
296
+ att.contentType
297
+ ? `contentType="${escapeAttachmentAttribute(att.contentType)}"`
298
+ : null,
299
+ att.type ? `type="${escapeAttachmentAttribute(att.type)}"` : null,
300
+ ].filter(Boolean);
301
+ return `<attachment ${attrs.join(" ")}>\n${truncateStoredAttachment(text)}\n</attachment>`;
302
+ }
303
+ function buildStoredAttachments(attachments, runId) {
304
+ return (attachments ?? [])
305
+ .map((att, index) => {
306
+ const id = `server-${runId ?? Date.now()}-attachment-${index}`;
307
+ if (att.type === "image" && att.data) {
308
+ return {
309
+ id,
310
+ type: "image",
311
+ name: att.name,
312
+ contentType: att.contentType,
313
+ status: { type: "complete" },
314
+ content: [{ type: "image", image: att.data }],
315
+ };
316
+ }
317
+ if (att.data) {
318
+ return {
319
+ id,
320
+ type: "file",
321
+ name: att.name,
322
+ contentType: att.contentType,
323
+ status: { type: "complete" },
324
+ content: [
325
+ {
326
+ type: "file",
327
+ data: att.data,
328
+ mimeType: att.contentType,
329
+ filename: att.name,
330
+ },
331
+ ],
332
+ };
333
+ }
334
+ if (typeof att.text === "string" && att.text.length > 0) {
335
+ return {
336
+ id,
337
+ type: "file",
338
+ name: att.name,
339
+ contentType: att.contentType,
340
+ status: { type: "complete" },
341
+ content: [
342
+ { type: "text", text: textAttachmentEnvelope(att, att.text) },
343
+ ],
344
+ };
345
+ }
346
+ return null;
347
+ })
348
+ .filter(Boolean);
349
+ }
350
+ export function buildUserMessage(opts) {
351
+ const attachments = buildStoredAttachments(opts.attachments, opts.runId);
352
+ return {
353
+ id: `server-user-${opts.runId ?? Date.now()}`,
354
+ createdAt: opts.createdAt ?? new Date(),
355
+ role: "user",
356
+ content: [{ type: "text", text: opts.text }],
357
+ ...(attachments.length > 0 ? { attachments } : {}),
358
+ metadata: {
359
+ custom: {
360
+ submittedRunId: opts.runId,
361
+ },
362
+ },
363
+ };
364
+ }
365
+ export function upsertUserMessage(repo, userMsg) {
366
+ const nextRepo = repo && typeof repo === "object" ? repo : {};
367
+ if (!Array.isArray(nextRepo.messages))
368
+ nextRepo.messages = [];
369
+ const lastIndex = nextRepo.messages.length - 1;
370
+ const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;
371
+ const lastMsg = getStoredMessage(lastEntry);
372
+ if (lastMsg?.role === "user" && messagesMatch(lastMsg, userMsg)) {
373
+ return nextRepo;
374
+ }
375
+ const isWrapped = Boolean(lastEntry && "message" in lastEntry);
376
+ if (isWrapped) {
377
+ const parentId = lastIndex >= 0 ? (getStoredMessage(lastEntry)?.id ?? null) : null;
378
+ nextRepo.messages.push({ message: userMsg, parentId });
379
+ }
380
+ else {
381
+ nextRepo.messages.push(userMsg);
382
+ }
383
+ return nextRepo;
384
+ }
253
385
  function shouldReplaceLastAssistant(lastMessage, assistantMsg) {
254
386
  const lastContent = lastMessage?.content;
255
387
  if (messageContentIsEmpty(lastContent))
@@ -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 { 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>>;\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 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 return keys;\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 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":"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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, \"&amp;\").replace(/\"/g, \"&quot;\");\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 +1 @@
1
- {"version":3,"file":"AgentTaskCard.d.ts","sourceRoot":"","sources":["../../src/client/AgentTaskCard.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,MAAM,GACP,EAAE,kBAAkB,2CAiOpB"}
1
+ {"version":3,"file":"AgentTaskCard.d.ts","sourceRoot":"","sources":["../../src/client/AgentTaskCard.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,MAAM,GACP,EAAE,kBAAkB,2CAiPpB"}
@@ -136,14 +136,27 @@ export function AgentTaskCard({ taskId, threadId, description, onOpen, }) {
136
136
  const isRunning = status === "running";
137
137
  const isComplete = status === "completed";
138
138
  const isError = status === "errored";
139
+ const taskTitle = description.trim() || "Task";
140
+ const currentStepText = currentStep.trim();
141
+ const statusLabel = isRunning ? "Running" : isError ? "Error" : "Done";
142
+ const statusClassName = cn("inline-flex h-5 shrink-0 items-center gap-1 rounded-md px-1.5 text-[10px] font-medium", isError
143
+ ? "bg-destructive/10 text-destructive"
144
+ : isComplete
145
+ ? "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"
146
+ : "bg-muted text-muted-foreground");
139
147
  const displayText = isComplete && summary ? summary : preview;
140
148
  const hasContent = displayText.length > 0;
141
- return (_jsxs("div", { className: cn("my-2 rounded-lg border overflow-hidden transition-colors", isError
149
+ const emptyMessage = isRunning
150
+ ? "Waiting for updates"
151
+ : isError
152
+ ? "No error details yet"
153
+ : "No summary available";
154
+ return (_jsxs("div", { className: cn("my-2 overflow-hidden rounded-lg border bg-background/50 transition-colors", isError
142
155
  ? "border-destructive/30"
143
156
  : isComplete
144
157
  ? "border-emerald-500/20"
145
- : "border-border"), children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 cursor-pointer select-none hover:bg-muted/50", onClick: () => setExpanded(!expanded), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin text-muted-foreground" })) : isError ? (_jsx(IconAlertCircle, { className: "h-3.5 w-3.5 text-destructive" })) : (_jsx(IconCheck, { className: "h-3.5 w-3.5 text-emerald-500" })) }), _jsx(IconSubtask, { className: "h-3.5 w-3.5 text-muted-foreground/60 shrink-0" }), _jsx("span", { className: "text-xs font-medium truncate min-w-0 flex-1", children: description }), currentStep && isRunning && (_jsx("span", { className: "text-[10px] text-muted-foreground/70 truncate max-w-[180px] shrink-0", children: currentStep })), isComplete && (_jsx("span", { className: "text-[10px] text-emerald-500/70 shrink-0", children: "Done" })), _jsx(IconChevronRight, { className: cn("h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150", expanded && "rotate-90") })] }), expanded && hasContent && (_jsx("div", { className: "px-3 pb-2", children: _jsx("div", { ref: previewRef, className: "rounded-md bg-muted/30 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: displayText.length > 800
158
+ : "border-border"), children: [_jsxs("button", { type: "button", "aria-expanded": expanded, className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-muted/45", onClick: () => setExpanded(!expanded), children: [_jsxs("span", { className: "inline-flex h-5 shrink-0 items-center gap-1 rounded-md border border-border/60 bg-background/70 px-1.5 text-[10px] font-medium text-muted-foreground", children: [_jsx(IconSubtask, { className: "h-3 w-3" }), "Sub-agent"] }), _jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium text-foreground", children: taskTitle }), _jsxs("span", { className: statusClassName, children: [isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isError ? (_jsx(IconAlertCircle, { className: "h-3 w-3" })) : (_jsx(IconCheck, { className: "h-3 w-3" })), statusLabel] }), _jsx(IconChevronRight, { className: cn("h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150", expanded && "rotate-90") })] }), expanded && isRunning && currentStepText && (_jsxs("div", { className: "flex gap-1.5 border-t border-border/60 px-3 py-1.5 text-[11px] text-muted-foreground", children: [_jsx("span", { className: "shrink-0 font-medium text-foreground/70", children: "Now:" }), _jsx("span", { className: "min-w-0 break-words", children: currentStepText })] })), expanded && hasContent && (_jsx("div", { className: "px-3 pb-2 pt-1", children: _jsx("div", { ref: previewRef, className: "agent-markdown prose prose-sm prose-invert max-h-48 max-w-none overflow-y-auto break-words rounded-md border border-border/50 bg-muted/25 px-3 py-2 text-xs text-muted-foreground", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: displayText.length > 800
146
159
  ? "..." + displayText.slice(-800)
147
- : displayText }) }) })), expanded && (_jsxs("div", { className: "flex items-center justify-between px-3 pb-2", children: [isRunning && !hasContent && (_jsx("span", { className: "text-[10px] text-muted-foreground/50", children: "Working..." })), !isRunning && !hasContent && _jsx("span", {}), hasContent && _jsx("span", {}), _jsxs("button", { onClick: handleOpen, className: "inline-flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground hover:bg-muted", children: ["Open", _jsx(IconExternalLink, { className: "h-3 w-3" })] })] }))] }));
160
+ : displayText }) }) })), expanded && (_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pb-2", children: [_jsx("span", { className: "min-w-0 flex-1 truncate text-[10px] text-muted-foreground/60", children: !hasContent ? emptyMessage : "" }), _jsxs("button", { onClick: handleOpen, className: "inline-flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-foreground", children: ["Open thread", _jsx(IconExternalLink, { className: "h-3 w-3" })] })] }))] }));
148
161
  }
149
162
  //# sourceMappingURL=AgentTaskCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentTaskCard.js","sourceRoot":"","sources":["../../src/client/AgentTaskCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport {\n IconLoader2,\n IconCheck,\n IconChevronRight,\n IconExternalLink,\n IconAlertCircle,\n IconSubtask,\n} from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { agentNativePath } from \"./api-path.js\";\n\nexport interface AgentTaskCardProps {\n taskId: string;\n threadId: string;\n description: string;\n onOpen?: (threadId: string) => void;\n}\n\n/**\n * Rich preview card for a sub-agent task. Listens for agent-task-event\n * CustomEvents to update its state in real-time.\n */\nexport function AgentTaskCard({\n taskId,\n threadId,\n description,\n onOpen,\n}: AgentTaskCardProps) {\n const [expanded, setExpanded] = useState(true);\n const [status, setStatus] = useState<\"running\" | \"completed\" | \"errored\">(\n \"running\",\n );\n const [preview, setPreview] = useState(\"\");\n const [currentStep, setCurrentStep] = useState(\"\");\n const [summary, setSummary] = useState(\"\");\n const previewRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleEvent(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail?.taskId || detail.taskId !== taskId) return;\n\n if (detail.type === \"agent_task_update\") {\n if (detail.preview != null) setPreview(detail.preview);\n if (detail.currentStep != null) setCurrentStep(detail.currentStep);\n } else if (detail.type === \"agent_task_complete\") {\n setStatus(\"completed\");\n if (detail.summary) setSummary(detail.summary);\n setCurrentStep(\"\");\n } else if (detail.type === \"agent_task\" && detail.status === \"errored\") {\n setStatus(\"errored\");\n setCurrentStep(\"\");\n }\n }\n\n window.addEventListener(\"agent-task-event\", handleEvent);\n return () => window.removeEventListener(\"agent-task-event\", handleEvent);\n }, [taskId]);\n\n // Poll for task status when running — the main chat's SSE stream may close\n // before the sub-agent completes, so SSE events alone aren't reliable.\n useEffect(() => {\n if (status !== \"running\") return;\n let stopped = false;\n let pollCount = 0;\n const poll = async () => {\n while (!stopped) {\n await new Promise((r) => setTimeout(r, 3000));\n if (stopped) break;\n pollCount++;\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/application-state/agent-task:${taskId}`,\n ),\n );\n if (!res.ok) continue;\n const data = await res.json();\n // The HTTP handler returns the value directly (not wrapped)\n const task = data?.value ?? data;\n if (!task || !task.status) continue;\n if (task.status === \"completed\") {\n setStatus(\"completed\");\n if (task.summary) setSummary(task.summary);\n if (task.preview) setPreview(task.preview);\n setCurrentStep(\"\");\n break;\n } else if (task.status === \"errored\") {\n setStatus(\"errored\");\n if (task.summary) setSummary(task.summary);\n setCurrentStep(\"\");\n break;\n } else {\n // Still running — update preview from persisted state\n if (task.preview) setPreview(task.preview);\n if (task.currentStep) setCurrentStep(task.currentStep);\n }\n\n // Fallback: every 5th poll, check if the sub-agent's run is still\n // active. If it's gone (completed without updating app-state), mark\n // the task as completed so the card doesn't spin forever.\n if (pollCount % 5 === 0) {\n try {\n const runRes = await fetch(\n agentNativePath(\n `/_agent-native/agent-chat/runs/active?threadId=${encodeURIComponent(threadId)}`,\n ),\n );\n if (runRes.ok) {\n const runData = await runRes.json();\n // null or non-running status means the run finished\n if (\n !runData ||\n runData.active === false ||\n (runData.status && runData.status !== \"running\") ||\n runData.status === \"completed\" ||\n runData.status === \"errored\"\n ) {\n const finalStatus =\n runData?.status === \"errored\" ? \"errored\" : \"completed\";\n setStatus(finalStatus);\n setCurrentStep(\"\");\n setSummary(\n (prev) => prev || task?.preview || \"Task completed.\",\n );\n break;\n }\n }\n } catch {\n // Fallback check failed — continue normal polling\n }\n }\n } catch {\n // Polling error — continue\n }\n }\n };\n poll();\n return () => {\n stopped = true;\n };\n }, [status, taskId, threadId]);\n\n // Auto-scroll preview to bottom\n useEffect(() => {\n if (previewRef.current && status === \"running\") {\n previewRef.current.scrollTop = previewRef.current.scrollHeight;\n }\n }, [preview, status]);\n\n const handleOpen = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onOpen?.(threadId);\n },\n [onOpen, threadId],\n );\n\n const isRunning = status === \"running\";\n const isComplete = status === \"completed\";\n const isError = status === \"errored\";\n\n const displayText = isComplete && summary ? summary : preview;\n const hasContent = displayText.length > 0;\n\n return (\n <div\n className={cn(\n \"my-2 rounded-lg border overflow-hidden transition-colors\",\n isError\n ? \"border-destructive/30\"\n : isComplete\n ? \"border-emerald-500/20\"\n : \"border-border\",\n )}\n >\n {/* Header */}\n <div\n className=\"flex items-center gap-2 px-3 py-2.5 cursor-pointer select-none hover:bg-muted/50\"\n onClick={() => setExpanded(!expanded)}\n >\n <span className=\"shrink-0\">\n {isRunning ? (\n <IconLoader2 className=\"h-3.5 w-3.5 animate-spin text-muted-foreground\" />\n ) : isError ? (\n <IconAlertCircle className=\"h-3.5 w-3.5 text-destructive\" />\n ) : (\n <IconCheck className=\"h-3.5 w-3.5 text-emerald-500\" />\n )}\n </span>\n\n <IconSubtask className=\"h-3.5 w-3.5 text-muted-foreground/60 shrink-0\" />\n\n <span className=\"text-xs font-medium truncate min-w-0 flex-1\">\n {description}\n </span>\n\n {currentStep && isRunning && (\n <span className=\"text-[10px] text-muted-foreground/70 truncate max-w-[180px] shrink-0\">\n {currentStep}\n </span>\n )}\n\n {isComplete && (\n <span className=\"text-[10px] text-emerald-500/70 shrink-0\">Done</span>\n )}\n\n <IconChevronRight\n className={cn(\n \"h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150\",\n expanded && \"rotate-90\",\n )}\n />\n </div>\n\n {/* Preview content */}\n {expanded && hasContent && (\n <div className=\"px-3 pb-2\">\n <div\n ref={previewRef}\n className=\"rounded-md bg-muted/30 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none\"\n >\n <ReactMarkdown remarkPlugins={[remarkGfm]}>\n {displayText.length > 800\n ? \"...\" + displayText.slice(-800)\n : displayText}\n </ReactMarkdown>\n </div>\n </div>\n )}\n\n {/* Footer with Open button */}\n {expanded && (\n <div className=\"flex items-center justify-between px-3 pb-2\">\n {isRunning && !hasContent && (\n <span className=\"text-[10px] text-muted-foreground/50\">\n Working...\n </span>\n )}\n {!isRunning && !hasContent && <span />}\n {hasContent && <span />}\n <button\n onClick={handleOpen}\n className=\"inline-flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground hover:bg-muted\"\n >\n Open\n <IconExternalLink className=\"h-3 w-3\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"AgentTaskCard.js","sourceRoot":"","sources":["../../src/client/AgentTaskCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport {\n IconLoader2,\n IconCheck,\n IconChevronRight,\n IconExternalLink,\n IconAlertCircle,\n IconSubtask,\n} from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { agentNativePath } from \"./api-path.js\";\n\nexport interface AgentTaskCardProps {\n taskId: string;\n threadId: string;\n description: string;\n onOpen?: (threadId: string) => void;\n}\n\n/**\n * Rich preview card for a sub-agent task. Listens for agent-task-event\n * CustomEvents to update its state in real-time.\n */\nexport function AgentTaskCard({\n taskId,\n threadId,\n description,\n onOpen,\n}: AgentTaskCardProps) {\n const [expanded, setExpanded] = useState(true);\n const [status, setStatus] = useState<\"running\" | \"completed\" | \"errored\">(\n \"running\",\n );\n const [preview, setPreview] = useState(\"\");\n const [currentStep, setCurrentStep] = useState(\"\");\n const [summary, setSummary] = useState(\"\");\n const previewRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleEvent(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail?.taskId || detail.taskId !== taskId) return;\n\n if (detail.type === \"agent_task_update\") {\n if (detail.preview != null) setPreview(detail.preview);\n if (detail.currentStep != null) setCurrentStep(detail.currentStep);\n } else if (detail.type === \"agent_task_complete\") {\n setStatus(\"completed\");\n if (detail.summary) setSummary(detail.summary);\n setCurrentStep(\"\");\n } else if (detail.type === \"agent_task\" && detail.status === \"errored\") {\n setStatus(\"errored\");\n setCurrentStep(\"\");\n }\n }\n\n window.addEventListener(\"agent-task-event\", handleEvent);\n return () => window.removeEventListener(\"agent-task-event\", handleEvent);\n }, [taskId]);\n\n // Poll for task status when running — the main chat's SSE stream may close\n // before the sub-agent completes, so SSE events alone aren't reliable.\n useEffect(() => {\n if (status !== \"running\") return;\n let stopped = false;\n let pollCount = 0;\n const poll = async () => {\n while (!stopped) {\n await new Promise((r) => setTimeout(r, 3000));\n if (stopped) break;\n pollCount++;\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/application-state/agent-task:${taskId}`,\n ),\n );\n if (!res.ok) continue;\n const data = await res.json();\n // The HTTP handler returns the value directly (not wrapped)\n const task = data?.value ?? data;\n if (!task || !task.status) continue;\n if (task.status === \"completed\") {\n setStatus(\"completed\");\n if (task.summary) setSummary(task.summary);\n if (task.preview) setPreview(task.preview);\n setCurrentStep(\"\");\n break;\n } else if (task.status === \"errored\") {\n setStatus(\"errored\");\n if (task.summary) setSummary(task.summary);\n setCurrentStep(\"\");\n break;\n } else {\n // Still running — update preview from persisted state\n if (task.preview) setPreview(task.preview);\n if (task.currentStep) setCurrentStep(task.currentStep);\n }\n\n // Fallback: every 5th poll, check if the sub-agent's run is still\n // active. If it's gone (completed without updating app-state), mark\n // the task as completed so the card doesn't spin forever.\n if (pollCount % 5 === 0) {\n try {\n const runRes = await fetch(\n agentNativePath(\n `/_agent-native/agent-chat/runs/active?threadId=${encodeURIComponent(threadId)}`,\n ),\n );\n if (runRes.ok) {\n const runData = await runRes.json();\n // null or non-running status means the run finished\n if (\n !runData ||\n runData.active === false ||\n (runData.status && runData.status !== \"running\") ||\n runData.status === \"completed\" ||\n runData.status === \"errored\"\n ) {\n const finalStatus =\n runData?.status === \"errored\" ? \"errored\" : \"completed\";\n setStatus(finalStatus);\n setCurrentStep(\"\");\n setSummary(\n (prev) => prev || task?.preview || \"Task completed.\",\n );\n break;\n }\n }\n } catch {\n // Fallback check failed — continue normal polling\n }\n }\n } catch {\n // Polling error — continue\n }\n }\n };\n poll();\n return () => {\n stopped = true;\n };\n }, [status, taskId, threadId]);\n\n // Auto-scroll preview to bottom\n useEffect(() => {\n if (previewRef.current && status === \"running\") {\n previewRef.current.scrollTop = previewRef.current.scrollHeight;\n }\n }, [preview, status]);\n\n const handleOpen = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onOpen?.(threadId);\n },\n [onOpen, threadId],\n );\n\n const isRunning = status === \"running\";\n const isComplete = status === \"completed\";\n const isError = status === \"errored\";\n\n const taskTitle = description.trim() || \"Task\";\n const currentStepText = currentStep.trim();\n const statusLabel = isRunning ? \"Running\" : isError ? \"Error\" : \"Done\";\n const statusClassName = cn(\n \"inline-flex h-5 shrink-0 items-center gap-1 rounded-md px-1.5 text-[10px] font-medium\",\n isError\n ? \"bg-destructive/10 text-destructive\"\n : isComplete\n ? \"bg-emerald-500/10 text-emerald-600 dark:text-emerald-400\"\n : \"bg-muted text-muted-foreground\",\n );\n\n const displayText = isComplete && summary ? summary : preview;\n const hasContent = displayText.length > 0;\n const emptyMessage = isRunning\n ? \"Waiting for updates\"\n : isError\n ? \"No error details yet\"\n : \"No summary available\";\n\n return (\n <div\n className={cn(\n \"my-2 overflow-hidden rounded-lg border bg-background/50 transition-colors\",\n isError\n ? \"border-destructive/30\"\n : isComplete\n ? \"border-emerald-500/20\"\n : \"border-border\",\n )}\n >\n {/* Header */}\n <button\n type=\"button\"\n aria-expanded={expanded}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-muted/45\"\n onClick={() => setExpanded(!expanded)}\n >\n <span className=\"inline-flex h-5 shrink-0 items-center gap-1 rounded-md border border-border/60 bg-background/70 px-1.5 text-[10px] font-medium text-muted-foreground\">\n <IconSubtask className=\"h-3 w-3\" />\n Sub-agent\n </span>\n\n <span className=\"min-w-0 flex-1 truncate text-xs font-medium text-foreground\">\n {taskTitle}\n </span>\n\n <span className={statusClassName}>\n {isRunning ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : isError ? (\n <IconAlertCircle className=\"h-3 w-3\" />\n ) : (\n <IconCheck className=\"h-3 w-3\" />\n )}\n {statusLabel}\n </span>\n\n <IconChevronRight\n className={cn(\n \"h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150\",\n expanded && \"rotate-90\",\n )}\n />\n </button>\n\n {expanded && isRunning && currentStepText && (\n <div className=\"flex gap-1.5 border-t border-border/60 px-3 py-1.5 text-[11px] text-muted-foreground\">\n <span className=\"shrink-0 font-medium text-foreground/70\">Now:</span>\n <span className=\"min-w-0 break-words\">{currentStepText}</span>\n </div>\n )}\n\n {/* Preview content */}\n {expanded && hasContent && (\n <div className=\"px-3 pb-2 pt-1\">\n <div\n ref={previewRef}\n className=\"agent-markdown prose prose-sm prose-invert max-h-48 max-w-none overflow-y-auto break-words rounded-md border border-border/50 bg-muted/25 px-3 py-2 text-xs text-muted-foreground\"\n >\n <ReactMarkdown remarkPlugins={[remarkGfm]}>\n {displayText.length > 800\n ? \"...\" + displayText.slice(-800)\n : displayText}\n </ReactMarkdown>\n </div>\n </div>\n )}\n\n {/* Footer with Open button */}\n {expanded && (\n <div className=\"flex items-center justify-between gap-2 px-3 pb-2\">\n <span className=\"min-w-0 flex-1 truncate text-[10px] text-muted-foreground/60\">\n {!hasContent ? emptyMessage : \"\"}\n </span>\n <button\n onClick={handleOpen}\n className=\"inline-flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n Open thread\n <IconExternalLink className=\"h-3 w-3\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
3
3
  import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
4
- import { SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
4
+ import { SimpleImageAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
5
5
  import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
6
6
  import ReactMarkdown from "react-markdown";
7
7
  import remarkGfm from "remark-gfm";
@@ -9,6 +9,7 @@ import { createAgentChatAdapter } from "./agent-chat-adapter.js";
9
9
  import { getActiveRun } from "./active-run-state.js";
10
10
  import { AgentAutoContinueSignal, readSSEStreamRaw, } from "./sse-event-processor.js";
11
11
  import { cn } from "./utils.js";
12
+ import { TextAttachmentAdapter } from "./composer/attachment-accept.js";
12
13
  import { AgentTaskCard } from "./AgentTaskCard.js";
13
14
  import { ConnectBuilderCard } from "./ConnectBuilderCard.js";
14
15
  import { useBuilderConnectFlow } from "./settings/useBuilderStatus.js";
@@ -18,13 +19,11 @@ import { IframeEmbed, parseEmbedBody } from "./IframeEmbed.js";
18
19
  import { useDevMode } from "./use-dev-mode.js";
19
20
  import { agentNativePath } from "./api-path.js";
20
21
  import { BUILDER_SPACE_SETTINGS_URL } from "./error-format.js";
22
+ import { ThumbsFeedback } from "./observability/ThumbsFeedback.js";
21
23
  import { TiptapComposer, } from "./composer/TiptapComposer.js";
22
24
  import { isPastedTextAttachmentName } from "./composer/pasted-text.js";
23
25
  import { PastedTextChip } from "./composer/PastedTextChip.js";
24
26
  import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, IconDots, IconGitFork, IconId, IconQuote, IconGauge, IconArrowRight, IconSettings, IconAlertTriangle, IconRefresh, IconPlayerPlay, } from "@tabler/icons-react";
25
- const ThumbsFeedbackLazy = React.lazy(() => import("./observability/ThumbsFeedback.js").then((m) => ({
26
- default: m.ThumbsFeedback,
27
- })));
28
27
  class BinaryDocumentAttachmentAdapter {
29
28
  accept = "application/pdf,.pdf";
30
29
  async add(state) {
@@ -912,13 +911,13 @@ function AssistantMessage() {
912
911
  tools: {
913
912
  Fallback: ToolCallFallback,
914
913
  },
915
- } }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(React.Suspense, { fallback: null, children: _jsx(ThumbsFeedbackLazy, { threadId: cpCtx?.threadId ?? "", runId: (() => {
916
- const meta = messageRuntime.getState().metadata;
917
- return ((typeof meta?.custom?.runId === "string" &&
918
- meta.custom.runId) ||
919
- (typeof meta?.runId === "string" && meta.runId) ||
920
- "");
921
- })(), messageSeq: thread.messages.findIndex((m) => m.id === msg.id) }) }))] }))] }));
914
+ } }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(ThumbsFeedback, { threadId: cpCtx?.threadId ?? "", runId: (() => {
915
+ const meta = messageRuntime.getState().metadata;
916
+ return ((typeof meta?.custom?.runId === "string" &&
917
+ meta.custom.runId) ||
918
+ (typeof meta?.runId === "string" && meta.runId) ||
919
+ "");
920
+ })(), messageSeq: thread.messages.findIndex((m) => m.id === msg.id) }))] }))] }));
922
921
  }
923
922
  function ActivitySteps({ steps }) {
924
923
  if (steps.length === 0)
@@ -1819,6 +1818,17 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1819
1818
  window.addEventListener("agent-chat:activity", handler);
1820
1819
  return () => window.removeEventListener("agent-chat:activity", handler);
1821
1820
  }, [tabId]);
1821
+ useEffect(() => {
1822
+ const handler = (e) => {
1823
+ const detail = e.detail;
1824
+ if (tabId && detail?.tabId && detail.tabId !== tabId)
1825
+ return;
1826
+ setActivityLabel(null);
1827
+ setActivitySteps([]);
1828
+ };
1829
+ window.addEventListener("agent-chat:activity-clear", handler);
1830
+ return () => window.removeEventListener("agent-chat:activity-clear", handler);
1831
+ }, [tabId]);
1822
1832
  useEffect(() => {
1823
1833
  if (!showRunningInUI) {
1824
1834
  setActivityLabel(null);
@@ -2200,7 +2210,7 @@ export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentN
2200
2210
  const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
2201
2211
  new SimpleImageAttachmentAdapter(),
2202
2212
  new BinaryDocumentAttachmentAdapter(),
2203
- new SimpleTextAttachmentAdapter(),
2213
+ new TextAttachmentAdapter(),
2204
2214
  ]), []);
2205
2215
  const runtime = useLocalRuntime(adapter, {
2206
2216
  adapters: { attachments: attachmentAdapter },