@gram-ai/elements 1.27.4 → 1.27.6

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 (278) hide show
  1. package/README.md +72 -60
  2. package/README.typedoc.md +6 -6
  3. package/bin/cli.js +74 -74
  4. package/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
  5. package/dist/{compat-shims-BPJ7Q68c.js → compat-shims-DxtUrORi.js} +4 -2
  6. package/dist/compat-shims-DxtUrORi.js.map +1 -0
  7. package/dist/components/ShareButton/index.d.ts +2 -2
  8. package/dist/components/assistant-ui/message-feedback.d.ts +1 -1
  9. package/dist/components/assistant-ui/tooltip-icon-button.d.ts +2 -2
  10. package/dist/components/ui/avatar.d.ts +2 -2
  11. package/dist/components/ui/button.d.ts +1 -1
  12. package/dist/components/ui/calendar.d.ts +1 -1
  13. package/dist/components/ui/collapsible.d.ts +1 -1
  14. package/dist/components/ui/dialog.d.ts +4 -4
  15. package/dist/components/ui/popover.d.ts +2 -2
  16. package/dist/components/ui/skeleton.d.ts +1 -1
  17. package/dist/components/ui/time-range-picker.d.ts +1 -1
  18. package/dist/components/ui/tool-ui.d.ts +7 -7
  19. package/dist/components/ui/tooltip.d.ts +2 -2
  20. package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
  21. package/dist/elements.cjs +1 -1
  22. package/dist/elements.css +1 -1
  23. package/dist/elements.js +2 -2
  24. package/dist/hooks/useDensity.d.ts +73 -73
  25. package/dist/hooks/useMCPTools.d.ts +1 -1
  26. package/dist/hooks/useRadius.d.ts +1 -1
  27. package/dist/{index-KSX4Qjip.cjs → index-A17b62wR.cjs} +10 -10
  28. package/dist/index-A17b62wR.cjs.map +1 -0
  29. package/dist/{index-BpJstUh1.cjs → index-C4bFBGfl.cjs} +4 -4
  30. package/dist/{index-BpJstUh1.cjs.map → index-C4bFBGfl.cjs.map} +1 -1
  31. package/dist/{index-CUitXazZ.js → index-D93pV0_o.js} +55 -55
  32. package/dist/{index-CUitXazZ.js.map → index-D93pV0_o.js.map} +1 -1
  33. package/dist/{index-D0bAYNQy.js → index-Dm2wLFTN.js} +304 -282
  34. package/dist/index-Dm2wLFTN.js.map +1 -0
  35. package/dist/lib/cassette.d.ts +4 -4
  36. package/dist/lib/errorTracking.d.ts +1 -1
  37. package/dist/lib/messageConverter.d.ts +1 -1
  38. package/dist/lib/models.d.ts +1 -1
  39. package/dist/plugins/chart/ui/bar-chart.d.ts +1 -1
  40. package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
  41. package/dist/plugins/generative-ui/ui/accordion.d.ts +1 -1
  42. package/dist/plugins/generative-ui/ui/action-button.d.ts +2 -2
  43. package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +1 -1
  44. package/dist/plugins/generative-ui/ui/alert.d.ts +4 -4
  45. package/dist/plugins/generative-ui/ui/avatar.d.ts +5 -5
  46. package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
  47. package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -2
  48. package/dist/plugins/generative-ui/ui/button.d.ts +2 -2
  49. package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +2 -2
  50. package/dist/plugins/generative-ui/ui/card.d.ts +8 -8
  51. package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
  52. package/dist/plugins/generative-ui/ui/data-table.d.ts +2 -2
  53. package/dist/plugins/generative-ui/ui/dialog.d.ts +3 -3
  54. package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +3 -3
  55. package/dist/plugins/generative-ui/ui/grid.d.ts +3 -3
  56. package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +1 -1
  57. package/dist/plugins/generative-ui/ui/input.d.ts +2 -2
  58. package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
  59. package/dist/plugins/generative-ui/ui/metric.d.ts +3 -3
  60. package/dist/plugins/generative-ui/ui/pagination.d.ts +6 -6
  61. package/dist/plugins/generative-ui/ui/popover.d.ts +4 -4
  62. package/dist/plugins/generative-ui/ui/progress.d.ts +2 -2
  63. package/dist/plugins/generative-ui/ui/radio-group.d.ts +1 -1
  64. package/dist/plugins/generative-ui/ui/select.d.ts +2 -2
  65. package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
  66. package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
  67. package/dist/plugins/generative-ui/ui/stack.d.ts +6 -6
  68. package/dist/plugins/generative-ui/ui/switch.d.ts +2 -2
  69. package/dist/plugins/generative-ui/ui/table.d.ts +9 -9
  70. package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +1 -1
  71. package/dist/plugins/generative-ui/ui/tabs.d.ts +1 -1
  72. package/dist/plugins/generative-ui/ui/text.d.ts +3 -3
  73. package/dist/plugins/generative-ui/ui/textarea.d.ts +2 -2
  74. package/dist/plugins/generative-ui/ui/tooltip.d.ts +1 -1
  75. package/dist/plugins.cjs +1 -1
  76. package/dist/plugins.js +1 -1
  77. package/dist/{profiler-CyzxBxVz.cjs → profiler-Cbbf4eEX.cjs} +2 -2
  78. package/dist/{profiler-CyzxBxVz.cjs.map → profiler-Cbbf4eEX.cjs.map} +1 -1
  79. package/dist/{profiler-BFkhZRxj.js → profiler-mca4IXaY.js} +2 -2
  80. package/dist/{profiler-BFkhZRxj.js.map → profiler-mca4IXaY.js.map} +1 -1
  81. package/dist/react-shim.js +1 -1
  82. package/dist/server/express.cjs.map +1 -1
  83. package/dist/server/express.js.map +1 -1
  84. package/dist/{startRecording-C-PPAs_Z.js → startRecording-BCafdS7B.js} +2 -2
  85. package/dist/{startRecording-C-PPAs_Z.js.map → startRecording-BCafdS7B.js.map} +1 -1
  86. package/dist/{startRecording-Dq92sEHf.cjs → startRecording-Eb5f7wqP.cjs} +2 -2
  87. package/dist/{startRecording-Dq92sEHf.cjs.map → startRecording-Eb5f7wqP.cjs.map} +1 -1
  88. package/dist/types/index.d.ts +4 -4
  89. package/package.json +1 -5
  90. package/src/compat-plugin.ts +14 -14
  91. package/src/compat-shims.ts +33 -31
  92. package/src/compat.test.ts +48 -48
  93. package/src/compat.ts +6 -6
  94. package/src/components/Chat/index.tsx +17 -17
  95. package/src/components/Chat/stories/Charts.stories.tsx +98 -98
  96. package/src/components/Chat/stories/Composer.stories.tsx +15 -15
  97. package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +44 -44
  98. package/src/components/Chat/stories/CustomComponents.stories.tsx +17 -17
  99. package/src/components/Chat/stories/Density.stories.tsx +20 -20
  100. package/src/components/Chat/stories/ErrorBoundary.stories.tsx +47 -47
  101. package/src/components/Chat/stories/FrontendTools.stories.tsx +39 -39
  102. package/src/components/Chat/stories/GenerativeUI.stories.tsx +48 -48
  103. package/src/components/Chat/stories/MessageFeedback.stories.tsx +52 -52
  104. package/src/components/Chat/stories/Modal.stories.tsx +28 -28
  105. package/src/components/Chat/stories/Model.stories.tsx +11 -11
  106. package/src/components/Chat/stories/Radius.stories.tsx +20 -20
  107. package/src/components/Chat/stories/Sidecar.stories.tsx +13 -13
  108. package/src/components/Chat/stories/StyleIsolation.stories.tsx +11 -11
  109. package/src/components/Chat/stories/Theme.stories.tsx +25 -25
  110. package/src/components/Chat/stories/Thread.stories.tsx +25 -25
  111. package/src/components/Chat/stories/ToolApproval.stories.tsx +55 -55
  112. package/src/components/Chat/stories/ToolMentions.stories.tsx +17 -17
  113. package/src/components/Chat/stories/Tools.stories.tsx +88 -88
  114. package/src/components/Chat/stories/Variants.stories.tsx +32 -32
  115. package/src/components/Chat/stories/Welcome.stories.tsx +14 -14
  116. package/src/components/ChatHistory.tsx +7 -7
  117. package/src/components/FrontendTools/index.tsx +5 -5
  118. package/src/components/Replay.stories.tsx +157 -157
  119. package/src/components/Replay.tsx +76 -73
  120. package/src/components/ShadowRoot.tsx +40 -40
  121. package/src/components/ShareButton/index.tsx +32 -32
  122. package/src/components/assistant-ui/assistant-modal.tsx +92 -87
  123. package/src/components/assistant-ui/assistant-sidecar.tsx +35 -35
  124. package/src/components/assistant-ui/attachment.tsx +80 -80
  125. package/src/components/assistant-ui/connection-status-indicator.tsx +33 -33
  126. package/src/components/assistant-ui/error-boundary.tsx +34 -34
  127. package/src/components/assistant-ui/follow-on-suggestions.tsx +26 -26
  128. package/src/components/assistant-ui/markdown-text.tsx +69 -69
  129. package/src/components/assistant-ui/mentioned-tools-badges.tsx +38 -38
  130. package/src/components/assistant-ui/message-feedback.tsx +57 -50
  131. package/src/components/assistant-ui/reasoning.tsx +83 -83
  132. package/src/components/assistant-ui/thread-list.tsx +45 -45
  133. package/src/components/assistant-ui/thread.tsx +278 -278
  134. package/src/components/assistant-ui/tool-fallback.tsx +37 -37
  135. package/src/components/assistant-ui/tool-group.tsx +26 -26
  136. package/src/components/assistant-ui/tool-mention-autocomplete.tsx +122 -122
  137. package/src/components/assistant-ui/tooltip-icon-button.tsx +18 -18
  138. package/src/components/ui/avatar.tsx +12 -12
  139. package/src/components/ui/button.tsx +12 -12
  140. package/src/components/ui/buttonVariants.ts +17 -17
  141. package/src/components/ui/calendar.tsx +106 -106
  142. package/src/components/ui/charts.stories.tsx +56 -56
  143. package/src/components/ui/collapsible.tsx +5 -5
  144. package/src/components/ui/dialog.tsx +30 -30
  145. package/src/components/ui/generative-ui.stories.tsx +200 -200
  146. package/src/components/ui/generative-ui.tsx +26 -26
  147. package/src/components/ui/popover.tsx +14 -14
  148. package/src/components/ui/skeleton.tsx +5 -5
  149. package/src/components/ui/time-range-picker.stories.tsx +80 -80
  150. package/src/components/ui/time-range-picker.tsx +248 -246
  151. package/src/components/ui/tool-ui.stories.tsx +37 -37
  152. package/src/components/ui/tool-ui.tsx +221 -215
  153. package/src/components/ui/tooltip.tsx +15 -15
  154. package/src/constants/tailwind.ts +1 -1
  155. package/src/contexts/ChatIdContext.tsx +7 -7
  156. package/src/contexts/ConnectionStatusContext.tsx +64 -64
  157. package/src/contexts/ElementsProvider.tsx +214 -213
  158. package/src/contexts/ReplayContext.ts +3 -3
  159. package/src/contexts/ToolApprovalContext.tsx +54 -54
  160. package/src/contexts/ToolExecutionContext.tsx +34 -34
  161. package/src/contexts/contexts.ts +7 -7
  162. package/src/contexts/portal-container-context.ts +2 -2
  163. package/src/contexts/portal-container.tsx +7 -7
  164. package/src/embedded.ts +1 -1
  165. package/src/global.css +25 -25
  166. package/src/hooks/useAuth.ts +72 -72
  167. package/src/hooks/useDensity.ts +79 -79
  168. package/src/hooks/useElements.ts +6 -6
  169. package/src/hooks/useExpanded.ts +12 -12
  170. package/src/hooks/useFollowOnSuggestions.ts +83 -83
  171. package/src/hooks/useGramThreadListAdapter.tsx +99 -99
  172. package/src/hooks/useMCPTools.ts +47 -47
  173. package/src/hooks/useModel.ts +14 -14
  174. package/src/hooks/usePluginComponents.ts +11 -11
  175. package/src/hooks/usePortalContainer.ts +5 -5
  176. package/src/hooks/useRadius.ts +23 -23
  177. package/src/hooks/useRecordCassette.ts +34 -34
  178. package/src/hooks/useSession.ts +11 -11
  179. package/src/hooks/useThemeProps.ts +13 -13
  180. package/src/hooks/useThreadId.ts +4 -4
  181. package/src/hooks/useToolApproval.ts +7 -7
  182. package/src/hooks/useToolMentions.ts +40 -40
  183. package/src/index.ts +26 -26
  184. package/src/lib/api.test.ts +61 -61
  185. package/src/lib/api.ts +4 -3
  186. package/src/lib/auth.ts +13 -13
  187. package/src/lib/cassette.ts +84 -84
  188. package/src/lib/easing.ts +1 -1
  189. package/src/lib/errorTracking.config.ts +5 -5
  190. package/src/lib/errorTracking.ts +29 -29
  191. package/src/lib/generative-ui.ts +7 -7
  192. package/src/lib/humanize.ts +3 -3
  193. package/src/lib/messageConverter.test.ts +130 -127
  194. package/src/lib/messageConverter.ts +196 -196
  195. package/src/lib/models.ts +28 -20
  196. package/src/lib/token.test.ts +56 -56
  197. package/src/lib/token.ts +14 -14
  198. package/src/lib/tool-mentions.ts +45 -45
  199. package/src/lib/tools.ts +66 -62
  200. package/src/lib/utils.ts +5 -5
  201. package/src/lib.d.ts +1 -1
  202. package/src/plugins/README.md +5 -5
  203. package/src/plugins/chart/catalog.ts +18 -18
  204. package/src/plugins/chart/chart.test.ts +31 -31
  205. package/src/plugins/chart/component.tsx +34 -34
  206. package/src/plugins/chart/index.ts +4 -4
  207. package/src/plugins/chart/ui/area-chart.tsx +42 -42
  208. package/src/plugins/chart/ui/bar-chart.tsx +46 -46
  209. package/src/plugins/chart/ui/donut-chart.tsx +48 -48
  210. package/src/plugins/chart/ui/index.ts +7 -7
  211. package/src/plugins/chart/ui/line-chart.tsx +43 -43
  212. package/src/plugins/chart/ui/pie-chart.tsx +44 -44
  213. package/src/plugins/chart/ui/radar-chart.tsx +33 -33
  214. package/src/plugins/chart/ui/scatter-chart.tsx +43 -43
  215. package/src/plugins/components/MacOSWindowFrame.tsx +15 -15
  216. package/src/plugins/components/PluginLoadingState.tsx +10 -10
  217. package/src/plugins/components/index.ts +1 -1
  218. package/src/plugins/generative-ui/catalog.ts +54 -54
  219. package/src/plugins/generative-ui/component.tsx +85 -85
  220. package/src/plugins/generative-ui/index.ts +4 -4
  221. package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +16 -16
  222. package/src/plugins/generative-ui/ui/accordion.tsx +16 -16
  223. package/src/plugins/generative-ui/ui/action-button.tsx +28 -28
  224. package/src/plugins/generative-ui/ui/alert-wrapper.tsx +8 -8
  225. package/src/plugins/generative-ui/ui/alert.tsx +20 -20
  226. package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +7 -7
  227. package/src/plugins/generative-ui/ui/avatar.tsx +30 -30
  228. package/src/plugins/generative-ui/ui/badge.tsx +22 -22
  229. package/src/plugins/generative-ui/ui/button-wrapper.tsx +12 -12
  230. package/src/plugins/generative-ui/ui/button.tsx +28 -28
  231. package/src/plugins/generative-ui/ui/card-wrapper.tsx +8 -8
  232. package/src/plugins/generative-ui/ui/card.tsx +27 -27
  233. package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +9 -9
  234. package/src/plugins/generative-ui/ui/checkbox.tsx +9 -9
  235. package/src/plugins/generative-ui/ui/data-table.tsx +8 -8
  236. package/src/plugins/generative-ui/ui/dialog.tsx +31 -31
  237. package/src/plugins/generative-ui/ui/dropdown-menu.tsx +44 -44
  238. package/src/plugins/generative-ui/ui/grid.tsx +12 -12
  239. package/src/plugins/generative-ui/ui/index.ts +40 -40
  240. package/src/plugins/generative-ui/ui/input-wrapper.tsx +11 -11
  241. package/src/plugins/generative-ui/ui/input.tsx +9 -9
  242. package/src/plugins/generative-ui/ui/label.tsx +8 -8
  243. package/src/plugins/generative-ui/ui/list.tsx +11 -11
  244. package/src/plugins/generative-ui/ui/metric.tsx +23 -23
  245. package/src/plugins/generative-ui/ui/pagination.tsx +28 -28
  246. package/src/plugins/generative-ui/ui/popover.tsx +21 -21
  247. package/src/plugins/generative-ui/ui/progress.tsx +13 -13
  248. package/src/plugins/generative-ui/ui/radio-group.tsx +12 -12
  249. package/src/plugins/generative-ui/ui/select-wrapper.tsx +7 -7
  250. package/src/plugins/generative-ui/ui/select.tsx +37 -37
  251. package/src/plugins/generative-ui/ui/separator.tsx +9 -9
  252. package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +10 -10
  253. package/src/plugins/generative-ui/ui/skeleton.tsx +5 -5
  254. package/src/plugins/generative-ui/ui/stack.tsx +28 -28
  255. package/src/plugins/generative-ui/ui/switch.tsx +11 -11
  256. package/src/plugins/generative-ui/ui/table.tsx +32 -32
  257. package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +11 -11
  258. package/src/plugins/generative-ui/ui/tabs.tsx +26 -26
  259. package/src/plugins/generative-ui/ui/text.tsx +12 -12
  260. package/src/plugins/generative-ui/ui/textarea.tsx +7 -7
  261. package/src/plugins/generative-ui/ui/tooltip.tsx +12 -12
  262. package/src/plugins/index.ts +7 -7
  263. package/src/react-shim.ts +6 -6
  264. package/src/server/bun.ts +12 -12
  265. package/src/server/core.ts +25 -25
  266. package/src/server/express.ts +17 -15
  267. package/src/server/fastify.ts +14 -14
  268. package/src/server/hono.ts +9 -9
  269. package/src/server/nextjs.ts +12 -12
  270. package/src/server/tanstack-start.ts +12 -12
  271. package/src/server.ts +27 -27
  272. package/src/storybook.d.ts +4 -4
  273. package/src/types/index.ts +124 -124
  274. package/src/types/plugins.ts +7 -7
  275. package/src/vite-env.d.ts +12 -12
  276. package/dist/compat-shims-BPJ7Q68c.js.map +0 -1
  277. package/dist/index-D0bAYNQy.js.map +0 -1
  278. package/dist/index-KSX4Qjip.cjs.map +0 -1
