@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 { FrontendTools } from '@/components/FrontendTools'
2
- import { ROOT_SELECTOR } from '@/constants/tailwind'
1
+ import { FrontendTools } from "@/components/FrontendTools";
2
+ import { ROOT_SELECTOR } from "@/constants/tailwind";
3
3
  import {
4
4
  isLocalThreadId,
5
5
  useGramThreadListAdapter,
6
- } from '@/hooks/useGramThreadListAdapter'
7
- import { useMCPTools } from '@/hooks/useMCPTools'
8
- import { useToolApproval } from '@/hooks/useToolApproval'
9
- import { getApiUrl } from '@/lib/api'
10
- import { initErrorTracking, trackError } from '@/lib/errorTracking'
11
- import { MODELS } from '@/lib/models'
6
+ } from "@/hooks/useGramThreadListAdapter";
7
+ import { useMCPTools } from "@/hooks/useMCPTools";
8
+ import { useToolApproval } from "@/hooks/useToolApproval";
9
+ import { getApiUrl } from "@/lib/api";
10
+ import { initErrorTracking, trackError } from "@/lib/errorTracking";
11
+ import { MODELS } from "@/lib/models";
12
12
  import {
13
13
  clearFrontendToolApprovalConfig,
14
14
  getEnabledTools,
@@ -17,33 +17,34 @@ import {
17
17
  wrapToolsWithApproval,
18
18
  type ApprovalHelpers,
19
19
  type FrontendTool,
20
- } from '@/lib/tools'
21
- import { cn } from '@/lib/utils'
22
- import { recommended } from '@/plugins'
23
- import { ElementsConfig, Model } from '@/types'
24
- import { Plugin } from '@/types/plugins'
20
+ } from "@/lib/tools";
21
+ import { cn } from "@/lib/utils";
22
+ import { recommended } from "@/plugins";
23
+ import { ElementsConfig, Model } from "@/types";
24
+ import { Plugin } from "@/types/plugins";
25
25
  import {
26
26
  AssistantRuntimeProvider,
27
27
  AssistantTool,
28
28
  useAssistantState,
29
29
  unstable_useRemoteThreadListRuntime as useRemoteThreadListRuntime,
30
- } from '@assistant-ui/react'
30
+ } from "@assistant-ui/react";
31
31
  import {
32
32
  frontendTools as convertFrontendToolsToAISDKTools,
33
33
  useChatRuntime,
34
- } from '@assistant-ui/react-ai-sdk'
35
- import { createOpenRouter } from '@openrouter/ai-sdk-provider'
36
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
34
+ } from "@assistant-ui/react-ai-sdk";
35
+ import { createOpenRouter } from "@openrouter/ai-sdk-provider";
36
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
37
37
  import {
38
38
  convertToModelMessages,
39
39
  createUIMessageStream,
40
+ LanguageModel,
40
41
  smoothStream,
41
42
  stepCountIs,
42
43
  streamText,
43
44
  ToolSet,
44
45
  type ChatTransport,
45
46
  type UIMessage,
46
- } from 'ai'
47
+ } from "ai";
47
48
  import {
48
49
  ReactNode,
49
50
  useCallback,
@@ -51,16 +52,16 @@ import {
51
52
  useMemo,
52
53
  useRef,
53
54
  useState,
54
- } from 'react'
55
- import { useAuth } from '../hooks/useAuth'
56
- import { ChatIdContext } from './ChatIdContext'
55
+ } from "react";
56
+ import { useAuth } from "../hooks/useAuth";
57
+ import { ChatIdContext } from "./ChatIdContext";
57
58
  import {
58
59
  ConnectionStatusProvider,
59
60
  useConnectionStatusOptional,
60
- } from './ConnectionStatusContext'
61
- import { ElementsContext } from './contexts'
62
- import { ToolApprovalProvider } from './ToolApprovalContext'
63
- import { ToolExecutionProvider } from './ToolExecutionContext'
61
+ } from "./ConnectionStatusContext";
62
+ import { ElementsContext } from "./contexts";
63
+ import { ToolApprovalProvider } from "./ToolApprovalContext";
64
+ import { ToolExecutionProvider } from "./ToolExecutionContext";
64
65
 
65
66
  /**
66
67
  * Extracts executable tools from frontend tool definitions.
@@ -69,30 +70,30 @@ import { ToolExecutionProvider } from './ToolExecutionContext'
69
70
  */
70
71
  function extractExecutableTools(
71
72
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
- frontendTools: Record<string, FrontendTool<any, any>> | undefined
73
+ frontendTools: Record<string, FrontendTool<any, any>> | undefined,
73
74
  ): Record<
74
75
  string,
75
76
  { execute?: (args: unknown, options?: unknown) => Promise<unknown> }
