@truefoundry/agent-ui-sdk 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +192 -80
  2. package/dist/index.d.ts +229 -281
  3. package/dist/index.js +1824 -1791
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +2 -0
  6. package/package.json +36 -19
  7. package/src/atoms/AskUserPrompt.tsx +0 -102
  8. package/src/atoms/AttachmentCard.tsx +0 -92
  9. package/src/atoms/AttachmentPickerButton.tsx +0 -19
  10. package/src/atoms/AttachmentPreviewDialog.tsx +0 -34
  11. package/src/atoms/BranchIndicator.tsx +0 -41
  12. package/src/atoms/CodeBlockHeader.tsx +0 -44
  13. package/src/atoms/ComposerShell.tsx +0 -112
  14. package/src/atoms/Markdown.test.tsx +0 -28
  15. package/src/atoms/Markdown.tsx +0 -288
  16. package/src/atoms/McpAuthPrompt.tsx +0 -60
  17. package/src/atoms/MessageActionBar.tsx +0 -60
  18. package/src/atoms/MessageBubble.tsx +0 -80
  19. package/src/atoms/MessageErrorBanner.tsx +0 -26
  20. package/src/atoms/MessageIndicator.tsx +0 -23
  21. package/src/atoms/OpenUIBlock.test.tsx +0 -37
  22. package/src/atoms/OpenUIBlock.tsx +0 -50
  23. package/src/atoms/ReasoningCard.tsx +0 -52
  24. package/src/atoms/SandboxArtifactList.tsx +0 -63
  25. package/src/atoms/ScrollToBottomButton.tsx +0 -34
  26. package/src/atoms/Skeletons.tsx +0 -32
  27. package/src/atoms/ThreadListMisc.tsx +0 -76
  28. package/src/atoms/ThreadListRow.tsx +0 -81
  29. package/src/atoms/ThreadShell.tsx +0 -93
  30. package/src/atoms/Toast.tsx +0 -60
  31. package/src/atoms/ToolApprovalBar.tsx +0 -92
  32. package/src/atoms/ToolCallCard.tsx +0 -186
  33. package/src/atoms/ToolGroupCard.tsx +0 -52
  34. package/src/atoms/UserMessageActionBar.tsx +0 -62
  35. package/src/atoms/WelcomeScreen.tsx +0 -22
  36. package/src/atoms/lib/cn.ts +0 -6
  37. package/src/atoms/primitives/Avatar.tsx +0 -57
  38. package/src/atoms/primitives/Button.tsx +0 -73
  39. package/src/atoms/primitives/Collapsible.tsx +0 -32
  40. package/src/atoms/primitives/Dialog.tsx +0 -152
  41. package/src/atoms/primitives/IconButton.tsx +0 -43
  42. package/src/atoms/primitives/Skeleton.tsx +0 -17
  43. package/src/atoms/primitives/Tooltip.tsx +0 -58
  44. package/src/containers/AskUserContainer.tsx +0 -49
  45. package/src/containers/AssistantMessageContainer.test.tsx +0 -56
  46. package/src/containers/AssistantMessageContainer.tsx +0 -128
  47. package/src/containers/AssistantTextContainer.test.tsx +0 -111
  48. package/src/containers/AssistantTextContainer.tsx +0 -54
  49. package/src/containers/AttachmentsContainer.tsx +0 -83
  50. package/src/containers/ComposerContainer.tsx +0 -66
  51. package/src/containers/ErrorToasterContainer.tsx +0 -76
  52. package/src/containers/McpAuthContainer.test.tsx +0 -100
  53. package/src/containers/McpAuthContainer.tsx +0 -22
  54. package/src/containers/MessageImageContainer.tsx +0 -37
  55. package/src/containers/ReasoningContainer.tsx +0 -32
  56. package/src/containers/RuntimeHarness.tsx +0 -39
  57. package/src/containers/Thread.tsx +0 -9
  58. package/src/containers/ThreadContainer.test.tsx +0 -52
  59. package/src/containers/ThreadContainer.tsx +0 -87
  60. package/src/containers/ThreadListContainer.tsx +0 -63
  61. package/src/containers/ToolCallContainer.test.tsx +0 -135
  62. package/src/containers/ToolCallContainer.tsx +0 -167
  63. package/src/containers/ToolGroupContainer.test.tsx +0 -56
  64. package/src/containers/ToolGroupContainer.tsx +0 -24
  65. package/src/containers/UserEditComposerContainer.test.tsx +0 -52
  66. package/src/containers/UserEditComposerContainer.tsx +0 -86
  67. package/src/containers/UserMessageContainer.test.tsx +0 -99
  68. package/src/containers/UserMessageContainer.tsx +0 -26
  69. package/src/containers/nestedApprovalBridge.ts +0 -20
  70. package/src/containers/useAttachmentPreviewSrc.ts +0 -42
  71. package/src/hooks/useComposerBusyState.test.ts +0 -78
  72. package/src/hooks/useComposerBusyState.ts +0 -69
  73. package/src/index.ts +0 -193
  74. package/src/testSetup.ts +0 -42
  75. package/src/theme/SlotsProvider.test.tsx +0 -64
  76. package/src/theme/SlotsProvider.tsx +0 -41
  77. package/src/theme/defaultSlots.ts +0 -131
  78. package/src/theme/tokens.ts +0 -98
  79. package/src/theme/useClassDarkMode.ts +0 -24
package/dist/index.js CHANGED
@@ -1,10 +1,133 @@
1
1
  "use client";
2
2
 
3
+ // src/icons/fontawesome.ts
4
+ import { library } from "@fortawesome/fontawesome-svg-core";
5
+ import {
6
+ faArrowDown,
7
+ faArrowUp,
8
+ faBoxArchive,
9
+ faEllipsis,
10
+ faPencil,
11
+ faPlus,
12
+ faTrash,
13
+ faXmark
14
+ } from "@fortawesome/free-solid-svg-icons";
15
+ library.add(faArrowDown, faArrowUp, faBoxArchive, faEllipsis, faPencil, faPlus, faTrash, faXmark);
16
+
17
+ // src/icons/registerAgentIcons.ts
18
+ import { registerIcons } from "tfy-web-components/components/atoms/IconProvider";
19
+
20
+ // src/icons/agent-2.svg
21
+ import * as React from "react";
22
+ import { jsx } from "react/jsx-runtime";
23
+ var SvgAgent2 = (props) => /* @__PURE__ */ jsx("svg", { width: "1em", height: "1em", viewBox: "0 0 16 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx("path", { d: "M8 0C8.40158 8.28071e-05 8.72754 0.325937 8.72754 0.727539V2.90918H12.3623C13.5671 2.90921 14.5437 3.88607 14.5439 5.09082V7.27246H15.2725C15.6741 7.27253 16 7.59839 16 8C15.9999 8.40155 15.674 8.72747 15.2725 8.72754H14.5439V10.9092C14.5437 12.1139 13.5671 13.0908 12.3623 13.0908H3.63477C2.43015 13.0906 1.45334 12.1138 1.45312 10.9092V8.72754H0.727539C0.325964 8.7275 7.21982e-05 8.40157 0 8C0 7.59837 0.32592 7.2725 0.727539 7.27246H1.45312V5.09082C1.45335 3.8862 2.43015 2.90942 3.63477 2.90918H7.27246V1.45508H5.09082C4.68943 1.4549 4.36346 1.12893 4.36328 0.727539C4.36328 0.325997 4.68932 0.00017902 5.09082 0H8ZM3.63477 4.36426C3.23346 4.3645 2.90843 4.68951 2.9082 5.09082V7.99023C2.90824 7.99344 2.90918 7.99678 2.90918 8C2.90918 8.00326 2.90825 8.00651 2.9082 8.00977V10.9092C2.90841 11.3105 3.23345 11.6365 3.63477 11.6367H12.3623C12.7638 11.6367 13.0896 11.3106 13.0898 10.9092V5.09082C13.0896 4.68937 12.7638 4.36428 12.3623 4.36426H3.63477ZM5.81738 6.54492C6.21902 6.54492 6.54489 6.87084 6.54492 7.27246V8.72656C6.54492 9.12822 6.21904 9.4541 5.81738 9.4541C5.41587 9.45393 5.08984 9.12811 5.08984 8.72656V7.27246C5.08988 6.87094 5.41589 6.54509 5.81738 6.54492ZM10.1816 6.54492C10.5831 6.54514 10.9091 6.87097 10.9092 7.27246V8.72656C10.9092 9.12808 10.5831 9.45388 10.1816 9.4541C9.77999 9.4541 9.4541 9.12822 9.4541 8.72656V7.27246C9.45413 6.87084 9.78001 6.54492 10.1816 6.54492Z", fill: "currentColor" }) });
24
+ var agent_2_default = SvgAgent2;
25
+
26
+ // src/icons/ai.svg
27
+ import * as React2 from "react";
28
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
29
+ var SvgAi = (props) => /* @__PURE__ */ jsx2("svg", { width: "1em", height: "1em", viewBox: "0 0 16 17", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsxs("g", { opacity: 0.9, children: [
30
+ /* @__PURE__ */ jsx2("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M15.4419 9.43023C15.7501 9.43023 16 9.68012 16 9.98837V10.0304C16 11.398 16 12.4813 15.886 13.329C15.7687 14.2015 15.5216 14.9077 14.9647 15.4647C14.4077 16.0216 13.7015 16.2687 12.829 16.386C11.9813 16.5 10.898 16.5 9.53035 16.5H9.48837C9.18012 16.5 8.93023 16.2501 8.93023 15.9419C8.93023 15.6336 9.18012 15.3837 9.48837 15.3837C10.9074 15.3837 11.9155 15.3825 12.6803 15.2797C13.429 15.1791 13.8604 14.9903 14.1753 14.6753C14.4903 14.3604 14.6791 13.929 14.7797 13.1803C14.8825 12.4155 14.8837 11.4074 14.8837 9.98837C14.8837 9.68012 15.1336 9.43023 15.4419 9.43023Z", fill: "currentColor" }),
31
+ /* @__PURE__ */ jsx2("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M0.55814 9.43023C0.866392 9.43023 1.11628 9.68012 1.11628 9.98837C1.11628 11.4074 1.11747 12.4155 1.22029 13.1803C1.32095 13.929 1.50973 14.3604 1.82467 14.6753C2.13962 14.9903 2.57098 15.1791 3.3197 15.2797C4.08448 15.3825 5.0926 15.3837 6.51163 15.3837C6.81988 15.3837 7.06977 15.6336 7.06977 15.9419C7.06977 16.2501 6.81988 16.5 6.51163 16.5H6.46965C5.10201 16.5 4.01875 16.5 3.17096 16.386C2.29846 16.2687 1.59227 16.0216 1.03534 15.4647C0.478423 14.9077 0.231266 14.2015 0.113961 13.329C-2.0957e-05 12.4813 -1.15596e-05 11.398 2.3934e-07 10.0304C3.72411e-07 10.0164 5.05482e-07 10.0024 5.05482e-07 9.98837C5.05482e-07 9.68012 0.249888 9.43023 0.55814 9.43023Z", fill: "currentColor" }),
32
+ /* @__PURE__ */ jsx2("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M6.46964 0.5L6.51163 0.500001C6.81988 0.500001 7.06977 0.749888 7.06977 1.05814C7.06977 1.36639 6.81988 1.61628 6.51163 1.61628C5.0926 1.61628 4.08448 1.61747 3.3197 1.72029C2.57098 1.82095 2.13962 2.00973 1.82467 2.32467C1.50973 2.63962 1.32095 3.07098 1.22029 3.8197C1.11747 4.58448 1.11628 5.5926 1.11628 7.01163C1.11628 7.31988 0.866392 7.56977 0.55814 7.56977C0.249888 7.56977 5.05482e-07 7.31988 5.05482e-07 7.01163L2.3934e-07 6.96964C-1.15596e-05 5.60201 -2.0957e-05 4.51875 0.113961 3.67096C0.231266 2.79846 0.478423 2.09227 1.03534 1.53534C1.59227 0.978423 2.29846 0.731266 3.17096 0.613961C4.01875 0.499979 5.10201 0.499988 6.46964 0.5Z", fill: "currentColor" }),
33
+ /* @__PURE__ */ jsx2("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M12.6803 1.72029C11.9155 1.61747 10.9074 1.61628 9.48837 1.61628C9.18012 1.61628 8.93023 1.36639 8.93023 1.05814C8.93023 0.749888 9.18012 0.500001 9.48837 0.500001C9.5024 0.500001 9.51639 0.5 9.53036 0.5C10.898 0.499988 11.9813 0.499979 12.829 0.613961C13.7015 0.731266 14.4077 0.978423 14.9647 1.53534C15.5216 2.09227 15.7687 2.79846 15.886 3.67096C16 4.51875 16 5.60201 16 6.96965V7.01163C16 7.31988 15.7501 7.56977 15.4419 7.56977C15.1336 7.56977 14.8837 7.31988 14.8837 7.01163C14.8837 5.5926 14.8825 4.58448 14.7797 3.8197C14.6791 3.07098 14.4903 2.63962 14.1753 2.32467C13.8604 2.00973 13.429 1.82095 12.6803 1.72029Z", fill: "currentColor" }),
34
+ /* @__PURE__ */ jsx2("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M2.70041 3.20041C2.04651 3.85431 2.04651 4.90675 2.04651 7.01163V9.98837C2.04651 12.0933 2.04651 13.1457 2.70041 13.7996C3.35431 14.4535 4.40675 14.4535 6.51163 14.4535H9.48837C11.5933 14.4535 12.6457 14.4535 13.2996 13.7996C13.9535 13.1457 13.9535 12.0933 13.9535 9.98837V7.01163C13.9535 4.90675 13.9535 3.85431 13.2996 3.20041C12.6457 2.54651 11.5933 2.54651 9.48837 2.54651H6.51163C4.40675 2.54651 3.35431 2.54651 2.70041 3.20041ZM5.65417 10.5348C5.81478 10.3181 6.12065 10.2726 6.33733 10.4332C6.8116 10.7848 7.38407 10.9884 8 10.9884C8.61593 10.9884 9.1884 10.7848 9.66267 10.4332C9.87936 10.2726 10.1852 10.3181 10.3458 10.5348C10.5064 10.7514 10.461 11.0573 10.2443 11.2179C9.61111 11.6873 8.83673 11.9651 8 11.9651C7.16327 11.9651 6.38889 11.6873 5.75569 11.2179C5.53901 11.0573 5.49356 10.7514 5.65417 10.5348ZM10.6047 7.24419C10.6047 7.78363 10.3131 8.22093 9.95349 8.22093C9.59386 8.22093 9.30233 7.78363 9.30233 7.24419C9.30233 6.70475 9.59386 6.26744 9.95349 6.26744C10.3131 6.26744 10.6047 6.70475 10.6047 7.24419ZM6.04651 8.22093C6.40614 8.22093 6.69767 7.78363 6.69767 7.24419C6.69767 6.70475 6.40614 6.26744 6.04651 6.26744C5.68688 6.26744 5.39535 6.70475 5.39535 7.24419C5.39535 7.78363 5.68688 8.22093 6.04651 8.22093Z", fill: "currentColor" })
35
+ ] }) });
36
+ var ai_default = SvgAi;
37
+
38
+ // src/icons/brain-regular.svg
39
+ import * as React3 from "react";
40
+ import { jsx as jsx3 } from "react/jsx-runtime";
41
+ var SvgBrainRegular = (props) => /* @__PURE__ */ jsx3("svg", { width: "1em", height: "1em", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx3("path", { d: "M0 6.9375C0 6.30469 0.234375 5.69531 0.609375 5.25C0.5625 5.0625 0.5625 4.875 0.5625 4.6875C0.5625 3.9375 0.9375 3.25781 1.52344 2.85938C1.61719 2.17969 2.01562 1.59375 2.60156 1.26562C2.90625 0.515625 3.63281 0 4.5 0C5.08594 0 5.60156 0.257812 6 0.65625C6.375 0.257812 6.89062 0 7.5 0C8.34375 0 9.07031 0.515625 9.375 1.26562C9.96094 1.59375 10.3594 2.17969 10.4531 2.85938C11.0391 3.25781 11.4375 3.9375 11.4375 4.6875C11.4375 4.875 11.4141 5.0625 11.3672 5.25C11.7422 5.69531 12 6.30469 12 6.9375C12 7.66406 11.6953 8.32031 11.2266 8.78906L11.25 8.8125C11.25 9.9375 10.4297 10.8516 9.375 11.0391C9 11.625 8.34375 12 7.59375 12C6.96094 12 6.375 11.7422 6 11.2969C5.60156 11.7422 5.01562 12 4.40625 12C3.63281 12 2.97656 11.625 2.60156 11.0391C1.54688 10.8516 0.75 9.9375 0.75 8.8125V8.78906C0.28125 8.32031 0 7.66406 0 6.9375ZM5.41406 9.9375H5.4375V2.0625C5.4375 1.54688 5.01562 1.125 4.5 1.125C3.96094 1.125 3.5625 1.54688 3.5625 2.0625V2.08594C3.07031 2.17969 2.69531 2.55469 2.625 3.04688C2.625 3.09375 2.625 3.14062 2.625 3.1875C2.625 3.32812 2.625 3.46875 2.67188 3.58594C2.50781 3.60938 2.32031 3.65625 2.17969 3.75C1.89844 3.9375 1.71094 4.24219 1.6875 4.57031C1.6875 4.61719 1.6875 4.66406 1.6875 4.6875C1.6875 5.03906 1.82812 5.34375 2.0625 5.55469C1.71094 5.69531 1.40625 5.97656 1.24219 6.32812C1.17188 6.51562 1.10156 6.72656 1.10156 6.9375C1.10156 7.5 1.42969 7.99219 1.875 8.25C1.92188 8.27344 1.94531 8.29688 1.99219 8.32031C1.96875 8.34375 1.96875 8.36719 1.94531 8.39062C1.89844 8.53125 1.875 8.67188 1.875 8.8125C1.875 9.32812 2.20312 9.77344 2.67188 9.91406C2.76562 9.9375 2.88281 9.9375 3 9.9375C3.11719 9.9375 3.25781 9.91406 3.375 9.89062C3.375 10.1016 3.44531 10.3125 3.58594 10.4766C3.77344 10.7344 4.05469 10.875 4.40625 10.875C4.92188 10.875 5.36719 10.4766 5.41406 9.9375ZM8.41406 2.08594L8.4375 2.0625C8.4375 1.54688 8.01562 1.125 7.5 1.125C6.96094 1.125 6.5625 1.54688 6.5625 2.0625V9.9375C6.60938 10.4766 7.05469 10.875 7.59375 10.875C7.92188 10.875 8.20312 10.7344 8.39062 10.4766C8.53125 10.3125 8.60156 10.1016 8.60156 9.89062C8.71875 9.91406 8.85938 9.9375 9 9.9375C9.09375 9.9375 9.21094 9.9375 9.30469 9.91406C9.77344 9.77344 10.125 9.32812 10.125 8.8125C10.125 8.67188 10.0781 8.53125 10.0312 8.39062C10.0078 8.36719 10.0078 8.34375 9.98438 8.32031C10.0312 8.29688 10.0547 8.27344 10.1016 8.25C10.5469 7.99219 10.875 7.5 10.875 6.9375C10.875 6.72656 10.8047 6.51562 10.7344 6.32812C10.5703 5.97656 10.2656 5.69531 9.91406 5.55469C10.1484 5.34375 10.3125 5.03906 10.3125 4.6875C10.3125 4.66406 10.2891 4.61719 10.2891 4.57031C10.2656 4.24219 10.0781 3.9375 9.79688 3.75C9.65625 3.65625 9.46875 3.60938 9.30469 3.58594C9.35156 3.46875 9.375 3.32812 9.375 3.1875C9.375 3.14062 9.35156 3.09375 9.35156 3.04688C9.28125 2.55469 8.90625 2.17969 8.41406 2.08594Z", fill: "currentColor" }) });
42
+ var brain_regular_default = SvgBrainRegular;
43
+
44
+ // src/icons/compare.svg
45
+ import * as React4 from "react";
46
+ import { jsx as jsx4 } from "react/jsx-runtime";
47
+ var SvgCompare = (props) => /* @__PURE__ */ jsx4("svg", { width: "1em", height: "1em", viewBox: "0 0 14 17", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx4("path", { d: "M5.09091 16.5V15.0455H1.45455C1.05455 15.0455 0.712121 14.903 0.427273 14.6182C0.142424 14.3333 0 13.9909 0 13.5909V3.40909C0 3.00909 0.142424 2.66667 0.427273 2.38182C0.712121 2.09697 1.05455 1.95455 1.45455 1.95455H5.09091V0.5H6.54545V16.5H5.09091ZM8 15.0455V13.5909L11.6364 13.5909V3.40909H8V1.95455H11.6364C12.0364 1.95455 12.3788 2.09697 12.6636 2.38182C12.9485 2.66667 13.0909 3.00909 13.0909 3.40909V13.5909C13.0909 13.9909 12.9485 14.3333 12.6636 14.6182C12.3788 14.903 12.0364 15.0455 11.6364 15.0455H8Z", fill: "currentColor" }) });
48
+ var compare_default = SvgCompare;
49
+
50
+ // src/icons/mcp-server.svg
51
+ import * as React5 from "react";
52
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
53
+ var SvgMcpServer = (props) => /* @__PURE__ */ jsxs2("svg", { width: "1em", height: "1em", viewBox: "0 0 14 14", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
54
+ /* @__PURE__ */ jsxs2("g", { clipPath: "url(#clip0_5446_3655)", children: [
55
+ /* @__PURE__ */ jsx5("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M9.15174 1.36702C8.86989 1.09272 8.49212 0.939234 8.09883 0.939234C7.70553 0.939234 7.32776 1.09272 7.04591 1.36702L1.43074 6.87369C1.33678 6.96502 1.21091 7.01611 1.07987 7.01611C0.948831 7.01611 0.822958 6.96502 0.728994 6.87369C0.68299 6.82895 0.646423 6.77544 0.621453 6.71633C0.596483 6.65721 0.583618 6.59369 0.583618 6.52952C0.583618 6.46535 0.596483 6.40183 0.621453 6.34272C0.646423 6.2836 0.68299 6.23009 0.728994 6.18536L6.34416 0.678689C6.81387 0.221585 7.44341 -0.0341797 8.09883 -0.0341797C8.75424 -0.0341797 9.38379 0.221585 9.85349 0.678689C10.1253 0.943 10.3306 1.26791 10.4527 1.62683C10.5748 1.98575 10.6101 2.36848 10.5558 2.74369C10.936 2.68962 11.3235 2.72356 11.6885 2.8429C12.0535 2.96224 12.3863 3.16379 12.6611 3.43202L12.6902 3.46119C12.9203 3.68489 13.1031 3.95243 13.2279 4.248C13.3528 4.54357 13.4171 4.86117 13.4171 5.18202C13.4171 5.50288 13.3528 5.82048 13.2279 6.11605C13.1031 6.41162 12.9203 6.67916 12.6902 6.90286L7.61174 11.8828C7.59642 11.8977 7.58423 11.9155 7.57591 11.9352C7.56759 11.9549 7.5633 11.976 7.5633 11.9974C7.5633 12.0188 7.56759 12.0399 7.57591 12.0596C7.58423 12.0793 7.59642 12.0971 7.61174 12.112L8.65474 13.1352C8.70075 13.1799 8.73731 13.2334 8.76228 13.2926C8.78725 13.3517 8.80012 13.4152 8.80012 13.4794C8.80012 13.5435 8.78725 13.607 8.76228 13.6662C8.73731 13.7253 8.70075 13.7788 8.65474 13.8235C8.56078 13.9149 8.43491 13.9659 8.30387 13.9659C8.17283 13.9659 8.04696 13.9149 7.95299 13.8235L6.90999 12.8009C6.80257 12.6966 6.71717 12.5717 6.65886 12.4337C6.60054 12.2957 6.5705 12.1475 6.5705 11.9977C6.5705 11.8479 6.60054 11.6996 6.65886 11.5617C6.71717 11.4237 6.80257 11.2988 6.90999 11.1944L11.9885 6.21394C12.1264 6.07968 12.2361 5.91914 12.3109 5.74181C12.3858 5.56447 12.4244 5.37393 12.4244 5.18144C12.4244 4.98895 12.3858 4.79841 12.3109 4.62107C12.2361 4.44374 12.1264 4.2832 11.9885 4.14894L11.9593 4.12036C11.6778 3.84634 11.3005 3.69287 10.9076 3.69254C10.5148 3.69222 10.1372 3.84506 9.85524 4.11861L5.67158 8.22177L5.67041 8.22294L5.61324 8.27952C5.51925 8.37103 5.39326 8.42223 5.26208 8.42223C5.1309 8.42223 5.0049 8.37103 4.91091 8.27952C4.86491 8.23478 4.82834 8.18128 4.80337 8.12216C4.7784 8.06305 4.76553 7.99953 4.76553 7.93536C4.76553 7.87118 4.7784 7.80766 4.80337 7.74855C4.82834 7.68944 4.86491 7.63593 4.91091 7.59119L9.15349 3.43027C9.29105 3.29592 9.40033 3.1354 9.47488 2.95816C9.54943 2.78093 9.58776 2.59056 9.58759 2.39828C9.58743 2.206 9.54878 2.0157 9.47393 1.83859C9.39907 1.66147 9.28953 1.50114 9.15174 1.36702Z", fill: "currentColor" }),
56
+ /* @__PURE__ */ jsx5("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.44964 2.74425C8.49564 2.69951 8.53221 2.646 8.55718 2.58689C8.58215 2.52777 8.59501 2.46425 8.59501 2.40008C8.59501 2.33591 8.58215 2.27239 8.55718 2.21328C8.53221 2.15416 8.49564 2.10066 8.44964 2.05592C8.35564 1.96441 8.22965 1.91321 8.09847 1.91321C7.96729 1.91321 7.84129 1.96441 7.7473 2.05592L3.59455 6.12875C3.36454 6.35245 3.1817 6.61999 3.05685 6.91556C2.932 7.21113 2.86768 7.52873 2.86768 7.84958C2.86768 8.17044 2.932 8.48804 3.05685 8.78361C3.1817 9.07918 3.36454 9.34672 3.59455 9.57042C4.06433 10.0274 4.69385 10.2831 5.34922 10.2831C6.00459 10.2831 6.63411 10.0274 7.10389 9.57042L11.2572 5.49758C11.3032 5.45284 11.3398 5.39934 11.3648 5.34022C11.3897 5.28111 11.4026 5.21759 11.4026 5.15342C11.4026 5.08925 11.3897 5.02573 11.3648 4.96661C11.3398 4.9075 11.3032 4.85399 11.2572 4.80925C11.1632 4.71774 11.0372 4.66654 10.9061 4.66654C10.7749 4.66654 10.6489 4.71774 10.5549 4.80925L6.40214 8.88208C6.12029 9.15639 5.74252 9.30987 5.34922 9.30987C4.95592 9.30987 4.57815 9.15639 4.2963 8.88208C4.15836 8.74782 4.04873 8.58729 3.97386 8.40995C3.899 8.23261 3.86043 8.04207 3.86043 7.84958C3.86043 7.65709 3.899 7.46655 3.97386 7.28922C4.04873 7.11188 4.15836 6.95134 4.2963 6.81708L8.44964 2.74425Z", fill: "currentColor" })
57
+ ] }),
58
+ /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsx5("clipPath", { id: "clip0_5446_3655", children: /* @__PURE__ */ jsx5("rect", { width: 14, height: 14, fill: "white" }) }) })
59
+ ] });
60
+ var mcp_server_default = SvgMcpServer;
61
+
62
+ // src/icons/search-globe.svg
63
+ import * as React6 from "react";
64
+ import { jsx as jsx6 } from "react/jsx-runtime";
65
+ var SvgSearchGlobe = (props) => /* @__PURE__ */ jsx6("svg", { width: "1em", height: "1em", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx6("path", { d: "M7 0C10.8555 0 14 3.14453 14 7C14 10.8828 10.8555 14 7 14C3.11719 14 0 10.8828 0 7C0 3.14453 3.11719 0 7 0ZM7 12.6875C7.19141 12.6875 7.71094 12.4961 8.28516 11.375C8.53125 10.8828 8.72266 10.3086 8.88672 9.625H5.08594C5.25 10.3086 5.44141 10.8828 5.6875 11.375C6.26172 12.4961 6.78125 12.6875 7 12.6875ZM4.86719 8.3125H9.10547C9.16016 7.90234 9.1875 7.46484 9.1875 7C9.1875 6.5625 9.16016 6.125 9.10547 5.6875H4.86719C4.8125 6.125 4.8125 6.5625 4.8125 7C4.8125 7.46484 4.8125 7.90234 4.86719 8.3125ZM8.88672 4.375C8.72266 3.71875 8.53125 3.14453 8.28516 2.65234C7.71094 1.53125 7.19141 1.3125 7 1.3125C6.78125 1.3125 6.26172 1.53125 5.6875 2.65234C5.44141 3.14453 5.25 3.71875 5.08594 4.375H8.88672ZM10.418 5.6875C10.4727 6.125 10.5 6.5625 10.5 7C10.5 7.46484 10.4727 7.90234 10.418 8.3125H12.5234C12.6328 7.90234 12.6875 7.46484 12.6875 7C12.6875 6.5625 12.6328 6.125 12.5234 5.6875H10.418ZM9.35156 1.83203C9.73438 2.54297 10.0352 3.41797 10.2266 4.375H12.0312C11.457 3.25391 10.5 2.35156 9.35156 1.83203ZM4.62109 1.83203C3.47266 2.35156 2.51562 3.25391 1.94141 4.375H3.74609C3.9375 3.41797 4.23828 2.54297 4.62109 1.83203ZM1.3125 7C1.3125 7.46484 1.33984 7.90234 1.44922 8.3125H3.55469C3.5 7.90234 3.5 7.46484 3.5 7C3.5 6.5625 3.5 6.125 3.55469 5.6875H1.44922C1.33984 6.125 1.3125 6.5625 1.3125 7ZM12.0312 9.625H10.2266C10.0352 10.6094 9.73438 11.4844 9.35156 12.1953C10.5 11.6758 11.457 10.7734 12.0312 9.625ZM3.74609 9.625H1.94141C2.51562 10.7734 3.47266 11.6758 4.62109 12.1953C4.23828 11.4844 3.9375 10.6094 3.74609 9.625Z", fill: "currentColor" }) });
66
+ var search_globe_default = SvgSearchGlobe;
67
+
68
+ // src/icons/registerAgentIcons.ts
69
+ registerIcons({
70
+ "mcp-server": mcp_server_default,
71
+ "agent-2": agent_2_default,
72
+ compare: compare_default,
73
+ ai: ai_default,
74
+ searchGlobe: search_globe_default,
75
+ "brain-regular": brain_regular_default
76
+ });
77
+
3
78
  // src/theme/SlotsProvider.tsx