@@ -1,14 +1,14 @@
1
- import { cn } from '@/lib/utils'
1
+ import { cn } from "@/lib/utils";
2
2
  import {
3
3
  useAssistantState,
4
4
  type ToolCallMessagePartComponent,
5
- } from '@assistant-ui/react'
6
- import { useToolApproval } from '@/hooks/useToolApproval'
5
+ } from "@assistant-ui/react";
6
+ import { useToolApproval } from "@/hooks/useToolApproval";
7
7
  import {
8
8
  ToolUI,
9
9
  type ToolStatus,
10
10
  type ContentItem,
11
- } from '@/components/ui/tool-ui'
11
+ } from "@/components/ui/tool-ui";
12
12
 
13
13
  export const ToolFallback: ToolCallMessagePartComponent = ({
14
14
  toolName,
@@ -22,47 +22,47 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
22
22
  whitelistTool,
23
23
  confirmPendingApproval,
24
24
  rejectPendingApproval,
25
- } = useToolApproval()
25
+ } = useToolApproval();
26
26
 
27
27
  // Check if this specific tool call has a pending approval
28
- const pendingApproval = pendingApprovals.get(toolCallId)
29
- const message = useAssistantState(({ message }) => message)
30
- const toolParts = message.parts.filter((part) => part.type === 'tool-call')
28
+ const pendingApproval = pendingApprovals.get(toolCallId);
29
+ const message = useAssistantState(({ message }) => message);
30
+ const toolParts = message.parts.filter((part) => part.type === "tool-call");
31
31
  const matchingMessagePartIndex = toolParts.findIndex(
32
- (part) => part.toolCallId === toolCallId
33
- )
32
+ (part) => part.toolCallId === toolCallId,
33
+ );
34
34
 
