@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
package/src/lib/tools.ts CHANGED
@@ -1,12 +1,12 @@
1
- import type { ToolsFilter } from '@/types'
1
+ import type { ToolsFilter } from "@/types";
2
2
  import {
3
3
  AssistantToolProps,
4
4
  Tool,
5
5
  makeAssistantTool,
6
- } from '@assistant-ui/react'
7
- import { JSONSchema7, ToolSet, type ToolCallOptions } from 'ai'
8
- import { FC } from 'react'
9
- import z from 'zod'
6
+ } from "@assistant-ui/react";
7
+ import { JSONSchema7, ToolSet, type ToolCallOptions } from "ai";
8
+ import { FC } from "react";
9
+ import z from "zod";
10
10
 
11
11
  /**
12
12
  * Converts from assistant-ui tool format to the AI SDK tool shape
@@ -21,9 +21,9 @@ export const toAISDKTools = (tools: Record<string, Tool>) => {
21
21
  ? z.toJSONSchema(tool.parameters)
22
22
  : tool.parameters) as JSONSchema7,
23
23
  },
24
- ])
25
- )
26
- }
24
+ ]),
25
+ );
26
+ };
27
27
 
28
28
  /**
29
29
  * Returns only frontend tools that are enabled
@@ -31,10 +31,10 @@ export const toAISDKTools = (tools: Record<string, Tool>) => {
31
31
  export const getEnabledTools = (tools: Record<string, Tool>) => {
32
32
  return Object.fromEntries(
33
33
  Object.entries(tools).filter(
34
- ([, tool]) => !tool.disabled && tool.type !== 'backend'
35
- )
36
- )
37
- }
34
+ ([, tool]) => !tool.disabled && tool.type !== "backend",
35
+ ),
36
+ );
37
+ };
38
38
 
39
39
  /**
40
40
  * A frontend tool is a tool that is defined by the user and can be used in the chat.
@@ -42,37 +42,37 @@ export const getEnabledTools = (tools: Record<string, Tool>) => {
42
42
  export type FrontendTool<TArgs extends Record<string, unknown>, TResult> = FC<
43
43
  AssistantToolProps<TArgs, TResult>
44
44
  > & {
45
- unstable_tool: AssistantToolProps<TArgs, TResult>
46
- }
45
+ unstable_tool: AssistantToolProps<TArgs, TResult>;
46
+ };
47
47
 
48
48
  /**
49
49
  * Module-level approval config that gets set by ElementsProvider at runtime.
50
50
  * This allows defineFrontendTool to check approval status during execute.
51
51
  */
52
52
  let approvalConfig: {
53
- helpers: ApprovalHelpers
54
- requiresApproval: (toolName: string) => boolean
55
- } | null = null
53
+ helpers: ApprovalHelpers;
54
+ requiresApproval: (toolName: string) => boolean;
55
+ } | null = null;
56
56
 
57
57
  /**
58
58
  * Sets the approval configuration. Called by ElementsProvider.
59
59
  */
60
60
  export function setFrontendToolApprovalConfig(
61
61
  helpers: ApprovalHelpers,
62
- toolsRequiringApproval: ToolsFilter
62
+ toolsRequiringApproval: ToolsFilter,
63
63
  ): void {
64
- const requiresApproval = createRequiresApprovalFn(toolsRequiringApproval)
64
+ const requiresApproval = createRequiresApprovalFn(toolsRequiringApproval);
65
65
  approvalConfig = {
66
66
  helpers,
67
67
  requiresApproval,
68
- }
68
+ };
69
69
  }
70
70
 
71
71
  /**
72
72
  * Clears the approval configuration. Called when ElementsProvider unmounts.
73
73
  */
74
74
  export function clearFrontendToolApprovalConfig(): void {
75
- approvalConfig = null
75
+ approvalConfig = null;
76
76
  }
77
77
 
78
78
  /**
@@ -80,18 +80,18 @@ export function clearFrontendToolApprovalConfig(): void {
80
80
  * Handles both array and function-based configurations.
81
81
  */