4
- import { createContext, useContext, useMemo as useMemo2 } from "react";
79
+ import { createContext, useContext, useMemo } from "react";
80
+ import {
81
+ ThemeProvider as TfyThemeProvider,
82
+ useTheme as useTfyTheme
83
+ } from "tfy-web-components/components/theme/useTheme";
84
+
85
+ // src/theme/defaultSlots.ts
86
+ import {
87
+ Accordion as Accordion2,
88
+ AccordionDetails as AccordionDetails2,
89
+ AccordionSummary as AccordionSummary2
90
+ } from "tfy-web-components/components/atoms/Accordion";
91
+ import Button2 from "tfy-web-components/components/atoms/Button";
92
+ import IconButton4 from "tfy-web-components/components/atoms/IconButton";
93
+ import Modal2 from "tfy-web-components/components/atoms/Modal";
94
+ import Skeleton3 from "tfy-web-components/components/atoms/Skeleton";
95
+ import { LightTooltip } from "tfy-web-components/components/atoms/Tooltip";
96
+ import Dialog from "tfy-web-components/components/molecules/Dialog";
97
+
98
+ // src/atoms/adapters/AskUserPromptAdapter.tsx
99
+ import {
100
+ AskUserQuestionCard as TfyAskUserQuestionCard
101
+ } from "tfy-web-components/components/molecules/agent-chat";
102
+ import { jsx as jsx7 } from "react/jsx-runtime";
103
+ function AskUserPrompt(props) {
104
+ return /* @__PURE__ */ jsx7(TfyAskUserQuestionCard, { ...props });
105
+ }
106
+
107
+ // src/atoms/adapters/McpAuthPromptAdapter.tsx
108
+ import {
109
+ McpAuthCard as TfyMcpAuthCard
110
+ } from "tfy-web-components/components/molecules/agent-chat";
111
+ import { jsx as jsx8 } from "react/jsx-runtime";
112
+ function McpAuthPrompt(props) {
113
+ return /* @__PURE__ */ jsx8(TfyMcpAuthCard, { ...props });
114
+ }
115
+
116
+ // src/atoms/adapters/ReasoningCardAdapter.tsx
117
+ import {
118
+ ReasoningCard as TfyReasoningCard
119
+ } from "tfy-web-components/components/molecules/agent-chat";
120
+ import { jsx as jsx9 } from "react/jsx-runtime";
121
+ function ReasoningCard(props) {
122
+ return /* @__PURE__ */ jsx9(TfyReasoningCard, { ...props });
123
+ }
5
124
 
6
125
  // src/atoms/primitives/Avatar.tsx
7
- import { Avatar as AvatarPrimitive } from "radix-ui";
126
+ import "react";
127
+ import TfyAvatar, {
128
+ AvatarImage as TfyAvatarImage,
129
+ AvatarFallback as TfyAvatarFallback
130
+ } from "tfy-web-components/components/atoms/Avatar";
8
131
 
9
132
  // src/atoms/lib/cn.ts
10
133
  import { clsx } from "clsx";
@@ -14,885 +137,253 @@ function cn(...inputs) {
14
137
  }
15
138
 
16
139
  // src/atoms/primitives/Avatar.tsx
