@truefoundry/agent-ui-sdk 0.0.1 → 0.0.2

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 +228 -281
  3. package/dist/index.js +1823 -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,1064 +137,406 @@ 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
+ return /* @__PURE__ */ jsx13(
207
+ TfyToolCallCard,
303
208
  {
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
- ]
209
+ ...props,
210
+ className: cn("aui-tool-call-card", props.className)
317
211
  }
318
212
  );
319
213
  }
320
214
 
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",
215
+ // src/atoms/ToolCallContentBlock.tsx
216
+ import {
217
+ ToolCallContentBlock as TfyToolCallContentBlock
218
+ } from "tfy-web-components/components/molecules/agent-chat";
219
+ import { jsx as jsx14 } from "react/jsx-runtime";
220
+ function ToolCallContentBlock(props) {
221
+ return /* @__PURE__ */ jsx14(TfyToolCallContentBlock, { ...props });
222
+ }
223
+
224
+ // src/atoms/SubAgentCard.tsx
225
+ import { SubAgentCard as TfySubAgentCard } from "tfy-web-components/components/molecules/agent-chat";
226
+ import { jsx as jsx15 } from "react/jsx-runtime";
227
+ function SubAgentCard({
228
+ agentName,
229
+ instruction,
230
+ stepCount,
231
+ status,
232
+ expanded,
233
+ onToggle,
234
+ durationText,
235
+ children,
236
+ className
237
+ }) {
238
+ const Markdown2 = useSlot("Markdown");
239
+ return /* @__PURE__ */ jsx15(
240
+ TfySubAgentCard,
424
241
  {
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
- })
242
+ agentName,
243
+ instruction,
244
+ stepCount,
245
+ status,
246
+ expanded,
247
+ onToggle,
248
+ durationText,
249
+ renderInstruction: (content) => /* @__PURE__ */ jsx15(Markdown2, { content }),
250
+ className: cn("aui-sub-agent-card", className),
251
+ children
448
252
  }
449
253
  );
450
254
  }
451
255
 
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
- );
256
+ // src/atoms/SandboxToolCallCard.tsx
257
+ import {
258
+ SandboxToolCall,
259
+ ToolCallCard as TfyToolCallCard2
260
+ } from "tfy-web-components/components/molecules/agent-chat";
261
+ import { jsx as jsx16 } from "react/jsx-runtime";
262
+ function SandboxToolCallCard({
263
+ name,
264
+ intent,
265
+ status,
266
+ expanded,
267
+ onToggle,
268
+ command,
269
+ exitCode,
270
+ argsJson,
271
+ resultText,
272
+ resultJson,
273
+ viewMode,
274
+ hasContent,
275
+ onViewModeChange,
276
+ durationText,
277
+ className
278
+ }) {
279
+ const awaiting = status === "running";
280
+ const sandboxContent = /* @__PURE__ */ jsx16(
281
+ SandboxToolCall,
282
+ {
283
+ command,
284
+ exitCode,
285
+ argsJson,
286
+ resultText,
287
+ resultJson,
288
+ viewMode,
289
+ hasContent,
290
+ onViewModeChange
688
291
  }
689
- };
690
- }
691
- function Markdown({ content, className, isStreaming, onDownloadArtifact }) {
692
- const components = useMemo(
693
- () => createMarkdownComponents(isStreaming, onDownloadArtifact),
694
- [isStreaming, onDownloadArtifact]
695
292
  );
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",
293
+ return /* @__PURE__ */ jsx16(
294
+ TfyToolCallCard2,
706
295
  {
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
- ]
296
+ toolName: intent || name,
297
+ icon: "cube",
298
+ iconClassName: "text-indigo-600 dark:text-gray-750 shrink-0",
299
+ expanded,
300
+ onToggle,
301
+ awaiting,
302
+ awaitingText: durationText ?? "Running\u2026",
303
+ showResponseLine: false,
304
+ requestSlot: sandboxContent,
305
+ className: cn("aui-sandbox-tool-call-card", className)
737
306
  }
738
307
  );
739
308
  }
740
309
 
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,
310
+ // src/atoms/ToolApprovalBar.tsx
311
+ import {
312
+ ToolApprovalBlock
313
+ } from "tfy-web-components/components/molecules/agent-chat";
314
+ import { jsx as jsx17 } from "react/jsx-runtime";
315
+ function ToolApprovalBar({ className, ...props }) {
316
+ return /* @__PURE__ */ jsx17(
317
+ ToolApprovalBlock,
758
318
  {
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
- ]
319
+ ...props,
320
+ className: cn("aui-tool-approval-bar", className)
776
321
  }
777
322
  );
778
323
  }
779
324
 
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",
325
+ // src/atoms/ToolGroupCard.tsx
326
+ import { ChevronDownIcon, LoaderIcon } from "lucide-react";
327
+ import { Accordion, AccordionDetails, AccordionSummary } from "tfy-web-components/components/atoms/Accordion";
328
+ import { jsx as jsx18, jsxs as jsxs4 } from "react/jsx-runtime";
329
+ function ToolGroupCard({
330
+ toolCallCount,
331
+ expanded,
332
+ active = false,
333
+ onToggle,
334
+ children,
335
+ className
336
+ }) {
337
+ const label = `${toolCallCount} tool ${toolCallCount === 1 ? "call" : "calls"}`;
338
+ return /* @__PURE__ */ jsxs4(
339
+ Accordion,
813
340
  {
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
- ),
341
+ "data-slot": "tool-group-card",
342
+ expanded,
343
+ onChange: () => onToggle(),
344
+ background: "transparent",
345
+ className: cn("aui-tool-group-card group/tool-group w-full", className),
346
+ sx: { margin: 0, border: "none", boxShadow: "none" },
819
347
  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",
348
+ /* @__PURE__ */ jsx18(
349
+ AccordionSummary,
824
350
  {
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
- ]
351
+ hideIcon: true,
352
+ disableRipple: true,
353
+ sx: {
354
+ padding: 0,
355
+ minHeight: 0,
356
+ "&.Mui-expanded": { minHeight: 0 },
357
+ "&:hover": { backgroundColor: "transparent" },
358
+ "& .MuiAccordionSummary-content": { margin: 0, width: "100%" }
359
+ },
360
+ 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: [
361
+ active && /* @__PURE__ */ jsx18(LoaderIcon, { className: "size-3 shrink-0 animate-spin [animation-duration:0.6s]" }),
362
+ /* @__PURE__ */ jsx18("span", { className: "text-xs font-medium", children: label }),
363
+ /* @__PURE__ */ jsx18(
364
+ ChevronDownIcon,
365
+ {
366
+ className: cn(
367
+ "size-3 shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)]",
368
+ expanded ? "rotate-0" : "-rotate-90"
369
+ )
370
+ }
371
+ )
372
+ ] })
831
373
  }
832
- )
374
+ ),
375
+ /* @__PURE__ */ jsx18(AccordionDetails, { sx: { padding: 0 }, children: /* @__PURE__ */ jsx18("div", { className: "mt-1 flex flex-col gap-2 text-foreground", children }) })
833
376
  ]
834
377
  }
835
378
  );
836
379
  }
837
380
 
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
381
  // src/atoms/Skeletons.tsx
893
- import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
382
+ import Skeleton from "tfy-web-components/components/atoms/Skeleton";
383
+ import { jsx as jsx19, jsxs as jsxs5 } from "react/jsx-runtime";
894
384
  function MessageListSkeleton({ className }) {
895
- return /* @__PURE__ */ jsxs11(
385
+ return /* @__PURE__ */ jsxs5(
896
386
  "div",
897
387
  {
898
388
  role: "status",
899
389
  "aria-label": "Loading conversation",
900
390
  "data-slot": "aui_thread-history-skeleton",
901
- className: cn("mb-14 flex flex-col gap-y-6", className),
902
- children: [
903
- /* @__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";
391
+ className: cn("mb-14 flex flex-col gap-y-6", className),
392
+ children: [
393
+ /* @__PURE__ */ jsx19("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-10 w-[min(85%,20rem)] rounded-xl" }) }),
394
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2 px-2", children: [
395
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-md" }),
396
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full max-w-sm" }),
397
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-2/3 max-w-xs" })
398
+ ] })
399
+ ]
400
+ }
401
+ );
402
+ }
986
403
 
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,
404
+ // src/atoms/ComposerShell.tsx
405
+ import { jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
406
+ function ComposerShell({
407
+ value,
408
+ placeholder,
996
409
  disabled,
997
- onSelectOption,
998
- onOtherValueChange,
410
+ isRunning = false,
411
+ attachments,
412
+ modelLabel,
413
+ modelIcon,
414
+ connectorStatusLabel,
415
+ onValueChange,
999
416
  onSubmit,
417
+ onCancel,
418
+ onAttach,
1000
419
  className
1001
420
  }) {
1002
- const canSubmit = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID ? true : selectedOptionId === OTHER_OPTION_ID && otherValue.trim().length > 0;
1003
- return /* @__PURE__ */ jsxs12(
421
+ const ComposerLeftSection2 = useSlot("ComposerLeftSection");
422
+ const ComposerRightSection2 = useSlot("ComposerRightSection");
423
+ const ComposerSendButton2 = useSlot("ComposerSendButton");
424
+ return /* @__PURE__ */ jsxs6(
1004
425
  "div",
1005
426
  {
1006
- "data-slot": "aui_ask-user-prompt",
427
+ "data-slot": "aui_composer-shell",
1007
428
  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)]",
429
+ "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
430
  className
1010
431
  ),
1011
432
  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)
433
+ attachments,
434
+ /* @__PURE__ */ jsx20(
435
+ "textarea",
436
+ {
437
+ value,
438
+ placeholder,
439
+ disabled,
440
+ rows: 1,
441
+ "aria-label": "Message input",
442
+ onChange: (event) => onValueChange(event.target.value),
443
+ onKeyDown: (event) => {
444
+ if (event.key === "Enter" && !event.shiftKey) {
445
+ event.preventDefault();
446
+ onSubmit();
1023
447
  }
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",
448
+ },
449
+ 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"
450
+ }
451
+ ),
452
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-1", children: [
453
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
454
+ /* @__PURE__ */ jsx20(
455
+ ComposerLeftSection2,
1030
456
  {
1031
- type: "radio",
1032
- name: "ask-user-option",
1033
- checked: selectedOptionId === OTHER_OPTION_ID,
1034
457
  disabled,
1035
- onChange: () => onSelectOption(OTHER_OPTION_ID)
458
+ isRunning,
459
+ onAttach
1036
460
  }
1037
461
  ),
1038
- /* @__PURE__ */ jsx21(
1039
- "input",
462
+ connectorStatusLabel && /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-xs", children: connectorStatusLabel })
463
+ ] }),
464
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
465
+ 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: [
466
+ modelIcon,
467
+ modelLabel
468
+ ] }),
469
+ /* @__PURE__ */ jsx20(ComposerRightSection2, { disabled, isRunning }),
470
+ /* @__PURE__ */ jsx20(
471
+ ComposerSendButton2,
1040
472
  {
1041
- type: "text",
1042
- value: otherValue,
1043
- placeholder: "Type your answer...",
1044
473
  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"
474
+ canSubmit: !disabled && value.trim().length > 0,
475
+ isRunning,
476
+ onSubmit,
477
+ onCancel
1052
478
  }
1053
479
  )
1054
480
  ] })
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
- ) })
481
+ ] })
1066
482
  ]
1067
483
  }
1068
484
  );
1069
485
  }
1070
486
 