76
77
  > {
77
- if (!frontendTools) return {}
78
+ if (!frontendTools) return {};
78
79
 
79
80
  return Object.fromEntries(
80
81
  Object.entries(frontendTools).map(([name, tool]) => {
81
82
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
- const toolDef = (tool as any).unstable_tool
83
+ const toolDef = (tool as any).unstable_tool;
83
84
  return [
84
85
  name,
85
86
  {
86
87
  execute: toolDef?.execute,
87
88
  },
88
- ]
89
- })
90
- )
89
+ ];
90
+ }),
91
+ );
91
92
  }
92
93
 
93
94
  export interface ElementsProviderProps {
94
- children: ReactNode
95
- config: ElementsConfig
95
+ children: ReactNode;
96
+ config: ElementsConfig;
96
97
  }
97
98
 
98
99
  const BASE_SYSTEM_PROMPT = `You are a helpful assistant that can answer questions and help with tasks.
@@ -103,26 +104,26 @@ Some tools have custom visual components that automatically render their results
103
104
  For tools WITHOUT custom components, you should present the data clearly - either as plain text for simple results, or using the UI code block format for structured data like lists of items, categories, or dashboards.
104
105
 
105
106
  UI Widget Guidelines:
106
- IMPORTANT: Only render ONE generative UI widget (chart, dashboard, visualization) per response. Never render multiple widgets in a single message - this causes layout shifts during streaming and overwhelms the user. If you have multiple visualizations to show, render the most important one and explicitly offer to show others as follow-ups (e.g., "Would you like to see a breakdown by status as well?").`
107
+ IMPORTANT: Only render ONE generative UI widget (chart, dashboard, visualization) per response. Never render multiple widgets in a single message - this causes layout shifts during streaming and overwhelms the user. If you have multiple visualizations to show, render the most important one and explicitly offer to show others as follow-ups (e.g., "Would you like to see a breakdown by status as well?").`;
107
108
 
108
109
  function mergeInternalSystemPromptWith(
109
110
  userSystemPrompt: string | undefined,
110
111
  plugins: Plugin[],
111
- toolsWithCustomComponents: string[]
112
+ toolsWithCustomComponents: string[],
112
113
  ) {
113
114
  const customToolsSection =
114
115
  toolsWithCustomComponents.length > 0
115
- ? `\n\nTools with custom visual components (DO NOT render UI widgets for these - they already display rich visuals):\n${toolsWithCustomComponents.map((t) => `- ${t}`).join('\n')}`
116
- : ''
116
+ ? `\n\nTools with custom visual components (DO NOT render UI widgets for these - they already display rich visuals):\n${toolsWithCustomComponents.map((t) => `- ${t}`).join("\n")}`
117
+ : "";
117
118
 
118
119
  return `
119
120
  ${BASE_SYSTEM_PROMPT}${customToolsSection}
120
121
 
121
122
  User-provided System Prompt:
122
- ${userSystemPrompt ?? 'None provided'}
123
+ ${userSystemPrompt ?? "None provided"}
123
124
 
124
125
  Utilities:
125
- ${plugins.map((plugin) => `- ${plugin.language}: ${plugin.prompt}`).join('\n')}`
126
+ ${plugins.map((plugin) => `- ${plugin.language}: ${plugin.prompt}`).join("\n")}`;
126
127
  }
127
128
 
128
129
  /**
@@ -131,9 +132,9 @@ function mergeInternalSystemPromptWith(
131
132
  */
132
133
  function cleanMessagesForModel(messages: UIMessage[]): UIMessage[] {
133
134
  return messages.map((message) => {
134
- const partsArray = message.parts
135
+ const partsArray = message.parts;
135
136
  if (!Array.isArray(partsArray)) {
136
- return message
137
+ return message;
137
138
  }
138
139
 
139
140
  // Process each part: strip providerOptions/providerMetadata and filter reasoning
@@ -141,15 +142,15 @@ function cleanMessagesForModel(messages: UIMessage[]): UIMessage[] {
141
142
  const cleanedParts = partsArray.map((part: any) => {
142
143
  // Strip providerOptions and providerMetadata from all remaining parts
143
144
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
144
- const { callProviderMetadata: _, ...cleanPart } = part
145
- return cleanPart
146
- })
145
+ const { callProviderMetadata: _, ...cleanPart } = part;
146
+ return cleanPart;
147
+ });
147
148
 
148
149
  return {
149
150
  ...message,
150
151
  parts: cleanedParts,
151
- }
152
- })
152
+ };
153
+ });
153
154
  }
154
155
 
155
156
  /**
@@ -157,35 +158,35 @@ function cleanMessagesForModel(messages: UIMessage[]): UIMessage[] {
157
158
  * Delegates to either WithHistory or WithoutHistory based on config.
158
159
  */
159
160
  const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
160
- const apiUrl = getApiUrl(config)
161
+ const apiUrl = getApiUrl(config);
161
162
  const auth = useAuth({
162
163
  auth: config.api,
163
164
  projectSlug: config.projectSlug,
164
- })
165
+ });
165
166
 
