@agents24/chat-react 0.5.30 → 0.5.31

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 (45) hide show
  1. package/README.md +9 -4
  2. package/dist/generated/delegation-types.d.ts +129 -0
  3. package/dist/registry/agents24-chat.json +37 -19
  4. package/dist/runtime/index.cjs +52 -0
  5. package/dist/runtime/index.cjs.map +1 -1
  6. package/dist/runtime/index.d.ts +2 -0
  7. package/dist/runtime/index.js +51 -0
  8. package/dist/runtime/index.js.map +1 -1
  9. package/dist/runtime/use-delegation-tasks.d.ts +20 -0
  10. package/dist/scaffold/app.d.ts +2 -1
  11. package/dist/scaffold/components/chat/chat-composer.d.ts +4 -1
  12. package/dist/scaffold/components/chat/subagent-tasks.d.ts +3 -0
  13. package/dist/scaffold/components/theme-provider.d.ts +4 -3
  14. package/dist/scaffold/index.cjs +425 -280
  15. package/dist/scaffold/index.cjs.map +1 -1
  16. package/dist/scaffold/index.d.ts +3 -2
  17. package/dist/scaffold/index.js +416 -271
  18. package/dist/scaffold/index.js.map +1 -1
  19. package/dist/styles.css +14 -0
  20. package/dist/ui/adapters.d.ts +5 -2
  21. package/dist/ui/agent-chat-composer.d.ts +2 -1
  22. package/dist/ui/agent-chat-queue.d.ts +0 -2
  23. package/dist/ui/index.cjs +306 -260
  24. package/dist/ui/index.cjs.map +1 -1
  25. package/dist/ui/index.js +308 -263
  26. package/dist/ui/index.js.map +1 -1
  27. package/dist/ui/tool-sessions.d.ts +10 -2
  28. package/dist/ui/use-agent-chat-composer.d.ts +25 -26
  29. package/dist/ui/use-audio-recorder.d.ts +4 -2
  30. package/package.json +4 -3
  31. package/scaffold/host-styles.css +3 -0
  32. package/scaffold/manifest.json +2 -2
  33. package/scaffold/src/app.tsx +4 -1
  34. package/scaffold/src/chat.css +11 -1
  35. package/scaffold/src/components/chat/chat-composer.tsx +36 -19
  36. package/scaffold/src/components/chat/chat-shell.tsx +5 -4
  37. package/scaffold/src/components/chat/external-link-dialog.tsx +6 -5
  38. package/scaffold/src/components/chat/identity-control.tsx +0 -1
  39. package/scaffold/src/components/chat/subagent-tasks.tsx +109 -0
  40. package/scaffold/src/components/theme-provider.tsx +30 -27
  41. package/scaffold/src/components/ui/tooltip.tsx +3 -0
  42. package/scaffold/src/host.css +11 -0
  43. package/scaffold/src/index.css +1 -213
  44. package/scaffold/src/index.tsx +4 -2
  45. package/scaffold/src/theme.css +215 -0
@@ -15,7 +15,7 @@ import {
15
15
  } from "@agents24/chat-react/runtime";
16
16
  import { AgentChatQueue, queuedMessageComposerFiles, useLiveCompletionRuns } from "@agents24/chat-react/ui";
17
17
  import { CircleAlert, LoaderCircle as LoaderCircle3, SquarePen as SquarePen2, X } from "lucide-react";
18
- import * as React8 from "react";
18
+ import * as React9 from "react";
19
19
 
20
20
  // scaffold/src/components/chat/chat-composer.tsx
21
21
  import { ArrowUp, ChevronDown, LoaderCircle, Mic, Square } from "lucide-react";
@@ -96,6 +96,21 @@ import { CheckIcon, ChevronRightIcon } from "lucide-react";
96
96
  import * as React from "react";
97
97
  import { jsx as jsx2 } from "react/jsx-runtime";
98
98
  var ThemeContext = React.createContext(null);
99
+ var appearanceEvent = "agents24-chat-appearance-change";
100
+ var subscribeAppearance = (notify) => {
101
+ window.addEventListener("storage", notify);
102
+ window.addEventListener(appearanceEvent, notify);
103
+ return () => {
104
+ window.removeEventListener("storage", notify);
105
+ window.removeEventListener(appearanceEvent, notify);
106
+ };
107
+ };
108
+ var subscribeDarkMode = (notify) => {
109
+ const media = window.matchMedia?.("(prefers-color-scheme: dark)");
110
+ media?.addEventListener("change", notify);
111
+ return () => media?.removeEventListener("change", notify);
112
+ };
113
+ var getDarkMode = () => window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
99
114
  var storageKey = "agents24-chat-appearance";