487
+ // src/atoms/ComposerSections.tsx
488
+ import Spinner from "tfy-web-components/components/atoms/Spinner";
489
+ import { Fragment, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
490
+ function ComposerLeftSection({ onAttach }) {
491
+ const IconButton5 = useSlot("IconButton");
492
+ if (!onAttach) return null;
493
+ return /* @__PURE__ */ jsx21(IconButton5, { icon: "plus", tooltip: "Attach", onClick: onAttach });
494
+ }
495
+ function ComposerRightSection(_) {
496
+ return null;
497
+ }
498
+ function ComposerSendButton({
499
+ canSubmit,
500
+ isRunning,
501
+ onSubmit,
502
+ onCancel
503
+ }) {
504
+ const Button4 = useSlot("Button");
505
+ if (isRunning) {
506
+ return /* @__PURE__ */ jsx21(
507
+ Button4.Primary,
508
+ {
509
+ disabled: !onCancel,
510
+ onClick: onCancel,
511
+ text: /* @__PURE__ */ jsxs7(Fragment, { children: [
512
+ /* @__PURE__ */ jsx21(Spinner, { small: true }),
513
+ "Cancel"
514
+ ] })
515
+ }
516
+ );
517
+ }
518
+ return /* @__PURE__ */ jsx21(
519
+ Button4.Primary,
520
+ {
521
+ disabled: !canSubmit,
522
+ onClick: onSubmit,
523
+ icon: "arrow-up",
524
+ tooltipProps: {
525
+ title: "Send message",
526
+ size: "fit"
527
+ }
528
+ }
529
+ );
530
+ }
531
+
1071
532
  // 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";
533
+ import { FileTextIcon } from "lucide-react";
534
+
535
+ // src/constants/attachments.ts
1074
536
  var USER_MESSAGE_ATTACHMENT_PREVIEW_REM = 12;
537
+
538
+ // src/atoms/AttachmentCard.tsx
539
+ import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1075
540
  function AttachmentCard({
1076
541
  name,
1077
542
  previewSrc,
@@ -1081,6 +546,10 @@ function AttachmentCard({
1081
546
  onRemove,
1082
547
  className
1083
548
  }) {
549
+ const IconButton5 = useSlot("IconButton");
550
+ const Avatar2 = useSlot("Avatar");
551
+ const AvatarImage2 = useSlot("AvatarImage");
552
+ const AvatarFallback2 = useSlot("AvatarFallback");
1084
553
  if (size === "preview" && isImage && previewSrc) {
1085
554
  const previewSize = previewRem != null ? { width: `${previewRem}rem`, height: `${previewRem}rem` } : void 0;
1086
555
  return /* @__PURE__ */ jsx22(
@@ -1097,7 +566,7 @@ function AttachmentCard({
1097
566
  }
1098
567
  );
1099
568
  }
1100
- return /* @__PURE__ */ jsxs13(
569
+ return /* @__PURE__ */ jsxs8(
1101
570
  "div",
1102
571
  {
1103
572
  "data-slot": "aui_attachment-chip",
@@ -1107,19 +576,18 @@ function AttachmentCard({
1107
576
  className
1108
577
  ),
1109
578
  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" }) })
579
+ /* @__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: [
580
+ /* @__PURE__ */ jsx22(AvatarImage2, { src: previewSrc, alt: name, className: "object-cover" }),
581
+ /* @__PURE__ */ jsx22(AvatarFallback2, { children: /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) })
1113
582
  ] }) : /* @__PURE__ */ jsx22(FileTextIcon, { className: "text-muted-foreground size-4" }) }),
1114
583
  /* @__PURE__ */ jsx22("span", { className: "text-foreground min-w-0 truncate text-sm", children: name }),
1115
584
  onRemove && /* @__PURE__ */ jsx22(
1116
- IconButton,
585
+ IconButton5,
1117
586
  {
587
+ icon: "xmark",
1118
588
  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, {})
589
+ className: "size-6 shrink-0 rounded-full",
590
+ onClick: onRemove
1123
591
  }
1124
592
  )
1125
593
  ]
@@ -1128,20 +596,47 @@ function AttachmentCard({
1128
596
  }
1129
597
 
1130
598
  // src/atoms/AttachmentPickerButton.tsx
1131
- import { PlusIcon } from "lucide-react";
599
+ import IconButton from "tfy-web-components/components/atoms/IconButton";
1132
600
  import { jsx as jsx23 } from "react/jsx-runtime";
1133
601
  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" }) });
602
+ return /* @__PURE__ */ jsx23(
603
+ IconButton,
604
+ {
605
+ icon: "plus",
606
+ tooltip: "Add Attachment",
607
+ className: "size-7 rounded-full p-1",
608
+ ...props
609
+ }
610
+ );
1135
611
  }
1136
612
 
1137
613
  // src/atoms/AttachmentPreviewDialog.tsx
1138
- import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
614
+ import { useState } from "react";
615
+ import Modal from "tfy-web-components/components/atoms/Modal";
616
+ import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
1139
617
  function AttachmentPreviewDialog({ previewSrc, children }) {
618
+ const IconButton5 = useSlot("IconButton");
619
+ const [open, setOpen] = useState(false);
1140
620
  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" }),
621
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
622
+ /* @__PURE__ */ jsx24(
623
+ "div",
624
+ {
625
+ role: "button",
626
+ tabIndex: 0,
627
+ onClick: () => setOpen(true),
628
+ onKeyDown: (event) => {
629
+ if (event.key === "Enter" || event.key === " ") {
630
+ event.preventDefault();
631
+ setOpen(true);
632
+ }
633
+ },
634
+ className: "contents cursor-pointer",
635
+ children
636
+ }
637
+ ),
638
+ /* @__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: [
639
+ /* @__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
640
  /* @__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
641
  "img",
1147
642
  {
@@ -1150,602 +645,544 @@ function AttachmentPreviewDialog({ previewSrc, children }) {
1150
645
  className: "block h-auto max-h-[80vh] w-auto max-w-full object-contain"
1151
646
  }
1152
647
  ) })
1153
- ] })
648
+ ] }) })
1154
649
  ] });
1155
650
  }
1156
651
 
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(
652
+ // src/atoms/ScrollToBottomButton.tsx
653
+ import { forwardRef as forwardRef2 } from "react";
654
+ import IconButton2 from "tfy-web-components/components/atoms/IconButton";
655
+ import { jsx as jsx25 } from "react/jsx-runtime";
656
+ var ScrollToBottomButton = forwardRef2(
657
+ ({ className, disabled, ...rest }, ref) => {
658
+ if (disabled) return null;
659
+ return /* @__PURE__ */ jsx25(
660
+ "span",
661
+ {
662
+ ref,
663
+ className: cn("absolute -top-14 z-10 inline-flex self-center"),
664
+ children: /* @__PURE__ */ jsx25(
665
+ IconButton2,
666
+ {
667
+ icon: "arrow-down",
668
+ tooltip: "Scroll to bottom",
669
+ disabled,
670
+ className: cn(
671
+ "aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent rounded-full p-4",
672
+ className
673
+ ),
674
+ ...rest
675
+ }
676
+ )
677
+ }
678
+ );
679
+ }
680
+ );
681
+ ScrollToBottomButton.displayName = "ScrollToBottomButton";
682
+
683
+ // src/atoms/ThreadListRow.tsx
684
+ import IconProvider from "tfy-web-components/components/atoms/IconProvider";
685
+ import IconButton3 from "tfy-web-components/components/atoms/IconButton";
686
+ import DropdownMenu from "tfy-web-components/components/molecules/DropdownMenu";
687
+ import { jsx as jsx26, jsxs as jsxs10 } from "react/jsx-runtime";
688
+ function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }) {
689
+ return /* @__PURE__ */ jsxs10(
1176
690
  "div",
1177
691
  {
1178
- "data-slot": "aui_composer-shell",
692
+ "data-slot": "aui_thread-list-item",
693
+ "data-active": active || void 0,
1179
694
  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",
695
+ "group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
1181
696
  className
1182
697
  ),
1183
698
  children: [
1184
- attachments,
1185
- /* @__PURE__ */ jsx25(
1186
- "textarea",
699
+ /* @__PURE__ */ jsx26(
700
+ "button",
1187
701
  {
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"
702
+ type: "button",
703
+ onClick: onSelect,
704
+ "data-slot": "aui_thread-list-item-trigger",
705
+ 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",
706
+ children: /* @__PURE__ */ jsx26("span", { className: "min-w-0 flex-1 truncate", children: title })
1201
707
  }
1202
708
  ),
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,
709
+ (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(
710
+ DropdownMenu,
711
+ {
712
+ trigger: /* @__PURE__ */ jsx26(
713
+ IconButton3,
1228
714
  {
1229
- tooltip: "Send message",
1230
- variant: "default",
1231
- disabled: disabled || value.trim().length === 0,
1232
- onClick: onSubmit,
1233
- children: /* @__PURE__ */ jsx25(ArrowUpIcon, {})
715
+ icon: "ellipsis",
716
+ tooltip: "More options",
717
+ className: "size-6 p-0"
1234
718
  }
1235
- )
1236
- ] })
1237
- ] })
719
+ ),
720
+ side: "right",
721
+ align: "start",
722
+ children: [
723
+ onArchive && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onArchive, children: [
724
+ /* @__PURE__ */ jsx26(IconProvider, { icon: "box-archive", size: 0.75 }),
725
+ "Archive"
726
+ ] }),
727
+ onDelete && /* @__PURE__ */ jsxs10(DropdownMenu.Item, { onClick: onDelete, className: "text-destructive hover:bg-destructive/10", children: [
728
+ /* @__PURE__ */ jsx26(IconProvider, { icon: "trash", size: 0.75 }),
729
+ "Delete"
730
+ ] })
731
+ ]
732
+ }
733
+ ) })
1238
734
  ]
1239
735
  }
1240
736
  );
1241
737
  }
1242
738
 
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" }) })
739
+ // src/atoms/ThreadListMisc.tsx
740
+ import Button from "tfy-web-components/components/atoms/Button";
741
+ import Skeleton2 from "tfy-web-components/components/atoms/Skeleton";
742
+ import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
743
+ function ThreadListNewButton({ className, ...rest }) {
744
+ return /* @__PURE__ */ jsx27(
745
+ Button.Ghost,
746
+ {
747
+ "data-slot": "aui_thread-list-new",
748
+ className: cn("hover:bg-muted h-8 justify-start gap-2 rounded-md px-2.5 text-sm font-normal", className),
749
+ icon: "plus",
750
+ text: "New Thread",
751
+ ...rest
752
+ }
753
+ );
754
+ }
755
+ function ThreadListRowSkeleton({ count = 5, className }) {
756
+ 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)) });
757
+ }
758
+ function ThreadListEmptyState({ message = "No threads yet", className }) {
759
+ 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 });
760
+ }
761
+ function ThreadListShell({ header, children, className }) {
762
+ 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: [
763
+ header,
764
+ /* @__PURE__ */ jsx27("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1", children })
1278
765
  ] });
1279
766
  }
1280
767
 
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,
768
+ // src/atoms/MessageActionBar.tsx
769
+ import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
770
+ function MessageActionBar({ isCopied, onCopy, className }) {
771
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
772
+ const IconButton5 = useSlot("IconButton");
773
+ return /* @__PURE__ */ jsxs12(
774
+ "div",
1287
775
  {
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),
776
+ className: cn(
777
+ "aui-assistant-action-bar-root text-muted-foreground animate-in fade-in flex items-center gap-3 duration-200",
778
+ className
779
+ ),
1292
780
  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 })
781
+ /* @__PURE__ */ jsx28(MessageTimestamp2, {}),
782
+ /* @__PURE__ */ jsx28(
783
+ IconButton5,
784
+ {
785
+ icon: isCopied ? "check" : ["far", "clone"],
786
+ tooltip: "Copy",
787
+ onClick: onCopy
788
+ }
789
+ )
1313
790
  ]
1314
791
  }
1315
792
  );
1316
793
  }
1317
794
 
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
- ] });
795
+ // src/atoms/Markdown.tsx
796
+ import { MarkdownWithOpenUI } from "tfy-web-components/components/molecules/Markdown";
797
+ import { jsx as jsx29 } from "react/jsx-runtime";
798
+ function Markdown({
799
+ content,
800
+ isStreaming,
801
+ fileDownloadBaseUrl,
802
+ onDownloadArtifact,
803
+ readOnly,
804
+ className
805
+ }) {
806
+ const mode = useThemeMode();
807
+ return /* @__PURE__ */ jsx29(
808
+ MarkdownWithOpenUI,
809
+ {
810
+ isStreaming,
811
+ darkTheme: mode === "dark",
812
+ fileDownloadBaseUrl,
813
+ onDownloadArtifact,
814
+ readOnly,
815
+ className,
816
+ children: content
817
+ }
818
+ );
819
+ }
820
+
821
+ // src/atoms/AssistantMessageBubble.tsx
822
+ import { AssistantMessage } from "tfy-web-components/components/molecules/agent-chat";
823
+ import { jsx as jsx30 } from "react/jsx-runtime";
824
+ function AssistantMessageBubble({
825
+ children,
826
+ error,
827
+ actionBar,
828
+ className
829
+ }) {
830
+ return /* @__PURE__ */ jsx30(
831
+ "div",
832
+ {
833
+ "data-slot": "aui_assistant-message-root",
834
+ className: cn(
835
+ "group/assistant fade-in slide-in-from-bottom-1 animate-in relative duration-150",
836
+ className
837
+ ),
838
+ children: /* @__PURE__ */ jsx30(AssistantMessage, { error, actionBar, children })
839
+ }
840
+ );
841
+ }
842
+
843
+ // src/atoms/MessageErrorBanner.tsx
844
+ import { jsx as jsx31 } from "react/jsx-runtime";
845
+ function MessageErrorBanner({ message, className }) {
846
+ return /* @__PURE__ */ jsx31(
847
+ "div",
848
+ {
849
+ role: "alert",
850
+ className: cn(
851
+ "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",
852
+ className
853
+ ),
854
+ children: /* @__PURE__ */ jsx31("span", { className: "aui-message-error-message line-clamp-2", children: message })
855
+ }
856
+ );
857
+ }
858
+
859
+ // src/atoms/MessageIndicator.tsx
860
+ import { jsx as jsx32 } from "react/jsx-runtime";
861
+ function MessageIndicator({ className }) {
862
+ return /* @__PURE__ */ jsx32(
863
+ "span",
864
+ {
865
+ "data-slot": "aui_assistant-message-indicator",
866
+ className: cn("animate-pulse font-sans", className),
867
+ "aria-label": "Assistant is working",
868
+ children: "\u25CF"
869
+ }
870
+ );
871
+ }
872
+
873
+ // src/atoms/MessageTimestamp.tsx
874
+ import { useAuiState } from "@assistant-ui/react";
875
+ import { jsx as jsx33 } from "react/jsx-runtime";
876
+ function toDate(createdAt) {
877
+ if (createdAt == null) {
878
+ return null;
1354
879
  }
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,
880
+ const date = createdAt instanceof Date ? createdAt : new Date(createdAt);
881
+ return Number.isNaN(date.getTime()) ? null : date;
882
+ }
883
+ function formatTime(date) {
884
+ return new Intl.DateTimeFormat(void 0, {
885
+ hour: "2-digit",
886
+ minute: "2-digit",
887
+ second: "2-digit",
888
+ hour12: true
889
+ }).format(date);
890
+ }
891
+ function formatFullDate(date) {
892
+ return new Intl.DateTimeFormat(void 0, {
893
+ month: "short",
894
+ day: "numeric",
895
+ year: "numeric",
896
+ hour: "numeric",
897
+ minute: "2-digit",
898
+ hour12: true
899
+ }).format(date);
900
+ }
901
+ function MessageTimestamp({ className }) {
902
+ const LightTooltip3 = useSlot("LightTooltip");
903
+ const createdAt = useAuiState((s) => s.message.createdAt);
904
+ const date = toDate(createdAt);
905
+ if (date == null) {
906
+ return null;
907
+ }
908
+ return /* @__PURE__ */ jsx33(LightTooltip3, { title: formatFullDate(date), size: "fit", children: /* @__PURE__ */ jsx33(
909
+ "span",
1358
910
  {
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
- )) });
911
+ className: cn(
912
+ "text-xs font-medium cursor-pointer leading-normal shrink-0 text-muted-foreground",
913
+ className
914
+ ),
915
+ children: formatTime(date)
916
+ }
917
+ ) });
1367
918
  }
1368
919
 
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",
920
+ // src/atoms/UserMessageActionBar.tsx
921
+ import { ActionBarPrimitive, useAuiState as useAuiState2 } from "@assistant-ui/react";
922
+ import { useActionBarCopy, useActionBarEdit } from "@assistant-ui/core/react";
923
+ import { useTrueFoundryResetFromTurn } from "@truefoundry/assistant-ui-runtime";
924
+ import { jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
925
+ function parseTurnIdFromMessageId(messageId) {
926
+ return messageId.replace(/-user$/, "");
927
+ }
928
+ function UserMessageActionBar({ className }) {
929
+ const IconButton5 = useSlot("IconButton");
930
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
931
+ const messageId = useAuiState2((s) => s.message.id);
932
+ const turnId = parseTurnIdFromMessageId(messageId);
933
+ const resetFromTurn = useTrueFoundryResetFromTurn();
934
+ const { edit, disabled: editDisabled } = useActionBarEdit();
935
+ const { copy, isCopied } = useActionBarCopy({
936
+ copyToClipboard: (text) => navigator.clipboard.writeText(text)
937
+ });
938
+ return /* @__PURE__ */ jsxs13(
939
+ ActionBarPrimitive.Root,
1376
940
  {
1377
- "data-slot": "aui_thread-list-item",
1378
- "data-active": active || void 0,
941
+ hideWhenRunning: true,
1379
942
  className: cn(
1380
- "group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
943
+ "aui-user-action-bar-root text-muted-foreground animate-in fade-in flex items-center gap-2 duration-200",
1381
944
  className
1382
945
  ),
1383
946
  children: [
1384
- /* @__PURE__ */ jsx29(
1385
- "button",
947
+ /* @__PURE__ */ jsx34(
948
+ IconButton5,
1386
949
  {
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 })
950
+ icon: "rotate-right",
951
+ tooltip: "Try again",
952
+ onClick: () => void resetFromTurn(turnId)
1392
953
  }
1393
954
  ),
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
- ] })
955
+ /* @__PURE__ */ jsx34(
956
+ IconButton5,
957
+ {
958
+ icon: "pencil",
959
+ tooltip: "Edit",
960
+ disabled: editDisabled,
961
+ onClick: edit
962
+ }
963
+ ),
964
+ /* @__PURE__ */ jsx34(
965
+ IconButton5,
966
+ {
967
+ icon: isCopied ? "check" : ["far", "clone"],
968
+ tooltip: "Copy",
969
+ onClick: copy
970
+ }
971
+ ),
972
+ /* @__PURE__ */ jsx34(MessageTimestamp2, {})
1437
973
  ]