166
167
  // Ref to access ensureValidHeaders in async transport without stale closures
167
- const ensureValidHeadersRef = useRef(auth.ensureValidHeaders)
168
- ensureValidHeadersRef.current = auth.ensureValidHeaders
169
- const toolApproval = useToolApproval()
168
+ const ensureValidHeadersRef = useRef(auth.ensureValidHeaders);
169
+ ensureValidHeadersRef.current = auth.ensureValidHeaders;
170
+ const toolApproval = useToolApproval();
170
171
 
171
172
  const [model, setModel] = useState<Model>(
172
- config.model?.defaultModel ?? MODELS[0]
173
- )
173
+ config.model?.defaultModel ?? MODELS[0],
174
+ );
174
175
  const [isExpanded, setIsExpanded] = useState(
175
- config.modal?.defaultExpanded ?? false
176
- )
177
- const [isOpen, setIsOpen] = useState(config.modal?.defaultOpen)
176
+ config.modal?.defaultExpanded ?? false,
177
+ );
178
+ const [isOpen, setIsOpen] = useState(config.modal?.defaultOpen);
178
179
 
179
- const plugins = config.plugins ?? recommended
180
+ const plugins = config.plugins ?? recommended;
180
181
 
181
182
  // Get list of tools that have custom components registered
182
- const toolsWithCustomComponents = Object.keys(config.tools?.components ?? {})
183
+ const toolsWithCustomComponents = Object.keys(config.tools?.components ?? {});
183
184
 
184
185
  const systemPrompt = mergeInternalSystemPromptWith(
185
186
  config.systemPrompt,
186
187
  plugins,
187
- toolsWithCustomComponents
188
- )
188
+ toolsWithCustomComponents,
189
+ );
189
190
 
190
191
  // Initialize error tracking on mount
191
192
  useEffect(() => {
@@ -193,15 +194,15 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
193
194
  enabled: config.errorTracking?.enabled,
194
195
  projectSlug: config.projectSlug,
195
196
  variant: config.variant,
196
- })
197
- }, [])
197
+ });
198
+ }, []);
198
199
 
199
200
  // Generate a stable chat ID for server-side persistence (when history is disabled)
200
201
  // When history is enabled, the thread adapter manages chat IDs instead
201
- const chatIdRef = useRef<string | null>(null)
202
+ const chatIdRef = useRef<string | null>(null);
202
203
 
203
204
  // State to expose the current chat ID via context
204
- const [currentChatId, setCurrentChatId] = useState<string | null>(null)
205
+ const [currentChatId, setCurrentChatId] = useState<string | null>(null);
205
206
 
206
207
  const { data: mcpTools, mcpHeaders } = useMCPTools({
207
208
  auth,
@@ -209,23 +210,23 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
209
210
  environment: config.environment ?? {},
210
211
  toolsToInclude: config.tools?.toolsToInclude,
211
212
  gramEnvironment: config.gramEnvironment,
212
- })
213
+ });
213
214
 
214
215
  // Store approval helpers in ref so they can be used in async contexts
215
216
  const approvalHelpersRef = useRef<ApprovalHelpers>({
216
217
  requestApproval: toolApproval.requestApproval,
217
218
  isToolApproved: toolApproval.isToolApproved,
218
219
  whitelistTool: toolApproval.whitelistTool,
219
- })
220
+ });
220
221
 
221
222
  // Connection status for tracking network failures
222
- const connectionStatus = useConnectionStatusOptional()
223
+ const connectionStatus = useConnectionStatusOptional();
223
224
 
224
225
  approvalHelpersRef.current = {
225
226
  requestApproval: toolApproval.requestApproval,
226
227
  isToolApproved: toolApproval.isToolApproved,
227
228
  whitelistTool: toolApproval.whitelistTool,
228
- }
229
+ };
229
230
 
230
231
  const getApprovalHelpers = useCallback((): ApprovalHelpers => {
231
232
  return {
@@ -235,51 +236,51 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
235
236
  approvalHelpersRef.current.isToolApproved(...args),
236
237
  whitelistTool: (...args) =>
237
238
  approvalHelpersRef.current.whitelistTool(...args),
238
- }
239
- }, [])
239
+ };
240
+ }, []);
240
241
 
241
242
  // Set up frontend tool approval config for runtime checking
242
243
  useEffect(() => {
243
244
  if (config.tools?.toolsRequiringApproval) {
244
245
  setFrontendToolApprovalConfig(
245
246
  getApprovalHelpers(),
246
- config.tools.toolsRequiringApproval
247
- )
247
+ config.tools.toolsRequiringApproval,
248
+ );
248
249
  }
249
250
  return () => {
250
- clearFrontendToolApprovalConfig()
251
- }
252
- }, [config.tools?.toolsRequiringApproval, getApprovalHelpers])
251
+ clearFrontendToolApprovalConfig();
252
+ };
253
+ }, [config.tools?.toolsRequiringApproval, getApprovalHelpers]);
253
254
 