17
- import { jsx } from "react/jsx-runtime";
140
+ import { jsx as jsx10 } from "react/jsx-runtime";
141
+ var AvatarRoot = TfyAvatar;
142
+ var AvatarImagePrimitive = TfyAvatarImage;
143
+ var AvatarFallbackPrimitive = TfyAvatarFallback;
18
144
  function Avatar({ className, size = "default", ...props }) {
19
- return /* @__PURE__ */ jsx(
20
- AvatarPrimitive.Root,
145
+ return /* @__PURE__ */ jsx10(
146
+ AvatarRoot,
21
147
  {
22
148
  "data-slot": "avatar",
23
149
  "data-size": size,
24
- className: cn(
25
- "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
26
- className
27
- ),
150
+ size,
151
+ className: cn(className),
28
152
  ...props
29
153
  }
30
154
  );
31
155
  }
32
156
  function AvatarImage({ className, ...props }) {
33
- return /* @__PURE__ */ jsx(
34
- AvatarPrimitive.Image,
35
- {
36
- "data-slot": "avatar-image",
37
- className: cn("aspect-square size-full rounded-full object-cover", className),
38
- ...props
39
- }
40
- );
157
+ return /* @__PURE__ */ jsx10(AvatarImagePrimitive, { "data-slot": "avatar-image", className: cn(className), ...props });
41
158
  }
42
159
  function AvatarFallback({ className, ...props }) {
43
- return /* @__PURE__ */ jsx(
44
- AvatarPrimitive.Fallback,
45
- {
46
- "data-slot": "avatar-fallback",
47
- className: cn(
48
- "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
49
- className
50
- ),
51
- ...props
52
- }
53
- );
160
+ return /* @__PURE__ */ jsx10(AvatarFallbackPrimitive, { "data-slot": "avatar-fallback", className: cn(className), ...props });
54
161
  }
55
162
 
56
- // src/atoms/primitives/Button.tsx
57
- import { cva } from "class-variance-authority";
58
- import { Slot } from "radix-ui";
59
- import { jsx as jsx2 } from "react/jsx-runtime";
60
- var buttonVariants = cva(
61
- "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
62
- {
63
- variants: {
64
- variant: {
65
- default: "bg-primary text-primary-foreground hover:bg-primary/80",
66
- outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
67
- secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
68
- ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
69
- destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
70
- link: "text-primary underline-offset-4 hover:underline"
71
- },
72
- size: {
73
- default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
74
- xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
75
- sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
76
- lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
77
- icon: "size-8",
78
- "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
79
- "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
80
- "icon-lg": "size-9"
81
- }
82
- },
83
- defaultVariants: {
84
- variant: "default",
85
- size: "default"
86
- }
87
- }
88
- );
89
- function Button({
90
- className,
91
- variant = "default",
92
- size = "default",
93
- asChild = false,
94
- ...props
95
- }) {
96
- const Comp = asChild ? Slot.Root : "button";
97
- return /* @__PURE__ */ jsx2(
98
- Comp,
99
- {
100
- "data-slot": "button",
101
- "data-variant": variant,
102
- "data-size": size,
103
- className: cn(buttonVariants({ variant, size, className })),
104
- ...props
105
- }
106
- );
107
- }
108
-
109
- // src/atoms/primitives/Collapsible.tsx
110
- import { Collapsible as CollapsiblePrimitive } from "radix-ui";
111
- import { jsx as jsx3 } from "react/jsx-runtime";
112
- function Collapsible(props) {
113
- return /* @__PURE__ */ jsx3(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
114
- }
115
- function CollapsibleTrigger(props) {
116
- return /* @__PURE__ */ jsx3(CollapsiblePrimitive.CollapsibleTrigger, { "data-slot": "collapsible-trigger", ...props });
117
- }
118
- function CollapsibleContent(props) {
119
- return /* @__PURE__ */ jsx3(CollapsiblePrimitive.CollapsibleContent, { "data-slot": "collapsible-content", ...props });
120
- }
121
-
122
- // src/atoms/primitives/Dialog.tsx
123
- import { Dialog as DialogPrimitive } from "radix-ui";
124
- import { XIcon } from "lucide-react";
125
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
126
- function Dialog(props) {
127
- return /* @__PURE__ */ jsx4(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
128
- }
129
- function DialogTrigger(props) {
130
- return /* @__PURE__ */ jsx4(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
131
- }
132
- function DialogPortal(props) {
133
- return /* @__PURE__ */ jsx4(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
134
- }
135
- function DialogClose(props) {
136
- return /* @__PURE__ */ jsx4(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
137
- }
138
- function DialogOverlay({ className, ...props }) {
139
- return /* @__PURE__ */ jsx4(
140
- DialogPrimitive.Overlay,
141
- {
142
- "data-slot": "dialog-overlay",
143
- className: cn(
144
- "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
145
- className
146
- ),
147
- ...props
148
- }
149
- );
150
- }
151
- function DialogContent({
152
- className,
153
- children,
154
- showCloseButton = true,
155
- ...props
156
- }) {
157
- return /* @__PURE__ */ jsxs(DialogPortal, { children: [
158
- /* @__PURE__ */ jsx4(DialogOverlay, {}),
159
- /* @__PURE__ */ jsxs(
160
- DialogPrimitive.Content,
161
- {
162
- "data-slot": "dialog-content",
163
- className: cn(
164
- "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
165
- className
166
- ),
167
- ...props,
168
- children: [
169
- children,
170
- showCloseButton && /* @__PURE__ */ jsx4(DialogPrimitive.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", className: "absolute top-2 right-2", size: "icon-sm", children: [
171
- /* @__PURE__ */ jsx4(XIcon, {}),
172
- /* @__PURE__ */ jsx4("span", { className: "sr-only", children: "Close" })
173
- ] }) })
174
- ]
175
- }
176
- )
177
- ] });
178
- }
179
- function DialogHeader({ className, ...props }) {
180
- return /* @__PURE__ */ jsx4("div", { "data-slot": "dialog-header", className: cn("flex flex-col gap-2", className), ...props });
181
- }
182
- function DialogFooter({ className, showCloseButton = false, children, ...props }) {
183
- return /* @__PURE__ */ jsxs(
163
+ // src/atoms/UserMessageBubble.tsx
164
+ import { UserMessage } from "tfy-web-components/components/molecules/agent-chat";
165
+ import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
166
+ function UserMessageBubble({ text, attachments, editAction, className }) {
167
+ return /* @__PURE__ */ jsxs3(
184
168
  "div",
185
169
  {
186
- "data-slot": "dialog-footer",
187
- className: cn(
188
- "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
189
- className
190
- ),
191
- ...props,
170
+ "data-slot": "aui_user-message-root",
171
+ className: cn("fade-in slide-in-from-bottom-1 animate-in duration-150", className),
192
172
  children: [
193
- children,
194
- showCloseButton && /* @__PURE__ */ jsx4(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx4(Button, { variant: "outline", children: "Close" }) })
173
+ attachments,
174
+ /* @__PURE__ */ jsx11(UserMessage, { text, editAction, actionsAlwaysVisible: true })
195
175
  ]
196
176
  }
197
177
  );
198
178
  }
199
- function DialogTitle({ className, ...props }) {
200
- return /* @__PURE__ */ jsx4(
201
- DialogPrimitive.Title,
202
- {
203
- "data-slot": "dialog-title",
204
- className: cn("font-heading text-base leading-none font-medium", className),
205
- ...props
206
- }
207
- );
208
- }
209
- function DialogDescription({ className, ...props }) {
210
- return /* @__PURE__ */ jsx4(
211
- DialogPrimitive.Description,
212
- {
213
- "data-slot": "dialog-description",
214
- className: cn(
215
- "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
216
- className
217
- ),
218
- ...props
219
- }
220
- );
221
- }
222
179
 
223
- // src/atoms/primitives/IconButton.tsx
180
+ // src/atoms/UserMessageEdit.tsx
224
181
  import { forwardRef } from "react";
225
- import { Slot as Slot2 } from "radix-ui";
226
-
227
- // src/atoms/primitives/Tooltip.tsx
228
- import { Tooltip as TooltipPrimitive } from "radix-ui";
229
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
230
- function TooltipProvider({ delayDuration = 0, ...props }) {
231
- return /* @__PURE__ */ jsx5(
232
- TooltipPrimitive.Provider,
182
+ import TfyUserMessageEdit from "tfy-web-components/components/molecules/agent-chat/UserMessageEdit";
183
+ import { jsx as jsx12 } from "react/jsx-runtime";
184
+ var UserMessageEdit = forwardRef(function UserMessageEdit2({ timestamp, attachments, input, footer, className, ...rest }, ref) {
185
+ return /* @__PURE__ */ jsx12(
186
+ TfyUserMessageEdit,
233
187
  {
234
- "data-slot": "tooltip-provider",
235
- delayDuration,
236
- ...props
188
+ ref,
189
+ "data-slot": "aui_user-message-edit",
190
+ timestamp,
191
+ attachments,
192
+ input,
193
+ footer,
194
+ className: cn(className),
195
+ ...rest
237
196
  }
238
197
  );
239
- }
240
- function Tooltip(props) {
241
- return /* @__PURE__ */ jsx5(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
242
- }
243
- function TooltipTrigger(props) {
244
- return /* @__PURE__ */ jsx5(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
245
- }
246
- function TooltipContent({ className, sideOffset = 0, children, ...props }) {
247
- return /* @__PURE__ */ jsx5(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs2(
248
- TooltipPrimitive.Content,
249
- {
250
- "data-slot": "tooltip-content",
251
- sideOffset,
252
- className: cn(
253
- "z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
254
- className
255
- ),
256
- ...props,
257
- children: [
258
- children,
259
- /* @__PURE__ */ jsx5(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
260
- ]
261
- }
262
- ) });
263
- }
198
+ });
264
199
 
265
- // src/atoms/primitives/IconButton.tsx
266
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
267
- var IconButton = forwardRef(
268
- ({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
269
- return /* @__PURE__ */ jsx6(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(Tooltip, { children: [
270
- /* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
271
- Button,
272
- {
273
- variant: "ghost",
274
- size: "icon",
275
- ...rest,
276
- className: cn("aui-button-icon size-6 p-1 active:scale-90", className),
277
- ref,
278
- children: [
279
- /* @__PURE__ */ jsx6(Slot2.Slottable, { children }),
280
- /* @__PURE__ */ jsx6("span", { className: "aui-sr-only sr-only", children: tooltip })
281
- ]
282
- }
283
- ) }),
284
- /* @__PURE__ */ jsx6(TooltipContent, { side, children: tooltip })
285
- ] }) });
286
- }
287
- );
288
- IconButton.displayName = "IconButton";
289
-
290
- // src/atoms/primitives/Skeleton.tsx
291
- import { jsx as jsx7 } from "react/jsx-runtime";
292
- function Skeleton({ className, ...props }) {
293
- return /* @__PURE__ */ jsx7("div", { "data-slot": "skeleton", className: cn("animate-pulse rounded-md bg-muted", className), ...props });
294
- }
295
-
296
- // src/atoms/BranchIndicator.tsx
297
- import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
298
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
299
- function BranchIndicator({ index, count, onPrevious, onNext, className }) {
300
- if (count <= 1) return null;
301
- return /* @__PURE__ */ jsxs4(
302
- "div",
200
+ // src/atoms/ToolCallCard.tsx
201
+ import {
202
+ ToolCallCard as TfyToolCallCard
203
+ } from "tfy-web-components/components/molecules/agent-chat";
204
+ import { jsx as jsx13 } from "react/jsx-runtime";
205
+ function ToolCallCard(props) {
206
+ const { mcpServerName, ...tfyProps } = props;
207
+ return /* @__PURE__ */ jsx13(
208
+ TfyToolCallCard,
303
209
  {
304
- className: cn(
305
- "aui-branch-picker-root text-muted-foreground -ms-2 me-2 inline-flex items-center text-xs",
306
- className
307
- ),
308
- children: [
309
- /* @__PURE__ */ jsx8(IconButton, { tooltip: "Previous", onClick: onPrevious, children: /* @__PURE__ */ jsx8(ChevronLeftIcon, {}) }),
310
- /* @__PURE__ */ jsxs4("span", { className: "aui-branch-picker-state font-medium", children: [
311
- index,
312
- " / ",
313
- count
314
- ] }),
315
- /* @__PURE__ */ jsx8(IconButton, { tooltip: "Next", onClick: onNext, children: /* @__PURE__ */ jsx8(ChevronRightIcon, {}) })
316
- ]
210
+ ...tfyProps,
211
+ className: cn("aui-tool-call-card", props.className)
317
212
  }
318
213
  );
319
214
  }
320
215
 
321
- // src/atoms/CodeBlockHeader.tsx
322
- import { useState } from "react";
323
- import { CheckIcon, CopyIcon } from "lucide-react";
324
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
325
- function CodeBlockHeader({ language, code }) {
326
- const [isCopied, setIsCopied] = useState(false);
327
- const onCopy = () => {
328
- if (!code || isCopied || typeof navigator === "undefined" || !navigator.clipboard) {
329
- return;
330
- }
331
- navigator.clipboard.writeText(code).then(
332
- () => {
333
- setIsCopied(true);
334
- setTimeout(() => setIsCopied(false), 3e3);
335
- },
336
- () => {
337
- }
338
- );
339
- };
340
- return /* @__PURE__ */ jsxs5("div", { className: "aui-code-header-root border-border/50 bg-muted/50 mt-3 flex items-center justify-between rounded-t-xl border border-b-0 px-3.5 py-1.5 text-xs", children: [
341
- /* @__PURE__ */ jsx9("span", { className: "aui-code-header-language text-muted-foreground font-medium lowercase", children: language }),
342
- /* @__PURE__ */ jsxs5(IconButton, { tooltip: "Copy", onClick: onCopy, children: [
343
- !isCopied && /* @__PURE__ */ jsx9(CopyIcon, { className: "animate-in zoom-in-75 fade-in duration-150" }),
344
- isCopied && /* @__PURE__ */ jsx9(CheckIcon, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" })
345
- ] })
346
- ] });
347
- }
348
-
349
- // src/atoms/Markdown.tsx
350
- import { Children, isValidElement, useMemo } from "react";
351
- import ReactMarkdown from "react-markdown";
352
- import remarkGfm from "remark-gfm";
353
-
354
- // src/atoms/OpenUIBlock.tsx
355
- import { memo, useId } from "react";
356
- import { Renderer } from "@openuidev/react-lang";
357
- import { ThemeProvider } from "@openuidev/react-ui";
358
- import { openuiLibrary } from "@openuidev/react-ui/genui-lib";
359
-
360
- // src/theme/useClassDarkMode.ts
361
- import { useSyncExternalStore } from "react";
362
- function getThemeMode() {
363
- if (typeof document === "undefined") {
364
- return "light";
365
- }
366
- return document.documentElement.classList.contains("dark") ? "dark" : "light";
367
- }
368
- function subscribe(onStoreChange) {
369
- const observer = new MutationObserver(onStoreChange);
370
- observer.observe(document.documentElement, {
371
- attributes: true,
372
- attributeFilter: ["class"]
373
- });
374
- return () => observer.disconnect();
375
- }
376
- function useClassDarkMode() {
377
- return useSyncExternalStore(subscribe, getThemeMode, () => "light");
378
- }
379
-
380
- // src/atoms/OpenUIBlock.tsx
381
- import { jsx as jsx10 } from "react/jsx-runtime";
382
- var OpenUIBlock = memo(
383
- function OpenUIBlock2({ source, isStreaming, className, mode: modeProp }) {
384
- const detectedMode = useClassDarkMode();
385
- const mode = modeProp ?? detectedMode;
386
- const scopeClass = `aui-openui-theme-${useId().replace(/:/g, "")}`;
387
- return /* @__PURE__ */ jsx10(ThemeProvider, { mode, cssSelector: `.${scopeClass}`, children: /* @__PURE__ */ jsx10(
388
- "div",
389
- {
390
- "data-slot": "openui-block",
391
- className: cn("aui-openui-block my-3", scopeClass, className),
392
- style: { contain: "layout paint" },
393
- children: /* @__PURE__ */ jsx10(
394
- Renderer,
395
- {
396
- response: source,
397
- library: openuiLibrary,
398
- isStreaming: !!isStreaming
399
- }
400
- )
401
- }
402
- ) });
403
- },
404
- (prev, next) => prev.source === next.source && !!prev.isStreaming === !!next.isStreaming && prev.mode === next.mode
405
- );
406
-
407
- // src/atoms/SandboxArtifactList.tsx
408
- import { useState as useState2 } from "react";
409
- import { DownloadIcon, FileIcon, LoaderIcon } from "lucide-react";
410
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
411
- function SandboxArtifactList({ artifacts, onDownload, className }) {
412
- const [downloadingPath, setDownloadingPath] = useState2(null);
413
- const handleClick = async (path) => {
414
- if (downloadingPath != null) return;
415
- setDownloadingPath(path);
416
- try {
417
- await onDownload?.(path);
418
- } finally {
419
- setDownloadingPath(null);
420
- }
421
- };
422
- return /* @__PURE__ */ jsx11(
423
- "div",
216
+ // src/atoms/ToolCallContentBlock.tsx
217
+ import {
218
+ ToolCallContentBlock as TfyToolCallContentBlock
219
+ } from "tfy-web-components/components/molecules/agent-chat";
220
+ import { jsx as jsx14 } from "react/jsx-runtime";
221
+ function ToolCallContentBlock(props) {
222
+ return /* @__PURE__ */ jsx14(TfyToolCallContentBlock, { ...props });
223
+ }
224
+
225
+ // src/atoms/SubAgentCard.tsx
226
+ import { SubAgentCard as TfySubAgentCard } from "tfy-web-components/components/molecules/agent-chat";
227
+ import { jsx as jsx15 } from "react/jsx-runtime";
228
+ function SubAgentCard({
229
+ agentName,
230
+ instruction,
231
+ stepCount,
232
+ status,
233
+ expanded,
234
+ onToggle,
235
+ durationText,
236
+ children,
237
+ className
238
+ }) {
239
+ const Markdown2 = useSlot("Markdown");
240
+ return /* @__PURE__ */ jsx15(
241
+ TfySubAgentCard,
424
242
  {
425
- "data-slot": "aui_sandbox-artifact-list",
426
- className: cn("aui-sandbox-artifact-list my-3 flex w-fit max-w-full flex-wrap items-stretch text-sm", className),
427
- children: artifacts.map((artifact, index) => {
428
- const isDownloading = downloadingPath === artifact.path;
429
- return /* @__PURE__ */ jsxs6(
430
- "button",
431
- {
432
- type: "button",
433
- className: cn(
434
- "aui-sandbox-artifact-button text-muted-foreground hover:text-foreground flex min-w-0 items-center gap-1.5 py-1 pr-2 pl-2 transition-colors disabled:pointer-events-none disabled:opacity-70",
435
- index > 0 && "border-border/60 ml-1 border-l pl-3"
436
- ),
437
- disabled: isDownloading,
438
- onClick: () => handleClick(artifact.path),
439
- children: [
440
- /* @__PURE__ */ jsx11(FileIcon, { className: "size-4 shrink-0", "aria-hidden": true }),
441
- /* @__PURE__ */ jsx11("span", { className: "max-w-40 truncate", children: artifact.label }),
442
- isDownloading ? /* @__PURE__ */ jsx11(LoaderIcon, { className: "size-3.5 shrink-0 animate-spin [animation-duration:0.6s]", "aria-hidden": true }) : /* @__PURE__ */ jsx11(DownloadIcon, { className: "size-3.5 shrink-0", "aria-hidden": true })
443
- ]
444
- },
445
- artifact.path
446
- );
447
- })
243
+ agentName,
244
+ instruction,
245
+ stepCount,
246
+ status,
247
+ expanded,
248
+ onToggle,
249
+ durationText,
250
+ renderInstruction: (content) => /* @__PURE__ */ jsx15(Markdown2, { content }),
251
+ className: cn("aui-sub-agent-card", className),
252
+ children
448
253
  }
449
254
  );
450
255
  }
451
256
 
452
- // src/atoms/Markdown.tsx
453
- import { Fragment, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
454
- function extractCodeText(node) {
455
- if (typeof node === "string") return node;
456
- if (typeof node === "number") return String(node);
457
- if (Array.isArray(node)) return node.map(extractCodeText).join("");
458
- if (isValidElement(node)) {
459
- return extractCodeText(node.props.children);
460
- }
461
- return "";
462
- }
463
- var SANDBOX_ARTIFACT_TOKEN = "sandbox_artifact";
464
- function parseSandboxArtifactCodeBlock(code) {
465
- const links = [];
466
- for (const match of code.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g)) {
467
- links.push({ label: match[1], path: match[2] });
468
- }
469
- return links.length > 0 ? links : null;
470
- }
471
- function parseSandboxArtifactParagraph(children) {
472
- const items = Children.toArray(children);
473
- if (items.length === 0) return null;
474
- const first = items[0];
475
- if (typeof first !== "string") return null;
476
- const stripped = first.replace(/^\s*/, "");
477
- if (!stripped.startsWith(SANDBOX_ARTIFACT_TOKEN)) return null;
478
- if (!/^\s*$/.test(stripped.slice(SANDBOX_ARTIFACT_TOKEN.length))) return null;
479
- const links = [];
480
- for (let i = 1; i < items.length; i++) {
481
- const item = items[i];
482
- if (typeof item === "string") {
483
- const trimmed = item.trim();
484
- if (trimmed === "" || trimmed === SANDBOX_ARTIFACT_TOKEN) continue;
485
- return null;
486
- }
487
- if (isValidElement(item) && typeof item.props.href === "string") {
488
- links.push({
489
- label: extractCodeText(item.props.children),
490
- path: item.props.href
491
- });
492
- continue;
493
- }
494
- return null;
495
- }
496
- return links.length > 0 ? links : null;
497
- }
498
- function createMarkdownComponents(isStreaming, onDownloadArtifact) {
499
- return {
500
- h1: ({ className, ...props }) => /* @__PURE__ */ jsx12(
501
- "h1",
502
- {
503
- className: cn(
504
- "aui-md-h1 mt-5 mb-2 scroll-m-20 text-xl font-semibold first:mt-0 last:mb-0",
505
- className
506
- ),
507
- ...props
508
- }
509
- ),
510
- h2: ({ className, ...props }) => /* @__PURE__ */ jsx12(
511
- "h2",
512
- {
513
- className: cn(
514
- "aui-md-h2 mt-5 mb-2 scroll-m-20 text-lg font-semibold first:mt-0 last:mb-0",
515
- className
516
- ),
517
- ...props
518
- }
519
- ),
520
- h3: ({ className, ...props }) => /* @__PURE__ */ jsx12(
521
- "h3",
522
- {
523
- className: cn(
524
- "aui-md-h3 mt-4 mb-1.5 scroll-m-20 text-base font-semibold first:mt-0 last:mb-0",
525
- className
526
- ),
527
- ...props
528
- }
529
- ),
530
- h4: ({ className, ...props }) => /* @__PURE__ */ jsx12(
531
- "h4",
532
- {
533
- className: cn(
534
- "aui-md-h4 mt-3.5 mb-1 scroll-m-20 text-base font-medium first:mt-0 last:mb-0",
535
- className
536
- ),
537
- ...props
538
- }
539
- ),
540
- h5: ({ className, ...props }) => /* @__PURE__ */ jsx12(
541
- "h5",
542
- {
543
- className: cn("aui-md-h5 mt-3 mb-1 text-sm font-semibold first:mt-0 last:mb-0", className),
544
- ...props
545
- }
546
- ),
547
- h6: ({ className, ...props }) => /* @__PURE__ */ jsx12(
548
- "h6",
549
- {
550
- className: cn("aui-md-h6 mt-3 mb-1 text-sm font-medium first:mt-0 last:mb-0", className),
551
- ...props
552
- }
553
- ),
554
- p: ({ className, children, ...props }) => {
555
- const artifacts = parseSandboxArtifactParagraph(children);
556
- if (artifacts != null) {
557
- return /* @__PURE__ */ jsx12(SandboxArtifactList, { artifacts, onDownload: onDownloadArtifact });
558
- }
559
- return /* @__PURE__ */ jsx12("p", { className: cn("aui-md-p my-3 leading-relaxed first:mt-0 last:mb-0", className), ...props, children });
560
- },
561
- a: ({ className, ...props }) => /* @__PURE__ */ jsx12(
562
- "a",
563
- {
564
- className: cn(
565
- "aui-md-a text-primary hover:text-primary/80 underline underline-offset-2",
566
- className
567
- ),
568
- target: "_blank",
569
- rel: "noopener noreferrer",
570
- ...props
571
- }
572
- ),
573
- blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx12(
574
- "blockquote",
575
- {
576
- className: cn(
577
- "aui-md-blockquote border-muted-foreground/30 text-muted-foreground my-3 border-s-2 ps-4",
578
- className
579
- ),
580
- ...props
581
- }
582
- ),
583
- ul: ({ className, ...props }) => /* @__PURE__ */ jsx12(
584
- "ul",
585
- {
586
- className: cn(
587
- "aui-md-ul marker:text-muted-foreground my-3 ms-5 list-disc [&>li]:mt-1",
588
- className
589
- ),
590
- ...props
591
- }
592
- ),
593
- ol: ({ className, ...props }) => /* @__PURE__ */ jsx12(
594
- "ol",
595
- {
596
- className: cn(
597
- "aui-md-ol marker:text-muted-foreground my-3 ms-5 list-decimal [&>li]:mt-1",
598
- className
599
- ),
600
- ...props
601
- }
602
- ),
603
- hr: ({ className, ...props }) => /* @__PURE__ */ jsx12("hr", { className: cn("aui-md-hr border-muted-foreground/20 my-3", className), ...props }),
604
- table: ({ className, ...props }) => /* @__PURE__ */ jsx12(
605
- "table",
606
- {
607
- className: cn(
608
- "aui-md-table my-3 w-full border-separate border-spacing-0 overflow-y-auto",
609
- className
610
- ),
611
- ...props
612
- }
613
- ),
614
- th: ({ className, ...props }) => /* @__PURE__ */ jsx12(
615
- "th",
616
- {
617
- className: cn(
618
- "aui-md-th bg-muted px-3 py-1.5 text-start font-medium first:rounded-ss-lg last:rounded-se-lg [[align=center]]:text-center [[align=right]]:text-right",
619
- className
620
- ),
621
- ...props
622
- }
623
- ),
624
- td: ({ className, ...props }) => /* @__PURE__ */ jsx12(
625
- "td",
626
- {
627
- className: cn(
628
- "aui-md-td border-muted-foreground/20 border-s border-b px-3 py-1.5 text-start last:border-e [[align=center]]:text-center [[align=right]]:text-right",
629
- className
630
- ),
631
- ...props
632
- }
633
- ),
634
- tr: ({ className, ...props }) => /* @__PURE__ */ jsx12(
635
- "tr",
636
- {
637
- className: cn(
638
- "aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-es-lg [&:last-child>td:last-child]:rounded-ee-lg",
639
- className
640
- ),
641
- ...props
642
- }
643
- ),
644
- li: ({ className, ...props }) => /* @__PURE__ */ jsx12("li", { className: cn("aui-md-li leading-relaxed", className), ...props }),
645
- strong: ({ className, ...props }) => /* @__PURE__ */ jsx12("strong", { className: cn("aui-md-strong font-semibold", className), ...props }),
646
- sup: ({ className, ...props }) => /* @__PURE__ */ jsx12("sup", { className: cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className), ...props }),
647
- pre: ({ className, children, ...props }) => {
648
- const codeElement = isValidElement(children) ? children : void 0;
649
- const codeClassName = codeElement?.props?.className ?? "";
650
- const language = /language-(\S+)/.exec(codeClassName)?.[1] ?? "text";
651
- const code = extractCodeText(children);
652
- if (language === "openui") {
653
- return /* @__PURE__ */ jsx12(OpenUIBlock, { source: code, isStreaming });
654
- }
655
- if (language === "sandbox_artifact" || language === "sandbox_artifacts") {
656
- const artifacts = parseSandboxArtifactCodeBlock(code);
657
- if (artifacts != null) {
658
- return /* @__PURE__ */ jsx12(SandboxArtifactList, { artifacts, onDownload: onDownloadArtifact });
659
- }
660
- }
661
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
662
- /* @__PURE__ */ jsx12(CodeBlockHeader, { language, code }),
663
- /* @__PURE__ */ jsx12(
664
- "pre",
665
- {
666
- className: cn(
667
- "aui-md-pre border-border/50 bg-muted/30 overflow-x-auto rounded-t-none rounded-b-xl border border-t-0 p-3.5 text-[13px] leading-relaxed",
668
- className
669
- ),
670
- ...props,
671
- children
672
- }
673
- )
674
- ] });
675
- },
676
- code: ({ className, ...props }) => {
677
- const isCodeBlock = /language-/.test(className ?? "");
678
- return /* @__PURE__ */ jsx12(
679
- "code",
680
- {
681
- className: cn(
682
- !isCodeBlock && "aui-md-inline-code bg-muted rounded-md px-1.5 py-0.5 font-mono text-[0.85em]",
683
- className
684
- ),
685
- ...props
686
- }
687
- );
257
+ // src/atoms/SandboxToolCallCard.tsx
258
+ import {
259
+ SandboxToolCall,
260
+ ToolCallCard as TfyToolCallCard2
261
+ } from "tfy-web-components/components/molecules/agent-chat";
262
+ import { jsx as jsx16 } from "react/jsx-runtime";
263
+ function SandboxToolCallCard({
264
+ name,
265
+ intent,
266
+ status,
267
+ expanded,
268
+ onToggle,
269
+ command,
270
+ exitCode,
271
+ argsJson,
272
+ resultText,
273
+ resultJson,
274
+ viewMode,
275
+ hasContent,
276
+ onViewModeChange,
277
+ durationText,
278
+ className
279
+ }) {
280
+ const awaiting = status === "running";
281
+ const sandboxContent = /* @__PURE__ */ jsx16(
282
+ SandboxToolCall,
283
+ {
284
+ command,
285
+ exitCode,
286
+ argsJson,
287
+ resultText,
288
+ resultJson,
289
+ viewMode,
290
+ hasContent,
291
+ onViewModeChange
688
292
  }
689
- };
690
- }
691
- function Markdown({ content, className, isStreaming, onDownloadArtifact }) {
692
- const components = useMemo(
693
- () => createMarkdownComponents(isStreaming, onDownloadArtifact),
694
- [isStreaming, onDownloadArtifact]
695
293
  );
696
- return /* @__PURE__ */ jsx12("div", { className: cn("aui-md", className), children: /* @__PURE__ */ jsx12(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children: content }) });
697
- }
698
-
699
- // src/atoms/MessageActionBar.tsx
700
- import { CheckIcon as CheckIcon2, CopyIcon as CopyIcon2, DownloadIcon as DownloadIcon2, MoreHorizontalIcon } from "lucide-react";
701
- import { DropdownMenu } from "radix-ui";
702
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
703
- function MessageActionBar({ isCopied, onCopy, onExportMarkdown, className }) {
704
- return /* @__PURE__ */ jsxs8(
705
- "div",
294
+ return /* @__PURE__ */ jsx16(
295
+ TfyToolCallCard2,
706
296
  {
707
- className: cn(
708
- "aui-assistant-action-bar-root text-muted-foreground animate-in fade-in flex gap-1 duration-200",
709
- className
710
- ),
711
- children: [
712
- /* @__PURE__ */ jsx13(IconButton, { tooltip: "Copy", onClick: onCopy, children: isCopied ? /* @__PURE__ */ jsx13(CheckIcon2, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" }) : /* @__PURE__ */ jsx13(CopyIcon2, { className: "animate-in zoom-in-75 fade-in duration-150" }) }),
713
- /* @__PURE__ */ jsxs8(DropdownMenu.Root, { children: [
714
- /* @__PURE__ */ jsx13(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx13(IconButton, { tooltip: "More", className: "data-[state=open]:bg-accent", children: /* @__PURE__ */ jsx13(MoreHorizontalIcon, {}) }) }),
715
- /* @__PURE__ */ jsx13(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx13(
716
- DropdownMenu.Content,
717
- {
718
- side: "bottom",
719
- align: "start",
720
- sideOffset: 6,
721
- className: "aui-action-bar-more-content bg-popover/95 text-popover-foreground data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:animate-out data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm",
722
- children: /* @__PURE__ */ jsxs8(
723
- DropdownMenu.Item,
724
- {
725
- onSelect: onExportMarkdown,
726
- className: "aui-action-bar-more-item hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
727
- children: [
728
- /* @__PURE__ */ jsx13(DownloadIcon2, { className: "size-4" }),
729
- "Export as Markdown"
730
- ]
731
- }
732
- )
733
- }
734
- ) })
735
- ] })
736
- ]
297
+ toolName: intent || name,
298
+ icon: "cube",
299
+ iconClassName: "text-indigo-600 dark:text-gray-750 shrink-0",
300
+ expanded,
301
+ onToggle,
302
+ awaiting,
303
+ awaitingText: durationText ?? "Running\u2026",
304
+ showResponseLine: false,
305
+ requestSlot: sandboxContent,
306
+ className: cn("aui-sandbox-tool-call-card", className)
737
307
  }
738
308
  );
739
309
  }
740
310
 
741
- // src/atoms/UserMessageActionBar.tsx
742
- import { ActionBarPrimitive, useAui, useAuiState } from "@assistant-ui/react";
743
- import { useActionBarCopy } from "@assistant-ui/core/react";
744
- import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, PencilIcon, RotateCcwIcon } from "lucide-react";
745
- import { trueFoundryExtras } from "@truefoundry/assistant-ui-runtime";
746
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
747
- function parseTurnIdFromMessageId(messageId) {
748
- return messageId.replace(/-user$/, "");
749
- }
750
- function UserMessageActionBar({ className }) {
751
- const IconButton2 = useSlot("IconButton");
752
- const aui = useAui();
753
- const messageId = useAuiState((s) => s.message.id);
754
- const turnId = parseTurnIdFromMessageId(messageId);
755
- const { isCopied } = useActionBarCopy();
756
- return /* @__PURE__ */ jsxs9(
757
- ActionBarPrimitive.Root,
311
+ // src/atoms/ToolApprovalBar.tsx
312
+ import {
313
+ ToolApprovalBlock
314
+ } from "tfy-web-components/components/molecules/agent-chat";
315
+ import { jsx as jsx17 } from "react/jsx-runtime";
316
+ function ToolApprovalBar({ className, ...props }) {
317
+ return /* @__PURE__ */ jsx17(
318
+ ToolApprovalBlock,
758
319
  {
759
- hideWhenRunning: true,
760
- className: cn(
761
- "aui-user-action-bar-root text-muted-foreground animate-in fade-in flex gap-1 duration-200",
762
- className
763
- ),
764
- children: [
765
- /* @__PURE__ */ jsx14(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx14(IconButton2, { tooltip: "Edit", children: /* @__PURE__ */ jsx14(PencilIcon, {}) }) }),
766
- /* @__PURE__ */ jsx14(
767
- IconButton2,
768
- {
769
- tooltip: "Reset",
770
- onClick: () => void trueFoundryExtras.get(aui).resetFromTurn(turnId),
771
- children: /* @__PURE__ */ jsx14(RotateCcwIcon, {})
772
- }
773
- ),
774
- /* @__PURE__ */ jsx14(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsx14(IconButton2, { tooltip: "Copy", children: isCopied ? /* @__PURE__ */ jsx14(CheckIcon3, { className: "animate-in zoom-in-50 fade-in duration-200 ease-out" }) : /* @__PURE__ */ jsx14(CopyIcon3, { className: "animate-in zoom-in-75 fade-in duration-150" }) }) })
775
- ]
320
+ ...props,
321
+ className: cn("aui-tool-approval-bar", className)
776
322
  }
777
323
  );
778
324
  }
779
325
 
780
- // src/atoms/MessageBubble.tsx
781
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
782
- function MessageBubble(props) {
783
- if (props.variant === "assistant") {
784
- const { children: children2, error, branchIndicator: branchIndicator2, actionBar: actionBar2, className: className2 } = props;
785
- return /* @__PURE__ */ jsxs10(
786
- "div",
787
- {
788
- "data-slot": "aui_assistant-message-root",
789
- className: cn("fade-in slide-in-from-bottom-1 animate-in relative duration-150", className2),
790
- children: [
791
- /* @__PURE__ */ jsxs10(
792
- "div",
793
- {
794
- "data-slot": "aui_assistant-message-content",
795
- className: "text-foreground flex flex-col gap-3 px-2 leading-relaxed wrap-break-word [contain-intrinsic-size:auto_24px] [content-visibility:auto]",
796
- children: [
797
- children2,
798
- error
799
- ]
800
- }
801
- ),
802
- /* @__PURE__ */ jsxs10("div", { "data-slot": "aui_assistant-message-footer", className: "ms-2 -mb-7.5 min-h-7.5 pt-1.5 flex items-center", children: [
803
- branchIndicator2,
804
- actionBar2
805
- ] })
806
- ]
807
- }
808
- );
809
- }
810
- const { children, attachments, branchIndicator, actionBar, className } = props;
811
- return /* @__PURE__ */ jsxs10(
812
- "div",
326
+ // src/atoms/ToolGroupCard.tsx
327
+ import { ChevronDownIcon, LoaderIcon } from "lucide-react";
328
+ import { Accordion, AccordionDetails, AccordionSummary } from "tfy-web-components/components/atoms/Accordion";
329
+ import { jsx as jsx18, jsxs as jsxs4 } from "react/jsx-runtime";
330
+ function ToolGroupCard({
331
+ toolCallCount,
332
+ expanded,
333
+ active = false,
334
+ onToggle,
335
+ children,
336
+ className
337
+ }) {
338
+ const label = `${toolCallCount} tool ${toolCallCount === 1 ? "call" : "calls"}`;
339
+ return /* @__PURE__ */ jsxs4(
340
+ Accordion,
813
341
  {
814
- "data-slot": "aui_user-message-root",
815
- className: cn(
816
- "fade-in slide-in-from-bottom-1 animate-in grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 duration-150 [contain-intrinsic-size:auto_60px] [content-visibility:auto] [&:where(>*)]:col-start-2",
817
- className
818
- ),
342
+ "data-slot": "tool-group-card",
343
+ expanded,
344
+ onChange: () => onToggle(),
345
+ background: "transparent",
346
+ className: cn("aui-tool-group-card group/tool-group w-full", className),
347
+ sx: { margin: 0, border: "none", boxShadow: "none" },
819
348
  children: [
820
- attachments,
821
- /* @__PURE__ */ jsx15("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: /* @__PURE__ */ jsx15("div", { className: "aui-user-message-content bg-muted text-foreground rounded-xl px-4 py-2 wrap-break-word empty:hidden", children }) }),
822
- (branchIndicator != null || actionBar != null) && /* @__PURE__ */ jsxs10(
823
- "div",
349
+ /* @__PURE__ */ jsx18(
350
+ AccordionSummary,
824
351
  {
825
- "data-slot": "aui_user-message-footer",
826
- className: "col-span-full col-start-1 row-start-3 -me-1 flex items-center justify-end gap-1",
827
- children: [
828
- branchIndicator,
829
- actionBar
830
- ]
352
+ hideIcon: true,
353
+ disableRipple: true,
354
+ sx: {
355
+ padding: 0,
356
+ minHeight: 0,
357
+ "&.Mui-expanded": { minHeight: 0 },
358
+ "&:hover": { backgroundColor: "transparent" },
359
+ "& .MuiAccordionSummary-content": { margin: 0, width: "100%" }
360
+ },
361
+ 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(
365
+ ChevronDownIcon,
366
+ {
367
+ className: cn(
368
+ "size-3 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
369
+ expanded ? "rotate-0" : "-rotate-90"
370
+ )
371
+ }
372
+ )
373
+ ] })
831
374
  }
832
- )
375
+ ),
376
+ /* @__PURE__ */ jsx18(AccordionDetails, { sx: { padding: 0 }, children: /* @__PURE__ */ jsx18("div", { className: "mt-1 flex flex-col gap-2 text-foreground", children }) })
833
377
  ]
834
378
  }
835
379
  );
836
380
  }
837
381
 
838
- // src/atoms/MessageErrorBanner.tsx
839
- import { jsx as jsx16 } from "react/jsx-runtime";
840
- function MessageErrorBanner({ message, className }) {
841
- return /* @__PURE__ */ jsx16(
842
- "div",
843
- {
844
- role: "alert",
845
- className: cn(
846
- "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",
847
- className
848
- ),
849
- children: /* @__PURE__ */ jsx16("span", { className: "aui-message-error-message line-clamp-2", children: message })
850
- }
851
- );
852
- }
853
-
854
- // src/atoms/MessageIndicator.tsx
855
- import { jsx as jsx17 } from "react/jsx-runtime";
856
- function MessageIndicator({ className }) {
857
- return /* @__PURE__ */ jsx17(
858
- "span",
859
- {
860
- "data-slot": "aui_assistant-message-indicator",
861
- className: cn("animate-pulse font-sans", className),
862
- "aria-label": "Assistant is working",
863
- children: "\u25CF"
864
- }
865
- );
866
- }
867
-
868
- // src/atoms/ScrollToBottomButton.tsx
869
- import { forwardRef as forwardRef2 } from "react";
870
- import { ArrowDownIcon } from "lucide-react";
871
- import { jsx as jsx18 } from "react/jsx-runtime";
872
- var ScrollToBottomButton = forwardRef2(
873
- ({ className, ...rest }, ref) => {
874
- return /* @__PURE__ */ jsx18(
875
- IconButton,
876
- {
877
- ref,
878
- tooltip: "Scroll to bottom",
879
- variant: "outline",
880
- className: cn(
881
- "aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent absolute -top-14 z-10 self-center rounded-full p-4 disabled:invisible",
882
- className
883
- ),
884
- ...rest,
885
- children: /* @__PURE__ */ jsx18(ArrowDownIcon, {})
886
- }
887
- );
888
- }
889
- );
890
- ScrollToBottomButton.displayName = "ScrollToBottomButton";
891
-
892
382
  // src/atoms/Skeletons.tsx
893
- import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
383
+ import Skeleton from "tfy-web-components/components/atoms/Skeleton";
384
+ import { jsx as jsx19, jsxs as jsxs5 } from "react/jsx-runtime";
894
385
  function MessageListSkeleton({ className }) {
895
- return /* @__PURE__ */ jsxs11(
386
+ return /* @__PURE__ */ jsxs5(
896
387
  "div",
897
388
  {
898
389
  role: "status",
@@ -901,177 +392,152 @@ function MessageListSkeleton({ className }) {
901
392
  className: cn("mb-14 flex flex-col gap-y-6", className),
902
393
  children: [
903
394
  /* @__PURE__ */ jsx19("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-10 w-[min(85%,20rem)] rounded-xl" }) }),
904
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2 px-2", children: [
905
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-md" }),
906
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-sm" }),
907
- /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-2/3 max-w-xs" })
908
- ] })
909
- ]
910
- }
911
- );
912
- }
913
-
914
- // src/atoms/ThreadShell.tsx
915
- import { forwardRef as forwardRef3 } from "react";
916
- import { jsx as jsx20 } from "react/jsx-runtime";
917
- var THREAD_CSS_VARS = {
918
- ["--thread-max-width"]: "44rem",
919
- ["--composer-bg"]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
920
- ["--composer-radius"]: "1.5rem",
921
- ["--composer-padding"]: "8px"
922
- };
923
- var ThreadRootShell = forwardRef3(
924
- ({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx20(
925
- "div",
926
- {
927
- ref,
928
- className: cn(
929
- "aui-root aui-thread-root bg-background @container flex h-full min-h-0 flex-col overflow-hidden",
930
- className
931
- ),
932
- style: { ...THREAD_CSS_VARS, ...style },
933
- ...rest
934
- }
935
- )
936
- );
937
- ThreadRootShell.displayName = "ThreadRootShell";
938
- var ThreadViewportShell = forwardRef3(
939
- ({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx20(
940
- "div",
941
- {
942
- ref,
943
- "data-slot": "aui_thread-viewport",
944
- className: cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className),
945
- ...rest,
946
- children: /* @__PURE__ */ jsx20(
947
- "div",
948
- {
949
- className: cn(
950
- "mx-auto flex w-full max-w-(--thread-max-width) flex-col px-4 pt-4 pb-4",
951
- isEmpty && "min-h-full justify-center"
952
- ),
953
- children
954
- }
955
- )
956
- }
957
- )
958
- );
959
- ThreadViewportShell.displayName = "ThreadViewportShell";
960
- var ThreadComposerAreaShell = forwardRef3(
961
- ({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx20(
962
- "div",
963
- {
964
- ref,
965
- "data-slot": "aui_thread-composer",
966
- className: cn(
967
- "aui-thread-composer bg-background relative mx-auto flex w-full max-w-(--thread-max-width) shrink-0 flex-col gap-4 px-4 pb-4 md:pb-6",
968
- !isEmpty && "rounded-t-(--composer-radius)",
969
- className
970
- ),
971
- ...rest
972
- }
973
- )
974
- );
975
- ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
976
- var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */ jsx20(
977
- "div",
978
- {
979
- ref,
980
- "data-slot": "aui_message-group",
981
- className: cn("flex flex-col gap-y-6 empty:hidden", className),
982
- ...rest
983
- }
984
- ));
985
- MessageGroup.displayName = "MessageGroup";
395
+ /* @__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" })
399
+ ] })
400
+ ]
401
+ }
402
+ );
403
+ }
986
404
 
987
- // src/atoms/AskUserPrompt.tsx
988
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
989
- var OTHER_OPTION_ID = "__other";
990
- function AskUserPrompt({
991
- question,
992
- options,
993
- allowOther,
994
- selectedOptionId,
995
- otherValue,
405
+ // src/atoms/ComposerShell.tsx
406
+ import { jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
407
+ function ComposerShell({
408
+ value,
409
+ placeholder,
996
410
  disabled,
997
- onSelectOption,
998
- onOtherValueChange,
411
+ isRunning = false,
412
+ attachments,
413
+ modelLabel,
414
+ modelIcon,
415
+ connectorStatusLabel,
416
+ onValueChange,
999
417
  onSubmit,
418
+ onCancel,
419
+ onAttach,
1000
420
  className
1001
421
  }) {
1002
- const canSubmit = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID ? true : selectedOptionId === OTHER_OPTION_ID && otherValue.trim().length > 0;
1003
- return /* @__PURE__ */ jsxs12(
422
+ const ComposerLeftSection2 = useSlot("ComposerLeftSection");
423
+ const ComposerRightSection2 = useSlot("ComposerRightSection");
424
+ const ComposerSendButton2 = useSlot("ComposerSendButton");
425
+ return /* @__PURE__ */ jsxs6(
1004
426
  "div",
1005
427
  {
1006
- "data-slot": "aui_ask-user-prompt",
428
+ "data-slot": "aui_composer-shell",
1007
429
  className: cn(
1008
- "border-border/60 flex w-full flex-col gap-3 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)]",
430
+ "border-border/60 focus-within:border-ring focus-within:ring-ring/20 flex w-full flex-col gap-2 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)] shadow-sm transition-colors focus-within:ring-3",
1009
431
  className
1010
432
  ),
1011
433
  children: [
1012
- /* @__PURE__ */ jsx21("p", { className: "text-foreground px-2.5 text-sm font-medium", children: question }),
1013
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-1.5 px-2.5", children: [
1014
- options.map((option) => /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-sm", children: [
1015
- /* @__PURE__ */ jsx21(
1016
- "input",
1017
- {
1018
- type: "radio",
1019
- name: "ask-user-option",
1020
- checked: selectedOptionId === option.id,
1021
- disabled,
1022
- onChange: () => onSelectOption(option.id)
434
+ attachments,
435
+ /* @__PURE__ */ jsx20(
436
+ "textarea",
437
+ {
438
+ value,
439
+ placeholder,
440
+ disabled,
441
+ rows: 1,
442
+ "aria-label": "Message input",
443
+ onChange: (event) => onValueChange(event.target.value),
444
+ onKeyDown: (event) => {
445
+ if (event.key === "Enter" && !event.shiftKey) {
446
+ event.preventDefault();
447
+ onSubmit();
1023
448
  }
1024
- ),
1025
- option.label
1026
- ] }, option.id)),
1027
- allowOther && /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-sm", children: [
1028
- /* @__PURE__ */ jsx21(
1029
- "input",
449
+ },
450
+ className: "placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none rounded-lg bg-transparent px-2.5 py-1 text-base outline-none"
451
+ }
452
+ ),
453
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-1", children: [
454
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
455
+ /* @__PURE__ */ jsx20(
456
+ ComposerLeftSection2,
1030
457
  {
1031
- type: "radio",
1032
- name: "ask-user-option",
1033
- checked: selectedOptionId === OTHER_OPTION_ID,
1034
458
  disabled,
1035
- onChange: () => onSelectOption(OTHER_OPTION_ID)
459
+ isRunning,
460
+ onAttach
1036
461
  }
1037
462
  ),
1038
- /* @__PURE__ */ jsx21(
1039
- "input",
463
+ connectorStatusLabel && /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
464
+ ] }),
465
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
466
+ 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
+ modelIcon,
468
+ modelLabel
469
+ ] }),
470
+ /* @__PURE__ */ jsx20(ComposerRightSection2, { disabled, isRunning }),
471
+ /* @__PURE__ */ jsx20(
472
+ ComposerSendButton2,
1040
473
  {
1041
- type: "text",
1042
- value: otherValue,
1043
- placeholder: "Type your answer...",
1044
474
  disabled,
1045
- onFocus: () => onSelectOption(OTHER_OPTION_ID),
1046
- onChange: (event) => {
1047
- onSelectOption(OTHER_OPTION_ID);
1048
- onOtherValueChange(event.target.value);
1049
- },
1050
- "aria-label": "Other answer",
1051
- className: "border-border/60 flex-1 rounded-md border bg-transparent px-2 py-1 text-sm outline-none"
475
+ canSubmit: !disabled && value.trim().length > 0,
476
+ isRunning,
477
+ onSubmit,
478
+ onCancel
1052
479
  }
1053
480
  )
1054
481
  ] })