1438
974
  }
1439
975
  );
1440
976
  }
1441
977
 
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,
978
+ // src/atoms/ThreadShell.tsx
979
+ import { forwardRef as forwardRef3 } from "react";
980
+ import { jsx as jsx35 } from "react/jsx-runtime";
981
+ var THREAD_CSS_VARS = {
982
+ ["--thread-max-width"]: "44rem",
983
+ ["--composer-bg"]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
984
+ ["--composer-radius"]: "1.5rem",
985
+ ["--composer-padding"]: "8px"
986
+ };
987
+ var ThreadRootShell = forwardRef3(
988
+ ({ className, style, ...rest }, ref) => /* @__PURE__ */ jsx35(
989
+ "div",
1448
990
  {
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),
991
+ ref,
992
+ className: cn(
993
+ "font-sans-flex aui-root aui-thread-root bg-background @container flex h-full min-h-0 flex-col overflow-hidden",
994
+ className
995
+ ),
996
+ style: { ...THREAD_CSS_VARS, ...style },
997
+ ...rest
998
+ }
999
+ )
1000
+ );
1001
+ ThreadRootShell.displayName = "ThreadRootShell";
1002
+ var ThreadViewportShell = forwardRef3(
1003
+ ({ className, isEmpty, children, ...rest }, ref) => /* @__PURE__ */ jsx35(
1004
+ "div",
1005
+ {
1006
+ ref,
1007
+ "data-slot": "aui_thread-viewport",
1008
+ className: cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className),
1452
1009
  ...rest,
1453
- children: [
1454
- /* @__PURE__ */ jsx30(PlusIcon3, { className: "size-4 shrink-0" }),
1455
- /* @__PURE__ */ jsx30("span", { className: "whitespace-nowrap", children: "New Thread" })
1456
- ]
1010
+ children: /* @__PURE__ */ jsx35(
1011
+ "div",
1012
+ {
1013
+ className: cn(
1014
+ "mx-auto flex w-full max-w-(--thread-max-width) flex-col px-4 pt-4 pb-4",
1015
+ isEmpty && "min-h-full justify-center"
1016
+ ),
1017
+ children
1018
+ }
1019
+ )
1457
1020
  }
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
- ] });
1021
+ )
1022
+ );
1023
+ ThreadViewportShell.displayName = "ThreadViewportShell";
1024
+ var ThreadComposerAreaShell = forwardRef3(
1025
+ ({ className, isEmpty, ...rest }, ref) => /* @__PURE__ */ jsx35(
1026
+ "div",
1027
+ {
1028
+ ref,
1029
+ "data-slot": "aui_thread-composer",
1030
+ className: cn(
1031
+ "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",
1032
+ !isEmpty && "rounded-t-(--composer-radius)",
1033
+ className
1034
+ ),
1035
+ ...rest
1036
+ }
1037
+ )
1038
+ );
1039
+ ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
1040
+ var MessageGroup = forwardRef3(({ className, ...rest }, ref) => /* @__PURE__ */ jsx35(
1041
+ "div",
1042
+ {
1043
+ ref,
1044
+ "data-slot": "aui_message-group",
1045
+ className: cn("flex flex-col gap-y-6 empty:hidden", className),
1046
+ ...rest
1047
+ }
1048
+ ));
1049
+ MessageGroup.displayName = "MessageGroup";
1050
+
1051
+ // src/atoms/WelcomeScreen.tsx
1052
+ import { jsx as jsx36 } from "react/jsx-runtime";
1053
+ function WelcomeScreen({ heading = "How can I help you today?", className }) {
1054
+ 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 }) });
1471
1055
  }
1472
1056
 
1473
1057
  // 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";
1058
+ import { XIcon } from "lucide-react";
1059
+ import { Fragment as Fragment3, jsx as jsx37, jsxs as jsxs14 } from "react/jsx-runtime";
1477
1060
  function Toast({ title, description, open, onOpenChange, className }) {
1478
- return /* @__PURE__ */ jsxs21(
1479
- ToastPrimitive.Root,
1061
+ if (!open) return null;
1062
+ return /* @__PURE__ */ jsxs14(
1063
+ "div",
1480
1064
  {
1481
- open,
1482
- onOpenChange,
1483
1065
  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",
1066
+ "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",
1067
+ "animate-in fade-in-0 slide-in-from-bottom-4",
1487
1068
  className
1488
1069
  ),
1489
1070
  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 })
1071
+ /* @__PURE__ */ jsxs14("div", { className: "grid min-h-0 min-w-0 flex-1 gap-1 overflow-y-auto pe-6", children: [
1072
+ /* @__PURE__ */ jsx37("div", { className: "text-sm leading-none font-semibold", children: title }),
1073
+ /* @__PURE__ */ jsx37("div", { className: "font-mono text-sm break-words whitespace-pre-wrap", children: description })
1493
1074
  ] }),
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
- ] })
1075
+ /* @__PURE__ */ jsxs14(
1076
+ "button",
1077
+ {
1078
+ onClick: () => onOpenChange(false),
1079
+ 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",
1080
+ children: [
1081
+ /* @__PURE__ */ jsx37(XIcon, { className: "size-4" }),
1082
+ /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "Close" })
1083
+ ]
1084
+ }
1085
+ )
1498
1086
  ]
1499
1087
  }
1500
1088
  );
1501
1089
  }
1502
1090
  function ToastStack({ children, duration = Number.POSITIVE_INFINITY }) {
1503
- return /* @__PURE__ */ jsxs21(ToastPrimitive.Provider, { duration, children: [
1091
+ return /* @__PURE__ */ jsxs14(Fragment3, { children: [
1504
1092
  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" })
1093
+ /* @__PURE__ */ jsx37("div", { 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
1094
  ] });
1507
1095
  }
1508
1096
 
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
- );
1535
- }
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
- );
1623
- }
1624
-
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,
1639
- {
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),
1644
- 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
- )
1657
- ] }),
1658
- /* @__PURE__ */ jsx33(CollapsibleContent, { className: "mt-1 flex flex-col gap-1", children })
1659
- ]
1660
- }
1661
- );
1662
- }
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 }) });
1668
- }
1669
-
1670
1097
  // src/theme/defaultSlots.ts
1671
1098
  var defaultSlots = {
1672
- Button,
1673
- IconButton,
1099
+ // tfy-web-components — direct slot defaults
1100
+ Button: Button2,
1101
+ IconButton: IconButton4,
1102
+ LightTooltip,
1103
+ Modal: Modal2,
1104
+ Dialog,
1105
+ Accordion: Accordion2,
1106
+ AccordionSummary: AccordionSummary2,
1107
+ AccordionDetails: AccordionDetails2,
1108
+ Skeleton: Skeleton3,
1109
+ ReasoningCard,
1110
+ AskUserPrompt,
1111
+ McpAuthPrompt,
1112
+ // SDK atoms — wrap or compose tfy-web-components internally
1674
1113
  Avatar,
1675
1114
  AvatarImage,
1676
1115
  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,
1116
+ UserMessageBubble,
1117
+ UserMessageEdit,
1712
1118
  ToolCallCard,
1119
+ ToolCallContentBlock,
1120
+ SubAgentCard,
1121
+ SandboxToolCallCard,
1713
1122
  ToolApprovalBar,
1714
1123
  ToolGroupCard,
1715
- ReasoningCard,
1124
+ MessageListSkeleton,
1716
1125
  ComposerShell,
1717
- AskUserPrompt,
1718
- McpAuthPrompt,
1126
+ ComposerLeftSection,
1127
+ ComposerRightSection,
1128
+ ComposerSendButton,
1719
1129
  AttachmentCard,
1720
1130
  AttachmentPreviewDialog,
1721
1131
  AttachmentPickerButton,
1132
+ ScrollToBottomButton,
1722
1133
  ThreadListRow,
1723
1134
  ThreadListNewButton,
1724
1135
  ThreadListRowSkeleton,
1725
1136
  ThreadListEmptyState,
1726
1137
  ThreadListShell,
1138
+ MessageActionBar,
1139
+ Markdown,
1140
+ // SDK atoms — SDK-owned (no tfy slot component)
1141
+ AssistantMessageBubble,
1142
+ MessageErrorBanner,
1143
+ MessageTimestamp,
1144
+ UserMessageActionBar,
1145
+ MessageIndicator,
1146
+ WelcomeScreen,
1147
+ ThreadRootShell,
1148
+ ThreadViewportShell,
1149
+ ThreadComposerAreaShell,
1150
+ MessageGroup,
1727
1151
  Toast,
1728
1152
  ToastStack
1729
1153
  };
1730
1154
 
1731
1155
  // src/theme/SlotsProvider.tsx
1732
- import { jsx as jsx35 } from "react/jsx-runtime";
1156
+ import { jsx as jsx38 } from "react/jsx-runtime";
1733
1157
  var SlotsContext = createContext(defaultSlots);