254
255
  // Ref to access runtime from within transport's sendMessages.
255
256
  // This solves a circular dependency: transport needs runtime.thread.getModelContext(),
256
257
  // but runtime is created using transport. The ref gets populated after runtime creation.
257
- const runtimeRef = useRef<ReturnType<typeof useChatRuntime> | null>(null)
258
+ const runtimeRef = useRef<ReturnType<typeof useChatRuntime> | null>(null);
258
259
 
259
260
  // Map to share local thread IDs to UUIDs between adapter and transport (for history mode)
260
- const localIdToUuidMapRef = useRef(new Map<string, string>())
261
+ const localIdToUuidMapRef = useRef(new Map<string, string>());
261
262
 
262
263
  // Ref to store the current thread's remoteId, synced from assistant-ui state.
263
264
  // This is needed because the runtime object doesn't expose threadListItem.remoteId
264
265
  // in a way that's accessible from the transport's sendMessages function.
265
- const currentRemoteIdRef = useRef<string | null>(null)
266
+ const currentRemoteIdRef = useRef<string | null>(null);
266
267
 
267
268
  // Create chat transport configuration
268
269
  const transport = useMemo<ChatTransport<UIMessage>>(
269
270
  () => ({
270
271
  sendMessages: async ({ messages, abortSignal }) => {
271
- const usingCustomModel = !!config.languageModel
272
+ const usingCustomModel = !!config.languageModel;
272
273
 
273
274
  if (auth.isLoading) {
274
- throw new Error('Session is loading')
275
+ throw new Error("Session is loading");
275
276
  }
276
277
 
277
278
  // Ensure the session token is still valid; refresh if expired
278
- const validHeaders = await ensureValidHeadersRef.current()
279
+ const validHeaders = await ensureValidHeadersRef.current();
279
280
 
280
281
  // Get chat ID - use the synced remoteId ref first (history mode),
281
282
  // fall back to generated ID (non-history mode)
282
- let chatId = currentRemoteIdRef.current
283
+ let chatId = currentRemoteIdRef.current;
283
284
 
284
285
  // If we have a valid remoteId (not a local ID), use it directly
285
286
  if (chatId && !isLocalThreadId(chatId)) {
@@ -287,21 +288,21 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
287
288
  } else if (isLocalThreadId(chatId) || !chatId) {
288
289
  // For local thread IDs or no ID, check/generate UUID mapping
289
290
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
290
- const runtimeAny = runtimeRef.current as any
291
- const threadsState = runtimeAny?.threads?.getState?.()
291
+ const runtimeAny = runtimeRef.current as any;
292
+ const threadsState = runtimeAny?.threads?.getState?.();
292
293
  const localThreadId = (threadsState?.mainThreadId ??
293
- threadsState?.threadIds?.[0]) as string | undefined
294
+ threadsState?.threadIds?.[0]) as string | undefined;
294
295
 
295
- const lookupKey = chatId ?? localThreadId
296
+ const lookupKey = chatId ?? localThreadId;
296
297
  if (lookupKey) {
297
- const existingUuid = localIdToUuidMapRef.current.get(lookupKey)
298
+ const existingUuid = localIdToUuidMapRef.current.get(lookupKey);
298
299
  if (existingUuid) {
299
- chatId = existingUuid
300
+ chatId = existingUuid;
300
301
  } else {
301
302
  // Generate a new UUID and store the mapping
302
- const newUuid = crypto.randomUUID()
303
- localIdToUuidMapRef.current.set(lookupKey, newUuid)
304
- chatId = newUuid
303
+ const newUuid = crypto.randomUUID();
304
+ localIdToUuidMapRef.current.set(lookupKey, newUuid);
305
+ chatId = newUuid;
305
306
  }
306
307
  }
307
308
  }
@@ -309,40 +310,40 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
309
310
  if (!chatId) {
310
311
  // Non-history mode fallback - use stable chatIdRef
311
312
  if (!chatIdRef.current) {
312
- chatIdRef.current = crypto.randomUUID()
313
+ chatIdRef.current = crypto.randomUUID();
313
314
  }
314
- chatId = chatIdRef.current
315
+ chatId = chatIdRef.current;
315
316
  }
316
317
 
317
318
  // Mutate the shared headers object so the MCP transport picks up the
318
319
  // chat ID on subsequent tool call requests.
319
320
  if (chatId) {
320
- mcpHeaders['Gram-Chat-ID'] = chatId
321
+ mcpHeaders["Gram-Chat-ID"] = chatId;
321
322
  // Update the context state so consumers can access the current chat ID
322
- setCurrentChatId(chatId)
323
+ setCurrentChatId(chatId);
323
324
  }
324
325
 
325
- const context = runtimeRef.current?.thread.getModelContext()
326
+ const context = runtimeRef.current?.thread.getModelContext();
326
327
  const frontendTools = toAISDKTools(
327
- getEnabledTools(context?.tools ?? {})
328
- )
328
+ getEnabledTools(context?.tools ?? {}),
329
+ );
329
330
 
330
331
  // Include Gram-Chat-ID header for chat persistence and Gram-Environment for environment selection
331
332
  const headersWithChatId = {
332
333
  ...validHeaders,
333
- 'Gram-Chat-ID': chatId,
334
- 'X-Gram-Source': 'elements',
334
+ "Gram-Chat-ID": chatId,
335
+ "X-Gram-Source": "elements",
335
336
  ...config.api?.headers, // We do this after X-Gram-Source so the playground can override it
336
337
  ...(config.gramEnvironment && {
337
- 'Gram-Environment': config.gramEnvironment,
338
+ "Gram-Environment": config.gramEnvironment,
338
339
  }),
339
- }
340
+ };
340
341
 
341
342
  // Update MCP headers with the (possibly refreshed) session token
342
343
  // so mid-stream MCP tool calls use the fresh token
343
- const freshSession = validHeaders['Gram-Chat-Session']
344
+ const freshSession = validHeaders["Gram-Chat-Session"];
344
345
  if (freshSession) {
345
- mcpHeaders['Gram-Chat-Session'] = freshSession
346
+ mcpHeaders["Gram-Chat-Session"] = freshSession;
346
347
  }
347
348
 
348
349
  // Create OpenRouter model (only needed when not using custom model)
@@ -350,43 +351,43 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
350
351
  ? null
351
352
  : createOpenRouter({
352
353
  baseURL: apiUrl,
353
- apiKey: 'unused, but must be set',
354
+ apiKey: "unused, but must be set",
354
355
  headers: headersWithChatId,
355
- })
356
+ });
356
357
 