82
82
  function createRequiresApprovalFn(
83
- toolsRequiringApproval: ToolsFilter | undefined
83
+ toolsRequiringApproval: ToolsFilter | undefined,
84
84
  ): (toolName: string) => boolean {
85
85
  if (!toolsRequiringApproval) {
86
- return () => false
86
+ return () => false;
87
87
  }
88
88
 
89
- if (typeof toolsRequiringApproval === 'function') {
90
- return (toolName: string) => toolsRequiringApproval({ toolName })
89
+ if (typeof toolsRequiringApproval === "function") {
90
+ return (toolName: string) => toolsRequiringApproval({ toolName });
91
91
  }
92
92
 
93
- const approvalSet = new Set(toolsRequiringApproval)
94
- return (toolName: string) => approvalSet.has(toolName)
93
+ const approvalSet = new Set(toolsRequiringApproval);
94
+ return (toolName: string) => approvalSet.has(toolName);
95
95
  }
96
96
 
97
97
  /**
@@ -102,42 +102,46 @@ export const defineFrontendTool = <
102
102
  TResult,
103
103
  >(
104
104
  tool: Tool,
105
- name: string
105
+ name: string,
106
106
  ): FrontendTool<TArgs, TResult> => {
107
107
  type ToolExecutionContext = Parameters<
108
- NonNullable<Tool<Record<string, unknown>, void>['execute']>
109
- >[1]
108
+ NonNullable<Tool<Record<string, unknown>, void>["execute"]>
109
+ >[1];
110
110
  return makeAssistantTool({
111
111
  ...tool,
112
112
  execute: async (args: TArgs, context: ToolExecutionContext) => {
113
113
  // Check if this tool requires approval at runtime
114
114
  if (approvalConfig?.requiresApproval(name)) {
115
- const { helpers } = approvalConfig
116
- const toolCallId = context.toolCallId ?? ''
115
+ const { helpers } = approvalConfig;
116
+ const toolCallId = context.toolCallId ?? "";
117
117
 
118
118
  // Check if already approved (user chose "Approve always" previously)
119
119
  if (!helpers.isToolApproved(name)) {
120
- const approved = await helpers.requestApproval(name, toolCallId, args)
120
+ const approved = await helpers.requestApproval(
121
+ name,
122
+ toolCallId,
123
+ args,
124
+ );
121
125
 
122
126
  if (!approved) {
123
127
  return {
124
128
  content: [
125
129
  {
126
- type: 'text',
130
+ type: "text",
127
131
  text: `Tool "${name}" execution was denied by the user. Please acknowledge this and continue without using this tool's result.`,
128
132
  },
129
133
  ],
130
134
  isError: true,
131
- } as TResult
135
+ } as TResult;
132
136
  }
133
137
  }
134
138
  }
135
139
 
136
- return tool.execute?.(args, context)
140
+ return tool.execute?.(args, context);
137
141
  },
138
142
  toolName: name,
139
- } as AssistantToolProps<TArgs, TResult>)
140
- }
143
+ } as AssistantToolProps<TArgs, TResult>);
144
+ };
141
145
 
142
146
  /**
143
147
  * Helpers for requesting and tracking tool approval state.
@@ -146,10 +150,10 @@ export interface ApprovalHelpers {
146
150
  requestApproval: (
147
151
  toolName: string,
148
152
  toolCallId: string,
149
- args: unknown
150
- ) => Promise<boolean>
151
- isToolApproved: (toolName: string) => boolean
152
- whitelistTool: (toolName: string) => void
153
+ args: unknown,
154
+ ) => Promise<boolean>;
155
+ isToolApproved: (toolName: string) => boolean;
156
+ whitelistTool: (toolName: string) => void;
153
157
  }
154
158
 
155
159
  /**
@@ -158,10 +162,10 @@ export interface ApprovalHelpers {
158
162
  export function wrapToolsWithApproval(
159
163
  tools: ToolSet,
160
164
  toolsRequiringApproval: ToolsFilter | undefined,
161
- approvalHelpers: ApprovalHelpers
165
+ approvalHelpers: ApprovalHelpers,
162
166
  ): ToolSet {
163
167
  if (!toolsRequiringApproval) {
164
- return tools
168
+ return tools;
165
169
  }
166
170
 
167
171
  // Handle empty array case
@@ -169,20 +173,20 @@ export function wrapToolsWithApproval(
169
173
  Array.isArray(toolsRequiringApproval) &&
170
174
  toolsRequiringApproval.length === 0
171
175
  ) {
172
- return tools
176
+ return tools;
173
177
  }
174
178
 
175
- const requiresApproval = createRequiresApprovalFn(toolsRequiringApproval)
179
+ const requiresApproval = createRequiresApprovalFn(toolsRequiringApproval);
176
180
 
177
181
  return Object.fromEntries(
178
182
  Object.entries(tools).map(([name, tool]) => {
179
183
  if (!requiresApproval(name)) {
180
- return [name, tool]
184
+ return [name, tool];
181
185
  }
182
186
 
183
- const originalExecute = tool.execute
187
+ const originalExecute = tool.execute;
184
188
  if (!originalExecute) {
185
- return [name, tool]
189
+ return [name, tool];
186
190
  }
187
191
 
188
192
  return [
@@ -192,36 +196,36 @@ export function wrapToolsWithApproval(
192
196
  execute: async (args: unknown, options?: ToolCallOptions) => {
193
197
  const opts = (options ?? {}) as Parameters<
194
198
  typeof originalExecute
195
- >[1]
199
+ >[1];
196
200
  // Extract toolCallId from options
197
201
  const toolCallId =
198
- (opts as { toolCallId?: string }).toolCallId ?? ''
202
+ (opts as { toolCallId?: string }).toolCallId ?? "";
199
203
 
200
204
  // Check if already approved (user chose "Approve always" previously)
201
205
  if (approvalHelpers.isToolApproved(name)) {
202
206
  return originalExecute(
203
207
  args,
204
- opts as Parameters<typeof originalExecute>[1]
205
- )
208
+ opts as Parameters<typeof originalExecute>[1],
209
+ );
206
210
  }
207
211
 
208
212
  // Request approval using the actual toolCallId from the stream
209
213
  const approved = await approvalHelpers.requestApproval(
210
214
  name,
211
215
  toolCallId,
212
- args
213
- )
216
+ args,
217
+ );
214
218
 
215
219
  if (!approved) {
216
220
  return {
217
221
  content: [
218
222
  {
219
- type: 'text',
223
+ type: "text",
220
224
  text: `Tool "${name}" execution was denied by the user. Please acknowledge this and continue without using this tool's result.`,
221
225
  },
222
226
  ],
223
227
  isError: true,
224
- }
228
+ };
225
229
  }
226
230
 
227
231
  // Note: Tool is marked as approved via the UI when user clicks "Approve always"
@@ -229,11 +233,11 @@ export function wrapToolsWithApproval(
229
233
 
230
234
  return originalExecute(
231
235
  args,
232
- opts as Parameters<typeof originalExecute>[1]
233
- )
236
+ opts as Parameters<typeof originalExecute>[1],
237
+ );
234
238
  },
235
239
  },
236
- ]
237
- })
238
- ) as ToolSet
240
+ ];
241
+ }),
242
+ ) as ToolSet;
239
243
  }
package/src/lib/utils.ts CHANGED
@@ -1,16 +1,16 @@
1
- import { clsx, type ClassValue } from 'clsx'
2
- import { twMerge } from 'tailwind-merge'
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
3
 
4
4
  export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
5
+ return twMerge(clsx(inputs));
6
6
  }
7
7
 
8
8
  export function assertNever(value: unknown): never {
9
- throw new Error(`Unexpected value: ${value}`)
9
+ throw new Error(`Unexpected value: ${value}`);
10
10
  }
11
11
 
12
12
  export function assert(condition: unknown, message: string): asserts condition {
13
13
  if (!condition) {
14
- throw new Error(message)
14
+ throw new Error(message);
15
15
  }
16
16
  }
package/src/lib.d.ts CHANGED
@@ -1 +1 @@
1
- type FIXME<T, S extends string> = (T & S) | T
1
+ type FIXME<T, S extends string> = (T & S) | T;
@@ -19,19 +19,19 @@ A plugin is defined by the following TypeScript interface:
19
19
  ```typescript
20
20
  interface Plugin {
21
21
  // The language identifier for the code fence (e.g., "vega", "mermaid", "d3")
22
- language: string
22
+ language: string;
23
23
 
24
24
  // Instructions for the LLM on how to use this plugin
25
- prompt: string
25
+ prompt: string;
26
26
 
27
27
  // Your custom React component that renders the code block
28
- SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>
28
+ SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>;
29
29
 
30
30
  // Optional: Custom header component for the code block
31
- CodeHeader?: ComponentType<CodeHeaderProps> | null
31
+ CodeHeader?: ComponentType<CodeHeaderProps> | null;
32
32
 
33
33
  // Optional: Whether to override existing plugins with the same language
34
- overrideExisting?: boolean
34
+ overrideExisting?: boolean;
35
35
  }
36
36
  ```
37
37
 
@@ -1,5 +1,5 @@
1
- import { createCatalog } from '@json-render/core'
2
- import { z } from 'zod'
1
+ import { createCatalog } from "@json-render/core";
2
+ import { z } from "zod";
3
3
 
4
4
  /**
5
5
  * Data point schema - common structure for all chart types
@@ -8,7 +8,7 @@ const dataPointSchema = z.object({
8
8
  label: z.string(),
9
9
  value: z.number(),
10
10
  color: z.string().optional(),
11
- })
11
+ });
12
12
 
13
13
  /**
14
14
  * Multi-series data point for line/area charts
@@ -17,7 +17,7 @@ const seriesDataPointSchema = z
17
17
  .object({
18
18
  label: z.string(),
19
19
  })
20
- .catchall(z.number())
20
+ .catchall(z.number());
21
21
 
22
22
  /**
23
23
  * Chart Catalog
@@ -26,19 +26,19 @@ const seriesDataPointSchema = z
26
26
  * Uses Recharts under the hood for rendering.
27
27
  */
28
28
  export const chartCatalog = createCatalog({
29
- name: 'chart',
29
+ name: "chart",
30
30
  components: {
31
31
  BarChart: {
32
32
  props: z.object({
33
33
  title: z.string().optional(),
34
34
  data: z.array(dataPointSchema),
35
- layout: z.enum(['vertical', 'horizontal']).optional(),
35
+ layout: z.enum(["vertical", "horizontal"]).optional(),
36
36
  showGrid: z.boolean().optional(),
37
37
  showLegend: z.boolean().optional(),
38
38
  className: z.string().optional(),
39
39
  }),
40
40
  description:
41
- 'Bar chart for comparing categorical data. Use vertical for few categories, horizontal for many or long labels.',
41
+ "Bar chart for comparing categorical data. Use vertical for few categories, horizontal for many or long labels.",
42
42
  },
43
43
 
44
44
  LineChart: {
@@ -53,7 +53,7 @@ export const chartCatalog = createCatalog({
53
53
  className: z.string().optional(),
54
54
  }),
55
55
  description:
56
- 'Line chart for showing trends over time or continuous data. Supports multiple series.',
56
+ "Line chart for showing trends over time or continuous data. Supports multiple series.",
57
57
  },
58
58
 
59
59
  AreaChart: {
@@ -67,7 +67,7 @@ export const chartCatalog = createCatalog({
67
67
  className: z.string().optional(),
68
68
  }),
69
69
  description:
70
- 'Area chart for showing volume/magnitude over time. Use stacked for part-to-whole relationships.',
70
+ "Area chart for showing volume/magnitude over time. Use stacked for part-to-whole relationships.",
71
71
  },
72
72
 
73
73
  PieChart: {
@@ -79,7 +79,7 @@ export const chartCatalog = createCatalog({
79
79
  className: z.string().optional(),
80
80
  }),
81
81
  description:
82
- 'Pie chart for showing proportions of a whole. Best for 2-6 categories.',
82
+ "Pie chart for showing proportions of a whole. Best for 2-6 categories.",
83
83
  },
84
84
 
85
85
  DonutChart: {
@@ -93,7 +93,7 @@ export const chartCatalog = createCatalog({
93
93
  className: z.string().optional(),
94
94
  }),
95
95
  description:
96
- 'Donut chart (pie with center hole). Good for showing a key metric in the center.',
96
+ "Donut chart (pie with center hole). Good for showing a key metric in the center.",
97
97
  },
98
98
 
99
99
  ScatterChart: {
@@ -106,7 +106,7 @@ export const chartCatalog = createCatalog({
106
106
  label: z.string().optional(),
107
107
  size: z.number().optional(),
108
108
  color: z.string().optional(),
109
- })
109
+ }),
110
110
  ),
111
111
  xLabel: z.string().optional(),
112
112
  yLabel: z.string().optional(),
@@ -114,7 +114,7 @@ export const chartCatalog = createCatalog({
114
114
  className: z.string().optional(),
115
115
  }),
116
116
  description:
117
- 'Scatter plot for showing correlation between two variables.',
117
+ "Scatter plot for showing correlation between two variables.",
118
118
  },
119
119
 
120
120
  RadarChart: {
@@ -125,17 +125,17 @@ export const chartCatalog = createCatalog({
125
125
  className: z.string().optional(),
126
126
  }),
127
127
  description:
128
- 'Radar/spider chart for comparing multiple attributes. Best for 3-8 dimensions.',
128
+ "Radar/spider chart for comparing multiple attributes. Best for 3-8 dimensions.",
129
129
  },
130
130
  },