1158
+ var ThemeModeContext = createContext(void 0);
1734
1159
  function SlotsProvider({
1735
1160
  overrides,
1161
+ theme,
1736
1162
  children
1737
1163
  }) {
1738
1164
  const parentSlots = useContext(SlotsContext);
1739
- const resolved = useMemo2(
1165
+ const inheritedTheme = useContext(ThemeModeContext);
1166
+ const resolved = useMemo(
1740
1167
  () => ({ ...parentSlots, ...overrides }),
1741
1168
  [parentSlots, overrides]
1742
1169
  );
1743
- return /* @__PURE__ */ jsx35(SlotsContext.Provider, { value: resolved, children });
1170
+ return /* @__PURE__ */ jsx38(TfyThemeProvider, { theme: theme ?? inheritedTheme, children: /* @__PURE__ */ jsx38(SlotsProviderContents, { slots: resolved, children }) });
1171
+ }
1172
+ function SlotsProviderContents({
1173
+ slots,
1174
+ children
1175
+ }) {
1176
+ const { mode } = useTfyTheme();
1177
+ return /* @__PURE__ */ jsx38(ThemeModeContext.Provider, { value: mode, children: /* @__PURE__ */ jsx38(SlotsContext.Provider, { value: slots, children }) });
1744
1178
  }
1745
1179
  function useSlot(name) {
1746
1180
  const slots = useContext(SlotsContext);
1747
1181
  return slots[name];
1748
1182
  }
1183
+ function useThemeMode() {
1184
+ return useContext(ThemeModeContext) ?? "light";
1185
+ }
1749
1186
 
1750
1187
  // src/theme/tokens.ts
1751
1188
  import { createContext as createContext2, createElement, useContext as useContext2 } from "react";
@@ -1798,16 +1235,43 @@ function useTokens() {
1798
1235
  return useContext2(TokensContext);
1799
1236
  }
1800
1237
 
1238
+ // src/index.ts
1239
+ import {
1240
+ Button as Button3,
1241
+ DestructiveButton,
1242
+ GhostButton,
1243
+ PrimaryButton,
1244
+ SecondaryButton,
1245
+ TertiaryButton
1246
+ } from "tfy-web-components/components/atoms/Button";
1247
+ import { default as default2 } from "tfy-web-components/components/atoms/IconButton";
1248
+ import {
1249
+ default as default3,
1250
+ registerIcons as registerIcons2,
1251
+ registerImgIcons
1252
+ } from "tfy-web-components/components/atoms/IconProvider";
1253
+ import { LightTooltip as LightTooltip2 } from "tfy-web-components/components/atoms/Tooltip";
1254
+ import { default as default4 } from "tfy-web-components/components/atoms/Modal";
1255
+ import { default as default5 } from "tfy-web-components/components/molecules/Dialog";
1256
+ import {
1257
+ Accordion as Accordion3,
1258
+ AccordionSummary as AccordionSummary3,
1259
+ AccordionDetails as AccordionDetails3
1260
+ } from "tfy-web-components/components/atoms/Accordion";
1261
+ import { default as default6 } from "tfy-web-components/components/atoms/Skeleton";
1262
+
1801
1263
  // src/containers/ThreadContainer.tsx
1802
- import { ThreadPrimitive, useAuiState as useAuiState8 } from "@assistant-ui/react";
1264
+ import { useEffect as useEffect4 } from "react";
1265
+ import { preloadMarkdownOpenUI } from "tfy-web-components/components/molecules/Markdown";
1266
+ import { ThreadPrimitive, useAuiState as useAuiState11 } from "@assistant-ui/react";
1803
1267
 
1804
1268
  // src/hooks/useComposerBusyState.ts
1805
1269
  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";
1270
+ import { createContext as createContext3, createElement as createElement2, useCallback, useContext as useContext3, useEffect, useState as useState2 } from "react";
1807
1271
  var ComposerBusyContext = createContext3(null);
1808
1272
  function useComposerBusyStateValue() {
1809
1273
  const isRunning = useThreadIsRunning();
1810
- const [isSubmitting, setIsSubmitting] = useState4(false);
1274
+ const [isSubmitting, setIsSubmitting] = useState2(false);
1811
1275
  useEffect(() => {
1812
1276
  if (!isRunning) {
1813
1277
  setIsSubmitting(false);
@@ -1845,23 +1309,18 @@ function useComposerBusyState() {
1845
1309
  }
1846
1310
 
1847
1311
  // 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";
1312
+ import { groupPartByType, MessagePrimitive as MessagePrimitive2 } from "@assistant-ui/react";
1313
+ import { useActionBarCopy as useActionBarCopy2, useMessageError, useThreadIsRunning as useThreadIsRunning2 } from "@assistant-ui/core/react";
1855
1314
 
1856
1315
  // src/containers/AssistantTextContainer.tsx
1857
1316
  import { useCallback as useCallback3 } from "react";
1858
- import { useAuiState as useAuiState2 } from "@assistant-ui/react";
1317
+ import { useAuiState as useAuiState3 } from "@assistant-ui/react";
1859
1318
  import { useTrueFoundryDownloadSandboxFile } from "@truefoundry/assistant-ui-runtime";
1860
1319
 
1861
1320
  // src/containers/ErrorToasterContainer.tsx
1862
- import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo3, useState as useState5 } from "react";
1321
+ import { createContext as createContext4, useCallback as useCallback2, useContext as useContext4, useMemo as useMemo2, useState as useState3 } from "react";
1863
1322
  import { TrueFoundryGatewayError } from "truefoundry-gateway-sdk";
1864
- import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
1323
+ import { jsx as jsx39, jsxs as jsxs15 } from "react/jsx-runtime";
1865
1324
  var ErrorToasterContext = createContext4(null);
1866
1325
  function formatErrorBody(body) {
1867
1326
  if (body == null) return void 0;
@@ -1887,16 +1346,16 @@ function normalizeError(error) {
1887
1346
  function ErrorToasterProvider({ children }) {
1888
1347
  const ToastStack2 = useSlot("ToastStack");
1889
1348
  const Toast2 = useSlot("Toast");
1890
- const [toast, setToast] = useState5(null);
1891
- const [open, setOpen] = useState5(false);
1349
+ const [toast, setToast] = useState3(null);
1350
+ const [open, setOpen] = useState3(false);
1892
1351
  const showError = useCallback2((error) => {
1893
1352
  setToast(normalizeError(error));
1894
1353
  setOpen(true);
1895
1354
  }, []);
1896
- const value = useMemo3(() => ({ showError }), [showError]);
1897
- return /* @__PURE__ */ jsx36(ErrorToasterContext.Provider, { value, children: /* @__PURE__ */ jsxs24(ToastStack2, { children: [
1355
+ const value = useMemo2(() => ({ showError }), [showError]);
1356
+ return /* @__PURE__ */ jsx39(ErrorToasterContext.Provider, { value, children: /* @__PURE__ */ jsxs15(ToastStack2, { children: [
1898
1357
  children,
1899
- toast != null && /* @__PURE__ */ jsx36(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen })
1358
+ toast != null && /* @__PURE__ */ jsx39(Toast2, { title: toast.title, description: toast.description, open, onOpenChange: setOpen })
1900
1359
  ] }) });
1901
1360
  }
1902
1361
  function useErrorToaster() {
@@ -1911,7 +1370,7 @@ function useErrorToasterOptional() {
1911
1370
  }
1912
1371
 
1913
1372
  // src/containers/AssistantTextContainer.tsx
1914
- import { jsx as jsx37 } from "react/jsx-runtime";
1373
+ import { jsx as jsx40 } from "react/jsx-runtime";
1915
1374
  function filenameFromPath(path) {
1916
1375
  return path.split("/").pop() || "download";
1917
1376
  }
@@ -1928,10 +1387,10 @@ function AssistantTextContainer() {
1928
1387
  const Markdown2 = useSlot("Markdown");
1929
1388
  const downloadSandboxFile = useTrueFoundryDownloadSandboxFile();
1930
1389
  const errorToaster = useErrorToasterOptional();
1931
- const text = useAuiState2(
1390
+ const text = useAuiState3(
1932
1391
  (s) => s.part.type === "text" || s.part.type === "reasoning" ? s.part.text : ""
1933
1392
  );
1934
- const isStreaming = useAuiState2((s) => {
1393
+ const isStreaming = useAuiState3((s) => {
1935
1394
  if (s.message.status?.type !== "running") return false;
1936
1395
  const lastIndex = s.message.parts.length - 1;
1937
1396
  if (lastIndex < 0) return false;
@@ -1948,23 +1407,24 @@ function AssistantTextContainer() {
1948
1407
  }),
1949
1408
  [downloadSandboxFile, errorToaster]
1950
1409
  );
1951
- return /* @__PURE__ */ jsx37(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1410
+ return /* @__PURE__ */ jsx40(Markdown2, { content: text, isStreaming, onDownloadArtifact: handleDownloadArtifact });
1952
1411
  }
1953
1412
 
1954
1413
  // src/containers/MessageImageContainer.tsx
1955
- import { useAuiState as useAuiState3 } from "@assistant-ui/react";
1956
- import { jsx as jsx38 } from "react/jsx-runtime";
1414
+ import { useAuiState as useAuiState4 } from "@assistant-ui/react";
1415
+ import { jsx as jsx41 } from "react/jsx-runtime";
1957
1416
  function MessageImageContainer() {
1417
+ const AttachmentCard2 = useSlot("AttachmentCard");
1958
1418
  const AttachmentPreviewDialog2 = useSlot("AttachmentPreviewDialog");
1959
- const image = useAuiState3((s) => s.part.type === "image" ? s.part.image : "");
1960
- const filename = useAuiState3(
1419
+ const image = useAuiState4((s) => s.part.type === "image" ? s.part.image : "");
1420
+ const filename = useAuiState4(
1961
1421
  (s) => s.part.type === "image" ? s.part.filename : void 0
1962
1422
  );
1963
1423
  if (!image) {
1964
1424
  return null;
1965
1425
  }
1966
- const card = /* @__PURE__ */ jsx38(
1967
- AttachmentCard,
1426
+ const card = /* @__PURE__ */ jsx41(
1427
+ AttachmentCard2,
1968
1428
  {
1969
1429
  name: filename ?? "image",
1970
1430
  previewSrc: image,
@@ -1973,34 +1433,73 @@ function MessageImageContainer() {
1973
1433
  previewRem: USER_MESSAGE_ATTACHMENT_PREVIEW_REM
1974
1434
  }
1975
1435
  );
1976
- return /* @__PURE__ */ jsx38(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx38("div", { className: "aui-message-image", children: card }) });
1436
+ return /* @__PURE__ */ jsx41(AttachmentPreviewDialog2, { previewSrc: image, children: /* @__PURE__ */ jsx41("div", { className: "aui-message-image", children: card }) });
1977
1437
  }
1978
1438
 
1979
1439
  // 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 }) {
1440
+ import { useCallback as useCallback4, useRef, useState as useState4 } from "react";
1441
+ import { useAuiState as useAuiState5 } from "@assistant-ui/react";
1442
+ import { jsx as jsx42 } from "react/jsx-runtime";
1443
+ function ReasoningContainer({ group }) {
1984
1444
  const ReasoningCard2 = useSlot("ReasoningCard");
1985
- const streaming = useAuiState4((s) => {
1445
+ const content = useAuiState5(
1446
+ (s) => group.indices.map((i) => s.message.parts[i]).filter((p) => p != null && p.type === "reasoning").map((p) => p.text ?? "").join("")
1447
+ );
1448
+ const streaming = useAuiState5((s) => {
1986
1449
  if (s.message.status?.type !== "running") return false;
1987
1450
  const lastIndex = s.message.parts.length - 1;
1988
1451
  if (lastIndex < 0) return false;
1989
1452
  if (s.message.parts[lastIndex]?.type !== "reasoning") return false;
1990
- return lastIndex >= group.indices[0] && lastIndex <= group.indices[group.indices.length - 1];
1453
+ const lastGroupIndex = group.indices[group.indices.length - 1];
1454
+ return lastGroupIndex !== void 0 && lastIndex >= group.indices[0] && lastIndex <= lastGroupIndex;
1991
1455
  });
1992
- const [expanded, setExpanded] = useState6(streaming);
1993
- const [prevStreaming, setPrevStreaming] = useState6(streaming);
1456
+ const [expanded, setExpanded] = useState4(streaming);
1457
+ const [prevStreaming, setPrevStreaming] = useState4(streaming);
1458
+ const [isMultiLine, setIsMultiLine] = useState4(false);
1459
+ const observerRef = useRef(null);
1994
1460
  if (streaming !== prevStreaming) {
1995
1461
  setPrevStreaming(streaming);
1996
1462
  if (streaming) setExpanded(true);
1997
1463
  }
1998
- return /* @__PURE__ */ jsx39(ReasoningCard2, { streaming, expanded, onToggle: () => setExpanded((prev) => !prev), children });
1464
+ const contentRef = useCallback4(
1465
+ (node) => {
1466
+ observerRef.current?.disconnect();
1467
+ observerRef.current = null;
1468
+ if (node == null || streaming) return;
1469
+ const check = () => {
1470
+ const lineHeight = Number.parseFloat(getComputedStyle(node).lineHeight) || 24;
1471
+ setIsMultiLine(node.scrollHeight > lineHeight * 1.5);
1472
+ };
1473
+ check();
1474
+ observerRef.current = new ResizeObserver(check);
1475
+ observerRef.current.observe(node);
1476
+ },
1477
+ [streaming]
1478
+ );
1479
+ const reasoningTimeText = null;
1480
+ const previewText = content.replace(/\s+/g, " ").trim();
1481
+ const isShortText = !streaming && content.length > 0 && !isMultiLine;
1482
+ const headingText = streaming && !content ? expanded ? "Reasoning" : "Show Reasoning" : reasoningTimeText ?? (expanded ? "Hide Reasoning" : "Show Reasoning");
1483
+ return /* @__PURE__ */ jsx42(
1484
+ ReasoningCard2,
1485
+ {
1486
+ content,
1487
+ isStreaming: streaming,
1488
+ expanded,
1489
+ isMultiLine,
1490
+ reasoningTimeText,
1491
+ previewText,
1492
+ headingText,
1493
+ contentRef: isShortText ? contentRef : void 0,
1494
+ onToggle: () => setExpanded((prev) => !prev)
1495
+ }
1496
+ );
1999
1497
  }
2000
1498
 
2001
1499
  // src/containers/ToolCallContainer.tsx
2002
- import { useState as useState7 } from "react";
1500
+ import { useState as useState8 } from "react";
2003
1501
  import {
1502
+ MessagePartPrimitive,
2004
1503
  MessagePrimitive,
2005
1504
  useToolCallElapsed
2006
1505
  } from "@assistant-ui/react";
@@ -2015,9 +1514,192 @@ function useNestedApprovalBridge() {
2015
1514
  return useContext5(NestedApprovalBridgeContext);
2016
1515
  }
2017
1516
 
1517
+ // src/containers/SandboxToolCallContainer.tsx
1518
+ import { useMemo as useMemo3, useState as useState5 } from "react";
1519
+ import { jsx as jsx43 } from "react/jsx-runtime";
1520
+ function SandboxToolCallContainer(props) {
1521
+ const SandboxToolCallCard2 = useSlot("SandboxToolCallCard");
1522
+ const [viewMode, setViewMode] = useState5("terminal");
1523
+ const hasContent = useMemo3(() => {
1524
+ if (viewMode === "code") return Boolean(props.argsJson || props.resultJson);
1525
+ return Boolean(props.command || props.resultText || props.resultJson);
1526
+ }, [
1527
+ props.argsJson,
1528
+ props.command,
1529
+ props.resultJson,
1530
+ props.resultText,
1531
+ viewMode
1532
+ ]);
1533
+ return /* @__PURE__ */ jsx43(
1534
+ SandboxToolCallCard2,
1535
+ {
1536
+ ...props,
1537
+ viewMode,
1538
+ hasContent,
1539
+ onViewModeChange: setViewMode
1540
+ }
1541
+ );
1542
+ }
1543
+
1544
+ // src/containers/ToolApprovalContainer.tsx
1545
+ import { useCallback as useCallback5, useMemo as useMemo4, useState as useState6 } from "react";
1546
+ import { jsx as jsx44 } from "react/jsx-runtime";
1547
+ function ToolApprovalContainer({
1548
+ toolName = "",
1549
+ options,
1550
+ onSelectOption
1551
+ }) {
1552
+ const ToolApprovalBar2 = useSlot("ToolApprovalBar");
1553
+ const [selectedDenyOptionId, setSelectedDenyOptionId] = useState6(null);
1554
+ const [denialReason, setDenialReason] = useState6("");
1555
+ const [showReasonError, setShowReasonError] = useState6(false);
1556
+ const approveOptions = useMemo4(
1557
+ () => options.filter((option) => option.isAllow).map((option, index) => ({
1558
+ ...option,
1559
+ variant: index === 0 ? "primary" : "secondary",
1560
+ requiresReason: false
1561
+ })),
1562
+ [options]
1563
+ );
1564
+ const denyOptions = useMemo4(
1565
+ () => options.filter((option) => !option.isAllow).map((option) => ({
1566
+ ...option,
1567
+ variant: "secondary",
1568
+ requiresReason: option.confirm != null
1569
+ })),
1570
+ [options]
1571
+ );
1572
+ const selectedDenyOption = denyOptions.find(
1573
+ (option) => option.id === selectedDenyOptionId
1574
+ );
1575
+ const onDenyOptionChange = useCallback5((optionId) => {
1576
+ setSelectedDenyOptionId(optionId);
1577
+ setDenialReason("");
1578
+ setShowReasonError(false);
1579
+ }, []);
1580
+ const onDenialReasonChange = useCallback5((reason) => {
1581
+ setDenialReason(reason);
1582
+ setShowReasonError(false);
1583
+ }, []);
1584
+ const onReasonSubmit = useCallback5(() => {
1585
+ const reason = denialReason.trim();
1586
+ if (!reason) {
1587
+ setShowReasonError(true);
1588
+ return;
1589
+ }
1590
+ if (selectedDenyOptionId) {
1591
+ onSelectOption(selectedDenyOptionId, reason);
1592
+ onDenyOptionChange(null);
1593
+ }
1594
+ }, [denialReason, onDenyOptionChange, onSelectOption, selectedDenyOptionId]);
1595
+ return /* @__PURE__ */ jsx44(
1596
+ ToolApprovalBar2,
1597
+ {
1598
+ toolName,
1599
+ approveOptions: approveOptions.length > 0 ? approveOptions : void 0,
1600
+ denyOptions: denyOptions.length > 0 ? denyOptions : void 0,
1601
+ selectedDenyOption,
1602
+ denialReason,
1603
+ showReasonError,
1604
+ onSelect: onSelectOption,
1605
+ onDenyOptionChange,
1606
+ onDenialReasonChange,
1607
+ onReasonSubmit
1608
+ }
1609
+ );
1610
+ }
1611
+
1612
+ // src/containers/ToolCallContentBlockContainer.tsx
1613
+ import { useCallback as useCallback6, useEffect as useEffect2, useRef as useRef2, useState as useState7 } from "react";
1614
+ import { jsx as jsx45 } from "react/jsx-runtime";
1615
+ function ToolCallContentBlockContainer(props) {
1616
+ const ToolCallContentBlock2 = useSlot("ToolCallContentBlock");
1617
+ const [fullscreen, setFullscreen] = useState7(false);
1618
+ const [contentHeightRem, setContentHeightRem] = useState7(1.5);
1619
+ const observerRef = useRef2(null);
1620
+ const contentRef = useCallback6(
1621
+ (node) => {
1622
+ observerRef.current?.disconnect();
1623
+ observerRef.current = null;
1624
+ if (!props.resizable || node == null) return;
1625
+ const updateHeight = () => setContentHeightRem(node.scrollHeight / 16);
1626
+ updateHeight();
1627
+ observerRef.current = new ResizeObserver(updateHeight);
1628
+ observerRef.current.observe(node);
1629
+ },
1630
+ [props.resizable]
1631
+ );
1632
+ useEffect2(
1633
+ () => () => {
1634
+ observerRef.current?.disconnect();
1635
+ },
1636
+ []
1637
+ );
1638
+ return /* @__PURE__ */ jsx45(
1639
+ ToolCallContentBlock2,
1640
+ {
1641
+ ...props,
1642
+ fullscreen,
1643
+ onFullscreenChange: setFullscreen,
1644
+ contentHeightRem,
1645
+ contentRef
1646
+ }
1647
+ );
1648
+ }
1649
+
2018
1650
  // src/containers/ToolCallContainer.tsx
2019
- import { jsx as jsx40 } from "react/jsx-runtime";
1651
+ import { jsx as jsx46 } from "react/jsx-runtime";
2020
1652
  var SUB_AGENT_TOOL_NAME = "create_sub_agent";
1653
+ var ASK_USER_TOOL_NAME = "ask_user_question";
1654
+ function NestedSubAgentAssistantMessage() {
1655
+ const AssistantMessageBubble2 = useSlot("AssistantMessageBubble");
1656
+ 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(
1657
+ MessagePrimitive.Parts,
1658
+ {
1659
+ components: {
1660
+ Text: AssistantTextContainer,
1661
+ Reasoning: AssistantTextContainer,
1662
+ tools: { Fallback: ToolCallContainer }
1663
+ }
1664
+ }
1665
+ ) }) }) });
1666
+ }
1667
+ function parseAskUserQuestionArgs(argsText) {
1668
+ if (!argsText) return {};
1669
+ try {
1670
+ const parsed = JSON.parse(argsText);
1671
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
1672
+ return {};
1673
+ }
1674
+ const record = parsed;
1675
+ const question = typeof record.question === "string" ? record.question : void 0;
1676
+ const options = Array.isArray(record.options) ? record.options.filter(
1677
+ (item) => typeof item === "string"
1678
+ ) : void 0;
1679
+ return { question, options };
1680
+ } catch {
1681
+ return {};
1682
+ }
1683
+ }
1684
+ function getAskUserAnswerResult(result) {
1685
+ if (result === void 0 || result === null) return void 0;
1686
+ if (typeof result === "string") {
1687
+ const trimmed = result.trim();
1688
+ return trimmed.length > 0 ? trimmed : void 0;
1689
+ }
1690
+ if (typeof result === "object" && "content" in result) {
1691
+ const content = result.content;
1692
+ if (typeof content === "string" && content.trim()) {
1693
+ return content.trim();
1694
+ }
1695
+ }
1696
+ return void 0;
1697
+ }
1698
+ function hasPendingAskUserResponse(part) {
1699
+ return part.interrupt != null && part.result === void 0;
1700
+ }
1701
+ var SANDBOX_TOOL_NAMES = /* @__PURE__ */ new Set(["exec", "sandbox_exec"]);
1702
+ var MCP_META_TOOLS = /* @__PURE__ */ new Set(["call_tool", "list_tools", "get_tool_info"]);
2021
1703
  var APPROVAL_OPTION_DEFAULT_LABELS = {
2022
1704
  "allow-once": "Allow",
2023
1705
  "allow-always": "Always allow",
@@ -2029,7 +1711,9 @@ function hasPendingToolApproval(approval) {
2029
1711
  return approval != null && approval.approved === void 0 && approval.resolution === void 0;
2030
1712
  }
2031
1713
  function buildApprovalOptions(options) {
2032
- const declared = options?.filter((o) => Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, o.kind));
1714
+ const declared = options?.filter(
1715
+ (o) => Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, o.kind)
1716
+ );
2033
1717
  if (declared && declared.length > 0) {
2034
1718
  const allow = declared.filter((o) => isAllowKind(o.kind));
2035
1719
  const reject = declared.filter((o) => !isAllowKind(o.kind));
@@ -2041,13 +1725,13 @@ function buildApprovalOptions(options) {
2041
1725
  confirm: o.confirm != null ? typeof o.confirm === "object" ? o.confirm : {} : void 0
2042
1726
  }));
2043
1727
  if (reject.length === 0) {
2044
- mapped.push({ id: "__deny", label: "Deny", isAllow: false });
1728
+ mapped.push({ id: "__deny", label: "Deny", isAllow: false, confirm: {} });
2045
1729
  }
2046
1730
  return mapped;
2047
1731
  }
2048
1732
  return [
2049
1733
  { id: "__allow", label: "Allow", isAllow: true },
2050
- { id: "__deny", label: "Deny", isAllow: false }
1734
+ { id: "__deny", label: "Deny", isAllow: false, confirm: {} }
2051
1735
  ];
2052
1736
  }
2053
1737
  function formatDuration(ms) {
@@ -2062,8 +1746,80 @@ function toStatus(statusType) {
2062
1746
  if (statusType === "incomplete") return "error";
2063
1747
  return "running";
2064
1748
  }
1749
+ function parseSandboxArgs(argsText) {
1750
+ if (!argsText) return {};
1751
+ try {
1752
+ const parsed = JSON.parse(argsText);
1753
+ return {
1754
+ command: parsed.command,
1755
+ intent: parsed.intent,
1756
+ argsJson: JSON.stringify(parsed, null, 2)
1757
+ };
1758
+ } catch {
1759
+ return { argsJson: argsText };
1760
+ }
1761
+ }
1762
+ function parseSandboxResult(result) {
1763
+ if (result === void 0) return {};
1764
+ try {
1765
+ const parsed = JSON.parse(result);
1766
+ const exitCode = parsed.response?.exitCode ?? null;
1767
+ const resultText = parsed.response?.result;
1768
+ return {
1769
+ exitCode,
1770
+ resultText,
1771
+ resultJson: JSON.stringify(parsed, null, 2)
1772
+ };
1773
+ } catch {
1774
+ return { resultText: result };
1775
+ }
1776
+ }
1777
+ function parseMcpToolArgs(argsText) {
1778
+ if (!argsText) return {};
1779
+ try {
1780
+ const parsed = JSON.parse(argsText);
1781
+ return {
1782
+ mcpServer: parsed.mcp_server,
1783
+ innerToolName: parsed.tool_name,
1784
+ input: parsed.input
1785
+ };
1786
+ } catch {
1787
+ return {};
1788
+ }
1789
+ }
1790
+ function getJsonDisplayValue(content) {
1791
+ if (!content?.trim()) return { value: "", isJson: false };
1792
+ const trimmed = content.trim();
1793
+ if (trimmed[0] !== "{" && trimmed[0] !== "[") {
1794
+ return { value: content, isJson: false };
1795
+ }
1796
+ try {
1797
+ const parsed = JSON.parse(content);
1798
+ return { value: JSON.stringify(parsed, null, 2), isJson: true };
1799
+ } catch {
1800
+ return { value: content, isJson: false };
1801
+ }
1802
+ }
1803
+ function getToolResultContent(content) {
1804
+ try {
1805
+ if (!content) return { isJson: false, data: "" };
1806
+ const parsedResult = typeof content === "string" && content.trim().startsWith("{") ? JSON.parse(content) : content;
1807
+ if (Array.isArray(parsedResult.content)) {
1808
+ const text = parsedResult.content[0]?.text || "";
1809
+ const display2 = getJsonDisplayValue(
1810
+ typeof text === "string" ? text : JSON.stringify(text)
1811
+ );
1812
+ return { data: display2.value, isJson: display2.isJson };
1813
+ }
1814
+ const display = getJsonDisplayValue(
1815
+ typeof parsedResult === "string" ? parsedResult : JSON.stringify(parsedResult)
1816
+ );
1817
+ return { data: display.value, isJson: display.isJson };
1818
+ } catch (error) {
1819
+ return { data: String(content), isJson: false };
1820
+ }
1821
+ }
2065
1822
  function ToolApprovalSlot({ part }) {
2066
- const ToolApprovalBar2 = useSlot("ToolApprovalBar");
2067
1823
  const nestedBridge = useNestedApprovalBridge();
2068
1824
  const respond = (response) => {
2069
1825
  if (nestedBridge) {
@@ -2072,33 +1828,73 @@ function ToolApprovalSlot({ part }) {
2072
1828
  }
2073
1829
  part.respondToApproval(response);
2074
1830
  };
2075
- const onSelectOption = (optionId) => {
1831
+ const onSelectOption = (optionId, reason) => {
2076
1832
  if (optionId === "__allow") return respond({ approved: true });
2077
- if (optionId === "__deny") return respond({ approved: false });
2078
- return respond({ optionId });
1833
+ if (optionId === "__deny") return respond({ approved: false, reason });
1834
+ return respond({ optionId, reason });
2079
1835
  };
2080
- return /* @__PURE__ */ jsx40(ToolApprovalBar2, { options: buildApprovalOptions(part.approval?.options), onSelectOption });
1836
+ return /* @__PURE__ */ jsx46(
1837
+ ToolApprovalContainer,
1838
+ {
1839
+ toolName: part.toolName,
1840
+ options: buildApprovalOptions(part.approval?.options),
1841
+ onSelectOption
1842
+ }
1843
+ );
2081
1844
  }
2082
1845
  var ToolCallContainer = (part) => {
2083
1846
  const ToolCallCard2 = useSlot("ToolCallCard");
1847
+ const SubAgentCard2 = useSlot("SubAgentCard");
1848
+ const AskUserPrompt2 = useSlot("AskUserPrompt");
2084
1849
  const respondToNestedApproval = useTrueFoundryRespondToToolApproval();
2085
1850
  const elapsedMs = useToolCallElapsed();
2086
1851
  const isRequiresAction = part.status?.type === "requires-action";
2087
- const [expanded, setExpanded] = useState7(isRequiresAction);
2088
- const [prevRequiresAction, setPrevRequiresAction] = useState7(isRequiresAction);
1852
+ const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
1853
+ const isSandbox = SANDBOX_TOOL_NAMES.has(part.toolName);
1854
+ const [expanded, setExpanded] = useState8(isRequiresAction || isSubAgent);
1855
+ const [prevRequiresAction, setPrevRequiresAction] = useState8(isRequiresAction);
2089
1856
  if (isRequiresAction !== prevRequiresAction) {
2090
1857
  setPrevRequiresAction(isRequiresAction);
2091
1858
  if (isRequiresAction) setExpanded(true);
2092
1859
  }
2093
1860
  const showApproval = isRequiresAction && hasPendingToolApproval(part.approval);
2094
- const isSubAgent = part.toolName === SUB_AGENT_TOOL_NAME;
2095
1861
  const durationText = elapsedMs === void 0 ? void 0 : formatDuration(elapsedMs);
2096
1862
  const status = toStatus(part.status?.type);
1863
+ if (part.toolName === ASK_USER_TOOL_NAME) {
1864
+ if (hasPendingAskUserResponse(part)) {
1865
+ return null;
1866
+ }
1867
+ const answer = getAskUserAnswerResult(part.result);
1868
+ if (answer == null) {
1869
+ return null;
1870
+ }
1871
+ const { question, options = [] } = parseAskUserQuestionArgs(part.argsText);
1872
+ const isCustom = options.length > 0 && !options.includes(answer);
1873
+ return /* @__PURE__ */ jsx46(
1874
+ AskUserPrompt2,
1875
+ {
1876
+ questions: [],
1877
+ answeredQuestions: [
1878
+ {
1879
+ id: part.toolCallId,
1880
+ question: question ?? "Question",
1881
+ options,
1882
+ answer,
1883
+ isCustom
1884
+ }
1885
+ ],
1886
+ onSubmit: () => {
1887
+ },
1888
+ readOnly: true
1889
+ }
1890
+ );
1891
+ }
2097
1892
  if (isSubAgent) {
1893
+ const artifactSubAgent = part.artifact?.subAgents?.[0];
2098
1894
  const firstNested = part.messages?.[0];
2099
1895
  const subAgent = firstNested?.metadata?.custom?.subAgent;
2100
- const agentName = subAgent?.title ?? subAgent?.name ?? part.toolName;
2101
- const instruction = subAgent?.input ?? "";
1896
+ const agentName = subAgent?.title ?? subAgent?.name ?? artifactSubAgent?.title ?? artifactSubAgent?.agentInfo?.name ?? part.toolName;
1897
+ const instruction = subAgent?.input ?? artifactSubAgent?.agentInfo?.input ?? "";
2102
1898
  const stepCount = part.messages?.length ?? 0;
2103
1899
  const bridge = (response) => {
2104
1900
  if (part.approval == null) return;
@@ -2106,51 +1902,220 @@ var ToolCallContainer = (part) => {
2106
1902
  if (approved === void 0) return;
2107
1903
  respondToNestedApproval({ approvalId: part.approval.id, approved });
2108
1904
  };
2109
- return /* @__PURE__ */ jsx40(
2110
- ToolCallCard2,
1905
+ return /* @__PURE__ */ jsx46(
1906
+ "div",
1907
+ {
1908
+ "data-slot": "tool-call-card",
1909
+ "data-variant": "sub-agent",
1910
+ className: "w-full py-2",
1911
+ children: /* @__PURE__ */ jsx46(
1912
+ SubAgentCard2,
1913
+ {
1914
+ status,
1915
+ expanded,
1916
+ onToggle: () => setExpanded((prev) => !prev),
1917
+ durationText,
1918
+ agentName,
1919
+ instruction,
1920
+ stepCount,
1921
+ children: /* @__PURE__ */ jsx46(NestedApprovalBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsx46(
1922
+ MessagePartPrimitive.Messages,
1923
+ {
1924
+ components: {
1925
+ AssistantMessage: NestedSubAgentAssistantMessage,
1926
+ UserMessage: () => null
1927
+ }
1928
+ }
1929
+ ) })
1930
+ }
1931
+ )
1932
+ }
1933
+ );
1934
+ }
1935
+ const resultString = part.result === void 0 ? void 0 : typeof part.result === "string" ? part.result : JSON.stringify(part.result, null, 2);
1936
+ if (isSandbox) {
1937
+ const { command, intent, argsJson } = parseSandboxArgs(part.argsText);
1938
+ const { exitCode, resultText, resultJson } = parseSandboxResult(resultString);
1939
+ return /* @__PURE__ */ jsx46(
1940
+ SandboxToolCallContainer,
2111
1941
  {
2112
- variant: "sub-agent",
2113
1942
  name: part.toolName,
1943
+ intent,
2114
1944
  status,
2115
1945
  expanded,
2116
1946
  onToggle: () => setExpanded((prev) => !prev),
2117
1947
  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 } } }) }) })
1948
+ command,
1949
+ exitCode,
1950
+ argsJson,
1951
+ resultText,
1952
+ resultJson
1953
+ }
1954
+ );
1955
+ }
1956
+ const isMcpMetaTool = MCP_META_TOOLS.has(part.toolName);
1957
+ if (isMcpMetaTool) {
1958
+ const { mcpServer, innerToolName, input } = parseMcpToolArgs(part.argsText);
1959
+ const argsDisplay2 = getJsonDisplayValue(part.argsText);
1960
+ const resultDisplay2 = getToolResultContent(part.result);
1961
+ if (part.toolName === "list_tools" && mcpServer) {
1962
+ return /* @__PURE__ */ jsx46(
1963
+ ToolCallCard2,
1964
+ {
1965
+ toolName: `Listing tools \xB7 ${mcpServer}`,
1966
+ icon: "mcp-server",
1967
+ expanded,
1968
+ onToggle: () => setExpanded((prev) => !prev),
1969
+ awaiting: status === "running",
1970
+ awaitingText: durationText ?? "Awaiting Response\u2026",
1971
+ showResponseLine: status !== "running" && !!resultDisplay2.data,
1972
+ requestSlot: argsDisplay2.value ? /* @__PURE__ */ jsx46(
1973
+ ToolCallContentBlockContainer,
1974
+ {
1975
+ title: "Request",
1976
+ content: argsDisplay2.value,
1977
+ isJson: argsDisplay2.isJson,
1978
+ maxHeight: "10.5rem"
1979
+ }
1980
+ ) : resultDisplay2.data ? /* @__PURE__ */ jsx46(
1981
+ ToolCallContentBlockContainer,
1982
+ {
1983
+ title: "Request",
1984
+ content: "{}",
1985
+ isJson: true,
1986
+ maxHeight: "10.5rem"
1987
+ }
1988
+ ) : void 0,
1989
+ responseSlot: resultDisplay2.data ? /* @__PURE__ */ jsx46(
1990
+ ToolCallContentBlockContainer,
1991
+ {
1992
+ title: "Response",
1993
+ content: resultDisplay2.data,
1994
+ isJson: resultDisplay2.isJson,
1995
+ resizable: true
1996
+ }
1997
+ ) : void 0
1998
+ }
1999
+ );
2000
+ }
2001
+ let displayName = part.toolName;
2002
+ if (part.toolName === "call_tool" && innerToolName) {
2003
+ displayName = mcpServer ? `call_tool: ${innerToolName} (${mcpServer})` : `call_tool: ${innerToolName}`;
2004
+ } else if (part.toolName === "get_tool_info" && innerToolName && mcpServer) {
2005
+ displayName = `get_tool_info: ${innerToolName} (${mcpServer})`;
2006
+ }
2007
+ const inputDisplay = input !== void 0 ? getJsonDisplayValue(JSON.stringify(input, null, 2)) : argsDisplay2;
2008
+ return /* @__PURE__ */ jsx46(
2009
+ ToolCallCard2,
2010
+ {
2011
+ toolName: displayName,
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
+ requestSlot: inputDisplay.value ? /* @__PURE__ */ jsx46(
2018
+ ToolCallContentBlockContainer,
2019
+ {
2020
+ title: "Request",
2021
+ content: inputDisplay.value,
2022
+ isJson: inputDisplay.isJson,
2023
+ maxHeight: "10.5rem"
2024
+ }
2025
+ ) : resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2026
+ ToolCallContentBlockContainer,
2027
+ {
2028
+ title: "Request",
2029
+ content: "{}",
2030
+ isJson: true,
2031
+ maxHeight: "10.5rem"
2032
+ }
2033
+ ) : void 0,
2034
+ responseSlot: resultDisplay2.data !== void 0 ? /* @__PURE__ */ jsx46(
2035
+ ToolCallContentBlockContainer,
2036
+ {
2037
+ title: "Response",
2038
+ content: resultDisplay2.data,
2039
+ isJson: resultDisplay2.isJson,
2040
+ resizable: true
2041
+ }
2042
+ ) : void 0,
2043
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2122
2044
  }
2123
2045
  );
2124
2046
  }
2125
- return /* @__PURE__ */ jsx40(
2047
+ const argsDisplay = getJsonDisplayValue(part.argsText);
2048
+ const resultDisplay = getToolResultContent(part.result);
2049
+ return /* @__PURE__ */ jsx46(
2126
2050
  ToolCallCard2,
2127
2051
  {
2128
- variant: "tool",
2129
- name: part.toolName,
2130
- status,
2052
+ toolName: part.toolName,
2131
2053
  expanded,
2132
2054
  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
2055
+ awaiting: status === "running",
2056
+ awaitingText: durationText ?? "Awaiting Response\u2026",
2057
+ showResponseLine: status !== "running" && resultDisplay.data !== void 0,
2058
+ requestSlot: argsDisplay.value ? /* @__PURE__ */ jsx46(
2059
+ ToolCallContentBlockContainer,
2060
+ {
2061
+ title: "Request",
2062
+ content: argsDisplay.value,
2063
+ isJson: argsDisplay.isJson,
2064
+ maxHeight: "10.5rem"
2065
+ }
2066
+ ) : resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2067
+ ToolCallContentBlockContainer,
2068
+ {
2069
+ title: "Request",
2070
+ content: "{}",
2071
+ isJson: true,
2072
+ maxHeight: "10.5rem"
2073
+ }
2074
+ ) : void 0,
2075
+ responseSlot: resultDisplay.data !== void 0 ? /* @__PURE__ */ jsx46(
2076
+ ToolCallContentBlockContainer,
2077
+ {
2078
+ title: "Response",
2079
+ content: resultDisplay.data,
2080
+ isJson: resultDisplay.isJson,
2081
+ resizable: true
2082
+ }
2083
+ ) : void 0,
2084
+ approvalSlot: showApproval ? /* @__PURE__ */ jsx46(ToolApprovalSlot, { part }) : void 0
2138
2085
  }
2139
2086
  );
2140
2087
  };
2141
2088
 
2142
2089
  // 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 }) {
2090
+ import { useState as useState9 } from "react";
2091
+ import { useAuiState as useAuiState6 } from "@assistant-ui/react";
2092
+ import { jsx as jsx47 } from "react/jsx-runtime";
2093
+ function ToolGroupContainer({
2094
+ children,
2095
+ group
2096
+ }) {
2146
2097
  const ToolGroupCard2 = useSlot("ToolGroupCard");
2147
- const [expanded, setExpanded] = useState8(true);
2148
- return /* @__PURE__ */ jsx41(
2098
+ const toolCallCount = group.indices.length;
2099
+ const active = useAuiState6((s) => {
2100
+ if (s.message.status?.type !== "running") return false;
2101
+ const lastIndex = s.message.parts.length - 1;
2102
+ if (lastIndex < 0) return false;
2103
+ if (s.message.parts[lastIndex]?.type !== "tool-call") return false;
2104
+ const lastGroupIndex = group.indices[group.indices.length - 1];
2105
+ return lastGroupIndex !== void 0 && lastIndex >= group.indices[0] && lastIndex <= lastGroupIndex;
2106
+ });
2107
+ const [expanded, setExpanded] = useState9(true);
2108
+ const [prevActive, setPrevActive] = useState9(active);
2109
+ if (active !== prevActive) {
2110
+ setPrevActive(active);
2111
+ if (active) setExpanded(true);
2112
+ }
2113
+ return /* @__PURE__ */ jsx47(
2149
2114
  ToolGroupCard2,
2150
2115
  {
2151
- toolCallCount: group.indices.length,
2152
- active: group.status.type === "running",
2116
+ toolCallCount,
2153
2117
  expanded,
2118
+ active,
2154
2119
  onToggle: () => setExpanded((prev) => !prev),
2155
2120
  children
2156
2121
  }
@@ -2158,66 +2123,36 @@ function ToolGroupContainer({ group, children }) {
2158
2123
  }
2159
2124
 
2160
2125
  // src/containers/AssistantMessageContainer.tsx
2161
- import { jsx as jsx42 } from "react/jsx-runtime";
2126
+ import { jsx as jsx48 } from "react/jsx-runtime";
2162
2127
  function AssistantLeafPartContainer({ part }) {
2163
2128
  switch (part.type) {
2164
2129
  case "text":
2165
2130
  case "reasoning":
2166
- return /* @__PURE__ */ jsx42(AssistantTextContainer, {});
2131
+ return /* @__PURE__ */ jsx48(AssistantTextContainer, {});
2167
2132
  case "image":
2168
- return /* @__PURE__ */ jsx42(MessageImageContainer, {});
2133
+ return /* @__PURE__ */ jsx48(MessageImageContainer, {});
2169
2134
  case "tool-call":
2170
- return /* @__PURE__ */ jsx42(ToolCallContainer, { ...part });
2135
+ return /* @__PURE__ */ jsx48(ToolCallContainer, { ...part });
2171
2136
  default:
2172
2137
  return null;
2173
2138
  }
2174
2139
  }
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
2140
  function AssistantMessageContainer() {
2186
- const MessageBubble2 = useSlot("MessageBubble");
2141
+ const AssistantMessageBubble2 = useSlot("AssistantMessageBubble");
2187
2142
  const MessageIndicator2 = useSlot("MessageIndicator");
2188
2143
  const MessageErrorBanner2 = useSlot("MessageErrorBanner");
2189
2144
  const MessageActionBar2 = useSlot("MessageActionBar");
2190
- const BranchIndicator2 = useSlot("BranchIndicator");
2191
- const aui = useAui2();
2192
2145
  const isRunning = useThreadIsRunning2();
2193
2146
  const error = useMessageError();
2194
2147
  const { copy, isCopied } = useActionBarCopy2({
2195
2148
  copyToClipboard: (text) => navigator.clipboard.writeText(text)
2196
2149
  });
2197
- const { branchNumber, branchCount, goToPrev, goToNext } = useMessageBranching();
2198
- return /* @__PURE__ */ jsx42(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx42(
2199
- MessageBubble2,
2150
+ return /* @__PURE__ */ jsx48(MessagePrimitive2.Root, { "data-role": "assistant", children: /* @__PURE__ */ jsx48(
2151
+ AssistantMessageBubble2,
2200
2152
  {
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(
2153
+ error: error !== void 0 ? /* @__PURE__ */ jsx48(MessageErrorBanner2, { message: String(error) }) : void 0,
2154
+ actionBar: !isRunning ? /* @__PURE__ */ jsx48(MessageActionBar2, { isCopied, onCopy: copy }) : void 0,
2155
+ children: /* @__PURE__ */ jsx48(
2221
2156
  MessagePrimitive2.GroupedParts,
2222
2157
  {
2223
2158
  groupBy: groupPartByType({
@@ -2228,19 +2163,19 @@ function AssistantMessageContainer() {
2228
2163
  children: ({ part, children }) => {
2229
2164
  switch (part.type) {
2230
2165
  case "group-chainOfThought":
2231
- return /* @__PURE__ */ jsx42("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
2166
+ return /* @__PURE__ */ jsx48("div", { "data-slot": "aui_chain-of-thought", className: "flex flex-col gap-3", children });
2232
2167
  case "group-tool":
2233
- return /* @__PURE__ */ jsx42(ToolGroupContainer, { group: part, children });
2168
+ return /* @__PURE__ */ jsx48(ToolGroupContainer, { group: part, children });
2234
2169
  case "group-reasoning":
2235
- return /* @__PURE__ */ jsx42(ReasoningContainer, { group: part, children });
2170
+ return /* @__PURE__ */ jsx48(ReasoningContainer, { group: part });
2236
2171
  case "text":
2237
2172
  case "reasoning":
2238
2173
  case "tool-call":
2239
2174
  case "image":
2240
2175
  case "data":
2241
- return /* @__PURE__ */ jsx42(AssistantLeafPartContainer, { part });
2176
+ return /* @__PURE__ */ jsx48(AssistantLeafPartContainer, { part });
2242
2177
  case "indicator":
2243
- return /* @__PURE__ */ jsx42(MessageIndicator2, {});
2178
+ return /* @__PURE__ */ jsx48(MessageIndicator2, {});
2244
2179
  default:
2245
2180
  return null;
2246
2181
  }
@@ -2255,22 +2190,22 @@ function AssistantMessageContainer() {
2255
2190
  import {
2256
2191
  ComposerPrimitive as ComposerPrimitive2,
2257
2192
  MessagePrimitive as MessagePrimitive4,
2258
- useAuiState as useAuiState7
2193
+ useAuiState as useAuiState9
2259
2194
  } from "@assistant-ui/react";
2260
- import { useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
2195
+ import { useComposerCancel, useComposerSend, useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
2261
2196
 
2262
2197
  // src/containers/AttachmentsContainer.tsx
2263
- import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui as useAui3, useAuiState as useAuiState6 } from "@assistant-ui/react";
2198
+ import { ComposerPrimitive, MessagePrimitive as MessagePrimitive3, useAui, useAuiState as useAuiState8 } from "@assistant-ui/react";
2264
2199
 
2265
2200
  // src/containers/useAttachmentPreviewSrc.ts
2266
- import { useEffect as useEffect2, useState as useState9 } from "react";
2267
- import { useAuiState as useAuiState5 } from "@assistant-ui/react";
2201
+ import { useEffect as useEffect3, useState as useState10 } from "react";
2202
+ import { useAuiState as useAuiState7 } from "@assistant-ui/react";
2268
2203
  function isImageAttachment(type, contentType) {
2269
2204
  return type === "image" || (contentType?.startsWith("image/") ?? false);
2270
2205
  }
2271
2206
  function useFileObjectUrl(file) {
2272
- const [src, setSrc] = useState9(void 0);
2273
- useEffect2(() => {
2207
+ const [src, setSrc] = useState10(void 0);
2208
+ useEffect3(() => {
2274
2209
  if (!file) {
2275
2210
  setSrc(void 0);
2276
2211
  return;
@@ -2282,10 +2217,10 @@ function useFileObjectUrl(file) {
2282
2217
  return src;
2283
2218
  }
2284
2219
  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) => {
2220
+ const type = useAuiState7((s) => s.attachment.type);
2221
+ const contentType = useAuiState7((s) => s.attachment.contentType);
2222
+ const file = useAuiState7((s) => "file" in s.attachment ? s.attachment.file : void 0);
2223
+ const contentSrc = useAuiState7((s) => {
2289
2224
  if (!isImageAttachment(s.attachment.type, s.attachment.contentType)) return void 0;
2290
2225
  const imagePart = s.attachment.content?.find((part) => part.type === "image");
2291
2226
  if (imagePart?.type === "image" && imagePart.image) return imagePart.image;
@@ -2298,17 +2233,17 @@ function useAttachmentPreviewSrc() {
2298
2233
  }
2299
2234
 
2300
2235
  // src/containers/AttachmentsContainer.tsx
2301
- import { jsx as jsx43 } from "react/jsx-runtime";
2236
+ import { jsx as jsx49 } from "react/jsx-runtime";
2302
2237
  function ComposerAttachmentItem() {
2303
2238
  const AttachmentCard2 = useSlot("AttachmentCard");
2304
2239
  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);
2240
+ const aui = useAui();
2241
+ const name = useAuiState8((s) => s.attachment.name);
2242
+ const contentType = useAuiState8((s) => s.attachment.contentType);
2243
+ const type = useAuiState8((s) => s.attachment.type);
2309
2244
  const isImage = isImageAttachment(type, contentType);
2310
2245
  const previewSrc = useAttachmentPreviewSrc();
2311
- return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx43(
2246
+ return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: /* @__PURE__ */ jsx49(
2312
2247
  AttachmentCard2,
2313
2248
  {
2314
2249
  name,
@@ -2323,12 +2258,12 @@ function ComposerAttachmentItem() {
2323
2258
  function MessageAttachmentItem() {
2324
2259
  const AttachmentCard2 = useSlot("AttachmentCard");
2325
2260
  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);
2261
+ const name = useAuiState8((s) => s.attachment.name);
2262
+ const contentType = useAuiState8((s) => s.attachment.contentType);
2263
+ const type = useAuiState8((s) => s.attachment.type);
2329
2264
  const isImage = isImageAttachment(type, contentType);
2330
2265
  const previewSrc = useAttachmentPreviewSrc();
2331
- const card = /* @__PURE__ */ jsx43(
2266
+ const card = /* @__PURE__ */ jsx49(
2332
2267
  AttachmentCard2,
2333
2268
  {
2334
2269
  name,
@@ -2340,122 +2275,120 @@ function MessageAttachmentItem() {
2340
2275
  }
2341
2276
  );
2342
2277
  if (isImage && previewSrc) {
2343
- return /* @__PURE__ */ jsx43(AttachmentPreviewDialog2, { previewSrc, children: card });
2278
+ return /* @__PURE__ */ jsx49(AttachmentPreviewDialog2, { previewSrc, children: card });
2344
2279
  }
2345
2280
  return card;
2346
2281
  }
2347
2282
  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, {}) }) });
2283
+ 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
2284
  }
2350
2285
  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, {}) }) });
2286
+ 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
2287
  }
2353
2288
  function ComposerAttachmentPickerContainer() {
2354
2289
  const AttachmentPickerButton2 = useSlot("AttachmentPickerButton");
2355
- return /* @__PURE__ */ jsx43(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx43(AttachmentPickerButton2, {}) });
2290
+ return /* @__PURE__ */ jsx49(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx49(AttachmentPickerButton2, {}) });
2356
2291
  }
2357
2292
 
2358
2293
  // src/containers/UserEditComposerContainer.tsx
2359
- import { jsx as jsx44, jsxs as jsxs25 } from "react/jsx-runtime";
2294
+ import { jsx as jsx50, jsxs as jsxs16 } from "react/jsx-runtime";
2360
2295
  function ReadOnlyMessageAttachments() {
2361
- const hasAttachments = useAuiState7(
2296
+ const hasAttachments = useAuiState9(
2362
2297
  (s) => (s.message.attachments?.length ?? 0) > 0
2363
2298
  );
2364
2299
  if (!hasAttachments) {
2365
2300
  return null;
2366
2301
  }
2367
- return /* @__PURE__ */ jsx44("div", { className: "pointer-events-none opacity-90", children: /* @__PURE__ */ jsx44(MessageAttachmentsContainer, {}) });
2302
+ return /* @__PURE__ */ jsx50("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx50(MessageAttachmentsContainer, {}) });
2368
2303
  }
2369
2304
  function UserEditComposerContainer() {
2370
- const Button2 = useSlot("Button");
2305
+ const Button4 = useSlot("Button");
2306
+ const MessageTimestamp2 = useSlot("MessageTimestamp");
2307
+ const UserMessageEdit3 = useSlot("UserMessageEdit");
2371
2308
  const isRunning = useThreadIsRunning3();
2372
- return /* @__PURE__ */ jsx44(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsxs25(
2309
+ const { cancel, disabled: cancelDisabled } = useComposerCancel();
2310
+ const { send, disabled: sendDisabled } = useComposerSend();
2311
+ return /* @__PURE__ */ jsx50(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx50(
2373
2312
  "div",
2374
2313
  {
2375
2314
  "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(
2315
+ className: "fade-in slide-in-from-bottom-1 animate-in flex w-full justify-end px-2 duration-150",
2316
+ children: /* @__PURE__ */ jsx50(ComposerPrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx50(
2317
+ UserMessageEdit3,
2318
+ {
2319
+ timestamp: /* @__PURE__ */ jsx50(MessageTimestamp2, { className: "text-gray-500" }),
2320
+ attachments: /* @__PURE__ */ jsx50(ReadOnlyMessageAttachments, {}),
2321
+ 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
2322
  ComposerPrimitive2.Input,
2382
2323
  {
2383
2324
  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"
2325
+ 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
2326
  }
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
- ] })
2327
+ ) }),
2328
+ footer: /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-end gap-2", children: [
2329
+ /* @__PURE__ */ jsx50(
2330
+ Button4.Secondary,
2331
+ {
2332
+ type: "button",
2333
+ disabled: cancelDisabled,
2334
+ onClick: cancel,
2335
+ text: "Cancel"
2336
+ }
2337
+ ),
2338
+ /* @__PURE__ */ jsx50(
2339
+ Button4.Primary,
2340
+ {
2341
+ type: "button",
2342
+ disabled: sendDisabled || isRunning,
2343
+ onClick: () => send(),
2344
+ text: "Save & Rerun"
2345
+ }
2346
+ )
2419
2347
  ] })
2420
- ] }) }) })
2421
- ]
2348
+ }
2349
+ ) })
2422
2350
  }
2423
2351
  ) });
2424
2352
  }
2425
2353
 
2426
2354
  // src/containers/UserMessageContainer.tsx
2427
- import { MessagePrimitive as MessagePrimitive5 } from "@assistant-ui/react";
2355
+ import { MessagePrimitive as MessagePrimitive5, useAuiState as useAuiState10 } from "@assistant-ui/react";
2428
2356
  import { useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
2429
- import { jsx as jsx45 } from "react/jsx-runtime";
2357
+ import { jsx as jsx51 } from "react/jsx-runtime";
2430
2358
  function UserMessageContainer() {
2431
- const MessageBubble2 = useSlot("MessageBubble");
2359
+ const UserMessageBubble2 = useSlot("UserMessageBubble");
2432
2360
  const UserMessageActionBar2 = useSlot("UserMessageActionBar");
2433
2361
  const isRunning = useThreadIsRunning4();
2434
- return /* @__PURE__ */ jsx45(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx45(
2435
- MessageBubble2,
2362
+ const text = useAuiState10(
2363
+ (s) => s.message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n")
2364
+ );
2365
+ return /* @__PURE__ */ jsx51(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx51(
2366
+ UserMessageBubble2,
2436
2367
  {
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 } })
2368
+ text,
2369
+ attachments: /* @__PURE__ */ jsx51(MessageAttachmentsContainer, {}),
2370
+ editAction: !isRunning ? /* @__PURE__ */ jsx51(UserMessageActionBar2, {}) : void 0
2441
2371
  }
2442
2372
  ) });
2443
2373
  }
2444
2374
 
2445
2375
  // src/containers/ThreadContainer.tsx
2446
- import { jsx as jsx46, jsxs as jsxs26 } from "react/jsx-runtime";
2376
+ import { jsx as jsx52, jsxs as jsxs17 } from "react/jsx-runtime";
2447
2377
  var isNewChatView = (s) => s.thread.messages.length === 0 && (!s.thread.isLoading || s.threads.isLoading);
2448
2378
  function ThreadMessage({ isEditing }) {
2449
- const role = useAuiState8((s) => s.message.role);
2379
+ const role = useAuiState11((s) => s.message.role);
2450
2380
  if (role === "user") {
2451
2381
  if (isEditing) {
2452
- return /* @__PURE__ */ jsx46(UserEditComposerContainer, {});
2382
+ return /* @__PURE__ */ jsx52(UserEditComposerContainer, {});
2453
2383
  }
2454
- return /* @__PURE__ */ jsx46(UserMessageContainer, {});
2384
+ return /* @__PURE__ */ jsx52(UserMessageContainer, {});
2455
2385
  }
2456
- return /* @__PURE__ */ jsx46(AssistantMessageContainer, {});
2386
+ return /* @__PURE__ */ jsx52(AssistantMessageContainer, {});
2457
2387
  }
2458
2388
  function ThreadContainer({ composer }) {
2389
+ useEffect4(() => {
2390
+ void preloadMarkdownOpenUI();
2391
+ }, []);
2459
2392
  const ThreadRootShell2 = useSlot("ThreadRootShell");
2460
2393
  const ThreadViewportShell2 = useSlot("ThreadViewportShell");
2461
2394
  const ThreadComposerAreaShell2 = useSlot("ThreadComposerAreaShell");
@@ -2463,64 +2396,139 @@ function ThreadContainer({ composer }) {
2463
2396
  const WelcomeScreen2 = useSlot("WelcomeScreen");
2464
2397
  const MessageListSkeleton2 = useSlot("MessageListSkeleton");
2465
2398
  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(
2399
+ const isEmpty = useAuiState11(isNewChatView);
2400
+ const isLoading = useAuiState11((s) => s.thread.isLoading);
2401
+ return /* @__PURE__ */ jsx52(ComposerBusyProvider, { children: /* @__PURE__ */ jsx52(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs17(ThreadRootShell2, { children: [
2402
+ /* @__PURE__ */ jsx52(ThreadPrimitive.Viewport, { asChild: true, turnAnchor: "top", autoScroll: true, children: /* @__PURE__ */ jsxs17(ThreadViewportShell2, { isEmpty, children: [
2403
+ isEmpty && /* @__PURE__ */ jsx52(WelcomeScreen2, {}),
2404
+ isLoading ? /* @__PURE__ */ jsx52(MessageListSkeleton2, {}) : /* @__PURE__ */ jsx52(MessageGroup2, { children: /* @__PURE__ */ jsx52(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx52(
2472
2405
  ThreadMessage,
2473
2406
  {
2474
2407
  isEditing: message.role === "user" && message.composer.isEditing
2475
2408
  }
2476
2409
  ) }) })
2477
2410
  ] }) }),
2478
- !isLoading && /* @__PURE__ */ jsxs26(ThreadComposerAreaShell2, { isEmpty, children: [
2479
- /* @__PURE__ */ jsx46(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx46(ScrollToBottomButton2, {}) }),
2411
+ !isLoading && /* @__PURE__ */ jsxs17(ThreadComposerAreaShell2, { isEmpty, children: [
2412
+ !isEmpty && /* @__PURE__ */ jsx52(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx52(ScrollToBottomButton2, {}) }),
2480
2413
  composer
2481
2414
  ] })
2482
2415
  ] }) }) });
2483
2416
  }
2484
2417
 
2485
2418
  // 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";
2419
+ import { useRef as useRef3 } from "react";
2420
+ import { useAui as useAui2, useAuiState as useAuiState13 } from "@assistant-ui/react";
2421
+ import { useTrueFoundryCancel } from "@truefoundry/assistant-ui-runtime";
2489
2422
 
2490
- // src/containers/AskUserContainer.tsx
2491
- import { useState as useState10 } from "react";
2423
+ // src/hooks/useComposerPauseView.ts
2424
+ import { useAuiState as useAuiState12 } from "@assistant-ui/react";
2492
2425
  import { useTrueFoundryToolResponses } from "@truefoundry/assistant-ui-runtime";
2426
+ function threadHasPendingMcpAuth(s) {
2427
+ const messages = s.thread.messages;
2428
+ const last = messages[messages.length - 1];
2429
+ if (last?.role !== "assistant") return false;
2430
+ if (last.status?.type !== "requires-action") return false;
2431
+ return last.metadata?.custom?.pendingMcpAuth === true;
2432
+ }
2433
+ function useComposerPauseView() {
2434
+ const mcpPending = useAuiState12(threadHasPendingMcpAuth);
2435
+ const { pending: toolResponsesPending } = useTrueFoundryToolResponses();
2436
+ if (mcpPending) {
2437
+ return { kind: "mcp" };
2438
+ }
2439
+ if (toolResponsesPending.length > 0) {
2440
+ return { kind: "ask-user" };
2441
+ }
2442
+ return { kind: "compose" };
2443
+ }
2444
+
2445
+ // src/containers/AskUserContainer.tsx
2446
+ import { useTrueFoundryToolResponses as useTrueFoundryToolResponses2 } from "@truefoundry/assistant-ui-runtime";
2493
2447
  import { useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
2494
- import { jsx as jsx47 } from "react/jsx-runtime";
2495
- var OTHER_OPTION_ID2 = "__other";
2448
+ import { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo5, useState as useState11 } from "react";
2449
+ import {
2450
+ ASK_USER_CUSTOM_OPTION
2451
+ } from "tfy-web-components/components/molecules/agent-chat";
2452
+ import { jsx as jsx53 } from "react/jsx-runtime";
2453
+ var EMPTY_ANSWER = { radioValue: "", custom: "" };
2496
2454
  function AskUserContainer() {
2497
2455
  const AskUserPrompt2 = useSlot("AskUserPrompt");
2498
- const { pending, respond } = useTrueFoundryToolResponses();
2456
+ const { pending, respond } = useTrueFoundryToolResponses2();
2499
2457
  const isRunning = useThreadIsRunning5();
2500
- const [selectedOptionId, setSelectedOptionId] = useState10(void 0);
2501
- const [otherValue, setOtherValue] = useState10("");
2502
2458
  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();
2459
+ const questions = useMemo5(
2460
+ () => item == null ? [] : [
2461
+ {
2462
+ id: item.toolCallId,
2463
+ question: item.question ?? "Answer required",
2464
+ options: item.options ?? []
2465
+ }
2466
+ ],
2467
+ [item]
2468
+ );
2469
+ const [currentQuestionIndex, setCurrentQuestionIndex] = useState11(0);
2470
+ const [answers, setAnswers] = useState11(
2471
+ {}
2472
+ );
2473
+ useEffect5(() => {
2474
+ setCurrentQuestionIndex(0);
2475
+ setAnswers({});
2476
+ }, [item?.toolCallId]);
2477
+ const safeIndex = Math.min(
2478
+ currentQuestionIndex,
2479
+ Math.max(questions.length - 1, 0)
2480
+ );
2481
+ const currentQuestion = questions[safeIndex];
2482
+ const currentAnswer = currentQuestion == null ? EMPTY_ANSWER : answers[currentQuestion.id] ?? EMPTY_ANSWER;
2483
+ const getResponseForQuestion = useCallback7(
2484
+ (questionId) => {
2485
+ const answer = answers[questionId] ?? EMPTY_ANSWER;
2486
+ return answer.radioValue === ASK_USER_CUSTOM_OPTION ? answer.custom.trim() : answer.radioValue.trim();
2487
+ },
2488
+ [answers]
2489
+ );
2490
+ const allQuestionsAnswered = useMemo5(
2491
+ () => questions.every((question) => getResponseForQuestion(question.id)),
2492
+ [getResponseForQuestion, questions]
2493
+ );
2494
+ const selectedResponse = currentAnswer.radioValue === ASK_USER_CUSTOM_OPTION ? currentAnswer.custom.trim() : currentAnswer.radioValue.trim();
2495
+ const isSubmitDisabled = isRunning || currentQuestion == null || selectedResponse.length === 0;
2496
+ const isSubmitAllDisabled = isSubmitDisabled || !allQuestionsAnswered;
2497
+ const onCurrentAnswerChange = useCallback7(
2498
+ (questionId, update) => {
2499
+ setAnswers((previous) => ({
2500
+ ...previous,
2501
+ [questionId]: {
2502
+ ...previous[questionId] ?? EMPTY_ANSWER,
2503
+ ...update
2504
+ }
2505
+ }));
2506
+ },
2507
+ []
2508
+ );
2509
+ const onSubmit = useCallback7(() => {
2510
+ if (item == null || !allQuestionsAnswered) return;
2511
+ const content = getResponseForQuestion(item.toolCallId);
2508
2512
  if (!content) return;
2509
2513
  respond({ toolCallId: item.toolCallId, content });
2510
- setSelectedOptionId(void 0);
2511
- setOtherValue("");
2512
- };
2513
- return /* @__PURE__ */ jsx47(
2514
+ }, [allQuestionsAnswered, getResponseForQuestion, item, respond]);
2515
+ if (item == null || currentQuestion == null) return null;
2516
+ return /* @__PURE__ */ jsx53(
2514
2517
  AskUserPrompt2,
2515
2518
  {
2516
- question: item.question ?? "Answer required",
2517
- options,
2518
- allowOther,
2519
- selectedOptionId,
2520
- otherValue,
2521
- disabled: isRunning,
2522
- onSelectOption: setSelectedOptionId,
2523
- onOtherValueChange: setOtherValue,
2519
+ questions,
2520
+ readOnly: isRunning,
2521
+ currentQuestion,
2522
+ currentQuestionIndex: safeIndex,
2523
+ currentAnswer,
2524
+ totalQuestions: questions.length,
2525
+ isMultiQuestion: questions.length > 1,
2526
+ isLastQuestion: safeIndex === questions.length - 1,
2527
+ allQuestionsAnswered,
2528
+ isSubmitDisabled,
2529
+ isSubmitAllDisabled,
2530
+ onCurrentQuestionIndexChange: setCurrentQuestionIndex,
2531
+ onCurrentAnswerChange,
2524
2532
  onSubmit
2525
2533
  }
2526
2534
  );
@@ -2529,66 +2537,72 @@ function AskUserContainer() {
2529
2537
  // src/containers/McpAuthContainer.tsx
2530
2538
  import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
2531
2539
  import { useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
2532
- import { jsx as jsx48 } from "react/jsx-runtime";
2540
+ import { jsx as jsx54 } from "react/jsx-runtime";
2533
2541
  function McpAuthContainer() {
2534
2542
  const McpAuthPrompt2 = useSlot("McpAuthPrompt");
2535
2543
  const { pending, resume } = useTrueFoundryMcpAuth();
2536
2544
  const isRunning = useThreadIsRunning6();
2537
2545
  if (!pending) return null;
2538
- return /* @__PURE__ */ jsx48(
2546
+ const handleConnect = (serverId) => {
2547
+ const server = pending.mcpServers.find((s) => s.id === serverId);
2548
+ if (server?.authUrl) {
2549
+ window.open(server.authUrl, "_blank", "noopener,noreferrer");
2550
+ }
2551
+ };
2552
+ return /* @__PURE__ */ jsx54(
2539
2553
  McpAuthPrompt2,
2540
2554
  {
2541
2555
  servers: pending.mcpServers,
2542
- disabled: isRunning,
2543
- onContinue: () => void resume()
2556
+ onConnect: handleConnect,
2557
+ onContinue: () => void resume(),
2558
+ readOnly: isRunning
2544
2559
  }
2545
2560
  );
2546
2561
  }
2547
2562
 
2548
2563
  // 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() {
2564
+ import { Fragment as Fragment4, jsx as jsx55, jsxs as jsxs18 } from "react/jsx-runtime";
2565
+ function ComposerContainer({
2566
+ placeholder = "Ask anything... (Shift+Enter for new line)"
2567
+ }) {
2558
2568
  const ComposerShell2 = useSlot("ComposerShell");
2559
- const aui = useAui4();
2560
- const text = useAuiState9((s) => s.composer.text);
2569
+ const aui = useAui2();
2570
+ const text = useAuiState13((s) => s.composer.text);
2561
2571
  const { isBusy, send, resetBusy } = useComposerBusyState();
2562
- const mcpPending = useAuiState9(threadHasPendingMcpAuth);
2563
- const { pending: toolResponsesPending } = useTrueFoundryToolResponses2();
2572
+ const pauseView = useComposerPauseView();
2564
2573
  const cancel = useTrueFoundryCancel();
2565
- const fileInputRef = useRef(null);
2566
- if (mcpPending) {
2567
- return /* @__PURE__ */ jsx49(McpAuthContainer, {});
2574
+ const fileInputRef = useRef3(null);
2575
+ if (pauseView.kind === "mcp") {
2576
+ return /* @__PURE__ */ jsx55(McpAuthContainer, {});
2568
2577
  }
2569
- if (toolResponsesPending.length > 0) {
2570
- return /* @__PURE__ */ jsx49(AskUserContainer, {});
2578
+ if (pauseView.kind === "ask-user") {
2579
+ return /* @__PURE__ */ jsx55(AskUserContainer, {});
2571
2580
  }
2572
- return /* @__PURE__ */ jsxs27(Fragment3, { children: [
2573
- /* @__PURE__ */ jsx49(
2581
+ return /* @__PURE__ */ jsxs18(Fragment4, { children: [
2582
+ /* @__PURE__ */ jsx55(
2574
2583
  "input",
2575
2584
  {
2576
2585
  ref: fileInputRef,
2577
2586
  type: "file",
2587
+ multiple: true,
2578
2588
  hidden: true,
2579
2589
  onChange: (event) => {
2580
- const file = event.target.files?.[0];
2581
- if (file) void aui.composer().addAttachment(file);
2590
+ const files = event.target.files;
2591
+ if (files) {
2592
+ for (const file of files) {
2593
+ void aui.composer().addAttachment(file);
2594
+ }
2595
+ }
2582
2596
  event.target.value = "";
2583
2597
  }
2584
2598
  }
2585
2599
  ),
2586
- /* @__PURE__ */ jsx49(
2600
+ /* @__PURE__ */ jsx55(
2587
2601
  ComposerShell2,
2588
2602
  {
2589
- attachments: /* @__PURE__ */ jsx49(ComposerAttachmentsContainer, {}),
2603
+ attachments: /* @__PURE__ */ jsx55(ComposerAttachmentsContainer, {}),
2590
2604
  value: text,
2591
- placeholder: "Ask anything... (Shift+Enter for new line)",
2605
+ placeholder,
2592
2606
  disabled: isBusy,
2593
2607
  isRunning: isBusy,
2594
2608
  onValueChange: (value) => aui.composer().setText(value),
@@ -2604,27 +2618,39 @@ function ComposerContainer() {
2604
2618
  }
2605
2619
 
2606
2620
  // 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";
2621
+ import { useAui as useAui3, useAuiState as useAuiState14 } from "@assistant-ui/react";
2622
+ import { useEffect as useEffect6, useRef as useRef4 } from "react";
2623
+ import { Fragment as Fragment5, jsx as jsx56, jsxs as jsxs19 } from "react/jsx-runtime";
2609
2624
  function ThreadListContainer() {
2610
2625
  const ThreadListShell2 = useSlot("ThreadListShell");
2611
2626
  const ThreadListNewButton2 = useSlot("ThreadListNewButton");
2612
2627
  const ThreadListRow2 = useSlot("ThreadListRow");
2613
2628
  const ThreadListRowSkeleton2 = useSlot("ThreadListRowSkeleton");
2614
2629
  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);
2630
+ const aui = useAui3();
2631
+ const isLoading = useAuiState14((s) => s.threads.isLoading);
2632
+ const isLoadingMore = useAuiState14((s) => s.threads.isLoadingMore);
2633
+ const hasMore = useAuiState14((s) => s.threads.hasMore);
2634
+ const threadIds = useAuiState14((s) => s.threads.threadIds);
2635
+ const threadItems = useAuiState14((s) => s.threads.threadItems);
2636
+ const mainThreadId = useAuiState14((s) => s.threads.mainThreadId);
2637
+ const sentinelRef = useRef4(null);
2638
+ useEffect6(() => {
2639
+ const node = sentinelRef.current;
2640
+ if (!node || !hasMore) return;
2641
+ const observer = new IntersectionObserver((entries) => {
2642
+ if (entries.some((e) => e.isIntersecting) && hasMore && !isLoadingMore) {
2643
+ void aui.threads().loadMore();
2644
+ }
2645
+ });
2646
+ observer.observe(node);
2647
+ return () => observer.disconnect();
2648
+ }, [aui, hasMore, isLoadingMore]);
2623
2649
  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) => {
2650
+ return /* @__PURE__ */ jsxs19(ThreadListShell2, { header: /* @__PURE__ */ jsx56(ThreadListNewButton2, { onClick: () => aui.threads().switchToNewThread() }), children: [
2651
+ isLoading ? /* @__PURE__ */ jsx56(ThreadListRowSkeleton2, {}) : threadIds.length === 0 ? /* @__PURE__ */ jsx56(ThreadListEmptyState2, {}) : threadIds.map((id) => {
2626
2652
  const item = itemsById.get(id);
2627
- return /* @__PURE__ */ jsx50(
2653
+ return /* @__PURE__ */ jsx56(
2628
2654
  ThreadListRow2,
2629
2655
  {
2630
2656
  title: item?.title ?? "New Chat",
@@ -2636,18 +2662,24 @@ function ThreadListContainer() {
2636
2662
  id
2637
2663
  );
2638
2664
  }),
2639
- !isLoading && hasMore && (isLoadingMore ? /* @__PURE__ */ jsx50(ThreadListRowSkeleton2, { count: 1 }) : /* @__PURE__ */ jsx50(Button2, { variant: "ghost", onClick: () => void aui.threads().loadMore(), children: "Load more" }))
2665
+ !isLoading && hasMore && /* @__PURE__ */ jsxs19(Fragment5, { children: [
2666
+ isLoadingMore && /* @__PURE__ */ jsx56(ThreadListRowSkeleton2, { count: 1 }),
2667
+ /* @__PURE__ */ jsx56("div", { ref: sentinelRef, "aria-hidden": true })
2668
+ ] })
2640
2669
  ] });
2641
2670
  }
2642
2671
 
2643
2672
  // src/containers/Thread.tsx
2644
- import { jsx as jsx51 } from "react/jsx-runtime";
2673
+ import { jsx as jsx57 } from "react/jsx-runtime";
2645
2674
  function Thread() {
2646
- return /* @__PURE__ */ jsx51(ThreadContainer, { composer: /* @__PURE__ */ jsx51(ComposerContainer, {}) });
2675
+ return /* @__PURE__ */ jsx57(ThreadContainer, { composer: /* @__PURE__ */ jsx57(ComposerContainer, {}) });
2647
2676
  }
2648
2677
  export {
2678
+ Accordion3 as Accordion,
2679
+ AccordionDetails3 as AccordionDetails,
2680
+ AccordionSummary3 as AccordionSummary,
2649
2681
  AskUserContainer,
2650
- AskUserPrompt,
2682
+ AssistantMessageBubble,
2651
2683
  AssistantMessageContainer,
2652
2684
  AssistantTextContainer,
2653
2685
  AttachmentCard,
@@ -2656,46 +2688,41 @@ export {
2656
2688
  Avatar,
2657
2689
  AvatarFallback,
2658
2690
  AvatarImage,
2659
- BranchIndicator,
2660
- Button,
2661
- CodeBlockHeader,
2662
- Collapsible,
2663
- CollapsibleContent,
2664
- CollapsibleTrigger,
2691
+ Button3 as Button,
2665
2692
  ComposerAttachmentPickerContainer,
2666
2693
  ComposerAttachmentsContainer,
2667
2694
  ComposerBusyProvider,
2668
2695
  ComposerContainer,
2696
+ ComposerLeftSection,
2697
+ ComposerRightSection,
2698
+ ComposerSendButton,
2669
2699
  ComposerShell,
2670
- Dialog,
2671
- DialogClose,
2672
- DialogContent,
2673
- DialogDescription,
2674
- DialogFooter,
2675
- DialogHeader,
2676
- DialogOverlay,
2677
- DialogPortal,
2678
- DialogTitle,
2679
- DialogTrigger,
2700
+ DestructiveButton,
2701
+ default5 as Dialog,
2680
2702
  ErrorToasterProvider,
2681
- IconButton,
2703
+ GhostButton,
2704
+ default2 as IconButton,
2705
+ default3 as IconProvider,
2706
+ LightTooltip2 as LightTooltip,
2682
2707
  Markdown,
2683
2708
  McpAuthContainer,
2684
- McpAuthPrompt,
2685
2709
  MessageActionBar,
2686
2710
  MessageAttachmentsContainer,
2687
- MessageBubble,
2688
2711
  MessageErrorBanner,
2689
2712
  MessageGroup,
2690
2713
  MessageIndicator,
2691
2714
  MessageListSkeleton,
2692
- OpenUIBlock,
2693
- ReasoningCard,
2715
+ MessageTimestamp,
2716
+ default4 as Modal,
2717
+ PrimaryButton,
2694
2718
  ReasoningContainer,
2695
- SandboxArtifactList,
2719
+ SandboxToolCallCard,
2696
2720
  ScrollToBottomButton,
2697
- Skeleton,
2721
+ SecondaryButton,
2722
+ default6 as Skeleton,
2698
2723
  SlotsProvider,
2724
+ SubAgentCard,
2725
+ TertiaryButton,
2699
2726
  Thread,
2700
2727
  ThreadComposerAreaShell,
2701
2728
  ThreadContainer,
@@ -2711,26 +2738,31 @@ export {
2711
2738
  ToastStack,
2712
2739
  TokensProvider,
2713
2740
  ToolApprovalBar,
2741
+ ToolApprovalContainer,
2714
2742
  ToolCallCard,
2715
2743
  ToolCallContainer,
2744
+ ToolCallContentBlock,
2745
+ ToolCallContentBlockContainer,
2716
2746
  ToolGroupCard,
2717
2747
  ToolGroupContainer,
2718
- Tooltip,
2719
- TooltipContent,
2720
- TooltipProvider,
2721
- TooltipTrigger,
2722
2748
  USER_MESSAGE_ATTACHMENT_PREVIEW_REM,
2723
2749
  UserEditComposerContainer,
2724
2750
  UserMessageActionBar,
2751
+ UserMessageBubble,
2725
2752
  UserMessageContainer,
2753
+ UserMessageEdit,
2726
2754
  WelcomeScreen,
2727
- buttonVariants,
2728
2755
  defaultSlots,
2729
2756
  defaultTokens,
2757
+ registerIcons2 as registerIcons,
2758
+ registerImgIcons,
2759
+ threadHasPendingMcpAuth,
2730
2760
  useComposerBusyState,
2761
+ useComposerPauseView,
2731
2762
  useErrorToaster,
2732
2763
  useErrorToasterOptional,
2733
2764
  useSlot,
2765
+ useThemeMode,
2734
2766
  useTokens
2735
2767
  };
2736
2768
  //# sourceMappingURL=index.js.map