357
358
  if (config.languageModel) {
358
- console.log('Using custom language model', config.languageModel)
359
+ console.log("Using custom language model", config.languageModel);
359
360
  }
360
361
 
361
362
  // Combine tools - MCP tools only available when not using custom model
362
363
  const combinedTools: ToolSet = {
363
364
  ...mcpTools,
364
365
  ...convertFrontendToolsToAISDKTools(frontendTools),
365
- } as ToolSet
366
+ } as ToolSet;
366
367
 
367
368
  // Wrap tools that require approval
368
369
  const tools = wrapToolsWithApproval(
369
370
  combinedTools,
370
371
  config.tools?.toolsRequiringApproval,
371
- getApprovalHelpers()
372
- )
372
+ getApprovalHelpers(),
373
+ );
373
374
 
374
375
  // Stream the response
375
376
  const modelToUse = config.languageModel
376
377
  ? config.languageModel
377
- : openRouterModel!.chat(model)
378
+ : (openRouterModel!.chat(model) as LanguageModel);
378
379
 
379
380
  try {
380
381
  // This works around AI SDK bug where these fields cause validation failures
381
- const cleanedMessages = cleanMessagesForModel(messages)
382
+ const cleanedMessages = cleanMessagesForModel(messages);
382
383
  // Filter out system messages from the UI state — the system prompt
383
384
  // is already provided via the `system:` parameter to streamText().
384
385
  // Without this, loaded chat history includes the system message which
385
386
  // gets sent alongside the `system:` param, causing duplication.
386
387
  const nonSystemMessages = cleanedMessages.filter(
387
- (m) => m.role !== 'system'
388
- )
389
- const modelMessages = convertToModelMessages(nonSystemMessages)
388
+ (m) => m.role !== "system",
389
+ );
390
+ const modelMessages = convertToModelMessages(nonSystemMessages);
390
391
 
391
392
  const result = streamText({
392
393
  system: systemPrompt,
@@ -397,59 +398,59 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
397
398
  experimental_transform: smoothStream({ delayInMs: 15 }),
398
399
  abortSignal,
399
400
  onError: ({ error }) => {
400
- console.error('Stream error in onError callback:', error)
401
- trackError(error, { source: 'streaming' })
401
+ console.error("Stream error in onError callback:", error);
402
+ trackError(error, { source: "streaming" });
402
403
 
403
404
  // Check if this is a network/connection error
404
405
  const isNetworkError =
405
406
  error instanceof TypeError ||
406
407
  (error instanceof Error &&
407
- (error.message.includes('fetch') ||
408
- error.message.includes('network') ||
409
- error.message.includes('Failed to fetch') ||
410
- error.message.includes('NetworkError') ||
411
- error.message.includes('ECONNREFUSED') ||
412
- error.message.includes('ETIMEDOUT')))
408
+ (error.message.includes("fetch") ||
409
+ error.message.includes("network") ||
410
+ error.message.includes("Failed to fetch") ||
411
+ error.message.includes("NetworkError") ||
412
+ error.message.includes("ECONNREFUSED") ||
413
+ error.message.includes("ETIMEDOUT")));
413
414
 
414
415
  if (isNetworkError) {
415
- connectionStatus?.markDisconnected()
416
+ connectionStatus?.markDisconnected();
416
417
  }
417
418
  },
418
- })
419
+ });
419
420
 