131
- })
131
+ });
132
132
 
133
133
  export type ChartCatalogComponentProps = typeof chartCatalog extends {
134
- components: infer C
134
+ components: infer C;
135
135
  }
136
136
  ? {
137
137
  [K in keyof C]: C[K] extends { props: infer P }
138
138
  ? z.infer<P extends z.ZodType ? P : never>
139
- : never
139
+ : never;
140
140
  }
141
- : never
141
+ : never;
@@ -1,66 +1,66 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { parse, View, Warn } from 'vega'
3
- import { expressionInterpreter } from 'vega-interpreter'
1
+ import { describe, it, expect } from "vitest";
2
+ import { parse, View, Warn } from "vega";
3
+ import { expressionInterpreter } from "vega-interpreter";
4
4
 
5
- describe('ChartRenderer CSP compliance', () => {
6
- it('renders a chart using vega-interpreter without eval', async () => {
5
+ describe("ChartRenderer CSP compliance", () => {
6
+ it("renders a chart using vega-interpreter without eval", async () => {
7
7
  const spec = {
8
- $schema: 'https://vega.github.io/schema/vega/v5.json',
8
+ $schema: "https://vega.github.io/schema/vega/v5.json",
9
9
  width: 400,
10
10
  height: 200,
11
11
  data: [
12
12
  {
13
- name: 'table',
13
+ name: "table",
14
14
  values: [
15
- { category: 'A', amount: 28 },
16
- { category: 'B', amount: 55 },
15
+ { category: "A", amount: 28 },
16
+ { category: "B", amount: 55 },
17
17
  ],
18
18
  },
19
19
  ],
20
20
  marks: [
21
21
  {
22
- type: 'rect',
23
- from: { data: 'table' },
22
+ type: "rect",
23
+ from: { data: "table" },
24
24
  encode: {
25
25
  enter: {
26
- x: { scale: 'xscale', field: 'category' },
27
- width: { scale: 'xscale', band: 1 },
28
- y: { scale: 'yscale', field: 'amount' },
29
- y2: { scale: 'yscale', value: 0 },
26
+ x: { scale: "xscale", field: "category" },
27
+ width: { scale: "xscale", band: 1 },
28
+ y: { scale: "yscale", field: "amount" },
29
+ y2: { scale: "yscale", value: 0 },
30
30
  },
31
31
  },
32
32
  },
33
33
  ],
34
34
  scales: [
35
35
  {
36
- name: 'xscale',
37
- type: 'band',
38
- domain: { data: 'table', field: 'category' },
39
- range: 'width',
36
+ name: "xscale",
37
+ type: "band",
38
+ domain: { data: "table", field: "category" },
39
+ range: "width",
40
40
  },
41
41
  {
42
- name: 'yscale',
43
- domain: { data: 'table', field: 'amount' },
44
- range: 'height',
42
+ name: "yscale",
43
+ domain: { data: "table", field: "amount" },
44
+ range: "height",
45
45
  },
46
46
  ],
47
- }
47
+ };
48
48
 
49
49
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
- const runtime = parse(spec as any, undefined, { ast: true })
50
+ const runtime = parse(spec as any, undefined, { ast: true });
51
51
 
52
52
  // This is the key - using expr: vegaInterpreter means no eval() is called
53
53
  const view = new View(runtime, {
54
- renderer: 'none',
54
+ renderer: "none",
55
55
  logLevel: Warn,
56
56
  expr: expressionInterpreter,
57
- })
57
+ });
58
58
 
59
- await view.runAsync()
59
+ await view.runAsync();
60
60
 
61
61
  // If we get here without error, CSP compliance works
62
- expect(view.data('table')).toHaveLength(2)
62
+ expect(view.data("table")).toHaveLength(2);
63
63
 
64
- view.finalize()
65
- })
66
- })
64
+ view.finalize();
65
+ });
66
+ });