35
35
  const handleApproveOnce = () => {
36
- confirmPendingApproval(toolCallId)
37
- }
36
+ confirmPendingApproval(toolCallId);
37
+ };
38
38
 
39
39
  const handleApproveForSession = () => {
40
- whitelistTool(toolName)
41
- confirmPendingApproval(toolCallId)
42
- }
40
+ whitelistTool(toolName);
41
+ confirmPendingApproval(toolCallId);
42
+ };
43
43
 
44
44
  const handleDeny = () => {
45
- rejectPendingApproval(toolCallId)
46
- }
45
+ rejectPendingApproval(toolCallId);
46
+ };
47
47
 
48
48
  // Map assistant-ui status to ToolUI status
49
49
  const getToolStatus = (): ToolStatus => {
50
- if (pendingApproval) return 'approval'
51
- if (status.type === 'incomplete') return 'error'
52
- if (status.type === 'complete') {
50
+ if (pendingApproval) return "approval";
51
+ if (status.type === "incomplete") return "error";
52
+ if (status.type === "complete") {
53
53
  // Check if the result indicates an error (e.g., tool was denied)
54
54
  if (
55
55
  result &&
56
- typeof result === 'object' &&
57
- 'isError' in result &&
56
+ typeof result === "object" &&
57
+ "isError" in result &&
58
58
  result.isError
59
59
  ) {
60
- return 'error'
60
+ return "error";
61
61
  }
62
- return 'complete'
62
+ return "complete";
63
63
  }
64
- return 'running'
65
- }
64
+ return "running";
65
+ };
66
66
 