420
421
  // Mark as connected when stream starts successfully
421
- connectionStatus?.markConnected()
422
+ connectionStatus?.markConnected();
422
423
 
423
424
  // This weird construction is necessary to get errors to propagate properly to assistant-ui
424
425
  return createUIMessageStream({
425
426
  execute: ({ writer }) => {
426
- writer.merge(result.toUIMessageStream())
427
+ writer.merge(result.toUIMessageStream());
427
428
  },
428
- })
429
+ });
429
430
  } catch (error) {
430
- console.error('Error creating stream:', error)
431
- trackError(error, { source: 'stream-creation' })
431
+ console.error("Error creating stream:", error);
432
+ trackError(error, { source: "stream-creation" });
432
433
 
433
434
  // Check if this is a network/connection error
434
435
  const isNetworkError =
435
436
  error instanceof TypeError ||
436
437
  (error instanceof Error &&
437
- (error.message.includes('fetch') ||
438
- error.message.includes('network') ||
439
- error.message.includes('Failed to fetch') ||
440
- error.message.includes('NetworkError') ||
441
- error.message.includes('ECONNREFUSED') ||
442
- error.message.includes('ETIMEDOUT')))
438
+ (error.message.includes("fetch") ||
439
+ error.message.includes("network") ||
440
+ error.message.includes("Failed to fetch") ||
441
+ error.message.includes("NetworkError") ||
442
+ error.message.includes("ECONNREFUSED") ||
443
+ error.message.includes("ETIMEDOUT")));
443
444
 
444
445
  if (isNetworkError) {
445
- connectionStatus?.markDisconnected()
446
+ connectionStatus?.markDisconnected();
446
447
  }
447
448
 
448
- throw error
449
+ throw error;
449
450
  }
450
451
  },
451
452
  reconnectToStream: async () => {
452
- throw new Error('Stream reconnection not supported')
453
+ throw new Error("Stream reconnection not supported");
453
454
  },
454
455
  }),
455
456
  [
@@ -462,10 +463,10 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
462
463
  apiUrl,
463
464
  auth.isLoading,
464
465
  connectionStatus,
465
- ]
466
- )
466
+ ],
467
+ );
467
468
 
468
- const historyEnabled = config.history?.enabled ?? false
469
+ const historyEnabled = config.history?.enabled ?? false;
469
470
 
470
471
  // Shared context value for ElementsContext
471
472
  const contextValue = useMemo(
@@ -480,10 +481,10 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
480
481
  plugins,
481
482
  mcpTools,
482
483
  }),
483
- [config, model, isExpanded, isOpen, plugins, mcpTools]
484
- )
484
+ [config, model, isExpanded, isOpen, plugins, mcpTools],
485
+ );
485
486
 
486
- const frontendTools = config.tools?.frontendTools ?? {}
487
+ const frontendTools = config.tools?.frontendTools ?? {};
487
488
 
488
489
  // Create combined executable tools for direct tool execution (ActionButton)
489
490
  // Uses a simplified type that focuses on the execute function
@@ -491,17 +492,17 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
491
492
  string,
492
493
  | { execute?: (args: unknown, options?: unknown) => Promise<unknown> }
493
494
  | undefined
494
- >
495
+ >;
495
496
  const executableTools = useMemo<ExecutableToolSet>(() => {
496
497
  const extractedFrontendTools = extractExecutableTools(
497
- config.tools?.frontendTools
498
- )
498
+ config.tools?.frontendTools,
499
+ );
499
500
  // MCP tools and extracted frontend tools both have execute functions
500
501
  return {
501
502
  ...mcpTools,
502
503
  ...extractedFrontendTools,
503
- } as ExecutableToolSet
504
- }, [mcpTools, config.tools?.frontendTools])
504
+ } as ExecutableToolSet;
505
+ }, [mcpTools, config.tools?.frontendTools]);
505
506
 
506
507
  // Render the appropriate runtime provider based on history config.
507
508
  // We use separate components to avoid conditional hook calls.
@@ -522,7 +523,7 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
522
523
  >
523
524
  {children}
524
525
  </ElementsProviderWithHistory>
525
- )
526
+ );
526
527
  }
527
528
 
528
529
  return (
@@ -536,31 +537,31 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
536
537
  >
537
538
  {children}
538
539
  </ElementsProviderWithoutHistory>
539
- )
540
- }
540
+ );
541
+ };
541
542
 