1055
- ] }),
1056
- /* @__PURE__ */ jsx21("div", { className: "flex justify-end px-2.5", children: /* @__PURE__ */ jsx21(
1057
- Button,
1058
- {
1059
- type: "button",
1060
- className: "rounded-full px-4",
1061
- disabled: disabled || !canSubmit,
1062
- onClick: onSubmit,
1063
- children: "Submit"
1064
- }
1065
- ) })
482
+ ] })
1066
483
  ]
1067
484
  }
1068
485
  );
1069
486
  }
1070
487
 
488
+ // src/atoms/ComposerSections.tsx
489
+ import Spinner from "tfy-web-components/components/atoms/Spinner";
490
+ import { Fragment, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
491
+ function ComposerLeftSection({ onAttach }) {
492
+ const IconButton5 = useSlot("IconButton");
493
+ if (!onAttach) return null;
494
+ return /* @__PURE__ */ jsx21(IconButton5, { icon: "plus", tooltip: "Attach", onClick: onAttach });
495
+ }
496
+ function ComposerRightSection(_) {
497
+ return null;
498
+ }
499
+ function ComposerSendButton({
500
+ canSubmit,
501
+ isRunning,
502
+ onSubmit,
503
+ onCancel
504
+ }) {
505
+ const Button4 = useSlot("Button");
506
+ if (isRunning) {
507
+ return /* @__PURE__ */ jsx21(
508
+ Button4.Primary,
509
+ {
510
+ disabled: !onCancel,
511
+ onClick: onCancel,
512
+ text: /* @__PURE__ */ jsxs7(Fragment, { children: [
513
+ /* @__PURE__ */ jsx21(Spinner, { small: true }),
514
+ "Cancel"
515
+ ] })
516
+ }
517
+ );
518
+ }
519
+ return /* @__PURE__ */ jsx21(
520
+ Button4.Primary,
521
+ {
522
+ disabled: !canSubmit,
523
+ onClick: onSubmit,
524
+ icon: "arrow-up",
525
+ tooltipProps: {
526
+ title: "Send message",
527
+ size: "fit"
528
+ }
529
+ }
530
+ );
531
+ }
532
+
1071
533
  // src/atoms/AttachmentCard.tsx
1072
- import { FileTextIcon, XIcon as XIcon2 } from "lucide-react";
1073
- import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
534
+ import { FileTextIcon } from "lucide-react";
535
+
536
+ // src/constants/attachments.ts
1074
537
  var USER_MESSAGE_ATTACHMENT_PREVIEW_REM = 12;
538
+
539
+ // src/atoms/AttachmentCard.tsx
540
+ import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1075
541
  function AttachmentCard({
1076
542
  name,
1077
543
  previewSrc,
@@ -1081,6 +547,10 @@ function AttachmentCard({
1081
547
  onRemove,
1082
548
  className
1083
549
  }) {
550
+ const IconButton5 = useSlot("IconButton");
551
+ const Avatar2 = useSlot("Avatar");
552
+ const AvatarImage2 = useSlot("AvatarImage");
553
+ const AvatarFallback2 = useSlot("AvatarFallback");
1084
554
  if (size === "preview" && isImage && previewSrc) {
1085
555
  const previewSize = previewRem != null ? { width: `${previewRem}rem`, height: `${previewRem}rem` } : void 0;
1086
556
  return /* @__PURE__ */ jsx22(
@@ -1097,7 +567,7 @@ function AttachmentCard({
1097
567
  }
1098
568
  );
1099
569
  }
1100
- return /* @__PURE__ */ jsxs13(
570
+ return /* @__PURE__ */ jsxs8(
1101
571
  "div",
1102
572
  {
1103
573
  "data-slot": "aui_attachment-chip",
@@ -1107,19 +577,18 @@ function AttachmentCard({
1107
577
  className
1108
578
  ),
1109
579
  children: [
1110
- /* @__PURE__ */ jsx22("div", { className: "bg-background flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md border", children: isImage && previewSrc ? /* @__PURE__ */ jsxs13(Avatar, { className: "size-7 rounded-none", children: [
1111
- /* @__PURE__ */ jsx22(AvatarImage, { src: previewSrc, alt: name, className: "object-cover" }),
1112
- /* @__PURE__ */ jsx22(AvatarFallback, { children: /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) })
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" }) })
1113
583
  ] }) : /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) }),
1114
584
  /* @__PURE__ */ jsx22("span", { className: "text-foreground min-w-0 truncate text-sm", children: name }),
1115
585
  onRemove && /* @__PURE__ */ jsx22(
1116
- IconButton,
586
+ IconButton5,
1117
587
  {
588
+ icon: "xmark",
1118
589
  tooltip: "Remove file",
1119
- side: "top",
1120
- className: "size-6 shrink-0 rounded-full [&_svg]:size-3",
1121
- onClick: onRemove,
1122
- children: /* @__PURE__ */ jsx22(XIcon2, {})
590
+ className: "size-6 shrink-0 rounded-full",
591
+ onClick: onRemove
1123
592
  }
1124
593
  )
1125
594
  ]
@@ -1128,20 +597,47 @@ function AttachmentCard({
1128
597
  }
1129
598
 
1130
599
  // src/atoms/AttachmentPickerButton.tsx
1131
- import { PlusIcon } from "lucide-react";
600
+ import IconButton from "tfy-web-components/components/atoms/IconButton";
1132
601
  import { jsx as jsx23 } from "react/jsx-runtime";
1133
602
  function AttachmentPickerButton(props) {
1134
- return /* @__PURE__ */ jsx23(IconButton, { tooltip: "Add Attachment", variant: "ghost", className: "size-7 rounded-full p-1", ...props, children: /* @__PURE__ */ jsx23(PlusIcon, { className: "size-4.5" }) });
603
+ return /* @__PURE__ */ jsx23(
604
+ IconButton,
605
+ {
606
+ icon: "plus",
607
+ tooltip: "Add Attachment",
608
+ className: "size-7 rounded-full p-1",
609
+ ...props
610
+ }
611
+ );
1135
612
  }
1136
613
 
1137
614
  // src/atoms/AttachmentPreviewDialog.tsx
1138
- import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
615
+ import { useState } from "react";
616
+ import Modal from "tfy-web-components/components/atoms/Modal";
617
+ import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
1139
618
  function AttachmentPreviewDialog({ previewSrc, children }) {
619
+ const IconButton5 = useSlot("IconButton");
620
+ const [open, setOpen] = useState(false);
1140
621
  if (!previewSrc) return /* @__PURE__ */ jsx24(Fragment2, { children });
1141
- return /* @__PURE__ */ jsxs14(Dialog, { children: [
1142
- /* @__PURE__ */ jsx24(DialogTrigger, { asChild: true, children }),
1143
- /* @__PURE__ */ jsxs14(DialogContent, { className: "p-2 sm:max-w-3xl", children: [
1144
- /* @__PURE__ */ jsx24(DialogTitle, { className: "sr-only", children: "Image Attachment Preview" }),
622
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
623
+ /* @__PURE__ */ jsx24(
624
+ "div",
625
+ {
626
+ role: "button",
627
+ tabIndex: 0,
628
+ onClick: () => setOpen(true),
629
+ onKeyDown: (event) => {
630
+ if (event.key === "Enter" || event.key === " ") {
631
+ event.preventDefault();
632
+ setOpen(true);
633
+ }
634
+ },
635
+ className: "contents cursor-pointer",
636
+ children
637
+ }
638
+ ),
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) }) }),
1145
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(
1146
642
  "img",
1147
643
  {
@@ -1150,602 +646,541 @@ function AttachmentPreviewDialog({ previewSrc, children }) {
1150
646
  className: "block h-auto max-h-[80vh] w-auto max-w-full object-contain"
1151
647
  }
1152
648
  ) })
1153
- ] })
649
+ ] }) })
1154
650
  ] });
1155
651
  }
1156
652
 
1157
- // src/atoms/ComposerShell.tsx
1158
- import { ArrowUpIcon, LoaderIcon as LoaderIcon2, PlusIcon as PlusIcon2 } from "lucide-react";
1159
- import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
1160
- function ComposerShell({
1161
- value,
1162
- placeholder,
1163
- disabled,
1164
- isRunning = false,
1165
- attachments,
1166
- modelLabel,
1167
- modelIcon,
1168
- connectorStatusLabel,
1169
- onValueChange,
1170
- onSubmit,
1171
- onCancel,
1172
- onAttach,
1173
- className
1174
- }) {
1175
- return /* @__PURE__ */ jsxs15(
653
+ // src/atoms/ScrollToBottomButton.tsx
654
+ import { forwardRef as forwardRef2 } from "react";
655
+ import IconButton2 from "tfy-web-components/components/atoms/IconButton";
656
+ import { jsx as jsx25 } from "react/jsx-runtime";
657
+ var ScrollToBottomButton = forwardRef2(
658
+ ({ className, disabled, ...rest }, ref) => {
659
+ if (disabled) return null;
660
+ return /* @__PURE__ */ jsx25(
661
+ "span",
662
+ {
663
+ ref,
664
+ className: cn("absolute -top-14 z-10 inline-flex self-center"),
665
+ children: /* @__PURE__ */ jsx25(
666
+ IconButton2,
667
+ {
668
+ icon: "arrow-down",
669
+ tooltip: "Scroll to bottom",
670
+ disabled,
671
+ className: cn(
672
+ "aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent rounded-full p-4",
673
+ className
674
+ ),
675
+ ...rest
676
+ }
677
+ )
678
+ }
679
+ );
680
+ }
681
+ );
682
+ ScrollToBottomButton.displayName = "ScrollToBottomButton";
683
+
684
+ // src/atoms/ThreadListRow.tsx
685
+ import IconProvider from "tfy-web-components/components/atoms/IconProvider";
686
+ import IconButton3 from "tfy-web-components/components/atoms/IconButton";
687
+ import DropdownMenu from "tfy-web-components/components/molecules/DropdownMenu";
688
+ import { jsx as jsx26, jsxs as jsxs10 } from "react/jsx-runtime";
689
+ function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }) {
690
+ return /* @__PURE__ */ jsxs10(
1176
691
  "div",
1177
692
  {
1178
- "data-slot": "aui_composer-shell",
693
+ "data-slot": "aui_thread-list-item",
694
+ "data-active": active || void 0,
1179
695
  className: cn(
1180
- "border-border/60 focus-within:border-ring focus-within:ring-ring/20 flex w-full flex-col gap-2 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)] shadow-sm transition-colors focus-within:ring-3",
696
+ "group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
1181
697
  className
1182
698
  ),
1183
699
  children: [
1184
- attachments,
1185
- /* @__PURE__ */ jsx25(
1186
- "textarea",
700
+ /* @__PURE__ */ jsx26(
701
+ "button",
1187
702
  {
1188
- value,
1189
- placeholder,
1190
- disabled,
1191
- rows: 1,
1192
- "aria-label": "Message input",
1193
- onChange: (event) => onValueChange(event.target.value),
1194
- onKeyDown: (event) => {
1195
- if (event.key === "Enter" && !event.shiftKey) {
1196
- event.preventDefault();
1197
- onSubmit();
1198
- }
1199
- },
1200
- className: "placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none rounded-lg bg-transparent px-2.5 py-1 text-base outline-none"
703
+ type: "button",
704
+ onClick: onSelect,
705
+ "data-slot": "aui_thread-list-item-trigger",
706
+ 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 })
1201
708
  }
1202
709
  ),
1203
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between px-1", children: [
1204
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
1205
- onAttach && /* @__PURE__ */ jsx25(IconButton, { tooltip: "Attach", onClick: onAttach, children: /* @__PURE__ */ jsx25(PlusIcon2, {}) }),
1206
- connectorStatusLabel && /* @__PURE__ */ jsx25("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
1207
- ] }),
1208
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
1209
- modelLabel && /* @__PURE__ */ jsxs15("span", { className: "bg-muted text-muted-foreground flex items-center gap-1 rounded-full px-2 py-0.5 text-xs", children: [
1210
- modelIcon,
1211
- modelLabel
1212
- ] }),
1213
- isRunning ? /* @__PURE__ */ jsxs15(
1214
- Button,
1215
- {
1216
- variant: "default",
1217
- size: "sm",
1218
- className: "gap-1.5 rounded-full",
1219
- disabled: !onCancel,
1220
- onClick: onCancel,
1221
- children: [
1222
- /* @__PURE__ */ jsx25(LoaderIcon2, { className: "size-3.5 animate-spin [animation-duration:0.6s]" }),
1223
- "Cancel"
1224
- ]
1225
- }
1226
- ) : /* @__PURE__ */ jsx25(
1227
- IconButton,
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(
711
+ DropdownMenu,
712
+ {
713
+ trigger: /* @__PURE__ */ jsx26(
714
+ IconButton3,
1228
715
  {
1229
- tooltip: "Send message",
1230
- variant: "default",
1231
- disabled: disabled || value.trim().length === 0,
1232
- onClick: onSubmit,
1233
- children: /* @__PURE__ */ jsx25(ArrowUpIcon, {})
716
+ icon: "ellipsis",
717
+ tooltip: "More options",
718
+ className: "size-6 p-0"
1234
719
  }
1235
- )
1236
- ] })
1237
- ] })
720
+ ),
721
+ side: "right",
722
+ align: "start",
723
+ children: [
724
+ onArchive && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onArchive, children: [
725
+ /* @__PURE__ */ jsx26(IconProvider, { icon: "box-archive", size: 0.75 }),
726
+ "Archive"
727
+ ] }),
728
+ onDelete && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onDelete, className: "text-destructive hover:bg-destructive/10", children: [
729
+ /* @__PURE__ */ jsx26(IconProvider, { icon: "trash", size: 0.75 }),
730
+ "Delete"
731
+ ] })
732
+ ]
733
+ }
734
+ ) })
1238
735
  ]
1239
736
  }
1240
737
  );
1241
738
  }
1242
739
 
1243
- // src/atoms/McpAuthPrompt.tsx
1244
- import { ExternalLinkIcon } from "lucide-react";
1245
- import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
1246
- function McpAuthPrompt({ servers, disabled, onContinue, className }) {
1247
- return /* @__PURE__ */ jsxs16("div", { "data-slot": "aui_mcp-auth-continue-composer", className: cn("flex w-full flex-col gap-3", className), children: [
1248
- /* @__PURE__ */ jsxs16("div", { className: "border-primary/20 bg-background overflow-hidden rounded-2xl border", children: [
1249
- /* @__PURE__ */ jsx26("div", { className: "bg-primary/10 border-primary/20 border-b px-4 py-2.5", children: /* @__PURE__ */ jsx26("p", { className: "text-primary text-sm font-semibold", children: "MCP Authentication Required" }) }),
1250
- /* @__PURE__ */ jsx26("ul", { className: "divide-border/60 divide-y", children: servers.map((server) => /* @__PURE__ */ jsxs16(
1251
- "li",
1252
- {
1253
- className: "flex items-center justify-between gap-3 px-4 py-2.5",
1254
- children: [
1255
- /* @__PURE__ */ jsxs16("p", { className: "text-sm", children: [
1256
- /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: "MCP Server Name" }),
1257
- /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground mx-1.5", children: ":" }),
1258
- /* @__PURE__ */ jsx26("span", { className: "font-semibold", children: server.name })
1259
- ] }),
1260
- /* @__PURE__ */ jsx26(
1261
- Button,
1262
- {
1263
- asChild: true,
1264
- size: "sm",
1265
- className: "bg-foreground text-background hover:bg-foreground/80 rounded-full",
1266
- children: /* @__PURE__ */ jsxs16("a", { href: server.authUrl, target: "_blank", rel: "noopener noreferrer", children: [
1267
- "Connect",
1268
- /* @__PURE__ */ jsx26(ExternalLinkIcon, { className: "size-3.5" })
1269
- ] })
1270
- }
1271
- )
1272
- ]
1273
- },
1274
- server.id
1275
- )) })
1276
- ] }),
1277
- /* @__PURE__ */ jsx26("div", { className: "flex justify-end px-2.5", children: /* @__PURE__ */ jsx26(Button, { type: "button", className: "rounded-full px-4", disabled, onClick: onContinue, children: "Continue" }) })
740
+ // src/atoms/ThreadListMisc.tsx
741
+ import Button from "tfy-web-components/components/atoms/Button";
742
+ import Skeleton2 from "tfy-web-components/components/atoms/Skeleton";
743
+ import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
744
+ function ThreadListNewButton({ className, ...rest }) {
745
+ return /* @__PURE__ */ jsx27(
746
+ Button.Ghost,
747
+ {
748
+ "data-slot": "aui_thread-list-new",
749
+ className: cn("hover:bg-muted h-8 justify-start gap-2 rounded-md px-2.5 text-sm font-normal", className),
750
+ icon: "plus",
751
+ text: "New Thread",
752
+ ...rest
753
+ }
754
+ );
755
+ }
756
+ 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)) });
758
+ }
759
+ 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 });
761
+ }
762
+ function ThreadListShell({ header, children, className }) {
763
+ 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
+ header,
765
+ /* @__PURE__ */ jsx27("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
1278
766
  ] });
1279
767
  }
1280
768
 
1281
- // src/atoms/ReasoningCard.tsx
1282
- import { BrainIcon, ChevronDownIcon } from "lucide-react";
1283
- import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
1284
- function ReasoningCard({ streaming, expanded, onToggle, children, className }) {
1285
- return /* @__PURE__ */ jsxs17(
1286
- Collapsible,
769
+ // src/atoms/MessageActionBar.tsx
770
+ import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
771
+ function MessageActionBar({ isCopied, onCopy, className }) {
772
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
773
+ const IconButton5 = useSlot("IconButton");
774
+ return /* @__PURE__ */ jsxs12(
775
+ "div",
1287
776
  {
1288
- "data-slot": "reasoning-card",
1289
- open: expanded,
1290
- onOpenChange: onToggle,
1291
- className: cn("aui-reasoning-card w-full rounded-lg border px-3 py-2", className),
777
+ className: cn(
778
+ "aui-assistant-action-bar-root text-muted-foreground animate-in fade-in flex items-center gap-3 duration-200",
779
+ className
780
+ ),
1292
781
  children: [
1293
- /* @__PURE__ */ jsxs17(CollapsibleTrigger, { className: "text-muted-foreground hover:text-foreground flex max-w-[75%] origin-left items-center gap-2 py-1.5 text-sm transition-[color,scale] active:scale-[0.98]", children: [
1294
- /* @__PURE__ */ jsx27(BrainIcon, { className: "size-4 shrink-0" }),
1295
- /* @__PURE__ */ jsxs17("span", { className: "leading-none tabular-nums", children: [
1296
- "Reasoning",
1297
- streaming && /* @__PURE__ */ jsxs17("span", { "aria-hidden": true, className: "shimmer pointer-events-none", children: [
1298
- " ",
1299
- "\u2026"
1300
- ] })
1301
- ] }),
1302
- /* @__PURE__ */ jsx27(
1303
- ChevronDownIcon,
1304
- {
1305
- className: cn(
1306
- "mt-0.5 size-4 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
1307
- expanded ? "rotate-0" : "-rotate-90"
1308
- )
1309
- }
1310
- )
1311
- ] }),
1312
- /* @__PURE__ */ jsx27(CollapsibleContent, { className: "text-muted-foreground max-h-64 overflow-y-auto pt-2 pb-1 pl-6 text-sm leading-relaxed", children })
782
+ /* @__PURE__ */ jsx28(MessageTimestamp2, {}),
783
+ /* @__PURE__ */ jsx28(
784
+ IconButton5,
785
+ {
786
+ icon: isCopied ? "check" : ["far", "clone"],
787
+ tooltip: "Copy",
788
+ onClick: onCopy
789
+ }
790
+ )
1313
791
  ]
1314
792
  }
1315
793
  );
1316
794
  }
1317
795
 
1318
- // src/atoms/ToolApprovalBar.tsx
1319
- import { useState as useState3 } from "react";
1320
- import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
1321
- function ToolApprovalBar({ options, onSelectOption, className }) {
1322
- const [confirmingId, setConfirmingId] = useState3(null);
1323
- const confirming = confirmingId != null ? options.find((o) => o.id === confirmingId) : void 0;
1324
- if (confirming) {
1325
- return /* @__PURE__ */ jsxs18("div", { className: cn("aui-tool-approval-confirm flex flex-col gap-2 pt-1", className), children: [
1326
- /* @__PURE__ */ jsx28("p", { className: "font-semibold", children: confirming.confirm?.title ?? `${confirming.label}?` }),
1327
- confirming.confirm?.description && /* @__PURE__ */ jsx28("p", { className: "text-muted-foreground", children: confirming.confirm.description }),
1328
- confirming.grants && confirming.grants.length > 0 && /* @__PURE__ */ jsx28("ul", { className: "flex flex-col gap-1", children: confirming.grants.map((grant) => /* @__PURE__ */ jsx28("li", { children: /* @__PURE__ */ jsx28("code", { className: "bg-muted rounded px-1.5 py-0.5 text-xs", children: grant }) }, grant)) }),
1329
- /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
1330
- /* @__PURE__ */ jsx28(
1331
- Button,
1332
- {
1333
- size: "sm",
1334
- className: "active:scale-[0.98]",
1335
- onClick: () => {
1336
- onSelectOption(confirming.id);
1337
- setConfirmingId(null);
1338
- },
1339
- children: "Confirm"
1340
- }
1341
- ),
1342
- /* @__PURE__ */ jsx28(
1343
- Button,
1344
- {
1345
- size: "sm",
1346
- variant: "outline",
1347
- className: "active:scale-[0.98]",
1348
- onClick: () => setConfirmingId(null),
1349
- children: "Back"
1350
- }
1351
- )
1352
- ] })
1353
- ] });
796
+ // src/atoms/Markdown.tsx
797
+ import { MarkdownWithOpenUI } from "tfy-web-components/components/molecules/Markdown";
798
+ import { jsx as jsx29 } from "react/jsx-runtime";
799
+ function Markdown({
800
+ content,
801
+ isStreaming,
802
+ fileDownloadBaseUrl,
803
+ onDownloadArtifact,
804
+ readOnly,
805
+ className
806
+ }) {
807
+ const mode = useThemeMode();
808
+ return /* @__PURE__ */ jsx29(
809
+ MarkdownWithOpenUI,
810
+ {
811
+ isStreaming,
812
+ darkTheme: mode === "dark",
813
+ fileDownloadBaseUrl,
814
+ onDownloadArtifact,
815
+ readOnly,
816
+ className,
817
+ children: content
818
+ }
819
+ );
820
+ }
821
+
822
+ // src/atoms/AssistantMessageBubble.tsx
823
+ import { AssistantMessage } from "tfy-web-components/components/molecules/agent-chat";
824
+ import { jsx as jsx30 } from "react/jsx-runtime";
825
+ function AssistantMessageBubble({
826
+ children,
827
+ error,
828
+ actionBar,
829
+ className
830
+ }) {
831
+ return /* @__PURE__ */ jsx30(
832
+ "div",
833
+ {
834
+ "data-slot": "aui_assistant-message-root",
835
+ className: cn(
836
+ "group/assistant fade-in slide-in-from-bottom-1 animate-in relative duration-150",
837
+ className
838
+ ),
839
+ children: /* @__PURE__ */ jsx30(AssistantMessage, { error, actionBar, children })
840
+ }
841
+ );
842
+ }
843
+
844
+ // src/atoms/MessageErrorBanner.tsx
845
+ import { jsx as jsx31 } from "react/jsx-runtime";
846
+ function MessageErrorBanner({ message, className }) {
847
+ return /* @__PURE__ */ jsx31(
848
+ "div",
849
+ {
850
+ role: "alert",
851
+ className: cn(
852
+ "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
+ className
854
+ ),
855
+ children: /* @__PURE__ */ jsx31("span", { className: "aui-message-error-message line-clamp-2", children: message })
856
+ }
857
+ );
858
+ }
859
+
860
+ // src/atoms/MessageIndicator.tsx
861
+ import { jsx as jsx32 } from "react/jsx-runtime";
862
+ function MessageIndicator({ className }) {
863
+ return /* @__PURE__ */ jsx32(
864
+ "span",
865
+ {
866
+ "data-slot": "aui_assistant-message-indicator",
867
+ className: cn("animate-pulse font-sans", className),
868
+ "aria-label": "Assistant is working",
869
+ children: "\u25CF"
870
+ }
871
+ );
872
+ }
873
+
874
+ // src/atoms/MessageTimestamp.tsx
875
+ import { useAuiState } from "@assistant-ui/react";
876
+ import { jsx as jsx33 } from "react/jsx-runtime";
877
+ function toDate(createdAt) {
878
+ if (createdAt == null) {
879
+ return null;
880
+ }
881
+ const date = createdAt instanceof Date ? createdAt : new Date(createdAt);
882
+ return Number.isNaN(date.getTime()) ? null : date;
883
+ }
884
+ function formatTime(date) {
885
+ return new Intl.DateTimeFormat(void 0, {
886
+ hour: "2-digit",
887
+ minute: "2-digit",
888
+ second: "2-digit",
889
+ hour12: true
890
+ }).format(date);
891
+ }
892
+ function formatFullDate(date) {
893
+ return new Intl.DateTimeFormat(void 0, {
894
+ month: "short",
895
+ day: "numeric",
896
+ year: "numeric",
897
+ hour: "numeric",
898
+ minute: "2-digit",
899
+ hour12: true
900
+ }).format(date);
901
+ }
902
+ function MessageTimestamp({ className }) {
903
+ const LightTooltip3 = useSlot("LightTooltip");
904
+ const createdAt = useAuiState((s) => s.message.createdAt);
905
+ const date = toDate(createdAt);
906
+ if (date == null) {
907
+ return null;
1354
908
  }
1355
- const firstAllowId = options.find((o) => o.isAllow)?.id;
1356
- return /* @__PURE__ */ jsx28("div", { className: cn("aui-tool-approval-bar flex flex-wrap items-center gap-2 pt-1", className), children: options.map((option) => /* @__PURE__ */ jsx28(
1357
- Button,
909
+ return /* @__PURE__ */ jsx33(LightTooltip3, { title: formatFullDate(date), size: "fit", children: /* @__PURE__ */ jsx33(
910
+ "span",
1358
911
  {
1359
- size: "sm",
1360
- variant: option.id === firstAllowId ? "default" : "outline",
1361
- className: "active:scale-[0.98]",
1362
- onClick: () => option.confirm ? setConfirmingId(option.id) : onSelectOption(option.id),
1363
- children: option.label
1364
- },
1365
- option.id
1366
- )) });
912
+ className: cn(
913
+ "text-xs font-medium cursor-pointer leading-normal shrink-0 text-muted-foreground",
914
+ className
915
+ ),
916
+ children: formatTime(date)
917
+ }
918
+ ) });
1367
919
  }