67
67
  // Parse result to structured content if possible
68
68
  const getResult = ():
@@ -70,28 +70,28 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
70
70
  | Record<string, unknown>
71
71
  | { content: ContentItem[] }
72
72
  | undefined => {
73
- if (result === undefined) return undefined
73
+ if (result === undefined) return undefined;
74
74
  // Check if it's structured content with a content array
75
75
  if (
76
- typeof result === 'object' &&
76
+ typeof result === "object" &&
77
77
  result !== null &&
78
- 'content' in result &&
78
+ "content" in result &&
79
79
  Array.isArray((result as { content: unknown }).content)
80
80
  ) {
81
- return result as { content: ContentItem[] }
81
+ return result as { content: ContentItem[] };
82
82
  }
83
83
  // Otherwise return as-is (string or object)
84
- if (typeof result === 'string') return result
85
- return result as Record<string, unknown>
86
- }
84
+ if (typeof result === "string") return result;
85
+ return result as Record<string, unknown>;
86
+ };
87
87
 
88
88
  return (
89
89
  <div
90
90
  className={cn(
91
- 'aui-tool-fallback-root flex w-full flex-col',
91
+ "aui-tool-fallback-root flex w-full flex-col",
92
92
  matchingMessagePartIndex !== -1 &&
93
93
  matchingMessagePartIndex !== toolParts.length - 1 &&
94
- 'border-b'
94
+ "border-b",
95
95
  )}
96
96
  >
97
97
  <ToolUI
@@ -107,5 +107,5 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
107
107
  className="rounded-none border-0"
108
108
  />
109
109
  </div>
110
- )
111
- }
110
+ );
111
+ };
@@ -1,9 +1,9 @@
1
- import { cn } from '@/lib/utils'
2
- import { useAssistantState } from '@assistant-ui/react'
3
- import { useMemo, type FC, type PropsWithChildren } from 'react'
4
- import { useElements } from '@/hooks/useElements'
5
- import { humanizeToolName } from '@/lib/humanize'
6
- import { ToolUIGroup } from '@/components/ui/tool-ui'
1
+ import { cn } from "@/lib/utils";
2
+ import { useAssistantState } from "@assistant-ui/react";
3
+ import { useMemo, type FC, type PropsWithChildren } from "react";
4
+ import { useElements } from "@/hooks/useElements";
5
+ import { humanizeToolName } from "@/lib/humanize";
6
+ import { ToolUIGroup } from "@/components/ui/tool-ui";
7
7
 