542
543
  // Shared type for executable tools
543
544
  type ExecutableToolSet = Record<
544
545
  string,
545
546
  | { execute?: (args: unknown, options?: unknown) => Promise<unknown> }
546
547
  | undefined
547
- >
548
+ >;
548
549
 
549
550
  // Separate component for history-enabled mode to avoid conditional hook calls
550
551
  interface ElementsProviderWithHistoryProps {
551
- children: ReactNode
552
- transport: ChatTransport<UIMessage>
553
- apiUrl: string
554
- headers: Record<string, string>
555
- contextValue: React.ContextType<typeof ElementsContext>
556
- runtimeRef: React.RefObject<ReturnType<typeof useChatRuntime> | null>
552
+ children: ReactNode;
553
+ transport: ChatTransport<UIMessage>;
554
+ apiUrl: string;
555
+ headers: Record<string, string>;
556
+ contextValue: React.ContextType<typeof ElementsContext>;
557
+ runtimeRef: React.RefObject<ReturnType<typeof useChatRuntime> | null>;
557
558
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
558
- frontendTools: Record<string, AssistantTool | FrontendTool<any, any>>
559
- localIdToUuidMap: Map<string, string>
560
- currentRemoteIdRef: React.RefObject<string | null>
561
- executableTools: ExecutableToolSet
562
- currentChatId: string | null
563
- setCurrentChatId: (chatId: string | null) => void
559
+ frontendTools: Record<string, AssistantTool | FrontendTool<any, any>>;
560
+ localIdToUuidMap: Map<string, string>;
561
+ currentRemoteIdRef: React.RefObject<string | null>;
562
+ executableTools: ExecutableToolSet;
563
+ currentChatId: string | null;
564
+ setCurrentChatId: (chatId: string | null) => void;
564
565
  }
565
566
 