1368
920
 
1369
- // src/atoms/ThreadListRow.tsx
1370
- import { ArchiveIcon, MoreHorizontalIcon as MoreHorizontalIcon2, TrashIcon } from "lucide-react";
1371
- import { DropdownMenu as DropdownMenu2 } from "radix-ui";
1372
- import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
1373
- function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }) {
1374
- return /* @__PURE__ */ jsxs19(
1375
- "div",
921
+ // src/atoms/UserMessageActionBar.tsx
922
+ import { ActionBarPrimitive, useAuiState as useAuiState2 } from "@assistant-ui/react";
923
+ import { useActionBarCopy, useActionBarEdit } from "@assistant-ui/core/react";
924
+ import { useTrueFoundryResetFromTurn } from "@truefoundry/assistant-ui-runtime";
925
+ import { jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
926
+ function parseTurnIdFromMessageId(messageId) {
927
+ return messageId.replace(/-user$/, "");
928
+ }
929
+ function UserMessageActionBar({ className }) {
930
+ const IconButton5 = useSlot("IconButton");
931
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
932
+ const messageId = useAuiState2((s) => s.message.id);
933
+ const turnId = parseTurnIdFromMessageId(messageId);
934
+ const resetFromTurn = useTrueFoundryResetFromTurn();
935
+ const { edit, disabled: editDisabled } = useActionBarEdit();
936
+ const { copy, isCopied } = useActionBarCopy({
937
+ copyToClipboard: (text) => navigator.clipboard.writeText(text)
938
+ });
939
+ return /* @__PURE__ */ jsxs13(
940
+ ActionBarPrimitive.Root,
1376
941
  {
1377
- "data-slot": "aui_thread-list-item",
1378
- "data-active": active || void 0,
942
+ hideWhenRunning: true,
1379
943
  className: cn(
1380
- "group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
944
+ "aui-user-action-bar-root text-muted-foreground animate-in fade-in flex items-center gap-2 duration-200",
1381
945
  className
1382
946
  ),
1383
947
  children: [
1384
- /* @__PURE__ */ jsx29(
1385
- "button",
948
+ /* @__PURE__ */ jsx34(
949
+ IconButton5,
1386
950
  {
1387
- type: "button",
1388
- onClick: onSelect,
1389
- "data-slot": "aui_thread-list-item-trigger",
1390
- 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",
1391
- children: /* @__PURE__ */ jsx29("span", { className: "min-w-0 flex-1 truncate", children: title })
951
+ icon: "rotate-right",
952
+ tooltip: "Try again",
953
+ onClick: () => void resetFromTurn(turnId)
1392
954
  }
1393
955
  ),
1394
- (onArchive || onDelete) && /* @__PURE__ */ jsxs19(DropdownMenu2.Root, { children: [
1395
- /* @__PURE__ */ jsx29(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx29(
1396
- IconButton,
1397
- {
1398
- tooltip: "More options",
1399
- className: "absolute end-1.5 top-1/2 size-6 -translate-y-1/2 p-0 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100",
1400
- children: /* @__PURE__ */ jsx29(MoreHorizontalIcon2, { className: "size-3.5" })
1401
- }
1402
- ) }),
1403
- /* @__PURE__ */ jsx29(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs19(
1404
- DropdownMenu2.Content,
1405
- {
1406
- side: "right",
1407
- align: "start",
1408
- sideOffset: 6,
1409
- className: "bg-popover/95 text-popover-foreground z-50 min-w-32 overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm",
1410
- children: [
1411
- onArchive && /* @__PURE__ */ jsxs19(
1412
- DropdownMenu2.Item,
1413
- {
1414
- onSelect: onArchive,
1415
- className: "hover:bg-accent hover:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
1416
- children: [
1417
- /* @__PURE__ */ jsx29(ArchiveIcon, { className: "size-4" }),
1418
- "Archive"
1419
- ]
1420
- }
1421
- ),
1422
- onDelete && /* @__PURE__ */ jsxs19(
1423
- DropdownMenu2.Item,
1424
- {
1425
- onSelect: onDelete,
1426
- className: "text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none",
1427
- children: [
1428
- /* @__PURE__ */ jsx29(TrashIcon, { className: "size-4" }),
1429
- "Delete"
1430
- ]
1431
- }
1432
- )
1433
- ]
1434
- }
1435
- ) })
1436
- ] })
956
+ /* @__PURE__ */ jsx34(
957
+ IconButton5,
958
+ {
959
+ icon: "pencil",
960
+ tooltip: "Edit",
961
+ disabled: editDisabled,
962
+ onClick: edit
963
+ }
964
+ ),
965
+ /* @__PURE__ */ jsx34(
966
+ IconButton5,
967
+ {
968
+ icon: isCopied ? "check" : ["far", "clone"],
969
+ tooltip: "Copy",
970
+ onClick: copy
971
+ }
972
+ ),
973
+ /* @__PURE__ */ jsx34(MessageTimestamp2, {})
1437
974
  ]
1438
975
  }
1439
976
  );
1440
977
  }
1441
978
 
1442
- // src/atoms/ThreadListMisc.tsx
1443
- import { PlusIcon as PlusIcon3 } from "lucide-react";
1444
- import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
1445
- function ThreadListNewButton({ className, ...rest }) {
1446
- return /* @__PURE__ */ jsxs20(
1447
- Button,
979
+ // src/atoms/ThreadShell.tsx
980
+ import { forwardRef as forwardRef3 } from "react";
981
+ import { jsx as jsx35 } from "react/jsx-runtime";
982
+ var THREAD_CSS_VARS = {
983
+ ["--thread-max-width"]: "44rem",
984
+ ["--composer-bg"]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
985
+ ["--composer-radius"]: "1.5rem",
986
+ ["--composer-padding"]: "8px"
987
+ };
988
+ var ThreadRootShell = forwardRef3(
989
+ ({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx35(
990
+ "div",
1448
991
  {
1449
- variant: "ghost",
1450
- "data-slot": "aui_thread-list-new",
1451
- className: cn("hover:bg-muted h-8 justify-start gap-2 rounded-md px-2.5 text-sm font-normal", className),
992
+ ref,
993
+ className: cn(
994
+ "font-sans-flex aui-root aui-thread-root bg-background @container flex h-full min-h-0 flex-col overflow-hidden",
995
+ className
996
+ ),
997
+ style: { ...THREAD_CSS_VARS, ...style },
998
+ ...rest
999
+ }
1000
+ )
1001
+ );
1002
+ ThreadRootShell.displayName = "ThreadRootShell";
1003
+ var ThreadViewportShell = forwardRef3(
1004
+ ({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx35(
1005
+ "div",
1006
+ {
1007
+ ref,
1008
+ "data-slot": "aui_thread-viewport",
1009
+ className: cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className),
1452
1010
  ...rest,
1453
- children: [
1454
- /* @__PURE__ */ jsx30(PlusIcon3, { className: "size-4 shrink-0" }),
1455
- /* @__PURE__ */ jsx30("span", { className: "whitespace-nowrap", children: "New Thread" })
1456
- ]
1011
+ children: /* @__PURE__ */ jsx35(
1012
+ "div",
1013
+ {
1014
+ className: cn(
1015
+ "mx-auto flex w-full max-w-(--thread-max-width) flex-col px-4 pt-4 pb-4",
1016
+ isEmpty && "min-h-full justify-center"
1017
+ ),
1018
+ children
1019
+ }
1020
+ )
1457
1021
  }
1458
- );
1459
- }
1460
- function ThreadListRowSkeleton({ count = 5, className }) {
1461
- return /* @__PURE__ */ jsx30("div", { className: cn("flex flex-col gap-1", className), role: "status", "aria-label": "Loading threads", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx30("div", { className: "flex h-8 items-center px-2.5", children: /* @__PURE__ */ jsx30(Skeleton, { className: "h-3.5 w-full" }) }, i)) });
1462
- }
1463
- function ThreadListEmptyState({ message = "No threads yet", className }) {
1464
- return /* @__PURE__ */ jsx30("div", { className: cn("text-muted-foreground flex flex-1 items-center justify-center px-4 text-center text-sm", className), children: message });
1465
- }
1466
- function ThreadListShell({ header, children, className }) {
1467
- return /* @__PURE__ */ jsxs20("div", { className: cn("flex min-h-0 flex-1 flex-col gap-1 overflow-hidden p-3", className), children: [
1468
- header,
1469
- /* @__PURE__ */ jsx30("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
1470
- ] });
1471
- }
1472
-
1473
- // src/atoms/Toast.tsx
1474
- import { XIcon as XIcon3 } from "lucide-react";
1475
- import { Toast as ToastPrimitive } from "radix-ui";
1476
- import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
1477
- function Toast({ title, description, open, onOpenChange, className }) {
1478
- return /* @__PURE__ */ jsxs21(
1479
- ToastPrimitive.Root,
1022
+ )
1023
+ );
1024
+ ThreadViewportShell.displayName = "ThreadViewportShell";
1025
+ var ThreadComposerAreaShell = forwardRef3(
1026
+ ({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx35(
1027
+ "div",
1480
1028
  {
1481
- open,
1482
- onOpenChange,
1029
+ ref,
1030
+ "data-slot": "aui_thread-composer",
1483
1031
  className: cn(
1484
- "border-destructive bg-background text-destructive dark:bg-card pointer-events-auto relative flex max-h-[min(70vh,32rem)] w-full items-start gap-3 rounded-xl border p-4 shadow-lg dark:text-red-200",
1485
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-4",
1486
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-bottom-4",
1032
+ "aui-thread-composer bg-background relative mx-auto flex w-full max-w-(--thread-max-width) shrink-0 flex-col gap-4 px-4 pb-4 md:pb-6",
1033
+ !isEmpty && "rounded-t-(--composer-radius)",
1487
1034
  className
1488
1035
  ),
1489
- children: [
1490
- /* @__PURE__ */ jsxs21("div", { className: "grid min-h-0 min-w-0 flex-1 gap-1 overflow-y-auto pe-6", children: [
1491
- /* @__PURE__ */ jsx31(ToastPrimitive.Title, { className: "text-sm leading-none font-semibold", children: title }),
1492
- /* @__PURE__ */ jsx31(ToastPrimitive.Description, { className: "font-mono text-sm break-words whitespace-pre-wrap", children: description })
1493
- ] }),
1494
- /* @__PURE__ */ jsxs21(ToastPrimitive.Close, { 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", children: [
1495
- /* @__PURE__ */ jsx31(XIcon3, { className: "size-4" }),
1496
- /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "Close" })
1497
- ] })
1498
- ]
1036
+ ...rest
1499
1037
  }
1500
- );
1501
- }
1502
- function ToastStack({ children, duration = Number.POSITIVE_INFINITY }) {
1503
- return /* @__PURE__ */ jsxs21(ToastPrimitive.Provider, { duration, children: [
1504
- children,
1505
- /* @__PURE__ */ jsx31(ToastPrimitive.Viewport, { className: "fixed inset-x-0 bottom-0 z-50 flex max-h-screen flex-col-reverse gap-2 p-4 sm:bottom-4 sm:left-1/2 sm:w-full sm:max-w-2xl sm:-translate-x-1/2" })
1506
- ] });
1507
- }
1508
-
1509
- // src/atoms/ToolCallCard.tsx
1510
- import { BriefcaseIcon, CheckIcon as CheckIcon4, ChevronDownIcon as ChevronDownIcon2, LoaderIcon as LoaderIcon3, PlugIcon, WrenchIcon, XCircleIcon } from "lucide-react";
1511
- import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
1512
- var variantIcon = {
1513
- tool: WrenchIcon,
1514
- "sub-agent": BriefcaseIcon,
1515
- "mcp-listing": PlugIcon
1516
- };
1517
- function StatusIcon({ status }) {
1518
- if (status === "running") {
1519
- return /* @__PURE__ */ jsx32(
1520
- LoaderIcon3,
1521
- {
1522
- "data-slot": "tool-call-card-status-icon",
1523
- className: "text-muted-foreground size-4 shrink-0 animate-spin [animation-duration:0.6s]"
1524
- }
1525
- );
1526
- }
1527
- if (status === "success") {
1528
- return /* @__PURE__ */ jsx32(
1529
- CheckIcon4,
1530
- {
1531
- "data-slot": "tool-call-card-status-icon",
1532
- className: "size-4 shrink-0 text-emerald-600 dark:text-emerald-400"
1533
- }
1534
- );
1038
+ )
1039
+ );
1040
+ ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
1041
+ var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */ jsx35(
1042
+ "div",
1043
+ {
1044
+ ref,
1045
+ "data-slot": "aui_message-group",
1046
+ className: cn("flex flex-col gap-y-6 empty:hidden", className),
1047
+ ...rest
1535
1048
  }
1536
- return /* @__PURE__ */ jsx32(XCircleIcon, { "data-slot": "tool-call-card-status-icon", className: "text-destructive size-4 shrink-0" });
1537
- }
1538
- function IconChip({ Icon }) {
1539
- return /* @__PURE__ */ jsx32("span", { className: "bg-muted text-muted-foreground flex size-6 shrink-0 items-center justify-center rounded-md", children: /* @__PURE__ */ jsx32(Icon, { className: "size-3.5" }) });
1540
- }
1541
- function ToolCallCard(props) {
1542
- const { variant, name, status, expanded, onToggle, durationText, className } = props;
1543
- const VariantIcon = variantIcon[variant];
1544
- return /* @__PURE__ */ jsxs22(
1545
- Collapsible,
1546
- {
1547
- "data-slot": "tool-call-card",
1548
- "data-variant": variant,
1549
- open: expanded,
1550
- onOpenChange: onToggle,
1551
- className: cn("aui-tool-call-card w-full rounded-lg border py-2", className),
1552
- children: [
1553
- /* @__PURE__ */ jsxs22(CollapsibleTrigger, { className: "flex w-full items-center gap-2 px-3 text-left", children: [
1554
- /* @__PURE__ */ jsx32(IconChip, { Icon: VariantIcon }),
1555
- variant === "tool" && /* @__PURE__ */ jsx32("span", { className: "text-sm", children: name }),
1556
- variant === "sub-agent" && /* @__PURE__ */ jsxs22("span", { className: "flex min-w-0 flex-col items-start", children: [
1557
- /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground text-[10px] font-semibold tracking-wide uppercase", children: "Sub-agent" }),
1558
- /* @__PURE__ */ jsx32("span", { className: "truncate text-sm font-medium", children: props.agentName })
1559
- ] }),
1560
- variant === "mcp-listing" && /* @__PURE__ */ jsxs22("span", { className: "truncate text-sm", children: [
1561
- "Listing tools \xB7 ",
1562
- props.serverName
1563
- ] }),
1564
- /* @__PURE__ */ jsxs22("span", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
1565
- durationText && /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground text-xs tabular-nums", children: durationText }),
1566
- /* @__PURE__ */ jsx32(StatusIcon, { status }),
1567
- /* @__PURE__ */ jsx32(
1568
- ChevronDownIcon2,
1569
- {
1570
- className: cn(
1571
- "size-4 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
1572
- expanded ? "rotate-0" : "-rotate-90"
1573
- )
1574
- }
1575
- )
1576
- ] })
1577
- ] }),
1578
- /* @__PURE__ */ jsxs22(CollapsibleContent, { className: "px-3 pt-2", children: [
1579
- variant === "tool" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
1580
- props.approvalSlot,
1581
- props.argsText && /* @__PURE__ */ jsxs22("div", { children: [
1582
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Request:" }),
1583
- /* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.argsText })
1584
- ] }),
1585
- props.result !== void 0 && /* @__PURE__ */ jsxs22("div", { children: [
1586
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Result:" }),
1587
- /* @__PURE__ */ jsx32(
1588
- "pre",
1589
- {
1590
- className: cn(
1591
- "bg-muted/50 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap",
1592
- props.isError ? "text-destructive" : "text-foreground/90"
1593
- ),
1594
- children: props.result
1595
- }
1596
- )
1597
- ] })
1598
- ] }),
1599
- variant === "sub-agent" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
1600
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground line-clamp-2 text-sm", children: props.instruction }),
1601
- /* @__PURE__ */ jsxs22("p", { className: "text-muted-foreground text-[10px] font-medium tracking-wide uppercase", children: [
1602
- "Steps \xB7 ",
1603
- props.stepCount,
1604
- " steps"
1605
- ] }),
1606
- /* @__PURE__ */ jsx32("div", { className: "border-border/60 flex flex-col gap-2 border-l pl-3", children: props.children })
1607
- ] }),
1608
- variant === "mcp-listing" && /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
1609
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-sm", children: props.description }),
1610
- /* @__PURE__ */ jsxs22("div", { children: [
1611
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Request:" }),
1612
- /* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.argsText })
1613
- ] }),
1614
- /* @__PURE__ */ jsxs22("div", { children: [
1615
- /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs font-medium", children: "Result:" }),
1616
- /* @__PURE__ */ jsx32("pre", { className: "bg-muted/50 text-foreground/90 mt-1 rounded-md p-2.5 text-xs break-words whitespace-pre-wrap", children: props.resultText })
1617
- ] })
1618
- ] })
1619
- ] })
1620
- ]
1621
- }
1622
- );
1049
+ ));
1050
+ MessageGroup.displayName = "MessageGroup";
1051
+
1052
+ // src/atoms/WelcomeScreen.tsx
1053
+ import { jsx as jsx36 } from "react/jsx-runtime";
1054
+ 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 }) });
1623
1056
  }
1624
1057
 