8
8
  export const ToolGroup: FC<
9
9
  PropsWithChildren<{ startIndex: number; endIndex: number }>
@@ -11,48 +11,48 @@ export const ToolGroup: FC<
11
11
  // startIndex/endIndex are inclusive indices into message.parts.
12
12
  // assistant-ui only groups consecutive tool-call parts, so every part
13
13
  // in the range is a tool-call — the count is simply the range size.
14
- const toolCount = endIndex - startIndex + 1
14
+ const toolCount = endIndex - startIndex + 1;
15
15
 
16
16
  const firstToolName = useAssistantState(({ message }) => {
17
- const part = message.parts[startIndex]
18
- return part?.type === 'tool-call' ? part.toolName : undefined
19
- })
17
+ const part = message.parts[startIndex];
18
+ return part?.type === "tool-call" ? part.toolName : undefined;
19
+ });
20
20
  const anyMessagePartsAreRunning = useAssistantState(({ message }) => {
21
21
  for (let i = startIndex; i <= endIndex; i++) {
22
- if (message.parts[i]?.status?.type === 'running') return true
22
+ if (message.parts[i]?.status?.type === "running") return true;
23
23
  }
24
- return false
25
- })
24
+ return false;
25
+ });
26
26
 
27
- const { config } = useElements()
28
- const defaultExpanded = config.tools?.expandToolGroupsByDefault ?? false
27
+ const { config } = useElements();
28
+ const defaultExpanded = config.tools?.expandToolGroupsByDefault ?? false;
29
29
 
30
30
  const groupTitle = useMemo(() => {
31
- if (toolCount === 0) return 'No tools called'
31
+ if (toolCount === 0) return "No tools called";
32
32
  if (toolCount === 1) {
33
33
  return firstToolName
34
34
  ? `Calling ${humanizeToolName(firstToolName)}...`
35
- : 'Calling tool...'
35
+ : "Calling tool...";
36
36
  }
37
37
  return anyMessagePartsAreRunning
38
38
  ? `Calling ${toolCount} tools...`
39
- : `Executed ${toolCount} tools`
40
- }, [toolCount, firstToolName, anyMessagePartsAreRunning])
39
+ : `Executed ${toolCount} tools`;
40
+ }, [toolCount, firstToolName, anyMessagePartsAreRunning]);
41
41
 
42
42
  // If there's a custom component for the single tool, render children directly
43
43
  if (firstToolName && config.tools?.components?.[firstToolName]) {
44
- return children
44
+ return children;
45
45
  }
46
46
 
47
47
  // For single tool calls, render without the group wrapper
48
48
  if (toolCount === 1) {
49
49
  return (
50
- <div className={cn('my-4 w-full max-w-xl')}>
51
- <div className="border-border bg-card overflow-hidden rounded-lg border">
50
+ <div className={cn("my-4 w-full max-w-xl")}>
51
+ <div className="overflow-hidden rounded-lg border border-border bg-card">
52
52
  {children}
53
53
  </div>
54
54
  </div>
55
- )
55
+ );
56
56
  }
57
57
 
58
58
  // For multiple tool calls, use the group component
@@ -60,11 +60,11 @@ export const ToolGroup: FC<
60
60
  <div className="my-4 w-full max-w-xl">
61
61
  <ToolUIGroup
62
62
  title={groupTitle}
63
- status={anyMessagePartsAreRunning ? 'running' : 'complete'}
63
+ status={anyMessagePartsAreRunning ? "running" : "complete"}
64
64
  defaultExpanded={defaultExpanded}
65
65
  >
66
66
  {children}
67
67
  </ToolUIGroup>
68
68
  </div>