566
567
  /**
@@ -571,18 +572,18 @@ const ThreadIdSync = ({
571
572
  remoteIdRef,
572
573
  onChatIdChange,
573
574
  }: {
574
- remoteIdRef: React.RefObject<string | null>
575
- onChatIdChange: (chatId: string | null) => void
575
+ remoteIdRef: React.RefObject<string | null>;
576
+ onChatIdChange: (chatId: string | null) => void;
576
577
  }) => {
577
578
  const remoteId = useAssistantState(
578
- ({ threadListItem }) => threadListItem.remoteId ?? null
579
- )
579
+ ({ threadListItem }) => threadListItem.remoteId ?? null,
580
+ );
580
581
  useEffect(() => {
581
- remoteIdRef.current = remoteId
582
- onChatIdChange(remoteId)
583
- }, [remoteId, remoteIdRef, onChatIdChange])
584
- return null
585
- }
582
+ remoteIdRef.current = remoteId;
583
+ onChatIdChange(remoteId);
584
+ }, [remoteId, remoteIdRef, onChatIdChange]);
585
+ return null;
586
+ };
586
587
 
587
588
  const ElementsProviderWithHistory = ({
588
589
  children,
@@ -602,43 +603,43 @@ const ElementsProviderWithHistory = ({
602
603
  apiUrl,
603
604
  headers,
604
605
  localIdToUuidMap,
605
- })
606
- const initialThreadId = contextValue?.config.history?.initialThreadId
606
+ });
607
+ const initialThreadId = contextValue?.config.history?.initialThreadId;
607
608
 
608
609
  // Hook factory for creating the base chat runtime
609
610
  const useChatRuntimeHook = useCallback(() => {
610
- return useChatRuntime({ transport })
611
- }, [transport])
611
+ return useChatRuntime({ transport });
612
+ }, [transport]);
612
613
 
613
614
  const runtime = useRemoteThreadListRuntime({
614
615
  adapter: threadListAdapter,
615
616
  runtimeHook: useChatRuntimeHook,
616
- })
617
+ });
617
618
 
618
619
  // Populate runtimeRef so transport can access thread context
619
620
  useEffect(() => {
620
- runtimeRef.current = runtime as ReturnType<typeof useChatRuntime>
621
- }, [runtime, runtimeRef])
621
+ runtimeRef.current = runtime as ReturnType<typeof useChatRuntime>;
622
+ }, [runtime, runtimeRef]);
622
623
 
623
624
  // Switch to initial thread if provided (for shared chat URLs)
624
- const initialThreadSwitched = useRef(false)
625
+ const initialThreadSwitched = useRef(false);
625
626
  useEffect(() => {
626
627
  if (initialThreadId && !initialThreadSwitched.current) {
627
- initialThreadSwitched.current = true
628
+ initialThreadSwitched.current = true;
628
629
  // Use setTimeout to ensure runtime is fully initialized
629
630
  const timeoutId = setTimeout(() => {
630
631
  runtime.threads.switchToThread(initialThreadId).catch((error) => {
631
- console.error('Failed to switch to initial thread:', error)
632
- })
633
- }, 100)
634
- return () => clearTimeout(timeoutId)
632
+ console.error("Failed to switch to initial thread:", error);
633
+ });
634
+ }, 100);
635
+ return () => clearTimeout(timeoutId);
635
636
  }
636
- }, [initialThreadId, runtime])
637
+ }, [initialThreadId, runtime]);
637
638
 
638
639
  // Get the Provider from our adapter to wrap the content
639
640
  const HistoryProvider =
640
641
  threadListAdapter.unstable_Provider ??
641
- (({ children }: { children: React.ReactNode }) => <>{children}</>)
642
+ (({ children }: { children: React.ReactNode }) => <>{children}</>);
642
643
 
643
644
  return (
644
645
  <AssistantRuntimeProvider runtime={runtime}>
@@ -653,9 +654,9 @@ const ElementsProviderWithHistory = ({
653
654
  <div
654
655
  className={cn(
655
656
  ROOT_SELECTOR,
656
- (contextValue?.config.variant === 'standalone' ||
657
- contextValue?.config.variant === 'sidecar') &&
658
- 'h-full'
657
+ (contextValue?.config.variant === "standalone" ||
658
+ contextValue?.config.variant === "sidecar") &&
659
+ "h-full",
659
660
  )}
660
661
  >
661
662
  {children}
@@ -666,19 +667,19 @@ const ElementsProviderWithHistory = ({
666
667
  </ChatIdContext.Provider>
667
668
  </HistoryProvider>
668
669
  </AssistantRuntimeProvider>
669
- )
670
- }
670
+ );
671
+ };
671
672
 
672
673
  // Separate component for non-history mode to avoid conditional hook calls
673
674
  interface ElementsProviderWithoutHistoryProps {
674
- children: ReactNode
675
- transport: ChatTransport<UIMessage>
676
- contextValue: React.ContextType<typeof ElementsContext>
677
- runtimeRef: React.RefObject<ReturnType<typeof useChatRuntime> | null>
675
+ children: ReactNode;
676
+ transport: ChatTransport<UIMessage>;
677
+ contextValue: React.ContextType<typeof ElementsContext>;
678
+ runtimeRef: React.RefObject<ReturnType<typeof useChatRuntime> | null>;
678
679
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
679
- frontendTools: Record<string, AssistantTool | FrontendTool<any, any>>
680
- executableTools: ExecutableToolSet
681
- currentChatId: string | null
680
+ frontendTools: Record<string, AssistantTool | FrontendTool<any, any>>;
681
+ executableTools: ExecutableToolSet;
682
+ currentChatId: string | null;
682
683
  }
683
684
 
684
685
  const ElementsProviderWithoutHistory = ({
@@ -690,12 +691,12 @@ const ElementsProviderWithoutHistory = ({
690
691
  executableTools,
691
692
  currentChatId,
692
693
  }: ElementsProviderWithoutHistoryProps) => {
693
- const runtime = useChatRuntime({ transport })
694
+ const runtime = useChatRuntime({ transport });
694
695
 
695
696
  // Populate runtimeRef so transport can access thread context
696
697
  useEffect(() => {
697
- runtimeRef.current = runtime
698
- }, [runtime, runtimeRef])
698
+ runtimeRef.current = runtime;
699
+ }, [runtime, runtimeRef]);
699
700
 
700
701
  return (
701
702
  <AssistantRuntimeProvider runtime={runtime}>
@@ -705,9 +706,9 @@ const ElementsProviderWithoutHistory = ({
705
706
  <div
706
707
  className={cn(
707
708
  ROOT_SELECTOR,
708
- (contextValue?.config.variant === 'standalone' ||
709
- contextValue?.config.variant === 'sidecar') &&
710
- 'h-full'
709
+ (contextValue?.config.variant === "standalone" ||
710
+ contextValue?.config.variant === "sidecar") &&
711
+ "h-full",
711
712
  )}
712
713
  >
713
714
  {children}
@@ -717,10 +718,10 @@ const ElementsProviderWithoutHistory = ({
717
718
  </ElementsContext.Provider>
718
719
  </ChatIdContext.Provider>
719
720
  </AssistantRuntimeProvider>
720
- )
721
- }
721
+ );
722
+ };
722
723
 
723
- const queryClient = new QueryClient()
724
+ const queryClient = new QueryClient();
724
725
 
725
726
  export const ElementsProvider = (props: ElementsProviderProps) => {
726
727
  return (
@@ -731,5 +732,5 @@ export const ElementsProvider = (props: ElementsProviderProps) => {
731
732
  </ToolApprovalProvider>
732
733
  </ConnectionStatusProvider>
733
734
  </QueryClientProvider>
734
- )
735
- }
735
+ );
736
+ };