1625
- // src/atoms/ToolGroupCard.tsx
1626
- import { ChevronDownIcon as ChevronDownIcon3, LoaderIcon as LoaderIcon4 } from "lucide-react";
1627
- import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
1628
- function ToolGroupCard({
1629
- toolCallCount,
1630
- expanded,
1631
- active = false,
1632
- onToggle,
1633
- children,
1634
- className
1635
- }) {
1636
- const label = `${toolCallCount} tool ${toolCallCount === 1 ? "call" : "calls"}`;
1637
- return /* @__PURE__ */ jsxs23(
1638
- Collapsible,
1058
+ // src/atoms/Toast.tsx
1059
+ import { XIcon } from "lucide-react";
1060
+ import { jsx as jsx37, jsxs as jsxs14 } from "react/jsx-runtime";
1061
+ function Toast({ title, description, open, onOpenChange, className }) {
1062
+ if (!open) return null;
1063
+ return /* @__PURE__ */ jsxs14(
1064
+ "div",
1639
1065
  {
1640
- "data-slot": "tool-group-card",
1641
- open: expanded,
1642
- onOpenChange: onToggle,
1643
- className: cn("aui-tool-group-card group/tool-group w-full", className),
1066
+ className: cn(
1067
+ "font-sans-flex border-destructive bg-background text-destructive dark:bg-card pointer-events-auto relative flex max-h-[min(70vh,32rem)] w-full items-start gap-3 rounded-xl border p-4 shadow-lg dark:text-red-200",
1068
+ "animate-in fade-in-0 slide-in-from-bottom-4",
1069
+ className
1070
+ ),
1644
1071
  children: [
1645
- /* @__PURE__ */ jsxs23(CollapsibleTrigger, { 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: [
1646
- active && /* @__PURE__ */ jsx33(LoaderIcon4, { className: "size-3 shrink-0 animate-spin [animation-duration:0.6s]" }),
1647
- /* @__PURE__ */ jsx33("span", { className: "text-xs font-medium", children: label }),
1648
- /* @__PURE__ */ jsx33(
1649
- ChevronDownIcon3,
1650
- {
1651
- className: cn(
1652
- "size-3 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
1653
- expanded ? "rotate-0" : "-rotate-90"
1654
- )
1655
- }
1656
- )
1072
+ /* @__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 })
1657
1075
  ] }),
1658
- /* @__PURE__ */ jsx33(CollapsibleContent, { className: "mt-1 flex flex-col gap-1", children })
1076
+ /* @__PURE__ */ jsxs14(
1077
+ "button",
1078
+ {
1079
+ onClick: () => onOpenChange(false),
1080
+ 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
+ children: [
1082
+ /* @__PURE__ */ jsx37(XIcon, { className: "size-4" }),
1083
+ /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "Close" })
1084
+ ]
1085
+ }
1086
+ )
1659
1087
  ]
1660
1088
  }
1661
1089
  );
1662
1090
  }
1663
-
1664
- // src/atoms/WelcomeScreen.tsx
1665
- import { jsx as jsx34 } from "react/jsx-runtime";
1666
- function WelcomeScreen({ heading = "How can I help you today?", className }) {
1667
- return /* @__PURE__ */ jsx34("div", { className: cn("aui-thread-welcome-root mb-6 flex flex-col items-center px-4 text-center", className), children: /* @__PURE__ */ jsx34("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 }) });
1091
+ 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 });
1668
1093
  }
1669
1094
 
1670
1095
  // src/theme/defaultSlots.ts
1671
1096
  var defaultSlots = {
1672
- Button,
1673
- IconButton,
1097
+ // tfy-web-components — direct slot defaults
1098
+ Button: Button2,
1099
+ IconButton: IconButton4,
1100
+ LightTooltip,
1101
+ Modal: Modal2,
1102
+ Dialog,
1103
+ Accordion: Accordion2,
1104
+ AccordionSummary: AccordionSummary2,
1105
+ AccordionDetails: AccordionDetails2,
1106
+ Skeleton: Skeleton3,
1107
+ ReasoningCard,
1108
+ AskUserPrompt,
1109
+ McpAuthPrompt,
1110
+ // SDK atoms — wrap or compose tfy-web-components internally
1674
1111
  Avatar,
1675
1112
  AvatarImage,
1676
1113
  AvatarFallback,
1677
- Tooltip,
1678
- TooltipProvider,
1679
- TooltipTrigger,
1680
- TooltipContent,
1681
- Dialog,
1682
- DialogTrigger,
1683
- DialogPortal,
1684
- DialogClose,
1685
- DialogOverlay,
1686
- DialogContent,
1687
- DialogHeader,
1688
- DialogFooter,
1689
- DialogTitle,
1690
- DialogDescription,
1691
- Collapsible,
1692
- CollapsibleTrigger,
1693
- CollapsibleContent,
1694
- Skeleton,
1695
- Markdown,
1696
- OpenUIBlock,
1697
- SandboxArtifactList,
1698
- CodeBlockHeader,
1699
- MessageBubble,
1700
- MessageErrorBanner,
1701
- MessageActionBar,
1702
- UserMessageActionBar,
1703
- BranchIndicator,
1704
- MessageIndicator,
1705
- WelcomeScreen,
1706
- MessageListSkeleton,
1707
- ScrollToBottomButton,
1708
- ThreadRootShell,
1709
- ThreadViewportShell,
1710
- ThreadComposerAreaShell,
1711
- MessageGroup,
1114
+ UserMessageBubble,
1115
+ UserMessageEdit,
1712
1116
  ToolCallCard,
1117
+ ToolCallContentBlock,
1118
+ SubAgentCard,
1119
+ SandboxToolCallCard,
1713
1120
  ToolApprovalBar,
1714
1121
  ToolGroupCard,
1715
- ReasoningCard,
1122
+ MessageListSkeleton,
1716
1123
  ComposerShell,
1717
- AskUserPrompt,
1718
- McpAuthPrompt,
1124
+ ComposerLeftSection,
1125
+ ComposerRightSection,
1126
+ ComposerSendButton,
1719
1127
  AttachmentCard,
1720
1128
  AttachmentPreviewDialog,
1721
1129
  AttachmentPickerButton,
1130
+ ScrollToBottomButton,
1722
1131
  ThreadListRow,
1723
1132
  ThreadListNewButton,
1724
1133
  ThreadListRowSkeleton,
1725
1134
  ThreadListEmptyState,
1726
1135
  ThreadListShell,
1136
+ MessageActionBar,
1137
+ Markdown,
1138
+ // SDK atoms — SDK-owned (no tfy slot component)
1139
+ AssistantMessageBubble,
1140
+ MessageErrorBanner,
1141
+ MessageTimestamp,
1142
+ UserMessageActionBar,
1143
+ MessageIndicator,
1144
+ WelcomeScreen,
1145
+ ThreadRootShell,
1146
+ ThreadViewportShell,
1147
+ ThreadComposerAreaShell,
1148
+ MessageGroup,
1727
1149
  Toast,
1728
1150
  ToastStack
1729
1151
  };
1730
1152
 
1731
1153
  // src/theme/SlotsProvider.tsx
1732
- import { jsx as jsx35 } from "react/jsx-runtime";
1154
+ import { jsx as jsx38 } from "react/jsx-runtime";
1733
1155
  var SlotsContext = createContext(defaultSlots);
1156
+ var ThemeModeContext = createContext(void 0);
1734
1157
  function SlotsProvider({
1735
1158
  overrides,
1159
+ theme,
1736
1160
  children
1737
1161
  }) {
1738
1162
  const parentSlots = useContext(SlotsContext);
1739
- const resolved = useMemo2(
1163
+ const inheritedTheme = useContext(ThemeModeContext);
1164
+ const resolved = useMemo(
1740
1165
  () => ({ ...parentSlots, ...overrides }),
1741
1166
  [parentSlots, overrides]
1742
1167
  );
1743
- return /* @__PURE__ */ jsx35(SlotsContext.Provider, { value: resolved, children });
1168
+ return /* @__PURE__ */ jsx38(TfyThemeProvider, { theme: theme ?? inheritedTheme, children: /* @__PURE__ */ jsx38(SlotsProviderContents, { slots: resolved, children }) });
1169
+ }
1170
+ function SlotsProviderContents({
1171
+ slots,
1172
+ children
1173
+ }) {
1174
+ const { mode } = useTfyTheme();
1175
+ return /* @__PURE__ */ jsx38(ThemeModeContext.Provider, { value: mode, children: /* @__PURE__ */ jsx38(SlotsContext.Provider, { value: slots, children }) });
1744
1176
  }
1745
1177
  function useSlot(name) {
1746
1178
  const slots = useContext(SlotsContext);
1747
1179
  return slots[name];
1748
1180
  }
1181
+ function useThemeMode() {
1182
+ return useContext(ThemeModeContext) ?? "light";
1183
+ }
1749
1184
 
1750
1185
  // src/theme/tokens.ts
1751
1186
  import { createContext as createContext2, createElement, useContext as useContext2 } from "react";
@@ -1798,16 +1233,43 @@ function useTokens() {
1798
1233
  return useContext2(TokensContext);
1799
1234
  }
1800
1235
 
1236
+ // src/index.ts
1237
+ import {
1238
+ Button as Button3,
1239
+ DestructiveButton,
1240
+ GhostButton,
1241
+ PrimaryButton,
1242
+ SecondaryButton,
1243
+ TertiaryButton
1244
+ } from "tfy-web-components/components/atoms/Button";
1245
+ import { default as default2 } from "tfy-web-components/components/atoms/IconButton";
1246
+ import {
1247
+ default as default3,
1248
+ registerIcons as registerIcons2,
1249
+ registerImgIcons
1250
+ } from "tfy-web-components/components/atoms/IconProvider";
1251
+ import { LightTooltip as LightTooltip2 } from "tfy-web-components/components/atoms/Tooltip";
1252
+ import { default as default4 } from "tfy-web-components/components/atoms/Modal";
1253
+ import { default as default5 } from "tfy-web-components/components/molecules/Dialog";
1254
+ import {
1255
+ Accordion as Accordion3,
1256
+ AccordionSummary as AccordionSummary3,
1257
+ AccordionDetails as AccordionDetails3
1258
+ } from "tfy-web-components/components/atoms/Accordion";
1259
+ import { default as default6 } from "tfy-web-components/components/atoms/Skeleton";
1260
+
1801
1261
  // src/containers/ThreadContainer.tsx
1802
- import { ThreadPrimitive, useAuiState as useAuiState8 } from "@assistant-ui/react";
1262
+ import { useEffect as useEffect4 } from "react";
1263
+ import { preloadMarkdownOpenUI } from "tfy-web-components/components/molecules/Markdown";
1264
+ import { ThreadPrimitive, useAuiState as useAuiState11 } from "@assistant-ui/react";
1803
1265
 
1804
1266
  // src/hooks/useComposerBusyState.ts
1805
1267
  import { useThreadIsRunning } from "@assistant-ui/core/react";
1806
- import { createContext as createContext3, createElement as createElement2, useCallback, useContext as useContext3, useEffect, useState as useState4 } from "react";
1268
+ import { createContext as createContext3, createElement as createElement2, useCallback, useContext as useContext3, useEffect, useState as useState2 } from "react";
1807
1269
  var ComposerBusyContext = createContext3(null);
1808
1270
  function useComposerBusyStateValue() {
1809
1271
  const isRunning = useThreadIsRunning();
1810
- const [isSubmitting, setIsSubmitting] = useState4(false);
1272
+ const [isSubmitting, setIsSubmitting] = useState2(false);
1811
1273
  useEffect(() => {
1812
1274
  if (!isRunning) {
1813
1275
  setIsSubmitting(false);
@@ -1845,23 +1307,18 @@ function useComposerBusyState() {
1845
1307
  }
1846
1308
 
1847
1309
  // src/containers/AssistantMessageContainer.tsx
1848
- import { groupPartByType, MessagePrimitive as MessagePrimitive2, useAui as useAui2 } from "@assistant-ui/react";
1849
- import {
1850
- useActionBarCopy as useActionBarCopy2,
1851
- useMessageBranching,
1852
- useMessageError,
1853
- useThreadIsRunning as useThreadIsRunning2
1854
- } from "@assistant-ui/core/react";
1310
+ import { groupPartByType, MessagePrimitive as MessagePrimitive2 } from "@assistant-ui/react";
1311
+ import { useActionBarCopy as useActionBarCopy2, useMessageError, useThreadIsRunning as useThreadIsRunning2 } from "@assistant-ui/core/react";
1855
1312
 
1856
1313
  // src/containers/AssistantTextContainer.tsx
1857
1314
  import { useCallback as useCallback3 } from "react";
1858
- import { useAuiState as useAuiState2 } from "@assistant-ui/react";
1315
+ import { useAuiState as useAuiState3 } from "@assistant-ui/react";
1859
1316
  import { useTrueFoundryDownloadSandboxFile } from "@truefoundry/assistant-ui-runtime";
1860
1317
 
1861
1318
  // src/containers/ErrorToasterContainer.tsx
1862
- import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo3, useState as useState5 } from "react";
1319
+ import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo2, useState as useState3 } from "react";
1863
1320
  import { TrueFoundryGatewayError } from "truefoundry-gateway-sdk";
1864
- import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
1321
+ import { jsx as jsx39, jsxs as jsxs15 } from "react/jsx-runtime";
1865
1322
  var ErrorToasterContext = createContext4(null);
1866
1323
  function formatErrorBody(body) {
1867
1324
  if (body == null) return void 0;
@@ -1887,17 +1344,17 @@ function normalizeError(error) {
1887
1344
  function ErrorToasterProvider({ children }) {
1888
1345
  const ToastStack2 = useSlot("ToastStack");
1889
1346
  const Toast2 = useSlot("Toast");
1890
- const [toast, setToast] = useState5(null);
1891
- const [open, setOpen] = useState5(false);
1347
+ const [toast, setToast] = useState3(null);
1348
+ const [open, setOpen] = useState3(false);
1892
1349
  const showError = useCallback2((error) => {
1893
1350
  setToast(normalizeError(error));
1894
1351
  setOpen(true);
1895
1352
  }, []);
1896
- const value = useMemo3(() => ({ showError }), [showError]);
1897
- return /* @__PURE__ */ jsx36(ErrorToasterContext.Provider, { value, children: /* @__PURE__ */ jsxs24(ToastStack2, { children: [
1353
+ const value = useMemo2(() => ({ showError }), [showError]);
1354
+ return /* @__PURE__ */ jsxs15(ErrorToasterContext.Provider, { value, children: [
1898
1355
  children,
1899
- toast != null && /* @__PURE__ */ jsx36(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen })
1900
- ] }) });
1356
+ /* @__PURE__ */ jsx39(ToastStack2, { children: toast != null && /* @__PURE__ */ jsx39(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen }) })
1357
+ ] });
1901
1358
  }
1902
1359
  function useErrorToaster() {
1903
1360
  const context = useContext4(ErrorToasterContext);
@@ -1911,7 +1368,7 @@ function useErrorToasterOptional() {
1911
1368
  }
1912
1369
 
1913
1370
  // src/containers/AssistantTextContainer.tsx
1914
- import { jsx as jsx37 } from "react/jsx-runtime";
1371
+ import { jsx as jsx40 } from "react/jsx-runtime";
1915
1372
  function filenameFromPath(path) {
1916
1373
  return path.split("/").pop() || "download";
1917
1374
  }
@@ -1928,10 +1385,10 @@ function AssistantTextContainer() {
1928
1385
  const Markdown2 = useSlot("Markdown");
1929
1386
  const downloadSandboxFile = useTrueFoundryDownloadSandboxFile();
1930
1387
  const errorToaster = useErrorToasterOptional();
1931
- const text = useAuiState2(
1388
+ const text = useAuiState3(
1932
1389
  (s) => s.part.type === "text" || s.part.type === "reasoning" ? s.part.text : ""
1933
1390
  );
1934
- const isStreaming = useAuiState2((s) => {
1391
+ const isStreaming = useAuiState3((s) => {
1935
1392
  if (s.message.status?.type !== "running") return false;
1936
1393
  const lastIndex = s.message.parts.length - 1;
1937
1394
  if (lastIndex < 0) return false;
@@ -1948,23 +1405,24 @@ function AssistantTextContainer() {
1948
1405
  }),
1949
1406
  [downloadSandboxFile, errorToaster]
1950
1407
  );
1951
- return /* @__PURE__ */ jsx37(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1408
+ return /* @__PURE__ */ jsx40(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1952
1409
  }
1953
1410
 
1954
1411
  // src/containers/MessageImageContainer.tsx
1955
- import { useAuiState as useAuiState3 } from "@assistant-ui/react";
1956
- import { jsx as jsx38 } from "react/jsx-runtime";
1412
+ import { useAuiState as useAuiState4 } from "@assistant-ui/react";
1413
+ import { jsx as jsx41 } from "react/jsx-runtime";
1957
1414
  function MessageImageContainer() {
1415
+ const AttachmentCard2 = useSlot("AttachmentCard");
1958
1416
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
1959
- const image = useAuiState3((s) => s.part.type === "image" ? s.part.image : "");
1960
- const filename = useAuiState3(
1417
+ const image = useAuiState4((s) => s.part.type === "image" ? s.part.image : "");
1418
+ const filename = useAuiState4(
1961
1419
  (s) => s.part.type === "image" ? s.part.filename : void 0
1962
1420
  );
1963
1421
  if (!image) {
1964
1422
  return null;
1965
1423
  }
1966
- const card = /* @__PURE__ */ jsx38(
1967
- AttachmentCard,
1424
+ const card = /* @__PURE__ */ jsx41(
1425
+ AttachmentCard2,
1968
1426
  {
1969
1427
  name: filename ?? "image",
1970
1428
  previewSrc: image,
@@ -1973,34 +1431,73 @@ function MessageImageContainer() {
1973
1431
  previewRem: USER_MESSAGE_ATTACHMENT_PREVIEW_REM
1974
1432
  }
1975
1433
  );
1976
- return /* @__PURE__ */ jsx38(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx38("div", { className: "aui-message-image", children: card }) });
1434
+ return /* @__PURE__ */ jsx41(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx41("div", { className: "aui-message-image", children: card }) });
1977
1435
  }
1978
1436
 
1979
1437
  // src/containers/ReasoningContainer.tsx
1980
- import { useState as useState6 } from "react";
1981
- import { useAuiState as useAuiState4 } from "@assistant-ui/react";
1982
- import { jsx as jsx39 } from "react/jsx-runtime";
1983
- function ReasoningContainer({ group, children }) {
1438
+ import { useCallback as useCallback4, useRef, useState as useState4 } from "react";
1439
+ import { useAuiState as useAuiState5 } from "@assistant-ui/react";
1440
+ import { jsx as jsx42 } from "react/jsx-runtime";
1441
+ function ReasoningContainer({ group }) {
1984
1442
  const ReasoningCard2 = useSlot("ReasoningCard");
1985
- const streaming = useAuiState4((s) => {
1443
+ const content = useAuiState5(
1444
+ (s) => group.indices.map((i) => s.message.parts[i]).filter((p) => p != null && p.type === "reasoning").map((p) => p.text ?? "").join("")
1445
+ );
1446
+ const streaming = useAuiState5((s) => {
1986
1447
  if (s.message.status?.type !== "running") return false;
1987
1448
  const lastIndex = s.message.parts.length - 1;
1988
1449
  if (lastIndex < 0) return false;
1989
1450
  if (s.message.parts[lastIndex]?.type !== "reasoning") return false;
1990
- return lastIndex >= group.indices[0] && lastIndex <= group.indices[group.indices.length - 1];
1451
+ const lastGroupIndex = group.indices[group.indices.length - 1];
1452
+ return lastGroupIndex !== void 0 && lastIndex >= group.indices[0] && lastIndex <= lastGroupIndex;
1991
1453
  });
1992
- const [expanded, setExpanded] = useState6(streaming);
1993
- const [prevStreaming, setPrevStreaming] = useState6(streaming);
1454
+ const [expanded, setExpanded] = useState4(streaming);
1455
+ const [prevStreaming, setPrevStreaming] = useState4(streaming);
1456
+ const [isMultiLine, setIsMultiLine] = useState4(false);
1457
+ const observerRef = useRef(null);
1994
1458
  if (streaming !== prevStreaming) {
1995
1459
  setPrevStreaming(streaming);
1996
1460
  if (streaming) setExpanded(true);
1997
1461
  }
1998
- return /* @__PURE__ */ jsx39(ReasoningCard2, { streaming, expanded, onToggle: () => setExpanded((prev) => !prev), children });
1462
+ const contentRef = useCallback4(
1463
+ (node) => {
1464
+ observerRef.current?.disconnect();
1465
+ observerRef.current = null;
1466
+ if (node == null || streaming) return;
1467
+ const check = () => {
1468
+ const lineHeight = Number.parseFloat(getComputedStyle(node).lineHeight) || 24;
1469
+ setIsMultiLine(node.scrollHeight > lineHeight * 1.5);
1470
+ };
1471
+ check();
1472
+ observerRef.current = new ResizeObserver(check);
1473
+ observerRef.current.observe(node);
1474
+ },
1475
+ [streaming]
1476
+ );
1477
+ const reasoningTimeText = null;
1478
+ const previewText = content.replace(/\s+/g, " ").trim();
1479
+ 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(
1482
+ ReasoningCard2,
1483
+ {
1484
+ content,
1485
+ isStreaming: streaming,
1486
+ expanded,
1487
+ isMultiLine,
1488
+ reasoningTimeText,
1489
+ previewText,
1490
+ headingText,
1491
+ contentRef: isShortText ? contentRef : void 0,
1492
+ onToggle: () => setExpanded((prev) => !prev)
1493
+ }
1494
+ );
1999
1495
  }
2000
1496
 
2001
1497
  // src/containers/ToolCallContainer.tsx
2002
- import { useState as useState7 } from "react";
1498
+ import { useState as useState8 } from "react";
2003
1499
  import {
1500
+ MessagePartPrimitive,
2004
1501
  MessagePrimitive,
2005
1502
  useToolCallElapsed
2006
1503
  } from "@assistant-ui/react";
@@ -2015,9 +1512,192 @@ function useNestedApprovalBridge() {
2015
1512
  return useContext5(NestedApprovalBridgeContext);
2016
1513
  }
2017
1514
 
1515
+ // src/containers/SandboxToolCallContainer.tsx
1516
+ import { useMemo as useMemo3, useState as useState5 } from "react";
1517
+ import { jsx as jsx43 } from "react/jsx-runtime";
1518
+ function SandboxToolCallContainer(props) {
1519
+ const SandboxToolCallCard2 = useSlot("SandboxToolCallCard");
1520
+ const [viewMode, setViewMode] = useState5("terminal");
1521
+ const hasContent = useMemo3(() => {
1522
+ if (viewMode === "code") return Boolean(props.argsJson || props.resultJson);
1523
+ return Boolean(props.command || props.resultText || props.resultJson);
1524
+ }, [
1525
+ props.argsJson,
1526
+ props.command,
1527
+ props.resultJson,
1528
+ props.resultText,
1529
+ viewMode
1530
+ ]);
1531
+ return /* @__PURE__ */ jsx43(
1532
+ SandboxToolCallCard2,
1533
+ {
1534
+ ...props,
1535
+ viewMode,
1536
+ hasContent,
1537
+ onViewModeChange: setViewMode
1538
+ }
1539
+ );
1540
+ }
1541
+
1542
+ // src/containers/ToolApprovalContainer.tsx
1543
+ import { useCallback as useCallback5, useMemo as useMemo4, useState as useState6 } from "react";
1544
+ import { jsx as jsx44 } from "react/jsx-runtime";
1545
+ function ToolApprovalContainer({
1546
+ toolName = "",
1547
+ options,
1548
+ onSelectOption
1549
+ }) {
1550
+ const ToolApprovalBar2 = useSlot("ToolApprovalBar");
1551
+ const [selectedDenyOptionId, setSelectedDenyOptionId] = useState6(null);
1552
+ const [denialReason, setDenialReason] = useState6("");
1553
+ const [showReasonError, setShowReasonError] = useState6(false);
1554
+ const approveOptions = useMemo4(
1555
+ () => options.filter((option) => option.isAllow).map((option, index) => ({
1556
+ ...option,
1557
+ variant: index === 0 ? "primary" : "secondary",
1558
+ requiresReason: false
1559
+ })),
1560
+ [options]
1561
+ );
1562
+ const denyOptions = useMemo4(
1563
+ () => options.filter((option) => !option.isAllow).map((option) => ({
1564
+ ...option,
1565
+ variant: "secondary",
1566
+ requiresReason: option.confirm != null
1567
+ })),
1568
+ [options]
1569
+ );
1570
+ const selectedDenyOption = denyOptions.find(
1571
+ (option) => option.id === selectedDenyOptionId
1572
+ );
1573
+ const onDenyOptionChange = useCallback5((optionId) => {
1574
+ setSelectedDenyOptionId(optionId);
1575
+ setDenialReason("");
1576
+ setShowReasonError(false);
1577
+ }, []);
1578
+ const onDenialReasonChange = useCallback5((reason) => {
1579
+ setDenialReason(reason);
1580
+ setShowReasonError(false);
1581
+ }, []);
1582
+ const onReasonSubmit = useCallback5(() => {
1583
+ const reason = denialReason.trim();
1584
+ if (!reason) {
1585
+ setShowReasonError(true);
1586
+ return;
1587
+ }
1588
+ if (selectedDenyOptionId) {
1589
+ onSelectOption(selectedDenyOptionId, reason);
1590
+ onDenyOptionChange(null);
1591
+ }
1592
+ }, [denialReason, onDenyOptionChange, onSelectOption, selectedDenyOptionId]);
1593
+ return /* @__PURE__ */ jsx44(
1594
+ ToolApprovalBar2,
1595
+ {
1596
+ toolName,
1597
+ approveOptions: approveOptions.length > 0 ? approveOptions : void 0,
1598
+ denyOptions: denyOptions.length > 0 ? denyOptions : void 0,
1599
+ selectedDenyOption,
1600
+ denialReason,
1601
+ showReasonError,
1602
+ onSelect: onSelectOption,
1603
+ onDenyOptionChange,
1604
+ onDenialReasonChange,
1605
+ onReasonSubmit
1606
+ }
1607
+ );
1608
+ }
1609
+
1610
+ // src/containers/ToolCallContentBlockContainer.tsx
1611
+ import { useCallback as useCallback6, useEffect as useEffect2, useRef as useRef2, useState as useState7 } from "react";
1612
+ import { jsx as jsx45 } from "react/jsx-runtime";
1613
+ function ToolCallContentBlockContainer(props) {
1614
+ const ToolCallContentBlock2 = useSlot("ToolCallContentBlock");
1615
+ const [fullscreen, setFullscreen] = useState7(false);
1616
+ const [contentHeightRem, setContentHeightRem] = useState7(1.5);
1617
+ const observerRef = useRef2(null);
1618
+ const contentRef = useCallback6(
1619
+ (node) => {
1620
+ observerRef.current?.disconnect();
1621
+ observerRef.current = null;
1622
+ if (!props.resizable || node == null) return;
1623
+ const updateHeight = () => setContentHeightRem(node.scrollHeight / 16);
1624
+ updateHeight();
1625
+ observerRef.current = new ResizeObserver(updateHeight);
1626
+ observerRef.current.observe(node);
1627
+ },
1628
+ [props.resizable]
1629
+ );
1630
+ useEffect2(
1631
+ () => () => {
1632
+ observerRef.current?.disconnect();
1633
+ },
1634
+ []
1635
+ );
1636
+ return /* @__PURE__ */ jsx45(
1637
+ ToolCallContentBlock2,
1638
+ {
1639
+ ...props,
1640
+ fullscreen,
1641
+ onFullscreenChange: setFullscreen,
1642
+ contentHeightRem,
1643
+ contentRef
1644
+ }
1645
+ );
1646
+ }
1647
+
2018
1648
  // src/containers/ToolCallContainer.tsx
2019
- import { jsx as jsx40 } from "react/jsx-runtime";
1649
+ import { jsx as jsx46 } from "react/jsx-runtime";
2020
1650
  var SUB_AGENT_TOOL_NAME = "create_sub_agent";
1651
+ var ASK_USER_TOOL_NAME = "ask_user_question";
1652
+ function NestedSubAgentAssistantMessage() {
1653
+ 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(
1655
+ MessagePrimitive.Parts,
1656
+ {
1657
+ components: {
1658
+ Text: AssistantTextContainer,
1659
+ Reasoning: AssistantTextContainer,
1660
+ tools: { Fallback: ToolCallContainer }
1661
+ }
1662
+ }
1663
+ ) }) }) });
1664
+ }
1665
+ function parseAskUserQuestionArgs(argsText) {
1666
+ if (!argsText) return {};
1667
+ try {
1668
+ const parsed = JSON.parse(argsText);
1669
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
1670
+ return {};
1671
+ }
1672
+ const record = parsed;
1673
+ const question = typeof record.question === "string" ? record.question : void 0;
1674
+ const options = Array.isArray(record.options) ? record.options.filter(
1675
+ (item) => typeof item === "string"
1676
+ ) : void 0;
1677
+ return { question, options };
1678
+ } catch {
1679
+ return {};
1680
+ }
1681
+ }
1682
+ function getAskUserAnswerResult(result) {
1683
+ if (result === void 0 || result === null) return void 0;
1684
+ if (typeof result === "string") {
1685
+ const trimmed = result.trim();
1686
+ return trimmed.length > 0 ? trimmed : void 0;
1687
+ }
1688
+ if (typeof result === "object" && "content" in result) {
1689
+ const content = result.content;
1690
+ if (typeof content === "string" && content.trim()) {
1691
+ return content.trim();
1692
+ }
1693
+ }
1694
+ return void 0;
1695
+ }
1696
+ function hasPendingAskUserResponse(part) {
1697
+ return part.interrupt != null && part.result === void 0;
1698
+ }
1699
+ var SANDBOX_TOOL_NAMES = /* @__PURE__ */ new Set(["exec", "sandbox_exec"]);
1700
+ var MCP_META_TOOLS = /* @__PURE__ */ new Set(["call_tool", "list_tools", "get_tool_info"]);
2021
1701
  var APPROVAL_OPTION_DEFAULT_LABELS = {
2022
1702
  "allow-once": "Allow",
2023
1703
  "allow-always": "Always allow",
@@ -2029,7 +1709,9 @@ function hasPendingToolApproval(approval) {
2029
1709
  return approval != null && approval.approved === void 0 && approval.resolution === void 0;
2030
1710
  }
2031
1711
  function buildApprovalOptions(options) {
2032
- const declared = options?.filter((o) => Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, o.kind));
1712
+ const declared = options?.filter(
1713
+ (o) => Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, o.kind)
1714
+ );
2033
1715
  if (declared && declared.length > 0) {
2034
1716
  const allow = declared.filter((o) => isAllowKind(o.kind));
2035
1717
  const reject = declared.filter((o) => !isAllowKind(o.kind));
@@ -2041,13 +1723,13 @@ function buildApprovalOptions(options) {
2041
1723
  confirm: o.confirm != null ? typeof o.confirm === "object" ? o.confirm : {} : void 0
2042
1724
  }));
2043
1725
  if (reject.length === 0) {
2044
- mapped.push({ id: "__deny", label: "Deny", isAllow: false });
1726
+ mapped.push({ id: "__deny", label: "Deny", isAllow: false, confirm: {} });
2045
1727
  }
2046
1728
  return mapped;
2047
1729
  }
2048
1730
  return [
2049
1731
  { id: "__allow", label: "Allow", isAllow: true },
2050
- { id: "__deny", label: "Deny", isAllow: false }
1732
+ { id: "__deny", label: "Deny", isAllow: false, confirm: {} }
2051
1733
  ];
2052
1734
  }
2053
1735
  function formatDuration(ms) {
@@ -2062,8 +1744,80 @@ function toStatus(statusType) {
2062
1744
  if (statusType === "incomplete") return "error";
2063
1745
  return "running";
2064
1746
  }
1747
+ function parseSandboxArgs(argsText) {
1748
+ if (!argsText) return {};
1749
+ try {
1750
+ const parsed = JSON.parse(argsText);
1751
+ return {
1752
+ command: parsed.command,
1753
+ intent: parsed.intent,
1754
+ argsJson: JSON.stringify(parsed, null, 2)
1755
+ };
1756
+ } catch {
1757
+ return { argsJson: argsText };
1758
+ }
1759
+ }
1760
+ function parseSandboxResult(result) {
1761
+ if (result === void 0) return {};
1762
+ try {
1763
+ const parsed = JSON.parse(result);
1764
+ const exitCode = parsed.response?.exitCode ?? null;
1765
+ const resultText = parsed.response?.result;
1766
+ return {
1767
+ exitCode,
1768
+ resultText,
1769
+ resultJson: JSON.stringify(parsed, null, 2)
1770
+ };
1771
+ } catch {
1772
+ return { resultText: result };
1773
+ }
1774
+ }
1775
+ function parseMcpToolArgs(argsText) {
1776
+ if (!argsText) return {};
1777
+ try {
1778
+ const parsed = JSON.parse(argsText);
1779
+ return {
1780
+ mcpServer: parsed.mcp_server,
1781
+ innerToolName: parsed.tool_name,
1782
+ input: parsed.input
1783
+ };
1784
+ } catch {
1785
+ return {};
1786
+ }
1787
+ }
1788
+ function getJsonDisplayValue(content) {
1789
+ if (!content?.trim()) return { value: "", isJson: false };
1790
+ const trimmed = content.trim();
1791
+ if (trimmed[0] !== "{" && trimmed[0] !== "[") {
1792
+ return { value: content, isJson: false };
1793
+ }
1794
+ try {
1795
+ const parsed = JSON.parse(content);
1796
+ return { value: JSON.stringify(parsed, null, 2), isJson: true };
1797
+ } catch {
1798
+ return { value: content, isJson: false };
1799
+ }
1800
+ }
1801
+ function getToolResultContent(content) {
1802
+ try {
1803
+ if (!content) return { isJson: false, data: "" };
1804
+ const parsedResult = typeof content === "string" && content.trim().startsWith("{") ? JSON.parse(content) : content;
1805
+ if (Array.isArray(parsedResult.content)) {
1806
+ const text = parsedResult.content[0]?.text || "";
1807
+ const display2 = getJsonDisplayValue(
1808
+ typeof text === "string" ? text : JSON.stringify(text)
1809
+ );
1810
+ return { data: display2.value, isJson: display2.isJson };
1811
+ }
1812
+ const display = getJsonDisplayValue(
1813
+ typeof parsedResult === "string" ? parsedResult : JSON.stringify(parsedResult)
1814
+ );
1815
+ return { data: display.value, isJson: display.isJson };
1816
+ } catch (error) {
1817
+ return { data: String(content), isJson: false };
1818
+ }
1819
+ }
2065
1820
  function ToolApprovalSlot({ part }) {
2066
- const ToolApprovalBar2 = useSlot("ToolApprovalBar");
2067
1821
  const nestedBridge = useNestedApprovalBridge();
2068
1822
  const respond = (response) => {
2069
1823
  if (nestedBridge) {
@@ -2072,33 +1826,73 @@ function ToolApprovalSlot({ part }) {
2072
1826
  }
2073
1827
  part.respondToApproval(response);
2074
1828
  };
2075
- const onSelectOption = (optionId) => {
1829
+ const onSelectOption = (optionId, reason) => {
2076
1830
  if (optionId === "__allow") return respond({ approved: true });
2077
- if (optionId === "__deny") return respond({ approved: false });
2078
- return respond({ optionId });
1831
+ if (optionId === "__deny") return respond({ approved: false, reason });
1832
+ return respond({ optionId, reason });
2079
1833
  };
2080
- return /* @__PURE__ */ jsx40(ToolApprovalBar2, { options: buildApprovalOptions(part.approval?.options), onSelectOption });
1834
+ return /* @__PURE__ */ jsx46(
1835
+ ToolApprovalContainer,
1836
+ {
1837
+ toolName: part.toolName,
1838
+ options: buildApprovalOptions(part.approval?.options),
1839
+ onSelectOption
1840
+ }
1841
+ );
2081
1842
  }
2082
1843
  var ToolCallContainer = (part) => {
2083
1844
  const ToolCallCard2 = useSlot("ToolCallCard");
1845
+ const SubAgentCard2 = useSlot("SubAgentCard");
1846
+ const AskUserPrompt2 = useSlot("AskUserPrompt");
2084
1847
  const respondToNestedApproval = useTrueFoundryRespondToToolApproval();
2085
1848
  const elapsedMs = useToolCallElapsed();
2086
1849
  const isRequiresAction = part.status?.type === "requires-action";
2087
- const [expanded, setExpanded] = useState7(isRequiresAction);
2088
- const [prevRequiresAction, setPrevRequiresAction] = useState7(isRequiresAction);
1850
+ const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
1851
+ const isSandbox = SANDBOX_TOOL_NAMES.has(part.toolName);
1852
+ const [expanded, setExpanded] = useState8(isRequiresAction || isSubAgent);
1853
+ const [prevRequiresAction, setPrevRequiresAction] = useState8(isRequiresAction);
2089
1854
  if (isRequiresAction !== prevRequiresAction) {
2090
1855
  setPrevRequiresAction(isRequiresAction);
2091
1856
  if (isRequiresAction) setExpanded(true);
2092
1857
  }
2093
1858
  const showApproval = isRequiresAction && hasPendingToolApproval(part.approval);
2094
- const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
2095
1859
  const durationText = elapsedMs === void 0 ? void 0 : formatDuration(elapsedMs);
2096
1860
  const status = toStatus(part.status?.type);
1861
+ if (part.toolName === ASK_USER_TOOL_NAME) {
1862
+ if (hasPendingAskUserResponse(part)) {
1863
+ return null;
1864
+ }
1865
+ const answer = getAskUserAnswerResult(part.result);
1866
+ if (answer == null) {
1867
+ return null;
1868
+ }
1869
+ const { question, options = [] } = parseAskUserQuestionArgs(part.argsText);
1870
+ const isCustom = options.length > 0 && !options.includes(answer);
1871
+ return /* @__PURE__ */ jsx46(
1872
+ AskUserPrompt2,
1873
+ {
1874
+ questions: [],
1875
+ answeredQuestions: [
1876
+ {
1877
+ id: part.toolCallId,
1878
+ question: question ?? "Question",
1879
+ options,
1880
+ answer,
1881
+ isCustom
1882
+ }
1883
+ ],
1884
+ onSubmit: () => {
1885
+ },
1886
+ readOnly: true
1887
+ }
1888
+ );
1889
+ }
2097
1890
  if (isSubAgent) {
1891
+ const artifactSubAgent = part.artifact?.subAgents?.[0];
2098
1892
  const firstNested = part.messages?.[0];
2099
1893
  const subAgent = firstNested?.metadata?.custom?.subAgent;
2100
- const agentName = subAgent?.title ?? subAgent?.name ?? part.toolName;
2101
- const instruction = subAgent?.input ?? "";
1894
+ const agentName = subAgent?.title ?? subAgent?.name ?? artifactSubAgent?.title ?? artifactSubAgent?.agentInfo?.name ?? part.toolName;
1895
+ const instruction = subAgent?.input ?? artifactSubAgent?.agentInfo?.input ?? "";
2102
1896
  const stepCount = part.messages?.length ?? 0;
2103
1897
  const bridge = (response) => {
2104
1898
  if (part.approval == null) return;
@@ -2106,51 +1900,223 @@ var ToolCallContainer = (part) => {
2106
1900
  if (approved === void 0) return;
2107
1901
  respondToNestedApproval({ approvalId: part.approval.id, approved });
2108
1902
  };
2109
- return /* @__PURE__ */ jsx40(
2110
- ToolCallCard2,
1903
+ return /* @__PURE__ */ jsx46(
1904
+ "div",
1905
+ {
1906
+ "data-slot": "tool-call-card",
1907
+ "data-variant": "sub-agent",
1908
+ className: "w-full py-2",
1909
+ children: /* @__PURE__ */ jsx46(
1910
+ SubAgentCard2,
1911
+ {
1912
+ status,
1913
+ expanded,
1914
+ onToggle: () => setExpanded((prev) => !prev),
1915
+ durationText,
1916
+ agentName,
1917
+ instruction,
1918
+ stepCount,
1919
+ children: /* @__PURE__ */ jsx46(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx46(
1920
+ MessagePartPrimitive.Messages,
1921
+ {
1922
+ components: {
1923
+ AssistantMessage: NestedSubAgentAssistantMessage,
1924
+ UserMessage: () => null
1925
+ }
1926
+ }
1927
+ ) })
1928
+ }
1929
+ )
1930
+ }
1931
+ );
1932
+ }
1933
+ const resultString = part.result === void 0 ? void 0 : typeof part.result === "string" ? part.result : JSON.stringify(part.result, null, 2);
1934
+ if (isSandbox) {
1935
+ const { command, intent, argsJson } = parseSandboxArgs(part.argsText);
1936
+ const { exitCode, resultText, resultJson } = parseSandboxResult(resultString);
1937
+ return /* @__PURE__ */ jsx46(
1938
+ SandboxToolCallContainer,
2111
1939
  {
2112
- variant: "sub-agent",
2113
1940
  name: part.toolName,
1941
+ intent,
2114
1942
  status,
2115
1943
  expanded,
2116
1944
  onToggle: () => setExpanded((prev) => !prev),
2117
1945
  durationText,
2118
- agentName,
2119
- instruction,
2120
- stepCount,
2121
- children: /* @__PURE__ */ jsx40(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx40(MessagePrimitive.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx40(MessagePrimitive.Parts, { components: { tools: { Fallback: ToolCallContainer } } }) }) })
1946
+ command,
1947
+ exitCode,
1948
+ argsJson,
1949
+ resultText,
1950
+ resultJson
1951
+ }
1952
+ );
1953
+ }
1954
+ const isMcpMetaTool = MCP_META_TOOLS.has(part.toolName);
1955
+ if (isMcpMetaTool) {
1956
+ const { mcpServer, innerToolName, input } = parseMcpToolArgs(part.argsText);
1957
+ const argsDisplay2 = getJsonDisplayValue(part.argsText);
1958
+ const resultDisplay2 = getToolResultContent(part.result);
1959
+ if (part.toolName === "list_tools" && mcpServer) {
1960
+ return /* @__PURE__ */ jsx46(
1961
+ ToolCallCard2,
1962
+ {
1963
+ toolName: `Listing tools \xB7 ${mcpServer}`,
1964
+ icon: "mcp-server",
1965
+ expanded,
1966
+ onToggle: () => setExpanded((prev) => !prev),
1967
+ awaiting: status === "running",
1968
+ awaitingText: durationText ?? "Awaiting Response\u2026",
1969
+ showResponseLine: status !== "running" && !!resultDisplay2.data,
1970
+ mcpServerName: mcpServer,
1971
+ requestSlot: argsDisplay2.value ? /* @__PURE__ */ jsx46(
1972
+ ToolCallContentBlockContainer,
1973
+ {
1974
+ title: "Request",
1975
+ content: argsDisplay2.value,
1976
+ isJson: argsDisplay2.isJson,
1977
+ maxHeight: "10.5rem"
1978
+ }
1979
+ ) : resultDisplay2.data ? /* @__PURE__ */ jsx46(
1980
+ ToolCallContentBlockContainer,
1981
+ {
1982
+ title: "Request",
1983
+ content: "{}",
1984
+ isJson: true,
1985
+ maxHeight: "10.5rem"
1986
+ }
1987
+ ) : void 0,
1988
+ responseSlot: resultDisplay2.data ? /* @__PURE__ */ jsx46(
1989
+ ToolCallContentBlockContainer,
1990
+ {
1991
+ title: "Response",
1992
+ content: resultDisplay2.data,
1993
+ isJson: resultDisplay2.isJson,
1994
+ resizable: true
1995
+ }
1996
+ ) : void 0
1997
+ }
1998
+ );
1999
+ }
2000
+ let displayName = part.toolName;
2001
+ if (part.toolName === "call_tool" && innerToolName) {
2002
+ displayName = mcpServer ? `call_tool: ${innerToolName} (${mcpServer})` : `call_tool: ${innerToolName}`;
2003
+ } else if (part.toolName === "get_tool_info" && innerToolName && mcpServer) {
2004
+ displayName = `get_tool_info: ${innerToolName} (${mcpServer})`;
2005
+ }
2006
+ const inputDisplay = input !== void 0 ? getJsonDisplayValue(JSON.stringify(input, null, 2)) : argsDisplay2;
2007
+ return /* @__PURE__ */ jsx46(
2008
+ ToolCallCard2,
2009
+ {
2010
+ toolName: displayName,
2011
+ icon: "mcp-server",
2012
+ expanded,
2013
+ onToggle: () => setExpanded((prev) => !prev),
2014
+ awaiting: status === "running",
2015
+ awaitingText: durationText ?? "Awaiting Response\u2026",
2016
+ showResponseLine: status !== "running" && resultDisplay2.data !== void 0,
2017
+ mcpServerName: mcpServer,
2018
+ requestSlot: inputDisplay.value ? /* @__PURE__ */ jsx46(
2019
+ ToolCallContentBlockContainer,
2020
+ {
2021
+ title: "Request",
2022
+ content: inputDisplay.value,
2023
+ isJson: inputDisplay.isJson,
2024
+ maxHeight: "10.5rem"
2025
+ }
2026
+ ) : resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2027
+ ToolCallContentBlockContainer,
2028
+ {
2029
+ title: "Request",
2030
+ content: "{}",
2031
+ isJson: true,
2032
+ maxHeight: "10.5rem"
2033
+ }
2034
+ ) : void 0,
2035
+ responseSlot: resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2036
+ ToolCallContentBlockContainer,
2037
+ {
2038
+ title: "Response",
2039
+ content: resultDisplay2.data,
2040
+ isJson: resultDisplay2.isJson,
2041
+ resizable: true
2042
+ }
2043
+ ) : void 0,
2044
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2122
2045
  }
2123
2046
  );
2124
2047
  }
2125
- return /* @__PURE__ */ jsx40(
2048
+ const argsDisplay = getJsonDisplayValue(part.argsText);
2049
+ const resultDisplay = getToolResultContent(part.result);
2050
+ return /* @__PURE__ */ jsx46(
2126
2051
  ToolCallCard2,
2127
2052
  {
2128
- variant: "tool",
2129
- name: part.toolName,
2130
- status,
2053
+ toolName: part.toolName,
2131
2054
  expanded,
2132
2055
  onToggle: () => setExpanded((prev) => !prev),
2133
- durationText,
2134
- argsText: part.argsText,
2135
- result: part.result === void 0 ? void 0 : typeof part.result === "string" ? part.result : JSON.stringify(part.result, null, 2),
2136
- isError: part.isError,
2137
- approvalSlot: showApproval ? /* @__PURE__ */ jsx40(ToolApprovalSlot, { part }) : void 0
2056
+ awaiting: status === "running",
2057
+ awaitingText: durationText ?? "Awaiting Response\u2026",
2058
+ showResponseLine: status !== "running" && resultDisplay.data !== void 0,
2059
+ requestSlot: argsDisplay.value ? /* @__PURE__ */ jsx46(
2060
+ ToolCallContentBlockContainer,
2061
+ {
2062
+ title: "Request",
2063
+ content: argsDisplay.value,
2064
+ isJson: argsDisplay.isJson,
2065
+ maxHeight: "10.5rem"
2066
+ }
2067
+ ) : resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2068
+ ToolCallContentBlockContainer,
2069
+ {
2070
+ title: "Request",
2071
+ content: "{}",
2072
+ isJson: true,
2073
+ maxHeight: "10.5rem"
2074
+ }
2075
+ ) : void 0,
2076
+ responseSlot: resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2077
+ ToolCallContentBlockContainer,
2078
+ {
2079
+ title: "Response",
2080
+ content: resultDisplay.data,
2081
+ isJson: resultDisplay.isJson,
2082
+ resizable: true
2083
+ }
2084
+ ) : void 0,
2085
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2138
2086
  }
2139
2087
  );
2140
2088
  };
2141
2089
 
2142
2090
  // src/containers/ToolGroupContainer.tsx
2143
- import { useState as useState8 } from "react";
2144
- import { jsx as jsx41 } from "react/jsx-runtime";
2145
- function ToolGroupContainer({ group, children }) {
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({
2095
+ children,
2096
+ group
2097
+ }) {
2146
2098
  const ToolGroupCard2 = useSlot("ToolGroupCard");
2147
- const [expanded, setExpanded] = useState8(true);
2148
- return /* @__PURE__ */ jsx41(
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
+ });
2108
+ 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(
2149
2115
  ToolGroupCard2,
2150
2116
  {
2151
- toolCallCount: group.indices.length,
2152
- active: group.status.type === "running",
2117
+ toolCallCount,
2153
2118
  expanded,
2119
+ active,
2154
2120
  onToggle: () => setExpanded((prev) => !prev),
2155
2121
  children
2156
2122
  }
@@ -2158,66 +2124,36 @@ function ToolGroupContainer({ group, children }) {
2158
2124
  }
2159
2125
 
2160
2126
  // src/containers/AssistantMessageContainer.tsx
2161
- import { jsx as jsx42 } from "react/jsx-runtime";
2127
+ import { jsx as jsx48 } from "react/jsx-runtime";
2162
2128
  function AssistantLeafPartContainer({ part }) {
2163
2129
  switch (part.type) {
2164
2130
  case "text":
2165
2131
  case "reasoning":
2166
- return /* @__PURE__ */ jsx42(AssistantTextContainer, {});
2132
+ return /* @__PURE__ */ jsx48(AssistantTextContainer, {});
2167
2133
  case "image":
2168
- return /* @__PURE__ */ jsx42(MessageImageContainer, {});
2134
+ return /* @__PURE__ */ jsx48(MessageImageContainer, {});
2169
2135
  case "tool-call":
2170
- return /* @__PURE__ */ jsx42(ToolCallContainer, { ...part });
2136
+ return /* @__PURE__ */ jsx48(ToolCallContainer, { ...part });
2171
2137
  default:
2172
2138
  return null;
2173
2139
  }
2174
2140
  }
2175
- function downloadMarkdown(text) {
2176
- if (typeof document === "undefined") return;
2177
- const blob = new Blob([text], { type: "text/markdown" });
2178
- const url = URL.createObjectURL(blob);
2179
- const anchor = document.createElement("a");
2180
- anchor.href = url;
2181
- anchor.download = "message.md";
2182
- anchor.click();
2183
- URL.revokeObjectURL(url);
2184
- }
2185
2141
  function AssistantMessageContainer() {
2186
- const MessageBubble2 = useSlot("MessageBubble");
2142
+ const AssistantMessageBubble2 = useSlot("AssistantMessageBubble");
2187
2143
  const MessageIndicator2 = useSlot("MessageIndicator");
2188
2144
  const MessageErrorBanner2 = useSlot("MessageErrorBanner");
2189
2145
  const MessageActionBar2 = useSlot("MessageActionBar");
2190
- const BranchIndicator2 = useSlot("BranchIndicator");
2191
- const aui = useAui2();
2192
2146
  const isRunning = useThreadIsRunning2();
2193
2147
  const error = useMessageError();
2194
2148
  const { copy, isCopied } = useActionBarCopy2({
2195
2149
  copyToClipboard: (text) => navigator.clipboard.writeText(text)
2196
2150
  });
2197
- const { branchNumber, branchCount, goToPrev, goToNext } = useMessageBranching();
2198
- return /* @__PURE__ */ jsx42(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx42(
2199
- MessageBubble2,
2151
+ return /* @__PURE__ */ jsx48(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx48(
2152
+ AssistantMessageBubble2,
2200
2153
  {
2201
- variant: "assistant",
2202
- error: error !== void 0 ? /* @__PURE__ */ jsx42(MessageErrorBanner2, { message: String(error) }) : void 0,
2203
- branchIndicator: /* @__PURE__ */ jsx42(
2204
- BranchIndicator2,
2205
- {
2206
- index: branchNumber,
2207
- count: branchCount,
2208
- onPrevious: goToPrev,
2209
- onNext: goToNext
2210
- }
2211
- ),
2212
- actionBar: !isRunning ? /* @__PURE__ */ jsx42(
2213
- MessageActionBar2,
2214
- {
2215
- isCopied,
2216
- onCopy: copy,
2217
- onExportMarkdown: () => downloadMarkdown(aui.message().getCopyText())
2218
- }
2219
- ) : void 0,
2220
- children: /* @__PURE__ */ jsx42(
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(
2221
2157
  MessagePrimitive2.GroupedParts,
2222
2158
  {
2223
2159
  groupBy: groupPartByType({
@@ -2228,19 +2164,19 @@ function AssistantMessageContainer() {
2228
2164
  children: ({ part, children }) => {
2229
2165
  switch (part.type) {
2230
2166
  case "group-chainOfThought":
2231
- return /* @__PURE__ */ jsx42("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
2167
+ return /* @__PURE__ */ jsx48("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
2232
2168
  case "group-tool":
2233
- return /* @__PURE__ */ jsx42(ToolGroupContainer, { group: part, children });
2169
+ return /* @__PURE__ */ jsx48(ToolGroupContainer, { group: part, children });
2234
2170
  case "group-reasoning":
2235
- return /* @__PURE__ */ jsx42(ReasoningContainer, { group: part, children });
2171
+ return /* @__PURE__ */ jsx48(ReasoningContainer, { group: part });
2236
2172
  case "text":
2237
2173
  case "reasoning":
2238
2174
  case "tool-call":
2239
2175
  case "image":
2240
2176
  case "data":
2241
- return /* @__PURE__ */ jsx42(AssistantLeafPartContainer, { part });
2177
+ return /* @__PURE__ */ jsx48(AssistantLeafPartContainer, { part });
2242
2178
  case "indicator":
2243
- return /* @__PURE__ */ jsx42(MessageIndicator2, {});
2179
+ return /* @__PURE__ */ jsx48(MessageIndicator2, {});
2244
2180
  default:
2245
2181
  return null;
2246
2182
  }
@@ -2255,22 +2191,22 @@ function AssistantMessageContainer() {
2255
2191
  import {
2256
2192
  ComposerPrimitive as ComposerPrimitive2,
2257
2193
  MessagePrimitive as MessagePrimitive4,
2258
- useAuiState as useAuiState7
2194
+ useAuiState as useAuiState9
2259
2195
  } from "@assistant-ui/react";
2260
- import { useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
2196
+ import { useComposerCancel, useComposerSend, useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
2261
2197
 
2262
2198
  // src/containers/AttachmentsContainer.tsx
2263
- import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui as useAui3, useAuiState as useAuiState6 } from "@assistant-ui/react";
2199
+ import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui, useAuiState as useAuiState8 } from "@assistant-ui/react";
2264
2200
 
2265
2201
  // src/containers/useAttachmentPreviewSrc.ts
2266
- import { useEffect as useEffect2, useState as useState9 } from "react";
2267
- import { useAuiState as useAuiState5 } from "@assistant-ui/react";
2202
+ import { useEffect as useEffect3, useState as useState10 } from "react";
2203
+ import { useAuiState as useAuiState7 } from "@assistant-ui/react";
2268
2204
  function isImageAttachment(type, contentType) {
2269
2205
  return type === "image" || (contentType?.startsWith("image/") ?? false);
2270
2206
  }
2271
2207
  function useFileObjectUrl(file) {
2272
- const [src, setSrc] = useState9(void 0);
2273
- useEffect2(() => {
2208
+ const [src, setSrc] = useState10(void 0);
2209
+ useEffect3(() => {
2274
2210
  if (!file) {
2275
2211
  setSrc(void 0);
2276
2212
  return;
@@ -2282,10 +2218,10 @@ function useFileObjectUrl(file) {
2282
2218
  return src;
2283
2219
  }
2284
2220
  function useAttachmentPreviewSrc() {
2285
- const type = useAuiState5((s) => s.attachment.type);
2286
- const contentType = useAuiState5((s) => s.attachment.contentType);
2287
- const file = useAuiState5((s) => "file" in s.attachment ? s.attachment.file : void 0);
2288
- const contentSrc = useAuiState5((s) => {
2221
+ const type = useAuiState7((s) => s.attachment.type);
2222
+ const contentType = useAuiState7((s) => s.attachment.contentType);
2223
+ const file = useAuiState7((s) => "file" in s.attachment ? s.attachment.file : void 0);
2224
+ const contentSrc = useAuiState7((s) => {
2289
2225
  if (!isImageAttachment(s.attachment.type, s.attachment.contentType)) return void 0;
2290
2226
  const imagePart = s.attachment.content?.find((part) => part.type === "image");
2291
2227
  if (imagePart?.type === "image" && imagePart.image) return imagePart.image;
@@ -2298,17 +2234,17 @@ function useAttachmentPreviewSrc() {
2298
2234
  }
2299
2235
 
2300
2236
  // src/containers/AttachmentsContainer.tsx
2301
- import { jsx as jsx43 } from "react/jsx-runtime";
2237
+ import { jsx as jsx49 } from "react/jsx-runtime";
2302
2238
  function ComposerAttachmentItem() {
2303
2239
  const AttachmentCard2 = useSlot("AttachmentCard");
2304
2240
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
2305
- const aui = useAui3();
2306
- const name = useAuiState6((s) => s.attachment.name);
2307
- const contentType = useAuiState6((s) => s.attachment.contentType);
2308
- const type = useAuiState6((s) => s.attachment.type);
2241
+ const aui = useAui();
2242
+ const name = useAuiState8((s) => s.attachment.name);
2243
+ const contentType = useAuiState8((s) => s.attachment.contentType);
2244
+ const type = useAuiState8((s) => s.attachment.type);
2309
2245
  const isImage = isImageAttachment(type, contentType);
2310
2246
  const previewSrc = useAttachmentPreviewSrc();
2311
- return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx43(
2247
+ return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx49(
2312
2248
  AttachmentCard2,
2313
2249
  {
2314
2250
  name,
@@ -2323,12 +2259,12 @@ function ComposerAttachmentItem() {
2323
2259
  function MessageAttachmentItem() {
2324
2260
  const AttachmentCard2 = useSlot("AttachmentCard");
2325
2261
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
2326
- const name = useAuiState6((s) => s.attachment.name);
2327
- const contentType = useAuiState6((s) => s.attachment.contentType);
2328
- const type = useAuiState6((s) => s.attachment.type);
2262
+ const name = useAuiState8((s) => s.attachment.name);
2263
+ const contentType = useAuiState8((s) => s.attachment.contentType);
2264
+ const type = useAuiState8((s) => s.attachment.type);
2329
2265
  const isImage = isImageAttachment(type, contentType);
2330
2266
  const previewSrc = useAttachmentPreviewSrc();
2331
- const card = /* @__PURE__ */ jsx43(
2267
+ const card = /* @__PURE__ */ jsx49(
2332
2268
  AttachmentCard2,
2333
2269
  {
2334
2270
  name,
@@ -2340,122 +2276,120 @@ function MessageAttachmentItem() {
2340
2276
  }
2341
2277
  );
2342
2278
  if (isImage && previewSrc) {
2343
- return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: card });
2279
+ return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: card });
2344
2280
  }
2345
2281
  return card;
2346
2282
  }
2347
2283
  function ComposerAttachmentsContainer() {
2348
- return /* @__PURE__ */ jsx43("div", { className: "aui-composer-attachments flex w-full flex-row flex-wrap items-center gap-2 empty:hidden", children: /* @__PURE__ */ jsx43(ComposerPrimitive.Attachments, { children: () => /* @__PURE__ */ jsx43(ComposerAttachmentItem, {}) }) });
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, {}) }) });
2349
2285
  }
2350
2286
  function MessageAttachmentsContainer() {
2351
- return /* @__PURE__ */ jsx43("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__ */ jsx43(MessagePrimitive3.Attachments, { children: () => /* @__PURE__ */ jsx43(MessageAttachmentItem, {}) }) });
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, {}) }) });
2352
2288
  }
2353
2289
  function ComposerAttachmentPickerContainer() {
2354
2290
  const AttachmentPickerButton2 = useSlot("AttachmentPickerButton");
2355
- return /* @__PURE__ */ jsx43(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx43(AttachmentPickerButton2, {}) });
2291
+ return /* @__PURE__ */ jsx49(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx49(AttachmentPickerButton2, {}) });
2356
2292
  }
2357
2293
 
2358
2294
  // src/containers/UserEditComposerContainer.tsx
2359
- import { jsx as jsx44, jsxs as jsxs25 } from "react/jsx-runtime";
2295
+ import { jsx as jsx50, jsxs as jsxs16 } from "react/jsx-runtime";
2360
2296
  function ReadOnlyMessageAttachments() {
2361
- const hasAttachments = useAuiState7(
2297
+ const hasAttachments = useAuiState9(
2362
2298
  (s) => (s.message.attachments?.length ?? 0) > 0
2363
2299
  );
2364
2300
  if (!hasAttachments) {
2365
2301
  return null;
2366
2302
  }
2367
- return /* @__PURE__ */ jsx44("div", { className: "pointer-events-none opacity-90", children: /* @__PURE__ */ jsx44(MessageAttachmentsContainer, {}) });
2303
+ return /* @__PURE__ */ jsx50("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx50(MessageAttachmentsContainer, {}) });
2368
2304
  }
2369
2305
  function UserEditComposerContainer() {
2370
- const Button2 = useSlot("Button");
2306
+ const Button4 = useSlot("Button");
2307
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
2308
+ const UserMessageEdit3 = useSlot("UserMessageEdit");
2371
2309
  const isRunning = useThreadIsRunning3();
2372
- return /* @__PURE__ */ jsx44(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsxs25(
2310
+ const { cancel, disabled: cancelDisabled } = useComposerCancel();
2311
+ const { send, disabled: sendDisabled } = useComposerSend();
2312
+ return /* @__PURE__ */ jsx50(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx50(
2373
2313
  "div",
2374
2314
  {
2375
2315
  "data-slot": "aui_user-edit-composer-root",
2376
- className: "fade-in slide-in-from-bottom-1 animate-in grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 duration-150 [&:where(>*)]:col-start-2",
2377
- children: [
2378
- /* @__PURE__ */ jsx44(ReadOnlyMessageAttachments, {}),
2379
- /* @__PURE__ */ jsx44(ComposerPrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx44("div", { className: "aui-user-edit-composer col-start-2 min-w-0", children: /* @__PURE__ */ jsxs25("div", { className: "ring-primary/60 bg-muted rounded-xl px-4 py-3 ring-2", children: [
2380
- /* @__PURE__ */ jsx44(
2316
+ 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(
2318
+ UserMessageEdit3,
2319
+ {
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(
2381
2323
  ComposerPrimitive2.Input,
2382
2324
  {
2383
2325
  disabled: isRunning,
2384
- className: "placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none bg-transparent text-base outline-none"
2326
+ className: "max-h-32 min-h-10 w-full resize-none border-none bg-transparent p-0 text-base leading-[1.34] outline-none focus:shadow-none"
2385
2327
  }
2386
- ),
2387
- /* @__PURE__ */ jsxs25("div", { className: "mt-3 flex items-end justify-between gap-3", children: [
2388
- /* @__PURE__ */ jsxs25("p", { className: "text-muted-foreground text-xs", children: [
2389
- /* @__PURE__ */ jsx44("kbd", { className: "bg-background/60 rounded border px-1 py-0.5 font-sans text-[10px]", children: "Enter" }),
2390
- " ",
2391
- "to save",
2392
- " ",
2393
- /* @__PURE__ */ jsx44("kbd", { className: "bg-background/60 rounded border px-1 py-0.5 font-sans text-[10px]", children: "Esc" }),
2394
- " ",
2395
- "to cancel"
2396
- ] }),
2397
- /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
2398
- /* @__PURE__ */ jsx44(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx44(
2399
- Button2,
2400
- {
2401
- type: "button",
2402
- variant: "ghost",
2403
- size: "sm",
2404
- className: "text-muted-foreground h-8 px-2",
2405
- children: "Cancel"
2406
- }
2407
- ) }),
2408
- /* @__PURE__ */ jsx44(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx44(
2409
- Button2,
2410
- {
2411
- type: "button",
2412
- size: "sm",
2413
- className: cn("h-8 rounded-lg px-3"),
2414
- disabled: isRunning,
2415
- children: "Send"
2416
- }
2417
- ) })
2418
- ] })
2328
+ ) }),
2329
+ footer: /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-end gap-2", children: [
2330
+ /* @__PURE__ */ jsx50(
2331
+ Button4.Secondary,
2332
+ {
2333
+ type: "button",
2334
+ disabled: cancelDisabled,
2335
+ onClick: cancel,
2336
+ text: "Cancel"
2337
+ }
2338
+ ),
2339
+ /* @__PURE__ */ jsx50(
2340
+ Button4.Primary,
2341
+ {
2342
+ type: "button",
2343
+ disabled: sendDisabled || isRunning,
2344
+ onClick: () => send(),
2345
+ text: "Save & Rerun"
2346
+ }
2347
+ )
2419
2348
  ] })
2420
- ] }) }) })
2421
- ]
2349
+ }
2350
+ ) })
2422
2351
  }
2423
2352
  ) });
2424
2353
  }
2425
2354
 
2426
2355
  // src/containers/UserMessageContainer.tsx
2427
- import { MessagePrimitive as MessagePrimitive5 } from "@assistant-ui/react";
2356
+ import { MessagePrimitive as MessagePrimitive5, useAuiState as useAuiState10 } from "@assistant-ui/react";
2428
2357
  import { useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
2429
- import { jsx as jsx45 } from "react/jsx-runtime";
2358
+ import { jsx as jsx51 } from "react/jsx-runtime";
2430
2359
  function UserMessageContainer() {
2431
- const MessageBubble2 = useSlot("MessageBubble");
2360
+ const UserMessageBubble2 = useSlot("UserMessageBubble");
2432
2361
  const UserMessageActionBar2 = useSlot("UserMessageActionBar");
2433
2362
  const isRunning = useThreadIsRunning4();
2434
- return /* @__PURE__ */ jsx45(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx45(
2435
- MessageBubble2,
2363
+ const text = useAuiState10(
2364
+ (s) => s.message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n")
2365
+ );
2366
+ return /* @__PURE__ */ jsx51(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx51(
2367
+ UserMessageBubble2,
2436
2368
  {
2437
- variant: "user",
2438
- attachments: /* @__PURE__ */ jsx45(MessageAttachmentsContainer, {}),
2439
- actionBar: !isRunning ? /* @__PURE__ */ jsx45(UserMessageActionBar2, {}) : void 0,
2440
- children: /* @__PURE__ */ jsx45(MessagePrimitive5.Parts, { components: { Text: AssistantTextContainer } })
2369
+ text,
2370
+ attachments: /* @__PURE__ */ jsx51(MessageAttachmentsContainer, {}),
2371
+ editAction: !isRunning ? /* @__PURE__ */ jsx51(UserMessageActionBar2, {}) : void 0
2441
2372
  }
2442
2373
  ) });
2443
2374
  }
2444
2375
 
2445
2376
  // src/containers/ThreadContainer.tsx
2446
- import { jsx as jsx46, jsxs as jsxs26 } from "react/jsx-runtime";
2377
+ import { jsx as jsx52, jsxs as jsxs17 } from "react/jsx-runtime";
2447
2378
  var isNewChatView = (s) => s.thread.messages.length === 0 && (!s.thread.isLoading || s.threads.isLoading);
2448
2379
  function ThreadMessage({ isEditing }) {
2449
- const role = useAuiState8((s) => s.message.role);
2380
+ const role = useAuiState11((s) => s.message.role);
2450
2381
  if (role === "user") {
2451
2382
  if (isEditing) {
2452
- return /* @__PURE__ */ jsx46(UserEditComposerContainer, {});
2383
+ return /* @__PURE__ */ jsx52(UserEditComposerContainer, {});
2453
2384
  }
2454
- return /* @__PURE__ */ jsx46(UserMessageContainer, {});
2385
+ return /* @__PURE__ */ jsx52(UserMessageContainer, {});
2455
2386
  }
2456
- return /* @__PURE__ */ jsx46(AssistantMessageContainer, {});
2387
+ return /* @__PURE__ */ jsx52(AssistantMessageContainer, {});
2457
2388
  }
2458
2389
  function ThreadContainer({ composer }) {
2390
+ useEffect4(() => {
2391
+ void preloadMarkdownOpenUI();
2392
+ }, []);
2459
2393
  const ThreadRootShell2 = useSlot("ThreadRootShell");
2460
2394
  const ThreadViewportShell2 = useSlot("ThreadViewportShell");
2461
2395
  const ThreadComposerAreaShell2 = useSlot("ThreadComposerAreaShell");
@@ -2463,64 +2397,139 @@ function ThreadContainer({ composer }) {
2463
2397
  const WelcomeScreen2 = useSlot("WelcomeScreen");
2464
2398
  const MessageListSkeleton2 = useSlot("MessageListSkeleton");
2465
2399
  const ScrollToBottomButton2 = useSlot("ScrollToBottomButton");
2466
- const isEmpty = useAuiState8(isNewChatView);
2467
- const isLoading = useAuiState8((s) => s.thread.isLoading);
2468
- return /* @__PURE__ */ jsx46(ComposerBusyProvider, { children: /* @__PURE__ */ jsx46(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs26(ThreadRootShell2, { children: [
2469
- /* @__PURE__ */ jsx46(ThreadPrimitive.Viewport, { asChild: true, turnAnchor: "top", autoScroll: true, children: /* @__PURE__ */ jsxs26(ThreadViewportShell2, { isEmpty, children: [
2470
- isEmpty && /* @__PURE__ */ jsx46(WelcomeScreen2, {}),
2471
- isLoading ? /* @__PURE__ */ jsx46(MessageListSkeleton2, {}) : /* @__PURE__ */ jsx46(MessageGroup2, { children: /* @__PURE__ */ jsx46(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx46(
2400
+ const isEmpty = useAuiState11(isNewChatView);
2401
+ 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(
2472
2406
  ThreadMessage,
2473
2407
  {
2474
2408
  isEditing: message.role === "user" && message.composer.isEditing
2475
2409
  }
2476
2410
  ) }) })
2477
2411
  ] }) }),
2478
- !isLoading && /* @__PURE__ */ jsxs26(ThreadComposerAreaShell2, { isEmpty, children: [
2479
- /* @__PURE__ */ jsx46(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx46(ScrollToBottomButton2, {}) }),
2412
+ !isLoading && /* @__PURE__ */ jsxs17(ThreadComposerAreaShell2, { isEmpty, children: [
2413
+ !isEmpty && /* @__PURE__ */ jsx52(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx52(ScrollToBottomButton2, {}) }),
2480
2414
  composer
2481
2415
  ] })
2482
2416
  ] }) }) });
2483
2417
  }
2484
2418
 
2485
2419
  // src/containers/ComposerContainer.tsx
2486
- import { useRef } from "react";
2487
- import { useAui as useAui4, useAuiState as useAuiState9 } from "@assistant-ui/react";
2488
- import { useTrueFoundryCancel, useTrueFoundryToolResponses as useTrueFoundryToolResponses2 } from "@truefoundry/assistant-ui-runtime";
2420
+ import { useRef as useRef3 } from "react";
2421
+ import { useAui as useAui2, useAuiState as useAuiState13 } from "@assistant-ui/react";
2422
+ import { useTrueFoundryCancel } from "@truefoundry/assistant-ui-runtime";
2489
2423
 
2490
- // src/containers/AskUserContainer.tsx
2491
- import { useState as useState10 } from "react";
2424
+ // src/hooks/useComposerPauseView.ts
2425
+ import { useAuiState as useAuiState12 } from "@assistant-ui/react";
2492
2426
  import { useTrueFoundryToolResponses } from "@truefoundry/assistant-ui-runtime";
2427
+ function threadHasPendingMcpAuth(s) {
2428
+ const messages = s.thread.messages;
2429
+ const last = messages[messages.length - 1];
2430
+ if (last?.role !== "assistant") return false;
2431
+ if (last.status?.type !== "requires-action") return false;
2432
+ return last.metadata?.custom?.pendingMcpAuth === true;
2433
+ }
2434
+ function useComposerPauseView() {
2435
+ const mcpPending = useAuiState12(threadHasPendingMcpAuth);
2436
+ const { pending: toolResponsesPending } = useTrueFoundryToolResponses();
2437
+ if (mcpPending) {
2438
+ return { kind: "mcp" };
2439
+ }
2440
+ if (toolResponsesPending.length > 0) {
2441
+ return { kind: "ask-user" };
2442
+ }
2443
+ return { kind: "compose" };
2444
+ }
2445
+
2446
+ // src/containers/AskUserContainer.tsx
2447
+ import { useTrueFoundryToolResponses as useTrueFoundryToolResponses2 } from "@truefoundry/assistant-ui-runtime";
2493
2448
  import { useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
2494
- import { jsx as jsx47 } from "react/jsx-runtime";
2495
- var OTHER_OPTION_ID2 = "__other";
2449
+ import { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo5, useState as useState11 } from "react";
2450
+ import {
2451
+ ASK_USER_CUSTOM_OPTION
2452
+ } from "tfy-web-components/components/molecules/agent-chat";
2453
+ import { jsx as jsx53 } from "react/jsx-runtime";
2454
+ var EMPTY_ANSWER = { radioValue: "", custom: "" };
2496
2455
  function AskUserContainer() {
2497
2456
  const AskUserPrompt2 = useSlot("AskUserPrompt");
2498
- const { pending, respond } = useTrueFoundryToolResponses();
2457
+ const { pending, respond } = useTrueFoundryToolResponses2();
2499
2458
  const isRunning = useThreadIsRunning5();
2500
- const [selectedOptionId, setSelectedOptionId] = useState10(void 0);
2501
- const [otherValue, setOtherValue] = useState10("");
2502
2459
  const item = pending[0];
2503
- if (item == null) return null;
2504
- const options = (item.options ?? []).map((option) => ({ id: option, label: option }));
2505
- const allowOther = options.length === 0;
2506
- const onSubmit = () => {
2507
- const content = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID2 ? options.find((o) => o.id === selectedOptionId)?.label ?? "" : otherValue.trim();
2460
+ const questions = useMemo5(
2461
+ () => item == null ? [] : [
2462
+ {
2463
+ id: item.toolCallId,
2464
+ question: item.question ?? "Answer required",
2465
+ options: item.options ?? []
2466
+ }
2467
+ ],
2468
+ [item]
2469
+ );
2470
+ const [currentQuestionIndex, setCurrentQuestionIndex] = useState11(0);
2471
+ const [answers, setAnswers] = useState11(
2472
+ {}
2473
+ );
2474
+ useEffect5(() => {
2475
+ setCurrentQuestionIndex(0);
2476
+ setAnswers({});
2477
+ }, [item?.toolCallId]);
2478
+ const safeIndex = Math.min(
2479
+ currentQuestionIndex,
2480
+ Math.max(questions.length - 1, 0)
2481
+ );
2482
+ const currentQuestion = questions[safeIndex];
2483
+ const currentAnswer = currentQuestion == null ? EMPTY_ANSWER : answers[currentQuestion.id] ?? EMPTY_ANSWER;
2484
+ const getResponseForQuestion = useCallback7(
2485
+ (questionId) => {
2486
+ const answer = answers[questionId] ?? EMPTY_ANSWER;
2487
+ return answer.radioValue === ASK_USER_CUSTOM_OPTION ? answer.custom.trim() : answer.radioValue.trim();
2488
+ },
2489
+ [answers]
2490
+ );
2491
+ const allQuestionsAnswered = useMemo5(
2492
+ () => questions.every((question) => getResponseForQuestion(question.id)),
2493
+ [getResponseForQuestion, questions]
2494
+ );
2495
+ const selectedResponse = currentAnswer.radioValue === ASK_USER_CUSTOM_OPTION ? currentAnswer.custom.trim() : currentAnswer.radioValue.trim();
2496
+ const isSubmitDisabled = isRunning || currentQuestion == null || selectedResponse.length === 0;
2497
+ const isSubmitAllDisabled = isSubmitDisabled || !allQuestionsAnswered;
2498
+ const onCurrentAnswerChange = useCallback7(
2499
+ (questionId, update) => {
2500
+ setAnswers((previous) => ({
2501
+ ...previous,
2502
+ [questionId]: {
2503
+ ...previous[questionId] ?? EMPTY_ANSWER,
2504
+ ...update
2505
+ }
2506
+ }));
2507
+ },
2508
+ []
2509
+ );
2510
+ const onSubmit = useCallback7(() => {
2511
+ if (item == null || !allQuestionsAnswered) return;
2512
+ const content = getResponseForQuestion(item.toolCallId);
2508
2513
  if (!content) return;
2509
2514
  respond({ toolCallId: item.toolCallId, content });
2510
- setSelectedOptionId(void 0);
2511
- setOtherValue("");
2512
- };
2513
- return /* @__PURE__ */ jsx47(
2515
+ }, [allQuestionsAnswered, getResponseForQuestion, item, respond]);
2516
+ if (item == null || currentQuestion == null) return null;
2517
+ return /* @__PURE__ */ jsx53(
2514
2518
  AskUserPrompt2,
2515
2519
  {
2516
- question: item.question ?? "Answer required",
2517
- options,
2518
- allowOther,
2519
- selectedOptionId,
2520
- otherValue,
2521
- disabled: isRunning,
2522
- onSelectOption: setSelectedOptionId,
2523
- onOtherValueChange: setOtherValue,
2520
+ questions,
2521
+ readOnly: isRunning,
2522
+ currentQuestion,
2523
+ currentQuestionIndex: safeIndex,
2524
+ currentAnswer,
2525
+ totalQuestions: questions.length,
2526
+ isMultiQuestion: questions.length > 1,
2527
+ isLastQuestion: safeIndex === questions.length - 1,
2528
+ allQuestionsAnswered,
2529
+ isSubmitDisabled,
2530
+ isSubmitAllDisabled,
2531
+ onCurrentQuestionIndexChange: setCurrentQuestionIndex,
2532
+ onCurrentAnswerChange,
2524
2533
  onSubmit
2525
2534
  }
2526
2535
  );
@@ -2529,66 +2538,72 @@ function AskUserContainer() {
2529
2538
  // src/containers/McpAuthContainer.tsx
2530
2539
  import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
2531
2540
  import { useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
2532
- import { jsx as jsx48 } from "react/jsx-runtime";
2541
+ import { jsx as jsx54 } from "react/jsx-runtime";
2533
2542
  function McpAuthContainer() {
2534
2543
  const McpAuthPrompt2 = useSlot("McpAuthPrompt");
2535
2544
  const { pending, resume } = useTrueFoundryMcpAuth();
2536
2545
  const isRunning = useThreadIsRunning6();
2537
2546
  if (!pending) return null;
2538
- return /* @__PURE__ */ jsx48(
2547
+ const handleConnect = (serverId) => {
2548
+ const server = pending.mcpServers.find((s) => s.id === serverId);
2549
+ if (server?.authUrl) {
2550
+ window.open(server.authUrl, "_blank", "noopener,noreferrer");
2551
+ }
2552
+ };
2553
+ return /* @__PURE__ */ jsx54(
2539
2554
  McpAuthPrompt2,
2540
2555
  {
2541
2556
  servers: pending.mcpServers,
2542
- disabled: isRunning,
2543
- onContinue: () => void resume()
2557
+ onConnect: handleConnect,
2558
+ onContinue: () => void resume(),
2559
+ readOnly: isRunning
2544
2560
  }
2545
2561
  );
2546
2562
  }
2547
2563
 
2548
2564
  // src/containers/ComposerContainer.tsx
2549
- import { Fragment as Fragment3, jsx as jsx49, jsxs as jsxs27 } from "react/jsx-runtime";
2550
- var threadHasPendingMcpAuth = (s) => {
2551
- const messages = s.thread.messages;
2552
- const last = messages[messages.length - 1];
2553
- if (last?.role !== "assistant") return false;
2554
- if (last.status?.type !== "requires-action") return false;
2555
- return last.metadata?.custom?.pendingMcpAuth === true;
2556
- };
2557
- function ComposerContainer() {
2565
+ import { Fragment as Fragment3, jsx as jsx55, jsxs as jsxs18 } from "react/jsx-runtime";
2566
+ function ComposerContainer({
2567
+ placeholder = "Ask anything... (Shift+Enter for new line)"
2568
+ }) {
2558
2569
  const ComposerShell2 = useSlot("ComposerShell");
2559
- const aui = useAui4();
2560
- const text = useAuiState9((s) => s.composer.text);
2570
+ const aui = useAui2();
2571
+ const text = useAuiState13((s) => s.composer.text);
2561
2572
  const { isBusy, send, resetBusy } = useComposerBusyState();
2562
- const mcpPending = useAuiState9(threadHasPendingMcpAuth);
2563
- const { pending: toolResponsesPending } = useTrueFoundryToolResponses2();
2573
+ const pauseView = useComposerPauseView();
2564
2574
  const cancel = useTrueFoundryCancel();
2565
- const fileInputRef = useRef(null);
2566
- if (mcpPending) {
2567
- return /* @__PURE__ */ jsx49(McpAuthContainer, {});
2575
+ const fileInputRef = useRef3(null);
2576
+ if (pauseView.kind === "mcp") {
2577
+ return /* @__PURE__ */ jsx55(McpAuthContainer, {});
2568
2578
  }
2569
- if (toolResponsesPending.length > 0) {
2570
- return /* @__PURE__ */ jsx49(AskUserContainer, {});
2579
+ if (pauseView.kind === "ask-user") {
2580
+ return /* @__PURE__ */ jsx55(AskUserContainer, {});
2571
2581
  }
2572
- return /* @__PURE__ */ jsxs27(Fragment3, { children: [
2573
- /* @__PURE__ */ jsx49(
2582
+ return /* @__PURE__ */ jsxs18(Fragment3, { children: [
2583
+ /* @__PURE__ */ jsx55(
2574
2584
  "input",
2575
2585
  {
2576
2586
  ref: fileInputRef,
2577
2587
  type: "file",
2588
+ multiple: true,
2578
2589
  hidden: true,
2579
2590
  onChange: (event) => {
2580
- const file = event.target.files?.[0];
2581
- if (file) void aui.composer().addAttachment(file);
2591
+ const files = event.target.files;
2592
+ if (files) {
2593
+ for (const file of files) {
2594
+ void aui.composer().addAttachment(file);
2595
+ }
2596
+ }
2582
2597
  event.target.value = "";
2583
2598
  }
2584
2599
  }
2585
2600
  ),
2586
- /* @__PURE__ */ jsx49(
2601
+ /* @__PURE__ */ jsx55(
2587
2602
  ComposerShell2,
2588
2603
  {
2589
- attachments: /* @__PURE__ */ jsx49(ComposerAttachmentsContainer, {}),
2604
+ attachments: /* @__PURE__ */ jsx55(ComposerAttachmentsContainer, {}),
2590
2605
  value: text,
2591
- placeholder: "Ask anything... (Shift+Enter for new line)",
2606
+ placeholder,
2592
2607
  disabled: isBusy,
2593
2608
  isRunning: isBusy,
2594
2609
  onValueChange: (value) => aui.composer().setText(value),
@@ -2604,27 +2619,39 @@ function ComposerContainer() {
2604
2619
  }
2605
2620
 
2606
2621
  // src/containers/ThreadListContainer.tsx
2607
- import { useAui as useAui5, useAuiState as useAuiState10 } from "@assistant-ui/react";
2608
- import { jsx as jsx50, jsxs as jsxs28 } from "react/jsx-runtime";
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";
2609
2625
  function ThreadListContainer() {
2610
2626
  const ThreadListShell2 = useSlot("ThreadListShell");
2611
2627
  const ThreadListNewButton2 = useSlot("ThreadListNewButton");
2612
2628
  const ThreadListRow2 = useSlot("ThreadListRow");
2613
2629
  const ThreadListRowSkeleton2 = useSlot("ThreadListRowSkeleton");
2614
2630
  const ThreadListEmptyState2 = useSlot("ThreadListEmptyState");
2615
- const Button2 = useSlot("Button");
2616
- const aui = useAui5();
2617
- const isLoading = useAuiState10((s) => s.threads.isLoading);
2618
- const isLoadingMore = useAuiState10((s) => s.threads.isLoadingMore);
2619
- const hasMore = useAuiState10((s) => s.threads.hasMore);
2620
- const threadIds = useAuiState10((s) => s.threads.threadIds);
2621
- const threadItems = useAuiState10((s) => s.threads.threadItems);
2622
- const mainThreadId = useAuiState10((s) => s.threads.mainThreadId);
2631
+ 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(() => {
2640
+ const node = sentinelRef.current;
2641
+ if (!node || !hasMore) return;
2642
+ const observer = new IntersectionObserver((entries) => {
2643
+ if (entries.some((e) => e.isIntersecting) && hasMore && !isLoadingMore) {
2644
+ void aui.threads().loadMore();
2645
+ }
2646
+ });
2647
+ observer.observe(node);
2648
+ return () => observer.disconnect();
2649
+ }, [aui, hasMore, isLoadingMore]);
2623
2650
  const itemsById = new Map(threadItems.map((item) => [item.id, item]));
2624
- return /* @__PURE__ */ jsxs28(ThreadListShell2, { header: /* @__PURE__ */ jsx50(ThreadListNewButton2, { onClick: () => aui.threads().switchToNewThread() }), children: [
2625
- isLoading ? /* @__PURE__ */ jsx50(ThreadListRowSkeleton2, {}) : threadIds.length === 0 ? /* @__PURE__ */ jsx50(ThreadListEmptyState2, {}) : threadIds.map((id) => {
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) => {
2626
2653
  const item = itemsById.get(id);
2627
- return /* @__PURE__ */ jsx50(
2654
+ return /* @__PURE__ */ jsx56(
2628
2655
  ThreadListRow2,
2629
2656
  {
2630
2657
  title: item?.title ?? "New Chat",
@@ -2636,18 +2663,24 @@ function ThreadListContainer() {
2636
2663
  id
2637
2664
  );
2638
2665
  }),
2639
- !isLoading && hasMore && (isLoadingMore ? /* @__PURE__ */ jsx50(ThreadListRowSkeleton2, { count: 1 }) : /* @__PURE__ */ jsx50(Button2, { variant: "ghost", onClick: () => void aui.threads().loadMore(), children: "Load more" }))
2666
+ !isLoading && hasMore && /* @__PURE__ */ jsxs19(Fragment4, { children: [
2667
+ isLoadingMore && /* @__PURE__ */ jsx56(ThreadListRowSkeleton2, { count: 1 }),
2668
+ /* @__PURE__ */ jsx56("div", { ref: sentinelRef, "aria-hidden": true })
2669
+ ] })
2640
2670
  ] });
2641
2671
  }
2642
2672
 
2643
2673
  // src/containers/Thread.tsx
2644
- import { jsx as jsx51 } from "react/jsx-runtime";
2674
+ import { jsx as jsx57 } from "react/jsx-runtime";
2645
2675
  function Thread() {
2646
- return /* @__PURE__ */ jsx51(ThreadContainer, { composer: /* @__PURE__ */ jsx51(ComposerContainer, {}) });
2676
+ return /* @__PURE__ */ jsx57(ThreadContainer, { composer: /* @__PURE__ */ jsx57(ComposerContainer, {}) });
2647
2677
  }
2648
2678
  export {
2679
+ Accordion3 as Accordion,
2680
+ AccordionDetails3 as AccordionDetails,
2681
+ AccordionSummary3 as AccordionSummary,
2649
2682
  AskUserContainer,
2650
- AskUserPrompt,
2683
+ AssistantMessageBubble,
2651
2684
  AssistantMessageContainer,
2652
2685
  AssistantTextContainer,
2653
2686
  AttachmentCard,
@@ -2656,46 +2689,41 @@ export {
2656
2689
  Avatar,
2657
2690
  AvatarFallback,
2658
2691
  AvatarImage,
2659
- BranchIndicator,
2660
- Button,
2661
- CodeBlockHeader,
2662
- Collapsible,
2663
- CollapsibleContent,
2664
- CollapsibleTrigger,
2692
+ Button3 as Button,
2665
2693
  ComposerAttachmentPickerContainer,
2666
2694
  ComposerAttachmentsContainer,
2667
2695
  ComposerBusyProvider,
2668
2696
  ComposerContainer,
2697
+ ComposerLeftSection,
2698
+ ComposerRightSection,
2699
+ ComposerSendButton,
2669
2700
  ComposerShell,
2670
- Dialog,
2671
- DialogClose,
2672
- DialogContent,
2673
- DialogDescription,
2674
- DialogFooter,
2675
- DialogHeader,
2676
- DialogOverlay,
2677
- DialogPortal,
2678
- DialogTitle,
2679
- DialogTrigger,
2701
+ DestructiveButton,
2702
+ default5 as Dialog,
2680
2703
  ErrorToasterProvider,
2681
- IconButton,
2704
+ GhostButton,
2705
+ default2 as IconButton,
2706
+ default3 as IconProvider,
2707
+ LightTooltip2 as LightTooltip,
2682
2708
  Markdown,
2683
2709
  McpAuthContainer,
2684
- McpAuthPrompt,
2685
2710
  MessageActionBar,
2686
2711
  MessageAttachmentsContainer,
2687
- MessageBubble,
2688
2712
  MessageErrorBanner,
2689
2713
  MessageGroup,
2690
2714
  MessageIndicator,
2691
2715
  MessageListSkeleton,
2692
- OpenUIBlock,
2693
- ReasoningCard,
2716
+ MessageTimestamp,
2717
+ default4 as Modal,
2718
+ PrimaryButton,
2694
2719
  ReasoningContainer,
2695
- SandboxArtifactList,
2720
+ SandboxToolCallCard,
2696
2721
  ScrollToBottomButton,
2697
- Skeleton,
2722
+ SecondaryButton,
2723
+ default6 as Skeleton,
2698
2724
  SlotsProvider,
2725
+ SubAgentCard,
2726
+ TertiaryButton,
2699
2727
  Thread,
2700
2728
  ThreadComposerAreaShell,
2701
2729
  ThreadContainer,
@@ -2711,26 +2739,31 @@ export {
2711
2739
  ToastStack,
2712
2740
  TokensProvider,
2713
2741
  ToolApprovalBar,
2742
+ ToolApprovalContainer,
2714
2743
  ToolCallCard,
2715
2744
  ToolCallContainer,
2745
+ ToolCallContentBlock,
2746
+ ToolCallContentBlockContainer,
2716
2747
  ToolGroupCard,
2717
2748
  ToolGroupContainer,
2718
- Tooltip,
2719
- TooltipContent,
2720
- TooltipProvider,
2721
- TooltipTrigger,
2722
2749
  USER_MESSAGE_ATTACHMENT_PREVIEW_REM,
2723
2750
  UserEditComposerContainer,
2724
2751
  UserMessageActionBar,
2752
+ UserMessageBubble,
2725
2753
  UserMessageContainer,
2754
+ UserMessageEdit,
2726
2755
  WelcomeScreen,
2727
- buttonVariants,
2728
2756
  defaultSlots,
2729
2757
  defaultTokens,
2758
+ registerIcons2 as registerIcons,
2759
+ registerImgIcons,
2760
+ threadHasPendingMcpAuth,
2730
2761
  useComposerBusyState,
2762
+ useComposerPauseView,
2731
2763
  useErrorToaster,
2732
2764
  useErrorToasterOptional,
2733
2765
  useSlot,
2766
+ useThemeMode,
2734
2767
  useTokens
2735
2768
  };
2736
2769
  //# sourceMappingURL=index.js.map