100
115
  function storedAppearance() {
101
116
  try {
@@ -108,44 +123,33 @@ function storedAppearance() {
108
123
  function ThemeProvider({
109
124
  children,
110
125
  controller,
111
- theme = "soft"
126
+ theme = "soft",
127
+ mode = "isolated"
112
128
  }) {
113
- const [internalAppearance, setInternalAppearance] = React.useState("system");
114
- const [resolvedAppearance, setResolvedAppearance] = React.useState("light");
115
- const [mounted, setMounted] = React.useState(false);
129
+ const [sessionAppearance, setSessionAppearance] = React.useState(null);
130
+ const stored = React.useSyncExternalStore(subscribeAppearance, storedAppearance, () => "system");
131
+ const systemDark = React.useSyncExternalStore(subscribeDarkMode, getDarkMode, () => false);
116
132
  const [portalContainer, setPortalContainer] = React.useState(null);
117
- const appearance = controller?.appearance ?? internalAppearance;
118
- React.useEffect(() => {
119
- if (theme !== "inherit" && !controller) setInternalAppearance(storedAppearance());
120
- setMounted(true);
121
- }, [controller, theme]);
122
- React.useEffect(() => {
123
- if (theme === "inherit" || !mounted || typeof window === "undefined" || typeof window.matchMedia !== "function") return;
124
- const media = window.matchMedia("(prefers-color-scheme: dark)");
125
- const apply = () => setResolvedAppearance(
126
- appearance === "system" ? media.matches ? "dark" : "light" : appearance
127
- );
128
- apply();
129
- media.addEventListener("change", apply);
130
- return () => media.removeEventListener("change", apply);
131
- }, [appearance, mounted, theme]);
133
+ const appearance = controller?.appearance ?? sessionAppearance ?? stored;
134
+ const resolvedAppearance = appearance === "system" ? systemDark ? "dark" : "light" : appearance;
132
135
  const change = React.useCallback((next) => {
133
- if (theme === "inherit") return;
134
136
  if (controller) {
135
137
  controller.setAppearance(next);
136
138
  return;
137
139
  }
140
+ setSessionAppearance(next);
138
141
  try {
139
142
  window.localStorage.setItem(storageKey, next);
140
143
  } catch {
141
144
  }
142
- setInternalAppearance(next);
143
- }, [controller, theme]);
144
- return /* @__PURE__ */ jsx2(ThemeContext.Provider, { value: { appearance, inherited: theme === "inherit", portalContainer, setAppearance: change }, children: /* @__PURE__ */ jsx2(
145
+ window.dispatchEvent(new Event(appearanceEvent));
146
+ }, [controller]);
147
+ return /* @__PURE__ */ jsx2(ThemeContext.Provider, { value: { appearance, portalContainer, setAppearance: change, inherited: mode === "inherit" }, children: /* @__PURE__ */ jsx2(
145
148
  "div",
146
149
  {
147
150
  ref: setPortalContainer,
148
- className: theme === "inherit" ? "size-full" : `${resolvedAppearance} size-full`,
151
+ className: mode === "inherit" ? "size-full" : `${resolvedAppearance} size-full`,
152
+ "data-agents24-theme-mode": mode,
149
153
  "data-agents24-theme": theme,
150
154
  "data-agents24-theme-root": "",
151
155
  children
@@ -447,6 +451,7 @@ function TooltipTrigger({
447
451
  asChild: _asChild,
448
452
  ...props
449
453
  }) {
454
+ void _asChild;
450
455
  return /* @__PURE__ */ jsx6(Slot2.Root, { "data-slot": "tooltip-trigger", ...props });
451
456
  }
452
457
  function TooltipContent({
@@ -456,6 +461,8 @@ function TooltipContent({
456
461
  sideOffset: _sideOffset,
457
462
  ...props
458
463
  }) {
464
+ void _align;
465
+ void _sideOffset;
459
466
  return /* @__PURE__ */ jsx6(
460
467
  "span",
461
468
  {
@@ -479,6 +486,8 @@ function TooltipContent({
479
486
  import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
480
487
  function ChatComposer({
481
488
  inputContract,
489
+ queue,
490
+ onRecordingStreamChange,
482
491
  disabled,
483
492
  contextWindow,
484
493
  focusKey,
@@ -497,30 +506,34 @@ function ChatComposer({
497
506
  utilityRow = "inline"
498
507
  }) {
499
508
  const inputRef = React2.useRef(null);
500
- const textareaRef = React2.useRef(null);
501
- const composer = useAgentChatComposer({
502
- inputContract,
503
- disabled,
504
- isRunning,
505
- isCancelling,
506
- focusKey,
507
- restoredDraft,
508
- textareaRef,
509
- onSubmit: ({ text: text2, files: files2 }) => onSubmit(text2, files2)
510
- });
511
509
  const {
512
510
  text,
513
- files,
514
511
  setText,
515
- validationError,
512
+ files,
513
+ removeFile,
514
+ addFiles,
515
+ textareaRef,
516
+ submit,
516
517
  attachmentError,
517
- recorder,
518
- recordingAllowed,
518
+ attachmentMimeTypes,
519
519
  allowAttachments,
520
+ recordingAllowed,
521
+ recorder,
522
+ isExpanded,
523
+ validationError,
520
524
  action,
521
- submit
522
- } = composer;
523
- const isExpanded = forceExpanded || text.includes("\n") || text.length > 62;
525
+ canSubmit
526
+ } = useAgentChatComposer({
527
+ inputContract,
528
+ disabled,
529
+ focusKey,
530
+ forceExpanded,
531
+ isCancelling,
532
+ isRunning,
533
+ onSubmit,
534
+ restoredDraft,
535
+ onRecordingStreamChange
536
+ });
524
537
  const selectedAgent = agents.find((item) => item.id === agentId);
525
538
  const selectedModel = models.find((item) => item.id === modelId);
526
539
  const modelSelector = models.length > 0 ? /* @__PURE__ */ jsx7("div", { className: "w-fit max-w-40", children: /* @__PURE__ */ jsxs3(Select, { disabled: disabled || isRunning, onValueChange: onModelChange, value: modelId || void 0, children: [
@@ -566,25 +579,29 @@ function ChatComposer({
566
579
  className: "relative z-10 w-full pb-[max(1rem,env(safe-area-inset-bottom))]",
567
580
  "data-agents24-chat-composer": "",
568
581
  children: [
569
- allowAttachments && files.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mb-2 min-w-0", children: /* @__PURE__ */ jsx7(
570
- ChatAttachmentRows,
571
- {
572
- attachments: files,
573
- onRemove: (attachment) => {
574
- if (attachment.id) composer.removeFile(attachment.id);
575
- }
576
- }
577
- ) }),
582
+ queue,
578
583
  attachmentError || recorder.error ? /* @__PURE__ */ jsx7("p", { className: "mb-2 text-xs text-destructive", role: "alert", children: attachmentError || recorder.error }) : null,
579
584
  /* @__PURE__ */ jsxs3(
580
585
  "div",
581
586
  {
582
587
  "data-expanded": isExpanded || void 0,
588
+ "data-attachments": files.length > 0 || void 0,
583
589
  className: cn(
584
590
  "agents24-composer-grid grid min-w-0 items-center gap-2 rounded-xl border bg-background shadow-sm",
585
591
  isExpanded ? "p-2" : "p-1.5"
586
592
  ),
587
593
  children: [
594
+ allowAttachments && files.length > 0 && /* @__PURE__ */ jsx7("div", { className: "agents24-composer-attachments min-w-0", children: /* @__PURE__ */ jsx7(
595
+ ChatAttachmentRows,
596
+ {
597
+ layout: "composer",
598
+ attachments: files,
599
+ onRemove: (attachment) => {
600
+ if (!attachment.id) return;
601
+ removeFile(attachment.id);
602
+ }
603
+ }
604
+ ) }),
588
605
  allowAttachments ? /* @__PURE__ */ jsxs3(Fragment, { children: [
589
606
  /* @__PURE__ */ jsx7(
590
607
  "input",
@@ -593,9 +610,9 @@ function ChatComposer({
593
610
  className: "sr-only",
594
611
  type: "file",
595
612
  multiple: true,
596
- accept: composer.fileAccept,
613
+ accept: attachmentMimeTypes.join(","),
597
614
  onChange: (event) => {
598
- composer.addFiles(Array.from(event.target.files ?? []));
615
+ addFiles(Array.from(event.target.files ?? []));
599
616
  event.currentTarget.value = "";
600
617
  }
601
618
  }
@@ -615,8 +632,15 @@ function ChatComposer({
615
632
  "agents24-composer-textarea max-h-56 min-h-9 field-sizing-content resize-none overflow-y-auto border-0 bg-transparent px-2 shadow-none focus-visible:ring-0 dark:bg-transparent",
616
633
  isExpanded ? "py-2" : "h-9 py-2"
617
634
  ),
618
- onChange: (event) => setText(event.target.value),
619
- onKeyDown: composer.onKeyDown
635
+ onChange: (event) => {
636
+ setText(event.target.value);
637
+ },
638
+ onKeyDown: (event) => {
639
+ if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
640
+ event.preventDefault();
641
+ void submit();
642
+ }
643
+ }
620
644
  }
621
645
  ),
622
646
  /* @__PURE__ */ jsxs3("div", { className: "agents24-composer-actions flex items-center gap-1", children: [
@@ -648,7 +672,7 @@ function ChatComposer({
648
672
  ) : validationError ? /* @__PURE__ */ jsxs3(Tooltip, { children: [
649
673
  /* @__PURE__ */ jsx7(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx7("span", { tabIndex: 0, "aria-label": validationError, children: /* @__PURE__ */ jsx7(Button, { size: "icon", "aria-label": isRunning ? "Queue message" : "Send message", disabled: true, onClick: () => void submit(), children: /* @__PURE__ */ jsx7(ArrowUp, {}) }) }) }),
650
674
  /* @__PURE__ */ jsx7(TooltipContent, { children: validationError })
651
- ] }) : /* @__PURE__ */ jsx7(Button, { size: "icon", "aria-label": isRunning ? "Queue message" : "Send message", disabled: disabled || !composer.canSubmit, onClick: () => void submit(), children: /* @__PURE__ */ jsx7(ArrowUp, {}) })
675
+ ] }) : /* @__PURE__ */ jsx7(Button, { size: "icon", "aria-label": isRunning ? "Queue message" : "Send message", disabled: !canSubmit, onClick: () => void submit(), children: /* @__PURE__ */ jsx7(ArrowUp, {}) })
652
676
  ] })
653
677
  ]
654
678
  }
@@ -860,19 +884,20 @@ function DialogDescription({
860
884
  import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
861
885
  function ExternalLinkDialog({ isOpen, onClose, onConfirm, url }) {
862
886
  const [copied, setCopied] = React4.useState(false);
863
- React4.useEffect(() => {
864
- if (!isOpen) setCopied(false);
865
- }, [isOpen]);
887
+ const close = () => {
888
+ setCopied(false);
889
+ onClose();
890
+ };
866
891
  const copyUrl = async () => {
867
892
  await navigator.clipboard.writeText(url);
868
893
  setCopied(true);
869
894
  };
870
895
  const openUrl = () => {
871
896
  onConfirm();
872
- onClose();
897
+ close();
873
898
  };
874
899
  return /* @__PURE__ */ jsx10(Dialog, { open: isOpen, onOpenChange: (open) => {
875
- if (!open) onClose();
900
+ if (!open) close();
876
901
  }, children: /* @__PURE__ */ jsxs6(DialogContent, { className: "max-h-[calc(100dvh-2rem)] min-w-0 overflow-hidden sm:max-w-md", children: [
877
902
  /* @__PURE__ */ jsxs6(DialogHeader, { children: [
878
903
  /* @__PURE__ */ jsx10(DialogTitle, { children: "Open external link?" }),
@@ -1134,10 +1159,134 @@ function ChatMessage({
1134
1159
  ] }) });
1135
1160
  }
1136
1161
 
1137
- // scaffold/src/components/chat/theme-menu.tsx
1138
- import { Laptop, Moon, Sun } from "lucide-react";
1162
+ // scaffold/src/components/chat/subagent-tasks.tsx
1139
1163
  import * as React5 from "react";
1164
+ import { useAgentClient, partsFromResponseBlocks } from "@agents24/react";
1165
+ import { AgentResponseTimeline as AgentResponseTimeline2 } from "@agents24/chat-react/ui";
1166
+ import { useDelegationTasks } from "@agents24/chat-react/runtime";
1140
1167
  import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1168
+ function SubagentTasks({ threadId }) {
1169
+ const client = useAgentClient();
1170
+ const source = React5.useMemo(() => ({ events: (input) => client.threads.delegations.events(input) }), [client]);
1171
+ const { tasks, error, refresh } = useDelegationTasks({ threadId, source });
1172
+ const [selection, setSelection] = React5.useState({ threadId: null, handle: null });
1173
+ const selected = selection.threadId === threadId ? selection.handle : null;
1174
+ if (!threadId || !tasks.length && !error) return null;
1175
+ return /* @__PURE__ */ jsx15("section", { "aria-label": "Subagent tasks", className: "mx-auto w-full max-w-3xl px-4 py-2 text-sm", children: /* @__PURE__ */ jsxs9("details", { children: [
1176
+ /* @__PURE__ */ jsxs9("summary", { className: "cursor-pointer font-medium", children: [
1177
+ "Tasks (",
1178
+ tasks.length,
1179
+ ")"
1180
+ ] }),
1181
+ error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: "Task updates are unavailable. Retrying\u2026" }) : null,
1182
+ /* @__PURE__ */ jsx15("ul", { className: "max-h-56 overflow-y-auto", children: tasks.map((task) => /* @__PURE__ */ jsx15("li", { style: { paddingInlineStart: Math.max(0, task.depth - 1) * 12 }, children: /* @__PURE__ */ jsxs9(
1183
+ "button",
1184
+ {
1185
+ type: "button",
1186
+ className: "flex w-full items-center justify-between gap-3 rounded-md px-2 py-2 text-start hover:bg-muted",
1187
+ onClick: () => setSelection({ threadId, handle: selected === task.handle ? null : task.handle }),
1188
+ "aria-expanded": selected === task.handle,
1189
+ children: [
1190
+ /* @__PURE__ */ jsxs9("span", { className: "min-w-0 truncate", children: [
1191
+ task.name,
1192
+ task.background ? " \xB7 Background" : ""
1193
+ ] }),
1194
+ /* @__PURE__ */ jsx15("span", { className: "shrink-0 text-xs text-muted-foreground", children: task.status.replaceAll("_", " ") })
1195
+ ]
1196
+ }
1197
+ ) }, task.handle)) }),
1198
+ tasks.filter((task) => task.handle === selected).map((task) => /* @__PURE__ */ jsx15(TaskConversation, { threadId, task, onChanged: refresh }, `${threadId}:${task.handle}`))
1199
+ ] }) });
1200
+ }
1201
+ function TaskConversation({ threadId, task, onChanged }) {
1202
+ const client = useAgentClient();
1203
+ const [history, setHistory] = React5.useState(null);
1204
+ const [earlier, setEarlier] = React5.useState([]);
1205
+ const historyInitialized = React5.useRef(false);
1206
+ const [before, setBefore] = React5.useState(null);
1207
+ const [error, setError] = React5.useState(null);
1208
+ const [busy, setBusy] = React5.useState(false);
1209
+ const operation = React5.useRef(null);
1210
+ React5.useEffect(() => {
1211
+ const controller = new AbortController();
1212
+ let timer;
1213
+ const refresh = async () => {
1214
+ try {
1215
+ const page = await client.threads.delegations.history({ threadId, handle: task.handle, signal: controller.signal });
1216
+ if (controller.signal.aborted) return;
1217
+ setHistory(page);
1218
+ if (!historyInitialized.current) {
1219
+ historyInitialized.current = true;
1220
+ setBefore(page.paging.next_before_turn_index);
1221
+ }
1222
+ } catch {
1223
+ if (!controller.signal.aborted) setError("Task history could not be loaded.");
1224
+ } finally {
1225
+ if (!controller.signal.aborted) timer = setTimeout(refresh, 2e3);
1226
+ }
1227
+ };
1228
+ void refresh();
1229
+ return () => {
1230
+ controller.abort();
1231
+ clearTimeout(timer);
1232
+ };
1233
+ }, [client, threadId, task.handle]);
1234
+ const loadEarlier = async () => {
1235
+ if (before === null) return;
1236
+ setBusy(true);
1237
+ try {
1238
+ const page = await client.threads.delegations.history({ threadId, handle: task.handle, before });
1239
+ setEarlier((current) => [...page.turns, ...current]);
1240
+ setBefore(page.paging.next_before_turn_index);
1241
+ } catch {
1242
+ setError("Earlier task history could not be loaded.");
1243
+ } finally {
1244
+ setBusy(false);
1245
+ }
1246
+ };
1247
+ const act = async (action) => {
1248
+ setBusy(true);
1249
+ setError(null);
1250
+ if (operation.current?.action !== action) operation.current = { action, id: crypto.randomUUID() };
1251
+ try {
1252
+ await client.threads.delegations.act({
1253
+ threadId,
1254
+ handle: task.handle,
1255
+ action: { action, operation_id: operation.current.id }
1256
+ });
1257
+ operation.current = null;
1258
+ onChanged();
1259
+ } catch {
1260
+ setError("The task action could not be completed. Try again.");
1261
+ } finally {
1262
+ setBusy(false);
1263
+ }
1264
+ };
1265
+ const turns = Array.from(new Map([...earlier, ...history?.turns || []].map((turn) => [turn.id, turn])).values()).sort((a, b) => a.turn_index - b.turn_index);
1266
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-3 rounded-md bg-muted/30 p-3", children: [
1267
+ /* @__PURE__ */ jsx15("h3", { className: "font-medium", children: task.name }),
1268
+ error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: error }) : null,
1269
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap gap-2", children: [
1270
+ task.capabilities.interrupt ? /* @__PURE__ */ jsx15(Button, { variant: "secondary", size: "sm", disabled: busy, onClick: () => void act("interrupt"), children: "Interrupt" }) : null,
1271
+ task.capabilities.cancel ? /* @__PURE__ */ jsx15(Button, { variant: "secondary", size: "sm", disabled: busy, onClick: () => void act("cancel"), children: "Cancel task" }) : null,
1272
+ before !== null ? /* @__PURE__ */ jsx15(Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => void loadEarlier(), children: "Earlier exchanges" }) : null
1273
+ ] }),
1274
+ /* @__PURE__ */ jsx15("div", { className: "max-h-[55dvh] space-y-4 overflow-y-auto break-words", children: turns.map((turn) => /* @__PURE__ */ jsxs9("article", { className: "space-y-2", children: [
1275
+ turn.assignment_instruction ? /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap text-muted-foreground", children: turn.assignment_instruction }) : null,
1276
+ turn.user_input_text ? /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: turn.user_input_text }) : null,
1277
+ turn.exchanges?.map((exchange) => /* @__PURE__ */ jsxs9("div", { className: "whitespace-pre-wrap break-words text-sm", children: [
1278
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-medium", children: exchange.sender === "parent" ? "Parent Agent" : "Subagent update" }),
1279
+ exchange.text
1280
+ ] }, exchange.id)),
1281
+ /* @__PURE__ */ jsx15(AgentResponseTimeline2, { message: { id: turn.id, role: "assistant", createdAt: turn.created_at, content: turn.assistant_output_text || "", parts: partsFromResponseBlocks(turn.response_blocks) } })
1282
+ ] }, turn.id)) })
1283
+ ] });
1284
+ }
1285
+
1286
+ // scaffold/src/components/chat/theme-menu.tsx
1287
+ import { Laptop, Moon, Sun } from "lucide-react";
1288
+ import * as React6 from "react";
1289
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1141
1290
  var options = [
1142
1291
  { value: "system", label: "System", icon: Laptop },
1143
1292
  { value: "light", label: "Light", icon: Sun },
@@ -1145,12 +1294,12 @@ var options = [
1145
1294
  ];
1146
1295
  function ThemeMenu() {
1147
1296
  const { appearance, setAppearance, inherited } = useTheme();
1148
- const [open, setOpen] = React5.useState(false);
1149
- const rootRef = React5.useRef(null);
1150
- const firstItemRef = React5.useRef(null);
1151
- const menuId = React5.useId();
1297
+ const [open, setOpen] = React6.useState(false);
1298
+ const rootRef = React6.useRef(null);
1299
+ const firstItemRef = React6.useRef(null);
1300
+ const menuId = React6.useId();
1152
1301
  const ActiveIcon = options.find((item) => item.value === appearance)?.icon ?? Laptop;
1153
- React5.useEffect(() => {
1302
+ React6.useEffect(() => {
1154
1303
  if (!open) return;
1155
1304
  firstItemRef.current?.focus();
1156
1305
  const closeOnOutsidePointer = (event) => {
@@ -1168,8 +1317,8 @@ function ThemeMenu() {
1168
1317
  }, [open]);
1169
1318
  if (inherited) return null;
1170
1319
  const label = appearance === "system" ? "System" : appearance === "light" ? "Light" : "Dark";
1171
- return /* @__PURE__ */ jsxs9("div", { ref: rootRef, className: "relative", children: [
1172
- /* @__PURE__ */ jsx15(
1320
+ return /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative", children: [
1321
+ /* @__PURE__ */ jsx16(
1173
1322
  Button,
1174
1323
  {
1175
1324
  "aria-controls": menuId,
@@ -1179,16 +1328,16 @@ function ThemeMenu() {
1179
1328
  onClick: () => setOpen((value) => !value),
1180
1329
  size: "icon-sm",
1181
1330
  variant: "ghost",
1182
- children: /* @__PURE__ */ jsx15(ActiveIcon, {})
1331
+ children: /* @__PURE__ */ jsx16(ActiveIcon, {})
1183
1332
  }
1184
1333
  ),
1185
- open ? /* @__PURE__ */ jsx15(
1334
+ open ? /* @__PURE__ */ jsx16(
1186
1335
  "div",
1187
1336
  {
1188
1337
  id: menuId,
1189
1338
  className: "absolute end-0 top-full z-50 mt-1 flex min-w-44 flex-col rounded-xl border bg-popover p-1 text-popover-foreground shadow-md",
1190
1339
  role: "menu",
1191
- children: options.map(({ value, label: optionLabel, icon: Icon }, index) => /* @__PURE__ */ jsxs9(
1340
+ children: options.map(({ value, label: optionLabel, icon: Icon }, index) => /* @__PURE__ */ jsxs10(
1192
1341
  Button,
1193
1342
  {
1194
1343
  ref: index === 0 ? firstItemRef : void 0,
@@ -1202,7 +1351,7 @@ function ThemeMenu() {
1202
1351
  size: "sm",
1203
1352
  variant: "ghost",
1204
1353
  children: [
1205
- /* @__PURE__ */ jsx15(Icon, {}),
1354
+ /* @__PURE__ */ jsx16(Icon, {}),
1206
1355
  " ",
1207
1356
  optionLabel
1208
1357
  ]
@@ -1222,16 +1371,16 @@ import { LoaderCircle as LoaderCircle2, SquarePen, Trash2 } from "lucide-react";
1222
1371
  import { LogIn, LogOut, UserRound } from "lucide-react";
1223
1372
 
1224
1373
  // scaffold/src/components/ui/sidebar.tsx
1225
- import * as React7 from "react";
1374
+ import * as React8 from "react";
1226
1375
  import { cva as cva3 } from "class-variance-authority";
1227
1376
  import { Slot as Slot4 } from "radix-ui";
1228
1377
 
1229
1378
  // scaffold/src/hooks/use-mobile.ts
1230
- import * as React6 from "react";
1379
+ import * as React7 from "react";
1231
1380
  var MOBILE_BREAKPOINT = 768;
1232
1381
  function useIsMobile() {
1233
- const [isMobile, setIsMobile] = React6.useState(void 0);
1234
- React6.useEffect(() => {
1382
+ const [isMobile, setIsMobile] = React7.useState(void 0);
1383
+ React7.useEffect(() => {
1235
1384
  const onChange = () => {
1236
1385
  setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1237
1386
  };
@@ -1249,31 +1398,31 @@ function useIsMobile() {
1249
1398
  }
1250
1399
 
1251
1400
  // scaffold/src/components/ui/input.tsx
1252
- import { jsx as jsx16 } from "react/jsx-runtime";
1401
+ import { jsx as jsx17 } from "react/jsx-runtime";
1253
1402
 
1254
1403
  // scaffold/src/components/ui/separator.tsx
1255
1404
  import { Separator as SeparatorPrimitive } from "radix-ui";
1256
- import { jsx as jsx17 } from "react/jsx-runtime";
1405
+ import { jsx as jsx18 } from "react/jsx-runtime";
1257
1406
 
1258
1407
  // scaffold/src/components/ui/sheet.tsx
1259
1408
  import { Dialog as SheetPrimitive } from "radix-ui";
1260
1409
  import { XIcon as XIcon2 } from "lucide-react";
1261
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
1410
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
1262
1411
  function Sheet({ ...props }) {
1263
- return /* @__PURE__ */ jsx18(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
1412
+ return /* @__PURE__ */ jsx19(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
1264
1413
  }
1265
1414
  function SheetPortal({
1266
1415
  container,
1267
1416
  ...props
1268
1417
  }) {
1269
1418
  const themeContainer = useThemePortalContainer();
1270
- return /* @__PURE__ */ jsx18(SheetPrimitive.Portal, { container: container || themeContainer || void 0, "data-slot": "sheet-portal", ...props });
1419
+ return /* @__PURE__ */ jsx19(SheetPrimitive.Portal, { container: container || themeContainer || void 0, "data-slot": "sheet-portal", ...props });
1271
1420
  }
1272
1421
  function SheetOverlay({
1273
1422
  className,
1274
1423
  ...props
1275
1424
  }) {
1276
- return /* @__PURE__ */ jsx18(
1425
+ return /* @__PURE__ */ jsx19(
1277
1426
  SheetPrimitive.Overlay,
1278
1427
  {
1279
1428
  "data-slot": "sheet-overlay",
@@ -1292,9 +1441,9 @@ function SheetContent({
1292
1441
  showCloseButton = true,
1293
1442
  ...props
1294
1443
  }) {
1295
- return /* @__PURE__ */ jsxs10(SheetPortal, { children: [
1296
- /* @__PURE__ */ jsx18(SheetOverlay, {}),
1297
- /* @__PURE__ */ jsxs10(
1444
+ return /* @__PURE__ */ jsxs11(SheetPortal, { children: [
1445
+ /* @__PURE__ */ jsx19(SheetOverlay, {}),
1446
+ /* @__PURE__ */ jsxs11(
1298
1447
  SheetPrimitive.Content,
1299
1448
  {
1300
1449
  "data-slot": "sheet-content",
@@ -1306,18 +1455,18 @@ function SheetContent({
1306
1455
  ...props,
1307
1456
  children: [
1308
1457
  children,
1309
- showCloseButton && /* @__PURE__ */ jsx18(SheetPrimitive.Close, { "data-slot": "sheet-close", asChild: true, children: /* @__PURE__ */ jsxs10(
1458
+ showCloseButton && /* @__PURE__ */ jsx19(SheetPrimitive.Close, { "data-slot": "sheet-close", asChild: true, children: /* @__PURE__ */ jsxs11(
1310
1459
  Button,
1311
1460
  {
1312
1461
  variant: "ghost",
1313
1462
  className: "absolute top-4 right-4 bg-secondary",
1314
1463
  size: "icon-sm",
1315
1464
  children: [
1316
- /* @__PURE__ */ jsx18(
1465
+ /* @__PURE__ */ jsx19(
1317
1466
  XIcon2,
1318
1467
  {}
1319
1468
  ),
1320
- /* @__PURE__ */ jsx18("span", { className: "sr-only", children: "Close" })
1469
+ /* @__PURE__ */ jsx19("span", { className: "sr-only", children: "Close" })
1321
1470
  ]
1322
1471
  }
1323
1472
  ) })
@@ -1327,7 +1476,7 @@ function SheetContent({
1327
1476
  ] });
1328
1477
  }
1329
1478
  function SheetHeader({ className, ...props }) {
1330
- return /* @__PURE__ */ jsx18(
1479
+ return /* @__PURE__ */ jsx19(
1331
1480
  "div",
1332
1481
  {
1333
1482
  "data-slot": "sheet-header",
@@ -1340,7 +1489,7 @@ function SheetTitle({
1340
1489
  className,
1341
1490
  ...props
1342
1491
  }) {
1343
- return /* @__PURE__ */ jsx18(
1492
+ return /* @__PURE__ */ jsx19(
1344
1493
  SheetPrimitive.Title,
1345
1494
  {
1346
1495
  "data-slot": "sheet-title",
@@ -1356,7 +1505,7 @@ function SheetDescription({
1356
1505
  className,
1357
1506
  ...props
1358
1507
  }) {
1359
- return /* @__PURE__ */ jsx18(
1508
+ return /* @__PURE__ */ jsx19(
1360
1509
  SheetPrimitive.Description,
1361
1510
  {
1362
1511
  "data-slot": "sheet-description",
@@ -1367,17 +1516,17 @@ function SheetDescription({
1367
1516
  }
1368
1517
 
1369
1518
  // scaffold/src/components/ui/skeleton.tsx
1370
- import { jsx as jsx19 } from "react/jsx-runtime";
1519
+ import { jsx as jsx20 } from "react/jsx-runtime";
1371
1520
 
1372
1521
  // scaffold/src/components/ui/sidebar.tsx
1373
1522
  import { PanelLeftIcon } from "lucide-react";
1374
- import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
1523
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
1375
1524
  var SIDEBAR_COOKIE_NAME = "sidebar_state";
1376
1525
  var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
1377
1526
  var SIDEBAR_KEYBOARD_SHORTCUT = "b";
1378
- var SidebarContext = React7.createContext(null);
1527
+ var SidebarContext = React8.createContext(null);
1379
1528
  function useSidebar() {
1380
- const context = React7.useContext(SidebarContext);
1529
+ const context = React8.useContext(SidebarContext);
1381
1530
  if (!context) {
1382
1531
  throw new Error("useSidebar must be used within a SidebarProvider.");
1383
1532
  }
@@ -1392,10 +1541,10 @@ function SidebarProvider({
1392
1541
  ...props
1393
1542
  }) {
1394
1543
  const isMobile = useIsMobile();
1395
- const [openMobile, setOpenMobile] = React7.useState(false);
1396
- const [_open, _setOpen] = React7.useState(defaultOpen);
1544
+ const [openMobile, setOpenMobile] = React8.useState(false);
1545
+ const [_open, _setOpen] = React8.useState(defaultOpen);
1397
1546
  const open = openProp ?? _open;
1398
- const setOpen = React7.useCallback(
1547
+ const setOpen = React8.useCallback(
1399
1548
  (value) => {
1400
1549
  const openState = typeof value === "function" ? value(open) : value;
1401
1550
  if (setOpenProp) {
@@ -1407,10 +1556,10 @@ function SidebarProvider({
1407
1556
  },
1408
1557
  [setOpenProp, open]
1409
1558
  );
1410
- const toggleSidebar = React7.useCallback(() => {
1559
+ const toggleSidebar = React8.useCallback(() => {
1411
1560
  return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
1412
1561
  }, [isMobile, setOpen, setOpenMobile]);
1413
- React7.useEffect(() => {
1562
+ React8.useEffect(() => {
1414
1563
  const handleKeyDown = (event) => {
1415
1564
  if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
1416
1565
  event.preventDefault();
@@ -1421,7 +1570,7 @@ function SidebarProvider({
1421
1570
  return () => window.removeEventListener("keydown", handleKeyDown);
1422
1571
  }, [toggleSidebar]);
1423
1572
  const state = open ? "expanded" : "collapsed";
1424
- const contextValue = React7.useMemo(
1573
+ const contextValue = React8.useMemo(
1425
1574
  () => ({
1426
1575
  state,
1427
1576
  open,
@@ -1433,7 +1582,7 @@ function SidebarProvider({
1433
1582
  }),
1434
1583
  [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
1435
1584
  );
1436
- return /* @__PURE__ */ jsx20(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(
1585
+ return /* @__PURE__ */ jsx21(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx21(
1437
1586
  "div",
1438
1587
  {
1439
1588
  "data-slot": "sidebar-wrapper",
@@ -1457,7 +1606,7 @@ function Sidebar({
1457
1606
  }) {
1458
1607
  const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
1459
1608
  if (collapsible === "none") {
1460
- return /* @__PURE__ */ jsx20(
1609
+ return /* @__PURE__ */ jsx21(
1461
1610
  "div",
1462
1611
  {
1463
1612
  "data-slot": "sidebar",
@@ -1471,7 +1620,7 @@ function Sidebar({
1471
1620
  );
1472
1621
  }
1473
1622
  if (isMobile) {
1474
- return /* @__PURE__ */ jsx20(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ jsxs11(
1623
+ return /* @__PURE__ */ jsx21(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ jsxs12(
1475
1624
  SheetContent,
1476
1625
  {
1477
1626
  dir,
@@ -1481,16 +1630,16 @@ function Sidebar({
1481
1630
  className: "w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [--sidebar-width:18rem] [&>button]:hidden",
1482
1631
  side,
1483
1632
  children: [
1484
- /* @__PURE__ */ jsxs11(SheetHeader, { className: "sr-only", children: [
1485
- /* @__PURE__ */ jsx20(SheetTitle, { children: "Sidebar" }),
1486
- /* @__PURE__ */ jsx20(SheetDescription, { children: "Displays the mobile sidebar." })
1633
+ /* @__PURE__ */ jsxs12(SheetHeader, { className: "sr-only", children: [
1634
+ /* @__PURE__ */ jsx21(SheetTitle, { children: "Sidebar" }),
1635
+ /* @__PURE__ */ jsx21(SheetDescription, { children: "Displays the mobile sidebar." })
1487
1636
  ] }),
1488
- /* @__PURE__ */ jsx20("div", { className: "flex h-full w-full flex-col", children })
1637
+ /* @__PURE__ */ jsx21("div", { className: "flex h-full w-full flex-col", children })
1489
1638
  ]
1490
1639
  }
1491
1640
  ) });
1492
1641
  }
1493
- return /* @__PURE__ */ jsxs11(
1642
+ return /* @__PURE__ */ jsxs12(
1494
1643
  "div",
1495
1644
  {
1496
1645
  className: "group peer hidden text-sidebar-foreground md:block",
@@ -1500,7 +1649,7 @@ function Sidebar({
1500
1649
  "data-side": side,
1501
1650
  "data-slot": "sidebar",
1502
1651
  children: [
1503
- /* @__PURE__ */ jsx20(
1652
+ /* @__PURE__ */ jsx21(
1504
1653
  "div",
1505
1654
  {
1506
1655
  "data-slot": "sidebar-gap",
@@ -1512,7 +1661,7 @@ function Sidebar({
1512
1661
  )
1513
1662
  }
1514
1663
  ),
1515
- /* @__PURE__ */ jsx20(
1664
+ /* @__PURE__ */ jsx21(
1516
1665
  "div",
1517
1666
  {
1518
1667
  "data-slot": "sidebar-container",
@@ -1524,7 +1673,7 @@ function Sidebar({
1524
1673
  className
1525
1674
  ),
1526
1675
  ...props,
1527
- children: /* @__PURE__ */ jsx20(
1676
+ children: /* @__PURE__ */ jsx21(
1528
1677
  "div",
1529
1678
  {
1530
1679
  "data-sidebar": "sidebar",
@@ -1545,7 +1694,7 @@ function SidebarTrigger({
1545
1694
  ...props
1546
1695
  }) {
1547
1696
  const { toggleSidebar } = useSidebar();
1548
- return /* @__PURE__ */ jsxs11(
1697
+ return /* @__PURE__ */ jsxs12(
1549
1698
  Button,
1550
1699
  {
1551
1700
  "data-sidebar": "trigger",
@@ -1559,15 +1708,15 @@ function SidebarTrigger({
1559
1708
  },
1560
1709
  ...props,
1561
1710
  children: [
1562
- /* @__PURE__ */ jsx20(PanelLeftIcon, {}),
1563
- /* @__PURE__ */ jsx20("span", { className: "sr-only", children: "Toggle Sidebar" })
1711
+ /* @__PURE__ */ jsx21(PanelLeftIcon, {}),
1712
+ /* @__PURE__ */ jsx21("span", { className: "sr-only", children: "Toggle Sidebar" })
1564
1713
  ]
1565
1714
  }
1566
1715
  );
1567
1716
  }
1568
1717
  function SidebarRail({ className, ...props }) {
1569
1718
  const { toggleSidebar } = useSidebar();
1570
- return /* @__PURE__ */ jsx20(
1719
+ return /* @__PURE__ */ jsx21(
1571
1720
  "button",
1572
1721
  {
1573
1722
  "data-sidebar": "rail",
@@ -1590,7 +1739,7 @@ function SidebarRail({ className, ...props }) {
1590
1739
  );
1591
1740
  }
1592
1741
  function SidebarInset({ className, ...props }) {
1593
- return /* @__PURE__ */ jsx20(
1742
+ return /* @__PURE__ */ jsx21(
1594
1743
  "main",
1595
1744
  {
1596
1745
  "data-slot": "sidebar-inset",
@@ -1603,7 +1752,7 @@ function SidebarInset({ className, ...props }) {
1603
1752
  );
1604
1753
  }
1605
1754
  function SidebarHeader({ className, ...props }) {
1606
- return /* @__PURE__ */ jsx20(
1755
+ return /* @__PURE__ */ jsx21(
1607
1756
  "div",
1608
1757
  {
1609
1758
  "data-slot": "sidebar-header",
@@ -1617,7 +1766,7 @@ function SidebarHeader({ className, ...props }) {
1617
1766
  );
1618
1767
  }
1619
1768
  function SidebarFooter({ className, ...props }) {
1620
- return /* @__PURE__ */ jsx20(
1769
+ return /* @__PURE__ */ jsx21(
1621
1770
  "div",
1622
1771
  {
1623
1772
  "data-slot": "sidebar-footer",
@@ -1628,7 +1777,7 @@ function SidebarFooter({ className, ...props }) {
1628
1777
  );
1629
1778
  }
1630
1779
  function SidebarContent({ className, ...props }) {
1631
- return /* @__PURE__ */ jsx20(
1780
+ return /* @__PURE__ */ jsx21(
1632
1781
  "div",
1633
1782
  {
1634
1783
  "data-slot": "sidebar-content",
@@ -1642,7 +1791,7 @@ function SidebarContent({ className, ...props }) {
1642
1791
  );
1643
1792
  }
1644
1793
  function SidebarGroup({ className, ...props }) {
1645
- return /* @__PURE__ */ jsx20(
1794
+ return /* @__PURE__ */ jsx21(
1646
1795
  "div",
1647
1796
  {
1648
1797
  "data-slot": "sidebar-group",
@@ -1656,7 +1805,7 @@ function SidebarGroupContent({
1656
1805
  className,
1657
1806
  ...props
1658
1807
  }) {
1659
- return /* @__PURE__ */ jsx20(
1808
+ return /* @__PURE__ */ jsx21(
1660
1809
  "div",
1661
1810
  {
1662
1811
  "data-slot": "sidebar-group-content",
@@ -1667,7 +1816,7 @@ function SidebarGroupContent({
1667
1816
  );
1668
1817
  }
1669
1818
  function SidebarMenu({ className, ...props }) {
1670
- return /* @__PURE__ */ jsx20(
1819
+ return /* @__PURE__ */ jsx21(
1671
1820
  "ul",
1672
1821
  {
1673
1822
  "data-slot": "sidebar-menu",
@@ -1678,7 +1827,7 @@ function SidebarMenu({ className, ...props }) {
1678
1827
  );
1679
1828
  }
1680
1829
  function SidebarMenuItem({ className, ...props }) {
1681
- return /* @__PURE__ */ jsx20(
1830
+ return /* @__PURE__ */ jsx21(
1682
1831
  "li",
1683
1832
  {
1684
1833
  "data-slot": "sidebar-menu-item",
@@ -1719,7 +1868,7 @@ function SidebarMenuButton({
1719
1868
  }) {
1720
1869
  const Comp = asChild ? Slot4.Root : "button";
1721
1870
  const { isMobile, state } = useSidebar();
1722
- const button = /* @__PURE__ */ jsx20(
1871
+ const button = /* @__PURE__ */ jsx21(
1723
1872
  Comp,
1724
1873
  {
1725
1874
  "data-slot": "sidebar-menu-button",
@@ -1738,9 +1887,9 @@ function SidebarMenuButton({
1738
1887
  children: tooltip
1739
1888
  };
1740
1889
  }
1741
- return /* @__PURE__ */ jsxs11(Tooltip, { children: [
1742
- /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: button }),
1743
- /* @__PURE__ */ jsx20(
1890
+ return /* @__PURE__ */ jsxs12(Tooltip, { children: [
1891
+ /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: button }),
1892
+ /* @__PURE__ */ jsx21(
1744
1893
  TooltipContent,
1745
1894
  {
1746
1895
  side: "right",
@@ -1758,7 +1907,7 @@ function SidebarMenuAction({
1758
1907
  ...props
1759
1908
  }) {
1760
1909
  const Comp = asChild ? Slot4.Root : "button";
1761
- return /* @__PURE__ */ jsx20(
1910
+ return /* @__PURE__ */ jsx21(
1762
1911
  Comp,
1763
1912
  {
1764
1913
  "data-slot": "sidebar-menu-action",
@@ -1774,7 +1923,7 @@ function SidebarMenuAction({
1774
1923
  }
1775
1924
 
1776
1925
  // scaffold/src/components/chat/identity-control.tsx
1777
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
1926
+ import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
1778
1927
  function identityLabel(identity) {
1779
1928
  if (identity.displayName) return identity.displayName;
1780
1929
  if (identity.state === "authenticated") return "Signed in";
@@ -1784,44 +1933,43 @@ function identityLabel(identity) {
1784
1933
  return "Guest";
1785
1934
  }
1786
1935
  function IdentityAvatar({ identity }) {
1787
- const label = identityLabel(identity);
1788
1936
  if (identity.avatarUrl) {
1789
- return /* @__PURE__ */ jsx21("img", { alt: "", className: "size-6 rounded-full object-cover", src: identity.avatarUrl });
1937
+ return /* @__PURE__ */ jsx22("img", { alt: "", className: "size-6 rounded-full object-cover", src: identity.avatarUrl });
1790
1938
  }
1791
- return /* @__PURE__ */ jsx21("span", { className: "flex size-6 items-center justify-center rounded-full bg-sidebar-accent text-[10px] font-semibold", "aria-hidden": "true", children: identity.displayName ? identity.displayName.slice(0, 1).toUpperCase() : /* @__PURE__ */ jsx21(UserRound, { className: "size-3.5" }) });
1939
+ return /* @__PURE__ */ jsx22("span", { className: "flex size-6 items-center justify-center rounded-full bg-sidebar-accent text-[10px] font-semibold", "aria-hidden": "true", children: identity.displayName ? identity.displayName.slice(0, 1).toUpperCase() : /* @__PURE__ */ jsx22(UserRound, { className: "size-3.5" }) });
1792
1940
  }
1793
1941
  function IdentityControl({ identity }) {
1794
1942
  const label = identityLabel(identity);
1795
1943
  const canSignOut = identity.state === "authenticated" && Boolean(identity.onSignOut);
1796
1944
  const canSignIn = (identity.state === "guest" || identity.state === "signed_out" || identity.state === "error") && Boolean(identity.onSignIn);
1797
- return /* @__PURE__ */ jsx21(SidebarMenu, { className: "w-full min-w-0", children: /* @__PURE__ */ jsx21(SidebarMenuItem, { className: "w-full min-w-0", children: /* @__PURE__ */ jsxs12(DropdownMenu, { children: [
1798
- /* @__PURE__ */ jsx21(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
1945
+ return /* @__PURE__ */ jsx22(SidebarMenu, { className: "w-full min-w-0", children: /* @__PURE__ */ jsx22(SidebarMenuItem, { className: "w-full min-w-0", children: /* @__PURE__ */ jsxs13(DropdownMenu, { children: [
1946
+ /* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs13(
1799
1947
  SidebarMenuButton,
1800
1948
  {
1801
1949
  size: "lg",
1802
1950
  "aria-label": `Account: ${label}`,
1803
1951
  className: "w-full min-w-0 justify-start",
1804
1952
  children: [
1805
- /* @__PURE__ */ jsx21(IdentityAvatar, { identity }),
1806
- /* @__PURE__ */ jsxs12("span", { className: "min-w-0 flex-1 overflow-hidden text-start", children: [
1807
- /* @__PURE__ */ jsx21("span", { className: "block truncate text-sm font-medium", children: label }),
1808
- identity.secondaryText ? /* @__PURE__ */ jsx21("span", { className: "block truncate text-xs text-muted-foreground", children: identity.secondaryText }) : null
1953
+ /* @__PURE__ */ jsx22(IdentityAvatar, { identity }),
1954
+ /* @__PURE__ */ jsxs13("span", { className: "min-w-0 flex-1 overflow-hidden text-start", children: [
1955
+ /* @__PURE__ */ jsx22("span", { className: "block truncate text-sm font-medium", children: label }),
1956
+ identity.secondaryText ? /* @__PURE__ */ jsx22("span", { className: "block truncate text-xs text-muted-foreground", children: identity.secondaryText }) : null
1809
1957
  ] })
1810
1958
  ]
1811
1959
  }
1812
1960
  ) }),
1813
- /* @__PURE__ */ jsxs12(DropdownMenuContent, { align: "start", side: "top", sideOffset: 8, children: [
1814
- /* @__PURE__ */ jsxs12(DropdownMenuLabel, { children: [
1815
- /* @__PURE__ */ jsx21("span", { className: "block truncate", children: label }),
1816
- identity.secondaryText ? /* @__PURE__ */ jsx21("span", { className: "mt-0.5 block truncate text-xs font-normal text-muted-foreground", children: identity.secondaryText }) : null
1961
+ /* @__PURE__ */ jsxs13(DropdownMenuContent, { align: "start", side: "top", sideOffset: 8, children: [
1962
+ /* @__PURE__ */ jsxs13(DropdownMenuLabel, { children: [
1963
+ /* @__PURE__ */ jsx22("span", { className: "block truncate", children: label }),
1964
+ identity.secondaryText ? /* @__PURE__ */ jsx22("span", { className: "mt-0.5 block truncate text-xs font-normal text-muted-foreground", children: identity.secondaryText }) : null
1817
1965
  ] }),
1818
- canSignIn || canSignOut ? /* @__PURE__ */ jsx21(DropdownMenuSeparator, {}) : null,
1819
- canSignIn ? /* @__PURE__ */ jsxs12(DropdownMenuItem, { onSelect: () => identity.onSignIn?.(), children: [
1820
- /* @__PURE__ */ jsx21(LogIn, {}),
1966
+ canSignIn || canSignOut ? /* @__PURE__ */ jsx22(DropdownMenuSeparator, {}) : null,
1967
+ canSignIn ? /* @__PURE__ */ jsxs13(DropdownMenuItem, { onSelect: () => identity.onSignIn?.(), children: [
1968
+ /* @__PURE__ */ jsx22(LogIn, {}),
1821
1969
  "Sign in"
1822
1970
  ] }) : null,
1823
- canSignOut ? /* @__PURE__ */ jsxs12(DropdownMenuItem, { onSelect: () => identity.onSignOut?.(), children: [
1824
- /* @__PURE__ */ jsx21(LogOut, {}),
1971
+ canSignOut ? /* @__PURE__ */ jsxs13(DropdownMenuItem, { onSelect: () => identity.onSignOut?.(), children: [
1972
+ /* @__PURE__ */ jsx22(LogOut, {}),
1825
1973
  "Sign out"
1826
1974
  ] }) : null
1827
1975
  ] })
@@ -1829,25 +1977,25 @@ function IdentityControl({ identity }) {
1829
1977
  }
1830
1978
 
1831
1979
  // scaffold/src/components/chat/thread-sidebar.tsx
1832
- import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
1980
+ import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
1833
1981
  function ThreadStatus({ thread }) {
1834
1982
  const activity = getThreadActivity(thread);
1835
1983
  if (!activity.isSpinning) return null;
1836
1984
  const label = activity.status === "cancelling" ? "Cancelling" : activity.status === "queued" ? "Queued" : "Running";
1837
- return /* @__PURE__ */ jsx22(
1985
+ return /* @__PURE__ */ jsx23(
1838
1986
  "span",
1839
1987
  {
1840
1988
  className: "pointer-events-none absolute end-1 top-1/2 hidden size-5 -translate-y-1/2 items-center justify-center text-muted-foreground transition-opacity group-hover/menu-item:opacity-0 md:flex",
1841
1989
  role: "status",
1842
1990
  "aria-label": label,
1843
1991
  title: label,
1844
- children: /* @__PURE__ */ jsx22(LoaderCircle2, { className: "size-3.5 animate-spin" })
1992
+ children: /* @__PURE__ */ jsx23(LoaderCircle2, { className: "size-3.5 animate-spin" })
1845
1993
  }
1846
1994
  );
1847
1995
  }
1848
1996
  function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoadingMore, onDelete, onLoadMore, onNew, onOpen, threads }) {
1849
1997
  const { setOpenMobile } = useSidebar();
1850
- return /* @__PURE__ */ jsxs13(
1998
+ return /* @__PURE__ */ jsxs14(
1851
1999
  Sidebar,
1852
2000
  {
1853
2001
  "aria-label": "Conversations",
@@ -1855,19 +2003,19 @@ function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoading
1855
2003
  "data-agents24-chat-sidebar": "",
1856
2004
  role: "navigation",
1857
2005
  children: [
1858
- /* @__PURE__ */ jsxs13(SidebarHeader, { className: "gap-1 p-2", children: [
1859
- /* @__PURE__ */ jsx22("div", { className: "h-8 shrink-0", "aria-hidden": "true" }),
1860
- /* @__PURE__ */ jsxs13(Button, { className: "w-full justify-start", variant: "ghost", onClick: () => {
2006
+ /* @__PURE__ */ jsxs14(SidebarHeader, { className: "gap-1 p-2", children: [
2007
+ /* @__PURE__ */ jsx23("div", { className: "h-8 shrink-0", "aria-hidden": "true" }),
2008
+ /* @__PURE__ */ jsxs14(Button, { className: "w-full justify-start", variant: "ghost", onClick: () => {
1861
2009
  onNew();
1862
2010
  setOpenMobile(false);
1863
2011
  }, children: [
1864
- /* @__PURE__ */ jsx22(SquarePen, {}),
2012
+ /* @__PURE__ */ jsx23(SquarePen, {}),
1865
2013
  " New chat"
1866
2014
  ] })
1867
2015
  ] }),
1868
- /* @__PURE__ */ jsx22(SidebarContent, { children: /* @__PURE__ */ jsx22(SidebarGroup, { children: /* @__PURE__ */ jsxs13(SidebarGroupContent, { children: [
1869
- /* @__PURE__ */ jsx22(SidebarMenu, { children: threads.map((thread) => /* @__PURE__ */ jsxs13(SidebarMenuItem, { children: [
1870
- /* @__PURE__ */ jsx22(
2016
+ /* @__PURE__ */ jsx23(SidebarContent, { children: /* @__PURE__ */ jsx23(SidebarGroup, { children: /* @__PURE__ */ jsxs14(SidebarGroupContent, { children: [
2017
+ /* @__PURE__ */ jsx23(SidebarMenu, { children: threads.map((thread) => /* @__PURE__ */ jsxs14(SidebarMenuItem, { children: [
2018
+ /* @__PURE__ */ jsx23(
1871
2019
  SidebarMenuButton,
1872
2020
  {
1873
2021
  className: "pr-8 pl-3",
@@ -1877,11 +2025,11 @@ function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoading
1877
2025
  void onOpen(thread.id).catch(() => void 0);
1878
2026
  setOpenMobile(false);
1879
2027
  },
1880
- children: /* @__PURE__ */ jsx22("span", { className: "min-w-0 truncate", children: String(thread.title || "New conversation") })
2028
+ children: /* @__PURE__ */ jsx23("span", { className: "min-w-0 truncate", children: String(thread.title || "New conversation") })
1881
2029
  }
1882
2030
  ),
1883
- /* @__PURE__ */ jsx22(ThreadStatus, { thread }),
1884
- /* @__PURE__ */ jsx22(
2031
+ /* @__PURE__ */ jsx23(ThreadStatus, { thread }),
2032
+ /* @__PURE__ */ jsx23(
1885
2033
  SidebarMenuAction,
1886
2034
  {
1887
2035
  showOnHover: true,
@@ -1891,12 +2039,12 @@ function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoading
1891
2039
  event.stopPropagation();
1892
2040
  if (window.confirm("Delete this conversation?")) void onDelete(thread.id).catch(() => void 0);
1893
2041
  },
1894
- children: /* @__PURE__ */ jsx22(Trash2, {})
2042
+ children: /* @__PURE__ */ jsx23(Trash2, {})
1895
2043
  }
1896
2044
  )
1897
2045
  ] }, thread.id)) }),
1898
- !isLoading && threads.length === 0 && /* @__PURE__ */ jsx22("p", { className: "px-2 py-8 text-center text-xs text-muted-foreground", children: "No conversations" }),
1899
- hasMore && /* @__PURE__ */ jsxs13(
2046
+ !isLoading && threads.length === 0 && /* @__PURE__ */ jsx23("p", { className: "px-2 py-8 text-center text-xs text-muted-foreground", children: "No conversations" }),
2047
+ hasMore && /* @__PURE__ */ jsxs14(
1900
2048
  Button,
1901
2049
  {
1902
2050
  className: "mt-2 w-full",
@@ -1905,14 +2053,14 @@ function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoading
1905
2053
  variant: "ghost",
1906
2054
  onClick: () => void onLoadMore().catch(() => void 0),
1907
2055
  children: [
1908
- isLoadingMore && /* @__PURE__ */ jsx22(LoaderCircle2, { className: "animate-spin" }),
2056
+ isLoadingMore && /* @__PURE__ */ jsx23(LoaderCircle2, { className: "animate-spin" }),
1909
2057
  "Load more"
1910
2058
  ]
1911
2059
  }
1912
2060
  )
1913
2061
  ] }) }) }),
1914
- /* @__PURE__ */ jsx22(SidebarFooter, { className: "w-full min-w-0 p-2", children: /* @__PURE__ */ jsx22(IdentityControl, { identity }) }),
1915
- /* @__PURE__ */ jsx22(SidebarRail, {})
2062
+ /* @__PURE__ */ jsx23(SidebarFooter, { className: "w-full min-w-0 p-2", children: /* @__PURE__ */ jsx23(IdentityControl, { identity }) }),
2063
+ /* @__PURE__ */ jsx23(SidebarRail, {})
1916
2064
  ]
1917
2065
  }
1918
2066
  );
@@ -1920,7 +2068,7 @@ function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoading
1920
2068
 
1921
2069
  // scaffold/src/components/chat/turn-outline.tsx
1922
2070
  import { LatestThreadScroller } from "@agents24/chat-react";
1923
- import { jsx as jsx23 } from "react/jsx-runtime";
2071
+ import { jsx as jsx24 } from "react/jsx-runtime";
1924
2072
  function turnsFromMessages(messages) {
1925
2073
  return messages.reduce((turns, message) => {
1926
2074
  if (message.role === "user") {
@@ -1939,7 +2087,7 @@ function turnsFromMessages(messages) {
1939
2087
  }, []);
1940
2088
  }
1941
2089
  function TurnOutline({ messages }) {
1942
- return /* @__PURE__ */ jsx23(
2090
+ return /* @__PURE__ */ jsx24(
1943
2091
  LatestThreadScroller.Outline,
1944
2092
  {
1945
2093
  items: turnsFromMessages(messages),
@@ -1966,7 +2114,7 @@ import {
1966
2114
  LatestThreadScroller as LatestThreadScroller2,
1967
2115
  latestThreadAnchorId
1968
2116
  } from "@agents24/chat-react";
1969
- import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
2117
+ import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
1970
2118
  var LOADING_INPUT_CONTRACT = {
1971
2119
  version: "agents24.runtime-inputs.v2",
1972
2120
  modalities: {
@@ -1979,31 +2127,31 @@ var LOADING_INPUT_CONTRACT = {
1979
2127
  retention: { mode: "thread_lifetime" }
1980
2128
  };
1981
2129
  function PersistentSidebarTrigger() {
1982
- return /* @__PURE__ */ jsx24("div", { className: "pointer-events-none fixed start-3 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ jsx24(SidebarTrigger, { className: "pointer-events-auto [&_svg]:size-[18px]" }) });
2130
+ return /* @__PURE__ */ jsx25("div", { className: "pointer-events-none fixed start-3 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ jsx25(SidebarTrigger, { className: "pointer-events-auto [&_svg]:size-[18px]" }) });
1983
2131
  }
1984
2132
  function CollapsedHeaderActions({ onNew }) {
1985
2133
  const { isMobile, openMobile, state } = useSidebar();
1986
2134
  const sidebarVisible = isMobile ? openMobile : state === "expanded";
1987
2135
  if (sidebarVisible) return null;
1988
- return /* @__PURE__ */ jsxs14(Fragment3, { children: [
1989
- /* @__PURE__ */ jsx24("div", { className: "h-8 w-17 shrink-0", "aria-hidden": "true" }),
1990
- /* @__PURE__ */ jsx24("div", { className: "pointer-events-none fixed start-12 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ jsx24(Button, { className: "pointer-events-auto", variant: "ghost", size: "icon-sm", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ jsx24(SquarePen2, {}) }) })
2136
+ return /* @__PURE__ */ jsxs15(Fragment3, { children: [
2137
+ /* @__PURE__ */ jsx25("div", { className: "h-8 w-17 shrink-0", "aria-hidden": "true" }),
2138
+ /* @__PURE__ */ jsx25("div", { className: "pointer-events-none fixed start-12 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ jsx25(Button, { className: "pointer-events-auto", variant: "ghost", size: "icon-sm", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ jsx25(SquarePen2, {}) }) })
1991
2139
  ] });
1992
2140
  }
1993
2141
  function OperationErrorNotice({ runtime }) {
1994
2142
  const error = runtime.operationError || runtime.backgroundError;
1995
2143
  if (!error) return null;
1996
- return /* @__PURE__ */ jsx24("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-40 flex justify-center px-4", children: /* @__PURE__ */ jsxs14("div", { className: "pointer-events-auto flex max-w-lg items-start gap-2 rounded-lg border border-destructive/20 bg-background px-3 py-2 text-sm shadow-md", role: "alert", children: [
1997
- /* @__PURE__ */ jsx24(CircleAlert, { className: "mt-0.5 size-4 shrink-0 text-destructive" }),
1998
- /* @__PURE__ */ jsx24("span", { className: "min-w-0 flex-1 wrap-break-word", children: agentChatRuntimeErrorMessage(error) || "The chat could not complete that action." }),
1999
- /* @__PURE__ */ jsx24(
2144
+ return /* @__PURE__ */ jsx25("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-40 flex justify-center px-4", children: /* @__PURE__ */ jsxs15("div", { className: "pointer-events-auto flex max-w-lg items-start gap-2 rounded-lg border border-destructive/20 bg-background px-3 py-2 text-sm shadow-md", role: "alert", children: [
2145
+ /* @__PURE__ */ jsx25(CircleAlert, { className: "mt-0.5 size-4 shrink-0 text-destructive" }),
2146
+ /* @__PURE__ */ jsx25("span", { className: "min-w-0 flex-1 wrap-break-word", children: agentChatRuntimeErrorMessage(error) || "The chat could not complete that action." }),
2147
+ /* @__PURE__ */ jsx25(
2000
2148
  Button,
2001
2149
  {
2002
2150
  "aria-label": "Dismiss error",
2003
2151
  onClick: runtime.operationError ? runtime.clearOperationError : runtime.controller.clearBackgroundError,
2004
2152
  size: "icon-xs",
2005
2153
  variant: "ghost",
2006
- children: /* @__PURE__ */ jsx24(X, {})
2154
+ children: /* @__PURE__ */ jsx25(X, {})
2007
2155
  }
2008
2156
  )
2009
2157
  ] }) });
@@ -2024,11 +2172,11 @@ function ChatShell({
2024
2172
  const hasBlockingError = Boolean(runtime.fatalError && controller.messages.length === 0);
2025
2173
  const isEmptyState = controller.activeThreadId === null && controller.messages.length === 0 && !hasBlockingError;
2026
2174
  const latestAnchorId = latestThreadAnchorId(controller.messages);
2027
- const composerOverlayRef = React8.useRef(null);
2028
- const [composerOverlayHeight, setComposerOverlayHeight] = React8.useState(192);
2029
- const [restoredDraft, setRestoredDraft] = React8.useState(null);
2030
- const draftRevisionRef = React8.useRef(0);
2031
- const retractForEdit = React8.useCallback(async (message) => {
2175
+ const composerOverlayRef = React9.useRef(null);
2176
+ const [composerOverlayHeight, setComposerOverlayHeight] = React9.useState(192);
2177
+ const [restoredDraft, setRestoredDraft] = React9.useState(null);
2178
+ const draftRevisionRef = React9.useRef(0);
2179
+ const retractForEdit = React9.useCallback(async (message) => {
2032
2180
  const draft = await controller.retractPendingMessage(message);
2033
2181
  setRestoredDraft({
2034
2182
  revision: ++draftRevisionRef.current,
@@ -2036,7 +2184,7 @@ function ChatShell({
2036
2184
  files: queuedMessageComposerFiles(draft)
2037
2185
  });
2038
2186
  }, [controller]);
2039
- React8.useLayoutEffect(() => {
2187
+ React9.useLayoutEffect(() => {
2040
2188
  const overlay = composerOverlayRef.current;
2041
2189
  if (!overlay || isEmptyState) return;
2042
2190
  const updateHeight = () => {
@@ -2047,15 +2195,15 @@ function ChatShell({
2047
2195
  resizeObserver.observe(overlay);
2048
2196
  return () => resizeObserver.disconnect();
2049
2197
  }, [isEmptyState]);
2050
- return /* @__PURE__ */ jsxs14(
2198
+ return /* @__PURE__ */ jsxs15(
2051
2199
  SidebarProvider,
2052
2200
  {
2053
2201
  className: "h-svh min-h-0 overflow-hidden",
2054
2202
  "data-agents24-chat": "",
2055
2203
  "data-agents24-chat-layout": "",
2056
2204
  children: [
2057
- /* @__PURE__ */ jsx24(PersistentSidebarTrigger, {}),
2058
- sidebar || /* @__PURE__ */ jsx24(
2205
+ /* @__PURE__ */ jsx25(PersistentSidebarTrigger, {}),
2206
+ sidebar || /* @__PURE__ */ jsx25(
2059
2207
  ThreadSidebar,
2060
2208
  {
2061
2209
  activeThreadId: controller.activeThreadId,
@@ -2070,57 +2218,58 @@ function ChatShell({
2070
2218
  onOpen: runtime.openThread
2071
2219
  }
2072
2220
  ),
2073
- /* @__PURE__ */ jsxs14(SidebarInset, { className: "h-svh min-h-0 overflow-hidden bg-background", children: [
2074
- /* @__PURE__ */ jsxs14(
2221
+ /* @__PURE__ */ jsxs15(SidebarInset, { className: "h-svh min-h-0 overflow-hidden bg-background", children: [
2222
+ /* @__PURE__ */ jsxs15(
2075
2223
  "header",
2076
2224
  {
2077
2225
  className: "flex h-12 shrink-0 items-center gap-2 border-b border-border/50 px-3 sm:px-4",
2078
2226
  "data-agents24-chat-header": "",
2079
2227
  children: [
2080
- /* @__PURE__ */ jsx24(CollapsedHeaderActions, { onNew: runtime.newThread }),
2081
- /* @__PURE__ */ jsx24("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx24("h1", { className: "truncate text-sm font-medium", children: String(activeTitle || "New chat") }) }),
2082
- /* @__PURE__ */ jsx24(ThemeMenu, {})
2228
+ /* @__PURE__ */ jsx25(CollapsedHeaderActions, { onNew: runtime.newThread }),
2229
+ /* @__PURE__ */ jsx25("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx25("h1", { className: "truncate text-sm font-medium", children: String(activeTitle || "New chat") }) }),
2230
+ /* @__PURE__ */ jsx25(ThemeMenu, {})
2083
2231
  ]
2084
2232
  }
2085
2233
  ),
2086
- /* @__PURE__ */ jsxs14(
2234
+ /* @__PURE__ */ jsxs15(
2087
2235
  "section",
2088
2236
  {
2089
2237
  "aria-label": "Conversation",
2090
2238
  className: "relative flex min-h-0 flex-1 flex-col overflow-hidden",
2091
2239
  "data-agents24-chat-transcript": "",
2092
2240
  children: [
2093
- /* @__PURE__ */ jsx24(OperationErrorNotice, { runtime }),
2094
- /* @__PURE__ */ jsxs14(LatestThreadScroller2.Provider, { autoScroll: true, defaultScrollPosition: "last-anchor", scrollPreviousItemPeek: 64, children: [
2095
- !isEmptyState && /* @__PURE__ */ jsxs14(LatestThreadScroller2.Root, { className: "relative min-h-0 flex-1", children: [
2096
- /* @__PURE__ */ jsx24(LatestThreadScroller2.Viewport, { preserveScrollOnPrepend: true, children: /* @__PURE__ */ jsxs14(
2241
+ /* @__PURE__ */ jsx25(OperationErrorNotice, { runtime }),
2242
+ /* @__PURE__ */ jsx25(SubagentTasks, { threadId: controller.activeThreadId }),
2243
+ /* @__PURE__ */ jsxs15(LatestThreadScroller2.Provider, { autoScroll: true, defaultScrollPosition: "last-anchor", scrollPreviousItemPeek: 64, children: [
2244
+ !isEmptyState && /* @__PURE__ */ jsxs15(LatestThreadScroller2.Root, { className: "relative min-h-0 flex-1", children: [
2245
+ /* @__PURE__ */ jsx25(LatestThreadScroller2.Viewport, { preserveScrollOnPrepend: true, children: /* @__PURE__ */ jsxs15(
2097
2246
  LatestThreadScroller2.Content,
2098
2247
  {
2099
2248
  className: "mx-auto w-full max-w-3xl gap-3 px-4 pt-8 pb-0 sm:px-6 sm:pt-12",
2100
2249
  style: { paddingBottom: composerOverlayHeight + 72 },
2101
2250
  children: [
2102
- controller.hasOlderTurns && /* @__PURE__ */ jsxs14(Button, { className: "self-center", variant: "ghost", size: "sm", disabled: controller.isLoadingOlder, onClick: () => {
2251
+ controller.hasOlderTurns && /* @__PURE__ */ jsxs15(Button, { className: "self-center", variant: "ghost", size: "sm", disabled: controller.isLoadingOlder, onClick: () => {
2103
2252
  void controller.loadOlder().catch(() => void 0);
2104
2253
  }, children: [
2105
- controller.isLoadingOlder && /* @__PURE__ */ jsx24(LoaderCircle3, { className: "animate-spin" }),
2254
+ controller.isLoadingOlder && /* @__PURE__ */ jsx25(LoaderCircle3, { className: "animate-spin" }),
2106
2255
  " Load earlier messages"
2107
2256
  ] }),
2108
- runtime.isBootstrapping && /* @__PURE__ */ jsx24("div", { "aria-label": "Loading conversation", className: "flex flex-1 items-center justify-center py-24 text-muted-foreground", role: "status", children: /* @__PURE__ */ jsx24(LoaderCircle3, { className: "size-4 animate-spin" }) }),
2109
- hasBlockingError && /* @__PURE__ */ jsxs14("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 py-24 text-center", children: [
2110
- /* @__PURE__ */ jsx24(CircleAlert, { className: "size-5 text-destructive" }),
2111
- /* @__PURE__ */ jsxs14("div", { children: [
2112
- /* @__PURE__ */ jsx24("h2", { className: "font-medium", children: "Couldn\u2019t connect" }),
2113
- /* @__PURE__ */ jsx24("p", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: runtime.errorMessage })
2257
+ runtime.isBootstrapping && /* @__PURE__ */ jsx25("div", { "aria-label": "Loading conversation", className: "flex flex-1 items-center justify-center py-24 text-muted-foreground", role: "status", children: /* @__PURE__ */ jsx25(LoaderCircle3, { className: "size-4 animate-spin" }) }),
2258
+ hasBlockingError && /* @__PURE__ */ jsxs15("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 py-24 text-center", children: [
2259
+ /* @__PURE__ */ jsx25(CircleAlert, { className: "size-5 text-destructive" }),
2260
+ /* @__PURE__ */ jsxs15("div", { children: [
2261
+ /* @__PURE__ */ jsx25("h2", { className: "font-medium", children: "Couldn\u2019t connect" }),
2262
+ /* @__PURE__ */ jsx25("p", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: runtime.errorMessage })
2114
2263
  ] }),
2115
- /* @__PURE__ */ jsx24(Button, { variant: "outline", onClick: () => void runtime.retryBootstrap(), children: "Try again" })
2264
+ /* @__PURE__ */ jsx25(Button, { variant: "outline", onClick: () => void runtime.retryBootstrap(), children: "Try again" })
2116
2265
  ] }),
2117
- controller.messages.map((message) => /* @__PURE__ */ jsx24(
2266
+ controller.messages.map((message) => /* @__PURE__ */ jsx25(
2118
2267
  LatestThreadScroller2.Item,
2119
2268
  {
2120
2269
  messageId: message.id,
2121
2270
  scrollAnchor: isRunning && message.id === latestAnchorId,
2122
2271
  className: "overflow-visible [content-visibility:visible]",
2123
- children: /* @__PURE__ */ jsx24(
2272
+ children: /* @__PURE__ */ jsx25(
2124
2273
  ChatMessage,
2125
2274
  {
2126
2275
  animateCompletion: wasLiveRun(message.runId),
@@ -2146,9 +2295,9 @@ function ChatShell({
2146
2295
  ]
2147
2296
  }
2148
2297
  ) }),
2149
- /* @__PURE__ */ jsx24(TurnOutline, { messages: controller.messages })
2298
+ /* @__PURE__ */ jsx25(TurnOutline, { messages: controller.messages })
2150
2299
  ] }),
2151
- /* @__PURE__ */ jsxs14(
2300
+ /* @__PURE__ */ jsxs15(
2152
2301
  "div",
2153
2302
  {
2154
2303
  ref: composerOverlayRef,
@@ -2157,56 +2306,52 @@ function ChatShell({
2157
2306
  background: "linear-gradient(to bottom, transparent 0%, color-mix(in oklch, var(--background) 85%, transparent) 45%, var(--background) 65%, var(--background) 100%)"
2158
2307
  },
2159
2308
  children: [
2160
- isEmptyState ? /* @__PURE__ */ jsx24("div", { className: "mx-auto mb-8 w-full max-w-3xl px-4 text-center sm:px-6", children: /* @__PURE__ */ jsx24("h2", { className: "text-3xl font-semibold tracking-tight sm:text-4xl", children: "Ready when you are." }) }) : /* @__PURE__ */ jsx24("div", { className: "pointer-events-auto absolute inset-x-0 top-0 flex -translate-y-full justify-center pb-3", children: /* @__PURE__ */ jsx24(LatestThreadScroller2.Button, { className: "!relative !inset-auto !translate-x-0 rtl:!translate-x-0" }) }),
2161
- /* @__PURE__ */ jsxs14("div", { className: "pointer-events-auto mx-auto w-full max-w-3xl px-4 sm:px-6", children: [
2162
- /* @__PURE__ */ jsx24(
2163
- AgentChatQueue,
2164
- {
2165
- pending: controller.pendingMessages,
2166
- queue: controller.messageQueue,
2167
- canSteer: controller.runState === "streaming",
2168
- onSteer: controller.steerPendingMessage,
2169
- onRemove: controller.removePendingMessage,
2170
- onEdit: retractForEdit,
2171
- onResume: controller.resumeQueue
2172
- }
2173
- ),
2174
- /* @__PURE__ */ jsx24(
2175
- Composer,
2176
- {
2177
- restoredDraft,
2178
- inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
2179
- contextWindow: runtime.contextWindow,
2180
- disabled: runtime.isBootstrapping || runtime.isChangingAgent || isUploading || hasBlockingError,
2181
- focusKey: controller.activeThreadId,
2182
- forceExpanded: isEmptyState,
2183
- isCancelling,
2184
- isRunning,
2185
- agentId: runtime.agentId,
2186
- agents: runtime.agents,
2187
- onAgentChange: (agentId) => {
2188
- void runtime.changeAgent(agentId);
2189
- },
2190
- onStop: () => {
2191
- void controller.cancelRun().catch(() => void 0);
2192
- },
2193
- modelId: runtime.modelId,
2194
- models: runtime.models,
2195
- onModelChange: runtime.changeModel,
2196
- onSubmit: (text, files) => runtime.submit({
2197
- text,
2198
- files: files.filter((file) => file.source).map((file) => ({
2199
- data: file.source,
2200
- mediaType: file.mediaType,
2201
- name: file.filename
2202
- })),
2203
- attachmentIds: files.flatMap((file) => file.persistedAttachmentId ? [file.persistedAttachmentId] : []),
2204
- attachments: files
2205
- }),
2206
- utilityRow: isEmptyState ? "inline" : "below"
2207
- }
2208
- )
2209
- ] })
2309
+ isEmptyState ? /* @__PURE__ */ jsx25("div", { className: "mx-auto mb-8 w-full max-w-3xl px-4 text-center sm:px-6", children: /* @__PURE__ */ jsx25("h2", { className: "text-3xl font-semibold tracking-tight sm:text-4xl", children: "Ready when you are." }) }) : /* @__PURE__ */ jsx25("div", { className: "pointer-events-auto absolute inset-x-0 top-0 flex -translate-y-full justify-center pb-3", children: /* @__PURE__ */ jsx25(LatestThreadScroller2.Button, { className: "!relative !inset-auto !translate-x-0 rtl:!translate-x-0" }) }),
2310
+ /* @__PURE__ */ jsx25("div", { className: "pointer-events-auto mx-auto w-full max-w-3xl px-4 sm:px-6", children: /* @__PURE__ */ jsx25(
2311
+ Composer,
2312
+ {
2313
+ queue: /* @__PURE__ */ jsx25(
2314
+ AgentChatQueue,
2315
+ {
2316
+ pending: controller.pendingMessages,
2317
+ queue: controller.messageQueue,
2318
+ onRemove: controller.removePendingMessage,
2319
+ onEdit: retractForEdit,
2320
+ onResume: controller.resumeQueue
2321
+ }
2322
+ ),
2323
+ restoredDraft,
2324
+ inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
2325
+ contextWindow: runtime.contextWindow,
2326
+ disabled: runtime.isBootstrapping || runtime.isChangingAgent || isUploading || hasBlockingError,
2327
+ focusKey: controller.activeThreadId,
2328
+ forceExpanded: isEmptyState,
2329
+ isCancelling,
2330
+ isRunning,
2331
+ agentId: runtime.agentId,
2332
+ agents: runtime.agents,
2333
+ onAgentChange: (agentId) => {
2334
+ void runtime.changeAgent(agentId);
2335
+ },
2336
+ onStop: () => {
2337
+ void controller.cancelRun().catch(() => void 0);
2338
+ },
2339
+ modelId: runtime.modelId,
2340
+ models: runtime.models,
2341
+ onModelChange: runtime.changeModel,
2342
+ onSubmit: (text, files) => runtime.submit({
2343
+ text,
2344
+ files: files.filter((file) => file.source).map((file) => ({
2345
+ data: file.source,
2346
+ mediaType: file.mediaType,
2347
+ name: file.filename
2348
+ })),
2349
+ attachmentIds: files.flatMap((file) => file.persistedAttachmentId ? [file.persistedAttachmentId] : []),
2350
+ attachments: files
2351
+ }),
2352
+ utilityRow: isEmptyState ? "inline" : "below"
2353
+ }
2354
+ ) })
2210
2355
  ]
2211
2356
  }
2212
2357
  )
@@ -2224,7 +2369,7 @@ function ChatShell({
2224
2369
  var GUEST_CHAT_IDENTITY = { state: "guest" };
2225
2370
 
2226
2371
  // scaffold/src/app.tsx
2227
- import { jsx as jsx25 } from "react/jsx-runtime";
2372
+ import { jsx as jsx26 } from "react/jsx-runtime";
2228
2373
  var createBrowserAbortController = () => new AbortController();
2229
2374
  var browserVisibility = createBrowserVisibility();
2230
2375
  function RuntimeChat({
@@ -2236,17 +2381,17 @@ function RuntimeChat({
2236
2381
  ...props,
2237
2382
  mcpRedirectUri: props.mcpRedirectUri || (typeof window === "undefined" ? void 0 : window.location.href)
2238
2383
  });
2239
- return /* @__PURE__ */ jsx25(ChatShell, { components, identity, runtime, sidebar: props.sidebar });
2384
+ return /* @__PURE__ */ jsx26(ChatShell, { components, identity, runtime, sidebar: props.sidebar });
2240
2385
  }
2241
2386
  function App(props) {
2242
2387
  const identity = props.identity || GUEST_CHAT_IDENTITY;
2243
- return /* @__PURE__ */ jsx25(Agents24Provider, { client: props.client, createAbortController: createBrowserAbortController, visibility: browserVisibility, children: /* @__PURE__ */ jsx25(RuntimeChat, { ...props }, identity.state) });
2388
+ return /* @__PURE__ */ jsx26(Agents24Provider, { client: props.client, createAbortController: createBrowserAbortController, visibility: browserVisibility, children: /* @__PURE__ */ jsx26(RuntimeChat, { ...props }, identity.state) });
2244
2389
  }
2245
2390
 
2246
2391
  // scaffold/src/index.tsx
2247
- import { jsx as jsx26 } from "react/jsx-runtime";
2248
- function Agents24ChatScaffold({ appearanceController, theme, ...props }) {
2249
- return /* @__PURE__ */ jsx26(ThemeProvider, { controller: appearanceController, theme, children: /* @__PURE__ */ jsx26(TooltipProvider, { children: /* @__PURE__ */ jsx26(App, { ...props }) }) });
2392
+ import { jsx as jsx27 } from "react/jsx-runtime";
2393
+ function Agents24ChatScaffold({ appearanceController, theme, themeMode, ...props }) {
2394
+ return /* @__PURE__ */ jsx27(ThemeProvider, { controller: appearanceController, theme, mode: themeMode, children: /* @__PURE__ */ jsx27(TooltipProvider, { children: /* @__PURE__ */ jsx27(App, { ...props }) }) });
2250
2395
  }
2251
2396
  export {
2252
2397
  ChatComposer as Agents24ChatComposer,