@truefoundry/agent-ui-sdk 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -122,6 +122,15 @@ function ReasoningCard(props) {
122
122
  return /* @__PURE__ */ jsx9(TfyReasoningCard, { ...props });
123
123
  }
124
124
 
125
+ // src/atoms/adapters/AgentStepsCardAdapter.tsx
126
+ import {
127
+ AgentStepsCard as TfyAgentStepsCard
128
+ } from "tfy-web-components/components/molecules/agent-chat";
129
+ import { jsx as jsx10 } from "react/jsx-runtime";
130
+ function AgentStepsCard(props) {
131
+ return /* @__PURE__ */ jsx10(TfyAgentStepsCard, { ...props });
132
+ }
133
+
125
134
  // src/atoms/primitives/Avatar.tsx
126
135
  import "react";
127
136
  import TfyAvatar, {
@@ -137,12 +146,12 @@ function cn(...inputs) {
137
146
  }
138
147
 
139
148
  // src/atoms/primitives/Avatar.tsx
140
- import { jsx as jsx10 } from "react/jsx-runtime";
149
+ import { jsx as jsx11 } from "react/jsx-runtime";
141
150
  var AvatarRoot = TfyAvatar;
142
151
  var AvatarImagePrimitive = TfyAvatarImage;
143
152
  var AvatarFallbackPrimitive = TfyAvatarFallback;
144
153
  function Avatar({ className, size = "default", ...props }) {
145
- return /* @__PURE__ */ jsx10(
154
+ return /* @__PURE__ */ jsx11(
146
155
  AvatarRoot,
147
156
  {
148
157
  "data-slot": "avatar",
@@ -154,15 +163,15 @@ function Avatar({ className, size = "default", ...props }) {
154
163
  );
155
164
  }
156
165
  function AvatarImage({ className, ...props }) {
157
- return /* @__PURE__ */ jsx10(AvatarImagePrimitive, { "data-slot": "avatar-image", className: cn(className), ...props });
166
+ return /* @__PURE__ */ jsx11(AvatarImagePrimitive, { "data-slot": "avatar-image", className: cn(className), ...props });
158
167
  }
159
168
  function AvatarFallback({ className, ...props }) {
160
- return /* @__PURE__ */ jsx10(AvatarFallbackPrimitive, { "data-slot": "avatar-fallback", className: cn(className), ...props });
169
+ return /* @__PURE__ */ jsx11(AvatarFallbackPrimitive, { "data-slot": "avatar-fallback", className: cn(className), ...props });
161
170
  }
162
171
 
163
172
  // src/atoms/UserMessageBubble.tsx
164
173
  import { UserMessage } from "tfy-web-components/components/molecules/agent-chat";
165
- import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
174
+ import { jsx as jsx12, jsxs as jsxs3 } from "react/jsx-runtime";
166
175
  function UserMessageBubble({ text, attachments, editAction, className }) {
167
176
  return /* @__PURE__ */ jsxs3(
168
177
  "div",
@@ -171,7 +180,7 @@ function UserMessageBubble({ text, attachments, editAction, className }) {
171
180
  className: cn("fade-in slide-in-from-bottom-1 animate-in duration-150", className),
172
181
  children: [
173
182
  attachments,
174
- /* @__PURE__ */ jsx11(UserMessage, { text, editAction, actionsAlwaysVisible: true })
183
+ /* @__PURE__ */ jsx12(UserMessage, { text, editAction })
175
184
  ]
176
185
  }
177
186
  );
@@ -180,9 +189,9 @@ function UserMessageBubble({ text, attachments, editAction, className }) {
180
189
  // src/atoms/UserMessageEdit.tsx
181
190
  import { forwardRef } from "react";
182
191
  import TfyUserMessageEdit from "tfy-web-components/components/molecules/agent-chat/UserMessageEdit";
183
- import { jsx as jsx12 } from "react/jsx-runtime";
192
+ import { jsx as jsx13 } from "react/jsx-runtime";
184
193
  var UserMessageEdit = forwardRef(function UserMessageEdit2({ timestamp, attachments, input, footer, className, ...rest }, ref) {
185
- return /* @__PURE__ */ jsx12(
194
+ return /* @__PURE__ */ jsx13(
186
195
  TfyUserMessageEdit,
187
196
  {
188
197
  ref,
@@ -201,10 +210,10 @@ var UserMessageEdit = forwardRef(function UserMessageEdit2({ timestamp, attachme
201
210
  import {
202
211
  ToolCallCard as TfyToolCallCard
203
212
  } from "tfy-web-components/components/molecules/agent-chat";
204
- import { jsx as jsx13 } from "react/jsx-runtime";
213
+ import { jsx as jsx14 } from "react/jsx-runtime";
205
214
  function ToolCallCard(props) {
206
215
  const { mcpServerName, ...tfyProps } = props;
207
- return /* @__PURE__ */ jsx13(
216
+ return /* @__PURE__ */ jsx14(
208
217
  TfyToolCallCard,
209
218
  {
210
219
  ...tfyProps,
@@ -217,14 +226,14 @@ function ToolCallCard(props) {
217
226
  import {
218
227
  ToolCallContentBlock as TfyToolCallContentBlock
219
228
  } from "tfy-web-components/components/molecules/agent-chat";
220
- import { jsx as jsx14 } from "react/jsx-runtime";
229
+ import { jsx as jsx15 } from "react/jsx-runtime";
221
230
  function ToolCallContentBlock(props) {
222
- return /* @__PURE__ */ jsx14(TfyToolCallContentBlock, { ...props });
231
+ return /* @__PURE__ */ jsx15(TfyToolCallContentBlock, { ...props });
223
232
  }
224
233
 
225
234
  // src/atoms/SubAgentCard.tsx
226
235
  import { SubAgentCard as TfySubAgentCard } from "tfy-web-components/components/molecules/agent-chat";
227
- import { jsx as jsx15 } from "react/jsx-runtime";
236
+ import { jsx as jsx16 } from "react/jsx-runtime";
228
237
  function SubAgentCard({
229
238
  agentName,
230
239
  instruction,
@@ -237,7 +246,7 @@ function SubAgentCard({
237
246
  className
238
247
  }) {
239
248
  const Markdown2 = useSlot("Markdown");
240
- return /* @__PURE__ */ jsx15(
249
+ return /* @__PURE__ */ jsx16(
241
250
  TfySubAgentCard,
242
251
  {
243
252
  agentName,
@@ -247,7 +256,7 @@ function SubAgentCard({
247
256
  expanded,
248
257
  onToggle,
249
258
  durationText,
250
- renderInstruction: (content) => /* @__PURE__ */ jsx15(Markdown2, { content }),
259
+ renderInstruction: (content) => /* @__PURE__ */ jsx16(Markdown2, { content }),
251
260
  className: cn("aui-sub-agent-card", className),
252
261
  children
253
262
  }
@@ -259,7 +268,7 @@ import {
259
268
  SandboxToolCall,
260
269
  ToolCallCard as TfyToolCallCard2
261
270
  } from "tfy-web-components/components/molecules/agent-chat";
262
- import { jsx as jsx16 } from "react/jsx-runtime";
271
+ import { jsx as jsx17 } from "react/jsx-runtime";
263
272
  function SandboxToolCallCard({
264
273
  name,
265
274
  intent,
@@ -278,7 +287,7 @@ function SandboxToolCallCard({
278
287
  className
279
288
  }) {
280
289
  const awaiting = status === "running";
281
- const sandboxContent = /* @__PURE__ */ jsx16(
290
+ const sandboxContent = /* @__PURE__ */ jsx17(
282
291
  SandboxToolCall,
283
292
  {
284
293
  command,
@@ -291,7 +300,7 @@ function SandboxToolCallCard({
291
300
  onViewModeChange
292
301
  }
293
302
  );
294
- return /* @__PURE__ */ jsx16(
303
+ return /* @__PURE__ */ jsx17(
295
304
  TfyToolCallCard2,
296
305
  {
297
306
  toolName: intent || name,
@@ -312,9 +321,9 @@ function SandboxToolCallCard({
312
321
  import {
313
322
  ToolApprovalBlock
314
323
  } from "tfy-web-components/components/molecules/agent-chat";
315
- import { jsx as jsx17 } from "react/jsx-runtime";
324
+ import { jsx as jsx18 } from "react/jsx-runtime";
316
325
  function ToolApprovalBar({ className, ...props }) {
317
- return /* @__PURE__ */ jsx17(
326
+ return /* @__PURE__ */ jsx18(
318
327
  ToolApprovalBlock,
319
328
  {
320
329
  ...props,
@@ -326,7 +335,7 @@ function ToolApprovalBar({ className, ...props }) {
326
335
  // src/atoms/ToolGroupCard.tsx
327
336
  import { ChevronDownIcon, LoaderIcon } from "lucide-react";
328
337
  import { Accordion, AccordionDetails, AccordionSummary } from "tfy-web-components/components/atoms/Accordion";
329
- import { jsx as jsx18, jsxs as jsxs4 } from "react/jsx-runtime";
338
+ import { jsx as jsx19, jsxs as jsxs4 } from "react/jsx-runtime";
330
339
  function ToolGroupCard({
331
340
  toolCallCount,
332
341
  expanded,
@@ -346,7 +355,7 @@ function ToolGroupCard({
346
355
  className: cn("aui-tool-group-card group/tool-group w-full", className),
347
356
  sx: { margin: 0, border: "none", boxShadow: "none" },
348
357
  children: [
349
- /* @__PURE__ */ jsx18(
358
+ /* @__PURE__ */ jsx19(
350
359
  AccordionSummary,
351
360
  {
352
361
  hideIcon: true,
@@ -359,9 +368,9 @@ function ToolGroupCard({
359
368
  "& .MuiAccordionSummary-content": { margin: 0, width: "100%" }
360
369
  },
361
370
  children: /* @__PURE__ */ jsxs4("div", { className: "text-muted-foreground hover:text-foreground flex origin-left items-center gap-2 py-1.5 text-sm transition-[color,scale] active:scale-[0.98]", children: [
362
- active && /* @__PURE__ */ jsx18(LoaderIcon, { className: "size-3 shrink-0 animate-spin [animation-duration:0.6s]" }),
363
- /* @__PURE__ */ jsx18("span", { className: "text-xs font-medium", children: label }),
364
- /* @__PURE__ */ jsx18(
371
+ active && /* @__PURE__ */ jsx19(LoaderIcon, { className: "size-3 shrink-0 animate-spin [animation-duration:0.6s]" }),
372
+ /* @__PURE__ */ jsx19("span", { className: "text-xs font-medium", children: label }),
373
+ /* @__PURE__ */ jsx19(
365
374
  ChevronDownIcon,
366
375
  {
367
376
  className: cn(
@@ -373,7 +382,7 @@ function ToolGroupCard({
373
382
  ] })
374
383
  }
375
384
  ),
376
- /* @__PURE__ */ jsx18(AccordionDetails, { sx: { padding: 0 }, children: /* @__PURE__ */ jsx18("div", { className: "mt-1 flex flex-col gap-2 text-foreground", children }) })
385
+ /* @__PURE__ */ jsx19(AccordionDetails, { sx: { padding: 0 }, children: /* @__PURE__ */ jsx19("div", { className: "mt-1 flex flex-col gap-2 text-foreground", children }) })
377
386
  ]
378
387
  }
379
388
  );
@@ -381,7 +390,7 @@ function ToolGroupCard({
381
390
 
382
391
  // src/atoms/Skeletons.tsx
383
392
  import Skeleton from "tfy-web-components/components/atoms/Skeleton";
384
- import { jsx as jsx19, jsxs as jsxs5 } from "react/jsx-runtime";
393
+ import { jsx as jsx20, jsxs as jsxs5 } from "react/jsx-runtime";
385
394
  function MessageListSkeleton({ className }) {
386
395
  return /* @__PURE__ */ jsxs5(
387
396
  "div",
@@ -391,11 +400,11 @@ function MessageListSkeleton({ className }) {
391
400
  "data-slot": "aui_thread-history-skeleton",
392
401
  className: cn("mb-14 flex flex-col gap-y-6", className),
393
402
  children: [
394
- /* @__PURE__ */ jsx19("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-10 w-[min(85%,20rem)] rounded-xl" }) }),
403
+ /* @__PURE__ */ jsx20("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx20(Skeleton, { className: "h-10 w-[min(85%,20rem)] rounded-xl" }) }),
395
404
  /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2 px-2", children: [
396
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-md" }),
397
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-sm" }),
398
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-2/3 max-w-xs" })
405
+ /* @__PURE__ */ jsx20(Skeleton, { className: "h-4 w-full max-w-md" }),
406
+ /* @__PURE__ */ jsx20(Skeleton, { className: "h-4 w-full max-w-sm" }),
407
+ /* @__PURE__ */ jsx20(Skeleton, { className: "h-4 w-2/3 max-w-xs" })
399
408
  ] })
400
409
  ]
401
410
  }
@@ -403,7 +412,7 @@ function MessageListSkeleton({ className }) {
403
412
  }
404
413
 
405
414
  // src/atoms/ComposerShell.tsx
406
- import { jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
415
+ import { jsx as jsx21, jsxs as jsxs6 } from "react/jsx-runtime";
407
416
  function ComposerShell({
408
417
  value,
409
418
  placeholder,
@@ -432,7 +441,7 @@ function ComposerShell({
432
441
  ),
433
442
  children: [
434
443
  attachments,
435
- /* @__PURE__ */ jsx20(
444
+ /* @__PURE__ */ jsx21(
436
445
  "textarea",
437
446
  {
438
447
  value,
@@ -452,7 +461,7 @@ function ComposerShell({
452
461
  ),
453
462
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-1", children: [
454
463
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
455
- /* @__PURE__ */ jsx20(
464
+ /* @__PURE__ */ jsx21(
456
465
  ComposerLeftSection2,
457
466
  {
458
467
  disabled,
@@ -460,15 +469,15 @@ function ComposerShell({
460
469
  onAttach
461
470
  }
462
471
  ),
463
- connectorStatusLabel && /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
472
+ connectorStatusLabel && /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
464
473
  ] }),
465
474
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
466
475
  modelLabel && /* @__PURE__ */ jsxs6("span", { className: "bg-muted text-muted-foreground flex items-center gap-1 rounded-full px-2 py-0.5 text-xs", children: [
467
476
  modelIcon,
468
477
  modelLabel
469
478
  ] }),
470
- /* @__PURE__ */ jsx20(ComposerRightSection2, { disabled, isRunning }),
471
- /* @__PURE__ */ jsx20(
479
+ /* @__PURE__ */ jsx21(ComposerRightSection2, { disabled, isRunning }),
480
+ /* @__PURE__ */ jsx21(
472
481
  ComposerSendButton2,
473
482
  {
474
483
  disabled,
@@ -487,11 +496,11 @@ function ComposerShell({
487
496
 
488
497
  // src/atoms/ComposerSections.tsx
489
498
  import Spinner from "tfy-web-components/components/atoms/Spinner";
490
- import { Fragment, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
499
+ import { Fragment, jsx as jsx22, jsxs as jsxs7 } from "react/jsx-runtime";
491
500
  function ComposerLeftSection({ onAttach }) {
492
501
  const IconButton5 = useSlot("IconButton");
493
502
  if (!onAttach) return null;
494
- return /* @__PURE__ */ jsx21(IconButton5, { icon: "plus", tooltip: "Attach", onClick: onAttach });
503
+ return /* @__PURE__ */ jsx22(IconButton5, { icon: "plus", tooltip: "Attach", onClick: onAttach });
495
504
  }
496
505
  function ComposerRightSection(_) {
497
506
  return null;
@@ -504,19 +513,19 @@ function ComposerSendButton({
504
513
  }) {
505
514
  const Button4 = useSlot("Button");
506
515
  if (isRunning) {
507
- return /* @__PURE__ */ jsx21(
516
+ return /* @__PURE__ */ jsx22(
508
517
  Button4.Primary,
509
518
  {
510
519
  disabled: !onCancel,
511
520
  onClick: onCancel,
512
521
  text: /* @__PURE__ */ jsxs7(Fragment, { children: [
513
- /* @__PURE__ */ jsx21(Spinner, { small: true }),
522
+ /* @__PURE__ */ jsx22(Spinner, { small: true }),
514
523
  "Cancel"
515
524
  ] })
516
525
  }
517
526
  );
518
527
  }
519
- return /* @__PURE__ */ jsx21(
528
+ return /* @__PURE__ */ jsx22(
520
529
  Button4.Primary,
521
530
  {
522
531
  disabled: !canSubmit,
@@ -537,7 +546,7 @@ import { FileTextIcon } from "lucide-react";
537
546
  var USER_MESSAGE_ATTACHMENT_PREVIEW_REM = 12;
538
547
 
539
548
  // src/atoms/AttachmentCard.tsx
540
- import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
549
+ import { jsx as jsx23, jsxs as jsxs8 } from "react/jsx-runtime";
541
550
  function AttachmentCard({
542
551
  name,
543
552
  previewSrc,
@@ -553,7 +562,7 @@ function AttachmentCard({
553
562
  const AvatarFallback2 = useSlot("AvatarFallback");
554
563
  if (size === "preview" && isImage && previewSrc) {
555
564
  const previewSize = previewRem != null ? { width: `${previewRem}rem`, height: `${previewRem}rem` } : void 0;
556
- return /* @__PURE__ */ jsx22(
565
+ return /* @__PURE__ */ jsx23(
557
566
  "div",
558
567
  {
559
568
  "data-slot": "aui_attachment-preview",
@@ -563,7 +572,7 @@ function AttachmentCard({
563
572
  previewRem == null && "size-24",
564
573
  className
565
574
  ),
566
- children: /* @__PURE__ */ jsx22("img", { src: previewSrc, alt: name, className: "h-full w-full object-cover" })
575
+ children: /* @__PURE__ */ jsx23("img", { src: previewSrc, alt: name, className: "h-full w-full object-cover" })
567
576
  }
568
577
  );
569
578
  }
@@ -577,12 +586,12 @@ function AttachmentCard({
577
586
  className
578
587
  ),
579
588
  children: [
580
- /* @__PURE__ */ jsx22("div", { className: "bg-background flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md border", children: isImage && previewSrc ? /* @__PURE__ */ jsxs8(Avatar2, { className: "size-7 rounded-none", children: [
581
- /* @__PURE__ */ jsx22(AvatarImage2, { src: previewSrc, alt: name, className: "object-cover" }),
582
- /* @__PURE__ */ jsx22(AvatarFallback2, { children: /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) })
583
- ] }) : /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) }),
584
- /* @__PURE__ */ jsx22("span", { className: "text-foreground min-w-0 truncate text-sm", children: name }),
585
- onRemove && /* @__PURE__ */ jsx22(
589
+ /* @__PURE__ */ jsx23("div", { className: "bg-background flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md border", children: isImage && previewSrc ? /* @__PURE__ */ jsxs8(Avatar2, { className: "size-7 rounded-none", children: [
590
+ /* @__PURE__ */ jsx23(AvatarImage2, { src: previewSrc, alt: name, className: "object-cover" }),
591
+ /* @__PURE__ */ jsx23(AvatarFallback2, { children: /* @__PURE__ */ jsx23(FileTextIcon, { className: "text-muted-foreground size-4" }) })
592
+ ] }) : /* @__PURE__ */ jsx23(FileTextIcon, { className: "text-muted-foreground size-4" }) }),
593
+ /* @__PURE__ */ jsx23("span", { className: "text-foreground min-w-0 truncate text-sm", children: name }),
594
+ onRemove && /* @__PURE__ */ jsx23(
586
595
  IconButton5,
587
596
  {
588
597
  icon: "xmark",
@@ -598,9 +607,9 @@ function AttachmentCard({
598
607
 
599
608
  // src/atoms/AttachmentPickerButton.tsx
600
609
  import IconButton from "tfy-web-components/components/atoms/IconButton";
601
- import { jsx as jsx23 } from "react/jsx-runtime";
610
+ import { jsx as jsx24 } from "react/jsx-runtime";
602
611
  function AttachmentPickerButton(props) {
603
- return /* @__PURE__ */ jsx23(
612
+ return /* @__PURE__ */ jsx24(
604
613
  IconButton,
605
614
  {
606
615
  icon: "plus",
@@ -614,13 +623,13 @@ function AttachmentPickerButton(props) {
614
623
  // src/atoms/AttachmentPreviewDialog.tsx
615
624
  import { useState } from "react";
616
625
  import Modal from "tfy-web-components/components/atoms/Modal";
617
- import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
626
+ import { Fragment as Fragment2, jsx as jsx25, jsxs as jsxs9 } from "react/jsx-runtime";
618
627
  function AttachmentPreviewDialog({ previewSrc, children }) {
619
628
  const IconButton5 = useSlot("IconButton");
620
629
  const [open, setOpen] = useState(false);
621
- if (!previewSrc) return /* @__PURE__ */ jsx24(Fragment2, { children });
630
+ if (!previewSrc) return /* @__PURE__ */ jsx25(Fragment2, { children });
622
631
  return /* @__PURE__ */ jsxs9(Fragment2, { children: [
623
- /* @__PURE__ */ jsx24(
632
+ /* @__PURE__ */ jsx25(
624
633
  "div",
625
634
  {
626
635
  role: "button",
@@ -636,9 +645,9 @@ function AttachmentPreviewDialog({ previewSrc, children }) {
636
645
  children
637
646
  }
638
647
  ),
639
- /* @__PURE__ */ jsx24(Modal, { open, onClose: () => setOpen(false), children: /* @__PURE__ */ jsxs9("div", { className: "bg-popover fixed top-1/2 left-1/2 z-50 w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl p-2 outline-none sm:max-w-3xl", children: [
640
- /* @__PURE__ */ jsx24("span", { className: "absolute top-2 right-2 z-10 inline-flex", children: /* @__PURE__ */ jsx24(IconButton5, { icon: "xmark", tooltip: "Close", onClick: () => setOpen(false) }) }),
641
- /* @__PURE__ */ jsx24("div", { className: "bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden", children: /* @__PURE__ */ jsx24(
648
+ /* @__PURE__ */ jsx25(Modal, { open, onClose: () => setOpen(false), children: /* @__PURE__ */ jsxs9("div", { className: "bg-popover fixed top-1/2 left-1/2 z-50 w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl p-2 outline-none sm:max-w-3xl", children: [
649
+ /* @__PURE__ */ jsx25("span", { className: "absolute top-2 right-2 z-10 inline-flex", children: /* @__PURE__ */ jsx25(IconButton5, { icon: "xmark", tooltip: "Close", onClick: () => setOpen(false) }) }),
650
+ /* @__PURE__ */ jsx25("div", { className: "bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden", children: /* @__PURE__ */ jsx25(
642
651
  "img",
643
652
  {
644
653
  src: previewSrc,
@@ -653,16 +662,16 @@ function AttachmentPreviewDialog({ previewSrc, children }) {
653
662
  // src/atoms/ScrollToBottomButton.tsx
654
663
  import { forwardRef as forwardRef2 } from "react";
655
664
  import IconButton2 from "tfy-web-components/components/atoms/IconButton";
656
- import { jsx as jsx25 } from "react/jsx-runtime";
665
+ import { jsx as jsx26 } from "react/jsx-runtime";
657
666
  var ScrollToBottomButton = forwardRef2(
658
667
  ({ className, disabled, ...rest }, ref) => {
659
668
  if (disabled) return null;
660
- return /* @__PURE__ */ jsx25(
669
+ return /* @__PURE__ */ jsx26(
661
670
  "span",
662
671
  {
663
672
  ref,
664
673
  className: cn("absolute -top-14 z-10 inline-flex self-center"),
665
- children: /* @__PURE__ */ jsx25(
674
+ children: /* @__PURE__ */ jsx26(
666
675
  IconButton2,
667
676
  {
668
677
  icon: "arrow-down",
@@ -685,7 +694,7 @@ ScrollToBottomButton.displayName = "ScrollToBottomButton";
685
694
  import IconProvider from "tfy-web-components/components/atoms/IconProvider";
686
695
  import IconButton3 from "tfy-web-components/components/atoms/IconButton";
687
696
  import DropdownMenu from "tfy-web-components/components/molecules/DropdownMenu";
688
- import { jsx as jsx26, jsxs as jsxs10 } from "react/jsx-runtime";
697
+ import { jsx as jsx27, jsxs as jsxs10 } from "react/jsx-runtime";
689
698
  function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }) {
690
699
  return /* @__PURE__ */ jsxs10(
691
700
  "div",
@@ -697,20 +706,20 @@ function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className
697
706
  className
698
707
  ),
699
708
  children: [
700
- /* @__PURE__ */ jsx26(
709
+ /* @__PURE__ */ jsx27(
701
710
  "button",
702
711
  {
703
712
  type: "button",
704
713
  onClick: onSelect,
705
714
  "data-slot": "aui_thread-list-item-trigger",
706
715
  className: "flex min-h-9 min-w-0 flex-1 items-center rounded-lg px-2.5 py-2 text-start text-sm outline-none group-hover:pe-9",
707
- children: /* @__PURE__ */ jsx26("span", { className: "min-w-0 flex-1 truncate", children: title })
716
+ children: /* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate", children: title })
708
717
  }
709
718
  ),
710
- (onArchive || onDelete) && /* @__PURE__ */ jsx26("div", { className: "absolute end-1.5 top-1/2 inline-flex -translate-y-1/2 opacity-0 group-hover:opacity-100", children: /* @__PURE__ */ jsxs10(
719
+ (onArchive || onDelete) && /* @__PURE__ */ jsx27("div", { className: "absolute end-1.5 top-1/2 inline-flex -translate-y-1/2 opacity-0 group-hover:opacity-100", children: /* @__PURE__ */ jsxs10(
711
720
  DropdownMenu,
712
721
  {
713
- trigger: /* @__PURE__ */ jsx26(
722
+ trigger: /* @__PURE__ */ jsx27(
714
723
  IconButton3,
715
724
  {
716
725
  icon: "ellipsis",
@@ -722,11 +731,11 @@ function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className
722
731
  align: "start",
723
732
  children: [
724
733
  onArchive && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onArchive, children: [
725
- /* @__PURE__ */ jsx26(IconProvider, { icon: "box-archive", size: 0.75 }),
734
+ /* @__PURE__ */ jsx27(IconProvider, { icon: "box-archive", size: 0.75 }),
726
735
  "Archive"
727
736
  ] }),
728
737
  onDelete && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onDelete, className: "text-destructive hover:bg-destructive/10", children: [
729
- /* @__PURE__ */ jsx26(IconProvider, { icon: "trash", size: 0.75 }),
738
+ /* @__PURE__ */ jsx27(IconProvider, { icon: "trash", size: 0.75 }),
730
739
  "Delete"
731
740
  ] })
732
741
  ]
@@ -740,9 +749,9 @@ function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className
740
749
  // src/atoms/ThreadListMisc.tsx
741
750
  import Button from "tfy-web-components/components/atoms/Button";
742
751
  import Skeleton2 from "tfy-web-components/components/atoms/Skeleton";
743
- import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
752
+ import { jsx as jsx28, jsxs as jsxs11 } from "react/jsx-runtime";
744
753
  function ThreadListNewButton({ className, ...rest }) {
745
- return /* @__PURE__ */ jsx27(
754
+ return /* @__PURE__ */ jsx28(
746
755
  Button.Ghost,
747
756
  {
748
757
  "data-slot": "aui_thread-list-new",
@@ -754,20 +763,20 @@ function ThreadListNewButton({ className, ...rest }) {
754
763
  );
755
764
  }
756
765
  function ThreadListRowSkeleton({ count = 5, className }) {
757
- return /* @__PURE__ */ jsx27("div", { className: cn("flex flex-col gap-1", className), role: "status", "aria-label": "Loading threads", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx27("div", { className: "flex h-8 items-center px-2.5", children: /* @__PURE__ */ jsx27(Skeleton2, { className: "h-3.5 w-full" }) }, i)) });
766
+ return /* @__PURE__ */ jsx28("div", { className: cn("flex flex-col gap-1", className), role: "status", "aria-label": "Loading threads", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx28("div", { className: "flex h-8 items-center px-2.5", children: /* @__PURE__ */ jsx28(Skeleton2, { className: "h-3.5 w-full" }) }, i)) });
758
767
  }
759
768
  function ThreadListEmptyState({ message = "No threads yet", className }) {
760
- return /* @__PURE__ */ jsx27("div", { className: cn("text-muted-foreground flex flex-1 items-center justify-center px-4 text-center text-sm", className), children: message });
769
+ return /* @__PURE__ */ jsx28("div", { className: cn("text-muted-foreground flex flex-1 items-center justify-center px-4 text-center text-sm", className), children: message });
761
770
  }
762
771
  function ThreadListShell({ header, children, className }) {
763
772
  return /* @__PURE__ */ jsxs11("div", { className: cn("font-sans-flex flex min-h-0 flex-1 flex-col gap-1 overflow-hidden p-3", className), children: [
764
773
  header,
765
- /* @__PURE__ */ jsx27("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
774
+ /* @__PURE__ */ jsx28("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
766
775
  ] });
767
776
  }
768
777
 
769
778
  // src/atoms/MessageActionBar.tsx
770
- import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
779
+ import { jsx as jsx29, jsxs as jsxs12 } from "react/jsx-runtime";
771
780
  function MessageActionBar({ isCopied, onCopy, className }) {
772
781
  const MessageTimestamp2 = useSlot("MessageTimestamp");
773
782
  const IconButton5 = useSlot("IconButton");
@@ -779,8 +788,8 @@ function MessageActionBar({ isCopied, onCopy, className }) {
779
788
  className
780
789
  ),
781
790
  children: [
782
- /* @__PURE__ */ jsx28(MessageTimestamp2, {}),
783
- /* @__PURE__ */ jsx28(
791
+ /* @__PURE__ */ jsx29(MessageTimestamp2, {}),
792
+ /* @__PURE__ */ jsx29(
784
793
  IconButton5,
785
794
  {
786
795
  icon: isCopied ? "check" : ["far", "clone"],
@@ -795,7 +804,7 @@ function MessageActionBar({ isCopied, onCopy, className }) {
795
804
 
796
805
  // src/atoms/Markdown.tsx
797
806
  import { MarkdownWithOpenUI } from "tfy-web-components/components/molecules/Markdown";
798
- import { jsx as jsx29 } from "react/jsx-runtime";
807
+ import { jsx as jsx30 } from "react/jsx-runtime";
799
808
  function Markdown({
800
809
  content,
801
810
  isStreaming,
@@ -805,7 +814,7 @@ function Markdown({
805
814
  className
806
815
  }) {
807
816
  const mode = useThemeMode();
808
- return /* @__PURE__ */ jsx29(
817
+ return /* @__PURE__ */ jsx30(
809
818
  MarkdownWithOpenUI,
810
819
  {
811
820
  isStreaming,
@@ -821,14 +830,14 @@ function Markdown({
821
830
 
822
831
  // src/atoms/AssistantMessageBubble.tsx
823
832
  import { AssistantMessage } from "tfy-web-components/components/molecules/agent-chat";
824
- import { jsx as jsx30 } from "react/jsx-runtime";
833
+ import { jsx as jsx31 } from "react/jsx-runtime";
825
834
  function AssistantMessageBubble({
826
835
  children,
827
836
  error,
828
837
  actionBar,
829
838
  className
830
839
  }) {
831
- return /* @__PURE__ */ jsx30(
840
+ return /* @__PURE__ */ jsx31(
832
841
  "div",
833
842
  {
834
843
  "data-slot": "aui_assistant-message-root",
@@ -836,15 +845,36 @@ function AssistantMessageBubble({
836
845
  "group/assistant fade-in slide-in-from-bottom-1 animate-in relative duration-150",
837
846
  className
838
847
  ),
839
- children: /* @__PURE__ */ jsx30(AssistantMessage, { error, actionBar, children })
848
+ children: /* @__PURE__ */ jsx31(AssistantMessage, { error, actionBar, children })
840
849
  }
841
850
  );
842
851
  }
843
852
 
853
+ // src/atoms/HistoryLoader.tsx
854
+ import { forwardRef as forwardRef3 } from "react";
855
+ import Spinner2 from "tfy-web-components/components/atoms/Spinner";
856
+ import { jsx as jsx32 } from "react/jsx-runtime";
857
+ var HistoryLoader = forwardRef3(
858
+ ({ className, isLoading = false, ...rest }, ref) => /* @__PURE__ */ jsx32(
859
+ "div",
860
+ {
861
+ ref,
862
+ "data-slot": "aui_history-loader",
863
+ role: "status",
864
+ "aria-live": "polite",
865
+ "aria-label": isLoading ? "Loading older messages" : "Scroll up to load older messages",
866
+ className: cn("flex justify-center py-2", className),
867
+ ...rest,
868
+ children: isLoading && /* @__PURE__ */ jsx32(Spinner2, { small: true })
869
+ }
870
+ )
871
+ );
872
+ HistoryLoader.displayName = "HistoryLoader";
873
+
844
874
  // src/atoms/MessageErrorBanner.tsx
845
- import { jsx as jsx31 } from "react/jsx-runtime";
875
+ import { jsx as jsx33 } from "react/jsx-runtime";
846
876
  function MessageErrorBanner({ message, className }) {
847
- return /* @__PURE__ */ jsx31(
877
+ return /* @__PURE__ */ jsx33(
848
878
  "div",
849
879
  {
850
880
  role: "alert",
@@ -852,15 +882,15 @@ function MessageErrorBanner({ message, className }) {
852
882
  "aui-message-error-root border-destructive bg-destructive/10 text-destructive dark:bg-destructive/5 mt-2 rounded-md border p-3 text-sm dark:text-red-200",
853
883
  className
854
884
  ),
855
- children: /* @__PURE__ */ jsx31("span", { className: "aui-message-error-message line-clamp-2", children: message })
885
+ children: /* @__PURE__ */ jsx33("span", { className: "aui-message-error-message line-clamp-2", children: message })
856
886
  }
857
887
  );
858
888
  }
859
889
 
860
890
  // src/atoms/MessageIndicator.tsx
861
- import { jsx as jsx32 } from "react/jsx-runtime";
891
+ import { jsx as jsx34 } from "react/jsx-runtime";
862
892
  function MessageIndicator({ className }) {
863
- return /* @__PURE__ */ jsx32(
893
+ return /* @__PURE__ */ jsx34(
864
894
  "span",
865
895
  {
866
896
  "data-slot": "aui_assistant-message-indicator",
@@ -873,7 +903,7 @@ function MessageIndicator({ className }) {
873
903
 
874
904
  // src/atoms/MessageTimestamp.tsx
875
905
  import { useAuiState } from "@assistant-ui/react";
876
- import { jsx as jsx33 } from "react/jsx-runtime";
906
+ import { jsx as jsx35 } from "react/jsx-runtime";
877
907
  function toDate(createdAt) {
878
908
  if (createdAt == null) {
879
909
  return null;
@@ -906,7 +936,7 @@ function MessageTimestamp({ className }) {
906
936
  if (date == null) {
907
937
  return null;
908
938
  }
909
- return /* @__PURE__ */ jsx33(LightTooltip3, { title: formatFullDate(date), size: "fit", children: /* @__PURE__ */ jsx33(
939
+ return /* @__PURE__ */ jsx35(LightTooltip3, { title: formatFullDate(date), size: "fit", children: /* @__PURE__ */ jsx35(
910
940
  "span",
911
941
  {
912
942
  className: cn(
@@ -922,7 +952,7 @@ function MessageTimestamp({ className }) {
922
952
  import { ActionBarPrimitive, useAuiState as useAuiState2 } from "@assistant-ui/react";
923
953
  import { useActionBarCopy, useActionBarEdit } from "@assistant-ui/core/react";
924
954
  import { useTrueFoundryResetFromTurn } from "@truefoundry/assistant-ui-runtime";
925
- import { jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
955
+ import { jsx as jsx36, jsxs as jsxs13 } from "react/jsx-runtime";
926
956
  function parseTurnIdFromMessageId(messageId) {
927
957
  return messageId.replace(/-user$/, "");
928
958
  }
@@ -945,7 +975,7 @@ function UserMessageActionBar({ className }) {
945
975
  className
946
976
  ),
947
977
  children: [
948
- /* @__PURE__ */ jsx34(
978
+ /* @__PURE__ */ jsx36(
949
979
  IconButton5,
950
980
  {
951
981
  icon: "rotate-right",
@@ -953,7 +983,7 @@ function UserMessageActionBar({ className }) {
953
983
  onClick: () => void resetFromTurn(turnId)
954
984
  }
955
985
  ),
956
- /* @__PURE__ */ jsx34(
986
+ /* @__PURE__ */ jsx36(
957
987
  IconButton5,
958
988
  {
959
989
  icon: "pencil",
@@ -962,7 +992,7 @@ function UserMessageActionBar({ className }) {
962
992
  onClick: edit
963
993
  }
964
994
  ),
965
- /* @__PURE__ */ jsx34(
995
+ /* @__PURE__ */ jsx36(
966
996
  IconButton5,
967
997
  {
968
998
  icon: isCopied ? "check" : ["far", "clone"],
@@ -970,23 +1000,23 @@ function UserMessageActionBar({ className }) {
970
1000
  onClick: copy
971
1001
  }
972
1002
  ),
973
- /* @__PURE__ */ jsx34(MessageTimestamp2, {})
1003
+ /* @__PURE__ */ jsx36(MessageTimestamp2, {})
974
1004
  ]
975
1005
  }
976
1006
  );
977
1007
  }
978
1008
 
979
1009
  // src/atoms/ThreadShell.tsx
980
- import { forwardRef as forwardRef3 } from "react";
981
- import { jsx as jsx35 } from "react/jsx-runtime";
1010
+ import { forwardRef as forwardRef4 } from "react";
1011
+ import { jsx as jsx37 } from "react/jsx-runtime";
982
1012
  var THREAD_CSS_VARS = {
983
1013
  ["--thread-max-width"]: "44rem",
984
1014
  ["--composer-bg"]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
985
1015
  ["--composer-radius"]: "1.5rem",
986
1016
  ["--composer-padding"]: "8px"
987
1017
  };
988
- var ThreadRootShell = forwardRef3(
989
- ({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx35(
1018
+ var ThreadRootShell = forwardRef4(
1019
+ ({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx37(
990
1020
  "div",
991
1021
  {
992
1022
  ref,
@@ -1000,15 +1030,15 @@ var ThreadRootShell = forwardRef3(
1000
1030
  )
1001
1031
  );
1002
1032
  ThreadRootShell.displayName = "ThreadRootShell";
1003
- var ThreadViewportShell = forwardRef3(
1004
- ({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx35(
1033
+ var ThreadViewportShell = forwardRef4(
1034
+ ({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx37(
1005
1035
  "div",
1006
1036
  {
1007
1037
  ref,
1008
1038
  "data-slot": "aui_thread-viewport",
1009
1039
  className: cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className),
1010
1040
  ...rest,
1011
- children: /* @__PURE__ */ jsx35(
1041
+ children: /* @__PURE__ */ jsx37(
1012
1042
  "div",
1013
1043
  {
1014
1044
  className: cn(
@@ -1022,8 +1052,8 @@ var ThreadViewportShell = forwardRef3(
1022
1052
  )
1023
1053
  );
1024
1054
  ThreadViewportShell.displayName = "ThreadViewportShell";
1025
- var ThreadComposerAreaShell = forwardRef3(
1026
- ({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx35(
1055
+ var ThreadComposerAreaShell = forwardRef4(
1056
+ ({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx37(
1027
1057
  "div",
1028
1058
  {
1029
1059
  ref,
@@ -1038,7 +1068,7 @@ var ThreadComposerAreaShell = forwardRef3(
1038
1068
  )
1039
1069
  );
1040
1070
  ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
1041
- var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */ jsx35(
1071
+ var MessageGroup = forwardRef4(({ className, ...rest }, ref) => /* @__PURE__ */ jsx37(
1042
1072
  "div",
1043
1073
  {
1044
1074
  ref,
@@ -1050,14 +1080,14 @@ var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */
1050
1080
  MessageGroup.displayName = "MessageGroup";
1051
1081
 
1052
1082
  // src/atoms/WelcomeScreen.tsx
1053
- import { jsx as jsx36 } from "react/jsx-runtime";
1083
+ import { jsx as jsx38 } from "react/jsx-runtime";
1054
1084
  function WelcomeScreen({ heading = "How can I help you today?", className }) {
1055
- return /* @__PURE__ */ jsx36("div", { className: cn("aui-thread-welcome-root mb-6 flex flex-col items-center px-4 text-center", className), children: /* @__PURE__ */ jsx36("h1", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-2xl font-semibold duration-200", children: heading }) });
1085
+ return /* @__PURE__ */ jsx38("div", { className: cn("aui-thread-welcome-root mb-6 flex flex-col items-center px-4 text-center", className), children: /* @__PURE__ */ jsx38("h1", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-2xl font-semibold duration-200", children: heading }) });
1056
1086
  }
1057
1087
 
1058
1088
  // src/atoms/Toast.tsx
1059
1089
  import { XIcon } from "lucide-react";
1060
- import { jsx as jsx37, jsxs as jsxs14 } from "react/jsx-runtime";
1090
+ import { jsx as jsx39, jsxs as jsxs14 } from "react/jsx-runtime";
1061
1091
  function Toast({ title, description, open, onOpenChange, className }) {
1062
1092
  if (!open) return null;
1063
1093
  return /* @__PURE__ */ jsxs14(
@@ -1070,8 +1100,8 @@ function Toast({ title, description, open, onOpenChange, className }) {
1070
1100
  ),
1071
1101
  children: [
1072
1102
  /* @__PURE__ */ jsxs14("div", { className: "grid min-h-0 min-w-0 flex-1 gap-1 overflow-y-auto pe-6", children: [
1073
- /* @__PURE__ */ jsx37("div", { className: "text-sm leading-none font-semibold", children: title }),
1074
- /* @__PURE__ */ jsx37("div", { className: "font-mono text-sm break-words whitespace-pre-wrap", children: description })
1103
+ /* @__PURE__ */ jsx39("div", { className: "text-sm leading-none font-semibold", children: title }),
1104
+ /* @__PURE__ */ jsx39("div", { className: "font-mono text-sm break-words whitespace-pre-wrap", children: description })
1075
1105
  ] }),
1076
1106
  /* @__PURE__ */ jsxs14(
1077
1107
  "button",
@@ -1079,8 +1109,8 @@ function Toast({ title, description, open, onOpenChange, className }) {
1079
1109
  onClick: () => onOpenChange(false),
1080
1110
  className: "text-destructive hover:bg-muted focus-visible:ring-ring absolute top-3 right-3 rounded-md p-1 transition-colors focus:outline-none focus-visible:ring-2",
1081
1111
  children: [
1082
- /* @__PURE__ */ jsx37(XIcon, { className: "size-4" }),
1083
- /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "Close" })
1112
+ /* @__PURE__ */ jsx39(XIcon, { className: "size-4" }),
1113
+ /* @__PURE__ */ jsx39("span", { className: "sr-only", children: "Close" })
1084
1114
  ]
1085
1115
  }
1086
1116
  )
@@ -1089,7 +1119,7 @@ function Toast({ title, description, open, onOpenChange, className }) {
1089
1119
  );
1090
1120
  }
1091
1121
  function ToastStack({ children, duration = Number.POSITIVE_INFINITY }) {
1092
- return /* @__PURE__ */ jsx37("div", { className: "pointer-events-none fixed bottom-4 left-1/2 z-50 flex h-full max-h-screen w-full max-w-2xl -translate-x-1/2 flex-col-reverse gap-2 px-4", children });
1122
+ return /* @__PURE__ */ jsx39("div", { className: "pointer-events-none fixed bottom-4 left-1/2 z-50 flex h-full max-h-screen w-full max-w-2xl -translate-x-1/2 flex-col-reverse gap-2 px-4", children });
1093
1123
  }
1094
1124
 
1095
1125
  // src/theme/defaultSlots.ts
@@ -1119,6 +1149,7 @@ var defaultSlots = {
1119
1149
  SandboxToolCallCard,
1120
1150
  ToolApprovalBar,
1121
1151
  ToolGroupCard,
1152
+ AgentStepsCard,
1122
1153
  MessageListSkeleton,
1123
1154
  ComposerShell,
1124
1155
  ComposerLeftSection,
@@ -1137,6 +1168,7 @@ var defaultSlots = {
1137
1168
  Markdown,
1138
1169
  // SDK atoms — SDK-owned (no tfy slot component)
1139
1170
  AssistantMessageBubble,
1171
+ HistoryLoader,
1140
1172
  MessageErrorBanner,
1141
1173
  MessageTimestamp,
1142
1174
  UserMessageActionBar,
@@ -1151,7 +1183,7 @@ var defaultSlots = {
1151
1183
  };
1152
1184
 
1153
1185
  // src/theme/SlotsProvider.tsx
1154
- import { jsx as jsx38 } from "react/jsx-runtime";
1186
+ import { jsx as jsx40 } from "react/jsx-runtime";
1155
1187
  var SlotsContext = createContext(defaultSlots);
1156
1188
  var ThemeModeContext = createContext(void 0);
1157
1189
  function SlotsProvider({
@@ -1165,14 +1197,14 @@ function SlotsProvider({
1165
1197
  () => ({ ...parentSlots, ...overrides }),
1166
1198
  [parentSlots, overrides]
1167
1199
  );
1168
- return /* @__PURE__ */ jsx38(TfyThemeProvider, { theme: theme ?? inheritedTheme, children: /* @__PURE__ */ jsx38(SlotsProviderContents, { slots: resolved, children }) });
1200
+ return /* @__PURE__ */ jsx40(TfyThemeProvider, { theme: theme ?? inheritedTheme, children: /* @__PURE__ */ jsx40(SlotsProviderContents, { slots: resolved, children }) });
1169
1201
  }
1170
1202
  function SlotsProviderContents({
1171
1203
  slots,
1172
1204
  children
1173
1205
  }) {
1174
1206
  const { mode } = useTfyTheme();
1175
- return /* @__PURE__ */ jsx38(ThemeModeContext.Provider, { value: mode, children: /* @__PURE__ */ jsx38(SlotsContext.Provider, { value: slots, children }) });
1207
+ return /* @__PURE__ */ jsx40(ThemeModeContext.Provider, { value: mode, children: /* @__PURE__ */ jsx40(SlotsContext.Provider, { value: slots, children }) });
1176
1208
  }
1177
1209
  function useSlot(name) {
1178
1210
  const slots = useContext(SlotsContext);
@@ -1259,7 +1291,7 @@ import {
1259
1291
  import { default as default6 } from "tfy-web-components/components/atoms/Skeleton";
1260
1292
 
1261
1293
  // src/containers/ThreadContainer.tsx
1262
- import { useEffect as useEffect4 } from "react";
1294
+ import { useEffect as useEffect6 } from "react";
1263
1295
  import { preloadMarkdownOpenUI } from "tfy-web-components/components/molecules/Markdown";
1264
1296
  import { ThreadPrimitive, useAuiState as useAuiState11 } from "@assistant-ui/react";
1265
1297
 
@@ -1307,9 +1339,51 @@ function useComposerBusyState() {
1307
1339
  }
1308
1340
 
1309
1341
  // src/containers/AssistantMessageContainer.tsx
1310
- import { groupPartByType, MessagePrimitive as MessagePrimitive2 } from "@assistant-ui/react";
1342
+ import { MessagePrimitive as MessagePrimitive2, useAuiState as useAuiState6 } from "@assistant-ui/react";
1311
1343
  import { useActionBarCopy as useActionBarCopy2, useMessageError, useThreadIsRunning as useThreadIsRunning2 } from "@assistant-ui/core/react";
1312
1344
 
1345
+ // src/utils/computeAgentStepsSplit.ts
1346
+ function computeAgentStepsSplit(parts, isRunning) {
1347
+ const finalTexts = [];
1348
+ let cutIdx = parts.length;
1349
+ for (let i = parts.length - 1; i >= 0; i--) {
1350
+ const part = parts[i];
1351
+ if (!part) continue;
1352
+ if (part.type === "text") {
1353
+ const text = part.text ?? "";
1354
+ const trimmed = text.trim();
1355
+ if (trimmed) {
1356
+ finalTexts.unshift({ index: i, content: text });
1357
+ cutIdx = i;
1358
+ } else {
1359
+ cutIdx = i;
1360
+ }
1361
+ } else {
1362
+ break;
1363
+ }
1364
+ }
1365
+ const trailingChars = finalTexts.reduce((sum, t) => sum + t.content.length, 0);
1366
+ const finalConfirmed = finalTexts.length > 0 && (!isRunning || trailingChars >= 500);
1367
+ const actualCutIndex = finalConfirmed ? cutIdx : parts.length;
1368
+ let toolCount = 0;
1369
+ let thinkingCount = 0;
1370
+ for (let i = 0; i < actualCutIndex; i++) {
1371
+ const part = parts[i];
1372
+ if (!part) continue;
1373
+ if (part.type === "tool-call") {
1374
+ toolCount++;
1375
+ } else if (part.type === "reasoning") {
1376
+ thinkingCount++;
1377
+ }
1378
+ }
1379
+ return {
1380
+ cutIndex: actualCutIndex,
1381
+ hasFinal: finalConfirmed,
1382
+ toolCount,
1383
+ thinkingCount
1384
+ };
1385
+ }
1386
+
1313
1387
  // src/containers/AssistantTextContainer.tsx
1314
1388
  import { useCallback as useCallback3 } from "react";
1315
1389
  import { useAuiState as useAuiState3 } from "@assistant-ui/react";
@@ -1318,7 +1392,7 @@ import { useTrueFoundryDownloadSandboxFile } from "@truefoundry/assistant-ui-run
1318
1392
  // src/containers/ErrorToasterContainer.tsx
1319
1393
  import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo2, useState as useState3 } from "react";
1320
1394
  import { TrueFoundryGatewayError } from "truefoundry-gateway-sdk";
1321
- import { jsx as jsx39, jsxs as jsxs15 } from "react/jsx-runtime";
1395
+ import { jsx as jsx41, jsxs as jsxs15 } from "react/jsx-runtime";
1322
1396
  var ErrorToasterContext = createContext4(null);
1323
1397
  function formatErrorBody(body) {
1324
1398
  if (body == null) return void 0;
@@ -1353,7 +1427,7 @@ function ErrorToasterProvider({ children }) {
1353
1427
  const value = useMemo2(() => ({ showError }), [showError]);
1354
1428
  return /* @__PURE__ */ jsxs15(ErrorToasterContext.Provider, { value, children: [
1355
1429
  children,
1356
- /* @__PURE__ */ jsx39(ToastStack2, { children: toast != null && /* @__PURE__ */ jsx39(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen }) })
1430
+ /* @__PURE__ */ jsx41(ToastStack2, { children: toast != null && /* @__PURE__ */ jsx41(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen }) })
1357
1431
  ] });
1358
1432
  }
1359
1433
  function useErrorToaster() {
@@ -1368,7 +1442,7 @@ function useErrorToasterOptional() {
1368
1442
  }
1369
1443
 
1370
1444
  // src/containers/AssistantTextContainer.tsx
1371
- import { jsx as jsx40 } from "react/jsx-runtime";
1445
+ import { jsx as jsx42 } from "react/jsx-runtime";
1372
1446
  function filenameFromPath(path) {
1373
1447
  return path.split("/").pop() || "download";
1374
1448
  }
@@ -1405,12 +1479,12 @@ function AssistantTextContainer() {
1405
1479
  }),
1406
1480
  [downloadSandboxFile, errorToaster]
1407
1481
  );
1408
- return /* @__PURE__ */ jsx40(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1482
+ return /* @__PURE__ */ jsx42(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1409
1483
  }
1410
1484
 
1411
1485
  // src/containers/MessageImageContainer.tsx
1412
1486
  import { useAuiState as useAuiState4 } from "@assistant-ui/react";
1413
- import { jsx as jsx41 } from "react/jsx-runtime";
1487
+ import { jsx as jsx43 } from "react/jsx-runtime";
1414
1488
  function MessageImageContainer() {
1415
1489
  const AttachmentCard2 = useSlot("AttachmentCard");
1416
1490
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
@@ -1421,7 +1495,7 @@ function MessageImageContainer() {
1421
1495
  if (!image) {
1422
1496
  return null;
1423
1497
  }
1424
- const card = /* @__PURE__ */ jsx41(
1498
+ const card = /* @__PURE__ */ jsx43(
1425
1499
  AttachmentCard2,
1426
1500
  {
1427
1501
  name: filename ?? "image",
@@ -1431,13 +1505,13 @@ function MessageImageContainer() {
1431
1505
  previewRem: USER_MESSAGE_ATTACHMENT_PREVIEW_REM
1432
1506
  }
1433
1507
  );
1434
- return /* @__PURE__ */ jsx41(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx41("div", { className: "aui-message-image", children: card }) });
1508
+ return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx43("div", { className: "aui-message-image", children: card }) });
1435
1509
  }
1436
1510
 
1437
1511
  // src/containers/ReasoningContainer.tsx
1438
1512
  import { useCallback as useCallback4, useRef, useState as useState4 } from "react";
1439
1513
  import { useAuiState as useAuiState5 } from "@assistant-ui/react";
1440
- import { jsx as jsx42 } from "react/jsx-runtime";
1514
+ import { jsx as jsx44 } from "react/jsx-runtime";
1441
1515
  function ReasoningContainer({ group }) {
1442
1516
  const ReasoningCard2 = useSlot("ReasoningCard");
1443
1517
  const content = useAuiState5(
@@ -1477,8 +1551,8 @@ function ReasoningContainer({ group }) {
1477
1551
  const reasoningTimeText = null;
1478
1552
  const previewText = content.replace(/\s+/g, " ").trim();
1479
1553
  const isShortText = !streaming && content.length > 0 && !isMultiLine;
1480
- const headingText = streaming && !content ? expanded ? "Reasoning" : "Show Reasoning" : reasoningTimeText ?? (expanded ? "Hide Reasoning" : "Show Reasoning");
1481
- return /* @__PURE__ */ jsx42(
1554
+ const headingText = "Reasoning";
1555
+ return /* @__PURE__ */ jsx44(
1482
1556
  ReasoningCard2,
1483
1557
  {
1484
1558
  content,
@@ -1514,7 +1588,7 @@ function useNestedApprovalBridge() {
1514
1588
 
1515
1589
  // src/containers/SandboxToolCallContainer.tsx
1516
1590
  import { useMemo as useMemo3, useState as useState5 } from "react";
1517
- import { jsx as jsx43 } from "react/jsx-runtime";
1591
+ import { jsx as jsx45 } from "react/jsx-runtime";
1518
1592
  function SandboxToolCallContainer(props) {
1519
1593
  const SandboxToolCallCard2 = useSlot("SandboxToolCallCard");
1520
1594
  const [viewMode, setViewMode] = useState5("terminal");
@@ -1528,7 +1602,7 @@ function SandboxToolCallContainer(props) {
1528
1602
  props.resultText,
1529
1603
  viewMode
1530
1604
  ]);
1531
- return /* @__PURE__ */ jsx43(
1605
+ return /* @__PURE__ */ jsx45(
1532
1606
  SandboxToolCallCard2,
1533
1607
  {
1534
1608
  ...props,
@@ -1541,7 +1615,7 @@ function SandboxToolCallContainer(props) {
1541
1615
 
1542
1616
  // src/containers/ToolApprovalContainer.tsx
1543
1617
  import { useCallback as useCallback5, useMemo as useMemo4, useState as useState6 } from "react";
1544
- import { jsx as jsx44 } from "react/jsx-runtime";
1618
+ import { jsx as jsx46 } from "react/jsx-runtime";
1545
1619
  function ToolApprovalContainer({
1546
1620
  toolName = "",
1547
1621
  options,
@@ -1590,7 +1664,7 @@ function ToolApprovalContainer({
1590
1664
  onDenyOptionChange(null);
1591
1665
  }
1592
1666
  }, [denialReason, onDenyOptionChange, onSelectOption, selectedDenyOptionId]);
1593
- return /* @__PURE__ */ jsx44(
1667
+ return /* @__PURE__ */ jsx46(
1594
1668
  ToolApprovalBar2,
1595
1669
  {
1596
1670
  toolName,
@@ -1609,7 +1683,7 @@ function ToolApprovalContainer({
1609
1683
 
1610
1684
  // src/containers/ToolCallContentBlockContainer.tsx
1611
1685
  import { useCallback as useCallback6, useEffect as useEffect2, useRef as useRef2, useState as useState7 } from "react";
1612
- import { jsx as jsx45 } from "react/jsx-runtime";
1686
+ import { jsx as jsx47 } from "react/jsx-runtime";
1613
1687
  function ToolCallContentBlockContainer(props) {
1614
1688
  const ToolCallContentBlock2 = useSlot("ToolCallContentBlock");
1615
1689
  const [fullscreen, setFullscreen] = useState7(false);
@@ -1633,7 +1707,7 @@ function ToolCallContentBlockContainer(props) {
1633
1707
  },
1634
1708
  []
1635
1709
  );
1636
- return /* @__PURE__ */ jsx45(
1710
+ return /* @__PURE__ */ jsx47(
1637
1711
  ToolCallContentBlock2,
1638
1712
  {
1639
1713
  ...props,
@@ -1646,12 +1720,12 @@ function ToolCallContentBlockContainer(props) {
1646
1720
  }
1647
1721
 
1648
1722
  // src/containers/ToolCallContainer.tsx
1649
- import { jsx as jsx46 } from "react/jsx-runtime";
1723
+ import { jsx as jsx48 } from "react/jsx-runtime";
1650
1724
  var SUB_AGENT_TOOL_NAME = "create_sub_agent";
1651
1725
  var ASK_USER_TOOL_NAME = "ask_user_question";
1652
1726
  function NestedSubAgentAssistantMessage() {
1653
1727
  const AssistantMessageBubble2 = useSlot("AssistantMessageBubble");
1654
- return /* @__PURE__ */ jsx46("div", { className: "mb-3 min-w-0", children: /* @__PURE__ */ jsx46(MessagePrimitive.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx46(AssistantMessageBubble2, { children: /* @__PURE__ */ jsx46(
1728
+ return /* @__PURE__ */ jsx48("div", { className: "mb-3 min-w-0", children: /* @__PURE__ */ jsx48(MessagePrimitive.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx48(AssistantMessageBubble2, { children: /* @__PURE__ */ jsx48(
1655
1729
  MessagePrimitive.Parts,
1656
1730
  {
1657
1731
  components: {
@@ -1831,7 +1905,7 @@ function ToolApprovalSlot({ part }) {
1831
1905
  if (optionId === "__deny") return respond({ approved: false, reason });
1832
1906
  return respond({ optionId, reason });
1833
1907
  };
1834
- return /* @__PURE__ */ jsx46(
1908
+ return /* @__PURE__ */ jsx48(
1835
1909
  ToolApprovalContainer,
1836
1910
  {
1837
1911
  toolName: part.toolName,
@@ -1849,7 +1923,7 @@ var ToolCallContainer = (part) => {
1849
1923
  const isRequiresAction = part.status?.type === "requires-action";
1850
1924
  const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
1851
1925
  const isSandbox = SANDBOX_TOOL_NAMES.has(part.toolName);
1852
- const [expanded, setExpanded] = useState8(isRequiresAction || isSubAgent);
1926
+ const [expanded, setExpanded] = useState8(isRequiresAction);
1853
1927
  const [prevRequiresAction, setPrevRequiresAction] = useState8(isRequiresAction);
1854
1928
  if (isRequiresAction !== prevRequiresAction) {
1855
1929
  setPrevRequiresAction(isRequiresAction);
@@ -1868,7 +1942,7 @@ var ToolCallContainer = (part) => {
1868
1942
  }
1869
1943
  const { question, options = [] } = parseAskUserQuestionArgs(part.argsText);
1870
1944
  const isCustom = options.length > 0 && !options.includes(answer);
1871
- return /* @__PURE__ */ jsx46(
1945
+ return /* @__PURE__ */ jsx48(
1872
1946
  AskUserPrompt2,
1873
1947
  {
1874
1948
  questions: [],
@@ -1900,13 +1974,13 @@ var ToolCallContainer = (part) => {
1900
1974
  if (approved === void 0) return;
1901
1975
  respondToNestedApproval({ approvalId: part.approval.id, approved });
1902
1976
  };
1903
- return /* @__PURE__ */ jsx46(
1977
+ return /* @__PURE__ */ jsx48(
1904
1978
  "div",
1905
1979
  {
1906
1980
  "data-slot": "tool-call-card",
1907
1981
  "data-variant": "sub-agent",
1908
- className: "w-full py-2",
1909
- children: /* @__PURE__ */ jsx46(
1982
+ className: "w-full",
1983
+ children: /* @__PURE__ */ jsx48(
1910
1984
  SubAgentCard2,
1911
1985
  {
1912
1986
  status,
@@ -1916,7 +1990,7 @@ var ToolCallContainer = (part) => {
1916
1990
  agentName,
1917
1991
  instruction,
1918
1992
  stepCount,
1919
- children: /* @__PURE__ */ jsx46(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx46(
1993
+ children: /* @__PURE__ */ jsx48(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx48(
1920
1994
  MessagePartPrimitive.Messages,
1921
1995
  {
1922
1996
  components: {
@@ -1934,7 +2008,7 @@ var ToolCallContainer = (part) => {
1934
2008
  if (isSandbox) {
1935
2009
  const { command, intent, argsJson } = parseSandboxArgs(part.argsText);
1936
2010
  const { exitCode, resultText, resultJson } = parseSandboxResult(resultString);
1937
- return /* @__PURE__ */ jsx46(
2011
+ return /* @__PURE__ */ jsx48(
1938
2012
  SandboxToolCallContainer,
1939
2013
  {
1940
2014
  name: part.toolName,
@@ -1957,7 +2031,7 @@ var ToolCallContainer = (part) => {
1957
2031
  const argsDisplay2 = getJsonDisplayValue(part.argsText);
1958
2032
  const resultDisplay2 = getToolResultContent(part.result);
1959
2033
  if (part.toolName === "list_tools" && mcpServer) {
1960
- return /* @__PURE__ */ jsx46(
2034
+ return /* @__PURE__ */ jsx48(
1961
2035
  ToolCallCard2,
1962
2036
  {
1963
2037
  toolName: `Listing tools \xB7 ${mcpServer}`,
@@ -1968,7 +2042,7 @@ var ToolCallContainer = (part) => {
1968
2042
  awaitingText: durationText ?? "Awaiting Response\u2026",
1969
2043
  showResponseLine: status !== "running" && !!resultDisplay2.data,
1970
2044
  mcpServerName: mcpServer,
1971
- requestSlot: argsDisplay2.value ? /* @__PURE__ */ jsx46(
2045
+ requestSlot: argsDisplay2.value ? /* @__PURE__ */ jsx48(
1972
2046
  ToolCallContentBlockContainer,
1973
2047
  {
1974
2048
  title: "Request",
@@ -1976,7 +2050,7 @@ var ToolCallContainer = (part) => {
1976
2050
  isJson: argsDisplay2.isJson,
1977
2051
  maxHeight: "10.5rem"
1978
2052
  }
1979
- ) : resultDisplay2.data ? /* @__PURE__ */ jsx46(
2053
+ ) : resultDisplay2.data ? /* @__PURE__ */ jsx48(
1980
2054
  ToolCallContentBlockContainer,
1981
2055
  {
1982
2056
  title: "Request",
@@ -1985,7 +2059,7 @@ var ToolCallContainer = (part) => {
1985
2059
  maxHeight: "10.5rem"
1986
2060
  }
1987
2061
  ) : void 0,
1988
- responseSlot: resultDisplay2.data ? /* @__PURE__ */ jsx46(
2062
+ responseSlot: resultDisplay2.data ? /* @__PURE__ */ jsx48(
1989
2063
  ToolCallContentBlockContainer,
1990
2064
  {
1991
2065
  title: "Response",
@@ -2004,7 +2078,7 @@ var ToolCallContainer = (part) => {
2004
2078
  displayName = `get_tool_info: ${innerToolName} (${mcpServer})`;
2005
2079
  }
2006
2080
  const inputDisplay = input !== void 0 ? getJsonDisplayValue(JSON.stringify(input, null, 2)) : argsDisplay2;
2007
- return /* @__PURE__ */ jsx46(
2081
+ return /* @__PURE__ */ jsx48(
2008
2082
  ToolCallCard2,
2009
2083
  {
2010
2084
  toolName: displayName,
@@ -2015,7 +2089,7 @@ var ToolCallContainer = (part) => {
2015
2089
  awaitingText: durationText ?? "Awaiting Response\u2026",
2016
2090
  showResponseLine: status !== "running" && resultDisplay2.data !== void 0,
2017
2091
  mcpServerName: mcpServer,
2018
- requestSlot: inputDisplay.value ? /* @__PURE__ */ jsx46(
2092
+ requestSlot: inputDisplay.value ? /* @__PURE__ */ jsx48(
2019
2093
  ToolCallContentBlockContainer,
2020
2094
  {
2021
2095
  title: "Request",
@@ -2023,7 +2097,7 @@ var ToolCallContainer = (part) => {
2023
2097
  isJson: inputDisplay.isJson,
2024
2098
  maxHeight: "10.5rem"
2025
2099
  }
2026
- ) : resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2100
+ ) : resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx48(
2027
2101
  ToolCallContentBlockContainer,
2028
2102
  {
2029
2103
  title: "Request",
@@ -2032,7 +2106,7 @@ var ToolCallContainer = (part) => {
2032
2106
  maxHeight: "10.5rem"
2033
2107
  }
2034
2108
  ) : void 0,
2035
- responseSlot: resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2109
+ responseSlot: resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx48(
2036
2110
  ToolCallContentBlockContainer,
2037
2111
  {
2038
2112
  title: "Response",
@@ -2041,13 +2115,13 @@ var ToolCallContainer = (part) => {
2041
2115
  resizable: true
2042
2116
  }
2043
2117
  ) : void 0,
2044
- approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2118
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx48(ToolApprovalSlot, { part }) : void 0
2045
2119
  }
2046
2120
  );
2047
2121
  }
2048
2122
  const argsDisplay = getJsonDisplayValue(part.argsText);
2049
2123
  const resultDisplay = getToolResultContent(part.result);
2050
- return /* @__PURE__ */ jsx46(
2124
+ return /* @__PURE__ */ jsx48(
2051
2125
  ToolCallCard2,
2052
2126
  {
2053
2127
  toolName: part.toolName,
@@ -2056,7 +2130,7 @@ var ToolCallContainer = (part) => {
2056
2130
  awaiting: status === "running",
2057
2131
  awaitingText: durationText ?? "Awaiting Response\u2026",
2058
2132
  showResponseLine: status !== "running" && resultDisplay.data !== void 0,
2059
- requestSlot: argsDisplay.value ? /* @__PURE__ */ jsx46(
2133
+ requestSlot: argsDisplay.value ? /* @__PURE__ */ jsx48(
2060
2134
  ToolCallContentBlockContainer,
2061
2135
  {
2062
2136
  title: "Request",
@@ -2064,7 +2138,7 @@ var ToolCallContainer = (part) => {
2064
2138
  isJson: argsDisplay.isJson,
2065
2139
  maxHeight: "10.5rem"
2066
2140
  }
2067
- ) : resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2141
+ ) : resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx48(
2068
2142
  ToolCallContentBlockContainer,
2069
2143
  {
2070
2144
  title: "Request",
@@ -2073,7 +2147,7 @@ var ToolCallContainer = (part) => {
2073
2147
  maxHeight: "10.5rem"
2074
2148
  }
2075
2149
  ) : void 0,
2076
- responseSlot: resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2150
+ responseSlot: resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx48(
2077
2151
  ToolCallContentBlockContainer,
2078
2152
  {
2079
2153
  title: "Response",
@@ -2082,39 +2156,35 @@ var ToolCallContainer = (part) => {
2082
2156
  resizable: true
2083
2157
  }
2084
2158
  ) : void 0,
2085
- approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2159
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx48(ToolApprovalSlot, { part }) : void 0
2086
2160
  }
2087
2161
  );
2088
2162
  };
2089
2163
 
2090
- // src/containers/ToolGroupContainer.tsx
2091
- import { useState as useState9 } from "react";
2092
- import { useAuiState as useAuiState6 } from "@assistant-ui/react";
2093
- import { jsx as jsx47 } from "react/jsx-runtime";
2094
- function ToolGroupContainer({
2164
+ // src/containers/AgentStepsContainer.tsx
2165
+ import { useState as useState9, useEffect as useEffect3, useRef as useRef3 } from "react";
2166
+ import { jsx as jsx49 } from "react/jsx-runtime";
2167
+ function AgentStepsContainer({
2095
2168
  children,
2096
- group
2169
+ toolCount,
2170
+ thinkingCount,
2171
+ hasFinal,
2172
+ active
2097
2173
  }) {
2098
- const ToolGroupCard2 = useSlot("ToolGroupCard");
2099
- const toolCallCount = group.indices.length;
2100
- const active = useAuiState6((s) => {
2101
- if (s.message.status?.type !== "running") return false;
2102
- const lastIndex = s.message.parts.length - 1;
2103
- if (lastIndex < 0) return false;
2104
- if (s.message.parts[lastIndex]?.type !== "tool-call") return false;
2105
- const lastGroupIndex = group.indices[group.indices.length - 1];
2106
- return lastGroupIndex !== void 0 && lastIndex >= group.indices[0] && lastIndex <= lastGroupIndex;
2107
- });
2174
+ const AgentStepsCard2 = useSlot("AgentStepsCard");
2108
2175
  const [expanded, setExpanded] = useState9(true);
2109
- const [prevActive, setPrevActive] = useState9(active);
2110
- if (active !== prevActive) {
2111
- setPrevActive(active);
2112
- if (active) setExpanded(true);
2113
- }
2114
- return /* @__PURE__ */ jsx47(
2115
- ToolGroupCard2,
2176
+ const collapsedByFinal = useRef3(false);
2177
+ useEffect3(() => {
2178
+ if (hasFinal && !collapsedByFinal.current) {
2179
+ collapsedByFinal.current = true;
2180
+ setExpanded(false);
2181
+ }
2182
+ }, [hasFinal]);
2183
+ return /* @__PURE__ */ jsx49(
2184
+ AgentStepsCard2,
2116
2185
  {
2117
- toolCallCount,
2186
+ toolCount,
2187
+ thinkingCount,
2118
2188
  expanded,
2119
2189
  active,
2120
2190
  onToggle: () => setExpanded((prev) => !prev),
@@ -2124,16 +2194,16 @@ function ToolGroupContainer({
2124
2194
  }
2125
2195
 
2126
2196
  // src/containers/AssistantMessageContainer.tsx
2127
- import { jsx as jsx48 } from "react/jsx-runtime";
2197
+ import { jsx as jsx50 } from "react/jsx-runtime";
2128
2198
  function AssistantLeafPartContainer({ part }) {
2129
2199
  switch (part.type) {
2130
2200
  case "text":
2131
2201
  case "reasoning":
2132
- return /* @__PURE__ */ jsx48(AssistantTextContainer, {});
2202
+ return /* @__PURE__ */ jsx50(AssistantTextContainer, {});
2133
2203
  case "image":
2134
- return /* @__PURE__ */ jsx48(MessageImageContainer, {});
2204
+ return /* @__PURE__ */ jsx50(MessageImageContainer, {});
2135
2205
  case "tool-call":
2136
- return /* @__PURE__ */ jsx48(ToolCallContainer, { ...part });
2206
+ return /* @__PURE__ */ jsx50(ToolCallContainer, { ...part });
2137
2207
  default:
2138
2208
  return null;
2139
2209
  }
@@ -2148,45 +2218,108 @@ function AssistantMessageContainer() {
2148
2218
  const { copy, isCopied } = useActionBarCopy2({
2149
2219
  copyToClipboard: (text) => navigator.clipboard.writeText(text)
2150
2220
  });
2151
- return /* @__PURE__ */ jsx48(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx48(
2221
+ const parts = useAuiState6((s) => s.message.parts);
2222
+ const { cutIndex, hasFinal, toolCount, thinkingCount } = computeAgentStepsSplit(parts, isRunning);
2223
+ const groupBy = (part, _context) => {
2224
+ const index = parts.findIndex((p) => p === part);
2225
+ if (index === -1) return null;
2226
+ if (part.type === "text" && index >= cutIndex) {
2227
+ return null;
2228
+ }
2229
+ if (index < cutIndex) {
2230
+ if (part.type === "reasoning") {
2231
+ return ["group-agentSteps", "group-reasoning"];
2232
+ }
2233
+ return ["group-agentSteps"];
2234
+ }
2235
+ return null;
2236
+ };
2237
+ const agentStepsActive = isRunning && !hasFinal;
2238
+ return /* @__PURE__ */ jsx50(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx50(
2152
2239
  AssistantMessageBubble2,
2153
2240
  {
2154
- error: error !== void 0 ? /* @__PURE__ */ jsx48(MessageErrorBanner2, { message: String(error) }) : void 0,
2155
- actionBar: !isRunning ? /* @__PURE__ */ jsx48(MessageActionBar2, { isCopied, onCopy: copy }) : void 0,
2156
- children: /* @__PURE__ */ jsx48(
2157
- MessagePrimitive2.GroupedParts,
2158
- {
2159
- groupBy: groupPartByType({
2160
- reasoning: ["group-chainOfThought", "group-reasoning"],
2161
- "tool-call": ["group-chainOfThought", "group-tool"],
2162
- "standalone-tool-call": []
2163
- }),
2164
- children: ({ part, children }) => {
2165
- switch (part.type) {
2166
- case "group-chainOfThought":
2167
- return /* @__PURE__ */ jsx48("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
2168
- case "group-tool":
2169
- return /* @__PURE__ */ jsx48(ToolGroupContainer, { group: part, children });
2170
- case "group-reasoning":
2171
- return /* @__PURE__ */ jsx48(ReasoningContainer, { group: part });
2172
- case "text":
2173
- case "reasoning":
2174
- case "tool-call":
2175
- case "image":
2176
- case "data":
2177
- return /* @__PURE__ */ jsx48(AssistantLeafPartContainer, { part });
2178
- case "indicator":
2179
- return /* @__PURE__ */ jsx48(MessageIndicator2, {});
2180
- default:
2181
- return null;
2182
- }
2183
- }
2241
+ error: error !== void 0 ? /* @__PURE__ */ jsx50(MessageErrorBanner2, { message: String(error) }) : void 0,
2242
+ actionBar: !isRunning ? /* @__PURE__ */ jsx50(MessageActionBar2, { isCopied, onCopy: copy }) : void 0,
2243
+ children: /* @__PURE__ */ jsx50(MessagePrimitive2.GroupedParts, { groupBy, children: ({ part, children }) => {
2244
+ switch (part.type) {
2245
+ case "group-agentSteps":
2246
+ return /* @__PURE__ */ jsx50(
2247
+ AgentStepsContainer,
2248
+ {
2249
+ toolCount,
2250
+ thinkingCount,
2251
+ hasFinal,
2252
+ active: agentStepsActive,
2253
+ children
2254
+ }
2255
+ );
2256
+ case "group-reasoning":
2257
+ return /* @__PURE__ */ jsx50(ReasoningContainer, { group: part });
2258
+ case "text":
2259
+ case "reasoning":
2260
+ case "tool-call":
2261
+ case "image":
2262
+ case "data":
2263
+ return /* @__PURE__ */ jsx50(AssistantLeafPartContainer, { part });
2264
+ case "indicator":
2265
+ return /* @__PURE__ */ jsx50(MessageIndicator2, {});
2266
+ default:
2267
+ return null;
2184
2268
  }
2185
- )
2269
+ } })
2186
2270
  }
2187
2271
  ) });
2188
2272
  }
2189
2273
 
2274
+ // src/containers/HistoryLoaderContainer.tsx
2275
+ import { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef4, useState as useState10 } from "react";
2276
+ import { useTrueFoundryHistoryPagination } from "@truefoundry/assistant-ui-runtime";
2277
+ import { jsx as jsx51 } from "react/jsx-runtime";
2278
+ var TOP_THRESHOLD_PX = 200;
2279
+ var VIEWPORT_SELECTOR = '[data-slot="aui_thread-viewport"]';
2280
+ function HistoryLoaderContainer() {
2281
+ const HistoryLoader2 = useSlot("HistoryLoader");
2282
+ const { hasOlderHistory, isLoadingOlderHistory, loadOlderHistory } = useTrueFoundryHistoryPagination();
2283
+ const [sentinel, setSentinel] = useState10(null);
2284
+ const inflightRef = useRef4(false);
2285
+ const maybeLoadOlder = useCallback7(async () => {
2286
+ if (inflightRef.current) return;
2287
+ inflightRef.current = true;
2288
+ const viewport = sentinel?.closest(VIEWPORT_SELECTOR) ?? null;
2289
+ const prevScrollHeight = viewport?.scrollHeight ?? 0;
2290
+ const prevScrollTop = viewport?.scrollTop ?? 0;
2291
+ try {
2292
+ await loadOlderHistory();
2293
+ requestAnimationFrame(() => {
2294
+ if (viewport == null) return;
2295
+ const delta = viewport.scrollHeight - prevScrollHeight;
2296
+ if (delta > 0) {
2297
+ viewport.scrollTo({ top: prevScrollTop + delta, behavior: "instant" });
2298
+ }
2299
+ });
2300
+ } catch {
2301
+ } finally {
2302
+ inflightRef.current = false;
2303
+ }
2304
+ }, [sentinel, loadOlderHistory]);
2305
+ useEffect4(() => {
2306
+ if (sentinel == null || !hasOlderHistory) return;
2307
+ const viewport = sentinel.closest(VIEWPORT_SELECTOR);
2308
+ const observer = new IntersectionObserver(
2309
+ (entries) => {
2310
+ if (entries.some((entry) => entry.isIntersecting)) {
2311
+ void maybeLoadOlder();
2312
+ }
2313
+ },
2314
+ { root: viewport, rootMargin: `${TOP_THRESHOLD_PX}px 0px 0px 0px` }
2315
+ );
2316
+ observer.observe(sentinel);
2317
+ return () => observer.disconnect();
2318
+ }, [sentinel, hasOlderHistory, maybeLoadOlder]);
2319
+ if (!hasOlderHistory) return null;
2320
+ return /* @__PURE__ */ jsx51(HistoryLoader2, { ref: setSentinel, isLoading: isLoadingOlderHistory });
2321
+ }
2322
+
2190
2323
  // src/containers/UserEditComposerContainer.tsx
2191
2324
  import {
2192
2325
  ComposerPrimitive as ComposerPrimitive2,
@@ -2199,14 +2332,14 @@ import { useComposerCancel, useComposerSend, useThreadIsRunning as useThreadIsRu
2199
2332
  import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui, useAuiState as useAuiState8 } from "@assistant-ui/react";
2200
2333
 
2201
2334
  // src/containers/useAttachmentPreviewSrc.ts
2202
- import { useEffect as useEffect3, useState as useState10 } from "react";
2335
+ import { useEffect as useEffect5, useState as useState11 } from "react";
2203
2336
  import { useAuiState as useAuiState7 } from "@assistant-ui/react";
2204
2337
  function isImageAttachment(type, contentType) {
2205
2338
  return type === "image" || (contentType?.startsWith("image/") ?? false);
2206
2339
  }
2207
2340
  function useFileObjectUrl(file) {
2208
- const [src, setSrc] = useState10(void 0);
2209
- useEffect3(() => {
2341
+ const [src, setSrc] = useState11(void 0);
2342
+ useEffect5(() => {
2210
2343
  if (!file) {
2211
2344
  setSrc(void 0);
2212
2345
  return;
@@ -2234,7 +2367,7 @@ function useAttachmentPreviewSrc() {
2234
2367
  }
2235
2368
 
2236
2369
  // src/containers/AttachmentsContainer.tsx
2237
- import { jsx as jsx49 } from "react/jsx-runtime";
2370
+ import { jsx as jsx52 } from "react/jsx-runtime";
2238
2371
  function ComposerAttachmentItem() {
2239
2372
  const AttachmentCard2 = useSlot("AttachmentCard");
2240
2373
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
@@ -2244,7 +2377,7 @@ function ComposerAttachmentItem() {
2244
2377
  const type = useAuiState8((s) => s.attachment.type);
2245
2378
  const isImage = isImageAttachment(type, contentType);
2246
2379
  const previewSrc = useAttachmentPreviewSrc();
2247
- return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx49(
2380
+ return /* @__PURE__ */ jsx52(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx52(
2248
2381
  AttachmentCard2,
2249
2382
  {
2250
2383
  name,
@@ -2264,7 +2397,7 @@ function MessageAttachmentItem() {
2264
2397
  const type = useAuiState8((s) => s.attachment.type);
2265
2398
  const isImage = isImageAttachment(type, contentType);
2266
2399
  const previewSrc = useAttachmentPreviewSrc();
2267
- const card = /* @__PURE__ */ jsx49(
2400
+ const card = /* @__PURE__ */ jsx52(
2268
2401
  AttachmentCard2,
2269
2402
  {
2270
2403
  name,
@@ -2276,23 +2409,23 @@ function MessageAttachmentItem() {
2276
2409
  }
2277
2410
  );
2278
2411
  if (isImage && previewSrc) {
2279
- return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: card });
2412
+ return /* @__PURE__ */ jsx52(AttachmentPreviewDialog2, { previewSrc, children: card });
2280
2413
  }
2281
2414
  return card;
2282
2415
  }
2283
2416
  function ComposerAttachmentsContainer() {
2284
- return /* @__PURE__ */ jsx49("div", { className: "aui-composer-attachments flex w-full flex-row flex-wrap items-center gap-2 empty:hidden", children: /* @__PURE__ */ jsx49(ComposerPrimitive.Attachments, { children: () => /* @__PURE__ */ jsx49(ComposerAttachmentItem, {}) }) });
2417
+ return /* @__PURE__ */ jsx52("div", { className: "aui-composer-attachments flex w-full flex-row flex-wrap items-center gap-2 empty:hidden", children: /* @__PURE__ */ jsx52(ComposerPrimitive.Attachments, { children: () => /* @__PURE__ */ jsx52(ComposerAttachmentItem, {}) }) });
2285
2418
  }
2286
2419
  function MessageAttachmentsContainer() {
2287
- return /* @__PURE__ */ jsx49("div", { className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2", children: /* @__PURE__ */ jsx49(MessagePrimitive3.Attachments, { children: () => /* @__PURE__ */ jsx49(MessageAttachmentItem, {}) }) });
2420
+ return /* @__PURE__ */ jsx52("div", { className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2", children: /* @__PURE__ */ jsx52(MessagePrimitive3.Attachments, { children: () => /* @__PURE__ */ jsx52(MessageAttachmentItem, {}) }) });
2288
2421
  }
2289
2422
  function ComposerAttachmentPickerContainer() {
2290
2423
  const AttachmentPickerButton2 = useSlot("AttachmentPickerButton");
2291
- return /* @__PURE__ */ jsx49(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx49(AttachmentPickerButton2, {}) });
2424
+ return /* @__PURE__ */ jsx52(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx52(AttachmentPickerButton2, {}) });
2292
2425
  }
2293
2426
 
2294
2427
  // src/containers/UserEditComposerContainer.tsx
2295
- import { jsx as jsx50, jsxs as jsxs16 } from "react/jsx-runtime";
2428
+ import { jsx as jsx53, jsxs as jsxs16 } from "react/jsx-runtime";
2296
2429
  function ReadOnlyMessageAttachments() {
2297
2430
  const hasAttachments = useAuiState9(
2298
2431
  (s) => (s.message.attachments?.length ?? 0) > 0
@@ -2300,7 +2433,7 @@ function ReadOnlyMessageAttachments() {
2300
2433
  if (!hasAttachments) {
2301
2434
  return null;
2302
2435
  }
2303
- return /* @__PURE__ */ jsx50("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx50(MessageAttachmentsContainer, {}) });
2436
+ return /* @__PURE__ */ jsx53("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx53(MessageAttachmentsContainer, {}) });
2304
2437
  }
2305
2438
  function UserEditComposerContainer() {
2306
2439
  const Button4 = useSlot("Button");
@@ -2309,17 +2442,17 @@ function UserEditComposerContainer() {
2309
2442
  const isRunning = useThreadIsRunning3();
2310
2443
  const { cancel, disabled: cancelDisabled } = useComposerCancel();
2311
2444
  const { send, disabled: sendDisabled } = useComposerSend();
2312
- return /* @__PURE__ */ jsx50(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx50(
2445
+ return /* @__PURE__ */ jsx53(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx53(
2313
2446
  "div",
2314
2447
  {
2315
2448
  "data-slot": "aui_user-edit-composer-root",
2316
2449
  className: "fade-in slide-in-from-bottom-1 animate-in flex w-full justify-end px-2 duration-150",
2317
- children: /* @__PURE__ */ jsx50(ComposerPrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx50(
2450
+ children: /* @__PURE__ */ jsx53(ComposerPrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx53(
2318
2451
  UserMessageEdit3,
2319
2452
  {
2320
- timestamp: /* @__PURE__ */ jsx50(MessageTimestamp2, { className: "text-gray-500" }),
2321
- attachments: /* @__PURE__ */ jsx50(ReadOnlyMessageAttachments, {}),
2322
- input: /* @__PURE__ */ jsx50("div", { className: "mt-1 rounded border border-gray-250 bg-gray-100 p-2 text-gray-750 dark:border-gray-275 dark:bg-gray-275", children: /* @__PURE__ */ jsx50(
2453
+ timestamp: /* @__PURE__ */ jsx53(MessageTimestamp2, { className: "text-gray-500" }),
2454
+ attachments: /* @__PURE__ */ jsx53(ReadOnlyMessageAttachments, {}),
2455
+ input: /* @__PURE__ */ jsx53("div", { className: "mt-1 rounded border border-gray-250 bg-gray-100 p-2 text-gray-750 dark:border-gray-275 dark:bg-gray-275", children: /* @__PURE__ */ jsx53(
2323
2456
  ComposerPrimitive2.Input,
2324
2457
  {
2325
2458
  disabled: isRunning,
@@ -2327,7 +2460,7 @@ function UserEditComposerContainer() {
2327
2460
  }
2328
2461
  ) }),
2329
2462
  footer: /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-end gap-2", children: [
2330
- /* @__PURE__ */ jsx50(
2463
+ /* @__PURE__ */ jsx53(
2331
2464
  Button4.Secondary,
2332
2465
  {
2333
2466
  type: "button",
@@ -2336,7 +2469,7 @@ function UserEditComposerContainer() {
2336
2469
  text: "Cancel"
2337
2470
  }
2338
2471
  ),
2339
- /* @__PURE__ */ jsx50(
2472
+ /* @__PURE__ */ jsx53(
2340
2473
  Button4.Primary,
2341
2474
  {
2342
2475
  type: "button",
@@ -2355,7 +2488,7 @@ function UserEditComposerContainer() {
2355
2488
  // src/containers/UserMessageContainer.tsx
2356
2489
  import { MessagePrimitive as MessagePrimitive5, useAuiState as useAuiState10 } from "@assistant-ui/react";
2357
2490
  import { useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
2358
- import { jsx as jsx51 } from "react/jsx-runtime";
2491
+ import { jsx as jsx54 } from "react/jsx-runtime";
2359
2492
  function UserMessageContainer() {
2360
2493
  const UserMessageBubble2 = useSlot("UserMessageBubble");
2361
2494
  const UserMessageActionBar2 = useSlot("UserMessageActionBar");
@@ -2363,31 +2496,31 @@ function UserMessageContainer() {
2363
2496
  const text = useAuiState10(
2364
2497
  (s) => s.message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n")
2365
2498
  );
2366
- return /* @__PURE__ */ jsx51(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx51(
2499
+ return /* @__PURE__ */ jsx54(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx54(
2367
2500
  UserMessageBubble2,
2368
2501
  {
2369
2502
  text,
2370
- attachments: /* @__PURE__ */ jsx51(MessageAttachmentsContainer, {}),
2371
- editAction: !isRunning ? /* @__PURE__ */ jsx51(UserMessageActionBar2, {}) : void 0
2503
+ attachments: /* @__PURE__ */ jsx54(MessageAttachmentsContainer, {}),
2504
+ editAction: !isRunning ? /* @__PURE__ */ jsx54(UserMessageActionBar2, {}) : void 0
2372
2505
  }
2373
2506
  ) });
2374
2507
  }
2375
2508
 
2376
2509
  // src/containers/ThreadContainer.tsx
2377
- import { jsx as jsx52, jsxs as jsxs17 } from "react/jsx-runtime";
2510
+ import { Fragment as Fragment3, jsx as jsx55, jsxs as jsxs17 } from "react/jsx-runtime";
2378
2511
  var isNewChatView = (s) => s.thread.messages.length === 0 && (!s.thread.isLoading || s.threads.isLoading);
2379
2512
  function ThreadMessage({ isEditing }) {
2380
2513
  const role = useAuiState11((s) => s.message.role);
2381
2514
  if (role === "user") {
2382
2515
  if (isEditing) {
2383
- return /* @__PURE__ */ jsx52(UserEditComposerContainer, {});
2516
+ return /* @__PURE__ */ jsx55(UserEditComposerContainer, {});
2384
2517
  }
2385
- return /* @__PURE__ */ jsx52(UserMessageContainer, {});
2518
+ return /* @__PURE__ */ jsx55(UserMessageContainer, {});
2386
2519
  }
2387
- return /* @__PURE__ */ jsx52(AssistantMessageContainer, {});
2520
+ return /* @__PURE__ */ jsx55(AssistantMessageContainer, {});
2388
2521
  }
2389
2522
  function ThreadContainer({ composer }) {
2390
- useEffect4(() => {
2523
+ useEffect6(() => {
2391
2524
  void preloadMarkdownOpenUI();
2392
2525
  }, []);
2393
2526
  const ThreadRootShell2 = useSlot("ThreadRootShell");
@@ -2399,30 +2532,69 @@ function ThreadContainer({ composer }) {
2399
2532
  const ScrollToBottomButton2 = useSlot("ScrollToBottomButton");
2400
2533
  const isEmpty = useAuiState11(isNewChatView);
2401
2534
  const isLoading = useAuiState11((s) => s.thread.isLoading);
2402
- return /* @__PURE__ */ jsx52(ComposerBusyProvider, { children: /* @__PURE__ */ jsx52(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs17(ThreadRootShell2, { children: [
2403
- /* @__PURE__ */ jsx52(ThreadPrimitive.Viewport, { asChild: true, turnAnchor: "top", autoScroll: true, children: /* @__PURE__ */ jsxs17(ThreadViewportShell2, { isEmpty, children: [
2404
- isEmpty && /* @__PURE__ */ jsx52(WelcomeScreen2, {}),
2405
- isLoading ? /* @__PURE__ */ jsx52(MessageListSkeleton2, {}) : /* @__PURE__ */ jsx52(MessageGroup2, { children: /* @__PURE__ */ jsx52(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx52(
2406
- ThreadMessage,
2407
- {
2408
- isEditing: message.role === "user" && message.composer.isEditing
2409
- }
2410
- ) }) })
2535
+ return /* @__PURE__ */ jsx55(ComposerBusyProvider, { children: /* @__PURE__ */ jsx55(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs17(ThreadRootShell2, { children: [
2536
+ /* @__PURE__ */ jsx55(ThreadPrimitive.Viewport, { asChild: true, turnAnchor: "top", autoScroll: true, children: /* @__PURE__ */ jsxs17(ThreadViewportShell2, { isEmpty, children: [
2537
+ isEmpty && /* @__PURE__ */ jsx55(WelcomeScreen2, {}),
2538
+ isLoading ? /* @__PURE__ */ jsx55(MessageListSkeleton2, {}) : /* @__PURE__ */ jsxs17(Fragment3, { children: [
2539
+ /* @__PURE__ */ jsx55(HistoryLoaderContainer, {}),
2540
+ /* @__PURE__ */ jsx55(MessageGroup2, { children: /* @__PURE__ */ jsx55(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx55(
2541
+ ThreadMessage,
2542
+ {
2543
+ isEditing: message.role === "user" && message.composer.isEditing
2544
+ }
2545
+ ) }) })
2546
+ ] })
2411
2547
  ] }) }),
2412
2548
  !isLoading && /* @__PURE__ */ jsxs17(ThreadComposerAreaShell2, { isEmpty, children: [
2413
- !isEmpty && /* @__PURE__ */ jsx52(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx52(ScrollToBottomButton2, {}) }),
2549
+ !isEmpty && /* @__PURE__ */ jsx55(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx55(ScrollToBottomButton2, {}) }),
2414
2550
  composer
2415
2551
  ] })
2416
2552
  ] }) }) });
2417
2553
  }
2418
2554
 
2555
+ // src/containers/ToolGroupContainer.tsx
2556
+ import { useState as useState12 } from "react";
2557
+ import { useAuiState as useAuiState12 } from "@assistant-ui/react";
2558
+ import { jsx as jsx56 } from "react/jsx-runtime";
2559
+ function ToolGroupContainer({
2560
+ children,
2561
+ group
2562
+ }) {
2563
+ const ToolGroupCard2 = useSlot("ToolGroupCard");
2564
+ const toolCallCount = group.indices.length;
2565
+ const active = useAuiState12((s) => {
2566
+ if (s.message.status?.type !== "running") return false;
2567
+ const lastIndex = s.message.parts.length - 1;
2568
+ if (lastIndex < 0) return false;
2569
+ if (s.message.parts[lastIndex]?.type !== "tool-call") return false;
2570
+ const lastGroupIndex = group.indices[group.indices.length - 1];
2571
+ return lastGroupIndex !== void 0 && lastIndex >= group.indices[0] && lastIndex <= lastGroupIndex;
2572
+ });
2573
+ const [expanded, setExpanded] = useState12(true);
2574
+ const [prevActive, setPrevActive] = useState12(active);
2575
+ if (active !== prevActive) {
2576
+ setPrevActive(active);
2577
+ if (active) setExpanded(true);
2578
+ }
2579
+ return /* @__PURE__ */ jsx56(
2580
+ ToolGroupCard2,
2581
+ {
2582
+ toolCallCount,
2583
+ expanded,
2584
+ active,
2585
+ onToggle: () => setExpanded((prev) => !prev),
2586
+ children
2587
+ }
2588
+ );
2589
+ }
2590
+
2419
2591
  // src/containers/ComposerContainer.tsx
2420
- import { useRef as useRef3 } from "react";
2421
- import { useAui as useAui2, useAuiState as useAuiState13 } from "@assistant-ui/react";
2592
+ import { useRef as useRef5 } from "react";
2593
+ import { useAui as useAui2, useAuiState as useAuiState14 } from "@assistant-ui/react";
2422
2594
  import { useTrueFoundryCancel } from "@truefoundry/assistant-ui-runtime";
2423
2595
 
2424
2596
  // src/hooks/useComposerPauseView.ts
2425
- import { useAuiState as useAuiState12 } from "@assistant-ui/react";
2597
+ import { useAuiState as useAuiState13 } from "@assistant-ui/react";
2426
2598
  import { useTrueFoundryToolResponses } from "@truefoundry/assistant-ui-runtime";
2427
2599
  function threadHasPendingMcpAuth(s) {
2428
2600
  const messages = s.thread.messages;
@@ -2432,7 +2604,7 @@ function threadHasPendingMcpAuth(s) {
2432
2604
  return last.metadata?.custom?.pendingMcpAuth === true;
2433
2605
  }
2434
2606
  function useComposerPauseView() {
2435
- const mcpPending = useAuiState12(threadHasPendingMcpAuth);
2607
+ const mcpPending = useAuiState13(threadHasPendingMcpAuth);
2436
2608
  const { pending: toolResponsesPending } = useTrueFoundryToolResponses();
2437
2609
  if (mcpPending) {
2438
2610
  return { kind: "mcp" };
@@ -2446,11 +2618,11 @@ function useComposerPauseView() {
2446
2618
  // src/containers/AskUserContainer.tsx
2447
2619
  import { useTrueFoundryToolResponses as useTrueFoundryToolResponses2 } from "@truefoundry/assistant-ui-runtime";
2448
2620
  import { useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
2449
- import { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo5, useState as useState11 } from "react";
2621
+ import { useCallback as useCallback8, useEffect as useEffect7, useMemo as useMemo5, useState as useState13 } from "react";
2450
2622
  import {
2451
2623
  ASK_USER_CUSTOM_OPTION
2452
2624
  } from "tfy-web-components/components/molecules/agent-chat";
2453
- import { jsx as jsx53 } from "react/jsx-runtime";
2625
+ import { jsx as jsx57 } from "react/jsx-runtime";
2454
2626
  var EMPTY_ANSWER = { radioValue: "", custom: "" };
2455
2627
  function AskUserContainer() {
2456
2628
  const AskUserPrompt2 = useSlot("AskUserPrompt");
@@ -2467,11 +2639,11 @@ function AskUserContainer() {
2467
2639
  ],
2468
2640
  [item]
2469
2641
  );
2470
- const [currentQuestionIndex, setCurrentQuestionIndex] = useState11(0);
2471
- const [answers, setAnswers] = useState11(
2642
+ const [currentQuestionIndex, setCurrentQuestionIndex] = useState13(0);
2643
+ const [answers, setAnswers] = useState13(
2472
2644
  {}
2473
2645
  );
2474
- useEffect5(() => {
2646
+ useEffect7(() => {
2475
2647
  setCurrentQuestionIndex(0);
2476
2648
  setAnswers({});
2477
2649
  }, [item?.toolCallId]);
@@ -2481,7 +2653,7 @@ function AskUserContainer() {
2481
2653
  );
2482
2654
  const currentQuestion = questions[safeIndex];
2483
2655
  const currentAnswer = currentQuestion == null ? EMPTY_ANSWER : answers[currentQuestion.id] ?? EMPTY_ANSWER;
2484
- const getResponseForQuestion = useCallback7(
2656
+ const getResponseForQuestion = useCallback8(
2485
2657
  (questionId) => {
2486
2658
  const answer = answers[questionId] ?? EMPTY_ANSWER;
2487
2659
  return answer.radioValue === ASK_USER_CUSTOM_OPTION ? answer.custom.trim() : answer.radioValue.trim();
@@ -2495,7 +2667,7 @@ function AskUserContainer() {
2495
2667
  const selectedResponse = currentAnswer.radioValue === ASK_USER_CUSTOM_OPTION ? currentAnswer.custom.trim() : currentAnswer.radioValue.trim();
2496
2668
  const isSubmitDisabled = isRunning || currentQuestion == null || selectedResponse.length === 0;
2497
2669
  const isSubmitAllDisabled = isSubmitDisabled || !allQuestionsAnswered;
2498
- const onCurrentAnswerChange = useCallback7(
2670
+ const onCurrentAnswerChange = useCallback8(
2499
2671
  (questionId, update) => {
2500
2672
  setAnswers((previous) => ({
2501
2673
  ...previous,
@@ -2507,14 +2679,14 @@ function AskUserContainer() {
2507
2679
  },
2508
2680
  []
2509
2681
  );
2510
- const onSubmit = useCallback7(() => {
2682
+ const onSubmit = useCallback8(() => {
2511
2683
  if (item == null || !allQuestionsAnswered) return;
2512
2684
  const content = getResponseForQuestion(item.toolCallId);
2513
2685
  if (!content) return;
2514
2686
  respond({ toolCallId: item.toolCallId, content });
2515
2687
  }, [allQuestionsAnswered, getResponseForQuestion, item, respond]);
2516
2688
  if (item == null || currentQuestion == null) return null;
2517
- return /* @__PURE__ */ jsx53(
2689
+ return /* @__PURE__ */ jsx57(
2518
2690
  AskUserPrompt2,
2519
2691
  {
2520
2692
  questions,
@@ -2538,7 +2710,7 @@ function AskUserContainer() {
2538
2710
  // src/containers/McpAuthContainer.tsx
2539
2711
  import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
2540
2712
  import { useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
2541
- import { jsx as jsx54 } from "react/jsx-runtime";
2713
+ import { jsx as jsx58 } from "react/jsx-runtime";
2542
2714
  function McpAuthContainer() {
2543
2715
  const McpAuthPrompt2 = useSlot("McpAuthPrompt");
2544
2716
  const { pending, resume } = useTrueFoundryMcpAuth();
@@ -2550,7 +2722,7 @@ function McpAuthContainer() {
2550
2722
  window.open(server.authUrl, "_blank", "noopener,noreferrer");
2551
2723
  }
2552
2724
  };
2553
- return /* @__PURE__ */ jsx54(
2725
+ return /* @__PURE__ */ jsx58(
2554
2726
  McpAuthPrompt2,
2555
2727
  {
2556
2728
  servers: pending.mcpServers,
@@ -2562,25 +2734,25 @@ function McpAuthContainer() {
2562
2734
  }
2563
2735
 
2564
2736
  // src/containers/ComposerContainer.tsx
2565
- import { Fragment as Fragment3, jsx as jsx55, jsxs as jsxs18 } from "react/jsx-runtime";
2737
+ import { Fragment as Fragment4, jsx as jsx59, jsxs as jsxs18 } from "react/jsx-runtime";
2566
2738
  function ComposerContainer({
2567
2739
  placeholder = "Ask anything... (Shift+Enter for new line)"
2568
2740
  }) {
2569
2741
  const ComposerShell2 = useSlot("ComposerShell");
2570
2742
  const aui = useAui2();
2571
- const text = useAuiState13((s) => s.composer.text);
2743
+ const text = useAuiState14((s) => s.composer.text);
2572
2744
  const { isBusy, send, resetBusy } = useComposerBusyState();
2573
2745
  const pauseView = useComposerPauseView();
2574
2746
  const cancel = useTrueFoundryCancel();
2575
- const fileInputRef = useRef3(null);
2747
+ const fileInputRef = useRef5(null);
2576
2748
  if (pauseView.kind === "mcp") {
2577
- return /* @__PURE__ */ jsx55(McpAuthContainer, {});
2749
+ return /* @__PURE__ */ jsx59(McpAuthContainer, {});
2578
2750
  }
2579
2751
  if (pauseView.kind === "ask-user") {
2580
- return /* @__PURE__ */ jsx55(AskUserContainer, {});
2752
+ return /* @__PURE__ */ jsx59(AskUserContainer, {});
2581
2753
  }
2582
- return /* @__PURE__ */ jsxs18(Fragment3, { children: [
2583
- /* @__PURE__ */ jsx55(
2754
+ return /* @__PURE__ */ jsxs18(Fragment4, { children: [
2755
+ /* @__PURE__ */ jsx59(
2584
2756
  "input",
2585
2757
  {
2586
2758
  ref: fileInputRef,
@@ -2598,10 +2770,10 @@ function ComposerContainer({
2598
2770
  }
2599
2771
  }
2600
2772
  ),
2601
- /* @__PURE__ */ jsx55(
2773
+ /* @__PURE__ */ jsx59(
2602
2774
  ComposerShell2,
2603
2775
  {
2604
- attachments: /* @__PURE__ */ jsx55(ComposerAttachmentsContainer, {}),
2776
+ attachments: /* @__PURE__ */ jsx59(ComposerAttachmentsContainer, {}),
2605
2777
  value: text,
2606
2778
  placeholder,
2607
2779
  disabled: isBusy,
@@ -2619,9 +2791,9 @@ function ComposerContainer({
2619
2791
  }
2620
2792
 
2621
2793
  // src/containers/ThreadListContainer.tsx
2622
- import { useAui as useAui3, useAuiState as useAuiState14 } from "@assistant-ui/react";
2623
- import { useEffect as useEffect6, useRef as useRef4 } from "react";
2624
- import { Fragment as Fragment4, jsx as jsx56, jsxs as jsxs19 } from "react/jsx-runtime";
2794
+ import { useAui as useAui3, useAuiState as useAuiState15 } from "@assistant-ui/react";
2795
+ import { useEffect as useEffect8, useRef as useRef6 } from "react";
2796
+ import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs19 } from "react/jsx-runtime";
2625
2797
  function ThreadListContainer() {
2626
2798
  const ThreadListShell2 = useSlot("ThreadListShell");
2627
2799
  const ThreadListNewButton2 = useSlot("ThreadListNewButton");
@@ -2629,14 +2801,14 @@ function ThreadListContainer() {
2629
2801
  const ThreadListRowSkeleton2 = useSlot("ThreadListRowSkeleton");
2630
2802
  const ThreadListEmptyState2 = useSlot("ThreadListEmptyState");
2631
2803
  const aui = useAui3();
2632
- const isLoading = useAuiState14((s) => s.threads.isLoading);
2633
- const isLoadingMore = useAuiState14((s) => s.threads.isLoadingMore);
2634
- const hasMore = useAuiState14((s) => s.threads.hasMore);
2635
- const threadIds = useAuiState14((s) => s.threads.threadIds);
2636
- const threadItems = useAuiState14((s) => s.threads.threadItems);
2637
- const mainThreadId = useAuiState14((s) => s.threads.mainThreadId);
2638
- const sentinelRef = useRef4(null);
2639
- useEffect6(() => {
2804
+ const isLoading = useAuiState15((s) => s.threads.isLoading);
2805
+ const isLoadingMore = useAuiState15((s) => s.threads.isLoadingMore);
2806
+ const hasMore = useAuiState15((s) => s.threads.hasMore);
2807
+ const threadIds = useAuiState15((s) => s.threads.threadIds);
2808
+ const threadItems = useAuiState15((s) => s.threads.threadItems);
2809
+ const mainThreadId = useAuiState15((s) => s.threads.mainThreadId);
2810
+ const sentinelRef = useRef6(null);
2811
+ useEffect8(() => {
2640
2812
  const node = sentinelRef.current;
2641
2813
  if (!node || !hasMore) return;
2642
2814
  const observer = new IntersectionObserver((entries) => {
@@ -2648,10 +2820,10 @@ function ThreadListContainer() {
2648
2820
  return () => observer.disconnect();
2649
2821
  }, [aui, hasMore, isLoadingMore]);
2650
2822
  const itemsById = new Map(threadItems.map((item) => [item.id, item]));
2651
- return /* @__PURE__ */ jsxs19(ThreadListShell2, { header: /* @__PURE__ */ jsx56(ThreadListNewButton2, { onClick: () => aui.threads().switchToNewThread() }), children: [
2652
- isLoading ? /* @__PURE__ */ jsx56(ThreadListRowSkeleton2, {}) : threadIds.length === 0 ? /* @__PURE__ */ jsx56(ThreadListEmptyState2, {}) : threadIds.map((id) => {
2823
+ return /* @__PURE__ */ jsxs19(ThreadListShell2, { header: /* @__PURE__ */ jsx60(ThreadListNewButton2, { onClick: () => aui.threads().switchToNewThread() }), children: [
2824
+ isLoading ? /* @__PURE__ */ jsx60(ThreadListRowSkeleton2, {}) : threadIds.length === 0 ? /* @__PURE__ */ jsx60(ThreadListEmptyState2, {}) : threadIds.map((id) => {
2653
2825
  const item = itemsById.get(id);
2654
- return /* @__PURE__ */ jsx56(
2826
+ return /* @__PURE__ */ jsx60(
2655
2827
  ThreadListRow2,
2656
2828
  {
2657
2829
  title: item?.title ?? "New Chat",
@@ -2663,22 +2835,24 @@ function ThreadListContainer() {
2663
2835
  id
2664
2836
  );
2665
2837
  }),
2666
- !isLoading && hasMore && /* @__PURE__ */ jsxs19(Fragment4, { children: [
2667
- isLoadingMore && /* @__PURE__ */ jsx56(ThreadListRowSkeleton2, { count: 1 }),
2668
- /* @__PURE__ */ jsx56("div", { ref: sentinelRef, "aria-hidden": true })
2838
+ !isLoading && hasMore && /* @__PURE__ */ jsxs19(Fragment5, { children: [
2839
+ isLoadingMore && /* @__PURE__ */ jsx60(ThreadListRowSkeleton2, { count: 1 }),
2840
+ /* @__PURE__ */ jsx60("div", { ref: sentinelRef, "aria-hidden": true })
2669
2841
  ] })
2670
2842
  ] });
2671
2843
  }
2672
2844
 
2673
2845
  // src/containers/Thread.tsx
2674
- import { jsx as jsx57 } from "react/jsx-runtime";
2846
+ import { jsx as jsx61 } from "react/jsx-runtime";
2675
2847
  function Thread() {
2676
- return /* @__PURE__ */ jsx57(ThreadContainer, { composer: /* @__PURE__ */ jsx57(ComposerContainer, {}) });
2848
+ return /* @__PURE__ */ jsx61(ThreadContainer, { composer: /* @__PURE__ */ jsx61(ComposerContainer, {}) });
2677
2849
  }
2678
2850
  export {
2679
2851
  Accordion3 as Accordion,
2680
2852
  AccordionDetails3 as AccordionDetails,
2681
2853
  AccordionSummary3 as AccordionSummary,
2854
+ AgentStepsCard,
2855
+ AgentStepsContainer,
2682
2856
  AskUserContainer,
2683
2857
  AssistantMessageBubble,
2684
2858
  AssistantMessageContainer,
@@ -2702,6 +2876,8 @@ export {
2702
2876
  default5 as Dialog,
2703
2877
  ErrorToasterProvider,
2704
2878
  GhostButton,
2879
+ HistoryLoader,
2880
+ HistoryLoaderContainer,
2705
2881
  default2 as IconButton,
2706
2882
  default3 as IconProvider,
2707
2883
  LightTooltip2 as LightTooltip,
@@ -2753,6 +2929,7 @@ export {
2753
2929
  UserMessageContainer,
2754
2930
  UserMessageEdit,
2755
2931
  WelcomeScreen,
2932
+ computeAgentStepsSplit,
2756
2933
  defaultSlots,
2757
2934
  defaultTokens,
2758
2935
  registerIcons2 as registerIcons,