69
- )
70
- }
69
+ );
70
+ };
@@ -1,25 +1,25 @@
1
- import { FC, useCallback, useEffect, useRef, useState } from 'react'
2
- import { Wrench } from 'lucide-react'
3
- import * as m from 'motion/react-m'
4
-
5
- import { cn } from '@/lib/utils'
6
- import { useDensity } from '@/hooks/useDensity'
7
- import { useRadius } from '@/hooks/useRadius'
8
- import { EASE_OUT_QUINT } from '@/lib/easing'
1
+ import { FC, useCallback, useEffect, useRef, useState } from "react";
2
+ import { Wrench } from "lucide-react";
3
+ import * as m from "motion/react-m";
4
+
5
+ import { cn } from "@/lib/utils";
6
+ import { useDensity } from "@/hooks/useDensity";
7
+ import { useRadius } from "@/hooks/useRadius";
8
+ import { EASE_OUT_QUINT } from "@/lib/easing";
9
9
  import {
10
10
  MentionableTool,
11
11
  detectMentionContext,
12
12
  filterToolsByQuery,
13
13
  insertToolMention,
14
- } from '@/lib/tool-mentions'
14
+ } from "@/lib/tool-mentions";
15
15
 
16
16
  export interface ToolMentionAutocompleteProps {
17
- tools: MentionableTool[]
18
- value: string
19
- cursorPosition: number
20
- onValueChange: (value: string, cursorPosition: number) => void
21
- textareaRef: React.RefObject<HTMLTextAreaElement | null>
22
- className?: string
17
+ tools: MentionableTool[];
18
+ value: string;
19
+ cursorPosition: number;
20
+ onValueChange: (value: string, cursorPosition: number) => void;
21
+ textareaRef: React.RefObject<HTMLTextAreaElement | null>;
22
+ className?: string;
23
23
  }
24
24
 
25
25
  export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
@@ -30,112 +30,112 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
30
30
  textareaRef,
31
31
  className,
32
32
  }) => {
33
- const [selectedIndex, setSelectedIndex] = useState(0)
34
- const [isVisible, setIsVisible] = useState(false)
35
- const [filteredTools, setFilteredTools] = useState<MentionableTool[]>([])
33
+ const [selectedIndex, setSelectedIndex] = useState(0);
34
+ const [isVisible, setIsVisible] = useState(false);
35
+ const [filteredTools, setFilteredTools] = useState<MentionableTool[]>([]);
36
36
  const [mentionContext, setMentionContext] = useState<{
37
- atPosition: number
38
- query: string
39
- } | null>(null)
37
+ atPosition: number;
38
+ query: string;
39
+ } | null>(null);
40
40
 
41
- const containerRef = useRef<HTMLDivElement>(null)
42
- const d = useDensity()
43
- const r = useRadius()
41
+ const containerRef = useRef<HTMLDivElement>(null);
42
+ const d = useDensity();
43
+ const r = useRadius();
44
44
 
45
45
  useEffect(() => {
46
- const context = detectMentionContext(value, cursorPosition)
46
+ const context = detectMentionContext(value, cursorPosition);
47
47
 
48
48
  if (context.isInMention && tools.length > 0) {
49
- const filtered = filterToolsByQuery(tools, context.query)
50
- setFilteredTools(filtered)
51
- setIsVisible(filtered.length > 0)
49
+ const filtered = filterToolsByQuery(tools, context.query);
50
+ setFilteredTools(filtered);
51
+ setIsVisible(filtered.length > 0);
52
52
  setMentionContext({
53
53
  atPosition: context.atPosition,
54
54
  query: context.query,
55
- })
56
- setSelectedIndex(0)
55
+ });
56
+ setSelectedIndex(0);
57
57
  } else {
58
- setIsVisible(false)
59
- setMentionContext(null)
58
+ setIsVisible(false);
59
+ setMentionContext(null);
60
60
  }
61
- }, [value, cursorPosition, tools])
61
+ }, [value, cursorPosition, tools]);
62
62
 
63
63
  const selectTool = useCallback(
64
64
  (tool: MentionableTool) => {
65
- if (!mentionContext) return
65
+ if (!mentionContext) return;
66
66
 
67
67
  const result = insertToolMention(
68
68
  value,
69
69
  tool.name,
70
70
  mentionContext.atPosition,
71
- cursorPosition
72
- )
71
+ cursorPosition,
72
+ );
73
73
 
74
- onValueChange(result.text, result.cursorPosition)
75
- setIsVisible(false)
74
+ onValueChange(result.text, result.cursorPosition);
75
+ setIsVisible(false);
76
76
  },
77
- [mentionContext, value, cursorPosition, onValueChange, textareaRef]
78
- )
77
+ [mentionContext, value, cursorPosition, onValueChange, textareaRef],
78
+ );
79
79
 
80
80
  useEffect(() => {
81
- if (!isVisible) return
81
+ if (!isVisible) return;
82
82
 
83
83
  const handleKeyDown = (e: KeyboardEvent) => {
84
84
  switch (e.key) {
85
- case 'ArrowDown':
86
- e.preventDefault()
87
- e.stopPropagation()
88
- setSelectedIndex((prev) => (prev + 1) % filteredTools.length)
89
- break
90
- case 'ArrowUp':
91
- e.preventDefault()
92
- e.stopPropagation()
85
+ case "ArrowDown":
86
+ e.preventDefault();
87
+ e.stopPropagation();
88
+ setSelectedIndex((prev) => (prev + 1) % filteredTools.length);
89
+ break;
90
+ case "ArrowUp":
91
+ e.preventDefault();
92
+ e.stopPropagation();
93
93
  setSelectedIndex(
94
- (prev) => (prev - 1 + filteredTools.length) % filteredTools.length
95
- )
96
- break
97
- case 'Enter':
98
- case 'Tab':
99
- e.preventDefault()
100
- e.stopPropagation()
94
+ (prev) => (prev - 1 + filteredTools.length) % filteredTools.length,
95
+ );
96
+ break;
97
+ case "Enter":
98
+ case "Tab":
99
+ e.preventDefault();
100
+ e.stopPropagation();
101
101
  if (filteredTools[selectedIndex]) {
102
- selectTool(filteredTools[selectedIndex])
102
+ selectTool(filteredTools[selectedIndex]);
103
103
  }
104
- break
105
- case 'Escape':
106
- e.preventDefault()
107
- e.stopPropagation()
108
- setIsVisible(false)
109
- break
104
+ break;
105
+ case "Escape":
106
+ e.preventDefault();
107
+ e.stopPropagation();
108
+ setIsVisible(false);
109
+ break;
110
110
  }
111
- }
111
+ };
112
112
 
