@aigentyc/chat-sdk 0.1.0

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 (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -0
  3. package/dist/JsonRenderResult-Ftw4AKwb.d.cts +18 -0
  4. package/dist/JsonRenderResult-Ftw4AKwb.d.ts +18 -0
  5. package/dist/JsonRenderResult-GQOYPLVH.cjs +15 -0
  6. package/dist/JsonRenderResult-GQOYPLVH.cjs.map +1 -0
  7. package/dist/JsonRenderResult-ZFJ6VWMS.js +6 -0
  8. package/dist/JsonRenderResult-ZFJ6VWMS.js.map +1 -0
  9. package/dist/SlotsContext-CBtt36al.d.ts +148 -0
  10. package/dist/SlotsContext-CHvISDJT.d.cts +148 -0
  11. package/dist/VisualizationRenderer-FNFYNN66.js +5 -0
  12. package/dist/VisualizationRenderer-FNFYNN66.js.map +1 -0
  13. package/dist/VisualizationRenderer-VKMZXRUX.cjs +20 -0
  14. package/dist/VisualizationRenderer-VKMZXRUX.cjs.map +1 -0
  15. package/dist/ai-elements.cjs +4608 -0
  16. package/dist/ai-elements.cjs.map +1 -0
  17. package/dist/ai-elements.d.cts +897 -0
  18. package/dist/ai-elements.d.ts +897 -0
  19. package/dist/ai-elements.js +4363 -0
  20. package/dist/ai-elements.js.map +1 -0
  21. package/dist/chunk-3MP2EGEJ.cjs +270 -0
  22. package/dist/chunk-3MP2EGEJ.cjs.map +1 -0
  23. package/dist/chunk-3RW7O444.js +26 -0
  24. package/dist/chunk-3RW7O444.js.map +1 -0
  25. package/dist/chunk-42ARGQXE.js +51 -0
  26. package/dist/chunk-42ARGQXE.js.map +1 -0
  27. package/dist/chunk-4FBVV64J.js +257 -0
  28. package/dist/chunk-4FBVV64J.js.map +1 -0
  29. package/dist/chunk-4QT25AXI.js +21 -0
  30. package/dist/chunk-4QT25AXI.js.map +1 -0
  31. package/dist/chunk-525KS5HM.cjs +30 -0
  32. package/dist/chunk-525KS5HM.cjs.map +1 -0
  33. package/dist/chunk-5F3O3ZJH.js +299 -0
  34. package/dist/chunk-5F3O3ZJH.js.map +1 -0
  35. package/dist/chunk-5QSXB6UL.cjs +259 -0
  36. package/dist/chunk-5QSXB6UL.cjs.map +1 -0
  37. package/dist/chunk-5T4FJ2SR.js +664 -0
  38. package/dist/chunk-5T4FJ2SR.js.map +1 -0
  39. package/dist/chunk-7BNYTOTE.cjs +67 -0
  40. package/dist/chunk-7BNYTOTE.cjs.map +1 -0
  41. package/dist/chunk-AWAJOSFP.cjs +96 -0
  42. package/dist/chunk-AWAJOSFP.cjs.map +1 -0
  43. package/dist/chunk-BKDV2H6Z.js +224 -0
  44. package/dist/chunk-BKDV2H6Z.js.map +1 -0
  45. package/dist/chunk-FQN6OBGN.cjs +171 -0
  46. package/dist/chunk-FQN6OBGN.cjs.map +1 -0
  47. package/dist/chunk-FYPJSHCL.js +190 -0
  48. package/dist/chunk-FYPJSHCL.js.map +1 -0
  49. package/dist/chunk-J2H6MLQF.cjs +680 -0
  50. package/dist/chunk-J2H6MLQF.cjs.map +1 -0
  51. package/dist/chunk-J2K7EJYP.cjs +198 -0
  52. package/dist/chunk-J2K7EJYP.cjs.map +1 -0
  53. package/dist/chunk-JI5KCSOI.cjs +23 -0
  54. package/dist/chunk-JI5KCSOI.cjs.map +1 -0
  55. package/dist/chunk-JOO6C3XT.cjs +44 -0
  56. package/dist/chunk-JOO6C3XT.cjs.map +1 -0
  57. package/dist/chunk-KBGPBUTI.cjs +78 -0
  58. package/dist/chunk-KBGPBUTI.cjs.map +1 -0
  59. package/dist/chunk-MT2AMINB.js +75 -0
  60. package/dist/chunk-MT2AMINB.js.map +1 -0
  61. package/dist/chunk-MZQKGNWF.js +4 -0
  62. package/dist/chunk-MZQKGNWF.js.map +1 -0
  63. package/dist/chunk-NG7OTWXQ.cjs +226 -0
  64. package/dist/chunk-NG7OTWXQ.cjs.map +1 -0
  65. package/dist/chunk-NPJKLYLV.js +68 -0
  66. package/dist/chunk-NPJKLYLV.js.map +1 -0
  67. package/dist/chunk-NW2ESHRV.js +685 -0
  68. package/dist/chunk-NW2ESHRV.js.map +1 -0
  69. package/dist/chunk-NWF735F5.js +1631 -0
  70. package/dist/chunk-NWF735F5.js.map +1 -0
  71. package/dist/chunk-NYQSM3EB.cjs +305 -0
  72. package/dist/chunk-NYQSM3EB.cjs.map +1 -0
  73. package/dist/chunk-OU7OROOE.cjs +1643 -0
  74. package/dist/chunk-OU7OROOE.cjs.map +1 -0
  75. package/dist/chunk-PS3U7T37.js +42 -0
  76. package/dist/chunk-PS3U7T37.js.map +1 -0
  77. package/dist/chunk-Q7T3VAJV.cjs +687 -0
  78. package/dist/chunk-Q7T3VAJV.cjs.map +1 -0
  79. package/dist/chunk-QYCEHFAB.js +265 -0
  80. package/dist/chunk-QYCEHFAB.js.map +1 -0
  81. package/dist/chunk-RPDJXB3U.js +676 -0
  82. package/dist/chunk-RPDJXB3U.js.map +1 -0
  83. package/dist/chunk-UKEL7FWS.js +64 -0
  84. package/dist/chunk-UKEL7FWS.js.map +1 -0
  85. package/dist/chunk-VS3NZ7FX.js +164 -0
  86. package/dist/chunk-VS3NZ7FX.js.map +1 -0
  87. package/dist/chunk-WZLWAVSS.cjs +73 -0
  88. package/dist/chunk-WZLWAVSS.cjs.map +1 -0
  89. package/dist/chunk-X5YEOOPK.cjs +758 -0
  90. package/dist/chunk-X5YEOOPK.cjs.map +1 -0
  91. package/dist/chunk-X7R334SB.cjs +5 -0
  92. package/dist/chunk-X7R334SB.cjs.map +1 -0
  93. package/dist/chunk-XXNDL5SJ.cjs +432 -0
  94. package/dist/chunk-XXNDL5SJ.cjs.map +1 -0
  95. package/dist/chunk-YQELMJW5.js +429 -0
  96. package/dist/chunk-YQELMJW5.js.map +1 -0
  97. package/dist/components.cjs +551 -0
  98. package/dist/components.cjs.map +1 -0
  99. package/dist/components.d.cts +181 -0
  100. package/dist/components.d.ts +181 -0
  101. package/dist/components.js +483 -0
  102. package/dist/components.js.map +1 -0
  103. package/dist/core.cjs +283 -0
  104. package/dist/core.cjs.map +1 -0
  105. package/dist/core.d.cts +455 -0
  106. package/dist/core.d.ts +455 -0
  107. package/dist/core.js +241 -0
  108. package/dist/core.js.map +1 -0
  109. package/dist/hooks.cjs +324 -0
  110. package/dist/hooks.cjs.map +1 -0
  111. package/dist/hooks.d.cts +163 -0
  112. package/dist/hooks.d.ts +163 -0
  113. package/dist/hooks.js +277 -0
  114. package/dist/hooks.js.map +1 -0
  115. package/dist/i18n.cjs +26 -0
  116. package/dist/i18n.cjs.map +1 -0
  117. package/dist/i18n.d.cts +50 -0
  118. package/dist/i18n.d.ts +50 -0
  119. package/dist/i18n.js +5 -0
  120. package/dist/i18n.js.map +1 -0
  121. package/dist/index.cjs +466 -0
  122. package/dist/index.cjs.map +1 -0
  123. package/dist/index.d.cts +80 -0
  124. package/dist/index.d.ts +80 -0
  125. package/dist/index.js +438 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/interaction-tracker-D9P1Oq4j.d.cts +83 -0
  128. package/dist/interaction-tracker-D9P1Oq4j.d.ts +83 -0
  129. package/dist/json-render.cjs +23 -0
  130. package/dist/json-render.cjs.map +1 -0
  131. package/dist/json-render.d.cts +857 -0
  132. package/dist/json-render.d.ts +857 -0
  133. package/dist/json-render.js +6 -0
  134. package/dist/json-render.js.map +1 -0
  135. package/dist/live-chat-transport-4XLOIPOE.js +4 -0
  136. package/dist/live-chat-transport-4XLOIPOE.js.map +1 -0
  137. package/dist/live-chat-transport-ALVRGWX7.cjs +13 -0
  138. package/dist/live-chat-transport-ALVRGWX7.cjs.map +1 -0
  139. package/dist/select-B4l9yoyn.d.cts +99 -0
  140. package/dist/select-B4l9yoyn.d.ts +99 -0
  141. package/dist/styles.css +2 -0
  142. package/dist/theme.cjs +18 -0
  143. package/dist/theme.cjs.map +1 -0
  144. package/dist/theme.d.cts +55 -0
  145. package/dist/theme.d.ts +55 -0
  146. package/dist/theme.js +5 -0
  147. package/dist/theme.js.map +1 -0
  148. package/dist/tools.cjs +32 -0
  149. package/dist/tools.cjs.map +1 -0
  150. package/dist/tools.d.cts +117 -0
  151. package/dist/tools.d.ts +117 -0
  152. package/dist/tools.js +11 -0
  153. package/dist/tools.js.map +1 -0
  154. package/dist/types-DKJ_-nbG.d.cts +349 -0
  155. package/dist/types-DKJ_-nbG.d.ts +349 -0
  156. package/dist/ui.cjs +667 -0
  157. package/dist/ui.cjs.map +1 -0
  158. package/dist/ui.d.cts +95 -0
  159. package/dist/ui.d.ts +95 -0
  160. package/dist/ui.js +414 -0
  161. package/dist/ui.js.map +1 -0
  162. package/package.json +255 -0
@@ -0,0 +1,4363 @@
1
+ "use client";
2
+ export { Conversation, ConversationContent, ConversationEmptyState, ConversationScrollButton, Loader, SpinnerLoader } from './chunk-VS3NZ7FX.js';
3
+ import './chunk-MZQKGNWF.js';
4
+ import { useI18n } from './chunk-QYCEHFAB.js';
5
+ import { processImagesInHtml } from './chunk-PS3U7T37.js';
6
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent, Badge, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, Textarea, Input, Carousel, CarouselContent, CarouselItem, ScrollArea, ScrollBar, Progress, Alert, AlertDescription, Dialog, DialogTrigger, DialogContent, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Select, SelectTrigger, SelectContent, SelectItem, SelectValue, Separator } from './chunk-NW2ESHRV.js';
7
+ import { Button } from './chunk-42ARGQXE.js';
8
+ import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter } from './chunk-NPJKLYLV.js';
9
+ import { cn } from './chunk-3RW7O444.js';
10
+ import { Slot } from '@radix-ui/react-slot';
11
+ import { cva } from 'class-variance-authority';
12
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
+ import { BrainIcon, ChevronDownIcon, DotIcon, Search, ChevronLeftIcon, ChevronRightIcon, XIcon, PaperclipIcon, Check, Copy, X, CheckIcon, CopyIcon, BookIcon, ArrowLeftIcon, ArrowRightIcon, ChevronsUpDownIcon, ImageIcon, PlusIcon, MicIcon, SearchIcon, WrenchIcon, BookmarkIcon, CornerDownLeftIcon, Loader2Icon, SquareIcon, ExternalLinkIcon, MessageCircleIcon, XCircleIcon, CheckCircleIcon, ClockIcon, CircleIcon } from 'lucide-react';
14
+ import * as React2 from 'react';
15
+ import { createContext, memo, useState, useEffect, useMemo, useContext, useId, useRef, useSyncExternalStore, useCallback, Fragment as Fragment$1, Children, isValidElement } from 'react';
16
+ import { Streamdown } from 'streamdown';
17
+ import { codeToHtml } from 'shiki';
18
+ import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
19
+ import { useControllableState } from '@radix-ui/react-use-controllable-state';
20
+ import { motion } from 'motion/react';
21
+ import { getUsage } from 'tokenlens';
22
+ import { Controls as Controls$1, Panel as Panel$1, NodeToolbar, Position, ReactFlow, Background, getSimpleBezierPath, BaseEdge, useInternalNode, getBezierPath, Handle } from '@xyflow/react';
23
+ import { Command as Command$1 } from 'cmdk';
24
+ import { nanoid } from 'nanoid';
25
+ import '@xyflow/react/dist/style.css';
26
+
27
+ var buttonGroupVariants = cva(
28
+ "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
29
+ {
30
+ variants: {
31
+ orientation: {
32
+ horizontal: "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
33
+ vertical: "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none"
34
+ }
35
+ },
36
+ defaultVariants: {
37
+ orientation: "horizontal"
38
+ }
39
+ }
40
+ );
41
+ function ButtonGroup({
42
+ className,
43
+ orientation,
44
+ ...props
45
+ }) {
46
+ return /* @__PURE__ */ jsx(
47
+ "div",
48
+ {
49
+ role: "group",
50
+ "data-slot": "button-group",
51
+ "data-orientation": orientation,
52
+ className: cn(buttonGroupVariants({ orientation }), className),
53
+ ...props
54
+ }
55
+ );
56
+ }
57
+ function ButtonGroupText({
58
+ className,
59
+ asChild = false,
60
+ ...props
61
+ }) {
62
+ const Comp = asChild ? Slot : "div";
63
+ return /* @__PURE__ */ jsx(
64
+ Comp,
65
+ {
66
+ className: cn(
67
+ "bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
68
+ className
69
+ ),
70
+ ...props
71
+ }
72
+ );
73
+ }
74
+ var Message = ({ className, from, fullWidth, ...props }) => /* @__PURE__ */ jsx(
75
+ "div",
76
+ {
77
+ className: cn(
78
+ "group flex w-full flex-col gap-2",
79
+ fullWidth ? "" : from === "assistant" ? "max-w-[var(--ac-assistant-max-width,95%)]" : "max-w-[95%]",
80
+ from === "user" ? "is-user justify-end" : "is-assistant",
81
+ className
82
+ ),
83
+ ...props
84
+ }
85
+ );
86
+ var MessageContent = ({
87
+ children,
88
+ className,
89
+ fullWidth,
90
+ ...props
91
+ }) => /* @__PURE__ */ jsx(
92
+ "div",
93
+ {
94
+ className: cn(
95
+ "flex min-w-0 flex-col gap-2 overflow-hidden",
96
+ fullWidth ? "w-full" : "w-fit max-w-full",
97
+ "group-[.is-user]:ml-auto group-[.is-user]:px-6 group-[.is-user]:py-4 group-[.is-user]:text-foreground group-[.is-user]:rounded-bl-[24px] group-[.is-user]:rounded-br-[24px] group-[.is-user]:rounded-tl-[4px] group-[.is-user]:rounded-tr-[24px] group-[.is-user]:bg-[var(--ac-user-bubble-bg,#f0f4f8)]",
98
+ "group-[.is-assistant]:text-foreground group-[.is-assistant]:w-full",
99
+ className
100
+ ),
101
+ ...props,
102
+ children
103
+ }
104
+ );
105
+ var MessageActions = ({
106
+ className,
107
+ children,
108
+ ...props
109
+ }) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), ...props, children });
110
+ var MessageAction = ({
111
+ tooltip,
112
+ children,
113
+ label,
114
+ variant = "ghost",
115
+ size = "icon-sm",
116
+ ...props
117
+ }) => {
118
+ const button = /* @__PURE__ */ jsxs(Button, { size, type: "button", variant, ...props, children: [
119
+ children,
120
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label || tooltip })
121
+ ] });
122
+ if (tooltip) {
123
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
124
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: button }),
125
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: tooltip }) })
126
+ ] }) });
127
+ }
128
+ return button;
129
+ };
130
+ var MessageBranchContext = createContext(
131
+ null
132
+ );
133
+ var useMessageBranch = () => {
134
+ const context = useContext(MessageBranchContext);
135
+ if (!context) {
136
+ throw new Error(
137
+ "MessageBranch components must be used within MessageBranch"
138
+ );
139
+ }
140
+ return context;
141
+ };
142
+ var MessageBranch = ({
143
+ defaultBranch = 0,
144
+ onBranchChange,
145
+ className,
146
+ ...props
147
+ }) => {
148
+ const [currentBranch, setCurrentBranch] = useState(defaultBranch);
149
+ const [branches, setBranches] = useState([]);
150
+ const handleBranchChange = (newBranch) => {
151
+ setCurrentBranch(newBranch);
152
+ onBranchChange?.(newBranch);
153
+ };
154
+ const goToPrevious = () => {
155
+ const newBranch = currentBranch > 0 ? currentBranch - 1 : branches.length - 1;
156
+ handleBranchChange(newBranch);
157
+ };
158
+ const goToNext = () => {
159
+ const newBranch = currentBranch < branches.length - 1 ? currentBranch + 1 : 0;
160
+ handleBranchChange(newBranch);
161
+ };
162
+ const contextValue = {
163
+ currentBranch,
164
+ totalBranches: branches.length,
165
+ goToPrevious,
166
+ goToNext,
167
+ branches,
168
+ setBranches
169
+ };
170
+ return /* @__PURE__ */ jsx(MessageBranchContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
171
+ "div",
172
+ {
173
+ className: cn("grid w-full gap-2 [&>div]:pb-0", className),
174
+ ...props
175
+ }
176
+ ) });
177
+ };
178
+ var MessageBranchContent = ({
179
+ children,
180
+ ...props
181
+ }) => {
182
+ const { currentBranch, setBranches, branches } = useMessageBranch();
183
+ const childrenArray = Array.isArray(children) ? children : [children];
184
+ useEffect(() => {
185
+ if (branches.length !== childrenArray.length) {
186
+ setBranches(childrenArray);
187
+ }
188
+ }, [childrenArray, branches, setBranches]);
189
+ return childrenArray.map((branch, index) => /* @__PURE__ */ jsx(
190
+ "div",
191
+ {
192
+ className: cn(
193
+ "grid gap-2 overflow-hidden [&>div]:pb-0",
194
+ index === currentBranch ? "block" : "hidden"
195
+ ),
196
+ ...props,
197
+ children: branch
198
+ },
199
+ branch.key
200
+ ));
201
+ };
202
+ var MessageBranchSelector = ({
203
+ className,
204
+ from,
205
+ ...props
206
+ }) => {
207
+ const { totalBranches } = useMessageBranch();
208
+ if (totalBranches <= 1) {
209
+ return null;
210
+ }
211
+ return /* @__PURE__ */ jsx(
212
+ ButtonGroup,
213
+ {
214
+ className: "[&>*:not(:first-child)]:rounded-l-md [&>*:not(:last-child)]:rounded-r-md",
215
+ orientation: "horizontal",
216
+ ...props
217
+ }
218
+ );
219
+ };
220
+ var MessageBranchPrevious = ({
221
+ children,
222
+ ...props
223
+ }) => {
224
+ const { goToPrevious, totalBranches } = useMessageBranch();
225
+ return /* @__PURE__ */ jsx(
226
+ Button,
227
+ {
228
+ "aria-label": "Previous branch",
229
+ disabled: totalBranches <= 1,
230
+ onClick: goToPrevious,
231
+ size: "icon-sm",
232
+ type: "button",
233
+ variant: "ghost",
234
+ ...props,
235
+ children: children ?? /* @__PURE__ */ jsx(ChevronLeftIcon, { size: 14 })
236
+ }
237
+ );
238
+ };
239
+ var MessageBranchNext = ({
240
+ children,
241
+ className,
242
+ ...props
243
+ }) => {
244
+ const { goToNext, totalBranches } = useMessageBranch();
245
+ return /* @__PURE__ */ jsx(
246
+ Button,
247
+ {
248
+ "aria-label": "Next branch",
249
+ disabled: totalBranches <= 1,
250
+ onClick: goToNext,
251
+ size: "icon-sm",
252
+ type: "button",
253
+ variant: "ghost",
254
+ ...props,
255
+ children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, { size: 14 })
256
+ }
257
+ );
258
+ };
259
+ var MessageBranchPage = ({
260
+ className,
261
+ ...props
262
+ }) => {
263
+ const { currentBranch, totalBranches } = useMessageBranch();
264
+ return /* @__PURE__ */ jsxs(
265
+ ButtonGroupText,
266
+ {
267
+ className: cn(
268
+ "border-none bg-transparent text-muted-foreground shadow-none",
269
+ className
270
+ ),
271
+ ...props,
272
+ children: [
273
+ currentBranch + 1,
274
+ " of ",
275
+ totalBranches
276
+ ]
277
+ }
278
+ );
279
+ };
280
+ function addUtmParams(url) {
281
+ try {
282
+ const urlObj = new URL(url);
283
+ urlObj.searchParams.set("utm_source", "chat");
284
+ urlObj.searchParams.set("utm_medium", "referral");
285
+ return urlObj.toString();
286
+ } catch {
287
+ return url;
288
+ }
289
+ }
290
+ var CustomLink = ({ href, children, ...props }) => /* @__PURE__ */ jsx(
291
+ "a",
292
+ {
293
+ href: href ? addUtmParams(href) : href,
294
+ target: "_blank",
295
+ rel: "noopener noreferrer",
296
+ className: "hover:underline hover:opacity-80 transition-opacity font-medium",
297
+ ...props,
298
+ children
299
+ }
300
+ );
301
+ var CustomImage = ({ src, alt, ...props }) => /* @__PURE__ */ jsx(
302
+ "img",
303
+ {
304
+ src,
305
+ alt: alt || "",
306
+ loading: "lazy",
307
+ className: "rounded-xl max-w-full h-auto my-4",
308
+ ...props
309
+ }
310
+ );
311
+ var CustomTable = ({ children, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-4 overflow-x-auto", children: /* @__PURE__ */ jsx(
312
+ "table",
313
+ {
314
+ className: "w-full text-sm rounded-xl border border-black/[0.08] overflow-hidden",
315
+ ...props,
316
+ children
317
+ }
318
+ ) });
319
+ var CustomThead = ({ children, ...props }) => /* @__PURE__ */ jsx("thead", { className: "bg-black/[0.04]", ...props, children });
320
+ var CustomTh = ({ children, ...props }) => /* @__PURE__ */ jsx(
321
+ "th",
322
+ {
323
+ className: "px-4 py-3 text-start text-xs font-medium uppercase tracking-wider opacity-60 border-b border-black/[0.08]",
324
+ ...props,
325
+ children
326
+ }
327
+ );
328
+ var CustomTd = ({ children, ...props }) => /* @__PURE__ */ jsx(
329
+ "td",
330
+ {
331
+ className: "px-4 py-3 border-b border-black/[0.08]",
332
+ ...props,
333
+ children
334
+ }
335
+ );
336
+ var CustomTr = ({ children, ...props }) => /* @__PURE__ */ jsx(
337
+ "tr",
338
+ {
339
+ className: "hover:bg-black/[0.02] transition-colors",
340
+ ...props,
341
+ children
342
+ }
343
+ );
344
+ var MessageResponse = memo(
345
+ ({ className, ...props }) => /* @__PURE__ */ jsx(
346
+ Streamdown,
347
+ {
348
+ className: cn(
349
+ "message-response size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
350
+ className
351
+ ),
352
+ components: {
353
+ a: CustomLink,
354
+ img: CustomImage,
355
+ table: CustomTable,
356
+ thead: CustomThead,
357
+ th: CustomTh,
358
+ td: CustomTd,
359
+ tr: CustomTr
360
+ },
361
+ linkSafety: { enabled: false },
362
+ ...props
363
+ }
364
+ ),
365
+ (prevProps, nextProps) => prevProps.children === nextProps.children
366
+ );
367
+ MessageResponse.displayName = "MessageResponse";
368
+ function MessageAttachment({
369
+ data,
370
+ className,
371
+ onRemove,
372
+ ...props
373
+ }) {
374
+ const filename = data.filename || "";
375
+ const mediaType = data.mediaType?.startsWith("image/") && data.url ? "image" : "file";
376
+ const isImage = mediaType === "image";
377
+ const attachmentLabel = filename || (isImage ? "Image" : "Attachment");
378
+ return /* @__PURE__ */ jsx(
379
+ "div",
380
+ {
381
+ className: cn(
382
+ "group relative size-24 overflow-hidden rounded-lg",
383
+ className
384
+ ),
385
+ ...props,
386
+ children: isImage ? /* @__PURE__ */ jsxs(Fragment, { children: [
387
+ /* @__PURE__ */ jsx(
388
+ "img",
389
+ {
390
+ alt: filename || "attachment",
391
+ className: "size-full object-cover",
392
+ height: 100,
393
+ src: data.url,
394
+ width: 100
395
+ }
396
+ ),
397
+ onRemove && /* @__PURE__ */ jsxs(
398
+ Button,
399
+ {
400
+ "aria-label": "Remove attachment",
401
+ className: "absolute top-2 right-2 size-6 rounded-full bg-background/80 p-0 opacity-0 backdrop-blur-sm transition-opacity hover:bg-background group-hover:opacity-100 [&>svg]:size-3",
402
+ onClick: (e) => {
403
+ e.stopPropagation();
404
+ onRemove();
405
+ },
406
+ type: "button",
407
+ variant: "ghost",
408
+ children: [
409
+ /* @__PURE__ */ jsx(XIcon, {}),
410
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Remove" })
411
+ ]
412
+ }
413
+ )
414
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
415
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
416
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: "flex size-full shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" }) }) }),
417
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: attachmentLabel }) })
418
+ ] }),
419
+ onRemove && /* @__PURE__ */ jsxs(
420
+ Button,
421
+ {
422
+ "aria-label": "Remove attachment",
423
+ className: "size-6 shrink-0 rounded-full p-0 opacity-0 transition-opacity hover:bg-accent group-hover:opacity-100 [&>svg]:size-3",
424
+ onClick: (e) => {
425
+ e.stopPropagation();
426
+ onRemove();
427
+ },
428
+ type: "button",
429
+ variant: "ghost",
430
+ children: [
431
+ /* @__PURE__ */ jsx(XIcon, {}),
432
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Remove" })
433
+ ]
434
+ }
435
+ )
436
+ ] })
437
+ }
438
+ );
439
+ }
440
+ function MessageAttachments({
441
+ children,
442
+ className,
443
+ ...props
444
+ }) {
445
+ if (!children) {
446
+ return null;
447
+ }
448
+ return /* @__PURE__ */ jsx(
449
+ "div",
450
+ {
451
+ className: cn(
452
+ "ml-auto flex w-fit flex-wrap items-start gap-2",
453
+ className
454
+ ),
455
+ ...props,
456
+ children
457
+ }
458
+ );
459
+ }
460
+ var MessageToolbar = ({
461
+ className,
462
+ children,
463
+ ...props
464
+ }) => /* @__PURE__ */ jsx(
465
+ "div",
466
+ {
467
+ className: cn(
468
+ "mt-4 flex w-full items-center justify-between gap-4",
469
+ className
470
+ ),
471
+ ...props,
472
+ children
473
+ }
474
+ );
475
+
476
+ // src/core/api/kb-client.ts
477
+ function getDefaultEndpoint() {
478
+ try {
479
+ const env = import.meta.env;
480
+ if (env?.VITE_API_ENDPOINT) return env.VITE_API_ENDPOINT;
481
+ } catch {
482
+ }
483
+ return "http://localhost:3000";
484
+ }
485
+ async function submitFeedback(request, apiKey, apiEndpoint) {
486
+ const endpoint = apiEndpoint || getDefaultEndpoint();
487
+ const headers = {
488
+ "Content-Type": "application/json"
489
+ };
490
+ if (apiKey) {
491
+ headers["Authorization"] = `Bearer ${apiKey}`;
492
+ }
493
+ try {
494
+ const response = await fetch(`${endpoint}/api/kb/feedback`, {
495
+ method: "POST",
496
+ headers,
497
+ credentials: "include",
498
+ body: JSON.stringify(request)
499
+ });
500
+ if (!response.ok) {
501
+ const error = await response.json().catch(() => ({ error: response.statusText }));
502
+ return { success: false, error: error.error || response.statusText };
503
+ }
504
+ return { success: true };
505
+ } catch (error) {
506
+ return {
507
+ success: false,
508
+ error: error instanceof Error ? error.message : "Unknown error"
509
+ };
510
+ }
511
+ }
512
+ var ThumbsUpIcon = ({ className }) => /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className, children: /* @__PURE__ */ jsx(
513
+ "path",
514
+ {
515
+ d: "M7 11V19C7 19.2652 6.89464 19.5196 6.70711 19.7071C6.51957 19.8946 6.26522 20 6 20H4C3.73478 20 3.48043 19.8946 3.29289 19.7071C3.10536 19.5196 3 19.2652 3 19V12C3 11.7348 3.10536 11.4804 3.29289 11.2929C3.48043 11.1054 3.73478 11 4 11H7ZM7 11C8.06087 11 9.07828 10.5786 9.82843 9.82843C10.5786 9.07828 11 8.06087 11 7V6C11 5.46957 11.2107 4.96086 11.5858 4.58579C11.9609 4.21071 12.4696 4 13 4C13.5304 4 14.0391 4.21071 14.4142 4.58579C14.7893 4.96086 15 5.46957 15 6V11H18C18.5304 11 19.0391 11.2107 19.4142 11.5858C19.7893 11.9609 20 12.4696 20 13L19 18C18.8562 18.6135 18.5834 19.1402 18.2227 19.501C17.8619 19.8617 17.4328 20.0368 17 20H10C9.20435 20 8.44129 19.6839 7.87868 19.1213C7.31607 18.5587 7 17.7956 7 17",
516
+ stroke: "currentColor",
517
+ strokeWidth: "1.5",
518
+ strokeLinecap: "round",
519
+ strokeLinejoin: "round"
520
+ }
521
+ ) });
522
+ var ThumbsDownIcon = ({ className }) => /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className, children: /* @__PURE__ */ jsx(
523
+ "path",
524
+ {
525
+ d: "M7 13V4.99999C7 4.73478 6.89464 4.48042 6.70711 4.29289C6.51957 4.10535 6.26522 3.99999 6 3.99999H4C3.73478 3.99999 3.48043 4.10535 3.29289 4.29289C3.10536 4.48042 3 4.73478 3 4.99999V12C3 12.2652 3.10536 12.5196 3.29289 12.7071C3.48043 12.8946 3.73478 13 4 13H7ZM7 13C8.06087 13 9.07828 13.4214 9.82843 14.1716C10.5786 14.9217 11 15.9391 11 17V18C11 18.5304 11.2107 19.0391 11.5858 19.4142C11.9609 19.7893 12.4696 20 13 20C13.5304 20 14.0391 19.7893 14.4142 19.4142C14.7893 19.0391 15 18.5304 15 18V13H18C18.5304 13 19.0391 12.7893 19.4142 12.4142C19.7893 12.0391 20 11.5304 20 11L19 5.99999C18.8562 5.38652 18.5834 4.85975 18.2227 4.49903C17.8619 4.13831 17.4328 3.96317 17 3.99999H10C9.20435 3.99999 8.44129 4.31606 7.87868 4.87867C7.31607 5.44128 7 6.20434 7 6.99999",
526
+ stroke: "currentColor",
527
+ strokeWidth: "1.5",
528
+ strokeLinecap: "round",
529
+ strokeLinejoin: "round"
530
+ }
531
+ ) });
532
+ var REVIEW_TYPES = [
533
+ { value: "wrong_answer", labelKey: "wrongAnswer" },
534
+ { value: "partial_answer", labelKey: "partialAnswer" },
535
+ { value: "hallucination", labelKey: "hallucination" },
536
+ { value: "inappropriate_tone", labelKey: "inappropriateTone" }
537
+ ];
538
+ function MessageFeedback({
539
+ messageId,
540
+ projectId,
541
+ sessionId,
542
+ apiKey,
543
+ apiEndpoint,
544
+ textContent,
545
+ trackInteraction
546
+ }) {
547
+ const { t } = useI18n();
548
+ const [feedback, setFeedback] = useState(null);
549
+ const [showReviewForm, setShowReviewForm] = useState(false);
550
+ const [reviewType, setReviewType] = useState(null);
551
+ const [reviewText, setReviewText] = useState("");
552
+ const [isSubmitting, setIsSubmitting] = useState(false);
553
+ const [copied, setCopied] = useState(false);
554
+ const submitFeedbackToApi = async (feedbackData) => {
555
+ if (!projectId || !messageId || isSubmitting) return;
556
+ setIsSubmitting(true);
557
+ try {
558
+ const request = {
559
+ projectId,
560
+ sessionId,
561
+ messageId,
562
+ isPositive: feedbackData.isPositive,
563
+ issueType: feedbackData.reviewType,
564
+ feedbackText: feedbackData.reviewText
565
+ };
566
+ const result = await submitFeedback(request, apiKey, apiEndpoint);
567
+ if (!result.success) {
568
+ console.error("Failed to submit feedback:", result.error);
569
+ }
570
+ } catch (error) {
571
+ console.error("Failed to submit feedback:", error);
572
+ } finally {
573
+ setIsSubmitting(false);
574
+ }
575
+ };
576
+ const handlePositiveFeedback = () => {
577
+ if (isSubmitting) return;
578
+ setFeedback("positive");
579
+ setShowReviewForm(false);
580
+ submitFeedbackToApi({ isPositive: true });
581
+ trackInteraction?.({
582
+ type: "feedback",
583
+ target: "thumbs_up",
584
+ label: "Positive feedback",
585
+ messageId,
586
+ metadata: { isPositive: true }
587
+ });
588
+ };
589
+ const handleNegativeFeedback = () => {
590
+ if (isSubmitting) return;
591
+ setFeedback("negative");
592
+ setShowReviewForm(true);
593
+ };
594
+ const handleSubmitReview = () => {
595
+ if (isSubmitting) return;
596
+ const feedbackData = {
597
+ isPositive: false,
598
+ reviewType: reviewType ?? void 0,
599
+ reviewText: reviewText || void 0
600
+ };
601
+ setShowReviewForm(false);
602
+ submitFeedbackToApi(feedbackData);
603
+ trackInteraction?.({
604
+ type: "feedback",
605
+ target: "thumbs_down",
606
+ label: "Negative feedback",
607
+ messageId,
608
+ metadata: { isPositive: false, reviewType, reviewText }
609
+ });
610
+ };
611
+ const handleCancelReview = () => {
612
+ setFeedback(null);
613
+ setShowReviewForm(false);
614
+ setReviewType(null);
615
+ setReviewText("");
616
+ };
617
+ const handleCopy = async () => {
618
+ if (typeof window === "undefined" || !navigator?.clipboard?.writeText) return;
619
+ try {
620
+ await navigator.clipboard.writeText(textContent);
621
+ setCopied(true);
622
+ setTimeout(() => setCopied(false), 2e3);
623
+ trackInteraction?.({
624
+ type: "copy",
625
+ target: "message",
626
+ label: "Copy response",
627
+ messageId,
628
+ metadata: { contentLength: textContent.length }
629
+ });
630
+ } catch (error) {
631
+ console.error("Failed to copy:", error);
632
+ }
633
+ };
634
+ return /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
635
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
636
+ /* @__PURE__ */ jsx(
637
+ "button",
638
+ {
639
+ type: "button",
640
+ onClick: handlePositiveFeedback,
641
+ disabled: isSubmitting,
642
+ className: cn(
643
+ "group w-8 h-8 rounded-full flex items-center justify-center transition-all duration-300",
644
+ feedback === "positive" ? "bg-primary/10 text-primary" : "bg-secondary text-muted-foreground hover:bg-primary/10 hover:text-primary",
645
+ isSubmitting && "opacity-50 cursor-not-allowed"
646
+ ),
647
+ title: t("helpful"),
648
+ children: /* @__PURE__ */ jsx(ThumbsUpIcon, {})
649
+ }
650
+ ),
651
+ /* @__PURE__ */ jsx(
652
+ "button",
653
+ {
654
+ type: "button",
655
+ onClick: handleNegativeFeedback,
656
+ disabled: isSubmitting,
657
+ className: cn(
658
+ "group w-8 h-8 rounded-full flex items-center justify-center transition-all duration-300",
659
+ feedback === "negative" ? "bg-red-100 text-red-500" : "bg-secondary text-muted-foreground hover:bg-red-50 hover:text-red-500",
660
+ isSubmitting && "opacity-50 cursor-not-allowed"
661
+ ),
662
+ title: t("notHelpful"),
663
+ children: /* @__PURE__ */ jsx(ThumbsDownIcon, {})
664
+ }
665
+ ),
666
+ /* @__PURE__ */ jsx(
667
+ "button",
668
+ {
669
+ type: "button",
670
+ onClick: handleCopy,
671
+ className: "group w-8 h-8 rounded-full bg-secondary flex items-center justify-center text-muted-foreground hover:bg-primary/10 hover:text-primary transition-all duration-300",
672
+ title: t("copyResponse"),
673
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4" })
674
+ }
675
+ )
676
+ ] }),
677
+ showReviewForm && /* @__PURE__ */ jsxs("div", { className: "mt-4 bg-gradient-to-br from-accent to-secondary rounded-2xl border border-border overflow-hidden animate-in slide-in-from-top-2 duration-300", children: [
678
+ /* @__PURE__ */ jsxs("div", { className: "px-5 py-4 border-b border-border flex items-center justify-between", children: [
679
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
680
+ /* @__PURE__ */ jsx("span", { className: "w-8 h-8 rounded-xl bg-card border border-border flex items-center justify-center", children: /* @__PURE__ */ jsx(ThumbsDownIcon, { className: "text-red-500" }) }),
681
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: t("whatWentWrong") })
682
+ ] }),
683
+ /* @__PURE__ */ jsx(
684
+ "button",
685
+ {
686
+ type: "button",
687
+ onClick: handleCancelReview,
688
+ className: "w-8 h-8 rounded-full bg-card border border-border flex items-center justify-center hover:border-primary transition-colors",
689
+ children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
690
+ }
691
+ )
692
+ ] }),
693
+ /* @__PURE__ */ jsxs("div", { className: "p-5 space-y-4", children: [
694
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: REVIEW_TYPES.map((type) => /* @__PURE__ */ jsx(
695
+ "button",
696
+ {
697
+ type: "button",
698
+ onClick: () => setReviewType(type.value),
699
+ className: cn(
700
+ "px-4 py-2 rounded-full text-xs font-medium transition-all duration-300",
701
+ reviewType === type.value ? "bg-primary text-primary-foreground shadow-md shadow-primary/20" : "bg-card border border-border text-foreground hover:border-primary hover:text-primary"
702
+ ),
703
+ children: t(type.labelKey)
704
+ },
705
+ type.value
706
+ )) }),
707
+ /* @__PURE__ */ jsx(
708
+ Textarea,
709
+ {
710
+ placeholder: t("addDetails"),
711
+ value: reviewText,
712
+ onChange: (e) => setReviewText(e.target.value),
713
+ rows: 2,
714
+ className: "text-sm resize-none rounded-xl border-border focus:border-primary focus:ring-primary/20"
715
+ }
716
+ ),
717
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs(
718
+ "button",
719
+ {
720
+ type: "button",
721
+ onClick: handleSubmitReview,
722
+ disabled: isSubmitting,
723
+ className: "group relative px-5 py-2.5 bg-primary text-primary-foreground rounded-full text-sm font-medium overflow-hidden transition-all duration-300 hover:shadow-lg hover:shadow-primary/25 disabled:opacity-50 disabled:cursor-not-allowed",
724
+ children: [
725
+ /* @__PURE__ */ jsx("span", { className: "relative z-10", children: isSubmitting ? t("submitting") : t("submitFeedback") }),
726
+ /* @__PURE__ */ jsx(
727
+ "div",
728
+ {
729
+ className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-primary/90"
730
+ }
731
+ )
732
+ ]
733
+ }
734
+ ) })
735
+ ] })
736
+ ] }),
737
+ /* @__PURE__ */ jsx("style", { children: `
738
+ .animate-in {
739
+ animation: animateIn 0.3s ease-out;
740
+ }
741
+ .slide-in-from-top-2 {
742
+ --tw-enter-translate-y: -0.5rem;
743
+ }
744
+ @keyframes animateIn {
745
+ from {
746
+ opacity: 0;
747
+ transform: translateY(var(--tw-enter-translate-y, 0));
748
+ }
749
+ to {
750
+ opacity: 1;
751
+ transform: translateY(0);
752
+ }
753
+ }
754
+ ` })
755
+ ] });
756
+ }
757
+ var MOBILE_BREAKPOINT = 768;
758
+ function subscribeToResize(cb) {
759
+ if (typeof window === "undefined") return () => {
760
+ };
761
+ window.addEventListener("resize", cb);
762
+ return () => window.removeEventListener("resize", cb);
763
+ }
764
+ function getIsMobile() {
765
+ if (typeof window === "undefined") return false;
766
+ return window.innerWidth < MOBILE_BREAKPOINT;
767
+ }
768
+ function ComponentRenderer({
769
+ htmlCode,
770
+ cssCode,
771
+ data,
772
+ mobileGridCols = 1,
773
+ desktopGridCols = 3,
774
+ onInteraction,
775
+ messageId,
776
+ eventId,
777
+ mobilePageSize = 4,
778
+ desktopPageSize = 4
779
+ }) {
780
+ const containerId = useId();
781
+ const containerRef = useRef(null);
782
+ const [currentPage, setCurrentPage] = useState(0);
783
+ const isMobile = useSyncExternalStore(subscribeToResize, getIsMobile, () => true);
784
+ const pageSize = isMobile ? mobilePageSize : desktopPageSize;
785
+ const isArray = Array.isArray(data);
786
+ const totalItems = isArray ? data.length : 1;
787
+ const totalPages = isArray ? Math.ceil(totalItems / pageSize) : 1;
788
+ const hasPagination = isArray && totalItems > pageSize;
789
+ useEffect(() => {
790
+ setCurrentPage((p) => Math.min(p, Math.max(0, totalPages - 1)));
791
+ }, [totalPages]);
792
+ const displayData = isArray && hasPagination ? data.slice(currentPage * pageSize, (currentPage + 1) * pageSize) : data;
793
+ useEffect(() => {
794
+ if (!containerRef.current) return;
795
+ if (typeof document === "undefined") return;
796
+ let processedHtml = "";
797
+ if (Array.isArray(displayData)) {
798
+ const gridId = `grid-${containerId}`;
799
+ const items = displayData.map((item, idx) => {
800
+ let rendered = replaceTemplateVariables(htmlCode, item);
801
+ rendered = processImagesInHtml(rendered);
802
+ const globalIndex = currentPage * pageSize + idx;
803
+ return `<div class="grid-item" data-item-index="${globalIndex}">${rendered}</div>`;
804
+ }).join("");
805
+ processedHtml = `<div class="grid-container" id="${gridId}">${items}</div>`;
806
+ } else {
807
+ processedHtml = replaceTemplateVariables(htmlCode, displayData);
808
+ processedHtml = processImagesInHtml(processedHtml);
809
+ }
810
+ containerRef.current.innerHTML = processedHtml;
811
+ const styleId = `component-style-${containerId}`;
812
+ const existingStyle = document.getElementById(styleId);
813
+ if (existingStyle) {
814
+ existingStyle.remove();
815
+ }
816
+ let finalCss = cssCode;
817
+ if (Array.isArray(displayData)) {
818
+ const gridCss = `
819
+ #${containerId} .grid-container {
820
+ display: grid;
821
+ grid-template-columns: repeat(${mobileGridCols}, 1fr);
822
+ gap: 1rem;
823
+ width: 100%;
824
+ }
825
+
826
+ #${containerId} .grid-item {
827
+ width: 100%;
828
+ }
829
+
830
+ @media (min-width: 768px) {
831
+ #${containerId} .grid-container {
832
+ grid-template-columns: repeat(${desktopGridCols}, 1fr);
833
+ }
834
+ }
835
+ `;
836
+ finalCss = `${cssCode}
837
+ ${gridCss}`;
838
+ }
839
+ const style = document.createElement("style");
840
+ style.id = styleId;
841
+ style.textContent = finalCss;
842
+ containerRef.current.appendChild(style);
843
+ const images = containerRef.current.querySelectorAll("img");
844
+ images.forEach((img) => {
845
+ if (!img.hasAttribute("loading")) {
846
+ img.setAttribute("loading", "lazy");
847
+ }
848
+ });
849
+ const links = containerRef.current.querySelectorAll("a");
850
+ links.forEach((link) => {
851
+ link.setAttribute("target", "_blank");
852
+ link.setAttribute("rel", "noopener noreferrer");
853
+ });
854
+ }, [htmlCode, cssCode, displayData, mobileGridCols, desktopGridCols, containerId, currentPage, pageSize, totalItems, totalPages]);
855
+ return /* @__PURE__ */ jsxs("div", { className: "component-renderer-wrapper", children: [
856
+ /* @__PURE__ */ jsx(
857
+ "div",
858
+ {
859
+ ref: containerRef,
860
+ id: containerId,
861
+ className: "component-render w-full rounded",
862
+ onClick: (e) => {
863
+ if (!onInteraction) return;
864
+ const target = e.target;
865
+ const link = target.closest("a");
866
+ const button = target.closest("button");
867
+ if (link?.href) {
868
+ onInteraction({
869
+ type: "link_click",
870
+ target: link.href,
871
+ label: link.textContent || link.href,
872
+ metadata: { url: link.href, text: link.textContent },
873
+ messageId,
874
+ eventId
875
+ });
876
+ } else if (button && !button.hasAttribute("data-no-track")) {
877
+ onInteraction({
878
+ type: "button_click",
879
+ target: button.textContent || "button",
880
+ label: button.textContent || "button",
881
+ metadata: { buttonText: button.textContent },
882
+ messageId,
883
+ eventId
884
+ });
885
+ }
886
+ },
887
+ style: { display: "block" }
888
+ }
889
+ ),
890
+ hasPagination && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 mt-4", dir: "ltr", children: [
891
+ /* @__PURE__ */ jsx(
892
+ "button",
893
+ {
894
+ onClick: () => setCurrentPage((p) => Math.max(0, p - 1)),
895
+ disabled: currentPage === 0,
896
+ className: "px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors",
897
+ "aria-label": "Previous page",
898
+ children: "\u2039"
899
+ }
900
+ ),
901
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-600 px-2 tabular-nums", children: [
902
+ currentPage + 1,
903
+ " / ",
904
+ totalPages
905
+ ] }),
906
+ /* @__PURE__ */ jsx(
907
+ "button",
908
+ {
909
+ onClick: () => setCurrentPage((p) => Math.min(totalPages - 1, p + 1)),
910
+ disabled: currentPage >= totalPages - 1,
911
+ className: "px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors",
912
+ "aria-label": "Next page",
913
+ children: "\u203A"
914
+ }
915
+ )
916
+ ] })
917
+ ] });
918
+ }
919
+ function replaceTemplateVariables(html, data) {
920
+ let processed = processEachBlocks(html, data);
921
+ processed = processed.replace(/\{\{[#/][^}]+\}\}/g, "");
922
+ processed = processed.replace(/\{\{this\}\}/g, () => {
923
+ return data !== void 0 && data !== null ? String(data) : "";
924
+ });
925
+ processed = processed.replace(/\{\{this\.([^}]+)\}\}/g, "{{$1}}");
926
+ return processed.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
927
+ try {
928
+ const trimmedPath = path.trim();
929
+ const value = getNestedValue(data, trimmedPath);
930
+ if (value === void 0 || value === null) {
931
+ return "";
932
+ }
933
+ if (typeof value === "object") {
934
+ return JSON.stringify(value);
935
+ }
936
+ return String(value);
937
+ } catch (error) {
938
+ console.error(`Error processing template variable {{${path}}}:`, error);
939
+ return match;
940
+ }
941
+ });
942
+ }
943
+ function processEachBlocks(html, data) {
944
+ const eachRegex = /\{\{#each\s+([^}]+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
945
+ return html.replace(eachRegex, (_match, field, content) => {
946
+ const trimmedField = field.trim();
947
+ const array = getNestedValue(data, trimmedField);
948
+ if (!Array.isArray(array)) {
949
+ return "";
950
+ }
951
+ return array.map((item) => {
952
+ let itemHtml = processEachBlocks(content, item);
953
+ if (typeof item !== "object" || item === null) {
954
+ itemHtml = itemHtml.replace(/\{\{this\}\}/g, String(item));
955
+ return itemHtml;
956
+ }
957
+ itemHtml = itemHtml.replace(/\{\{this\.([^}]+)\}\}/g, "{{$1}}");
958
+ itemHtml = itemHtml.replace(/\{\{([^}]+)\}\}/g, (m, path) => {
959
+ const trimmedPath = path.trim();
960
+ if (trimmedPath.startsWith("#") || trimmedPath.startsWith("/")) return m;
961
+ const value = getNestedValue(item, trimmedPath);
962
+ if (value === void 0 || value === null) return "";
963
+ if (typeof value === "object") return JSON.stringify(value);
964
+ return String(value);
965
+ });
966
+ return itemHtml;
967
+ }).join("");
968
+ });
969
+ }
970
+ function getNestedValue(obj, path) {
971
+ if (!path || obj === null || obj === void 0) {
972
+ return void 0;
973
+ }
974
+ const parts = path.split(/\.(?![^[]*\])/);
975
+ let current = obj;
976
+ for (const part of parts) {
977
+ if (current === null || current === void 0) {
978
+ return void 0;
979
+ }
980
+ const arrayMatch = part.match(/^([^[]+)\[([^\]]+)\]$/);
981
+ if (arrayMatch) {
982
+ const [, key, index] = arrayMatch;
983
+ current = current[key];
984
+ if (Array.isArray(current)) {
985
+ current = current[parseInt(index, 10)];
986
+ }
987
+ } else {
988
+ current = current[part];
989
+ }
990
+ }
991
+ return current;
992
+ }
993
+ var Artifact = ({ className, ...props }) => /* @__PURE__ */ jsx(
994
+ "div",
995
+ {
996
+ className: cn(
997
+ "flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm",
998
+ className
999
+ ),
1000
+ ...props
1001
+ }
1002
+ );
1003
+ var ArtifactHeader = ({
1004
+ className,
1005
+ ...props
1006
+ }) => /* @__PURE__ */ jsx(
1007
+ "div",
1008
+ {
1009
+ className: cn(
1010
+ "flex items-center justify-between border-b bg-muted/50 px-4 py-3",
1011
+ className
1012
+ ),
1013
+ ...props
1014
+ }
1015
+ );
1016
+ var ArtifactClose = ({
1017
+ className,
1018
+ children,
1019
+ size = "sm",
1020
+ variant = "ghost",
1021
+ ...props
1022
+ }) => /* @__PURE__ */ jsxs(
1023
+ Button,
1024
+ {
1025
+ className: cn(
1026
+ "size-8 p-0 text-muted-foreground hover:text-foreground",
1027
+ className
1028
+ ),
1029
+ size,
1030
+ type: "button",
1031
+ variant,
1032
+ ...props,
1033
+ children: [
1034
+ children ?? /* @__PURE__ */ jsx(XIcon, { className: "size-4" }),
1035
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
1036
+ ]
1037
+ }
1038
+ );
1039
+ var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ jsx(
1040
+ "p",
1041
+ {
1042
+ className: cn("font-medium text-foreground text-sm", className),
1043
+ ...props
1044
+ }
1045
+ );
1046
+ var ArtifactDescription = ({
1047
+ className,
1048
+ ...props
1049
+ }) => /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground text-sm", className), ...props });
1050
+ var ArtifactActions = ({
1051
+ className,
1052
+ ...props
1053
+ }) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), ...props });
1054
+ var ArtifactAction = ({
1055
+ tooltip,
1056
+ label,
1057
+ icon: Icon,
1058
+ children,
1059
+ className,
1060
+ size = "sm",
1061
+ variant = "ghost",
1062
+ ...props
1063
+ }) => {
1064
+ const button = /* @__PURE__ */ jsxs(
1065
+ Button,
1066
+ {
1067
+ className: cn(
1068
+ "size-8 p-0 text-muted-foreground hover:text-foreground",
1069
+ className
1070
+ ),
1071
+ size,
1072
+ type: "button",
1073
+ variant,
1074
+ ...props,
1075
+ children: [
1076
+ Icon ? /* @__PURE__ */ jsx(Icon, { className: "size-4" }) : children,
1077
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label || tooltip })
1078
+ ]
1079
+ }
1080
+ );
1081
+ if (tooltip) {
1082
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
1083
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: button }),
1084
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: tooltip }) })
1085
+ ] }) });
1086
+ }
1087
+ return button;
1088
+ };
1089
+ var ArtifactContent = ({
1090
+ className,
1091
+ ...props
1092
+ }) => /* @__PURE__ */ jsx("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
1093
+ var CodeBlockContext = createContext({
1094
+ code: ""
1095
+ });
1096
+ var lineNumberTransformer = {
1097
+ name: "line-numbers",
1098
+ line(node, line) {
1099
+ node.children.unshift({
1100
+ type: "element",
1101
+ tagName: "span",
1102
+ properties: {
1103
+ className: [
1104
+ "inline-block",
1105
+ "min-w-10",
1106
+ "mr-4",
1107
+ "text-right",
1108
+ "select-none",
1109
+ "text-muted-foreground"
1110
+ ]
1111
+ },
1112
+ children: [{ type: "text", value: String(line) }]
1113
+ });
1114
+ }
1115
+ };
1116
+ async function highlightCode(code, language, showLineNumbers = false) {
1117
+ const transformers = showLineNumbers ? [lineNumberTransformer] : [];
1118
+ return await Promise.all([
1119
+ codeToHtml(code, {
1120
+ lang: language,
1121
+ theme: "one-light",
1122
+ transformers
1123
+ }),
1124
+ codeToHtml(code, {
1125
+ lang: language,
1126
+ theme: "one-dark-pro",
1127
+ transformers
1128
+ })
1129
+ ]);
1130
+ }
1131
+ var CodeBlock = ({
1132
+ code,
1133
+ language,
1134
+ showLineNumbers = false,
1135
+ className,
1136
+ children,
1137
+ ...props
1138
+ }) => {
1139
+ const [html, setHtml] = useState("");
1140
+ const [darkHtml, setDarkHtml] = useState("");
1141
+ const mounted = useRef(false);
1142
+ useEffect(() => {
1143
+ highlightCode(code, language, showLineNumbers).then(([light, dark]) => {
1144
+ if (!mounted.current) {
1145
+ setHtml(light);
1146
+ setDarkHtml(dark);
1147
+ mounted.current = true;
1148
+ }
1149
+ });
1150
+ return () => {
1151
+ mounted.current = false;
1152
+ };
1153
+ }, [code, language, showLineNumbers]);
1154
+ return /* @__PURE__ */ jsx(CodeBlockContext.Provider, { value: { code }, children: /* @__PURE__ */ jsx(
1155
+ "div",
1156
+ {
1157
+ className: cn(
1158
+ "group relative w-full overflow-hidden rounded-md border bg-background text-foreground",
1159
+ className
1160
+ ),
1161
+ ...props,
1162
+ children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1163
+ /* @__PURE__ */ jsx(
1164
+ "div",
1165
+ {
1166
+ className: "overflow-auto dark:hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm",
1167
+ dangerouslySetInnerHTML: { __html: html }
1168
+ }
1169
+ ),
1170
+ /* @__PURE__ */ jsx(
1171
+ "div",
1172
+ {
1173
+ className: "hidden overflow-auto dark:block [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm",
1174
+ dangerouslySetInnerHTML: { __html: darkHtml }
1175
+ }
1176
+ ),
1177
+ children && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 flex items-center gap-2", children })
1178
+ ] })
1179
+ }
1180
+ ) });
1181
+ };
1182
+ var CodeBlockCopyButton = ({
1183
+ onCopy,
1184
+ onError,
1185
+ timeout = 2e3,
1186
+ children,
1187
+ className,
1188
+ ...props
1189
+ }) => {
1190
+ const [isCopied, setIsCopied] = useState(false);
1191
+ const { code } = useContext(CodeBlockContext);
1192
+ const copyToClipboard = async () => {
1193
+ if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
1194
+ onError?.(new Error("Clipboard API not available"));
1195
+ return;
1196
+ }
1197
+ try {
1198
+ await navigator.clipboard.writeText(code);
1199
+ setIsCopied(true);
1200
+ onCopy?.();
1201
+ setTimeout(() => setIsCopied(false), timeout);
1202
+ } catch (error) {
1203
+ onError?.(error);
1204
+ }
1205
+ };
1206
+ const Icon = isCopied ? CheckIcon : CopyIcon;
1207
+ return /* @__PURE__ */ jsx(
1208
+ Button,
1209
+ {
1210
+ className: cn("shrink-0", className),
1211
+ onClick: copyToClipboard,
1212
+ size: "icon",
1213
+ variant: "ghost",
1214
+ ...props,
1215
+ children: children ?? /* @__PURE__ */ jsx(Icon, { size: 14 })
1216
+ }
1217
+ );
1218
+ };
1219
+ var WebPreviewContext = createContext(null);
1220
+ var useWebPreview = () => {
1221
+ const context = useContext(WebPreviewContext);
1222
+ if (!context) {
1223
+ throw new Error("WebPreview components must be used within a WebPreview");
1224
+ }
1225
+ return context;
1226
+ };
1227
+ var WebPreview = ({
1228
+ className,
1229
+ children,
1230
+ defaultUrl = "",
1231
+ onUrlChange,
1232
+ ...props
1233
+ }) => {
1234
+ const [url, setUrl] = useState(defaultUrl);
1235
+ const [consoleOpen, setConsoleOpen] = useState(false);
1236
+ const handleUrlChange = (newUrl) => {
1237
+ setUrl(newUrl);
1238
+ onUrlChange?.(newUrl);
1239
+ };
1240
+ const contextValue = {
1241
+ url,
1242
+ setUrl: handleUrlChange,
1243
+ consoleOpen,
1244
+ setConsoleOpen
1245
+ };
1246
+ return /* @__PURE__ */ jsx(WebPreviewContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
1247
+ "div",
1248
+ {
1249
+ className: cn(
1250
+ "flex size-full flex-col rounded-lg border bg-card",
1251
+ className
1252
+ ),
1253
+ ...props,
1254
+ children
1255
+ }
1256
+ ) });
1257
+ };
1258
+ var WebPreviewNavigation = ({
1259
+ className,
1260
+ children,
1261
+ ...props
1262
+ }) => /* @__PURE__ */ jsx(
1263
+ "div",
1264
+ {
1265
+ className: cn("flex items-center gap-1 border-b p-2", className),
1266
+ ...props,
1267
+ children
1268
+ }
1269
+ );
1270
+ var WebPreviewNavigationButton = ({
1271
+ onClick,
1272
+ disabled,
1273
+ tooltip,
1274
+ children,
1275
+ ...props
1276
+ }) => /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
1277
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1278
+ Button,
1279
+ {
1280
+ className: "h-8 w-8 p-0 hover:text-foreground",
1281
+ disabled,
1282
+ onClick,
1283
+ size: "sm",
1284
+ variant: "ghost",
1285
+ ...props,
1286
+ children
1287
+ }
1288
+ ) }),
1289
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: tooltip }) })
1290
+ ] }) });
1291
+ var WebPreviewUrl = ({
1292
+ value,
1293
+ onChange,
1294
+ onKeyDown,
1295
+ ...props
1296
+ }) => {
1297
+ const { url, setUrl } = useWebPreview();
1298
+ const [inputValue, setInputValue] = useState(url);
1299
+ useEffect(() => {
1300
+ setInputValue(url);
1301
+ }, [url]);
1302
+ const handleChange = (event) => {
1303
+ setInputValue(event.target.value);
1304
+ onChange?.(event);
1305
+ };
1306
+ const handleKeyDown = (event) => {
1307
+ if (event.key === "Enter") {
1308
+ const target = event.target;
1309
+ setUrl(target.value);
1310
+ }
1311
+ onKeyDown?.(event);
1312
+ };
1313
+ return /* @__PURE__ */ jsx(
1314
+ Input,
1315
+ {
1316
+ className: "h-8 flex-1 text-sm",
1317
+ onChange: onChange ?? handleChange,
1318
+ onKeyDown: handleKeyDown,
1319
+ placeholder: "Enter URL...",
1320
+ value: value ?? inputValue,
1321
+ ...props
1322
+ }
1323
+ );
1324
+ };
1325
+ var WebPreviewBody = ({
1326
+ className,
1327
+ loading,
1328
+ src,
1329
+ ...props
1330
+ }) => {
1331
+ const { url } = useWebPreview();
1332
+ return /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1333
+ /* @__PURE__ */ jsx(
1334
+ "iframe",
1335
+ {
1336
+ className: cn("size-full", className),
1337
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-presentation",
1338
+ src: (src ?? url) || void 0,
1339
+ title: "Preview",
1340
+ ...props
1341
+ }
1342
+ ),
1343
+ loading
1344
+ ] });
1345
+ };
1346
+ var WebPreviewConsole = ({
1347
+ className,
1348
+ logs = [],
1349
+ children,
1350
+ ...props
1351
+ }) => {
1352
+ const { consoleOpen, setConsoleOpen } = useWebPreview();
1353
+ return /* @__PURE__ */ jsxs(
1354
+ Collapsible,
1355
+ {
1356
+ className: cn("border-t bg-muted/50 font-mono text-sm", className),
1357
+ onOpenChange: setConsoleOpen,
1358
+ open: consoleOpen,
1359
+ ...props,
1360
+ children: [
1361
+ /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1362
+ Button,
1363
+ {
1364
+ className: "flex w-full items-center justify-between p-4 text-start font-medium hover:bg-muted/50",
1365
+ variant: "ghost",
1366
+ children: [
1367
+ "Console",
1368
+ /* @__PURE__ */ jsx(
1369
+ ChevronDownIcon,
1370
+ {
1371
+ className: cn(
1372
+ "h-4 w-4 transition-transform duration-200",
1373
+ consoleOpen && "rotate-180"
1374
+ )
1375
+ }
1376
+ )
1377
+ ]
1378
+ }
1379
+ ) }),
1380
+ /* @__PURE__ */ jsx(
1381
+ CollapsibleContent,
1382
+ {
1383
+ className: cn(
1384
+ "px-4 pb-4",
1385
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in"
1386
+ ),
1387
+ children: /* @__PURE__ */ jsxs("div", { className: "max-h-48 space-y-1 overflow-y-auto", children: [
1388
+ logs.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No console output" }) : logs.map((log, index) => /* @__PURE__ */ jsxs(
1389
+ "div",
1390
+ {
1391
+ className: cn(
1392
+ "text-xs",
1393
+ log.level === "error" && "text-destructive",
1394
+ log.level === "warn" && "text-yellow-600",
1395
+ log.level === "log" && "text-foreground"
1396
+ ),
1397
+ children: [
1398
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: log.timestamp.toLocaleTimeString() }),
1399
+ " ",
1400
+ log.message
1401
+ ]
1402
+ },
1403
+ `${log.timestamp.getTime()}-${index}`
1404
+ )),
1405
+ children
1406
+ ] })
1407
+ }
1408
+ )
1409
+ ]
1410
+ }
1411
+ );
1412
+ };
1413
+ var Sources = ({ className, ...props }) => /* @__PURE__ */ jsx(
1414
+ Collapsible,
1415
+ {
1416
+ className: cn("not-prose mb-4 text-primary text-xs", className),
1417
+ ...props
1418
+ }
1419
+ );
1420
+ var SourcesTrigger = ({
1421
+ className,
1422
+ count,
1423
+ children,
1424
+ ...props
1425
+ }) => /* @__PURE__ */ jsx(
1426
+ CollapsibleTrigger,
1427
+ {
1428
+ className: cn("flex items-center gap-2", className),
1429
+ ...props,
1430
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
1431
+ /* @__PURE__ */ jsxs("p", { className: "font-medium", children: [
1432
+ "Used ",
1433
+ count,
1434
+ " sources"
1435
+ ] }),
1436
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4" })
1437
+ ] })
1438
+ }
1439
+ );
1440
+ var SourcesContent = ({
1441
+ className,
1442
+ ...props
1443
+ }) => /* @__PURE__ */ jsx(
1444
+ CollapsibleContent,
1445
+ {
1446
+ className: cn(
1447
+ "mt-3 flex w-fit flex-col gap-2",
1448
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
1449
+ className
1450
+ ),
1451
+ ...props
1452
+ }
1453
+ );
1454
+ var Source = ({ href, title, children, ...props }) => /* @__PURE__ */ jsx(
1455
+ "a",
1456
+ {
1457
+ className: "flex items-center gap-2",
1458
+ href,
1459
+ rel: "noreferrer",
1460
+ target: "_blank",
1461
+ ...props,
1462
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
1463
+ /* @__PURE__ */ jsx(BookIcon, { className: "h-4 w-4" }),
1464
+ /* @__PURE__ */ jsx("span", { className: "block font-medium", children: title })
1465
+ ] })
1466
+ }
1467
+ );
1468
+ var HoverCard = HoverCardPrimitive.Root;
1469
+ var HoverCardTrigger = HoverCardPrimitive.Trigger;
1470
+ var HoverCardContent = React2.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
1471
+ HoverCardPrimitive.Content,
1472
+ {
1473
+ ref,
1474
+ align,
1475
+ sideOffset,
1476
+ className: cn(
1477
+ "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
1478
+ className
1479
+ ),
1480
+ ...props
1481
+ }
1482
+ ));
1483
+ HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
1484
+ var InlineCitation = ({
1485
+ className,
1486
+ ...props
1487
+ }) => /* @__PURE__ */ jsx(
1488
+ "span",
1489
+ {
1490
+ className: cn("group inline items-center gap-1", className),
1491
+ ...props
1492
+ }
1493
+ );
1494
+ var InlineCitationText = ({
1495
+ className,
1496
+ ...props
1497
+ }) => /* @__PURE__ */ jsx(
1498
+ "span",
1499
+ {
1500
+ className: cn("transition-colors group-hover:bg-accent", className),
1501
+ ...props
1502
+ }
1503
+ );
1504
+ var InlineCitationCard = (props) => /* @__PURE__ */ jsx(HoverCard, { closeDelay: 0, openDelay: 0, ...props });
1505
+ var InlineCitationCardTrigger = ({
1506
+ sources,
1507
+ className,
1508
+ ...props
1509
+ }) => /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1510
+ Badge,
1511
+ {
1512
+ className: cn("ml-1 rounded-full", className),
1513
+ variant: "secondary",
1514
+ ...props,
1515
+ children: sources[0] ? /* @__PURE__ */ jsxs(Fragment, { children: [
1516
+ new URL(sources[0]).hostname,
1517
+ " ",
1518
+ sources.length > 1 && `+${sources.length - 1}`
1519
+ ] }) : "unknown"
1520
+ }
1521
+ ) });
1522
+ var InlineCitationCardBody = ({
1523
+ className,
1524
+ ...props
1525
+ }) => /* @__PURE__ */ jsx(HoverCardContent, { className: cn("relative w-80 p-0", className), ...props });
1526
+ var CarouselApiContext = createContext(void 0);
1527
+ var useCarouselApi = () => {
1528
+ const context = useContext(CarouselApiContext);
1529
+ return context;
1530
+ };
1531
+ var InlineCitationCarousel = ({
1532
+ className,
1533
+ children,
1534
+ ...props
1535
+ }) => {
1536
+ const [api, setApi] = useState();
1537
+ return /* @__PURE__ */ jsx(CarouselApiContext.Provider, { value: api, children: /* @__PURE__ */ jsx(Carousel, { className: cn("w-full", className), setApi, ...props, children }) });
1538
+ };
1539
+ var InlineCitationCarouselContent = (props) => /* @__PURE__ */ jsx(CarouselContent, { ...props });
1540
+ var InlineCitationCarouselItem = ({
1541
+ className,
1542
+ ...props
1543
+ }) => /* @__PURE__ */ jsx(
1544
+ CarouselItem,
1545
+ {
1546
+ className: cn("w-full space-y-2 p-4 pl-8", className),
1547
+ ...props
1548
+ }
1549
+ );
1550
+ var InlineCitationCarouselHeader = ({
1551
+ className,
1552
+ ...props
1553
+ }) => /* @__PURE__ */ jsx(
1554
+ "div",
1555
+ {
1556
+ className: cn(
1557
+ "flex items-center justify-between gap-2 rounded-t-md bg-secondary p-2",
1558
+ className
1559
+ ),
1560
+ ...props
1561
+ }
1562
+ );
1563
+ var InlineCitationCarouselIndex = ({
1564
+ children,
1565
+ className,
1566
+ ...props
1567
+ }) => {
1568
+ const api = useCarouselApi();
1569
+ const [current, setCurrent] = useState(0);
1570
+ const [count, setCount] = useState(0);
1571
+ useEffect(() => {
1572
+ if (!api) {
1573
+ return;
1574
+ }
1575
+ setCount(api.scrollSnapList().length);
1576
+ setCurrent(api.selectedScrollSnap() + 1);
1577
+ api.on("select", () => {
1578
+ setCurrent(api.selectedScrollSnap() + 1);
1579
+ });
1580
+ }, [api]);
1581
+ return /* @__PURE__ */ jsx(
1582
+ "div",
1583
+ {
1584
+ className: cn(
1585
+ "flex flex-1 items-center justify-end px-3 py-1 text-muted-foreground text-xs",
1586
+ className
1587
+ ),
1588
+ ...props,
1589
+ children: children ?? `${current}/${count}`
1590
+ }
1591
+ );
1592
+ };
1593
+ var InlineCitationCarouselPrev = ({
1594
+ className,
1595
+ ...props
1596
+ }) => {
1597
+ const api = useCarouselApi();
1598
+ const handleClick = useCallback(() => {
1599
+ if (api) {
1600
+ api.scrollPrev();
1601
+ }
1602
+ }, [api]);
1603
+ return /* @__PURE__ */ jsx(
1604
+ "button",
1605
+ {
1606
+ "aria-label": "Previous",
1607
+ className: cn("shrink-0", className),
1608
+ onClick: handleClick,
1609
+ type: "button",
1610
+ ...props,
1611
+ children: /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "size-4 text-muted-foreground" })
1612
+ }
1613
+ );
1614
+ };
1615
+ var InlineCitationCarouselNext = ({
1616
+ className,
1617
+ ...props
1618
+ }) => {
1619
+ const api = useCarouselApi();
1620
+ const handleClick = useCallback(() => {
1621
+ if (api) {
1622
+ api.scrollNext();
1623
+ }
1624
+ }, [api]);
1625
+ return /* @__PURE__ */ jsx(
1626
+ "button",
1627
+ {
1628
+ "aria-label": "Next",
1629
+ className: cn("shrink-0", className),
1630
+ onClick: handleClick,
1631
+ type: "button",
1632
+ ...props,
1633
+ children: /* @__PURE__ */ jsx(ArrowRightIcon, { className: "size-4 text-muted-foreground" })
1634
+ }
1635
+ );
1636
+ };
1637
+ var InlineCitationSource = ({
1638
+ title,
1639
+ url,
1640
+ description,
1641
+ className,
1642
+ children,
1643
+ ...props
1644
+ }) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), ...props, children: [
1645
+ title && /* @__PURE__ */ jsx("h4", { className: "truncate font-medium text-sm leading-tight", children: title }),
1646
+ url && /* @__PURE__ */ jsx("p", { className: "truncate break-all text-muted-foreground text-xs", children: url }),
1647
+ description && /* @__PURE__ */ jsx("p", { className: "line-clamp-3 text-muted-foreground text-sm leading-relaxed", children: description }),
1648
+ children
1649
+ ] });
1650
+ var InlineCitationQuote = ({
1651
+ children,
1652
+ className,
1653
+ ...props
1654
+ }) => /* @__PURE__ */ jsx(
1655
+ "blockquote",
1656
+ {
1657
+ className: cn(
1658
+ "border-muted border-l-2 pl-3 text-muted-foreground text-sm italic",
1659
+ className
1660
+ ),
1661
+ ...props,
1662
+ children
1663
+ }
1664
+ );
1665
+ var ShimmerComponent = ({
1666
+ children,
1667
+ as: Component = "p",
1668
+ className,
1669
+ duration = 2,
1670
+ spread = 2
1671
+ }) => {
1672
+ const MotionComponent = motion.create(
1673
+ Component
1674
+ );
1675
+ const dynamicSpread = useMemo(
1676
+ () => (children?.length ?? 0) * spread,
1677
+ [children, spread]
1678
+ );
1679
+ return /* @__PURE__ */ jsx(
1680
+ MotionComponent,
1681
+ {
1682
+ animate: { backgroundPosition: "0% center" },
1683
+ className: cn(
1684
+ "relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent",
1685
+ "[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),var(--ac-background),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]",
1686
+ className
1687
+ ),
1688
+ initial: { backgroundPosition: "100% center" },
1689
+ style: {
1690
+ "--spread": `${dynamicSpread}px`,
1691
+ backgroundImage: "var(--bg), linear-gradient(var(--ac-muted-foreground), var(--ac-muted-foreground))"
1692
+ },
1693
+ transition: {
1694
+ repeat: Number.POSITIVE_INFINITY,
1695
+ duration,
1696
+ ease: "linear"
1697
+ },
1698
+ children
1699
+ }
1700
+ );
1701
+ };
1702
+ var Shimmer = memo(ShimmerComponent);
1703
+ var ReasoningContext = createContext(null);
1704
+ var useReasoning = () => {
1705
+ const context = useContext(ReasoningContext);
1706
+ if (!context) {
1707
+ throw new Error("Reasoning components must be used within Reasoning");
1708
+ }
1709
+ return context;
1710
+ };
1711
+ var AUTO_CLOSE_DELAY = 1e3;
1712
+ var MS_IN_S = 1e3;
1713
+ var Reasoning = memo(
1714
+ ({
1715
+ className,
1716
+ isStreaming = false,
1717
+ open,
1718
+ defaultOpen = true,
1719
+ onOpenChange,
1720
+ duration: durationProp,
1721
+ children,
1722
+ ...props
1723
+ }) => {
1724
+ const [isOpen, setIsOpen] = useControllableState({
1725
+ prop: open,
1726
+ defaultProp: defaultOpen,
1727
+ onChange: onOpenChange
1728
+ });
1729
+ const [duration, setDuration] = useControllableState({
1730
+ prop: durationProp,
1731
+ defaultProp: void 0
1732
+ });
1733
+ const [hasAutoClosed, setHasAutoClosed] = useState(false);
1734
+ const [startTime, setStartTime] = useState(null);
1735
+ useEffect(() => {
1736
+ if (isStreaming) {
1737
+ if (startTime === null) {
1738
+ setStartTime(Date.now());
1739
+ }
1740
+ } else if (startTime !== null) {
1741
+ setDuration(Math.ceil((Date.now() - startTime) / MS_IN_S));
1742
+ setStartTime(null);
1743
+ }
1744
+ }, [isStreaming, startTime, setDuration]);
1745
+ useEffect(() => {
1746
+ if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed) {
1747
+ const timer = setTimeout(() => {
1748
+ setIsOpen(false);
1749
+ setHasAutoClosed(true);
1750
+ }, AUTO_CLOSE_DELAY);
1751
+ return () => clearTimeout(timer);
1752
+ }
1753
+ }, [isStreaming, isOpen, defaultOpen, setIsOpen, hasAutoClosed]);
1754
+ const handleOpenChange = (newOpen) => {
1755
+ setIsOpen(newOpen);
1756
+ };
1757
+ return /* @__PURE__ */ jsx(
1758
+ ReasoningContext.Provider,
1759
+ {
1760
+ value: { isStreaming, isOpen, setIsOpen, duration },
1761
+ children: /* @__PURE__ */ jsx(
1762
+ Collapsible,
1763
+ {
1764
+ className: cn("not-prose mb-4", className),
1765
+ onOpenChange: handleOpenChange,
1766
+ open: isOpen,
1767
+ ...props,
1768
+ children
1769
+ }
1770
+ )
1771
+ }
1772
+ );
1773
+ }
1774
+ );
1775
+ var defaultGetThinkingMessage = (isStreaming, duration) => {
1776
+ if (isStreaming || duration === 0) {
1777
+ return /* @__PURE__ */ jsx(Shimmer, { duration: 1, children: "Thinking..." });
1778
+ }
1779
+ if (duration === void 0) {
1780
+ return /* @__PURE__ */ jsx("p", { children: "Thought for a few seconds" });
1781
+ }
1782
+ return /* @__PURE__ */ jsxs("p", { children: [
1783
+ "Thought for ",
1784
+ duration,
1785
+ " seconds"
1786
+ ] });
1787
+ };
1788
+ var ReasoningTrigger = memo(
1789
+ ({ className, children, getThinkingMessage = defaultGetThinkingMessage, ...props }) => {
1790
+ const { isStreaming, isOpen, duration } = useReasoning();
1791
+ return /* @__PURE__ */ jsx(
1792
+ CollapsibleTrigger,
1793
+ {
1794
+ className: cn(
1795
+ "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
1796
+ className
1797
+ ),
1798
+ ...props,
1799
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
1800
+ /* @__PURE__ */ jsx(BrainIcon, { className: "size-4" }),
1801
+ getThinkingMessage(isStreaming, duration),
1802
+ /* @__PURE__ */ jsx(
1803
+ ChevronDownIcon,
1804
+ {
1805
+ className: cn(
1806
+ "size-4 transition-transform",
1807
+ isOpen ? "rotate-180" : "rotate-0"
1808
+ )
1809
+ }
1810
+ )
1811
+ ] })
1812
+ }
1813
+ );
1814
+ }
1815
+ );
1816
+ var ReasoningContent = memo(
1817
+ ({ className, children, ...props }) => /* @__PURE__ */ jsx(
1818
+ CollapsibleContent,
1819
+ {
1820
+ className: cn(
1821
+ "mt-4 text-sm",
1822
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
1823
+ className
1824
+ ),
1825
+ ...props,
1826
+ children: /* @__PURE__ */ jsx(Streamdown, { ...props, children })
1827
+ }
1828
+ )
1829
+ );
1830
+ Reasoning.displayName = "Reasoning";
1831
+ ReasoningTrigger.displayName = "ReasoningTrigger";
1832
+ ReasoningContent.displayName = "ReasoningContent";
1833
+ function ThinkingSpinner({
1834
+ text = "Thinking...",
1835
+ className
1836
+ }) {
1837
+ const [displayText, setDisplayText] = useState(text);
1838
+ const [isAnimating, setIsAnimating] = useState(false);
1839
+ const prevTextRef = useRef(text);
1840
+ useEffect(() => {
1841
+ if (text !== prevTextRef.current) {
1842
+ setIsAnimating(true);
1843
+ const timer = setTimeout(() => {
1844
+ setDisplayText(text);
1845
+ setIsAnimating(false);
1846
+ prevTextRef.current = text;
1847
+ }, 150);
1848
+ return () => clearTimeout(timer);
1849
+ }
1850
+ }, [text]);
1851
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 my-4", className), children: [
1852
+ /* @__PURE__ */ jsxs(
1853
+ "svg",
1854
+ {
1855
+ className: "animate-spin",
1856
+ width: "20",
1857
+ height: "20",
1858
+ viewBox: "0 0 20 20",
1859
+ fill: "none",
1860
+ xmlns: "http://www.w3.org/2000/svg",
1861
+ style: { color: "var(--ac-loader-color, var(--ac-primary, #2f80ed))" },
1862
+ children: [
1863
+ /* @__PURE__ */ jsx(
1864
+ "circle",
1865
+ {
1866
+ cx: "10",
1867
+ cy: "10",
1868
+ r: "8",
1869
+ stroke: "#E5E5E5",
1870
+ strokeWidth: "2",
1871
+ fill: "none"
1872
+ }
1873
+ ),
1874
+ /* @__PURE__ */ jsx(
1875
+ "path",
1876
+ {
1877
+ d: "M10 2C14.4183 2 18 5.58172 18 10",
1878
+ stroke: "currentColor",
1879
+ strokeWidth: "2",
1880
+ strokeLinecap: "round",
1881
+ fill: "none"
1882
+ }
1883
+ )
1884
+ ]
1885
+ }
1886
+ ),
1887
+ /* @__PURE__ */ jsx(
1888
+ "span",
1889
+ {
1890
+ className: cn(
1891
+ "text-sm text-muted-foreground transition-all duration-150",
1892
+ isAnimating ? "opacity-0" : "opacity-100"
1893
+ ),
1894
+ children: displayText
1895
+ }
1896
+ )
1897
+ ] });
1898
+ }
1899
+ function FollowupButtons({
1900
+ suggestions,
1901
+ onSelect,
1902
+ className,
1903
+ disabled = false
1904
+ }) {
1905
+ if (!suggestions || suggestions.length === 0) return null;
1906
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-2", className), children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsx(
1907
+ Button,
1908
+ {
1909
+ variant: "outline",
1910
+ size: "sm",
1911
+ onClick: () => onSelect(suggestion),
1912
+ disabled,
1913
+ className: "text-xs h-auto py-1.5 px-3 whitespace-normal text-start",
1914
+ children: suggestion
1915
+ },
1916
+ index
1917
+ )) });
1918
+ }
1919
+ var Suggestions = ({
1920
+ className,
1921
+ children,
1922
+ ...props
1923
+ }) => /* @__PURE__ */ jsxs(ScrollArea, { className: "w-full overflow-x-auto whitespace-nowrap", ...props, children: [
1924
+ /* @__PURE__ */ jsx("div", { className: cn("flex w-max flex-nowrap items-center gap-2", className), children }),
1925
+ /* @__PURE__ */ jsx(ScrollBar, { className: "hidden", orientation: "horizontal" })
1926
+ ] });
1927
+ var Suggestion = ({
1928
+ suggestion,
1929
+ onClick,
1930
+ className,
1931
+ variant = "outline",
1932
+ size = "sm",
1933
+ children,
1934
+ ...props
1935
+ }) => {
1936
+ const handleClick = () => {
1937
+ onClick?.(suggestion);
1938
+ };
1939
+ return /* @__PURE__ */ jsx(
1940
+ Button,
1941
+ {
1942
+ className: cn("cursor-pointer rounded-full px-4", className),
1943
+ onClick: handleClick,
1944
+ size,
1945
+ type: "button",
1946
+ variant,
1947
+ ...props,
1948
+ children: children || suggestion
1949
+ }
1950
+ );
1951
+ };
1952
+ var PERCENT_MAX = 100;
1953
+ var ICON_RADIUS = 10;
1954
+ var ICON_VIEWBOX = 24;
1955
+ var ICON_CENTER = 12;
1956
+ var ICON_STROKE_WIDTH = 2;
1957
+ var ContextContext = createContext(null);
1958
+ var useContextValue = () => {
1959
+ const context = useContext(ContextContext);
1960
+ if (!context) {
1961
+ throw new Error("Context components must be used within Context");
1962
+ }
1963
+ return context;
1964
+ };
1965
+ var Context = ({
1966
+ usedTokens,
1967
+ maxTokens,
1968
+ usage,
1969
+ modelId,
1970
+ ...props
1971
+ }) => /* @__PURE__ */ jsx(
1972
+ ContextContext.Provider,
1973
+ {
1974
+ value: {
1975
+ usedTokens,
1976
+ maxTokens,
1977
+ usage,
1978
+ modelId
1979
+ },
1980
+ children: /* @__PURE__ */ jsx(HoverCard, { closeDelay: 0, openDelay: 0, ...props })
1981
+ }
1982
+ );
1983
+ var ContextIcon = () => {
1984
+ const { usedTokens, maxTokens } = useContextValue();
1985
+ const circumference = 2 * Math.PI * ICON_RADIUS;
1986
+ const usedPercent = usedTokens / maxTokens;
1987
+ const dashOffset = circumference * (1 - usedPercent);
1988
+ return /* @__PURE__ */ jsxs(
1989
+ "svg",
1990
+ {
1991
+ "aria-label": "Model context usage",
1992
+ height: "20",
1993
+ role: "img",
1994
+ style: { color: "currentcolor" },
1995
+ viewBox: `0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`,
1996
+ width: "20",
1997
+ children: [
1998
+ /* @__PURE__ */ jsx(
1999
+ "circle",
2000
+ {
2001
+ cx: ICON_CENTER,
2002
+ cy: ICON_CENTER,
2003
+ fill: "none",
2004
+ opacity: "0.25",
2005
+ r: ICON_RADIUS,
2006
+ stroke: "currentColor",
2007
+ strokeWidth: ICON_STROKE_WIDTH
2008
+ }
2009
+ ),
2010
+ /* @__PURE__ */ jsx(
2011
+ "circle",
2012
+ {
2013
+ cx: ICON_CENTER,
2014
+ cy: ICON_CENTER,
2015
+ fill: "none",
2016
+ opacity: "0.7",
2017
+ r: ICON_RADIUS,
2018
+ stroke: "currentColor",
2019
+ strokeDasharray: `${circumference} ${circumference}`,
2020
+ strokeDashoffset: dashOffset,
2021
+ strokeLinecap: "round",
2022
+ strokeWidth: ICON_STROKE_WIDTH,
2023
+ style: { transformOrigin: "center", transform: "rotate(-90deg)" }
2024
+ }
2025
+ )
2026
+ ]
2027
+ }
2028
+ );
2029
+ };
2030
+ var ContextTrigger = ({ children, ...props }) => {
2031
+ const { usedTokens, maxTokens } = useContextValue();
2032
+ const usedPercent = usedTokens / maxTokens;
2033
+ const renderedPercent = new Intl.NumberFormat("en-US", {
2034
+ style: "percent",
2035
+ maximumFractionDigits: 1
2036
+ }).format(usedPercent);
2037
+ return /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", ...props, children: [
2038
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-muted-foreground", children: renderedPercent }),
2039
+ /* @__PURE__ */ jsx(ContextIcon, {})
2040
+ ] }) });
2041
+ };
2042
+ var ContextContent = ({
2043
+ className,
2044
+ ...props
2045
+ }) => /* @__PURE__ */ jsx(
2046
+ HoverCardContent,
2047
+ {
2048
+ className: cn("min-w-60 divide-y overflow-hidden p-0", className),
2049
+ ...props
2050
+ }
2051
+ );
2052
+ var ContextContentHeader = ({
2053
+ children,
2054
+ className,
2055
+ ...props
2056
+ }) => {
2057
+ const { usedTokens, maxTokens } = useContextValue();
2058
+ const usedPercent = usedTokens / maxTokens;
2059
+ const displayPct = new Intl.NumberFormat("en-US", {
2060
+ style: "percent",
2061
+ maximumFractionDigits: 1
2062
+ }).format(usedPercent);
2063
+ const used = new Intl.NumberFormat("en-US", {
2064
+ notation: "compact"
2065
+ }).format(usedTokens);
2066
+ const total = new Intl.NumberFormat("en-US", {
2067
+ notation: "compact"
2068
+ }).format(maxTokens);
2069
+ return /* @__PURE__ */ jsx("div", { className: cn("w-full space-y-2 p-3", className), ...props, children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2070
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [
2071
+ /* @__PURE__ */ jsx("p", { children: displayPct }),
2072
+ /* @__PURE__ */ jsxs("p", { className: "font-mono text-muted-foreground", children: [
2073
+ used,
2074
+ " / ",
2075
+ total
2076
+ ] })
2077
+ ] }),
2078
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsx(Progress, { className: "bg-muted", value: usedPercent * PERCENT_MAX }) })
2079
+ ] }) });
2080
+ };
2081
+ var ContextContentBody = ({
2082
+ children,
2083
+ className,
2084
+ ...props
2085
+ }) => /* @__PURE__ */ jsx("div", { className: cn("w-full p-3", className), ...props, children });
2086
+ var ContextContentFooter = ({
2087
+ children,
2088
+ className,
2089
+ ...props
2090
+ }) => {
2091
+ const { modelId, usage } = useContextValue();
2092
+ const costUSD = modelId ? getUsage({
2093
+ modelId,
2094
+ usage: {
2095
+ input: usage?.inputTokens ?? 0,
2096
+ output: usage?.outputTokens ?? 0
2097
+ }
2098
+ }).costUSD?.totalUSD : void 0;
2099
+ const totalCost = new Intl.NumberFormat("en-US", {
2100
+ style: "currency",
2101
+ currency: "USD"
2102
+ }).format(costUSD ?? 0);
2103
+ return /* @__PURE__ */ jsx(
2104
+ "div",
2105
+ {
2106
+ className: cn(
2107
+ "flex w-full items-center justify-between gap-3 bg-secondary p-3 text-xs",
2108
+ className
2109
+ ),
2110
+ ...props,
2111
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2112
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Total cost" }),
2113
+ /* @__PURE__ */ jsx("span", { children: totalCost })
2114
+ ] })
2115
+ }
2116
+ );
2117
+ };
2118
+ var ContextInputUsage = ({
2119
+ className,
2120
+ children,
2121
+ ...props
2122
+ }) => {
2123
+ const { usage, modelId } = useContextValue();
2124
+ const inputTokens = usage?.inputTokens ?? 0;
2125
+ if (children) {
2126
+ return children;
2127
+ }
2128
+ if (!inputTokens) {
2129
+ return null;
2130
+ }
2131
+ const inputCost = modelId ? getUsage({
2132
+ modelId,
2133
+ usage: { input: inputTokens, output: 0 }
2134
+ }).costUSD?.totalUSD : void 0;
2135
+ const inputCostText = new Intl.NumberFormat("en-US", {
2136
+ style: "currency",
2137
+ currency: "USD"
2138
+ }).format(inputCost ?? 0);
2139
+ return /* @__PURE__ */ jsxs(
2140
+ "div",
2141
+ {
2142
+ className: cn("flex items-center justify-between text-xs", className),
2143
+ ...props,
2144
+ children: [
2145
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Input" }),
2146
+ /* @__PURE__ */ jsx(TokensWithCost, { costText: inputCostText, tokens: inputTokens })
2147
+ ]
2148
+ }
2149
+ );
2150
+ };
2151
+ var ContextOutputUsage = ({
2152
+ className,
2153
+ children,
2154
+ ...props
2155
+ }) => {
2156
+ const { usage, modelId } = useContextValue();
2157
+ const outputTokens = usage?.outputTokens ?? 0;
2158
+ if (children) {
2159
+ return children;
2160
+ }
2161
+ if (!outputTokens) {
2162
+ return null;
2163
+ }
2164
+ const outputCost = modelId ? getUsage({
2165
+ modelId,
2166
+ usage: { input: 0, output: outputTokens }
2167
+ }).costUSD?.totalUSD : void 0;
2168
+ const outputCostText = new Intl.NumberFormat("en-US", {
2169
+ style: "currency",
2170
+ currency: "USD"
2171
+ }).format(outputCost ?? 0);
2172
+ return /* @__PURE__ */ jsxs(
2173
+ "div",
2174
+ {
2175
+ className: cn("flex items-center justify-between text-xs", className),
2176
+ ...props,
2177
+ children: [
2178
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Output" }),
2179
+ /* @__PURE__ */ jsx(TokensWithCost, { costText: outputCostText, tokens: outputTokens })
2180
+ ]
2181
+ }
2182
+ );
2183
+ };
2184
+ var ContextReasoningUsage = ({
2185
+ className,
2186
+ children,
2187
+ ...props
2188
+ }) => {
2189
+ const { usage, modelId } = useContextValue();
2190
+ const reasoningTokens = usage?.reasoningTokens ?? 0;
2191
+ if (children) {
2192
+ return children;
2193
+ }
2194
+ if (!reasoningTokens) {
2195
+ return null;
2196
+ }
2197
+ const reasoningCost = modelId ? getUsage({
2198
+ modelId,
2199
+ usage: { reasoningTokens }
2200
+ }).costUSD?.totalUSD : void 0;
2201
+ const reasoningCostText = new Intl.NumberFormat("en-US", {
2202
+ style: "currency",
2203
+ currency: "USD"
2204
+ }).format(reasoningCost ?? 0);
2205
+ return /* @__PURE__ */ jsxs(
2206
+ "div",
2207
+ {
2208
+ className: cn("flex items-center justify-between text-xs", className),
2209
+ ...props,
2210
+ children: [
2211
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Reasoning" }),
2212
+ /* @__PURE__ */ jsx(TokensWithCost, { costText: reasoningCostText, tokens: reasoningTokens })
2213
+ ]
2214
+ }
2215
+ );
2216
+ };
2217
+ var ContextCacheUsage = ({
2218
+ className,
2219
+ children,
2220
+ ...props
2221
+ }) => {
2222
+ const { usage, modelId } = useContextValue();
2223
+ const cacheTokens = usage?.cachedInputTokens ?? 0;
2224
+ if (children) {
2225
+ return children;
2226
+ }
2227
+ if (!cacheTokens) {
2228
+ return null;
2229
+ }
2230
+ const cacheCost = modelId ? getUsage({
2231
+ modelId,
2232
+ usage: { cacheReads: cacheTokens, input: 0, output: 0 }
2233
+ }).costUSD?.totalUSD : void 0;
2234
+ const cacheCostText = new Intl.NumberFormat("en-US", {
2235
+ style: "currency",
2236
+ currency: "USD"
2237
+ }).format(cacheCost ?? 0);
2238
+ return /* @__PURE__ */ jsxs(
2239
+ "div",
2240
+ {
2241
+ className: cn("flex items-center justify-between text-xs", className),
2242
+ ...props,
2243
+ children: [
2244
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Cache" }),
2245
+ /* @__PURE__ */ jsx(TokensWithCost, { costText: cacheCostText, tokens: cacheTokens })
2246
+ ]
2247
+ }
2248
+ );
2249
+ };
2250
+ var TokensWithCost = ({
2251
+ tokens,
2252
+ costText
2253
+ }) => /* @__PURE__ */ jsxs("span", { children: [
2254
+ tokens === void 0 ? "\u2014" : new Intl.NumberFormat("en-US", {
2255
+ notation: "compact"
2256
+ }).format(tokens),
2257
+ costText ? /* @__PURE__ */ jsxs("span", { className: "ml-2 text-muted-foreground", children: [
2258
+ "\u2022 ",
2259
+ costText
2260
+ ] }) : null
2261
+ ] });
2262
+ var ChainOfThoughtContext = createContext(
2263
+ null
2264
+ );
2265
+ var useChainOfThought = () => {
2266
+ const context = useContext(ChainOfThoughtContext);
2267
+ if (!context) {
2268
+ throw new Error(
2269
+ "ChainOfThought components must be used within ChainOfThought"
2270
+ );
2271
+ }
2272
+ return context;
2273
+ };
2274
+ var ChainOfThought = memo(
2275
+ ({
2276
+ className,
2277
+ open,
2278
+ defaultOpen = false,
2279
+ onOpenChange,
2280
+ children,
2281
+ ...props
2282
+ }) => {
2283
+ const [isOpen, setIsOpen] = useControllableState({
2284
+ prop: open,
2285
+ defaultProp: defaultOpen,
2286
+ onChange: onOpenChange
2287
+ });
2288
+ const chainOfThoughtContext = useMemo(
2289
+ () => ({ isOpen, setIsOpen }),
2290
+ [isOpen, setIsOpen]
2291
+ );
2292
+ return /* @__PURE__ */ jsx(ChainOfThoughtContext.Provider, { value: chainOfThoughtContext, children: /* @__PURE__ */ jsx(
2293
+ "div",
2294
+ {
2295
+ className: cn("not-prose max-w-prose space-y-4", className),
2296
+ ...props,
2297
+ children
2298
+ }
2299
+ ) });
2300
+ }
2301
+ );
2302
+ var ChainOfThoughtHeader = memo(
2303
+ ({ className, children, ...props }) => {
2304
+ const { isOpen, setIsOpen } = useChainOfThought();
2305
+ return /* @__PURE__ */ jsx(Collapsible, { onOpenChange: setIsOpen, open: isOpen, children: /* @__PURE__ */ jsxs(
2306
+ CollapsibleTrigger,
2307
+ {
2308
+ className: cn(
2309
+ "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
2310
+ className
2311
+ ),
2312
+ ...props,
2313
+ children: [
2314
+ /* @__PURE__ */ jsx(BrainIcon, { className: "size-4" }),
2315
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-start", children: children ?? "Chain of Thought" }),
2316
+ /* @__PURE__ */ jsx(
2317
+ ChevronDownIcon,
2318
+ {
2319
+ className: cn(
2320
+ "size-4 transition-transform",
2321
+ isOpen ? "rotate-180" : "rotate-0"
2322
+ )
2323
+ }
2324
+ )
2325
+ ]
2326
+ }
2327
+ ) });
2328
+ }
2329
+ );
2330
+ var ChainOfThoughtStep = memo(
2331
+ ({
2332
+ className,
2333
+ icon: Icon = DotIcon,
2334
+ label,
2335
+ description,
2336
+ status = "complete",
2337
+ children,
2338
+ ...props
2339
+ }) => {
2340
+ const statusStyles = {
2341
+ complete: "text-muted-foreground",
2342
+ active: "text-foreground",
2343
+ pending: "text-muted-foreground/50"
2344
+ };
2345
+ return /* @__PURE__ */ jsxs(
2346
+ "div",
2347
+ {
2348
+ className: cn(
2349
+ "flex gap-2 text-sm",
2350
+ statusStyles[status],
2351
+ "fade-in-0 slide-in-from-top-2 animate-in",
2352
+ className
2353
+ ),
2354
+ ...props,
2355
+ children: [
2356
+ /* @__PURE__ */ jsxs("div", { className: "relative mt-0.5", children: [
2357
+ /* @__PURE__ */ jsx(Icon, { className: "size-4" }),
2358
+ /* @__PURE__ */ jsx("div", { className: "-mx-px absolute top-7 bottom-0 left-1/2 w-px bg-border" })
2359
+ ] }),
2360
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2 overflow-hidden", children: [
2361
+ /* @__PURE__ */ jsx("div", { children: label }),
2362
+ description && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground text-xs", children: description }),
2363
+ children
2364
+ ] })
2365
+ ]
2366
+ }
2367
+ );
2368
+ }
2369
+ );
2370
+ var ChainOfThoughtSearchResults = memo(
2371
+ ({ className, ...props }) => /* @__PURE__ */ jsx(
2372
+ "div",
2373
+ {
2374
+ className: cn("flex flex-wrap items-center gap-2", className),
2375
+ ...props
2376
+ }
2377
+ )
2378
+ );
2379
+ var ChainOfThoughtSearchResult = memo(
2380
+ ({ className, children, ...props }) => /* @__PURE__ */ jsx(
2381
+ Badge,
2382
+ {
2383
+ className: cn("gap-1 px-2 py-0.5 font-normal text-xs", className),
2384
+ variant: "secondary",
2385
+ ...props,
2386
+ children
2387
+ }
2388
+ )
2389
+ );
2390
+ var ChainOfThoughtContent = memo(
2391
+ ({ className, children, ...props }) => {
2392
+ const { isOpen } = useChainOfThought();
2393
+ return /* @__PURE__ */ jsx(Collapsible, { open: isOpen, children: /* @__PURE__ */ jsx(
2394
+ CollapsibleContent,
2395
+ {
2396
+ className: cn(
2397
+ "mt-2 space-y-3",
2398
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
2399
+ className
2400
+ ),
2401
+ ...props,
2402
+ children
2403
+ }
2404
+ ) });
2405
+ }
2406
+ );
2407
+ var ChainOfThoughtImage = memo(
2408
+ ({ className, children, caption, ...props }) => /* @__PURE__ */ jsxs("div", { className: cn("mt-2 space-y-2", className), ...props, children: [
2409
+ /* @__PURE__ */ jsx("div", { className: "relative flex max-h-[22rem] items-center justify-center overflow-hidden rounded-lg bg-muted p-3", children }),
2410
+ caption && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: caption })
2411
+ ] })
2412
+ );
2413
+ ChainOfThought.displayName = "ChainOfThought";
2414
+ ChainOfThoughtHeader.displayName = "ChainOfThoughtHeader";
2415
+ ChainOfThoughtStep.displayName = "ChainOfThoughtStep";
2416
+ ChainOfThoughtSearchResults.displayName = "ChainOfThoughtSearchResults";
2417
+ ChainOfThoughtSearchResult.displayName = "ChainOfThoughtSearchResult";
2418
+ ChainOfThoughtContent.displayName = "ChainOfThoughtContent";
2419
+ ChainOfThoughtImage.displayName = "ChainOfThoughtImage";
2420
+ var ConfirmationContext = createContext(
2421
+ null
2422
+ );
2423
+ var useConfirmation = () => {
2424
+ const context = useContext(ConfirmationContext);
2425
+ if (!context) {
2426
+ throw new Error("Confirmation components must be used within Confirmation");
2427
+ }
2428
+ return context;
2429
+ };
2430
+ var Confirmation = ({
2431
+ className,
2432
+ approval,
2433
+ state,
2434
+ ...props
2435
+ }) => {
2436
+ if (!approval || state === "input-streaming" || state === "input-available") {
2437
+ return null;
2438
+ }
2439
+ return /* @__PURE__ */ jsx(ConfirmationContext.Provider, { value: { approval, state }, children: /* @__PURE__ */ jsx(Alert, { className: cn("flex flex-col gap-2", className), ...props }) });
2440
+ };
2441
+ var ConfirmationTitle = ({
2442
+ className,
2443
+ ...props
2444
+ }) => /* @__PURE__ */ jsx(AlertDescription, { className: cn("inline", className), ...props });
2445
+ var ConfirmationRequest = ({ children }) => {
2446
+ const { state } = useConfirmation();
2447
+ if (state !== "approval-requested") {
2448
+ return null;
2449
+ }
2450
+ return children;
2451
+ };
2452
+ var ConfirmationAccepted = ({
2453
+ children
2454
+ }) => {
2455
+ const { approval, state } = useConfirmation();
2456
+ if (!approval?.approved || state !== "approval-responded" && state !== "output-denied" && state !== "output-available") {
2457
+ return null;
2458
+ }
2459
+ return children;
2460
+ };
2461
+ var ConfirmationRejected = ({
2462
+ children
2463
+ }) => {
2464
+ const { approval, state } = useConfirmation();
2465
+ if (approval?.approved !== false || state !== "approval-responded" && state !== "output-denied" && state !== "output-available") {
2466
+ return null;
2467
+ }
2468
+ return children;
2469
+ };
2470
+ var ConfirmationActions = ({
2471
+ className,
2472
+ ...props
2473
+ }) => {
2474
+ const { state } = useConfirmation();
2475
+ if (state !== "approval-requested") {
2476
+ return null;
2477
+ }
2478
+ return /* @__PURE__ */ jsx(
2479
+ "div",
2480
+ {
2481
+ className: cn("flex items-center justify-end gap-2 self-end", className),
2482
+ ...props
2483
+ }
2484
+ );
2485
+ };
2486
+ var ConfirmationAction = (props) => /* @__PURE__ */ jsx(Button, { className: "h-8 px-3 text-sm", type: "button", ...props });
2487
+ var Controls = ({ className, ...props }) => /* @__PURE__ */ jsx(
2488
+ Controls$1,
2489
+ {
2490
+ className: cn(
2491
+ "gap-px overflow-hidden rounded-md border bg-card p-1 shadow-none!",
2492
+ "[&>button]:rounded-md [&>button]:border-none! [&>button]:bg-transparent! [&>button]:hover:bg-secondary!",
2493
+ className
2494
+ ),
2495
+ ...props
2496
+ }
2497
+ );
2498
+ var Command = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2499
+ Command$1,
2500
+ {
2501
+ ref,
2502
+ className: cn(
2503
+ "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
2504
+ className
2505
+ ),
2506
+ ...props
2507
+ }
2508
+ ));
2509
+ Command.displayName = Command$1.displayName;
2510
+ var CommandDialog = ({ children, ...props }) => {
2511
+ return /* @__PURE__ */ jsx(Dialog, { ...props, children: /* @__PURE__ */ jsx(DialogContent, { className: "overflow-hidden p-0", children: /* @__PURE__ */ jsx(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children }) }) });
2512
+ };
2513
+ var CommandInput = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
2514
+ /* @__PURE__ */ jsx(Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
2515
+ /* @__PURE__ */ jsx(
2516
+ Command$1.Input,
2517
+ {
2518
+ ref,
2519
+ className: cn(
2520
+ "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
2521
+ className
2522
+ ),
2523
+ ...props
2524
+ }
2525
+ )
2526
+ ] }));
2527
+ CommandInput.displayName = Command$1.Input.displayName;
2528
+ var CommandList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2529
+ Command$1.List,
2530
+ {
2531
+ ref,
2532
+ className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
2533
+ ...props
2534
+ }
2535
+ ));
2536
+ CommandList.displayName = Command$1.List.displayName;
2537
+ var CommandEmpty = React2.forwardRef((props, ref) => /* @__PURE__ */ jsx(
2538
+ Command$1.Empty,
2539
+ {
2540
+ ref,
2541
+ className: "py-6 text-center text-sm",
2542
+ ...props
2543
+ }
2544
+ ));
2545
+ CommandEmpty.displayName = Command$1.Empty.displayName;
2546
+ var CommandGroup = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2547
+ Command$1.Group,
2548
+ {
2549
+ ref,
2550
+ className: cn(
2551
+ "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
2552
+ className
2553
+ ),
2554
+ ...props
2555
+ }
2556
+ ));
2557
+ CommandGroup.displayName = Command$1.Group.displayName;
2558
+ var CommandSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2559
+ Command$1.Separator,
2560
+ {
2561
+ ref,
2562
+ className: cn("-mx-1 h-px bg-border", className),
2563
+ ...props
2564
+ }
2565
+ ));
2566
+ CommandSeparator.displayName = Command$1.Separator.displayName;
2567
+ var CommandItem = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2568
+ Command$1.Item,
2569
+ {
2570
+ ref,
2571
+ className: cn(
2572
+ "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
2573
+ className
2574
+ ),
2575
+ ...props
2576
+ }
2577
+ ));
2578
+ CommandItem.displayName = Command$1.Item.displayName;
2579
+ var CommandShortcut = ({
2580
+ className,
2581
+ ...props
2582
+ }) => {
2583
+ return /* @__PURE__ */ jsx(
2584
+ "span",
2585
+ {
2586
+ className: cn(
2587
+ "ml-auto text-xs tracking-widest text-muted-foreground",
2588
+ className
2589
+ ),
2590
+ ...props
2591
+ }
2592
+ );
2593
+ };
2594
+ CommandShortcut.displayName = "CommandShortcut";
2595
+ var ModelSelector = (props) => /* @__PURE__ */ jsx(Dialog, { ...props });
2596
+ var ModelSelectorTrigger = (props) => /* @__PURE__ */ jsx(DialogTrigger, { ...props });
2597
+ var ModelSelectorContent = ({
2598
+ className,
2599
+ children,
2600
+ title = "Model Selector",
2601
+ ...props
2602
+ }) => /* @__PURE__ */ jsxs(DialogContent, { className: cn("p-0", className), ...props, children: [
2603
+ /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: title }),
2604
+ /* @__PURE__ */ jsx(Command, { className: "**:data-[slot=command-input-wrapper]:h-auto", children })
2605
+ ] });
2606
+ var ModelSelectorDialog = (props) => /* @__PURE__ */ jsx(CommandDialog, { ...props });
2607
+ var ModelSelectorInput = ({
2608
+ className,
2609
+ ...props
2610
+ }) => /* @__PURE__ */ jsx(CommandInput, { className: cn("h-auto py-3.5", className), ...props });
2611
+ var ModelSelectorList = (props) => /* @__PURE__ */ jsx(CommandList, { ...props });
2612
+ var ModelSelectorEmpty = (props) => /* @__PURE__ */ jsx(CommandEmpty, { ...props });
2613
+ var ModelSelectorGroup = (props) => /* @__PURE__ */ jsx(CommandGroup, { ...props });
2614
+ var ModelSelectorItem = (props) => /* @__PURE__ */ jsx(CommandItem, { ...props });
2615
+ var ModelSelectorShortcut = (props) => /* @__PURE__ */ jsx(CommandShortcut, { ...props });
2616
+ var ModelSelectorSeparator = (props) => /* @__PURE__ */ jsx(CommandSeparator, { ...props });
2617
+ var ModelSelectorLogo = ({
2618
+ provider,
2619
+ className,
2620
+ ...props
2621
+ }) => /* @__PURE__ */ jsx(
2622
+ "img",
2623
+ {
2624
+ ...props,
2625
+ alt: `${provider} logo`,
2626
+ className: cn("size-3 dark:invert", className),
2627
+ height: 12,
2628
+ src: `https://models.dev/logos/${provider}.svg`,
2629
+ width: 12
2630
+ }
2631
+ );
2632
+ var ModelSelectorLogoGroup = ({
2633
+ className,
2634
+ ...props
2635
+ }) => /* @__PURE__ */ jsx(
2636
+ "div",
2637
+ {
2638
+ className: cn(
2639
+ "-space-x-1 flex shrink-0 items-center [&>img]:rounded-full [&>img]:bg-background [&>img]:p-px [&>img]:ring-1 dark:[&>img]:bg-foreground",
2640
+ className
2641
+ ),
2642
+ ...props
2643
+ }
2644
+ );
2645
+ var ModelSelectorName = ({
2646
+ className,
2647
+ ...props
2648
+ }) => /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate text-start", className), ...props });
2649
+ var providers = {
2650
+ github: {
2651
+ title: "Open in GitHub",
2652
+ createUrl: (url) => url,
2653
+ icon: /* @__PURE__ */ jsxs("svg", { fill: "currentColor", role: "img", viewBox: "0 0 24 24", children: [
2654
+ /* @__PURE__ */ jsx("title", { children: "GitHub" }),
2655
+ /* @__PURE__ */ jsx("path", { d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" })
2656
+ ] })
2657
+ },
2658
+ chatgpt: {
2659
+ title: "Open in ChatGPT",
2660
+ createUrl: (prompt) => `https://chatgpt.com/?${new URLSearchParams({
2661
+ hints: "search",
2662
+ prompt
2663
+ })}`,
2664
+ icon: /* @__PURE__ */ jsxs("svg", { fill: "currentColor", role: "img", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: [
2665
+ /* @__PURE__ */ jsx("title", { children: "OpenAI" }),
2666
+ /* @__PURE__ */ jsx("path", { d: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729z" })
2667
+ ] })
2668
+ },
2669
+ claude: {
2670
+ title: "Open in Claude",
2671
+ createUrl: (q) => `https://claude.ai/new?${new URLSearchParams({ q })}`,
2672
+ icon: /* @__PURE__ */ jsx("svg", { fill: "currentColor", role: "img", viewBox: "0 0 12 12", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("title", { children: "Claude" }) })
2673
+ },
2674
+ t3: {
2675
+ title: "Open in T3 Chat",
2676
+ createUrl: (q) => `https://t3.chat/new?${new URLSearchParams({ q })}`,
2677
+ icon: /* @__PURE__ */ jsx(MessageCircleIcon, {})
2678
+ },
2679
+ scira: {
2680
+ title: "Open in Scira",
2681
+ createUrl: (q) => `https://scira.ai/?${new URLSearchParams({ q })}`,
2682
+ icon: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 910 934", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("title", { children: "Scira AI" }) })
2683
+ },
2684
+ v0: {
2685
+ title: "Open in v0",
2686
+ createUrl: (q) => `https://v0.app?${new URLSearchParams({ q })}`,
2687
+ icon: /* @__PURE__ */ jsxs("svg", { fill: "currentColor", viewBox: "0 0 147 70", xmlns: "http://www.w3.org/2000/svg", children: [
2688
+ /* @__PURE__ */ jsx("title", { children: "v0" }),
2689
+ /* @__PURE__ */ jsx("path", { d: "M56 50.2031V14H70V60.1562C70 65.5928 65.5928 70 60.1562 70C57.5605 70 54.9982 68.9992 53.1562 67.1573L0 14H19.7969L56 50.2031Z" }),
2690
+ /* @__PURE__ */ jsx("path", { d: "M147 56H133V23.9531L100.953 56H133V70H96.6875C85.8144 70 77 61.1856 77 50.3125V14H91V46.1562L123.156 14H91V0H127.312C138.186 0 147 8.81439 147 19.6875V56Z" })
2691
+ ] })
2692
+ },
2693
+ cursor: {
2694
+ title: "Open in Cursor",
2695
+ createUrl: (text) => {
2696
+ if (typeof window === "undefined") return `https://cursor.com/link/prompt?text=${encodeURIComponent(text)}`;
2697
+ const url = new URL("https://cursor.com/link/prompt");
2698
+ url.searchParams.set("text", text);
2699
+ return url.toString();
2700
+ },
2701
+ icon: /* @__PURE__ */ jsx("svg", { version: "1.1", viewBox: "0 0 466.73 532.09", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("title", { children: "Cursor" }) })
2702
+ }
2703
+ };
2704
+ var OpenInContext = createContext(void 0);
2705
+ var useOpenInContext = () => {
2706
+ const context = useContext(OpenInContext);
2707
+ if (!context) {
2708
+ throw new Error("OpenIn components must be used within an OpenIn provider");
2709
+ }
2710
+ return context;
2711
+ };
2712
+ var OpenIn = ({ query, ...props }) => /* @__PURE__ */ jsx(OpenInContext.Provider, { value: { query }, children: /* @__PURE__ */ jsx(DropdownMenu, { ...props }) });
2713
+ var OpenInContent = ({ className, ...props }) => /* @__PURE__ */ jsx(
2714
+ DropdownMenuContent,
2715
+ {
2716
+ align: "start",
2717
+ className: cn("w-[240px]", className),
2718
+ ...props
2719
+ }
2720
+ );
2721
+ var OpenInItem = (props) => /* @__PURE__ */ jsx(DropdownMenuItem, { ...props });
2722
+ var OpenInLabel = (props) => /* @__PURE__ */ jsx(DropdownMenuLabel, { ...props });
2723
+ var OpenInSeparator = (props) => /* @__PURE__ */ jsx(DropdownMenuSeparator, { ...props });
2724
+ var OpenInTrigger = ({ children, ...props }) => /* @__PURE__ */ jsx(DropdownMenuTrigger, { ...props, asChild: true, children: children ?? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", children: [
2725
+ "Open in chat",
2726
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
2727
+ ] }) });
2728
+ var makeProviderItem = (key) => {
2729
+ return (props) => {
2730
+ const { query } = useOpenInContext();
2731
+ const p = providers[key];
2732
+ return /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, ...props, children: /* @__PURE__ */ jsxs(
2733
+ "a",
2734
+ {
2735
+ className: "flex items-center gap-2",
2736
+ href: p.createUrl(query),
2737
+ rel: "noopener",
2738
+ target: "_blank",
2739
+ children: [
2740
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: p.icon }),
2741
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: p.title }),
2742
+ /* @__PURE__ */ jsx(ExternalLinkIcon, { className: "size-4 shrink-0" })
2743
+ ]
2744
+ }
2745
+ ) });
2746
+ };
2747
+ };
2748
+ var OpenInChatGPT = makeProviderItem("chatgpt");
2749
+ var OpenInClaude = makeProviderItem("claude");
2750
+ var OpenInT3 = makeProviderItem("t3");
2751
+ var OpenInScira = makeProviderItem("scira");
2752
+ var OpenInv0 = makeProviderItem("v0");
2753
+ var OpenInCursor = makeProviderItem("cursor");
2754
+ var Panel = ({ className, ...props }) => /* @__PURE__ */ jsx(
2755
+ Panel$1,
2756
+ {
2757
+ className: cn(
2758
+ "m-4 overflow-hidden rounded-md border bg-card p-1",
2759
+ className
2760
+ ),
2761
+ ...props
2762
+ }
2763
+ );
2764
+ var PlanContext = createContext(null);
2765
+ var usePlan = () => {
2766
+ const context = useContext(PlanContext);
2767
+ if (!context) {
2768
+ throw new Error("Plan components must be used within Plan");
2769
+ }
2770
+ return context;
2771
+ };
2772
+ var Plan = ({
2773
+ className,
2774
+ isStreaming = false,
2775
+ children,
2776
+ ...props
2777
+ }) => /* @__PURE__ */ jsx(PlanContext.Provider, { value: { isStreaming }, children: /* @__PURE__ */ jsx(Collapsible, { asChild: true, "data-slot": "plan", ...props, children: /* @__PURE__ */ jsx(Card, { className: cn("shadow-none", className), children }) }) });
2778
+ var PlanHeader = ({ className, ...props }) => /* @__PURE__ */ jsx(
2779
+ CardHeader,
2780
+ {
2781
+ className: cn("flex items-start justify-between", className),
2782
+ "data-slot": "plan-header",
2783
+ ...props
2784
+ }
2785
+ );
2786
+ var PlanTitle = ({ children, ...props }) => {
2787
+ const { isStreaming } = usePlan();
2788
+ return /* @__PURE__ */ jsx(CardTitle, { "data-slot": "plan-title", ...props, children: isStreaming ? /* @__PURE__ */ jsx(Shimmer, { children }) : children });
2789
+ };
2790
+ var PlanDescription = ({
2791
+ className,
2792
+ children,
2793
+ ...props
2794
+ }) => {
2795
+ const { isStreaming } = usePlan();
2796
+ return /* @__PURE__ */ jsx(
2797
+ CardDescription,
2798
+ {
2799
+ className: cn("text-balance", className),
2800
+ "data-slot": "plan-description",
2801
+ ...props,
2802
+ children: isStreaming ? /* @__PURE__ */ jsx(Shimmer, { children }) : children
2803
+ }
2804
+ );
2805
+ };
2806
+ var PlanAction = (props) => /* @__PURE__ */ jsx(CardAction, { "data-slot": "plan-action", ...props });
2807
+ var PlanContent = (props) => /* @__PURE__ */ jsx(CollapsibleContent, { asChild: true, children: /* @__PURE__ */ jsx(CardContent, { "data-slot": "plan-content", ...props }) });
2808
+ var PlanFooter = (props) => /* @__PURE__ */ jsx(CardFooter, { "data-slot": "plan-footer", ...props });
2809
+ var PlanTrigger = ({ className, ...props }) => /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2810
+ Button,
2811
+ {
2812
+ className: cn("size-8", className),
2813
+ "data-slot": "plan-trigger",
2814
+ size: "icon",
2815
+ variant: "ghost",
2816
+ ...props,
2817
+ children: [
2818
+ /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "size-4" }),
2819
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle plan" })
2820
+ ]
2821
+ }
2822
+ ) });
2823
+ function InputGroup({ className, ...props }) {
2824
+ return /* @__PURE__ */ jsx(
2825
+ "div",
2826
+ {
2827
+ "data-slot": "input-group",
2828
+ role: "group",
2829
+ className: cn(
2830
+ " shadow-xs relative flex w-full items-center rounded-md outline-none transition-[color,box-shadow]",
2831
+ "h-9 has-[>textarea]:h-auto",
2832
+ // Variants based on alignment.
2833
+ "has-[>[data-align=inline-start]]:[&>input]:pl-2",
2834
+ "has-[>[data-align=inline-end]]:[&>input]:pr-2",
2835
+ "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
2836
+ "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
2837
+ // Focus state.
2838
+ "has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1",
2839
+ // Error state.
2840
+ "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
2841
+ className
2842
+ ),
2843
+ ...props
2844
+ }
2845
+ );
2846
+ }
2847
+ var inputGroupAddonVariants = cva(
2848
+ "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
2849
+ {
2850
+ variants: {
2851
+ align: {
2852
+ "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
2853
+ "inline-end": "order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]",
2854
+ "block-start": "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5",
2855
+ "block-end": "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5"
2856
+ }
2857
+ },
2858
+ defaultVariants: {
2859
+ align: "inline-start"
2860
+ }
2861
+ }
2862
+ );
2863
+ function InputGroupAddon({
2864
+ className,
2865
+ align = "inline-start",
2866
+ ...props
2867
+ }) {
2868
+ return /* @__PURE__ */ jsx(
2869
+ "div",
2870
+ {
2871
+ role: "group",
2872
+ "data-slot": "input-group-addon",
2873
+ "data-align": align,
2874
+ className: cn(inputGroupAddonVariants({ align }), className),
2875
+ onClick: (e) => {
2876
+ if (e.target.closest("button")) {
2877
+ return;
2878
+ }
2879
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
2880
+ },
2881
+ ...props
2882
+ }
2883
+ );
2884
+ }
2885
+ var inputGroupButtonVariants = cva(
2886
+ "flex items-center gap-2 text-sm shadow-none",
2887
+ {
2888
+ variants: {
2889
+ size: {
2890
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
2891
+ sm: "h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5",
2892
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
2893
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
2894
+ }
2895
+ },
2896
+ defaultVariants: {
2897
+ size: "xs"
2898
+ }
2899
+ }
2900
+ );
2901
+ function InputGroupButton({
2902
+ className,
2903
+ type = "button",
2904
+ variant = "ghost",
2905
+ size = "xs",
2906
+ ...props
2907
+ }) {
2908
+ return /* @__PURE__ */ jsx(
2909
+ Button,
2910
+ {
2911
+ type,
2912
+ "data-size": size,
2913
+ variant,
2914
+ className: cn(inputGroupButtonVariants({ size }), className),
2915
+ ...props
2916
+ }
2917
+ );
2918
+ }
2919
+ function InputGroupTextarea({
2920
+ className,
2921
+ ...props
2922
+ }) {
2923
+ return /* @__PURE__ */ jsx(
2924
+ Textarea,
2925
+ {
2926
+ "data-slot": "input-group-control",
2927
+ className: cn(
2928
+ "flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
2929
+ className
2930
+ ),
2931
+ ...props
2932
+ }
2933
+ );
2934
+ }
2935
+ var PromptInputController = createContext(
2936
+ null
2937
+ );
2938
+ var ProviderAttachmentsContext = createContext(
2939
+ null
2940
+ );
2941
+ var usePromptInputController = () => {
2942
+ const ctx = useContext(PromptInputController);
2943
+ if (!ctx) {
2944
+ throw new Error(
2945
+ "Wrap your component inside <PromptInputProvider> to use usePromptInputController()."
2946
+ );
2947
+ }
2948
+ return ctx;
2949
+ };
2950
+ var useOptionalPromptInputController = () => useContext(PromptInputController);
2951
+ var useProviderAttachments = () => {
2952
+ const ctx = useContext(ProviderAttachmentsContext);
2953
+ if (!ctx) {
2954
+ throw new Error(
2955
+ "Wrap your component inside <PromptInputProvider> to use useProviderAttachments()."
2956
+ );
2957
+ }
2958
+ return ctx;
2959
+ };
2960
+ var useOptionalProviderAttachments = () => useContext(ProviderAttachmentsContext);
2961
+ function PromptInputProvider({
2962
+ initialInput: initialTextInput = "",
2963
+ children
2964
+ }) {
2965
+ const [textInput, setTextInput] = useState(initialTextInput);
2966
+ const clearInput = useCallback(() => setTextInput(""), []);
2967
+ const [attachmentFiles, setAttachmentFiles] = useState([]);
2968
+ const fileInputRef = useRef(null);
2969
+ const openRef = useRef(() => {
2970
+ });
2971
+ const add = useCallback((files) => {
2972
+ const incoming = Array.from(files);
2973
+ if (incoming.length === 0) {
2974
+ return;
2975
+ }
2976
+ setAttachmentFiles(
2977
+ (prev) => prev.concat(
2978
+ incoming.map((file) => ({
2979
+ id: nanoid(),
2980
+ type: "file",
2981
+ url: typeof window !== "undefined" ? URL.createObjectURL(file) : "",
2982
+ mediaType: file.type,
2983
+ filename: file.name
2984
+ }))
2985
+ )
2986
+ );
2987
+ }, []);
2988
+ const remove = useCallback((id) => {
2989
+ setAttachmentFiles((prev) => {
2990
+ const found = prev.find((f) => f.id === id);
2991
+ if (found?.url && typeof window !== "undefined") {
2992
+ URL.revokeObjectURL(found.url);
2993
+ }
2994
+ return prev.filter((f) => f.id !== id);
2995
+ });
2996
+ }, []);
2997
+ const clear = useCallback(() => {
2998
+ setAttachmentFiles((prev) => {
2999
+ if (typeof window !== "undefined") {
3000
+ for (const f of prev) {
3001
+ if (f.url) {
3002
+ URL.revokeObjectURL(f.url);
3003
+ }
3004
+ }
3005
+ }
3006
+ return [];
3007
+ });
3008
+ }, []);
3009
+ const attachmentsRef = useRef(attachmentFiles);
3010
+ attachmentsRef.current = attachmentFiles;
3011
+ useEffect(() => {
3012
+ return () => {
3013
+ if (typeof window !== "undefined") {
3014
+ for (const f of attachmentsRef.current) {
3015
+ if (f.url) {
3016
+ URL.revokeObjectURL(f.url);
3017
+ }
3018
+ }
3019
+ }
3020
+ };
3021
+ }, []);
3022
+ const openFileDialog = useCallback(() => {
3023
+ openRef.current?.();
3024
+ }, []);
3025
+ const attachments = useMemo(
3026
+ () => ({
3027
+ files: attachmentFiles,
3028
+ add,
3029
+ remove,
3030
+ clear,
3031
+ openFileDialog,
3032
+ fileInputRef
3033
+ }),
3034
+ [attachmentFiles, add, remove, clear, openFileDialog]
3035
+ );
3036
+ const __registerFileInput = useCallback(
3037
+ (ref, open) => {
3038
+ fileInputRef.current = ref.current;
3039
+ openRef.current = open;
3040
+ },
3041
+ []
3042
+ );
3043
+ const controller = useMemo(
3044
+ () => ({
3045
+ textInput: {
3046
+ value: textInput,
3047
+ setInput: setTextInput,
3048
+ clear: clearInput
3049
+ },
3050
+ attachments,
3051
+ __registerFileInput
3052
+ }),
3053
+ [textInput, clearInput, attachments, __registerFileInput]
3054
+ );
3055
+ return /* @__PURE__ */ jsx(PromptInputController.Provider, { value: controller, children: /* @__PURE__ */ jsx(ProviderAttachmentsContext.Provider, { value: attachments, children }) });
3056
+ }
3057
+ var LocalAttachmentsContext = createContext(null);
3058
+ var usePromptInputAttachments = () => {
3059
+ const provider = useOptionalProviderAttachments();
3060
+ const local = useContext(LocalAttachmentsContext);
3061
+ const context = provider ?? local;
3062
+ if (!context) {
3063
+ throw new Error(
3064
+ "usePromptInputAttachments must be used within a PromptInput or PromptInputProvider"
3065
+ );
3066
+ }
3067
+ return context;
3068
+ };
3069
+ function PromptInputAttachment({
3070
+ data,
3071
+ className,
3072
+ ...props
3073
+ }) {
3074
+ const attachments = usePromptInputAttachments();
3075
+ const filename = data.filename || "";
3076
+ const mediaType = data.mediaType?.startsWith("image/") && data.url ? "image" : "file";
3077
+ const isImage = mediaType === "image";
3078
+ const attachmentLabel = filename || (isImage ? "Image" : "Attachment");
3079
+ return /* @__PURE__ */ jsxs(PromptInputHoverCard, { children: [
3080
+ /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
3081
+ "div",
3082
+ {
3083
+ className: cn(
3084
+ "group relative flex h-8 cursor-pointer select-none items-center gap-1.5 rounded-md border border-border px-1.5 font-medium text-sm transition-all hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
3085
+ className
3086
+ ),
3087
+ ...props,
3088
+ children: [
3089
+ /* @__PURE__ */ jsxs("div", { className: "relative size-5 shrink-0", children: [
3090
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex size-5 items-center justify-center overflow-hidden rounded bg-background transition-opacity group-hover:opacity-0", children: isImage ? /* @__PURE__ */ jsx(
3091
+ "img",
3092
+ {
3093
+ alt: filename || "attachment",
3094
+ className: "size-5 object-cover",
3095
+ height: 20,
3096
+ src: data.url,
3097
+ width: 20
3098
+ }
3099
+ ) : /* @__PURE__ */ jsx("div", { className: "flex size-5 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-3" }) }) }),
3100
+ /* @__PURE__ */ jsxs(
3101
+ Button,
3102
+ {
3103
+ "aria-label": "Remove attachment",
3104
+ className: "absolute inset-0 size-5 cursor-pointer rounded p-0 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 [&>svg]:size-2.5",
3105
+ onClick: (e) => {
3106
+ e.stopPropagation();
3107
+ attachments.remove(data.id);
3108
+ },
3109
+ type: "button",
3110
+ variant: "ghost",
3111
+ children: [
3112
+ /* @__PURE__ */ jsx(XIcon, {}),
3113
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Remove" })
3114
+ ]
3115
+ }
3116
+ )
3117
+ ] }),
3118
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: attachmentLabel })
3119
+ ]
3120
+ },
3121
+ data.id
3122
+ ) }),
3123
+ /* @__PURE__ */ jsx(PromptInputHoverCardContent, { className: "w-auto p-2", children: /* @__PURE__ */ jsxs("div", { className: "w-auto space-y-3", children: [
3124
+ isImage && /* @__PURE__ */ jsx("div", { className: "flex max-h-96 w-96 items-center justify-center overflow-hidden rounded-md border", children: /* @__PURE__ */ jsx(
3125
+ "img",
3126
+ {
3127
+ alt: filename || "attachment preview",
3128
+ className: "max-h-full max-w-full object-contain",
3129
+ height: 384,
3130
+ src: data.url,
3131
+ width: 448
3132
+ }
3133
+ ) }),
3134
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2.5", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1 px-0.5", children: [
3135
+ /* @__PURE__ */ jsx("h4", { className: "truncate font-semibold text-sm leading-none", children: filename || (isImage ? "Image" : "Attachment") }),
3136
+ data.mediaType && /* @__PURE__ */ jsx("p", { className: "truncate font-mono text-muted-foreground text-xs", children: data.mediaType })
3137
+ ] }) })
3138
+ ] }) })
3139
+ ] });
3140
+ }
3141
+ function PromptInputAttachments({
3142
+ children,
3143
+ className,
3144
+ ...props
3145
+ }) {
3146
+ const attachments = usePromptInputAttachments();
3147
+ if (!attachments.files.length) {
3148
+ return null;
3149
+ }
3150
+ return /* @__PURE__ */ jsx(
3151
+ "div",
3152
+ {
3153
+ className: cn("flex flex-wrap items-center gap-2 p-3 w-full", className),
3154
+ ...props,
3155
+ children: attachments.files.map((file) => /* @__PURE__ */ jsx(Fragment$1, { children: children(file) }, file.id))
3156
+ }
3157
+ );
3158
+ }
3159
+ var PromptInputActionAddAttachments = ({
3160
+ label = "Add photos or files",
3161
+ ...props
3162
+ }) => {
3163
+ const attachments = usePromptInputAttachments();
3164
+ return /* @__PURE__ */ jsxs(
3165
+ DropdownMenuItem,
3166
+ {
3167
+ ...props,
3168
+ onSelect: (e) => {
3169
+ e.preventDefault();
3170
+ attachments.openFileDialog();
3171
+ },
3172
+ children: [
3173
+ /* @__PURE__ */ jsx(ImageIcon, { className: "mr-2 size-4" }),
3174
+ " ",
3175
+ label
3176
+ ]
3177
+ }
3178
+ );
3179
+ };
3180
+ var PromptInput = ({
3181
+ className,
3182
+ accept,
3183
+ multiple,
3184
+ globalDrop,
3185
+ syncHiddenInput,
3186
+ maxFiles,
3187
+ maxFileSize,
3188
+ onError,
3189
+ onSubmit,
3190
+ children,
3191
+ ...props
3192
+ }) => {
3193
+ const controller = useOptionalPromptInputController();
3194
+ const usingProvider = !!controller;
3195
+ const inputRef = useRef(null);
3196
+ const formRef = useRef(null);
3197
+ const [items, setItems] = useState([]);
3198
+ const files = usingProvider ? controller.attachments.files : items;
3199
+ const filesRef = useRef(files);
3200
+ filesRef.current = files;
3201
+ const openFileDialogLocal = useCallback(() => {
3202
+ inputRef.current?.click();
3203
+ }, []);
3204
+ const matchesAccept = useCallback(
3205
+ (f) => {
3206
+ if (!accept || accept.trim() === "") {
3207
+ return true;
3208
+ }
3209
+ const patterns = accept.split(",").map((s) => s.trim()).filter(Boolean);
3210
+ return patterns.some((pattern) => {
3211
+ if (pattern.endsWith("/*")) {
3212
+ const prefix = pattern.slice(0, -1);
3213
+ return f.type.startsWith(prefix);
3214
+ }
3215
+ return f.type === pattern;
3216
+ });
3217
+ },
3218
+ [accept]
3219
+ );
3220
+ const addLocal = useCallback(
3221
+ (fileList) => {
3222
+ const incoming = Array.from(fileList);
3223
+ const accepted = incoming.filter((f) => matchesAccept(f));
3224
+ if (incoming.length && accepted.length === 0) {
3225
+ onError?.({
3226
+ code: "accept",
3227
+ message: "No files match the accepted types."
3228
+ });
3229
+ return;
3230
+ }
3231
+ const withinSize = (f) => maxFileSize ? f.size <= maxFileSize : true;
3232
+ const sized = accepted.filter(withinSize);
3233
+ if (accepted.length > 0 && sized.length === 0) {
3234
+ onError?.({
3235
+ code: "max_file_size",
3236
+ message: "All files exceed the maximum size."
3237
+ });
3238
+ return;
3239
+ }
3240
+ setItems((prev) => {
3241
+ const capacity = typeof maxFiles === "number" ? Math.max(0, maxFiles - prev.length) : void 0;
3242
+ const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
3243
+ if (typeof capacity === "number" && sized.length > capacity) {
3244
+ onError?.({
3245
+ code: "max_files",
3246
+ message: "Too many files. Some were not added."
3247
+ });
3248
+ }
3249
+ const next = [];
3250
+ for (const file of capped) {
3251
+ next.push({
3252
+ id: nanoid(),
3253
+ type: "file",
3254
+ url: typeof window !== "undefined" ? URL.createObjectURL(file) : "",
3255
+ mediaType: file.type,
3256
+ filename: file.name
3257
+ });
3258
+ }
3259
+ return prev.concat(next);
3260
+ });
3261
+ },
3262
+ [matchesAccept, maxFiles, maxFileSize, onError]
3263
+ );
3264
+ const removeLocal = useCallback(
3265
+ (id) => setItems((prev) => {
3266
+ const found = prev.find((file) => file.id === id);
3267
+ if (found?.url && typeof window !== "undefined") {
3268
+ URL.revokeObjectURL(found.url);
3269
+ }
3270
+ return prev.filter((file) => file.id !== id);
3271
+ }),
3272
+ []
3273
+ );
3274
+ const clearLocal = useCallback(
3275
+ () => setItems((prev) => {
3276
+ if (typeof window !== "undefined") {
3277
+ for (const file of prev) {
3278
+ if (file.url) {
3279
+ URL.revokeObjectURL(file.url);
3280
+ }
3281
+ }
3282
+ }
3283
+ return [];
3284
+ }),
3285
+ []
3286
+ );
3287
+ const add = usingProvider ? controller.attachments.add : addLocal;
3288
+ const remove = usingProvider ? controller.attachments.remove : removeLocal;
3289
+ const clear = usingProvider ? controller.attachments.clear : clearLocal;
3290
+ const openFileDialog = usingProvider ? controller.attachments.openFileDialog : openFileDialogLocal;
3291
+ useEffect(() => {
3292
+ if (!usingProvider) return;
3293
+ controller.__registerFileInput(inputRef, () => inputRef.current?.click());
3294
+ }, [usingProvider, controller]);
3295
+ useEffect(() => {
3296
+ if (syncHiddenInput && inputRef.current && files.length === 0) {
3297
+ inputRef.current.value = "";
3298
+ }
3299
+ }, [files, syncHiddenInput]);
3300
+ useEffect(() => {
3301
+ const form = formRef.current;
3302
+ if (!form) return;
3303
+ if (globalDrop) return;
3304
+ const onDragOver = (e) => {
3305
+ if (e.dataTransfer?.types?.includes("Files")) {
3306
+ e.preventDefault();
3307
+ }
3308
+ };
3309
+ const onDrop = (e) => {
3310
+ if (e.dataTransfer?.types?.includes("Files")) {
3311
+ e.preventDefault();
3312
+ }
3313
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
3314
+ add(e.dataTransfer.files);
3315
+ }
3316
+ };
3317
+ form.addEventListener("dragover", onDragOver);
3318
+ form.addEventListener("drop", onDrop);
3319
+ return () => {
3320
+ form.removeEventListener("dragover", onDragOver);
3321
+ form.removeEventListener("drop", onDrop);
3322
+ };
3323
+ }, [add, globalDrop]);
3324
+ useEffect(() => {
3325
+ if (!globalDrop) return;
3326
+ if (typeof document === "undefined") return;
3327
+ const onDragOver = (e) => {
3328
+ if (e.dataTransfer?.types?.includes("Files")) {
3329
+ e.preventDefault();
3330
+ }
3331
+ };
3332
+ const onDrop = (e) => {
3333
+ if (e.dataTransfer?.types?.includes("Files")) {
3334
+ e.preventDefault();
3335
+ }
3336
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
3337
+ add(e.dataTransfer.files);
3338
+ }
3339
+ };
3340
+ document.addEventListener("dragover", onDragOver);
3341
+ document.addEventListener("drop", onDrop);
3342
+ return () => {
3343
+ document.removeEventListener("dragover", onDragOver);
3344
+ document.removeEventListener("drop", onDrop);
3345
+ };
3346
+ }, [add, globalDrop]);
3347
+ useEffect(
3348
+ () => () => {
3349
+ if (!usingProvider && typeof window !== "undefined") {
3350
+ for (const f of filesRef.current) {
3351
+ if (f.url) URL.revokeObjectURL(f.url);
3352
+ }
3353
+ }
3354
+ },
3355
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3356
+ [usingProvider]
3357
+ );
3358
+ const handleChange = (event) => {
3359
+ if (event.currentTarget.files) {
3360
+ add(event.currentTarget.files);
3361
+ }
3362
+ event.currentTarget.value = "";
3363
+ };
3364
+ const convertBlobUrlToDataUrl = async (url) => {
3365
+ if (typeof window === "undefined") return null;
3366
+ try {
3367
+ const response = await fetch(url);
3368
+ const blob = await response.blob();
3369
+ return new Promise((resolve) => {
3370
+ const reader = new FileReader();
3371
+ reader.onloadend = () => resolve(reader.result);
3372
+ reader.onerror = () => resolve(null);
3373
+ reader.readAsDataURL(blob);
3374
+ });
3375
+ } catch {
3376
+ return null;
3377
+ }
3378
+ };
3379
+ const ctx = useMemo(
3380
+ () => ({
3381
+ files: files.map((item) => ({ ...item, id: item.id })),
3382
+ add,
3383
+ remove,
3384
+ clear,
3385
+ openFileDialog,
3386
+ fileInputRef: inputRef
3387
+ }),
3388
+ [files, add, remove, clear, openFileDialog]
3389
+ );
3390
+ const handleSubmit = (event) => {
3391
+ event.preventDefault();
3392
+ const form = event.currentTarget;
3393
+ const text = usingProvider ? controller.textInput.value : (() => {
3394
+ const formData = new FormData(form);
3395
+ return formData.get("message") || "";
3396
+ })();
3397
+ if (!usingProvider) {
3398
+ form.reset();
3399
+ }
3400
+ Promise.all(
3401
+ files.map(async ({ id, ...item }) => {
3402
+ if (item.url && item.url.startsWith("blob:")) {
3403
+ const dataUrl = await convertBlobUrlToDataUrl(item.url);
3404
+ return {
3405
+ ...item,
3406
+ url: dataUrl ?? item.url
3407
+ };
3408
+ }
3409
+ return item;
3410
+ })
3411
+ ).then((convertedFiles) => {
3412
+ try {
3413
+ const result = onSubmit({ text, files: convertedFiles }, event);
3414
+ if (result instanceof Promise) {
3415
+ result.then(() => {
3416
+ clear();
3417
+ if (usingProvider) {
3418
+ controller.textInput.clear();
3419
+ }
3420
+ }).catch(() => {
3421
+ });
3422
+ } else {
3423
+ clear();
3424
+ if (usingProvider) {
3425
+ controller.textInput.clear();
3426
+ }
3427
+ }
3428
+ } catch {
3429
+ }
3430
+ }).catch(() => {
3431
+ });
3432
+ };
3433
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
3434
+ /* @__PURE__ */ jsx(
3435
+ "input",
3436
+ {
3437
+ accept,
3438
+ "aria-label": "Upload files",
3439
+ className: "hidden",
3440
+ multiple,
3441
+ onChange: handleChange,
3442
+ ref: inputRef,
3443
+ title: "Upload files",
3444
+ type: "file"
3445
+ }
3446
+ ),
3447
+ /* @__PURE__ */ jsx(
3448
+ "form",
3449
+ {
3450
+ className: cn("w-full", className),
3451
+ onSubmit: handleSubmit,
3452
+ ref: formRef,
3453
+ ...props,
3454
+ children: /* @__PURE__ */ jsx(InputGroup, { className: "overflow-hidden", children })
3455
+ }
3456
+ )
3457
+ ] });
3458
+ return usingProvider ? inner : /* @__PURE__ */ jsx(LocalAttachmentsContext.Provider, { value: ctx, children: inner });
3459
+ };
3460
+ var PromptInputBody = ({
3461
+ className,
3462
+ ...props
3463
+ }) => /* @__PURE__ */ jsx("div", { className: cn("contents", className), ...props });
3464
+ var PromptInputTextarea = ({
3465
+ onChange,
3466
+ className,
3467
+ placeholder = "What would you like to know?",
3468
+ ...props
3469
+ }) => {
3470
+ const controller = useOptionalPromptInputController();
3471
+ const attachments = usePromptInputAttachments();
3472
+ const [isComposing, setIsComposing] = useState(false);
3473
+ const handleKeyDown = (e) => {
3474
+ if (e.key === "Enter") {
3475
+ if (isComposing || e.nativeEvent.isComposing) {
3476
+ return;
3477
+ }
3478
+ if (e.shiftKey) {
3479
+ return;
3480
+ }
3481
+ e.preventDefault();
3482
+ const form = e.currentTarget.form;
3483
+ const submitButton = form?.querySelector(
3484
+ 'button[type="submit"]'
3485
+ );
3486
+ if (submitButton?.disabled) {
3487
+ return;
3488
+ }
3489
+ form?.requestSubmit();
3490
+ }
3491
+ if (e.key === "Backspace" && e.currentTarget.value === "" && attachments.files.length > 0) {
3492
+ e.preventDefault();
3493
+ const lastAttachment = attachments.files.at(-1);
3494
+ if (lastAttachment) {
3495
+ attachments.remove(lastAttachment.id);
3496
+ }
3497
+ }
3498
+ };
3499
+ const handlePaste = (event) => {
3500
+ const items = event.clipboardData?.items;
3501
+ if (!items) {
3502
+ return;
3503
+ }
3504
+ const files = [];
3505
+ for (const item of items) {
3506
+ if (item.kind === "file") {
3507
+ const file = item.getAsFile();
3508
+ if (file) {
3509
+ files.push(file);
3510
+ }
3511
+ }
3512
+ }
3513
+ if (files.length > 0) {
3514
+ event.preventDefault();
3515
+ attachments.add(files);
3516
+ }
3517
+ };
3518
+ const controlledProps = controller ? {
3519
+ value: controller.textInput.value,
3520
+ onChange: (e) => {
3521
+ controller.textInput.setInput(e.currentTarget.value);
3522
+ onChange?.(e);
3523
+ }
3524
+ } : {
3525
+ onChange
3526
+ };
3527
+ return /* @__PURE__ */ jsx(
3528
+ InputGroupTextarea,
3529
+ {
3530
+ className: cn("field-sizing-content max-h-48 min-h-16", className),
3531
+ name: "message",
3532
+ onCompositionEnd: () => setIsComposing(false),
3533
+ onCompositionStart: () => setIsComposing(true),
3534
+ onKeyDown: handleKeyDown,
3535
+ onPaste: handlePaste,
3536
+ placeholder,
3537
+ ...props,
3538
+ ...controlledProps
3539
+ }
3540
+ );
3541
+ };
3542
+ var PromptInputHeader = ({
3543
+ className,
3544
+ ...props
3545
+ }) => /* @__PURE__ */ jsx(
3546
+ InputGroupAddon,
3547
+ {
3548
+ align: "block-end",
3549
+ className: cn("order-first flex-wrap gap-1", className),
3550
+ ...props
3551
+ }
3552
+ );
3553
+ var PromptInputFooter = ({
3554
+ className,
3555
+ ...props
3556
+ }) => /* @__PURE__ */ jsx(
3557
+ InputGroupAddon,
3558
+ {
3559
+ align: "block-end",
3560
+ className: cn("justify-between gap-1", className),
3561
+ ...props
3562
+ }
3563
+ );
3564
+ var PromptInputTools = ({
3565
+ className,
3566
+ ...props
3567
+ }) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), ...props });
3568
+ var PromptInputButton = ({
3569
+ variant = "ghost",
3570
+ className,
3571
+ size,
3572
+ ...props
3573
+ }) => {
3574
+ const newSize = size ?? (Children.count(props.children) > 1 ? "sm" : "icon-sm");
3575
+ return /* @__PURE__ */ jsx(
3576
+ InputGroupButton,
3577
+ {
3578
+ className: cn(className),
3579
+ size: newSize,
3580
+ type: "button",
3581
+ variant,
3582
+ ...props
3583
+ }
3584
+ );
3585
+ };
3586
+ var PromptInputActionMenu = (props) => /* @__PURE__ */ jsx(DropdownMenu, { ...props });
3587
+ var PromptInputActionMenuTrigger = ({
3588
+ className,
3589
+ children,
3590
+ ...props
3591
+ }) => /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(PromptInputButton, { className, ...props, children: children ?? /* @__PURE__ */ jsx(PlusIcon, { className: "size-4" }) }) });
3592
+ var PromptInputActionMenuContent = ({
3593
+ className,
3594
+ ...props
3595
+ }) => /* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: cn(className), ...props });
3596
+ var PromptInputActionMenuItem = ({
3597
+ className,
3598
+ ...props
3599
+ }) => /* @__PURE__ */ jsx(DropdownMenuItem, { className: cn(className), ...props });
3600
+ var PromptInputSubmit = ({
3601
+ className,
3602
+ variant = "default",
3603
+ size = "icon-sm",
3604
+ status,
3605
+ children,
3606
+ ...props
3607
+ }) => {
3608
+ let Icon = /* @__PURE__ */ jsx(CornerDownLeftIcon, { className: "size-4" });
3609
+ if (status === "submitted") {
3610
+ Icon = /* @__PURE__ */ jsx(Loader2Icon, { className: "size-4 animate-spin" });
3611
+ } else if (status === "streaming") {
3612
+ Icon = /* @__PURE__ */ jsx(SquareIcon, { className: "size-4" });
3613
+ } else if (status === "error") {
3614
+ Icon = /* @__PURE__ */ jsx(XIcon, { className: "size-4" });
3615
+ }
3616
+ return /* @__PURE__ */ jsx(
3617
+ InputGroupButton,
3618
+ {
3619
+ "aria-label": "Submit",
3620
+ className: cn(className),
3621
+ size,
3622
+ type: "submit",
3623
+ variant,
3624
+ ...props,
3625
+ children: children ?? Icon
3626
+ }
3627
+ );
3628
+ };
3629
+ var PromptInputSpeechButton = ({
3630
+ className,
3631
+ textareaRef,
3632
+ onTranscriptionChange,
3633
+ ...props
3634
+ }) => {
3635
+ const [isListening, setIsListening] = useState(false);
3636
+ const [recognition, setRecognition] = useState(
3637
+ null
3638
+ );
3639
+ const recognitionRef = useRef(null);
3640
+ useEffect(() => {
3641
+ if (typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window)) {
3642
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
3643
+ const speechRecognition = new SpeechRecognition();
3644
+ speechRecognition.continuous = true;
3645
+ speechRecognition.interimResults = true;
3646
+ speechRecognition.lang = "en-US";
3647
+ speechRecognition.onstart = () => {
3648
+ setIsListening(true);
3649
+ };
3650
+ speechRecognition.onend = () => {
3651
+ setIsListening(false);
3652
+ };
3653
+ speechRecognition.onresult = (event) => {
3654
+ let finalTranscript = "";
3655
+ for (let i = event.resultIndex; i < event.results.length; i++) {
3656
+ const result = event.results[i];
3657
+ if (result.isFinal) {
3658
+ finalTranscript += result[0]?.transcript ?? "";
3659
+ }
3660
+ }
3661
+ if (finalTranscript && textareaRef?.current) {
3662
+ const textarea = textareaRef.current;
3663
+ const currentValue = textarea.value;
3664
+ const newValue = currentValue + (currentValue ? " " : "") + finalTranscript;
3665
+ textarea.value = newValue;
3666
+ textarea.dispatchEvent(new Event("input", { bubbles: true }));
3667
+ onTranscriptionChange?.(newValue);
3668
+ }
3669
+ };
3670
+ speechRecognition.onerror = (event) => {
3671
+ console.error("Speech recognition error:", event.error);
3672
+ setIsListening(false);
3673
+ };
3674
+ recognitionRef.current = speechRecognition;
3675
+ setRecognition(speechRecognition);
3676
+ }
3677
+ return () => {
3678
+ if (recognitionRef.current) {
3679
+ recognitionRef.current.stop();
3680
+ }
3681
+ };
3682
+ }, [textareaRef, onTranscriptionChange]);
3683
+ const toggleListening = useCallback(() => {
3684
+ if (!recognition) {
3685
+ return;
3686
+ }
3687
+ if (isListening) {
3688
+ recognition.stop();
3689
+ } else {
3690
+ recognition.start();
3691
+ }
3692
+ }, [recognition, isListening]);
3693
+ return /* @__PURE__ */ jsx(
3694
+ PromptInputButton,
3695
+ {
3696
+ className: cn(
3697
+ "relative transition-all duration-200",
3698
+ isListening && "animate-pulse bg-accent text-accent-foreground",
3699
+ className
3700
+ ),
3701
+ disabled: !recognition,
3702
+ onClick: toggleListening,
3703
+ ...props,
3704
+ children: /* @__PURE__ */ jsx(MicIcon, { className: "size-4" })
3705
+ }
3706
+ );
3707
+ };
3708
+ var PromptInputSelect = (props) => /* @__PURE__ */ jsx(Select, { ...props });
3709
+ var PromptInputSelectTrigger = ({
3710
+ className,
3711
+ ...props
3712
+ }) => /* @__PURE__ */ jsx(
3713
+ SelectTrigger,
3714
+ {
3715
+ className: cn(
3716
+ "border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors",
3717
+ "hover:bg-accent hover:text-foreground aria-expanded:bg-accent aria-expanded:text-foreground",
3718
+ className
3719
+ ),
3720
+ ...props
3721
+ }
3722
+ );
3723
+ var PromptInputSelectContent = ({
3724
+ className,
3725
+ ...props
3726
+ }) => /* @__PURE__ */ jsx(SelectContent, { className: cn(className), ...props });
3727
+ var PromptInputSelectItem = ({
3728
+ className,
3729
+ ...props
3730
+ }) => /* @__PURE__ */ jsx(SelectItem, { className: cn(className), ...props });
3731
+ var PromptInputSelectValue = ({
3732
+ className,
3733
+ ...props
3734
+ }) => /* @__PURE__ */ jsx(SelectValue, { className: cn(className), ...props });
3735
+ var PromptInputHoverCard = ({
3736
+ openDelay = 0,
3737
+ closeDelay = 0,
3738
+ ...props
3739
+ }) => /* @__PURE__ */ jsx(HoverCard, { closeDelay, openDelay, ...props });
3740
+ var PromptInputHoverCardTrigger = (props) => /* @__PURE__ */ jsx(HoverCardTrigger, { ...props });
3741
+ var PromptInputHoverCardContent = ({
3742
+ align = "start",
3743
+ ...props
3744
+ }) => /* @__PURE__ */ jsx(HoverCardContent, { align, ...props });
3745
+ var PromptInputTabsList = ({
3746
+ className,
3747
+ ...props
3748
+ }) => /* @__PURE__ */ jsx("div", { className: cn(className), ...props });
3749
+ var PromptInputTab = ({
3750
+ className,
3751
+ ...props
3752
+ }) => /* @__PURE__ */ jsx("div", { className: cn(className), ...props });
3753
+ var PromptInputTabLabel = ({
3754
+ className,
3755
+ ...props
3756
+ }) => /* @__PURE__ */ jsx(
3757
+ "h3",
3758
+ {
3759
+ className: cn(
3760
+ "mb-2 px-3 font-medium text-muted-foreground text-xs",
3761
+ className
3762
+ ),
3763
+ ...props
3764
+ }
3765
+ );
3766
+ var PromptInputTabBody = ({
3767
+ className,
3768
+ ...props
3769
+ }) => /* @__PURE__ */ jsx("div", { className: cn("space-y-1", className), ...props });
3770
+ var PromptInputTabItem = ({
3771
+ className,
3772
+ ...props
3773
+ }) => /* @__PURE__ */ jsx(
3774
+ "div",
3775
+ {
3776
+ className: cn(
3777
+ "flex items-center gap-2 px-3 py-2 text-xs hover:bg-accent",
3778
+ className
3779
+ ),
3780
+ ...props
3781
+ }
3782
+ );
3783
+ var PromptInputCommand = ({
3784
+ className,
3785
+ ...props
3786
+ }) => /* @__PURE__ */ jsx(Command, { className: cn(className), ...props });
3787
+ var PromptInputCommandInput = ({
3788
+ className,
3789
+ ...props
3790
+ }) => /* @__PURE__ */ jsx(CommandInput, { className: cn(className), ...props });
3791
+ var PromptInputCommandList = ({
3792
+ className,
3793
+ ...props
3794
+ }) => /* @__PURE__ */ jsx(CommandList, { className: cn(className), ...props });
3795
+ var PromptInputCommandEmpty = ({
3796
+ className,
3797
+ ...props
3798
+ }) => /* @__PURE__ */ jsx(CommandEmpty, { className: cn(className), ...props });
3799
+ var PromptInputCommandGroup = ({
3800
+ className,
3801
+ ...props
3802
+ }) => /* @__PURE__ */ jsx(CommandGroup, { className: cn(className), ...props });
3803
+ var PromptInputCommandItem = ({
3804
+ className,
3805
+ ...props
3806
+ }) => /* @__PURE__ */ jsx(CommandItem, { className: cn(className), ...props });
3807
+ var PromptInputCommandSeparator = ({
3808
+ className,
3809
+ ...props
3810
+ }) => /* @__PURE__ */ jsx(CommandSeparator, { className: cn(className), ...props });
3811
+ var QueueItem = ({ className, ...props }) => /* @__PURE__ */ jsx(
3812
+ "li",
3813
+ {
3814
+ className: cn(
3815
+ "group flex flex-col gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-muted",
3816
+ className
3817
+ ),
3818
+ ...props
3819
+ }
3820
+ );
3821
+ var QueueItemIndicator = ({
3822
+ completed = false,
3823
+ className,
3824
+ ...props
3825
+ }) => /* @__PURE__ */ jsx(
3826
+ "span",
3827
+ {
3828
+ className: cn(
3829
+ "mt-0.5 inline-block size-2.5 rounded-full border",
3830
+ completed ? "border-muted-foreground/20 bg-muted-foreground/10" : "border-muted-foreground/50",
3831
+ className
3832
+ ),
3833
+ ...props
3834
+ }
3835
+ );
3836
+ var QueueItemContent = ({
3837
+ completed = false,
3838
+ className,
3839
+ ...props
3840
+ }) => /* @__PURE__ */ jsx(
3841
+ "span",
3842
+ {
3843
+ className: cn(
3844
+ "line-clamp-1 grow break-words",
3845
+ completed ? "text-muted-foreground/50 line-through" : "text-muted-foreground",
3846
+ className
3847
+ ),
3848
+ ...props
3849
+ }
3850
+ );
3851
+ var QueueItemDescription = ({
3852
+ completed = false,
3853
+ className,
3854
+ ...props
3855
+ }) => /* @__PURE__ */ jsx(
3856
+ "div",
3857
+ {
3858
+ className: cn(
3859
+ "ml-6 text-xs",
3860
+ completed ? "text-muted-foreground/40 line-through" : "text-muted-foreground",
3861
+ className
3862
+ ),
3863
+ ...props
3864
+ }
3865
+ );
3866
+ var QueueItemActions = ({
3867
+ className,
3868
+ ...props
3869
+ }) => /* @__PURE__ */ jsx("div", { className: cn("flex gap-1", className), ...props });
3870
+ var QueueItemAction = ({
3871
+ className,
3872
+ ...props
3873
+ }) => /* @__PURE__ */ jsx(
3874
+ Button,
3875
+ {
3876
+ className: cn(
3877
+ "size-auto rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:bg-muted-foreground/10 hover:text-foreground group-hover:opacity-100",
3878
+ className
3879
+ ),
3880
+ size: "icon",
3881
+ type: "button",
3882
+ variant: "ghost",
3883
+ ...props
3884
+ }
3885
+ );
3886
+ var QueueItemAttachment = ({
3887
+ className,
3888
+ ...props
3889
+ }) => /* @__PURE__ */ jsx("div", { className: cn("mt-1 flex flex-wrap gap-2", className), ...props });
3890
+ var QueueItemImage = ({
3891
+ className,
3892
+ ...props
3893
+ }) => /* @__PURE__ */ jsx(
3894
+ "img",
3895
+ {
3896
+ alt: "",
3897
+ className: cn("h-8 w-8 rounded border object-cover", className),
3898
+ height: 32,
3899
+ width: 32,
3900
+ ...props
3901
+ }
3902
+ );
3903
+ var QueueItemFile = ({
3904
+ children,
3905
+ className,
3906
+ ...props
3907
+ }) => /* @__PURE__ */ jsxs(
3908
+ "span",
3909
+ {
3910
+ className: cn(
3911
+ "flex items-center gap-1 rounded border bg-muted px-2 py-1 text-xs",
3912
+ className
3913
+ ),
3914
+ ...props,
3915
+ children: [
3916
+ /* @__PURE__ */ jsx(PaperclipIcon, { size: 12 }),
3917
+ /* @__PURE__ */ jsx("span", { className: "max-w-[100px] truncate", children })
3918
+ ]
3919
+ }
3920
+ );
3921
+ var QueueList = ({
3922
+ children,
3923
+ className,
3924
+ ...props
3925
+ }) => /* @__PURE__ */ jsx(ScrollArea, { className: cn("-mb-1 mt-2", className), ...props, children: /* @__PURE__ */ jsx("div", { className: "max-h-40 pr-4", children: /* @__PURE__ */ jsx("ul", { children }) }) });
3926
+ var QueueSection = ({
3927
+ className,
3928
+ defaultOpen = true,
3929
+ ...props
3930
+ }) => /* @__PURE__ */ jsx(Collapsible, { className: cn(className), defaultOpen, ...props });
3931
+ var QueueSectionTrigger = ({
3932
+ children,
3933
+ className,
3934
+ ...props
3935
+ }) => /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3936
+ "button",
3937
+ {
3938
+ className: cn(
3939
+ "group flex w-full items-center justify-between rounded-md bg-muted/40 px-3 py-2 text-start font-medium text-muted-foreground text-sm transition-colors hover:bg-muted",
3940
+ className
3941
+ ),
3942
+ type: "button",
3943
+ ...props,
3944
+ children
3945
+ }
3946
+ ) });
3947
+ var QueueSectionLabel = ({
3948
+ count,
3949
+ label,
3950
+ icon,
3951
+ className,
3952
+ ...props
3953
+ }) => /* @__PURE__ */ jsxs("span", { className: cn("flex items-center gap-2", className), ...props, children: [
3954
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "group-data-[state=closed]:-rotate-90 size-4 transition-transform" }),
3955
+ icon,
3956
+ /* @__PURE__ */ jsxs("span", { children: [
3957
+ count,
3958
+ " ",
3959
+ label
3960
+ ] })
3961
+ ] });
3962
+ var QueueSectionContent = ({
3963
+ className,
3964
+ ...props
3965
+ }) => /* @__PURE__ */ jsx(CollapsibleContent, { className: cn(className), ...props });
3966
+ var Queue = ({ className, ...props }) => /* @__PURE__ */ jsx(
3967
+ "div",
3968
+ {
3969
+ className: cn(
3970
+ "flex flex-col gap-2 rounded-xl border border-border bg-background px-3 pt-2 pb-2 shadow-xs",
3971
+ className
3972
+ ),
3973
+ ...props
3974
+ }
3975
+ );
3976
+ var TaskItemFile = ({
3977
+ children,
3978
+ className,
3979
+ ...props
3980
+ }) => /* @__PURE__ */ jsx(
3981
+ "div",
3982
+ {
3983
+ className: cn(
3984
+ "inline-flex items-center gap-1 rounded-md border bg-secondary px-1.5 py-0.5 text-foreground text-xs",
3985
+ className
3986
+ ),
3987
+ ...props,
3988
+ children
3989
+ }
3990
+ );
3991
+ var TaskItem = ({ children, className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("text-muted-foreground text-sm", className), ...props, children });
3992
+ var Task = ({
3993
+ defaultOpen = true,
3994
+ className,
3995
+ ...props
3996
+ }) => /* @__PURE__ */ jsx(Collapsible, { className: cn(className), defaultOpen, ...props });
3997
+ var TaskTrigger = ({
3998
+ children,
3999
+ className,
4000
+ title,
4001
+ ...props
4002
+ }) => /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, className: cn("group", className), ...props, children: children ?? /* @__PURE__ */ jsxs("div", { className: "flex w-full cursor-pointer items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground", children: [
4003
+ /* @__PURE__ */ jsx(SearchIcon, { className: "size-4" }),
4004
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: title }),
4005
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 transition-transform group-data-[state=open]:rotate-180" })
4006
+ ] }) });
4007
+ var TaskContent = ({
4008
+ children,
4009
+ className,
4010
+ ...props
4011
+ }) => /* @__PURE__ */ jsx(
4012
+ CollapsibleContent,
4013
+ {
4014
+ className: cn(
4015
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
4016
+ className
4017
+ ),
4018
+ ...props,
4019
+ children: /* @__PURE__ */ jsx("div", { className: "mt-4 space-y-2 border-muted border-l-2 pl-4", children })
4020
+ }
4021
+ );
4022
+ var Tool = ({ className, ...props }) => /* @__PURE__ */ jsx(
4023
+ Collapsible,
4024
+ {
4025
+ className: cn("not-prose mb-4 w-full rounded-md border", className),
4026
+ ...props
4027
+ }
4028
+ );
4029
+ var getStatusBadge = (status) => {
4030
+ const labels = {
4031
+ "input-streaming": "Pending",
4032
+ "input-available": "Running",
4033
+ "approval-requested": "Awaiting Approval",
4034
+ "approval-responded": "Responded",
4035
+ "output-available": "Completed",
4036
+ "output-error": "Error",
4037
+ "output-denied": "Denied"
4038
+ };
4039
+ const icons = {
4040
+ "input-streaming": /* @__PURE__ */ jsx(CircleIcon, { className: "size-4" }),
4041
+ "input-available": /* @__PURE__ */ jsx(ClockIcon, { className: "size-4 animate-pulse" }),
4042
+ "approval-requested": /* @__PURE__ */ jsx(ClockIcon, { className: "size-4 text-yellow-600" }),
4043
+ "approval-responded": /* @__PURE__ */ jsx(CheckCircleIcon, { className: "size-4 text-blue-600" }),
4044
+ "output-available": /* @__PURE__ */ jsx(CheckCircleIcon, { className: "size-4 text-green-600" }),
4045
+ "output-error": /* @__PURE__ */ jsx(XCircleIcon, { className: "size-4 text-red-600" }),
4046
+ "output-denied": /* @__PURE__ */ jsx(XCircleIcon, { className: "size-4 text-orange-600" })
4047
+ };
4048
+ return /* @__PURE__ */ jsxs(Badge, { className: "gap-1.5 rounded-full text-xs", variant: "secondary", children: [
4049
+ icons[status],
4050
+ labels[status]
4051
+ ] });
4052
+ };
4053
+ var ToolHeader = ({
4054
+ className,
4055
+ title,
4056
+ type,
4057
+ state,
4058
+ ...props
4059
+ }) => /* @__PURE__ */ jsxs(
4060
+ CollapsibleTrigger,
4061
+ {
4062
+ className: cn(
4063
+ "flex w-full items-center justify-between gap-4 p-3",
4064
+ className
4065
+ ),
4066
+ ...props,
4067
+ children: [
4068
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4069
+ /* @__PURE__ */ jsx(WrenchIcon, { className: "size-4 text-muted-foreground" }),
4070
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: title ?? type.split("-").slice(1).join("-") }),
4071
+ getStatusBadge(state)
4072
+ ] }),
4073
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" })
4074
+ ]
4075
+ }
4076
+ );
4077
+ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ jsx(
4078
+ CollapsibleContent,
4079
+ {
4080
+ className: cn(
4081
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
4082
+ className
4083
+ ),
4084
+ ...props
4085
+ }
4086
+ );
4087
+ var ToolInput = ({ className, input, ...props }) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-2 overflow-hidden p-4", className), ...props, children: [
4088
+ /* @__PURE__ */ jsx("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Parameters" }),
4089
+ /* @__PURE__ */ jsx("div", { className: "rounded-md bg-muted/50", children: /* @__PURE__ */ jsx(CodeBlock, { code: JSON.stringify(input, null, 2), language: "json" }) })
4090
+ ] });
4091
+ var ToolOutput = ({
4092
+ className,
4093
+ output,
4094
+ errorText,
4095
+ ...props
4096
+ }) => {
4097
+ if (!(output || errorText)) {
4098
+ return null;
4099
+ }
4100
+ let Output = /* @__PURE__ */ jsx("div", { children: output });
4101
+ if (typeof output === "object" && !isValidElement(output)) {
4102
+ Output = /* @__PURE__ */ jsx(CodeBlock, { code: JSON.stringify(output, null, 2), language: "json" });
4103
+ } else if (typeof output === "string") {
4104
+ Output = /* @__PURE__ */ jsx(CodeBlock, { code: output, language: "json" });
4105
+ }
4106
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2 p-4", className), ...props, children: [
4107
+ /* @__PURE__ */ jsx("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: errorText ? "Error" : "Result" }),
4108
+ /* @__PURE__ */ jsxs(
4109
+ "div",
4110
+ {
4111
+ className: cn(
4112
+ "overflow-x-auto rounded-md text-xs [&_table]:w-full",
4113
+ errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground"
4114
+ ),
4115
+ children: [
4116
+ errorText && /* @__PURE__ */ jsx("div", { children: errorText }),
4117
+ Output
4118
+ ]
4119
+ }
4120
+ )
4121
+ ] });
4122
+ };
4123
+ var Toolbar = ({ className, ...props }) => /* @__PURE__ */ jsx(
4124
+ NodeToolbar,
4125
+ {
4126
+ className: cn(
4127
+ "flex items-center gap-1 rounded-sm border bg-background p-1.5",
4128
+ className
4129
+ ),
4130
+ position: Position.Bottom,
4131
+ ...props
4132
+ }
4133
+ );
4134
+ var Canvas = ({ children, ...props }) => /* @__PURE__ */ jsxs(
4135
+ ReactFlow,
4136
+ {
4137
+ deleteKeyCode: ["Backspace", "Delete"],
4138
+ fitView: true,
4139
+ panOnDrag: false,
4140
+ panOnScroll: true,
4141
+ selectionOnDrag: true,
4142
+ zoomOnDoubleClick: false,
4143
+ ...props,
4144
+ children: [
4145
+ /* @__PURE__ */ jsx(Background, { bgColor: "var(--ac-sidebar)" }),
4146
+ children
4147
+ ]
4148
+ }
4149
+ );
4150
+ var Checkpoint = ({
4151
+ className,
4152
+ children,
4153
+ ...props
4154
+ }) => /* @__PURE__ */ jsxs(
4155
+ "div",
4156
+ {
4157
+ className: cn("flex items-center gap-0.5 text-muted-foreground overflow-hidden", className),
4158
+ ...props,
4159
+ children: [
4160
+ children,
4161
+ /* @__PURE__ */ jsx(Separator, {})
4162
+ ]
4163
+ }
4164
+ );
4165
+ var CheckpointIcon = ({
4166
+ className,
4167
+ children,
4168
+ ...props
4169
+ }) => children ?? /* @__PURE__ */ jsx(BookmarkIcon, { className: cn("size-4 shrink-0", className), ...props });
4170
+ var CheckpointTrigger = ({
4171
+ children,
4172
+ className,
4173
+ variant = "ghost",
4174
+ size = "sm",
4175
+ tooltip,
4176
+ ...props
4177
+ }) => tooltip ? /* @__PURE__ */ jsxs(Tooltip, { children: [
4178
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size, type: "button", variant, ...props, children }) }),
4179
+ /* @__PURE__ */ jsx(TooltipContent, { align: "start", side: "bottom", children: tooltip })
4180
+ ] }) : /* @__PURE__ */ jsx(Button, { size, type: "button", variant, ...props, children });
4181
+ var HALF = 0.5;
4182
+ var Connection = ({
4183
+ fromX,
4184
+ fromY,
4185
+ toX,
4186
+ toY
4187
+ }) => /* @__PURE__ */ jsxs("g", { children: [
4188
+ /* @__PURE__ */ jsx(
4189
+ "path",
4190
+ {
4191
+ className: "animated",
4192
+ d: `M${fromX},${fromY} C ${fromX + (toX - fromX) * HALF},${fromY} ${fromX + (toX - fromX) * HALF},${toY} ${toX},${toY}`,
4193
+ fill: "none",
4194
+ stroke: "var(--ac-ring)",
4195
+ strokeWidth: 1
4196
+ }
4197
+ ),
4198
+ /* @__PURE__ */ jsx(
4199
+ "circle",
4200
+ {
4201
+ cx: toX,
4202
+ cy: toY,
4203
+ fill: "#fff",
4204
+ r: 3,
4205
+ stroke: "var(--ac-ring)",
4206
+ strokeWidth: 1
4207
+ }
4208
+ )
4209
+ ] });
4210
+ var Temporary = ({
4211
+ id,
4212
+ sourceX,
4213
+ sourceY,
4214
+ targetX,
4215
+ targetY,
4216
+ sourcePosition,
4217
+ targetPosition
4218
+ }) => {
4219
+ const [edgePath] = getSimpleBezierPath({
4220
+ sourceX,
4221
+ sourceY,
4222
+ sourcePosition,
4223
+ targetX,
4224
+ targetY,
4225
+ targetPosition
4226
+ });
4227
+ return /* @__PURE__ */ jsx(
4228
+ BaseEdge,
4229
+ {
4230
+ className: "stroke-1 stroke-ring",
4231
+ id,
4232
+ path: edgePath,
4233
+ style: {
4234
+ strokeDasharray: "5, 5"
4235
+ }
4236
+ }
4237
+ );
4238
+ };
4239
+ var getHandleCoordsByPosition = (node, handlePosition) => {
4240
+ const handleType = handlePosition === Position.Left ? "target" : "source";
4241
+ const handle = node.internals.handleBounds?.[handleType]?.find(
4242
+ (h) => h.position === handlePosition
4243
+ );
4244
+ if (!handle) {
4245
+ return [0, 0];
4246
+ }
4247
+ let offsetX = handle.width / 2;
4248
+ let offsetY = handle.height / 2;
4249
+ switch (handlePosition) {
4250
+ case Position.Left:
4251
+ offsetX = 0;
4252
+ break;
4253
+ case Position.Right:
4254
+ offsetX = handle.width;
4255
+ break;
4256
+ case Position.Top:
4257
+ offsetY = 0;
4258
+ break;
4259
+ case Position.Bottom:
4260
+ offsetY = handle.height;
4261
+ break;
4262
+ default:
4263
+ throw new Error(`Invalid handle position: ${handlePosition}`);
4264
+ }
4265
+ const x = node.internals.positionAbsolute.x + handle.x + offsetX;
4266
+ const y = node.internals.positionAbsolute.y + handle.y + offsetY;
4267
+ return [x, y];
4268
+ };
4269
+ var getEdgeParams = (source, target) => {
4270
+ const sourcePos = Position.Right;
4271
+ const [sx, sy] = getHandleCoordsByPosition(source, sourcePos);
4272
+ const targetPos = Position.Left;
4273
+ const [tx, ty] = getHandleCoordsByPosition(target, targetPos);
4274
+ return {
4275
+ sx,
4276
+ sy,
4277
+ tx,
4278
+ ty,
4279
+ sourcePos,
4280
+ targetPos
4281
+ };
4282
+ };
4283
+ var Animated = ({ id, source, target, markerEnd, style }) => {
4284
+ const sourceNode = useInternalNode(source);
4285
+ const targetNode = useInternalNode(target);
4286
+ if (!(sourceNode && targetNode)) {
4287
+ return null;
4288
+ }
4289
+ const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(
4290
+ sourceNode,
4291
+ targetNode
4292
+ );
4293
+ const [edgePath] = getBezierPath({
4294
+ sourceX: sx,
4295
+ sourceY: sy,
4296
+ sourcePosition: sourcePos,
4297
+ targetX: tx,
4298
+ targetY: ty,
4299
+ targetPosition: targetPos
4300
+ });
4301
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4302
+ /* @__PURE__ */ jsx(BaseEdge, { id, markerEnd, path: edgePath, style }),
4303
+ /* @__PURE__ */ jsx("circle", { fill: "var(--ac-primary)", r: "4", children: /* @__PURE__ */ jsx("animateMotion", { dur: "2s", path: edgePath, repeatCount: "indefinite" }) })
4304
+ ] });
4305
+ };
4306
+ var Edge = {
4307
+ Temporary,
4308
+ Animated
4309
+ };
4310
+ var Node = ({ handles, className, ...props }) => /* @__PURE__ */ jsxs(
4311
+ Card,
4312
+ {
4313
+ className: cn(
4314
+ "node-container relative size-full h-auto w-sm gap-0 rounded-md p-0",
4315
+ className
4316
+ ),
4317
+ ...props,
4318
+ children: [
4319
+ handles.target && /* @__PURE__ */ jsx(Handle, { position: Position.Left, type: "target" }),
4320
+ handles.source && /* @__PURE__ */ jsx(Handle, { position: Position.Right, type: "source" }),
4321
+ props.children
4322
+ ]
4323
+ }
4324
+ );
4325
+ var NodeHeader = ({ className, ...props }) => /* @__PURE__ */ jsx(
4326
+ CardHeader,
4327
+ {
4328
+ className: cn("gap-0.5 rounded-t-md border-b bg-secondary p-3!", className),
4329
+ ...props
4330
+ }
4331
+ );
4332
+ var NodeTitle = (props) => /* @__PURE__ */ jsx(CardTitle, { ...props });
4333
+ var NodeDescription = (props) => /* @__PURE__ */ jsx(CardDescription, { ...props });
4334
+ var NodeAction = (props) => /* @__PURE__ */ jsx(CardAction, { ...props });
4335
+ var NodeContent = ({ className, ...props }) => /* @__PURE__ */ jsx(CardContent, { className: cn("p-3", className), ...props });
4336
+ var NodeFooter = ({ className, ...props }) => /* @__PURE__ */ jsx(
4337
+ CardFooter,
4338
+ {
4339
+ className: cn("rounded-b-md border-t bg-secondary p-3!", className),
4340
+ ...props
4341
+ }
4342
+ );
4343
+ var Image = ({
4344
+ base64,
4345
+ uint8Array,
4346
+ mediaType,
4347
+ ...props
4348
+ }) => /* @__PURE__ */ jsx(
4349
+ "img",
4350
+ {
4351
+ ...props,
4352
+ alt: props.alt,
4353
+ className: cn(
4354
+ "h-auto max-w-full overflow-hidden rounded-md",
4355
+ props.className
4356
+ ),
4357
+ src: `data:${mediaType};base64,${base64}`
4358
+ }
4359
+ );
4360
+
4361
+ export { Image as AIImage, Artifact, ArtifactAction, ArtifactActions, ArtifactClose, ArtifactContent, ArtifactDescription, ArtifactHeader, ArtifactTitle, Canvas, ChainOfThought, ChainOfThoughtContent, ChainOfThoughtHeader, ChainOfThoughtImage, ChainOfThoughtSearchResult, ChainOfThoughtSearchResults, ChainOfThoughtStep, Checkpoint, CheckpointIcon, CheckpointTrigger, CodeBlock, CodeBlockCopyButton, ComponentRenderer, Confirmation, ConfirmationAccepted, ConfirmationAction, ConfirmationActions, ConfirmationRejected, ConfirmationRequest, ConfirmationTitle, Connection, Context, ContextCacheUsage, ContextContent, ContextContentBody, ContextContentFooter, ContextContentHeader, ContextInputUsage, ContextOutputUsage, ContextReasoningUsage, ContextTrigger, Controls, Edge, FollowupButtons, InlineCitation, InlineCitationCard, InlineCitationCardBody, InlineCitationCardTrigger, InlineCitationCarousel, InlineCitationCarouselContent, InlineCitationCarouselHeader, InlineCitationCarouselIndex, InlineCitationCarouselItem, InlineCitationCarouselNext, InlineCitationCarouselPrev, InlineCitationQuote, InlineCitationSource, InlineCitationText, Message, MessageAction, MessageActions, MessageAttachment, MessageAttachments, MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, MessageContent, MessageFeedback, MessageResponse, MessageToolbar, ModelSelector, ModelSelectorContent, ModelSelectorDialog, ModelSelectorEmpty, ModelSelectorGroup, ModelSelectorInput, ModelSelectorItem, ModelSelectorList, ModelSelectorLogo, ModelSelectorLogoGroup, ModelSelectorName, ModelSelectorSeparator, ModelSelectorShortcut, ModelSelectorTrigger, Node, NodeAction, NodeContent, NodeDescription, NodeFooter, NodeHeader, NodeTitle, OpenIn, OpenInChatGPT, OpenInClaude, OpenInContent, OpenInCursor, OpenInItem, OpenInLabel, OpenInScira, OpenInSeparator, OpenInT3, OpenInTrigger, OpenInv0, Panel, Plan, PlanAction, PlanContent, PlanDescription, PlanFooter, PlanHeader, PlanTitle, PlanTrigger, PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuItem, PromptInputActionMenuTrigger, PromptInputAttachment, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputCommand, PromptInputCommandEmpty, PromptInputCommandGroup, PromptInputCommandInput, PromptInputCommandItem, PromptInputCommandList, PromptInputCommandSeparator, PromptInputFooter, PromptInputHeader, PromptInputHoverCard, PromptInputHoverCardContent, PromptInputHoverCardTrigger, PromptInputProvider, PromptInputSelect, PromptInputSelectContent, PromptInputSelectItem, PromptInputSelectTrigger, PromptInputSelectValue, PromptInputSpeechButton, PromptInputSubmit, PromptInputTab, PromptInputTabBody, PromptInputTabItem, PromptInputTabLabel, PromptInputTabsList, PromptInputTextarea, PromptInputTools, Queue, QueueItem, QueueItemAction, QueueItemActions, QueueItemAttachment, QueueItemContent, QueueItemDescription, QueueItemFile, QueueItemImage, QueueItemIndicator, QueueList, QueueSection, QueueSectionContent, QueueSectionLabel, QueueSectionTrigger, Reasoning, ReasoningContent, ReasoningTrigger, Shimmer, Source, Sources, SourcesContent, SourcesTrigger, Suggestion, Suggestions, Task, TaskContent, TaskItem, TaskItemFile, TaskTrigger, ThinkingSpinner, Tool, ToolContent, ToolHeader, ToolInput, ToolOutput, Toolbar, WebPreview, WebPreviewBody, WebPreviewConsole, WebPreviewNavigation, WebPreviewNavigationButton, WebPreviewUrl, highlightCode, usePromptInputAttachments, usePromptInputController, useProviderAttachments, useReasoning };
4362
+ //# sourceMappingURL=ai-elements.js.map
4363
+ //# sourceMappingURL=ai-elements.js.map