113
- const textarea = textareaRef.current
113
+ const textarea = textareaRef.current;
114
114
  if (textarea) {
115
- textarea.addEventListener('keydown', handleKeyDown, { capture: true })
115
+ textarea.addEventListener("keydown", handleKeyDown, { capture: true });
116
116
  return () =>
117
- textarea.removeEventListener('keydown', handleKeyDown, {
117
+ textarea.removeEventListener("keydown", handleKeyDown, {
118
118
  capture: true,
119
- })
119
+ });
120
120
  }
121
- }, [isVisible, filteredTools, selectedIndex, selectTool, textareaRef])
121
+ }, [isVisible, filteredTools, selectedIndex, selectTool, textareaRef]);
122
122
 
123
123
  // Scroll selected item into view
124
124
  useEffect(() => {
125
- if (!isVisible) return
126
- const container = containerRef.current
127
- if (!container) return
125
+ if (!isVisible) return;
126
+ const container = containerRef.current;
127
+ if (!container) return;
128
128
 
129
129
  const selectedItem = container.querySelector(
130
- `[data-index="${selectedIndex}"]`
131
- ) as HTMLElement
130
+ `[data-index="${selectedIndex}"]`,
131
+ ) as HTMLElement;
132
132
  if (selectedItem) {
133
- selectedItem.scrollIntoView({ block: 'nearest' })
133
+ selectedItem.scrollIntoView({ block: "nearest" });
134
134
  }
135
- }, [selectedIndex, isVisible])
135
+ }, [selectedIndex, isVisible]);
136
136
 
137
137
  useEffect(() => {
138
- if (!isVisible) return
138
+ if (!isVisible) return;
139
139
 
140
140
  const handleClickOutside = (e: MouseEvent) => {
141
141
  if (
@@ -144,62 +144,62 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
144
144
  textareaRef.current &&
145
145
  !textareaRef.current.contains(e.target as Node)
146
146
  ) {
147
- setIsVisible(false)
147
+ setIsVisible(false);
148
148
  }
149
- }
149
+ };
150
150
 
151
- document.addEventListener('mousedown', handleClickOutside)
152
- return () => document.removeEventListener('mousedown', handleClickOutside)
153
- }, [isVisible, textareaRef])
151
+ document.addEventListener("mousedown", handleClickOutside);
152
+ return () => document.removeEventListener("mousedown", handleClickOutside);
153
+ }, [isVisible, textareaRef]);
154
154
 
155
155
  // When autocomplete is visible, modify composer styles and position autocomplete to match composer width
156
156
  useEffect(() => {
157
- const textarea = textareaRef.current
158
- if (!textarea) return
157
+ const textarea = textareaRef.current;
158
+ if (!textarea) return;
159
159
 
160
- const composer = textarea.closest('.aui-composer-root') as HTMLElement
161
- if (!composer) return
160
+ const composer = textarea.closest(".aui-composer-root") as HTMLElement;
161
+ if (!composer) return;
162
162
 
163
163
  const updateStyles = () => {
164
- const autocomplete = containerRef.current
165
- if (!autocomplete) return
164
+ const autocomplete = containerRef.current;
165
+ if (!autocomplete) return;
166
166
 
167
167
  if (isVisible) {
168
168
  // Modify composer to connect with autocomplete
169
- composer.style.borderTopColor = 'var(--ring)'
170
- composer.style.borderTopLeftRadius = '0'
171
- composer.style.borderTopRightRadius = '0'
169
+ composer.style.borderTopColor = "var(--ring)";
170
+ composer.style.borderTopLeftRadius = "0";
171
+ composer.style.borderTopRightRadius = "0";
172
172
 
173
173
  // Position autocomplete to match composer width
174
- const composerRect = composer.getBoundingClientRect()
175
- const autocompleteParent = autocomplete.offsetParent as HTMLElement
174
+ const composerRect = composer.getBoundingClientRect();
175
+ const autocompleteParent = autocomplete.offsetParent as HTMLElement;
176
176
  if (autocompleteParent) {
177
- const parentRect = autocompleteParent.getBoundingClientRect()
178
- autocomplete.style.left = `${composerRect.left - parentRect.left}px`
179
- autocomplete.style.right = 'auto'
180
- autocomplete.style.width = `${composerRect.width}px`
177
+ const parentRect = autocompleteParent.getBoundingClientRect();
178
+ autocomplete.style.left = `${composerRect.left - parentRect.left}px`;
179
+ autocomplete.style.right = "auto";
180
+ autocomplete.style.width = `${composerRect.width}px`;
181
181
  }
182
182
  }
183
- }
183
+ };
184
184
 
185
185
  if (isVisible) {
186
186
  // Use requestAnimationFrame to ensure DOM is updated
187
- requestAnimationFrame(updateStyles)
187
+ requestAnimationFrame(updateStyles);
188
188
  } else {
189
- composer.style.borderTopColor = ''
190
- composer.style.borderTopLeftRadius = ''
191
- composer.style.borderTopRightRadius = ''
189
+ composer.style.borderTopColor = "";
190
+ composer.style.borderTopLeftRadius = "";
191
+ composer.style.borderTopRightRadius = "";
192
192
  }
193
193
 
194
194
  return () => {
195
- composer.style.borderTopColor = ''
196
- composer.style.borderTopLeftRadius = ''
197
- composer.style.borderTopRightRadius = ''
198
- }
199
- }, [isVisible, textareaRef])
195
+ composer.style.borderTopColor = "";
196
+ composer.style.borderTopLeftRadius = "";
197
+ composer.style.borderTopRightRadius = "";
198
+ };
199
+ }, [isVisible, textareaRef]);
200
200
 
201
201
  if (!isVisible || filteredTools.length === 0) {
202
- return null
202
+ return null;
203
203
  }
204
204
 
205
205
  return (
@@ -210,9 +210,9 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
210
210
  exit={{ opacity: 0, y: 8 }}
211
211
  transition={{ duration: 0.15, ease: EASE_OUT_QUINT }}
212
212
  className={cn(
213
- 'aui-tool-mention-autocomplete border-ring bg-background absolute bottom-full z-50 max-h-[220px] overflow-clip overflow-y-auto overscroll-contain rounded-br-none! rounded-bl-none! border border-b-0 shadow-xs',
214
- r('xl'),
215
- className
213
+ "aui-tool-mention-autocomplete absolute bottom-full z-50 max-h-[220px] overflow-clip overflow-y-auto overscroll-contain rounded-br-none! rounded-bl-none! border border-b-0 border-ring bg-background shadow-xs",
214
+ r("xl"),
215
+ className,
216
216
  )}
217
217
  >
218
218
  <div className="flex flex-col gap-1">
@@ -222,15 +222,15 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
222
222
  type="button"
223
223
  data-index={index}
224
224
  className={cn(
225
- 'aui-tool-mention-item flex w-full items-center gap-2 text-left transition-colors',
226
- d('p-sm'),
227
- 'hover:bg-accent hover:text-accent-foreground',
228
- index === selectedIndex && 'bg-accent text-accent-foreground'
225
+ "aui-tool-mention-item flex w-full items-center gap-2 text-left transition-colors",
226
+ d("p-sm"),
227
+ "hover:bg-accent hover:text-accent-foreground",
228
+ index === selectedIndex && "bg-accent text-accent-foreground",
229
229
  )}
230
230
  onClick={(e) => {
231
- e.preventDefault()
232
- e.stopPropagation()
233
- selectTool(tool)
231
+ e.preventDefault();
232
+ e.stopPropagation();
233
+ selectTool(tool);
234
234
  }}
235
235
  onMouseEnter={() => setSelectedIndex(index)}
236
236
  >
@@ -238,7 +238,7 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
238
238
  <div className="min-w-0 flex-1">
239
239
  <div className="text-sm font-medium">{tool.name}</div>
240
240
  {tool.description && (
241
- <div className="text-muted-foreground line-clamp-2 text-xs">
241
+ <div className="line-clamp-2 text-xs text-muted-foreground">
242
242
  {tool.description}
243
243
  </div>
244
244
  )}
@@ -247,7 +247,7 @@ export const ToolMentionAutocomplete: FC<ToolMentionAutocompleteProps> = ({
247
247
  ))}
248
248
  </div>
249
249
  </m.div>
250
- )
251
- }
250
+ );
251
+ };
252
252
 
253
- export default ToolMentionAutocomplete
253
+ export default ToolMentionAutocomplete;
@@ -1,21 +1,21 @@
1
- 'use client'
1
+ "use client";
2
2
 
3
- import { ComponentPropsWithRef, forwardRef } from 'react'
4
- import { Slottable } from '@radix-ui/react-slot'
3
+ import { ComponentPropsWithRef, forwardRef } from "react";
4
+ import { Slottable } from "@radix-ui/react-slot";
5
5
 
6
6
  import {
7
7
  Tooltip,
8
8
  TooltipContent,
9
9
  TooltipTrigger,
10
- } from '@/components/ui/tooltip'
11
- import { Button } from '@/components/ui/button'
12
- import { cn } from '@/lib/utils'
10
+ } from "@/components/ui/tooltip";
11
+ import { Button } from "@/components/ui/button";
12
+ import { cn } from "@/lib/utils";
13
13
 
14
14
  type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
15
- tooltip: string
16
- side?: 'top' | 'bottom' | 'left' | 'right'
17
- align?: 'start' | 'center' | 'end'
18
- }
15
+ tooltip: string;
16
+ side?: "top" | "bottom" | "left" | "right";
17
+ align?: "start" | "center" | "end";
18
+ };
19
19
 
20
20
  export const TooltipIconButton = forwardRef<
21
21
  HTMLButtonElement,
@@ -25,12 +25,12 @@ export const TooltipIconButton = forwardRef<
25
25
  {
26
26
  children,
27
27
  tooltip,
28
- side = 'bottom',
29
- align = 'center',
28
+ side = "bottom",
29
+ align = "center",
30
30
  className,
31
31
  ...rest
32
32
  },
33
- ref
33
+ ref,
34
34
  ) => {
35
35
  return (
36
36
  <Tooltip>
@@ -39,7 +39,7 @@ export const TooltipIconButton = forwardRef<
39
39
  variant="ghost"
40
40
  size="icon"
41
41
  {...rest}
42
- className={cn('aui-button-icon size-6 p-1', className)}
42
+ className={cn("aui-button-icon size-6 p-1", className)}
43
43
  ref={ref}
44
44
  >
45
45
  <Slottable>{children}</Slottable>
@@ -50,8 +50,8 @@ export const TooltipIconButton = forwardRef<
50
50
  {tooltip}
51
51
  </TooltipContent>
52
52
  </Tooltip>
53
- )
54
- }
55
- )
53
+ );
54
+ },
55
+ );
56
56
 
57
- TooltipIconButton.displayName = 'TooltipIconButton'
57
+ TooltipIconButton.displayName = "TooltipIconButton";