@rodrigocoliveira/agno-react 1.0.1 → 1.0.3

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 (158) hide show
  1. package/README.md +363 -83
  2. package/dist/components/GenerativeUIRenderer.d.ts +21 -0
  3. package/dist/components/GenerativeUIRenderer.d.ts.map +1 -0
  4. package/dist/context/AgnoContext.d.ts +16 -0
  5. package/dist/context/AgnoContext.d.ts.map +1 -0
  6. package/dist/context/ToolHandlerContext.d.ts +44 -0
  7. package/dist/context/ToolHandlerContext.d.ts.map +1 -0
  8. package/dist/hooks/useAgnoActions.d.ts +25 -0
  9. package/dist/hooks/useAgnoActions.d.ts.map +1 -0
  10. package/dist/hooks/useAgnoChat.d.ts +22 -0
  11. package/dist/hooks/useAgnoChat.d.ts.map +1 -0
  12. package/dist/hooks/useAgnoCustomEvents.d.ts +38 -0
  13. package/dist/hooks/useAgnoCustomEvents.d.ts.map +1 -0
  14. package/dist/hooks/useAgnoEvals.d.ts +39 -0
  15. package/dist/hooks/useAgnoEvals.d.ts.map +1 -0
  16. package/dist/hooks/useAgnoKnowledge.d.ts +56 -0
  17. package/dist/hooks/useAgnoKnowledge.d.ts.map +1 -0
  18. package/dist/hooks/useAgnoMemory.d.ts +42 -0
  19. package/dist/hooks/useAgnoMemory.d.ts.map +1 -0
  20. package/dist/hooks/useAgnoMetrics.d.ts +51 -0
  21. package/dist/hooks/useAgnoMetrics.d.ts.map +1 -0
  22. package/dist/hooks/useAgnoSession.d.ts +38 -0
  23. package/dist/hooks/useAgnoSession.d.ts.map +1 -0
  24. package/dist/hooks/useAgnoToolExecution.d.ts +70 -0
  25. package/dist/hooks/useAgnoToolExecution.d.ts.map +1 -0
  26. package/dist/hooks/useAgnoTraces.d.ts +51 -0
  27. package/dist/hooks/useAgnoTraces.d.ts.map +1 -0
  28. package/dist/index.d.ts +27 -723
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +932 -1052
  31. package/dist/index.js.map +24 -0
  32. package/dist/index.mjs +816 -909
  33. package/dist/index.mjs.map +24 -0
  34. package/dist/ui/components/artifact.d.ts +24 -0
  35. package/dist/ui/components/artifact.d.ts.map +1 -0
  36. package/dist/ui/components/audio-recorder.d.ts +32 -0
  37. package/dist/ui/components/audio-recorder.d.ts.map +1 -0
  38. package/dist/ui/components/code-block.d.ts +15 -0
  39. package/dist/ui/components/code-block.d.ts.map +1 -0
  40. package/dist/ui/components/conversation.d.ts +17 -0
  41. package/dist/ui/components/conversation.d.ts.map +1 -0
  42. package/dist/ui/components/file-preview-card.d.ts +13 -0
  43. package/dist/ui/components/file-preview-card.d.ts.map +1 -0
  44. package/dist/ui/components/file-preview-modal.d.ts +8 -0
  45. package/dist/ui/components/file-preview-modal.d.ts.map +1 -0
  46. package/dist/ui/components/image-lightbox.d.ts +12 -0
  47. package/dist/ui/components/image-lightbox.d.ts.map +1 -0
  48. package/dist/ui/components/message.d.ts +19 -0
  49. package/dist/ui/components/message.d.ts.map +1 -0
  50. package/dist/ui/components/prompt-input/attachments.d.ts +21 -0
  51. package/dist/ui/components/prompt-input/attachments.d.ts.map +1 -0
  52. package/dist/ui/components/prompt-input/buttons.d.ts +19 -0
  53. package/dist/ui/components/prompt-input/buttons.d.ts.map +1 -0
  54. package/dist/ui/components/prompt-input/command.d.ts +17 -0
  55. package/dist/ui/components/prompt-input/command.d.ts.map +1 -0
  56. package/dist/ui/components/prompt-input/context.d.ts +36 -0
  57. package/dist/ui/components/prompt-input/context.d.ts.map +1 -0
  58. package/dist/ui/components/prompt-input/drop-zone.d.ts +7 -0
  59. package/dist/ui/components/prompt-input/drop-zone.d.ts.map +1 -0
  60. package/dist/ui/components/prompt-input/footer.d.ts +11 -0
  61. package/dist/ui/components/prompt-input/footer.d.ts.map +1 -0
  62. package/dist/ui/components/prompt-input/index.d.ts +25 -0
  63. package/dist/ui/components/prompt-input/index.d.ts.map +1 -0
  64. package/dist/ui/components/prompt-input/model-select.d.ts +13 -0
  65. package/dist/ui/components/prompt-input/model-select.d.ts.map +1 -0
  66. package/dist/ui/components/prompt-input/prompt-input.d.ts +22 -0
  67. package/dist/ui/components/prompt-input/prompt-input.d.ts.map +1 -0
  68. package/dist/ui/components/prompt-input/provider.d.ts +6 -0
  69. package/dist/ui/components/prompt-input/provider.d.ts.map +1 -0
  70. package/dist/ui/components/prompt-input/speech.d.ts +51 -0
  71. package/dist/ui/components/prompt-input/speech.d.ts.map +1 -0
  72. package/dist/ui/components/prompt-input/tabs.d.ts +12 -0
  73. package/dist/ui/components/prompt-input/tabs.d.ts.map +1 -0
  74. package/dist/ui/components/prompt-input/textarea.d.ts +5 -0
  75. package/dist/ui/components/prompt-input/textarea.d.ts.map +1 -0
  76. package/dist/ui/components/response.d.ts +5 -0
  77. package/dist/ui/components/response.d.ts.map +1 -0
  78. package/dist/ui/components/smart-timestamp.d.ts +8 -0
  79. package/dist/ui/components/smart-timestamp.d.ts.map +1 -0
  80. package/dist/ui/components/streaming-indicator.d.ts +8 -0
  81. package/dist/ui/components/streaming-indicator.d.ts.map +1 -0
  82. package/dist/ui/components/tool.d.ts +24 -0
  83. package/dist/ui/components/tool.d.ts.map +1 -0
  84. package/dist/ui/composed/AgnoChatInput.d.ts +44 -0
  85. package/dist/ui/composed/AgnoChatInput.d.ts.map +1 -0
  86. package/dist/ui/composed/AgnoChatInterface.d.ts +49 -0
  87. package/dist/ui/composed/AgnoChatInterface.d.ts.map +1 -0
  88. package/dist/ui/composed/AgnoMessageItem.d.ts +38 -0
  89. package/dist/ui/composed/AgnoMessageItem.d.ts.map +1 -0
  90. package/dist/ui/composed/agno-chat/agno-chat.d.ts +9 -0
  91. package/dist/ui/composed/agno-chat/agno-chat.d.ts.map +1 -0
  92. package/dist/ui/composed/agno-chat/context.d.ts +33 -0
  93. package/dist/ui/composed/agno-chat/context.d.ts.map +1 -0
  94. package/dist/ui/composed/agno-chat/empty-state.d.ts +6 -0
  95. package/dist/ui/composed/agno-chat/empty-state.d.ts.map +1 -0
  96. package/dist/ui/composed/agno-chat/error-bar.d.ts +5 -0
  97. package/dist/ui/composed/agno-chat/error-bar.d.ts.map +1 -0
  98. package/dist/ui/composed/agno-chat/index.d.ts +33 -0
  99. package/dist/ui/composed/agno-chat/index.d.ts.map +1 -0
  100. package/dist/ui/composed/agno-chat/input.d.ts +39 -0
  101. package/dist/ui/composed/agno-chat/input.d.ts.map +1 -0
  102. package/dist/ui/composed/agno-chat/messages.d.ts +21 -0
  103. package/dist/ui/composed/agno-chat/messages.d.ts.map +1 -0
  104. package/dist/ui/composed/agno-chat/suggested-prompts.d.ts +7 -0
  105. package/dist/ui/composed/agno-chat/suggested-prompts.d.ts.map +1 -0
  106. package/dist/ui/composed/agno-chat/tool-status.d.ts +5 -0
  107. package/dist/ui/composed/agno-chat/tool-status.d.ts.map +1 -0
  108. package/dist/ui/composed/index.d.ts +9 -0
  109. package/dist/ui/composed/index.d.ts.map +1 -0
  110. package/dist/ui/index.d.ts +59 -0
  111. package/dist/ui/index.d.ts.map +1 -0
  112. package/dist/ui/lib/cn.d.ts +3 -0
  113. package/dist/ui/lib/cn.d.ts.map +1 -0
  114. package/dist/ui/lib/file-utils.d.ts +20 -0
  115. package/dist/ui/lib/file-utils.d.ts.map +1 -0
  116. package/dist/ui/lib/format-timestamp.d.ts +16 -0
  117. package/dist/ui/lib/format-timestamp.d.ts.map +1 -0
  118. package/dist/ui/primitives/accordion.d.ts +8 -0
  119. package/dist/ui/primitives/accordion.d.ts.map +1 -0
  120. package/dist/ui/primitives/avatar.d.ts +7 -0
  121. package/dist/ui/primitives/avatar.d.ts.map +1 -0
  122. package/dist/ui/primitives/badge.d.ts +10 -0
  123. package/dist/ui/primitives/badge.d.ts.map +1 -0
  124. package/dist/ui/primitives/button.d.ts +12 -0
  125. package/dist/ui/primitives/button.d.ts.map +1 -0
  126. package/dist/ui/primitives/collapsible.d.ts +6 -0
  127. package/dist/ui/primitives/collapsible.d.ts.map +1 -0
  128. package/dist/ui/primitives/command.d.ts +79 -0
  129. package/dist/ui/primitives/command.d.ts.map +1 -0
  130. package/dist/ui/primitives/dialog.d.ts +26 -0
  131. package/dist/ui/primitives/dialog.d.ts.map +1 -0
  132. package/dist/ui/primitives/dropdown-menu.d.ts +28 -0
  133. package/dist/ui/primitives/dropdown-menu.d.ts.map +1 -0
  134. package/dist/ui/primitives/hover-card.d.ts +7 -0
  135. package/dist/ui/primitives/hover-card.d.ts.map +1 -0
  136. package/dist/ui/primitives/index.d.ts +16 -0
  137. package/dist/ui/primitives/index.d.ts.map +1 -0
  138. package/dist/ui/primitives/input-group.d.ts +17 -0
  139. package/dist/ui/primitives/input-group.d.ts.map +1 -0
  140. package/dist/ui/primitives/select.d.ts +14 -0
  141. package/dist/ui/primitives/select.d.ts.map +1 -0
  142. package/dist/ui/primitives/tooltip.d.ts +8 -0
  143. package/dist/ui/primitives/tooltip.d.ts.map +1 -0
  144. package/dist/ui/types.d.ts +56 -0
  145. package/dist/ui/types.d.ts.map +1 -0
  146. package/dist/ui.d.ts +2 -0
  147. package/dist/ui.d.ts.map +1 -0
  148. package/dist/ui.js +4059 -0
  149. package/dist/ui.js.map +60 -0
  150. package/dist/ui.mjs +4044 -0
  151. package/dist/ui.mjs.map +60 -0
  152. package/dist/utils/component-registry.d.ts +63 -0
  153. package/dist/utils/component-registry.d.ts.map +1 -0
  154. package/dist/utils/ui-helpers.d.ts +165 -0
  155. package/dist/utils/ui-helpers.d.ts.map +1 -0
  156. package/package.json +122 -17
  157. package/LICENSE +0 -21
  158. package/dist/index.d.mts +0 -724
package/dist/ui.js ADDED
@@ -0,0 +1,4059 @@
1
+ "use client";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
19
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
20
+ var __toCommonJS = (from) => {
21
+ var entry = __moduleCache.get(from), desc;
22
+ if (entry)
23
+ return entry;
24
+ entry = __defProp({}, "__esModule", { value: true });
25
+ if (from && typeof from === "object" || typeof from === "function")
26
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
27
+ get: () => from[key],
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ }));
30
+ __moduleCache.set(from, entry);
31
+ return entry;
32
+ };
33
+ var __export = (target, all) => {
34
+ for (var name in all)
35
+ __defProp(target, name, {
36
+ get: all[name],
37
+ enumerable: true,
38
+ configurable: true,
39
+ set: (newValue) => all[name] = () => newValue
40
+ });
41
+ };
42
+
43
+ // src/ui.ts
44
+ var exports_ui = {};
45
+ __export(exports_ui, {
46
+ useProviderAttachments: () => useProviderAttachments,
47
+ usePromptInputDropZone: () => usePromptInputDropZone,
48
+ usePromptInputController: () => usePromptInputController,
49
+ usePromptInputAttachments: () => usePromptInputAttachments,
50
+ useAgnoChatContext: () => useAgnoChatContext,
51
+ isPreviewable: () => isPreviewable,
52
+ getFilePreviewType: () => getFilePreviewType,
53
+ getFileExtension: () => getFileExtension,
54
+ formatSmartTimestamp: () => formatSmartTimestamp,
55
+ formatFullTimestamp: () => formatFullTimestamp,
56
+ formatFileSize: () => formatFileSize,
57
+ cn: () => cn,
58
+ buttonVariants: () => buttonVariants,
59
+ badgeVariants: () => badgeVariants,
60
+ TooltipTrigger: () => TooltipTrigger,
61
+ TooltipProvider: () => TooltipProvider,
62
+ TooltipContent: () => TooltipContent,
63
+ Tooltip: () => Tooltip,
64
+ ToolOutput: () => ToolOutput,
65
+ ToolInput: () => ToolInput,
66
+ ToolHeader: () => ToolHeader,
67
+ ToolContent: () => ToolContent,
68
+ Tool: () => Tool,
69
+ StreamingIndicator: () => StreamingIndicator,
70
+ SmartTimestamp: () => SmartTimestamp,
71
+ SelectValue: () => SelectValue,
72
+ SelectTrigger: () => SelectTrigger,
73
+ SelectSeparator: () => SelectSeparator,
74
+ SelectScrollUpButton: () => SelectScrollUpButton,
75
+ SelectScrollDownButton: () => SelectScrollDownButton,
76
+ SelectLabel: () => SelectLabel,
77
+ SelectItem: () => SelectItem,
78
+ SelectGroup: () => SelectGroup,
79
+ SelectContent: () => SelectContent,
80
+ Select: () => Select,
81
+ Response: () => Response,
82
+ PromptInputTools: () => PromptInputTools,
83
+ PromptInputTextarea: () => PromptInputTextarea,
84
+ PromptInputTabsList: () => PromptInputTabsList,
85
+ PromptInputTabLabel: () => PromptInputTabLabel,
86
+ PromptInputTabItem: () => PromptInputTabItem,
87
+ PromptInputTabBody: () => PromptInputTabBody,
88
+ PromptInputTab: () => PromptInputTab,
89
+ PromptInputSubmit: () => PromptInputSubmit,
90
+ PromptInputSpeechButton: () => PromptInputSpeechButton,
91
+ PromptInputProvider: () => PromptInputProvider,
92
+ PromptInputModelSelectValue: () => PromptInputModelSelectValue,
93
+ PromptInputModelSelectTrigger: () => PromptInputModelSelectTrigger,
94
+ PromptInputModelSelectItem: () => PromptInputModelSelectItem,
95
+ PromptInputModelSelectContent: () => PromptInputModelSelectContent,
96
+ PromptInputModelSelect: () => PromptInputModelSelect,
97
+ PromptInputHeader: () => PromptInputHeader,
98
+ PromptInputFooter: () => PromptInputFooter,
99
+ PromptInputDropZone: () => PromptInputDropZone,
100
+ PromptInputCommandSeparator: () => PromptInputCommandSeparator,
101
+ PromptInputCommandList: () => PromptInputCommandList,
102
+ PromptInputCommandItem: () => PromptInputCommandItem,
103
+ PromptInputCommandInput: () => PromptInputCommandInput,
104
+ PromptInputCommandGroup: () => PromptInputCommandGroup,
105
+ PromptInputCommandEmpty: () => PromptInputCommandEmpty,
106
+ PromptInputCommand: () => PromptInputCommand,
107
+ PromptInputButton: () => PromptInputButton,
108
+ PromptInputBody: () => PromptInputBody,
109
+ PromptInputAttachments: () => PromptInputAttachments,
110
+ PromptInputAttachment: () => PromptInputAttachment,
111
+ PromptInputActionMenuTrigger: () => PromptInputActionMenuTrigger,
112
+ PromptInputActionMenuItem: () => PromptInputActionMenuItem,
113
+ PromptInputActionMenuContent: () => PromptInputActionMenuContent,
114
+ PromptInputActionMenu: () => PromptInputActionMenu,
115
+ PromptInputActionAddAttachments: () => PromptInputActionAddAttachments,
116
+ PromptInput: () => PromptInput,
117
+ MessageContent: () => MessageContent,
118
+ MessageAvatar: () => MessageAvatar,
119
+ Message: () => Message,
120
+ InputGroupTextarea: () => InputGroupTextarea,
121
+ InputGroupText: () => InputGroupText,
122
+ InputGroupInput: () => InputGroupInput,
123
+ InputGroupButton: () => InputGroupButton,
124
+ InputGroupAddon: () => InputGroupAddon,
125
+ InputGroup: () => InputGroup,
126
+ ImageLightbox: () => ImageLightbox,
127
+ HoverCardTrigger: () => HoverCardTrigger,
128
+ HoverCardContent: () => HoverCardContent,
129
+ HoverCard: () => HoverCard,
130
+ FilePreviewModal: () => FilePreviewModal,
131
+ FilePreviewCard: () => FilePreviewCard,
132
+ DropdownMenuTrigger: () => DropdownMenuTrigger,
133
+ DropdownMenuSubTrigger: () => DropdownMenuSubTrigger,
134
+ DropdownMenuSubContent: () => DropdownMenuSubContent,
135
+ DropdownMenuSub: () => DropdownMenuSub,
136
+ DropdownMenuShortcut: () => DropdownMenuShortcut,
137
+ DropdownMenuSeparator: () => DropdownMenuSeparator,
138
+ DropdownMenuRadioItem: () => DropdownMenuRadioItem,
139
+ DropdownMenuRadioGroup: () => DropdownMenuRadioGroup,
140
+ DropdownMenuPortal: () => DropdownMenuPortal,
141
+ DropdownMenuLabel: () => DropdownMenuLabel,
142
+ DropdownMenuItem: () => DropdownMenuItem,
143
+ DropdownMenuGroup: () => DropdownMenuGroup,
144
+ DropdownMenuContent: () => DropdownMenuContent,
145
+ DropdownMenuCheckboxItem: () => DropdownMenuCheckboxItem,
146
+ DropdownMenu: () => DropdownMenu,
147
+ DialogTrigger: () => DialogTrigger,
148
+ DialogTitle: () => DialogTitle,
149
+ DialogPortal: () => DialogPortal,
150
+ DialogOverlay: () => DialogOverlay,
151
+ DialogHeader: () => DialogHeader,
152
+ DialogFooter: () => DialogFooter,
153
+ DialogDescription: () => DialogDescription,
154
+ DialogContent: () => DialogContent,
155
+ DialogClose: () => DialogClose,
156
+ Dialog: () => Dialog,
157
+ ConversationScrollButton: () => ConversationScrollButton,
158
+ ConversationEmptyState: () => ConversationEmptyState,
159
+ ConversationContent: () => ConversationContent,
160
+ Conversation: () => Conversation,
161
+ CommandShortcut: () => CommandShortcut,
162
+ CommandSeparator: () => CommandSeparator,
163
+ CommandList: () => CommandList,
164
+ CommandItem: () => CommandItem,
165
+ CommandInput: () => CommandInput,
166
+ CommandGroup: () => CommandGroup,
167
+ CommandEmpty: () => CommandEmpty,
168
+ Command: () => Command,
169
+ CollapsibleTrigger: () => CollapsibleTrigger2,
170
+ CollapsibleContent: () => CollapsibleContent2,
171
+ Collapsible: () => Collapsible,
172
+ CodeBlockCopyButton: () => CodeBlockCopyButton,
173
+ CodeBlock: () => CodeBlock,
174
+ Button: () => Button,
175
+ Badge: () => Badge,
176
+ AvatarImage: () => AvatarImage,
177
+ AvatarFallback: () => AvatarFallback,
178
+ Avatar: () => Avatar,
179
+ AudioRecorder: () => AudioRecorder,
180
+ ArtifactTitle: () => ArtifactTitle,
181
+ ArtifactHeader: () => ArtifactHeader,
182
+ ArtifactDescription: () => ArtifactDescription,
183
+ ArtifactContent: () => ArtifactContent,
184
+ ArtifactClose: () => ArtifactClose,
185
+ ArtifactActions: () => ArtifactActions,
186
+ ArtifactAction: () => ArtifactAction,
187
+ Artifact: () => Artifact,
188
+ AgnoMessageItem: () => AgnoMessageItem,
189
+ AgnoChatToolStatus: () => AgnoChatToolStatus,
190
+ AgnoChatSuggestedPrompts: () => AgnoChatSuggestedPrompts,
191
+ AgnoChatRoot: () => AgnoChatRoot,
192
+ AgnoChatMessages: () => AgnoChatMessages,
193
+ AgnoChatInterface: () => AgnoChatInterface,
194
+ AgnoChatInputArea: () => AgnoChatInputArea,
195
+ AgnoChatInput: () => AgnoChatInput,
196
+ AgnoChatErrorBar: () => AgnoChatErrorBar,
197
+ AgnoChatEmptyState: () => AgnoChatEmptyState,
198
+ AgnoChat: () => AgnoChat,
199
+ AccordionTrigger: () => AccordionTrigger,
200
+ AccordionItem: () => AccordionItem,
201
+ AccordionContent: () => AccordionContent,
202
+ Accordion: () => Accordion
203
+ });
204
+ module.exports = __toCommonJS(exports_ui);
205
+
206
+ // src/ui/lib/cn.ts
207
+ var import_clsx = require("clsx");
208
+ var import_tailwind_merge = require("tailwind-merge");
209
+ function cn(...inputs) {
210
+ return import_tailwind_merge.twMerge(import_clsx.clsx(inputs));
211
+ }
212
+ // src/ui/lib/format-timestamp.ts
213
+ function formatSmartTimestamp(date) {
214
+ const now = new Date;
215
+ const isToday = date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
216
+ if (isToday) {
217
+ return new Intl.DateTimeFormat(undefined, {
218
+ hour: "numeric",
219
+ minute: "2-digit",
220
+ hour12: true
221
+ }).format(date);
222
+ }
223
+ const isSameYear = date.getFullYear() === now.getFullYear();
224
+ if (isSameYear) {
225
+ return new Intl.DateTimeFormat(undefined, {
226
+ month: "short",
227
+ day: "numeric"
228
+ }).format(date);
229
+ }
230
+ return new Intl.DateTimeFormat(undefined, {
231
+ month: "short",
232
+ day: "numeric",
233
+ year: "numeric"
234
+ }).format(date);
235
+ }
236
+ function formatFullTimestamp(date) {
237
+ return new Intl.DateTimeFormat(undefined, {
238
+ month: "short",
239
+ day: "numeric",
240
+ year: "numeric",
241
+ hour: "numeric",
242
+ minute: "2-digit",
243
+ hour12: true
244
+ }).format(date);
245
+ }
246
+ // src/ui/lib/file-utils.ts
247
+ function getFilePreviewType(mimeType) {
248
+ if (!mimeType)
249
+ return "none";
250
+ if (mimeType.startsWith("image/"))
251
+ return "image";
252
+ if (mimeType === "application/pdf")
253
+ return "pdf";
254
+ if (mimeType.startsWith("text/"))
255
+ return "text";
256
+ if (mimeType.startsWith("video/"))
257
+ return "video";
258
+ if (mimeType.startsWith("audio/"))
259
+ return "audio";
260
+ return "none";
261
+ }
262
+ function formatFileSize(bytes) {
263
+ if (bytes === 0)
264
+ return "0 B";
265
+ const units = ["B", "KB", "MB", "GB", "TB"];
266
+ const k = 1024;
267
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
268
+ const value = bytes / Math.pow(k, i);
269
+ return `${value % 1 === 0 ? value : value.toFixed(1)} ${units[i]}`;
270
+ }
271
+ function getFileExtension(filename, mimeType) {
272
+ const lastDot = filename.lastIndexOf(".");
273
+ if (lastDot !== -1 && lastDot !== 0) {
274
+ return filename.slice(lastDot + 1).toLowerCase();
275
+ }
276
+ if (mimeType) {
277
+ return extensionFromMime(mimeType);
278
+ }
279
+ return "";
280
+ }
281
+ var mimeToExt = {
282
+ "application/pdf": "pdf",
283
+ "application/zip": "zip",
284
+ "application/x-rar-compressed": "rar",
285
+ "application/json": "json",
286
+ "application/xml": "xml",
287
+ "application/msword": "doc",
288
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
289
+ "application/vnd.ms-excel": "xls",
290
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
291
+ "application/vnd.ms-powerpoint": "ppt",
292
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
293
+ "text/csv": "csv",
294
+ "text/plain": "txt",
295
+ "text/html": "html",
296
+ "text/css": "css",
297
+ "text/javascript": "js"
298
+ };
299
+ function extensionFromMime(mimeType) {
300
+ if (mimeToExt[mimeType])
301
+ return mimeToExt[mimeType];
302
+ const subtype = mimeType.split("/")[1];
303
+ if (subtype && !subtype.includes(".") && !subtype.includes("+")) {
304
+ return subtype.toLowerCase();
305
+ }
306
+ return "";
307
+ }
308
+ function isPreviewable(mimeType) {
309
+ const type = getFilePreviewType(mimeType);
310
+ return type === "image" || type === "pdf";
311
+ }
312
+ // src/ui/primitives/button.tsx
313
+ var React = __toESM(require("react"));
314
+ var import_react_slot = require("@radix-ui/react-slot");
315
+ var import_class_variance_authority = require("class-variance-authority");
316
+ var jsx_dev_runtime = require("react/jsx-dev-runtime");
317
+ var buttonVariants = import_class_variance_authority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
318
+ variants: {
319
+ variant: {
320
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
321
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
322
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
323
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
324
+ ghost: "hover:bg-accent hover:text-accent-foreground",
325
+ link: "text-primary underline-offset-4 hover:underline"
326
+ },
327
+ size: {
328
+ default: "h-9 px-4 py-2",
329
+ sm: "h-8 rounded-md px-3 text-xs",
330
+ lg: "h-10 rounded-md px-8",
331
+ icon: "h-9 w-9"
332
+ }
333
+ },
334
+ defaultVariants: {
335
+ variant: "default",
336
+ size: "default"
337
+ }
338
+ });
339
+ var Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
340
+ const Comp = asChild ? import_react_slot.Slot : "button";
341
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Comp, {
342
+ className: cn(buttonVariants({ variant, size, className })),
343
+ ref,
344
+ ...props
345
+ }, undefined, false, undefined, this);
346
+ });
347
+ Button.displayName = "Button";
348
+ // src/ui/primitives/badge.tsx
349
+ var import_class_variance_authority2 = require("class-variance-authority");
350
+ var jsx_dev_runtime2 = require("react/jsx-dev-runtime");
351
+ var badgeVariants = import_class_variance_authority2.cva("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
352
+ variants: {
353
+ variant: {
354
+ default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
355
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
356
+ destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
357
+ outline: "text-foreground"
358
+ }
359
+ },
360
+ defaultVariants: {
361
+ variant: "default"
362
+ }
363
+ });
364
+ function Badge({ className, variant, ...props }) {
365
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV("div", {
366
+ className: cn(badgeVariants({ variant }), className),
367
+ ...props
368
+ }, undefined, false, undefined, this);
369
+ }
370
+ // src/ui/primitives/avatar.tsx
371
+ var React2 = __toESM(require("react"));
372
+ var AvatarPrimitive = __toESM(require("@radix-ui/react-avatar"));
373
+ var jsx_dev_runtime3 = require("react/jsx-dev-runtime");
374
+ var Avatar = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(AvatarPrimitive.Root, {
375
+ ref,
376
+ className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
377
+ ...props
378
+ }, undefined, false, undefined, this));
379
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
380
+ var AvatarImage = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(AvatarPrimitive.Image, {
381
+ ref,
382
+ className: cn("aspect-square h-full w-full", className),
383
+ ...props
384
+ }, undefined, false, undefined, this));
385
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
386
+ var AvatarFallback = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(AvatarPrimitive.Fallback, {
387
+ ref,
388
+ className: cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className),
389
+ ...props
390
+ }, undefined, false, undefined, this));
391
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
392
+ // src/ui/primitives/input-group.tsx
393
+ var React3 = __toESM(require("react"));
394
+ var import_class_variance_authority3 = require("class-variance-authority");
395
+ var jsx_dev_runtime4 = require("react/jsx-dev-runtime");
396
+ var Input = React3.forwardRef(({ className, type, ...props }, ref) => {
397
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV("input", {
398
+ type,
399
+ className: cn("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className),
400
+ ref,
401
+ ...props
402
+ }, undefined, false, undefined, this);
403
+ });
404
+ Input.displayName = "Input";
405
+ var Textarea = React3.forwardRef(({ className, ...props }, ref) => {
406
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV("textarea", {
407
+ className: cn("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className),
408
+ ref,
409
+ ...props
410
+ }, undefined, false, undefined, this);
411
+ });
412
+ Textarea.displayName = "Textarea";
413
+ function InputGroup({ className, ...props }) {
414
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV("div", {
415
+ "data-slot": "input-group",
416
+ role: "group",
417
+ className: cn("group/input-group border-input dark:bg-input/30 shadow-xs relative flex w-full items-center rounded-md border outline-none transition-[color,box-shadow]", "h-9 has-[>textarea]:h-auto", "has-[>[data-align=inline-start]]:[&>input]:pl-2", "has-[>[data-align=inline-end]]:[&>input]:pr-2", "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3", "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-2.5", "has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1", "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", className),
418
+ ...props
419
+ }, undefined, false, undefined, this);
420
+ }
421
+ var inputGroupAddonVariants = import_class_variance_authority3.cva("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", {
422
+ variants: {
423
+ align: {
424
+ "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
425
+ "inline-end": "order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]",
426
+ "block-start": "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-2 pb-0 group-has-[>input]/input-group:pt-2.5",
427
+ "block-end": "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-1.5 group-has-[>input]/input-group:pb-1.5"
428
+ }
429
+ },
430
+ defaultVariants: {
431
+ align: "inline-start"
432
+ }
433
+ });
434
+ function InputGroupAddon({
435
+ className,
436
+ align = "inline-start",
437
+ ...props
438
+ }) {
439
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV("div", {
440
+ role: "group",
441
+ "data-slot": "input-group-addon",
442
+ "data-align": align,
443
+ className: cn(inputGroupAddonVariants({ align }), className),
444
+ onClick: (e) => {
445
+ if (e.target.closest("button")) {
446
+ return;
447
+ }
448
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
449
+ },
450
+ ...props
451
+ }, undefined, false, undefined, this);
452
+ }
453
+ var inputGroupButtonVariants = import_class_variance_authority3.cva("flex items-center gap-2 text-sm shadow-none", {
454
+ variants: {
455
+ size: {
456
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
457
+ sm: "h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5",
458
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
459
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
460
+ }
461
+ },
462
+ defaultVariants: {
463
+ size: "xs"
464
+ }
465
+ });
466
+ function InputGroupButton({
467
+ className,
468
+ type = "button",
469
+ variant = "ghost",
470
+ size = "xs",
471
+ ...props
472
+ }) {
473
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Button, {
474
+ type,
475
+ "data-size": size,
476
+ variant,
477
+ className: cn(inputGroupButtonVariants({ size }), className),
478
+ ...props
479
+ }, undefined, false, undefined, this);
480
+ }
481
+ function InputGroupText({ className, ...props }) {
482
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV("span", {
483
+ className: cn("text-muted-foreground flex items-center gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none", className),
484
+ ...props
485
+ }, undefined, false, undefined, this);
486
+ }
487
+ function InputGroupInput({ className, ...props }) {
488
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Input, {
489
+ "data-slot": "input-group-control",
490
+ className: cn("flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent", className),
491
+ ...props
492
+ }, undefined, false, undefined, this);
493
+ }
494
+ function InputGroupTextarea({ className, ...props }) {
495
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Textarea, {
496
+ "data-slot": "input-group-control",
497
+ className: cn("flex-1 resize-none rounded-none border-0 bg-transparent min-h-0 pt-3.5 pb-1.5 pl-3.5 shadow-none focus-visible:ring-0 dark:bg-transparent", className),
498
+ ...props
499
+ }, undefined, false, undefined, this);
500
+ }
501
+ // src/ui/primitives/collapsible.tsx
502
+ var CollapsiblePrimitive = __toESM(require("@radix-ui/react-collapsible"));
503
+ var Collapsible = CollapsiblePrimitive.Root;
504
+ var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
505
+ var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
506
+ // src/ui/primitives/tooltip.tsx
507
+ var React4 = __toESM(require("react"));
508
+ var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"));
509
+ var jsx_dev_runtime5 = require("react/jsx-dev-runtime");
510
+ var TooltipProvider = TooltipPrimitive.Provider;
511
+ var Tooltip = TooltipPrimitive.Root;
512
+ var TooltipTrigger = TooltipPrimitive.Trigger;
513
+ var TooltipContent = React4.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(TooltipPrimitive.Portal, {
514
+ children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(TooltipPrimitive.Content, {
515
+ ref,
516
+ sideOffset,
517
+ className: cn("z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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-tooltip-content-transform-origin]", className),
518
+ ...props
519
+ }, undefined, false, undefined, this)
520
+ }, undefined, false, undefined, this));
521
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
522
+ // src/ui/primitives/accordion.tsx
523
+ var React5 = __toESM(require("react"));
524
+ var AccordionPrimitive = __toESM(require("@radix-ui/react-accordion"));
525
+ var import_lucide_react = require("lucide-react");
526
+ var jsx_dev_runtime6 = require("react/jsx-dev-runtime");
527
+ var Accordion = AccordionPrimitive.Root;
528
+ var AccordionItem = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(AccordionPrimitive.Item, {
529
+ ref,
530
+ className: cn("border-b", className),
531
+ ...props
532
+ }, undefined, false, undefined, this));
533
+ AccordionItem.displayName = "AccordionItem";
534
+ var AccordionTrigger = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(AccordionPrimitive.Header, {
535
+ className: "flex",
536
+ children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(AccordionPrimitive.Trigger, {
537
+ ref,
538
+ className: cn("flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180", className),
539
+ ...props,
540
+ children: [
541
+ children,
542
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(import_lucide_react.ChevronDown, {
543
+ className: "h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
544
+ }, undefined, false, undefined, this)
545
+ ]
546
+ }, undefined, true, undefined, this)
547
+ }, undefined, false, undefined, this));
548
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
549
+ var AccordionContent = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(AccordionPrimitive.Content, {
550
+ ref,
551
+ className: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
552
+ ...props,
553
+ children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV("div", {
554
+ className: cn("pb-4 pt-0", className),
555
+ children
556
+ }, undefined, false, undefined, this)
557
+ }, undefined, false, undefined, this));
558
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
559
+ // src/ui/primitives/dropdown-menu.tsx
560
+ var React6 = __toESM(require("react"));
561
+ var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
562
+ var import_lucide_react2 = require("lucide-react");
563
+ var jsx_dev_runtime7 = require("react/jsx-dev-runtime");
564
+ var DropdownMenu = DropdownMenuPrimitive.Root;
565
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
566
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
567
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
568
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
569
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
570
+ var DropdownMenuSubTrigger = React6.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.SubTrigger, {
571
+ ref,
572
+ className: cn("flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className),
573
+ ...props,
574
+ children: [
575
+ children,
576
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(import_lucide_react2.ChevronRight, {
577
+ className: "ml-auto"
578
+ }, undefined, false, undefined, this)
579
+ ]
580
+ }, undefined, true, undefined, this));
581
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
582
+ var DropdownMenuSubContent = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.SubContent, {
583
+ ref,
584
+ className: cn("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-dropdown-menu-content-transform-origin]", className),
585
+ ...props
586
+ }, undefined, false, undefined, this));
587
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
588
+ var DropdownMenuContent = React6.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.Portal, {
589
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.Content, {
590
+ ref,
591
+ sideOffset,
592
+ className: cn("z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md", "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-dropdown-menu-content-transform-origin]", className),
593
+ ...props
594
+ }, undefined, false, undefined, this)
595
+ }, undefined, false, undefined, this));
596
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
597
+ var DropdownMenuItem = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.Item, {
598
+ ref,
599
+ className: cn("relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0", inset && "pl-8", className),
600
+ ...props
601
+ }, undefined, false, undefined, this));
602
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
603
+ var DropdownMenuCheckboxItem = React6.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.CheckboxItem, {
604
+ ref,
605
+ className: cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
606
+ checked,
607
+ ...props,
608
+ children: [
609
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV("span", {
610
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
611
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.ItemIndicator, {
612
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(import_lucide_react2.Check, {
613
+ className: "h-4 w-4"
614
+ }, undefined, false, undefined, this)
615
+ }, undefined, false, undefined, this)
616
+ }, undefined, false, undefined, this),
617
+ children
618
+ ]
619
+ }, undefined, true, undefined, this));
620
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
621
+ var DropdownMenuRadioItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.RadioItem, {
622
+ ref,
623
+ className: cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
624
+ ...props,
625
+ children: [
626
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV("span", {
627
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
628
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.ItemIndicator, {
629
+ children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(import_lucide_react2.Circle, {
630
+ className: "h-2 w-2 fill-current"
631
+ }, undefined, false, undefined, this)
632
+ }, undefined, false, undefined, this)
633
+ }, undefined, false, undefined, this),
634
+ children
635
+ ]
636
+ }, undefined, true, undefined, this));
637
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
638
+ var DropdownMenuLabel = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.Label, {
639
+ ref,
640
+ className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
641
+ ...props
642
+ }, undefined, false, undefined, this));
643
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
644
+ var DropdownMenuSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(DropdownMenuPrimitive.Separator, {
645
+ ref,
646
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
647
+ ...props
648
+ }, undefined, false, undefined, this));
649
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
650
+ var DropdownMenuShortcut = ({ className, ...props }) => {
651
+ return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV("span", {
652
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
653
+ ...props
654
+ }, undefined, false, undefined, this);
655
+ };
656
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
657
+ // src/ui/primitives/hover-card.tsx
658
+ var React7 = __toESM(require("react"));
659
+ var HoverCardPrimitive = __toESM(require("@radix-ui/react-hover-card"));
660
+ var jsx_dev_runtime8 = require("react/jsx-dev-runtime");
661
+ var HoverCard = HoverCardPrimitive.Root;
662
+ var HoverCardTrigger = HoverCardPrimitive.Trigger;
663
+ var HoverCardContent = React7.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(HoverCardPrimitive.Content, {
664
+ ref,
665
+ align,
666
+ sideOffset,
667
+ className: cn("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]", className),
668
+ ...props
669
+ }, undefined, false, undefined, this));
670
+ HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
671
+ // src/ui/primitives/select.tsx
672
+ var React8 = __toESM(require("react"));
673
+ var SelectPrimitive = __toESM(require("@radix-ui/react-select"));
674
+ var import_lucide_react3 = require("lucide-react");
675
+ var jsx_dev_runtime9 = require("react/jsx-dev-runtime");
676
+ var Select = SelectPrimitive.Root;
677
+ var SelectGroup = SelectPrimitive.Group;
678
+ var SelectValue = SelectPrimitive.Value;
679
+ var SelectTrigger = React8.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Trigger, {
680
+ ref,
681
+ className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className),
682
+ ...props,
683
+ children: [
684
+ children,
685
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Icon, {
686
+ asChild: true,
687
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(import_lucide_react3.ChevronDown, {
688
+ className: "h-4 w-4 opacity-50"
689
+ }, undefined, false, undefined, this)
690
+ }, undefined, false, undefined, this)
691
+ ]
692
+ }, undefined, true, undefined, this));
693
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
694
+ var SelectScrollUpButton = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.ScrollUpButton, {
695
+ ref,
696
+ className: cn("flex cursor-default items-center justify-center py-1", className),
697
+ ...props,
698
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(import_lucide_react3.ChevronUp, {
699
+ className: "h-4 w-4"
700
+ }, undefined, false, undefined, this)
701
+ }, undefined, false, undefined, this));
702
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
703
+ var SelectScrollDownButton = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.ScrollDownButton, {
704
+ ref,
705
+ className: cn("flex cursor-default items-center justify-center py-1", className),
706
+ ...props,
707
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(import_lucide_react3.ChevronDown, {
708
+ className: "h-4 w-4"
709
+ }, undefined, false, undefined, this)
710
+ }, undefined, false, undefined, this));
711
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
712
+ var SelectContent = React8.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Portal, {
713
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Content, {
714
+ ref,
715
+ className: cn("relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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-select-content-transform-origin]", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
716
+ position,
717
+ ...props,
718
+ children: [
719
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectScrollUpButton, {}, undefined, false, undefined, this),
720
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Viewport, {
721
+ className: cn("p-1", position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),
722
+ children
723
+ }, undefined, false, undefined, this),
724
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectScrollDownButton, {}, undefined, false, undefined, this)
725
+ ]
726
+ }, undefined, true, undefined, this)
727
+ }, undefined, false, undefined, this));
728
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
729
+ var SelectLabel = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Label, {
730
+ ref,
731
+ className: cn("px-2 py-1.5 text-sm font-semibold", className),
732
+ ...props
733
+ }, undefined, false, undefined, this));
734
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
735
+ var SelectItem = React8.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Item, {
736
+ ref,
737
+ className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
738
+ ...props,
739
+ children: [
740
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV("span", {
741
+ className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center",
742
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.ItemIndicator, {
743
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(import_lucide_react3.Check, {
744
+ className: "h-4 w-4"
745
+ }, undefined, false, undefined, this)
746
+ }, undefined, false, undefined, this)
747
+ }, undefined, false, undefined, this),
748
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.ItemText, {
749
+ children
750
+ }, undefined, false, undefined, this)
751
+ ]
752
+ }, undefined, true, undefined, this));
753
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
754
+ var SelectSeparator = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SelectPrimitive.Separator, {
755
+ ref,
756
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
757
+ ...props
758
+ }, undefined, false, undefined, this));
759
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
760
+ // src/ui/primitives/command.tsx
761
+ var React9 = __toESM(require("react"));
762
+ var import_cmdk = require("cmdk");
763
+ var import_lucide_react4 = require("lucide-react");
764
+ var jsx_dev_runtime10 = require("react/jsx-dev-runtime");
765
+ var Command = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command, {
766
+ ref,
767
+ className: cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className),
768
+ ...props
769
+ }, undefined, false, undefined, this));
770
+ Command.displayName = import_cmdk.Command.displayName;
771
+ var CommandInput = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV("div", {
772
+ className: "flex items-center border-b px-3",
773
+ "cmdk-input-wrapper": "",
774
+ children: [
775
+ /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_lucide_react4.Search, {
776
+ className: "mr-2 h-4 w-4 shrink-0 opacity-50"
777
+ }, undefined, false, undefined, this),
778
+ /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.Input, {
779
+ ref,
780
+ className: cn("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", className),
781
+ ...props
782
+ }, undefined, false, undefined, this)
783
+ ]
784
+ }, undefined, true, undefined, this));
785
+ CommandInput.displayName = import_cmdk.Command.Input.displayName;
786
+ var CommandList = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.List, {
787
+ ref,
788
+ className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
789
+ ...props
790
+ }, undefined, false, undefined, this));
791
+ CommandList.displayName = import_cmdk.Command.List.displayName;
792
+ var CommandEmpty = React9.forwardRef((props, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.Empty, {
793
+ ref,
794
+ className: "py-6 text-center text-sm",
795
+ ...props
796
+ }, undefined, false, undefined, this));
797
+ CommandEmpty.displayName = import_cmdk.Command.Empty.displayName;
798
+ var CommandGroup = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.Group, {
799
+ ref,
800
+ className: cn("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", className),
801
+ ...props
802
+ }, undefined, false, undefined, this));
803
+ CommandGroup.displayName = import_cmdk.Command.Group.displayName;
804
+ var CommandSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.Separator, {
805
+ ref,
806
+ className: cn("-mx-1 h-px bg-border", className),
807
+ ...props
808
+ }, undefined, false, undefined, this));
809
+ CommandSeparator.displayName = import_cmdk.Command.Separator.displayName;
810
+ var CommandItem = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(import_cmdk.Command.Item, {
811
+ ref,
812
+ className: cn("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", className),
813
+ ...props
814
+ }, undefined, false, undefined, this));
815
+ CommandItem.displayName = import_cmdk.Command.Item.displayName;
816
+ var CommandShortcut = ({ className, ...props }) => {
817
+ return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV("span", {
818
+ className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className),
819
+ ...props
820
+ }, undefined, false, undefined, this);
821
+ };
822
+ CommandShortcut.displayName = "CommandShortcut";
823
+ // src/ui/primitives/dialog.tsx
824
+ var React10 = __toESM(require("react"));
825
+ var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
826
+ var import_class_variance_authority4 = require("class-variance-authority");
827
+ var import_lucide_react5 = require("lucide-react");
828
+ var jsx_dev_runtime11 = require("react/jsx-dev-runtime");
829
+ var Dialog = DialogPrimitive.Root;
830
+ var DialogTrigger = DialogPrimitive.Trigger;
831
+ var DialogPortal = DialogPrimitive.Portal;
832
+ var DialogClose = DialogPrimitive.Close;
833
+ var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPrimitive.Overlay, {
834
+ ref,
835
+ className: cn("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className),
836
+ ...props
837
+ }, undefined, false, undefined, this));
838
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
839
+ var dialogContentVariants = import_class_variance_authority4.cva("fixed left-[50%] top-[50%] z-50 grid translate-x-[-50%] translate-y-[-50%] gap-4 border shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", {
840
+ variants: {
841
+ variant: {
842
+ default: "w-full max-w-lg bg-background p-6",
843
+ lightbox: "max-w-[90vw] max-h-[90vh] bg-background/95 backdrop-blur-sm p-2"
844
+ }
845
+ },
846
+ defaultVariants: {
847
+ variant: "default"
848
+ }
849
+ });
850
+ var DialogContent = React10.forwardRef(({ className, variant, children, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPortal, {
851
+ children: [
852
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogOverlay, {}, undefined, false, undefined, this),
853
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPrimitive.Content, {
854
+ ref,
855
+ className: cn(dialogContentVariants({ variant }), className),
856
+ ...props,
857
+ children: [
858
+ children,
859
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPrimitive.Close, {
860
+ className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
861
+ children: [
862
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(import_lucide_react5.X, {
863
+ className: "h-4 w-4"
864
+ }, undefined, false, undefined, this),
865
+ /* @__PURE__ */ jsx_dev_runtime11.jsxDEV("span", {
866
+ className: "sr-only",
867
+ children: "Close"
868
+ }, undefined, false, undefined, this)
869
+ ]
870
+ }, undefined, true, undefined, this)
871
+ ]
872
+ }, undefined, true, undefined, this)
873
+ ]
874
+ }, undefined, true, undefined, this));
875
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
876
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV("div", {
877
+ className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className),
878
+ ...props
879
+ }, undefined, false, undefined, this);
880
+ DialogHeader.displayName = "DialogHeader";
881
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV("div", {
882
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
883
+ ...props
884
+ }, undefined, false, undefined, this);
885
+ DialogFooter.displayName = "DialogFooter";
886
+ var DialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPrimitive.Title, {
887
+ ref,
888
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
889
+ ...props
890
+ }, undefined, false, undefined, this));
891
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
892
+ var DialogDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(DialogPrimitive.Description, {
893
+ ref,
894
+ className: cn("text-sm text-muted-foreground", className),
895
+ ...props
896
+ }, undefined, false, undefined, this));
897
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
898
+ // src/ui/components/message.tsx
899
+ var import_class_variance_authority5 = require("class-variance-authority");
900
+ var jsx_dev_runtime12 = require("react/jsx-dev-runtime");
901
+ var Message = ({ className, from, ...props }) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV("div", {
902
+ className: cn("group flex w-full items-end justify-end gap-2 py-4", from === "user" ? "is-user" : "is-assistant flex-row-reverse justify-end", className),
903
+ ...props
904
+ }, undefined, false, undefined, this);
905
+ var messageContentVariants = import_class_variance_authority5.cva("flex flex-col gap-2 overflow-hidden rounded-lg text-sm", {
906
+ variants: {
907
+ variant: {
908
+ contained: [
909
+ "max-w-[80%] px-4 py-3",
910
+ "group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground",
911
+ "group-[.is-assistant]:bg-secondary group-[.is-assistant]:text-foreground"
912
+ ],
913
+ flat: [
914
+ "group-[.is-user]:max-w-[80%] group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
915
+ "group-[.is-assistant]:text-foreground"
916
+ ]
917
+ }
918
+ },
919
+ defaultVariants: {
920
+ variant: "contained"
921
+ }
922
+ });
923
+ var MessageContent = ({ children, className, variant, ...props }) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV("div", {
924
+ className: cn(messageContentVariants({ variant, className })),
925
+ ...props,
926
+ children
927
+ }, undefined, false, undefined, this);
928
+ var MessageAvatar = ({ src, name, className, ...props }) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Avatar, {
929
+ className: cn("size-8 ring-1 ring-border", className),
930
+ ...props,
931
+ children: [
932
+ /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(AvatarImage, {
933
+ alt: "",
934
+ className: "mt-0 mb-0",
935
+ src
936
+ }, undefined, false, undefined, this),
937
+ /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(AvatarFallback, {
938
+ children: name?.slice(0, 2) || "ME"
939
+ }, undefined, false, undefined, this)
940
+ ]
941
+ }, undefined, true, undefined, this);
942
+ // src/ui/components/conversation.tsx
943
+ var import_lucide_react6 = require("lucide-react");
944
+ var import_react = require("react");
945
+ var import_use_stick_to_bottom = require("use-stick-to-bottom");
946
+ var import_use_stick_to_bottom2 = require("use-stick-to-bottom");
947
+ var jsx_dev_runtime13 = require("react/jsx-dev-runtime");
948
+ var Conversation = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(import_use_stick_to_bottom.StickToBottom, {
949
+ className: cn("relative flex-1 overflow-y-auto", className),
950
+ initial: "smooth",
951
+ role: "log",
952
+ ...props
953
+ }, undefined, false, undefined, this);
954
+ var ConversationContent = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(import_use_stick_to_bottom.StickToBottom.Content, {
955
+ className: cn("p-4", className),
956
+ ...props
957
+ }, undefined, false, undefined, this);
958
+ var ConversationEmptyState = ({
959
+ className,
960
+ title = "No messages yet",
961
+ description = "Start a conversation to see messages here",
962
+ icon,
963
+ children,
964
+ ...props
965
+ }) => /* @__PURE__ */ jsx_dev_runtime13.jsxDEV("div", {
966
+ className: cn("flex size-full flex-col items-center justify-center gap-3 p-8 text-center", className),
967
+ ...props,
968
+ children: children ?? /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
969
+ children: [
970
+ icon && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV("div", {
971
+ className: "text-muted-foreground",
972
+ children: icon
973
+ }, undefined, false, undefined, this),
974
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV("div", {
975
+ className: "space-y-1",
976
+ children: [
977
+ /* @__PURE__ */ jsx_dev_runtime13.jsxDEV("h3", {
978
+ className: "font-medium text-sm",
979
+ children: title
980
+ }, undefined, false, undefined, this),
981
+ description && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV("p", {
982
+ className: "text-muted-foreground text-sm",
983
+ children: description
984
+ }, undefined, false, undefined, this)
985
+ ]
986
+ }, undefined, true, undefined, this)
987
+ ]
988
+ }, undefined, true, undefined, this)
989
+ }, undefined, false, undefined, this);
990
+ var ConversationScrollButton = ({ className, ...props }) => {
991
+ const { isAtBottom, scrollToBottom } = import_use_stick_to_bottom.useStickToBottomContext();
992
+ const handleScrollToBottom = import_react.useCallback(() => {
993
+ scrollToBottom();
994
+ }, [scrollToBottom]);
995
+ return !isAtBottom && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Button, {
996
+ className: cn("absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full", className),
997
+ onClick: handleScrollToBottom,
998
+ size: "icon",
999
+ type: "button",
1000
+ variant: "outline",
1001
+ ...props,
1002
+ children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(import_lucide_react6.ArrowDownIcon, {
1003
+ className: "size-4"
1004
+ }, undefined, false, undefined, this)
1005
+ }, undefined, false, undefined, this);
1006
+ };
1007
+ // src/ui/components/response.tsx
1008
+ var import_react2 = require("react");
1009
+ var import_streamdown = require("streamdown");
1010
+ var jsx_dev_runtime14 = require("react/jsx-dev-runtime");
1011
+ var Response = import_react2.memo(({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(import_streamdown.Streamdown, {
1012
+ className: cn("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className),
1013
+ ...props
1014
+ }, undefined, false, undefined, this), (prevProps, nextProps) => prevProps.children === nextProps.children);
1015
+ Response.displayName = "Response";
1016
+ // src/ui/components/tool.tsx
1017
+ var import_lucide_react8 = require("lucide-react");
1018
+ var import_react4 = require("react");
1019
+
1020
+ // src/ui/components/code-block.tsx
1021
+ var import_lucide_react7 = require("lucide-react");
1022
+ var import_react3 = require("react");
1023
+ var jsx_dev_runtime15 = require("react/jsx-dev-runtime");
1024
+ var CodeBlockContext = import_react3.createContext({
1025
+ code: ""
1026
+ });
1027
+ async function highlightCode(code, language, showLineNumbers = false) {
1028
+ try {
1029
+ const shiki = await import("shiki");
1030
+ const lineNumberTransformer = showLineNumbers ? [
1031
+ {
1032
+ name: "line-numbers",
1033
+ line(node, line) {
1034
+ node.children.unshift({
1035
+ type: "element",
1036
+ tagName: "span",
1037
+ properties: {
1038
+ className: ["inline-block", "min-w-10", "mr-4", "text-right", "select-none", "text-muted-foreground"]
1039
+ },
1040
+ children: [{ type: "text", value: String(line) }]
1041
+ });
1042
+ }
1043
+ }
1044
+ ] : [];
1045
+ const [light, dark] = await Promise.all([
1046
+ shiki.codeToHtml(code, { lang: language, theme: "one-light", transformers: lineNumberTransformer }),
1047
+ shiki.codeToHtml(code, { lang: language, theme: "one-dark-pro", transformers: lineNumberTransformer })
1048
+ ]);
1049
+ return [light, dark];
1050
+ } catch {
1051
+ return ["", ""];
1052
+ }
1053
+ }
1054
+ var CodeBlock = ({
1055
+ code,
1056
+ language,
1057
+ showLineNumbers = false,
1058
+ className,
1059
+ children,
1060
+ ...props
1061
+ }) => {
1062
+ const [html, setHtml] = import_react3.useState("");
1063
+ const [darkHtml, setDarkHtml] = import_react3.useState("");
1064
+ const effectIdRef = import_react3.useRef(0);
1065
+ import_react3.useEffect(() => {
1066
+ const id = ++effectIdRef.current;
1067
+ highlightCode(code, language, showLineNumbers).then(([light, dark]) => {
1068
+ if (id === effectIdRef.current) {
1069
+ setHtml(light);
1070
+ setDarkHtml(dark);
1071
+ }
1072
+ });
1073
+ }, [code, language, showLineNumbers]);
1074
+ const useFallback = !html && !darkHtml;
1075
+ return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(CodeBlockContext.Provider, {
1076
+ value: { code },
1077
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("div", {
1078
+ className: cn("group relative w-full overflow-hidden rounded-md border bg-background text-foreground", className),
1079
+ ...props,
1080
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("div", {
1081
+ className: "relative",
1082
+ children: [
1083
+ useFallback ? /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("pre", {
1084
+ className: "m-0 overflow-auto bg-background p-4 text-foreground text-sm",
1085
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("code", {
1086
+ className: "font-mono text-sm",
1087
+ children: code
1088
+ }, undefined, false, undefined, this)
1089
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(jsx_dev_runtime15.Fragment, {
1090
+ children: [
1091
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("div", {
1092
+ className: "overflow-hidden dark:hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm",
1093
+ dangerouslySetInnerHTML: { __html: html }
1094
+ }, undefined, false, undefined, this),
1095
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("div", {
1096
+ className: "hidden overflow-hidden dark:block [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm",
1097
+ dangerouslySetInnerHTML: { __html: darkHtml }
1098
+ }, undefined, false, undefined, this)
1099
+ ]
1100
+ }, undefined, true, undefined, this),
1101
+ children && /* @__PURE__ */ jsx_dev_runtime15.jsxDEV("div", {
1102
+ className: "absolute top-2 right-2 flex items-center gap-2",
1103
+ children
1104
+ }, undefined, false, undefined, this)
1105
+ ]
1106
+ }, undefined, true, undefined, this)
1107
+ }, undefined, false, undefined, this)
1108
+ }, undefined, false, undefined, this);
1109
+ };
1110
+ var CodeBlockCopyButton = ({
1111
+ onCopy,
1112
+ onError,
1113
+ timeout = 2000,
1114
+ children,
1115
+ className,
1116
+ ...props
1117
+ }) => {
1118
+ const [isCopied, setIsCopied] = import_react3.useState(false);
1119
+ const { code } = import_react3.useContext(CodeBlockContext);
1120
+ const copyToClipboard = async () => {
1121
+ if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
1122
+ onError?.(new Error("Clipboard API not available"));
1123
+ return;
1124
+ }
1125
+ try {
1126
+ await navigator.clipboard.writeText(code);
1127
+ setIsCopied(true);
1128
+ onCopy?.();
1129
+ setTimeout(() => setIsCopied(false), timeout);
1130
+ } catch (error) {
1131
+ onError?.(error);
1132
+ }
1133
+ };
1134
+ const Icon2 = isCopied ? import_lucide_react7.CheckIcon : import_lucide_react7.CopyIcon;
1135
+ return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Button, {
1136
+ className: cn("shrink-0", className),
1137
+ onClick: copyToClipboard,
1138
+ size: "icon",
1139
+ variant: "ghost",
1140
+ ...props,
1141
+ children: children ?? /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Icon2, {
1142
+ size: 14
1143
+ }, undefined, false, undefined, this)
1144
+ }, undefined, false, undefined, this);
1145
+ };
1146
+
1147
+ // src/ui/components/tool.tsx
1148
+ var jsx_dev_runtime16 = require("react/jsx-dev-runtime");
1149
+ var Tool = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Collapsible, {
1150
+ className: cn("not-prose mb-4 w-full rounded-md border", className),
1151
+ ...props
1152
+ }, undefined, false, undefined, this);
1153
+ var getStatusBadge = (status) => {
1154
+ const labels = {
1155
+ "input-streaming": "Pending",
1156
+ "input-available": "Running",
1157
+ "approval-requested": "Awaiting Approval",
1158
+ "approval-responded": "Responded",
1159
+ "output-available": "Completed",
1160
+ "output-error": "Error",
1161
+ "output-denied": "Denied"
1162
+ };
1163
+ const icons = {
1164
+ "input-streaming": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.CircleIcon, {
1165
+ className: "size-4"
1166
+ }, undefined, false, undefined, this),
1167
+ "input-available": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.ClockIcon, {
1168
+ className: "size-4 animate-pulse"
1169
+ }, undefined, false, undefined, this),
1170
+ "approval-requested": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.ClockIcon, {
1171
+ className: "size-4 text-yellow-600"
1172
+ }, undefined, false, undefined, this),
1173
+ "approval-responded": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.CheckCircleIcon, {
1174
+ className: "size-4 text-blue-600"
1175
+ }, undefined, false, undefined, this),
1176
+ "output-available": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.CheckCircleIcon, {
1177
+ className: "size-4 text-green-600"
1178
+ }, undefined, false, undefined, this),
1179
+ "output-error": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.XCircleIcon, {
1180
+ className: "size-4 text-red-600"
1181
+ }, undefined, false, undefined, this),
1182
+ "output-denied": /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.XCircleIcon, {
1183
+ className: "size-4 text-orange-600"
1184
+ }, undefined, false, undefined, this)
1185
+ };
1186
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Badge, {
1187
+ className: "gap-1.5 rounded-full text-xs",
1188
+ variant: "secondary",
1189
+ children: [
1190
+ icons[status],
1191
+ labels[status]
1192
+ ]
1193
+ }, undefined, true, undefined, this);
1194
+ };
1195
+ var ToolHeader = ({ className, title, type, state, ...props }) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(CollapsibleTrigger2, {
1196
+ className: cn("group flex w-full items-center justify-between gap-4 p-3", className),
1197
+ ...props,
1198
+ children: [
1199
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1200
+ className: "flex items-center gap-2",
1201
+ children: [
1202
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.WrenchIcon, {
1203
+ className: "size-4 text-muted-foreground"
1204
+ }, undefined, false, undefined, this),
1205
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("span", {
1206
+ className: "font-medium text-sm",
1207
+ children: title ?? type?.split("-").slice(1).join("-") ?? "Tool"
1208
+ }, undefined, false, undefined, this),
1209
+ getStatusBadge(state)
1210
+ ]
1211
+ }, undefined, true, undefined, this),
1212
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(import_lucide_react8.ChevronDownIcon, {
1213
+ className: "size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180"
1214
+ }, undefined, false, undefined, this)
1215
+ ]
1216
+ }, undefined, true, undefined, this);
1217
+ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(CollapsibleContent2, {
1218
+ className: cn("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", className),
1219
+ ...props
1220
+ }, undefined, false, undefined, this);
1221
+ var ToolInput = ({ className, input, ...props }) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1222
+ className: cn("space-y-2 overflow-hidden p-4", className),
1223
+ ...props,
1224
+ children: [
1225
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("h4", {
1226
+ className: "font-medium text-muted-foreground text-xs uppercase tracking-wide",
1227
+ children: "Parameters"
1228
+ }, undefined, false, undefined, this),
1229
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1230
+ className: "rounded-md bg-muted/50",
1231
+ children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(CodeBlock, {
1232
+ code: JSON.stringify(input, null, 2),
1233
+ language: "json"
1234
+ }, undefined, false, undefined, this)
1235
+ }, undefined, false, undefined, this)
1236
+ ]
1237
+ }, undefined, true, undefined, this);
1238
+ var ToolOutput = ({ className, output, errorText, ...props }) => {
1239
+ if (!(output || errorText)) {
1240
+ return null;
1241
+ }
1242
+ let Output = /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1243
+ children: output
1244
+ }, undefined, false, undefined, this);
1245
+ if (typeof output === "object" && !import_react4.isValidElement(output)) {
1246
+ Output = /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(CodeBlock, {
1247
+ code: JSON.stringify(output, null, 2),
1248
+ language: "json"
1249
+ }, undefined, false, undefined, this);
1250
+ } else if (typeof output === "string") {
1251
+ Output = /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(CodeBlock, {
1252
+ code: output,
1253
+ language: "json"
1254
+ }, undefined, false, undefined, this);
1255
+ }
1256
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1257
+ className: cn("space-y-2 p-4", className),
1258
+ ...props,
1259
+ children: [
1260
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("h4", {
1261
+ className: "font-medium text-muted-foreground text-xs uppercase tracking-wide",
1262
+ children: errorText ? "Error" : "Result"
1263
+ }, undefined, false, undefined, this),
1264
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1265
+ className: cn("overflow-x-auto rounded-md text-xs [&_table]:w-full", errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground"),
1266
+ children: [
1267
+ errorText && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV("div", {
1268
+ children: errorText
1269
+ }, undefined, false, undefined, this),
1270
+ Output
1271
+ ]
1272
+ }, undefined, true, undefined, this)
1273
+ ]
1274
+ }, undefined, true, undefined, this);
1275
+ };
1276
+ // src/ui/components/artifact.tsx
1277
+ var import_lucide_react9 = require("lucide-react");
1278
+ var jsx_dev_runtime17 = require("react/jsx-dev-runtime");
1279
+ var Artifact = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("div", {
1280
+ className: cn("flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm", className),
1281
+ ...props
1282
+ }, undefined, false, undefined, this);
1283
+ var ArtifactHeader = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("div", {
1284
+ className: cn("flex items-center justify-between border-b bg-muted/50 px-4 py-3", className),
1285
+ ...props
1286
+ }, undefined, false, undefined, this);
1287
+ var ArtifactClose = ({
1288
+ className,
1289
+ children,
1290
+ size = "sm",
1291
+ variant = "ghost",
1292
+ ...props
1293
+ }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Button, {
1294
+ className: cn("size-8 p-0 text-muted-foreground hover:text-foreground", className),
1295
+ size,
1296
+ type: "button",
1297
+ variant,
1298
+ ...props,
1299
+ children: [
1300
+ children ?? /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(import_lucide_react9.XIcon, {
1301
+ className: "size-4"
1302
+ }, undefined, false, undefined, this),
1303
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("span", {
1304
+ className: "sr-only",
1305
+ children: "Close"
1306
+ }, undefined, false, undefined, this)
1307
+ ]
1308
+ }, undefined, true, undefined, this);
1309
+ var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("p", {
1310
+ className: cn("font-medium text-foreground text-sm", className),
1311
+ ...props
1312
+ }, undefined, false, undefined, this);
1313
+ var ArtifactDescription = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("p", {
1314
+ className: cn("text-muted-foreground text-sm", className),
1315
+ ...props
1316
+ }, undefined, false, undefined, this);
1317
+ var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("div", {
1318
+ className: cn("flex items-center gap-1", className),
1319
+ ...props
1320
+ }, undefined, false, undefined, this);
1321
+ var ArtifactAction = ({
1322
+ tooltip,
1323
+ label,
1324
+ icon: Icon2,
1325
+ children,
1326
+ className,
1327
+ size = "sm",
1328
+ variant = "ghost",
1329
+ ...props
1330
+ }) => {
1331
+ const button = /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Button, {
1332
+ className: cn("size-8 p-0 text-muted-foreground hover:text-foreground", className),
1333
+ size,
1334
+ type: "button",
1335
+ variant,
1336
+ ...props,
1337
+ children: [
1338
+ Icon2 ? /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Icon2, {
1339
+ className: "size-4"
1340
+ }, undefined, false, undefined, this) : children,
1341
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("span", {
1342
+ className: "sr-only",
1343
+ children: label || tooltip
1344
+ }, undefined, false, undefined, this)
1345
+ ]
1346
+ }, undefined, true, undefined, this);
1347
+ if (tooltip) {
1348
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(TooltipProvider, {
1349
+ children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Tooltip, {
1350
+ children: [
1351
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(TooltipTrigger, {
1352
+ asChild: true,
1353
+ children: button
1354
+ }, undefined, false, undefined, this),
1355
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(TooltipContent, {
1356
+ children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("p", {
1357
+ children: tooltip
1358
+ }, undefined, false, undefined, this)
1359
+ }, undefined, false, undefined, this)
1360
+ ]
1361
+ }, undefined, true, undefined, this)
1362
+ }, undefined, false, undefined, this);
1363
+ }
1364
+ return button;
1365
+ };
1366
+ var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime17.jsxDEV("div", {
1367
+ className: cn("flex-1 overflow-auto p-4", className),
1368
+ ...props
1369
+ }, undefined, false, undefined, this);
1370
+ // src/ui/components/streaming-indicator.tsx
1371
+ var import_lucide_react10 = require("lucide-react");
1372
+ var jsx_dev_runtime18 = require("react/jsx-dev-runtime");
1373
+ function StreamingIndicator({ className, icon, avatar, ...props }) {
1374
+ return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("div", {
1375
+ className: cn("flex items-start gap-3 px-1", className),
1376
+ ...props,
1377
+ children: [
1378
+ avatar ?? /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("div", {
1379
+ className: "h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5",
1380
+ children: icon ?? /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(import_lucide_react10.Bot, {
1381
+ className: "h-4 w-4 text-primary"
1382
+ }, undefined, false, undefined, this)
1383
+ }, undefined, false, undefined, this),
1384
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("div", {
1385
+ className: "flex items-center gap-1.5 pt-2.5",
1386
+ children: [
1387
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("span", {
1388
+ className: "h-2 w-2 rounded-full bg-primary/60 animate-pulse"
1389
+ }, undefined, false, undefined, this),
1390
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("span", {
1391
+ className: "h-2 w-2 rounded-full bg-primary/60 animate-pulse [animation-delay:150ms]"
1392
+ }, undefined, false, undefined, this),
1393
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV("span", {
1394
+ className: "h-2 w-2 rounded-full bg-primary/60 animate-pulse [animation-delay:300ms]"
1395
+ }, undefined, false, undefined, this)
1396
+ ]
1397
+ }, undefined, true, undefined, this)
1398
+ ]
1399
+ }, undefined, true, undefined, this);
1400
+ }
1401
+ // src/ui/components/audio-recorder.tsx
1402
+ var import_react5 = require("react");
1403
+ var import_lucide_react11 = require("lucide-react");
1404
+ var jsx_dev_runtime19 = require("react/jsx-dev-runtime");
1405
+ function encodeWav(samples, sampleRate) {
1406
+ const numChannels = 1;
1407
+ const bitsPerSample = 16;
1408
+ const byteRate = sampleRate * numChannels * (bitsPerSample / 8);
1409
+ const blockAlign = numChannels * (bitsPerSample / 8);
1410
+ const dataLength = samples.length * (bitsPerSample / 8);
1411
+ const buffer = new ArrayBuffer(44 + dataLength);
1412
+ const view = new DataView(buffer);
1413
+ writeString(view, 0, "RIFF");
1414
+ view.setUint32(4, 36 + dataLength, true);
1415
+ writeString(view, 8, "WAVE");
1416
+ writeString(view, 12, "fmt ");
1417
+ view.setUint32(16, 16, true);
1418
+ view.setUint16(20, 1, true);
1419
+ view.setUint16(22, numChannels, true);
1420
+ view.setUint32(24, sampleRate, true);
1421
+ view.setUint32(28, byteRate, true);
1422
+ view.setUint16(32, blockAlign, true);
1423
+ view.setUint16(34, bitsPerSample, true);
1424
+ writeString(view, 36, "data");
1425
+ view.setUint32(40, dataLength, true);
1426
+ let offset = 44;
1427
+ for (let i = 0;i < samples.length; i++) {
1428
+ const s = Math.max(-1, Math.min(1, samples[i]));
1429
+ view.setInt16(offset, s < 0 ? s * 32768 : s * 32767, true);
1430
+ offset += 2;
1431
+ }
1432
+ return new Blob([buffer], { type: "audio/wav" });
1433
+ }
1434
+ function writeString(view, offset, str) {
1435
+ for (let i = 0;i < str.length; i++) {
1436
+ view.setUint8(offset + i, str.charCodeAt(i));
1437
+ }
1438
+ }
1439
+ function createWorkletUrl() {
1440
+ const code = `
1441
+ class RecorderProcessor extends AudioWorkletProcessor {
1442
+ constructor() {
1443
+ super();
1444
+ this._stopped = false;
1445
+ this.port.onmessage = (e) => {
1446
+ if (e.data === 'stop') this._stopped = true;
1447
+ };
1448
+ }
1449
+ process(inputs) {
1450
+ if (this._stopped) return false;
1451
+ const input = inputs[0];
1452
+ if (input && input[0]) {
1453
+ this.port.postMessage(new Float32Array(input[0]));
1454
+ }
1455
+ return true;
1456
+ }
1457
+ }
1458
+ registerProcessor('recorder-processor', RecorderProcessor);
1459
+ `;
1460
+ const blob = new Blob([code], { type: "application/javascript" });
1461
+ return URL.createObjectURL(blob);
1462
+ }
1463
+ function AudioRecorder({
1464
+ onRecordingComplete,
1465
+ disabled,
1466
+ className,
1467
+ mode = "send",
1468
+ transcriptionEndpoint,
1469
+ transcriptionHeaders,
1470
+ onTranscriptionComplete,
1471
+ transcriptionFieldName = "file",
1472
+ parseTranscriptionResponse,
1473
+ onRequestPermission,
1474
+ labels
1475
+ }) {
1476
+ const [isRecording, setIsRecording] = import_react5.useState(false);
1477
+ const [isTranscribing, setIsTranscribing] = import_react5.useState(false);
1478
+ const [duration, setDuration] = import_react5.useState(0);
1479
+ const [isSupported, setIsSupported] = import_react5.useState(true);
1480
+ const streamRef = import_react5.useRef(null);
1481
+ const audioContextRef = import_react5.useRef(null);
1482
+ const workletNodeRef = import_react5.useRef(null);
1483
+ const chunksRef = import_react5.useRef([]);
1484
+ const timerRef = import_react5.useRef(null);
1485
+ const workletUrlRef = import_react5.useRef(null);
1486
+ const onTranscriptionCompleteRef = import_react5.useRef(onTranscriptionComplete);
1487
+ onTranscriptionCompleteRef.current = onTranscriptionComplete;
1488
+ import_react5.useEffect(() => {
1489
+ if (typeof window === "undefined" || !navigator.mediaDevices?.getUserMedia) {
1490
+ setIsSupported(false);
1491
+ }
1492
+ return () => {
1493
+ if (timerRef.current)
1494
+ clearInterval(timerRef.current);
1495
+ if (workletNodeRef.current) {
1496
+ workletNodeRef.current.port.postMessage("stop");
1497
+ workletNodeRef.current.disconnect();
1498
+ workletNodeRef.current = null;
1499
+ }
1500
+ if (audioContextRef.current) {
1501
+ audioContextRef.current.close();
1502
+ audioContextRef.current = null;
1503
+ }
1504
+ if (streamRef.current) {
1505
+ streamRef.current.getTracks().forEach((track) => track.stop());
1506
+ streamRef.current = null;
1507
+ }
1508
+ if (workletUrlRef.current)
1509
+ URL.revokeObjectURL(workletUrlRef.current);
1510
+ };
1511
+ }, []);
1512
+ const startRecording = import_react5.useCallback(async () => {
1513
+ try {
1514
+ if (onRequestPermission) {
1515
+ const granted = await onRequestPermission();
1516
+ if (!granted)
1517
+ return;
1518
+ }
1519
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
1520
+ streamRef.current = stream;
1521
+ const audioContext = new AudioContext;
1522
+ audioContextRef.current = audioContext;
1523
+ const workletUrl = createWorkletUrl();
1524
+ workletUrlRef.current = workletUrl;
1525
+ await audioContext.audioWorklet.addModule(workletUrl);
1526
+ const source = audioContext.createMediaStreamSource(stream);
1527
+ const workletNode = new AudioWorkletNode(audioContext, "recorder-processor");
1528
+ workletNodeRef.current = workletNode;
1529
+ chunksRef.current = [];
1530
+ workletNode.port.onmessage = (e) => {
1531
+ if (e.data instanceof Float32Array) {
1532
+ chunksRef.current.push(e.data);
1533
+ }
1534
+ };
1535
+ source.connect(workletNode);
1536
+ workletNode.connect(audioContext.destination);
1537
+ setIsRecording(true);
1538
+ setDuration(0);
1539
+ timerRef.current = setInterval(() => {
1540
+ setDuration((prev) => prev + 1);
1541
+ }, 1000);
1542
+ } catch {
1543
+ console.error("Failed to start recording");
1544
+ }
1545
+ }, [onRequestPermission]);
1546
+ const stopRecording = import_react5.useCallback(async () => {
1547
+ if (workletNodeRef.current) {
1548
+ workletNodeRef.current.port.postMessage("stop");
1549
+ workletNodeRef.current.disconnect();
1550
+ workletNodeRef.current = null;
1551
+ }
1552
+ const audioContext = audioContextRef.current;
1553
+ let wavBlob = null;
1554
+ if (audioContext) {
1555
+ const sampleRate = audioContext.sampleRate;
1556
+ const totalLength = chunksRef.current.reduce((sum, chunk) => sum + chunk.length, 0);
1557
+ const merged = new Float32Array(totalLength);
1558
+ let offset = 0;
1559
+ for (const chunk of chunksRef.current) {
1560
+ merged.set(chunk, offset);
1561
+ offset += chunk.length;
1562
+ }
1563
+ chunksRef.current = [];
1564
+ wavBlob = encodeWav(merged, sampleRate);
1565
+ audioContext.close();
1566
+ audioContextRef.current = null;
1567
+ }
1568
+ if (streamRef.current) {
1569
+ streamRef.current.getTracks().forEach((track) => track.stop());
1570
+ streamRef.current = null;
1571
+ }
1572
+ if (workletUrlRef.current) {
1573
+ URL.revokeObjectURL(workletUrlRef.current);
1574
+ workletUrlRef.current = null;
1575
+ }
1576
+ setIsRecording(false);
1577
+ if (timerRef.current) {
1578
+ clearInterval(timerRef.current);
1579
+ timerRef.current = null;
1580
+ }
1581
+ if (!wavBlob)
1582
+ return;
1583
+ if (mode === "transcribe" && transcriptionEndpoint) {
1584
+ setIsTranscribing(true);
1585
+ const formData = new FormData;
1586
+ formData.append(transcriptionFieldName, wavBlob, "recording.wav");
1587
+ try {
1588
+ const res = await fetch(transcriptionEndpoint, {
1589
+ method: "POST",
1590
+ headers: transcriptionHeaders,
1591
+ credentials: "include",
1592
+ body: formData
1593
+ });
1594
+ const data = await res.json();
1595
+ const text = parseTranscriptionResponse ? parseTranscriptionResponse(data) : data.text || data.transcript || data.transcription || (typeof data === "string" ? data : "");
1596
+ if (text)
1597
+ onTranscriptionCompleteRef.current?.(text);
1598
+ } catch (err) {
1599
+ console.error("Transcription failed:", err);
1600
+ } finally {
1601
+ setIsTranscribing(false);
1602
+ }
1603
+ } else {
1604
+ onRecordingComplete(wavBlob);
1605
+ }
1606
+ }, [onRecordingComplete, mode, transcriptionEndpoint, transcriptionHeaders, transcriptionFieldName, parseTranscriptionResponse]);
1607
+ const resolvedLabels = {
1608
+ recordAudio: labels?.recordAudio ?? "Record audio",
1609
+ stopRecording: labels?.stopRecording ?? "Stop recording",
1610
+ transcribing: labels?.transcribing ?? "Transcribing..."
1611
+ };
1612
+ const formatDuration = (seconds) => {
1613
+ const m = Math.floor(seconds / 60);
1614
+ const s = seconds % 60;
1615
+ return `${m}:${s.toString().padStart(2, "0")}`;
1616
+ };
1617
+ if (!isSupported)
1618
+ return null;
1619
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV("div", {
1620
+ className: cn("flex items-center gap-1", className),
1621
+ children: [
1622
+ isRecording && /* @__PURE__ */ jsx_dev_runtime19.jsxDEV("span", {
1623
+ className: "text-xs text-destructive font-mono animate-pulse",
1624
+ children: formatDuration(duration)
1625
+ }, undefined, false, undefined, this),
1626
+ isTranscribing ? /* @__PURE__ */ jsx_dev_runtime19.jsxDEV("span", {
1627
+ className: "flex items-center gap-1.5 text-xs text-muted-foreground",
1628
+ children: [
1629
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(import_lucide_react11.Loader2, {
1630
+ className: "size-3.5 animate-spin"
1631
+ }, undefined, false, undefined, this),
1632
+ resolvedLabels.transcribing
1633
+ ]
1634
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Button, {
1635
+ type: "button",
1636
+ variant: "ghost",
1637
+ size: "icon",
1638
+ className: cn("h-8 w-8", isRecording && "text-destructive hover:text-destructive"),
1639
+ disabled,
1640
+ onClick: isRecording ? stopRecording : startRecording,
1641
+ title: isRecording ? resolvedLabels.stopRecording : resolvedLabels.recordAudio,
1642
+ children: isRecording ? /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(import_lucide_react11.Square, {
1643
+ className: "size-4 fill-current"
1644
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(import_lucide_react11.Mic, {
1645
+ className: "size-4"
1646
+ }, undefined, false, undefined, this)
1647
+ }, undefined, false, undefined, this)
1648
+ ]
1649
+ }, undefined, true, undefined, this);
1650
+ }
1651
+ // src/ui/components/smart-timestamp.tsx
1652
+ var jsx_dev_runtime20 = require("react/jsx-dev-runtime");
1653
+ function SmartTimestamp({ date, formatShort, className }) {
1654
+ const shortText = formatShort ? formatShort(date) : formatSmartTimestamp(date);
1655
+ const fullText = formatFullTimestamp(date);
1656
+ return /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(TooltipProvider, {
1657
+ children: /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Tooltip, {
1658
+ children: [
1659
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(TooltipTrigger, {
1660
+ asChild: true,
1661
+ children: /* @__PURE__ */ jsx_dev_runtime20.jsxDEV("span", {
1662
+ className,
1663
+ children: shortText
1664
+ }, undefined, false, undefined, this)
1665
+ }, undefined, false, undefined, this),
1666
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(TooltipContent, {
1667
+ children: /* @__PURE__ */ jsx_dev_runtime20.jsxDEV("p", {
1668
+ children: fullText
1669
+ }, undefined, false, undefined, this)
1670
+ }, undefined, false, undefined, this)
1671
+ ]
1672
+ }, undefined, true, undefined, this)
1673
+ }, undefined, false, undefined, this);
1674
+ }
1675
+ // src/ui/components/file-preview-card.tsx
1676
+ var import_lucide_react12 = require("lucide-react");
1677
+ var jsx_dev_runtime21 = require("react/jsx-dev-runtime");
1678
+ function ExtBadge({ ext }) {
1679
+ if (!ext)
1680
+ return null;
1681
+ return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("span", {
1682
+ className: "absolute bottom-1.5 left-1.5 rounded px-1 py-0.5 text-[9px] font-semibold uppercase leading-none bg-background/80 text-muted-foreground border border-border/50 backdrop-blur-sm",
1683
+ children: ext
1684
+ }, undefined, false, undefined, this);
1685
+ }
1686
+ function FilePreviewCard({ file, onClick, className }) {
1687
+ const previewType = getFilePreviewType(file.type);
1688
+ const isClickable = !!onClick;
1689
+ const ext = getFileExtension(file.name, file.type);
1690
+ const cardBase = cn("group relative flex flex-col overflow-hidden rounded-xl border border-border bg-muted/20 w-28 h-28", isClickable && "cursor-pointer hover:border-foreground/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 transition-colors", className);
1691
+ if (previewType === "image" && file.url) {
1692
+ return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("button", {
1693
+ type: "button",
1694
+ onClick,
1695
+ disabled: !isClickable,
1696
+ className: cardBase,
1697
+ children: [
1698
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("img", {
1699
+ src: file.url,
1700
+ alt: file.name,
1701
+ className: "w-full h-full object-cover"
1702
+ }, undefined, false, undefined, this),
1703
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(ExtBadge, {
1704
+ ext
1705
+ }, undefined, false, undefined, this),
1706
+ isClickable && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1707
+ className: "absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/30 transition-colors",
1708
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(import_lucide_react12.Search, {
1709
+ className: "h-5 w-5 text-white opacity-0 group-hover:opacity-100 transition-opacity"
1710
+ }, undefined, false, undefined, this)
1711
+ }, undefined, false, undefined, this)
1712
+ ]
1713
+ }, undefined, true, undefined, this);
1714
+ }
1715
+ if (previewType === "pdf" && file.url) {
1716
+ return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("button", {
1717
+ type: "button",
1718
+ onClick,
1719
+ disabled: !isClickable,
1720
+ className: cardBase,
1721
+ children: [
1722
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1723
+ className: "w-full h-full overflow-hidden pointer-events-none",
1724
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("object", {
1725
+ data: `${file.url}#page=1&view=FitH`,
1726
+ type: "application/pdf",
1727
+ className: "w-[200%] h-[200%] origin-top-left scale-50",
1728
+ "aria-label": file.name,
1729
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1730
+ className: "flex items-center justify-center w-full h-full",
1731
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(import_lucide_react12.FileIcon, {
1732
+ className: "h-8 w-8 text-muted-foreground/40"
1733
+ }, undefined, false, undefined, this)
1734
+ }, undefined, false, undefined, this)
1735
+ }, undefined, false, undefined, this)
1736
+ }, undefined, false, undefined, this),
1737
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(ExtBadge, {
1738
+ ext
1739
+ }, undefined, false, undefined, this),
1740
+ isClickable && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1741
+ className: "absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/10 transition-colors",
1742
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(import_lucide_react12.Search, {
1743
+ className: "h-5 w-5 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity"
1744
+ }, undefined, false, undefined, this)
1745
+ }, undefined, false, undefined, this)
1746
+ ]
1747
+ }, undefined, true, undefined, this);
1748
+ }
1749
+ return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("button", {
1750
+ type: "button",
1751
+ onClick,
1752
+ disabled: !isClickable,
1753
+ className: cardBase,
1754
+ children: [
1755
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1756
+ className: "flex-1 flex items-center justify-center",
1757
+ children: /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(import_lucide_react12.FileIcon, {
1758
+ className: "h-8 w-8 text-muted-foreground/40"
1759
+ }, undefined, false, undefined, this)
1760
+ }, undefined, false, undefined, this),
1761
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("div", {
1762
+ className: "w-full text-center min-w-0 px-2 pb-2 space-y-0.5",
1763
+ children: [
1764
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("p", {
1765
+ className: "text-[10px] text-foreground truncate leading-tight",
1766
+ title: file.name,
1767
+ children: file.name
1768
+ }, undefined, false, undefined, this),
1769
+ file.size != null && file.size > 0 && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV("p", {
1770
+ className: "text-[9px] text-muted-foreground leading-tight",
1771
+ children: formatFileSize(file.size)
1772
+ }, undefined, false, undefined, this)
1773
+ ]
1774
+ }, undefined, true, undefined, this),
1775
+ /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(ExtBadge, {
1776
+ ext
1777
+ }, undefined, false, undefined, this)
1778
+ ]
1779
+ }, undefined, true, undefined, this);
1780
+ }
1781
+ // src/ui/components/file-preview-modal.tsx
1782
+ var import_lucide_react13 = require("lucide-react");
1783
+ var jsx_dev_runtime22 = require("react/jsx-dev-runtime");
1784
+ function FilePreviewModal({ open, onOpenChange, file }) {
1785
+ if (!file)
1786
+ return null;
1787
+ const previewType = getFilePreviewType(file.type);
1788
+ const canPreview = isPreviewable(file.type) && !!file.url;
1789
+ return /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Dialog, {
1790
+ open,
1791
+ onOpenChange,
1792
+ children: previewType === "image" && file.url ? /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogContent, {
1793
+ variant: "lightbox",
1794
+ "aria-describedby": undefined,
1795
+ children: [
1796
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogTitle, {
1797
+ className: "sr-only",
1798
+ children: file.name
1799
+ }, undefined, false, undefined, this),
1800
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("img", {
1801
+ src: file.url,
1802
+ alt: file.name,
1803
+ className: "max-h-[85vh] max-w-full object-contain rounded-md"
1804
+ }, undefined, false, undefined, this)
1805
+ ]
1806
+ }, undefined, true, undefined, this) : previewType === "pdf" && file.url ? /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogContent, {
1807
+ variant: "lightbox",
1808
+ className: "w-[80vw] h-[85vh]",
1809
+ "aria-describedby": undefined,
1810
+ children: [
1811
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogTitle, {
1812
+ className: "sr-only",
1813
+ children: file.name
1814
+ }, undefined, false, undefined, this),
1815
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("object", {
1816
+ data: file.url,
1817
+ type: "application/pdf",
1818
+ className: "w-full h-full rounded-md",
1819
+ children: /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("div", {
1820
+ className: "flex flex-col items-center justify-center h-full gap-3 text-muted-foreground",
1821
+ children: [
1822
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("p", {
1823
+ className: "text-sm",
1824
+ children: "Unable to display PDF"
1825
+ }, undefined, false, undefined, this),
1826
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("a", {
1827
+ href: file.url,
1828
+ target: "_blank",
1829
+ rel: "noopener noreferrer",
1830
+ className: "inline-flex items-center gap-1.5 text-sm text-primary hover:underline",
1831
+ children: [
1832
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(import_lucide_react13.Download, {
1833
+ className: "h-4 w-4"
1834
+ }, undefined, false, undefined, this),
1835
+ "Download ",
1836
+ file.name
1837
+ ]
1838
+ }, undefined, true, undefined, this)
1839
+ ]
1840
+ }, undefined, true, undefined, this)
1841
+ }, undefined, false, undefined, this)
1842
+ ]
1843
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogContent, {
1844
+ children: [
1845
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogHeader, {
1846
+ children: [
1847
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogTitle, {
1848
+ className: "flex items-center gap-2",
1849
+ children: [
1850
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(import_lucide_react13.FileIcon, {
1851
+ className: "h-5 w-5 text-muted-foreground"
1852
+ }, undefined, false, undefined, this),
1853
+ file.name
1854
+ ]
1855
+ }, undefined, true, undefined, this),
1856
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(DialogDescription, {
1857
+ children: [
1858
+ file.size != null && file.size > 0 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("span", {
1859
+ children: formatFileSize(file.size)
1860
+ }, undefined, false, undefined, this),
1861
+ !canPreview && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("span", {
1862
+ children: " · Preview not available for this file type"
1863
+ }, undefined, false, undefined, this)
1864
+ ]
1865
+ }, undefined, true, undefined, this)
1866
+ ]
1867
+ }, undefined, true, undefined, this),
1868
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("div", {
1869
+ className: "flex flex-col items-center justify-center py-8 text-muted-foreground gap-3",
1870
+ children: [
1871
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(import_lucide_react13.FileIcon, {
1872
+ className: "h-12 w-12"
1873
+ }, undefined, false, undefined, this),
1874
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("p", {
1875
+ className: "text-sm",
1876
+ children: "Preview not available"
1877
+ }, undefined, false, undefined, this),
1878
+ file.url && /^https?:\/\//i.test(file.url) && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV("a", {
1879
+ href: file.url,
1880
+ target: "_blank",
1881
+ rel: "noopener noreferrer",
1882
+ className: "inline-flex items-center gap-1.5 text-sm text-primary hover:underline",
1883
+ children: [
1884
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(import_lucide_react13.Download, {
1885
+ className: "h-4 w-4"
1886
+ }, undefined, false, undefined, this),
1887
+ "Download file"
1888
+ ]
1889
+ }, undefined, true, undefined, this)
1890
+ ]
1891
+ }, undefined, true, undefined, this)
1892
+ ]
1893
+ }, undefined, true, undefined, this)
1894
+ }, undefined, false, undefined, this);
1895
+ }
1896
+ // src/ui/components/image-lightbox.tsx
1897
+ var import_react6 = require("react");
1898
+ var import_lucide_react14 = require("lucide-react");
1899
+ var jsx_dev_runtime23 = require("react/jsx-dev-runtime");
1900
+ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
1901
+ const [currentIndex, setCurrentIndex] = import_react6.useState(initialIndex);
1902
+ const hasMultiple = images.length > 1;
1903
+ import_react6.useEffect(() => {
1904
+ if (open)
1905
+ setCurrentIndex(initialIndex);
1906
+ }, [open, initialIndex]);
1907
+ const goNext = import_react6.useCallback(() => {
1908
+ setCurrentIndex((i) => (i + 1) % images.length);
1909
+ }, [images.length]);
1910
+ const goPrev = import_react6.useCallback(() => {
1911
+ setCurrentIndex((i) => (i - 1 + images.length) % images.length);
1912
+ }, [images.length]);
1913
+ import_react6.useEffect(() => {
1914
+ if (!open || !hasMultiple)
1915
+ return;
1916
+ const handler = (e) => {
1917
+ if (e.key === "ArrowRight")
1918
+ goNext();
1919
+ if (e.key === "ArrowLeft")
1920
+ goPrev();
1921
+ };
1922
+ window.addEventListener("keydown", handler);
1923
+ return () => window.removeEventListener("keydown", handler);
1924
+ }, [open, hasMultiple, goNext, goPrev]);
1925
+ if (images.length === 0)
1926
+ return null;
1927
+ const current = images[currentIndex];
1928
+ if (!current)
1929
+ return null;
1930
+ return /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Dialog, {
1931
+ open,
1932
+ onOpenChange,
1933
+ children: /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(DialogContent, {
1934
+ variant: "lightbox",
1935
+ "aria-describedby": undefined,
1936
+ children: [
1937
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(DialogTitle, {
1938
+ className: "sr-only",
1939
+ children: current.alt || `Image ${currentIndex + 1} of ${images.length}`
1940
+ }, undefined, false, undefined, this),
1941
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("div", {
1942
+ className: "relative flex items-center justify-center",
1943
+ children: [
1944
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("img", {
1945
+ src: current.url,
1946
+ alt: current.alt || "Image preview",
1947
+ className: "max-h-[85vh] max-w-full object-contain rounded-md"
1948
+ }, undefined, false, undefined, this),
1949
+ hasMultiple && /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(jsx_dev_runtime23.Fragment, {
1950
+ children: [
1951
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("button", {
1952
+ type: "button",
1953
+ onClick: goPrev,
1954
+ className: cn("absolute left-2 top-1/2 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white", "hover:bg-black/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors"),
1955
+ children: [
1956
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(import_lucide_react14.ChevronLeft, {
1957
+ className: "h-5 w-5"
1958
+ }, undefined, false, undefined, this),
1959
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("span", {
1960
+ className: "sr-only",
1961
+ children: "Previous image"
1962
+ }, undefined, false, undefined, this)
1963
+ ]
1964
+ }, undefined, true, undefined, this),
1965
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("button", {
1966
+ type: "button",
1967
+ onClick: goNext,
1968
+ className: cn("absolute right-2 top-1/2 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white", "hover:bg-black/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors"),
1969
+ children: [
1970
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(import_lucide_react14.ChevronRight, {
1971
+ className: "h-5 w-5"
1972
+ }, undefined, false, undefined, this),
1973
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("span", {
1974
+ className: "sr-only",
1975
+ children: "Next image"
1976
+ }, undefined, false, undefined, this)
1977
+ ]
1978
+ }, undefined, true, undefined, this),
1979
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV("div", {
1980
+ className: "absolute bottom-2 left-1/2 -translate-x-1/2 rounded-full bg-black/50 px-3 py-1 text-xs text-white",
1981
+ children: [
1982
+ currentIndex + 1,
1983
+ " / ",
1984
+ images.length
1985
+ ]
1986
+ }, undefined, true, undefined, this)
1987
+ ]
1988
+ }, undefined, true, undefined, this)
1989
+ ]
1990
+ }, undefined, true, undefined, this)
1991
+ ]
1992
+ }, undefined, true, undefined, this)
1993
+ }, undefined, false, undefined, this);
1994
+ }
1995
+ // src/ui/components/prompt-input/context.ts
1996
+ var import_react7 = require("react");
1997
+ var PromptInputController = import_react7.createContext(null);
1998
+ var ProviderAttachmentsContext = import_react7.createContext(null);
1999
+ var LocalAttachmentsContext = import_react7.createContext(null);
2000
+ var usePromptInputController = () => {
2001
+ const ctx = import_react7.useContext(PromptInputController);
2002
+ if (!ctx) {
2003
+ throw new Error("Wrap your component inside <PromptInputProvider> to use usePromptInputController().");
2004
+ }
2005
+ return ctx;
2006
+ };
2007
+ var useOptionalPromptInputController = () => import_react7.useContext(PromptInputController);
2008
+ var useProviderAttachments = () => {
2009
+ const ctx = import_react7.useContext(ProviderAttachmentsContext);
2010
+ if (!ctx) {
2011
+ throw new Error("Wrap your component inside <PromptInputProvider> to use useProviderAttachments().");
2012
+ }
2013
+ return ctx;
2014
+ };
2015
+ var useOptionalProviderAttachments = () => import_react7.useContext(ProviderAttachmentsContext);
2016
+ var usePromptInputAttachments = () => {
2017
+ const provider = useOptionalProviderAttachments();
2018
+ const local = import_react7.useContext(LocalAttachmentsContext);
2019
+ const context = provider ?? local;
2020
+ if (!context) {
2021
+ throw new Error("usePromptInputAttachments must be used within a PromptInput or PromptInputProvider");
2022
+ }
2023
+ return context;
2024
+ };
2025
+ var DropZoneContext = import_react7.createContext({ isDraggingOver: false });
2026
+ var usePromptInputDropZone = () => import_react7.useContext(DropZoneContext);
2027
+ // src/ui/components/prompt-input/provider.tsx
2028
+ var import_react8 = require("react");
2029
+ var jsx_dev_runtime24 = require("react/jsx-dev-runtime");
2030
+ function generateId() {
2031
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2032
+ return crypto.randomUUID();
2033
+ }
2034
+ return Math.random().toString(36).slice(2) + Date.now().toString(36);
2035
+ }
2036
+ function PromptInputProvider({ initialInput: initialTextInput = "", children }) {
2037
+ const [textInput, setTextInput] = import_react8.useState(initialTextInput);
2038
+ const clearInput = import_react8.useCallback(() => setTextInput(""), []);
2039
+ const [fileItems, setFileItems] = import_react8.useState([]);
2040
+ const fileInputRef = import_react8.useRef(null);
2041
+ const openRef = import_react8.useRef(() => {});
2042
+ const add = import_react8.useCallback((files) => {
2043
+ const incoming = Array.from(files);
2044
+ if (incoming.length === 0)
2045
+ return;
2046
+ setFileItems((prev) => prev.concat(incoming.map((file) => ({
2047
+ id: generateId(),
2048
+ type: "file",
2049
+ url: URL.createObjectURL(file),
2050
+ mediaType: file.type,
2051
+ filename: file.name
2052
+ }))));
2053
+ }, []);
2054
+ const remove = import_react8.useCallback((id) => {
2055
+ setFileItems((prev) => {
2056
+ const found = prev.find((f) => f.id === id);
2057
+ if (found?.url)
2058
+ URL.revokeObjectURL(found.url);
2059
+ return prev.filter((f) => f.id !== id);
2060
+ });
2061
+ }, []);
2062
+ const clear = import_react8.useCallback(() => {
2063
+ setFileItems((prev) => {
2064
+ for (const f of prev)
2065
+ if (f.url)
2066
+ URL.revokeObjectURL(f.url);
2067
+ return [];
2068
+ });
2069
+ }, []);
2070
+ const openFileDialog = import_react8.useCallback(() => {
2071
+ openRef.current?.();
2072
+ }, []);
2073
+ const attachments = import_react8.useMemo(() => ({
2074
+ files: fileItems,
2075
+ add,
2076
+ remove,
2077
+ clear,
2078
+ openFileDialog,
2079
+ fileInputRef
2080
+ }), [fileItems, add, remove, clear, openFileDialog]);
2081
+ const __registerFileInput = import_react8.useCallback((ref, open) => {
2082
+ fileInputRef.current = ref.current;
2083
+ openRef.current = open;
2084
+ }, []);
2085
+ const controller = import_react8.useMemo(() => ({
2086
+ textInput: { value: textInput, setInput: setTextInput, clear: clearInput },
2087
+ attachments,
2088
+ __registerFileInput
2089
+ }), [textInput, clearInput, attachments, __registerFileInput]);
2090
+ return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(PromptInputController.Provider, {
2091
+ value: controller,
2092
+ children: /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(ProviderAttachmentsContext.Provider, {
2093
+ value: attachments,
2094
+ children
2095
+ }, undefined, false, undefined, this)
2096
+ }, undefined, false, undefined, this);
2097
+ }
2098
+ // src/ui/components/prompt-input/prompt-input.tsx
2099
+ var import_react9 = require("react");
2100
+ var jsx_dev_runtime25 = require("react/jsx-dev-runtime");
2101
+ function generateId2() {
2102
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2103
+ return crypto.randomUUID();
2104
+ }
2105
+ return Math.random().toString(36).slice(2) + Date.now().toString(36);
2106
+ }
2107
+ var PromptInput = ({
2108
+ className,
2109
+ accept,
2110
+ multiple,
2111
+ globalDrop,
2112
+ syncHiddenInput,
2113
+ maxFiles,
2114
+ maxFileSize,
2115
+ dragListenerTarget,
2116
+ onError,
2117
+ onSubmit,
2118
+ children,
2119
+ ...props
2120
+ }) => {
2121
+ const controller = useOptionalPromptInputController();
2122
+ const usingProvider = !!controller;
2123
+ const inputRef = import_react9.useRef(null);
2124
+ const formRef = import_react9.useRef(null);
2125
+ const [items, setItems] = import_react9.useState([]);
2126
+ const files = usingProvider ? controller.attachments.files : items;
2127
+ const [isDraggingOver, setIsDraggingOver] = import_react9.useState(false);
2128
+ const dragCounter = import_react9.useRef(0);
2129
+ const openFileDialogLocal = import_react9.useCallback(() => {
2130
+ inputRef.current?.click();
2131
+ }, []);
2132
+ const matchesAccept = import_react9.useCallback((f) => {
2133
+ if (!accept || accept.trim() === "")
2134
+ return true;
2135
+ const patterns = accept.split(",").map((p) => p.trim()).filter(Boolean);
2136
+ for (const pattern of patterns) {
2137
+ if (pattern.endsWith("/*")) {
2138
+ const prefix = pattern.slice(0, -1);
2139
+ if (f.type.startsWith(prefix))
2140
+ return true;
2141
+ } else if (pattern.startsWith(".")) {
2142
+ const ext = f.name.toLowerCase().split(".").pop();
2143
+ if (ext && `.${ext}` === pattern.toLowerCase())
2144
+ return true;
2145
+ } else if (f.type === pattern) {
2146
+ return true;
2147
+ }
2148
+ }
2149
+ return false;
2150
+ }, [accept]);
2151
+ const addLocal = import_react9.useCallback((fileList) => {
2152
+ const incoming = Array.from(fileList);
2153
+ const accepted = incoming.filter((f) => matchesAccept(f));
2154
+ if (incoming.length && accepted.length === 0) {
2155
+ onError?.({ code: "accept", message: "No files match the accepted types." });
2156
+ return;
2157
+ }
2158
+ const withinSize = (f) => maxFileSize ? f.size <= maxFileSize : true;
2159
+ const sized = accepted.filter(withinSize);
2160
+ if (accepted.length > 0 && sized.length === 0) {
2161
+ onError?.({ code: "max_file_size", message: "All files exceed the maximum size." });
2162
+ return;
2163
+ }
2164
+ setItems((prev) => {
2165
+ const capacity = typeof maxFiles === "number" ? Math.max(0, maxFiles - prev.length) : undefined;
2166
+ const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
2167
+ if (typeof capacity === "number" && sized.length > capacity) {
2168
+ onError?.({ code: "max_files", message: "Too many files. Some were not added." });
2169
+ }
2170
+ const next = [];
2171
+ for (const file of capped) {
2172
+ next.push({
2173
+ id: generateId2(),
2174
+ type: "file",
2175
+ url: URL.createObjectURL(file),
2176
+ mediaType: file.type,
2177
+ filename: file.name
2178
+ });
2179
+ }
2180
+ return prev.concat(next);
2181
+ });
2182
+ }, [matchesAccept, maxFiles, maxFileSize, onError]);
2183
+ const add = usingProvider ? (fileList) => controller.attachments.add(fileList) : addLocal;
2184
+ const remove = usingProvider ? (id) => controller.attachments.remove(id) : (id) => setItems((prev) => {
2185
+ const found = prev.find((file) => file.id === id);
2186
+ if (found?.url)
2187
+ URL.revokeObjectURL(found.url);
2188
+ return prev.filter((file) => file.id !== id);
2189
+ });
2190
+ const clear = usingProvider ? () => controller.attachments.clear() : () => setItems((prev) => {
2191
+ for (const file of prev)
2192
+ if (file.url)
2193
+ URL.revokeObjectURL(file.url);
2194
+ return [];
2195
+ });
2196
+ const openFileDialog = usingProvider ? () => controller.attachments.openFileDialog() : openFileDialogLocal;
2197
+ import_react9.useEffect(() => {
2198
+ if (!usingProvider)
2199
+ return;
2200
+ controller.__registerFileInput(inputRef, () => inputRef.current?.click());
2201
+ }, [usingProvider, controller]);
2202
+ import_react9.useEffect(() => {
2203
+ if (syncHiddenInput && inputRef.current && files.length === 0) {
2204
+ inputRef.current.value = "";
2205
+ }
2206
+ }, [files, syncHiddenInput]);
2207
+ import_react9.useEffect(() => {
2208
+ if (globalDrop)
2209
+ return;
2210
+ const form = formRef.current;
2211
+ if (!form)
2212
+ return;
2213
+ const onDragOver = (e) => {
2214
+ if (e.dataTransfer?.types?.includes("Files"))
2215
+ e.preventDefault();
2216
+ };
2217
+ const onDragEnter = (e) => {
2218
+ if (e.dataTransfer?.types?.includes("Files")) {
2219
+ e.preventDefault();
2220
+ dragCounter.current++;
2221
+ if (dragCounter.current === 1)
2222
+ setIsDraggingOver(true);
2223
+ }
2224
+ };
2225
+ const onDragLeave = (_e) => {
2226
+ dragCounter.current--;
2227
+ if (dragCounter.current === 0)
2228
+ setIsDraggingOver(false);
2229
+ };
2230
+ const onDrop = (e) => {
2231
+ if (e.dataTransfer?.types?.includes("Files"))
2232
+ e.preventDefault();
2233
+ dragCounter.current = 0;
2234
+ setIsDraggingOver(false);
2235
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0)
2236
+ add(e.dataTransfer.files);
2237
+ };
2238
+ form.addEventListener("dragover", onDragOver);
2239
+ form.addEventListener("dragenter", onDragEnter);
2240
+ form.addEventListener("dragleave", onDragLeave);
2241
+ form.addEventListener("drop", onDrop);
2242
+ return () => {
2243
+ form.removeEventListener("dragover", onDragOver);
2244
+ form.removeEventListener("dragenter", onDragEnter);
2245
+ form.removeEventListener("dragleave", onDragLeave);
2246
+ form.removeEventListener("drop", onDrop);
2247
+ };
2248
+ }, [add, globalDrop]);
2249
+ import_react9.useEffect(() => {
2250
+ if (!globalDrop)
2251
+ return;
2252
+ const target = dragListenerTarget?.current ?? document;
2253
+ const onDragOver = (e) => {
2254
+ if (e.dataTransfer?.types?.includes("Files"))
2255
+ e.preventDefault();
2256
+ };
2257
+ const onDragEnter = (e) => {
2258
+ if (e.dataTransfer?.types?.includes("Files")) {
2259
+ e.preventDefault();
2260
+ dragCounter.current++;
2261
+ if (dragCounter.current === 1)
2262
+ setIsDraggingOver(true);
2263
+ }
2264
+ };
2265
+ const onDragLeave = (_e) => {
2266
+ dragCounter.current--;
2267
+ if (dragCounter.current === 0)
2268
+ setIsDraggingOver(false);
2269
+ };
2270
+ const onDrop = (e) => {
2271
+ if (e.dataTransfer?.types?.includes("Files"))
2272
+ e.preventDefault();
2273
+ dragCounter.current = 0;
2274
+ setIsDraggingOver(false);
2275
+ if (e.dataTransfer?.files && e.dataTransfer.files.length > 0)
2276
+ add(e.dataTransfer.files);
2277
+ };
2278
+ target.addEventListener("dragover", onDragOver);
2279
+ target.addEventListener("dragenter", onDragEnter);
2280
+ target.addEventListener("dragleave", onDragLeave);
2281
+ target.addEventListener("drop", onDrop);
2282
+ return () => {
2283
+ target.removeEventListener("dragover", onDragOver);
2284
+ target.removeEventListener("dragenter", onDragEnter);
2285
+ target.removeEventListener("dragleave", onDragLeave);
2286
+ target.removeEventListener("drop", onDrop);
2287
+ };
2288
+ }, [add, globalDrop, dragListenerTarget]);
2289
+ const filesRef = import_react9.useRef(files);
2290
+ filesRef.current = files;
2291
+ import_react9.useEffect(() => () => {
2292
+ if (!usingProvider) {
2293
+ for (const f of filesRef.current)
2294
+ if (f.url)
2295
+ URL.revokeObjectURL(f.url);
2296
+ }
2297
+ }, [usingProvider]);
2298
+ const handleChange = (event) => {
2299
+ if (event.currentTarget.files)
2300
+ add(event.currentTarget.files);
2301
+ };
2302
+ const convertBlobUrlToDataUrl = async (url) => {
2303
+ const response = await fetch(url);
2304
+ const blob = await response.blob();
2305
+ return new Promise((resolve, reject) => {
2306
+ const reader = new FileReader;
2307
+ reader.onloadend = () => resolve(reader.result);
2308
+ reader.onerror = reject;
2309
+ reader.readAsDataURL(blob);
2310
+ });
2311
+ };
2312
+ const ctx = import_react9.useMemo(() => ({
2313
+ files: files.map((item) => ({ ...item, id: item.id })),
2314
+ add,
2315
+ remove,
2316
+ clear,
2317
+ openFileDialog,
2318
+ fileInputRef: inputRef
2319
+ }), [files, add, remove, clear, openFileDialog]);
2320
+ const handleSubmit = (event) => {
2321
+ event.preventDefault();
2322
+ const form = event.currentTarget;
2323
+ const text = usingProvider ? controller.textInput.value : (() => {
2324
+ const formData = new FormData(form);
2325
+ return formData.get("message") || "";
2326
+ })();
2327
+ if (!usingProvider)
2328
+ form.reset();
2329
+ Promise.all(files.map(async ({ id, ...item }) => {
2330
+ if (item.url && item.url.startsWith("blob:")) {
2331
+ return { ...item, url: await convertBlobUrlToDataUrl(item.url) };
2332
+ }
2333
+ return item;
2334
+ })).then((convertedFiles) => {
2335
+ try {
2336
+ const result = onSubmit({ text, files: convertedFiles }, event);
2337
+ if (result instanceof Promise) {
2338
+ result.then(() => {
2339
+ clear();
2340
+ if (usingProvider)
2341
+ controller.textInput.clear();
2342
+ }).catch(() => {});
2343
+ } else {
2344
+ clear();
2345
+ if (usingProvider)
2346
+ controller.textInput.clear();
2347
+ }
2348
+ } catch {}
2349
+ });
2350
+ };
2351
+ const dropZoneValue = import_react9.useMemo(() => ({ isDraggingOver }), [isDraggingOver]);
2352
+ const inner = /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(DropZoneContext.Provider, {
2353
+ value: dropZoneValue,
2354
+ children: /* @__PURE__ */ jsx_dev_runtime25.jsxDEV("form", {
2355
+ className: cn("relative w-full", className),
2356
+ onSubmit: handleSubmit,
2357
+ ref: formRef,
2358
+ ...props,
2359
+ children: [
2360
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV("input", {
2361
+ accept,
2362
+ "aria-label": "Upload files",
2363
+ className: "hidden",
2364
+ multiple,
2365
+ onChange: handleChange,
2366
+ ref: inputRef,
2367
+ title: "Upload files",
2368
+ type: "file"
2369
+ }, undefined, false, undefined, this),
2370
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(InputGroup, {
2371
+ children
2372
+ }, undefined, false, undefined, this)
2373
+ ]
2374
+ }, undefined, true, undefined, this)
2375
+ }, undefined, false, undefined, this);
2376
+ return usingProvider ? inner : /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(LocalAttachmentsContext.Provider, {
2377
+ value: ctx,
2378
+ children: inner
2379
+ }, undefined, false, undefined, this);
2380
+ };
2381
+ // src/ui/components/prompt-input/textarea.tsx
2382
+ var import_react10 = require("react");
2383
+ var jsx_dev_runtime26 = require("react/jsx-dev-runtime");
2384
+ var PromptInputTextarea = ({
2385
+ onChange,
2386
+ className,
2387
+ placeholder = "What would you like to know?",
2388
+ ...props
2389
+ }) => {
2390
+ const controller = useOptionalPromptInputController();
2391
+ const attachments = usePromptInputAttachments();
2392
+ const [isComposing, setIsComposing] = import_react10.useState(false);
2393
+ const handleKeyDown = (e) => {
2394
+ if (e.key === "Enter") {
2395
+ if (isComposing || e.nativeEvent.isComposing)
2396
+ return;
2397
+ if (e.shiftKey)
2398
+ return;
2399
+ e.preventDefault();
2400
+ e.currentTarget.form?.requestSubmit();
2401
+ }
2402
+ if (e.key === "Backspace" && e.currentTarget.value === "" && attachments.files.length > 0) {
2403
+ e.preventDefault();
2404
+ const lastAttachment = attachments.files.at(-1);
2405
+ if (lastAttachment)
2406
+ attachments.remove(lastAttachment.id);
2407
+ }
2408
+ };
2409
+ const handlePaste = (event) => {
2410
+ const items = event.clipboardData?.items;
2411
+ if (!items)
2412
+ return;
2413
+ const files = [];
2414
+ for (const item of items) {
2415
+ if (item.kind === "file") {
2416
+ const file = item.getAsFile();
2417
+ if (file)
2418
+ files.push(file);
2419
+ }
2420
+ }
2421
+ if (files.length > 0) {
2422
+ event.preventDefault();
2423
+ attachments.add(files);
2424
+ }
2425
+ };
2426
+ const controlledProps = controller ? {
2427
+ value: controller.textInput.value,
2428
+ onChange: (e) => {
2429
+ controller.textInput.setInput(e.currentTarget.value);
2430
+ onChange?.(e);
2431
+ }
2432
+ } : { onChange };
2433
+ return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(InputGroupTextarea, {
2434
+ className: cn("[field-sizing:content] max-h-48 text-base", className),
2435
+ rows: 1,
2436
+ name: "message",
2437
+ onCompositionEnd: () => setIsComposing(false),
2438
+ onCompositionStart: () => setIsComposing(true),
2439
+ onKeyDown: handleKeyDown,
2440
+ onPaste: handlePaste,
2441
+ placeholder,
2442
+ ...props,
2443
+ ...controlledProps
2444
+ }, undefined, false, undefined, this);
2445
+ };
2446
+ // src/ui/components/prompt-input/attachments.tsx
2447
+ var import_lucide_react15 = require("lucide-react");
2448
+ var import_react11 = require("react");
2449
+ var jsx_dev_runtime27 = require("react/jsx-dev-runtime");
2450
+ function PromptInputAttachment({ data, className, ...props }) {
2451
+ const attachments = usePromptInputAttachments();
2452
+ const filename = data.filename || "";
2453
+ const isImage = data.mediaType?.startsWith("image/") && data.url;
2454
+ const isAudio = data.mediaType?.startsWith("audio/");
2455
+ const attachmentLabel = filename || (isImage ? "Image" : isAudio ? "Audio" : "Attachment");
2456
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(HoverCard, {
2457
+ openDelay: 0,
2458
+ closeDelay: 0,
2459
+ children: [
2460
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(HoverCardTrigger, {
2461
+ asChild: true,
2462
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2463
+ className: cn("group relative flex h-8 cursor-default 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", className),
2464
+ ...props,
2465
+ children: [
2466
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2467
+ className: "relative size-5 shrink-0",
2468
+ children: [
2469
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2470
+ className: "absolute inset-0 flex size-5 items-center justify-center overflow-hidden rounded bg-background transition-opacity group-hover:opacity-0",
2471
+ children: isImage ? /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("img", {
2472
+ alt: filename || "attachment",
2473
+ className: "size-5 object-cover",
2474
+ height: 20,
2475
+ src: data.url,
2476
+ width: 20
2477
+ }, undefined, false, undefined, this) : isAudio ? /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2478
+ className: "flex size-5 items-center justify-center text-muted-foreground",
2479
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(import_lucide_react15.MicIcon, {
2480
+ className: "size-3"
2481
+ }, undefined, false, undefined, this)
2482
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2483
+ className: "flex size-5 items-center justify-center text-muted-foreground",
2484
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(import_lucide_react15.PaperclipIcon, {
2485
+ className: "size-3"
2486
+ }, undefined, false, undefined, this)
2487
+ }, undefined, false, undefined, this)
2488
+ }, undefined, false, undefined, this),
2489
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Button, {
2490
+ "aria-label": "Remove attachment",
2491
+ 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",
2492
+ onClick: (e) => {
2493
+ e.stopPropagation();
2494
+ attachments.remove(data.id);
2495
+ },
2496
+ type: "button",
2497
+ variant: "ghost",
2498
+ children: [
2499
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(import_lucide_react15.XIcon, {}, undefined, false, undefined, this),
2500
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("span", {
2501
+ className: "sr-only",
2502
+ children: "Remove"
2503
+ }, undefined, false, undefined, this)
2504
+ ]
2505
+ }, undefined, true, undefined, this)
2506
+ ]
2507
+ }, undefined, true, undefined, this),
2508
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("span", {
2509
+ className: "flex-1 truncate",
2510
+ children: attachmentLabel
2511
+ }, undefined, false, undefined, this)
2512
+ ]
2513
+ }, data.id, true, undefined, this)
2514
+ }, undefined, false, undefined, this),
2515
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(HoverCardContent, {
2516
+ align: "start",
2517
+ className: "w-auto p-2",
2518
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2519
+ className: "w-auto space-y-3",
2520
+ children: [
2521
+ isImage && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2522
+ className: "flex max-h-96 w-96 items-center justify-center overflow-hidden rounded-md border",
2523
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("img", {
2524
+ alt: filename || "attachment preview",
2525
+ className: "max-h-full max-w-full object-contain",
2526
+ height: 384,
2527
+ src: data.url,
2528
+ width: 448
2529
+ }, undefined, false, undefined, this)
2530
+ }, undefined, false, undefined, this),
2531
+ isAudio && data.url && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2532
+ className: "w-64",
2533
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("audio", {
2534
+ src: data.url,
2535
+ controls: true,
2536
+ className: "w-full"
2537
+ }, undefined, false, undefined, this)
2538
+ }, undefined, false, undefined, this),
2539
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2540
+ className: "flex items-center gap-2.5",
2541
+ children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("div", {
2542
+ className: "min-w-0 flex-1 space-y-1 px-0.5",
2543
+ children: [
2544
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("h4", {
2545
+ className: "truncate font-semibold text-sm leading-none",
2546
+ children: filename || (isImage ? "Image" : "Attachment")
2547
+ }, undefined, false, undefined, this),
2548
+ data.mediaType && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV("p", {
2549
+ className: "truncate font-mono text-muted-foreground text-xs",
2550
+ children: data.mediaType
2551
+ }, undefined, false, undefined, this)
2552
+ ]
2553
+ }, undefined, true, undefined, this)
2554
+ }, undefined, false, undefined, this)
2555
+ ]
2556
+ }, undefined, true, undefined, this)
2557
+ }, undefined, false, undefined, this)
2558
+ ]
2559
+ }, undefined, true, undefined, this);
2560
+ }
2561
+ function PromptInputAttachments({ children }) {
2562
+ const attachments = usePromptInputAttachments();
2563
+ if (!attachments.files.length)
2564
+ return null;
2565
+ return attachments.files.map((file) => /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(import_react11.Fragment, {
2566
+ children: children(file)
2567
+ }, file.id, false, undefined, this));
2568
+ }
2569
+ var PromptInputActionAddAttachments = ({
2570
+ label = "Add photos or files",
2571
+ ...props
2572
+ }) => {
2573
+ const attachments = usePromptInputAttachments();
2574
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(DropdownMenuItem, {
2575
+ ...props,
2576
+ onSelect: () => {
2577
+ attachments.openFileDialog();
2578
+ },
2579
+ children: [
2580
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(import_lucide_react15.ImageIcon, {
2581
+ className: "mr-2 size-4"
2582
+ }, undefined, false, undefined, this),
2583
+ " ",
2584
+ label
2585
+ ]
2586
+ }, undefined, true, undefined, this);
2587
+ };
2588
+ // src/ui/components/prompt-input/footer.tsx
2589
+ var jsx_dev_runtime28 = require("react/jsx-dev-runtime");
2590
+ var PromptInputBody = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime28.jsxDEV("div", {
2591
+ className: cn("contents", className),
2592
+ ...props
2593
+ }, undefined, false, undefined, this);
2594
+ var PromptInputHeader = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(InputGroupAddon, {
2595
+ align: "block-start",
2596
+ className: cn("flex-wrap gap-1 empty:hidden empty:p-0", className),
2597
+ ...props
2598
+ }, undefined, false, undefined, this);
2599
+ var PromptInputFooter = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(InputGroupAddon, {
2600
+ align: "block-end",
2601
+ className: cn("justify-between gap-1", className),
2602
+ ...props
2603
+ }, undefined, false, undefined, this);
2604
+ var PromptInputTools = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime28.jsxDEV("div", {
2605
+ className: cn("flex items-center gap-1", className),
2606
+ ...props
2607
+ }, undefined, false, undefined, this);
2608
+ // src/ui/components/prompt-input/buttons.tsx
2609
+ var import_lucide_react16 = require("lucide-react");
2610
+ var import_react12 = require("react");
2611
+ var jsx_dev_runtime29 = require("react/jsx-dev-runtime");
2612
+ var PromptInputButton = ({
2613
+ variant = "ghost",
2614
+ className,
2615
+ size,
2616
+ ...props
2617
+ }) => {
2618
+ const newSize = size ?? (import_react12.Children.count(props.children) > 1 ? "sm" : "icon-sm");
2619
+ return /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(InputGroupButton, {
2620
+ className: cn(className),
2621
+ size: newSize,
2622
+ type: "button",
2623
+ variant,
2624
+ ...props
2625
+ }, undefined, false, undefined, this);
2626
+ };
2627
+ var PromptInputSubmit = ({
2628
+ className,
2629
+ variant = "default",
2630
+ size = "icon-sm",
2631
+ status,
2632
+ children,
2633
+ ...props
2634
+ }) => {
2635
+ let Icon2 = /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(import_lucide_react16.SendIcon, {
2636
+ className: "size-4"
2637
+ }, undefined, false, undefined, this);
2638
+ if (status === "submitted") {
2639
+ Icon2 = /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(import_lucide_react16.Loader2Icon, {
2640
+ className: "size-4 animate-spin"
2641
+ }, undefined, false, undefined, this);
2642
+ } else if (status === "streaming") {
2643
+ Icon2 = /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(import_lucide_react16.SquareIcon, {
2644
+ className: "size-4"
2645
+ }, undefined, false, undefined, this);
2646
+ } else if (status === "error") {
2647
+ Icon2 = /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(import_lucide_react16.XIcon, {
2648
+ className: "size-4"
2649
+ }, undefined, false, undefined, this);
2650
+ }
2651
+ return /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(InputGroupButton, {
2652
+ "aria-label": "Submit",
2653
+ className: cn(className),
2654
+ size,
2655
+ type: "submit",
2656
+ variant,
2657
+ ...props,
2658
+ children: children ?? Icon2
2659
+ }, undefined, false, undefined, this);
2660
+ };
2661
+ var PromptInputActionMenu = (props) => /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(DropdownMenu, {
2662
+ ...props
2663
+ }, undefined, false, undefined, this);
2664
+ var PromptInputActionMenuTrigger = ({
2665
+ className,
2666
+ children,
2667
+ ...props
2668
+ }) => /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(DropdownMenuTrigger, {
2669
+ asChild: true,
2670
+ children: /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(PromptInputButton, {
2671
+ className,
2672
+ ...props,
2673
+ children: children ?? /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(import_lucide_react16.PlusIcon, {
2674
+ className: "size-4"
2675
+ }, undefined, false, undefined, this)
2676
+ }, undefined, false, undefined, this)
2677
+ }, undefined, false, undefined, this);
2678
+ var PromptInputActionMenuContent = ({
2679
+ className,
2680
+ ...props
2681
+ }) => /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(DropdownMenuContent, {
2682
+ align: "start",
2683
+ className: cn(className),
2684
+ ...props
2685
+ }, undefined, false, undefined, this);
2686
+ var PromptInputActionMenuItem = ({
2687
+ className,
2688
+ ...props
2689
+ }) => /* @__PURE__ */ jsx_dev_runtime29.jsxDEV(DropdownMenuItem, {
2690
+ className: cn(className),
2691
+ ...props
2692
+ }, undefined, false, undefined, this);
2693
+ // src/ui/components/prompt-input/drop-zone.tsx
2694
+ var import_lucide_react17 = require("lucide-react");
2695
+ var import_react_dom = require("react-dom");
2696
+ var jsx_dev_runtime30 = require("react/jsx-dev-runtime");
2697
+ var PromptInputDropZone = ({
2698
+ label = "Drop files here",
2699
+ className,
2700
+ container,
2701
+ ...props
2702
+ }) => {
2703
+ const { isDraggingOver } = usePromptInputDropZone();
2704
+ const overlay = /* @__PURE__ */ jsx_dev_runtime30.jsxDEV("div", {
2705
+ className: cn("absolute inset-0 z-10 pointer-events-none", "flex flex-col items-center justify-center gap-2", "border-2 border-dashed border-primary rounded-xl", "bg-primary/5 backdrop-blur-[2px] text-primary", "transition-opacity duration-200", isDraggingOver ? "opacity-100" : "opacity-0", className),
2706
+ "aria-hidden": !isDraggingOver,
2707
+ ...props,
2708
+ children: [
2709
+ /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(import_lucide_react17.Upload, {
2710
+ className: "size-14"
2711
+ }, undefined, false, undefined, this),
2712
+ /* @__PURE__ */ jsx_dev_runtime30.jsxDEV("span", {
2713
+ className: "text-sm font-medium mt-2",
2714
+ children: label
2715
+ }, undefined, false, undefined, this)
2716
+ ]
2717
+ }, undefined, true, undefined, this);
2718
+ if (container?.current) {
2719
+ return import_react_dom.createPortal(overlay, container.current);
2720
+ }
2721
+ return overlay;
2722
+ };
2723
+ // src/ui/components/prompt-input/speech.tsx
2724
+ var import_lucide_react18 = require("lucide-react");
2725
+ var import_react13 = require("react");
2726
+ var jsx_dev_runtime31 = require("react/jsx-dev-runtime");
2727
+ var PromptInputSpeechButton = ({
2728
+ className,
2729
+ onTranscriptionChange,
2730
+ lang = "en-US",
2731
+ ...props
2732
+ }) => {
2733
+ const [isListening, setIsListening] = import_react13.useState(false);
2734
+ const [recognition, setRecognition] = import_react13.useState(null);
2735
+ const recognitionRef = import_react13.useRef(null);
2736
+ const onTranscriptionChangeRef = import_react13.useRef(onTranscriptionChange);
2737
+ onTranscriptionChangeRef.current = onTranscriptionChange;
2738
+ const controller = useOptionalPromptInputController();
2739
+ import_react13.useEffect(() => {
2740
+ if (typeof window !== "undefined" && (("SpeechRecognition" in window) || ("webkitSpeechRecognition" in window))) {
2741
+ const SpeechRecognitionCtor = window.SpeechRecognition || window.webkitSpeechRecognition;
2742
+ const speechRecognition = new SpeechRecognitionCtor;
2743
+ speechRecognition.continuous = true;
2744
+ speechRecognition.interimResults = true;
2745
+ speechRecognition.lang = lang;
2746
+ speechRecognition.onstart = () => setIsListening(true);
2747
+ speechRecognition.onend = () => setIsListening(false);
2748
+ speechRecognition.onresult = (event) => {
2749
+ let finalTranscript = "";
2750
+ const results = Array.from(event.results);
2751
+ for (const result of results) {
2752
+ if (result.isFinal)
2753
+ finalTranscript += result[0]?.transcript ?? "";
2754
+ }
2755
+ if (finalTranscript) {
2756
+ if (controller) {
2757
+ const current = controller.textInput.value;
2758
+ const newValue = current + (current ? " " : "") + finalTranscript;
2759
+ controller.textInput.setInput(newValue);
2760
+ }
2761
+ onTranscriptionChangeRef.current?.(finalTranscript);
2762
+ }
2763
+ };
2764
+ speechRecognition.onerror = (event) => {
2765
+ console.error("Speech recognition error:", event.error);
2766
+ setIsListening(false);
2767
+ };
2768
+ recognitionRef.current = speechRecognition;
2769
+ setRecognition(speechRecognition);
2770
+ }
2771
+ return () => {
2772
+ if (recognitionRef.current)
2773
+ recognitionRef.current.stop();
2774
+ };
2775
+ }, [lang]);
2776
+ const toggleListening = import_react13.useCallback(() => {
2777
+ if (!recognition)
2778
+ return;
2779
+ if (isListening)
2780
+ recognition.stop();
2781
+ else
2782
+ recognition.start();
2783
+ }, [recognition, isListening]);
2784
+ return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(PromptInputButton, {
2785
+ className: cn("relative transition-all duration-200", isListening && "animate-pulse bg-accent text-accent-foreground", className),
2786
+ disabled: !recognition,
2787
+ onClick: toggleListening,
2788
+ ...props,
2789
+ children: /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(import_lucide_react18.MicIcon, {
2790
+ className: "size-4"
2791
+ }, undefined, false, undefined, this)
2792
+ }, undefined, false, undefined, this);
2793
+ };
2794
+ // src/ui/components/prompt-input/model-select.tsx
2795
+ var jsx_dev_runtime32 = require("react/jsx-dev-runtime");
2796
+ var PromptInputModelSelect = (props) => /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Select, {
2797
+ ...props
2798
+ }, undefined, false, undefined, this);
2799
+ var PromptInputModelSelectTrigger = ({
2800
+ className,
2801
+ ...props
2802
+ }) => /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(SelectTrigger, {
2803
+ className: cn("border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors", 'hover:bg-accent hover:text-foreground [&[aria-expanded="true"]]:bg-accent [&[aria-expanded="true"]]:text-foreground', className),
2804
+ ...props
2805
+ }, undefined, false, undefined, this);
2806
+ var PromptInputModelSelectContent = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(SelectContent, {
2807
+ className: cn(className),
2808
+ ...props
2809
+ }, undefined, false, undefined, this);
2810
+ var PromptInputModelSelectItem = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(SelectItem, {
2811
+ className: cn(className),
2812
+ ...props
2813
+ }, undefined, false, undefined, this);
2814
+ var PromptInputModelSelectValue = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(SelectValue, {
2815
+ className: cn(className),
2816
+ ...props
2817
+ }, undefined, false, undefined, this);
2818
+ // src/ui/components/prompt-input/tabs.tsx
2819
+ var jsx_dev_runtime33 = require("react/jsx-dev-runtime");
2820
+ var PromptInputTabsList = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime33.jsxDEV("div", {
2821
+ className: cn(className),
2822
+ ...props
2823
+ }, undefined, false, undefined, this);
2824
+ var PromptInputTab = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime33.jsxDEV("div", {
2825
+ className: cn(className),
2826
+ ...props
2827
+ }, undefined, false, undefined, this);
2828
+ var PromptInputTabLabel = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime33.jsxDEV("h3", {
2829
+ className: cn("mb-2 px-3 font-medium text-muted-foreground text-xs", className),
2830
+ ...props
2831
+ }, undefined, false, undefined, this);
2832
+ var PromptInputTabBody = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime33.jsxDEV("div", {
2833
+ className: cn("space-y-1", className),
2834
+ ...props
2835
+ }, undefined, false, undefined, this);
2836
+ var PromptInputTabItem = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime33.jsxDEV("div", {
2837
+ className: cn("flex items-center gap-2 px-3 py-2 text-xs hover:bg-accent", className),
2838
+ ...props
2839
+ }, undefined, false, undefined, this);
2840
+ // src/ui/components/prompt-input/command.tsx
2841
+ var jsx_dev_runtime34 = require("react/jsx-dev-runtime");
2842
+ var PromptInputCommand = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(Command, {
2843
+ className: cn(className),
2844
+ ...props
2845
+ }, undefined, false, undefined, this);
2846
+ var PromptInputCommandInput = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandInput, {
2847
+ className: cn(className),
2848
+ ...props
2849
+ }, undefined, false, undefined, this);
2850
+ var PromptInputCommandList = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandList, {
2851
+ className: cn(className),
2852
+ ...props
2853
+ }, undefined, false, undefined, this);
2854
+ var PromptInputCommandEmpty = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandEmpty, {
2855
+ className: cn(className),
2856
+ ...props
2857
+ }, undefined, false, undefined, this);
2858
+ var PromptInputCommandGroup = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandGroup, {
2859
+ className: cn(className),
2860
+ ...props
2861
+ }, undefined, false, undefined, this);
2862
+ var PromptInputCommandItem = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandItem, {
2863
+ className: cn(className),
2864
+ ...props
2865
+ }, undefined, false, undefined, this);
2866
+ var PromptInputCommandSeparator = ({ className, ...props }) => /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(CommandSeparator, {
2867
+ className: cn(className),
2868
+ ...props
2869
+ }, undefined, false, undefined, this);
2870
+ // src/ui/composed/agno-chat/agno-chat.tsx
2871
+ var import_react15 = require("react");
2872
+ var import_agno_react = require("@rodrigocoliveira/agno-react");
2873
+
2874
+ // src/ui/composed/agno-chat/context.ts
2875
+ var import_react14 = require("react");
2876
+ var AgnoChatContext = import_react14.createContext(null);
2877
+ function useAgnoChatContext() {
2878
+ const ctx = import_react14.useContext(AgnoChatContext);
2879
+ if (!ctx) {
2880
+ throw new Error("useAgnoChatContext must be used within an <AgnoChat> provider. " + "Wrap your component tree with <AgnoChat>.");
2881
+ }
2882
+ return ctx;
2883
+ }
2884
+
2885
+ // src/ui/composed/agno-chat/agno-chat.tsx
2886
+ var jsx_dev_runtime35 = require("react/jsx-dev-runtime");
2887
+ function AgnoChatRoot({
2888
+ children,
2889
+ toolHandlers = {},
2890
+ autoExecuteTools = true,
2891
+ className,
2892
+ ...divProps
2893
+ }) {
2894
+ const chat = import_agno_react.useAgnoChat();
2895
+ const toolExec = import_agno_react.useAgnoToolExecution(toolHandlers, autoExecuteTools);
2896
+ const containerRef = import_react15.useRef(null);
2897
+ const sendRef = import_react15.useRef(chat.sendMessage);
2898
+ sendRef.current = chat.sendMessage;
2899
+ const handleSend = import_react15.useCallback(async (message) => {
2900
+ try {
2901
+ await sendRef.current(message);
2902
+ } catch {}
2903
+ }, []);
2904
+ const {
2905
+ messages,
2906
+ sendMessage,
2907
+ clearMessages,
2908
+ cancelRun,
2909
+ isStreaming,
2910
+ isRefreshing,
2911
+ isCancelling,
2912
+ currentRunId,
2913
+ error,
2914
+ state
2915
+ } = chat;
2916
+ const {
2917
+ isPaused,
2918
+ isExecuting,
2919
+ pendingTools,
2920
+ executeAndContinue,
2921
+ executeTools,
2922
+ continueWithResults,
2923
+ executionError
2924
+ } = toolExec;
2925
+ const contextValue = import_react15.useMemo(() => ({
2926
+ messages,
2927
+ sendMessage,
2928
+ clearMessages,
2929
+ cancelRun,
2930
+ isStreaming,
2931
+ isRefreshing,
2932
+ isCancelling: isCancelling ?? false,
2933
+ currentRunId,
2934
+ error,
2935
+ state,
2936
+ isPaused,
2937
+ isExecuting,
2938
+ pendingTools,
2939
+ executeAndContinue,
2940
+ executeTools,
2941
+ continueWithResults,
2942
+ executionError,
2943
+ handleSend,
2944
+ inputDisabled: isStreaming || isPaused,
2945
+ dropZoneContainerRef: containerRef
2946
+ }), [
2947
+ messages,
2948
+ sendMessage,
2949
+ clearMessages,
2950
+ cancelRun,
2951
+ isStreaming,
2952
+ isRefreshing,
2953
+ isCancelling,
2954
+ currentRunId,
2955
+ error,
2956
+ state,
2957
+ isPaused,
2958
+ isExecuting,
2959
+ pendingTools,
2960
+ executeAndContinue,
2961
+ executeTools,
2962
+ continueWithResults,
2963
+ executionError,
2964
+ handleSend
2965
+ ]);
2966
+ return /* @__PURE__ */ jsx_dev_runtime35.jsxDEV(AgnoChatContext.Provider, {
2967
+ value: contextValue,
2968
+ children: /* @__PURE__ */ jsx_dev_runtime35.jsxDEV("div", {
2969
+ ref: containerRef,
2970
+ className: cn("relative h-full flex flex-col", className),
2971
+ ...divProps,
2972
+ children
2973
+ }, undefined, false, undefined, this)
2974
+ }, undefined, false, undefined, this);
2975
+ }
2976
+
2977
+ // src/ui/composed/agno-chat/messages.tsx
2978
+ var import_react17 = require("react");
2979
+
2980
+ // src/ui/composed/AgnoMessageItem.tsx
2981
+ var import_react16 = require("react");
2982
+ var import_agno_react2 = require("@rodrigocoliveira/agno-react");
2983
+ var import_lucide_react19 = require("lucide-react");
2984
+ var jsx_dev_runtime36 = require("react/jsx-dev-runtime");
2985
+ var defaultFormatTimestamp = formatSmartTimestamp;
2986
+ var getToolState = (tool) => {
2987
+ return tool.tool_call_error ? "output-error" : "output-available";
2988
+ };
2989
+ function AgnoMessageItem({
2990
+ message,
2991
+ className,
2992
+ classNames,
2993
+ renderContent,
2994
+ renderToolCall,
2995
+ renderMedia,
2996
+ renderActions,
2997
+ userAvatar,
2998
+ assistantAvatar,
2999
+ showReasoning = true,
3000
+ showReferences = true,
3001
+ showTimestamp = true,
3002
+ showGenerativeUI = true,
3003
+ showToolCalls = true,
3004
+ showFilePreview = true,
3005
+ showImageLightbox = true,
3006
+ formatTimestamp
3007
+ }) {
3008
+ const isUser = message.role === "user";
3009
+ const hasError = message.streamingError;
3010
+ const toolsWithUI = message.tool_calls?.filter((tool) => tool.ui_component) || [];
3011
+ const [preview, setPreview] = import_react16.useState(null);
3012
+ const isCustomTimestamp = !!formatTimestamp;
3013
+ const resolvedFormatTimestamp = formatTimestamp ?? defaultFormatTimestamp;
3014
+ const openImageLightbox = (images, index) => {
3015
+ if (!showImageLightbox)
3016
+ return;
3017
+ setPreview({ type: "image", images, initialIndex: index });
3018
+ };
3019
+ const openFilePreview = (file) => {
3020
+ if (!showFilePreview)
3021
+ return;
3022
+ setPreview({ type: "file", file });
3023
+ };
3024
+ const closePreview = () => setPreview(null);
3025
+ return /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3026
+ className: cn("py-5 first:pt-2", isUser ? "flex justify-end" : "", classNames?.root, className),
3027
+ children: [
3028
+ isUser ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3029
+ className: "flex items-start gap-2.5 max-w-[80%] flex-row-reverse",
3030
+ children: [
3031
+ userAvatar,
3032
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3033
+ className: "space-y-1.5 flex flex-col items-end min-w-0",
3034
+ children: [
3035
+ (message.images && message.images.length > 0 || message.audio && message.audio.length > 0 || message.files && message.files.length > 0) && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3036
+ className: "flex flex-wrap gap-2 justify-end",
3037
+ children: [
3038
+ message.images?.map((img, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(FilePreviewCard, {
3039
+ file: { name: img.revised_prompt || `Image ${idx + 1}`, type: "image/png", url: img.url },
3040
+ onClick: showImageLightbox ? () => openImageLightbox(message.images.map((i) => ({ url: i.url, alt: i.revised_prompt })), idx) : undefined
3041
+ }, `img-${idx}`, false, undefined, this)),
3042
+ message.audio?.map((audio, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3043
+ className: "flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-2.5 py-1.5 text-xs text-foreground self-end",
3044
+ children: [
3045
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Music, {
3046
+ className: "h-3.5 w-3.5 text-muted-foreground"
3047
+ }, undefined, false, undefined, this),
3048
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3049
+ className: "truncate max-w-[150px]",
3050
+ children: audio.id || `Audio ${idx + 1}`
3051
+ }, undefined, false, undefined, this)
3052
+ ]
3053
+ }, `audio-${idx}`, true, undefined, this)),
3054
+ message.files?.map((file, idx) => showFilePreview ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(FilePreviewCard, {
3055
+ file: { name: file.name, type: file.type, url: file.url, size: file.size },
3056
+ onClick: () => openFilePreview({ name: file.name, type: file.type, url: file.url, size: file.size })
3057
+ }, `file-${idx}`, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3058
+ className: "flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-2.5 py-1.5 text-xs text-foreground self-end",
3059
+ children: [
3060
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.FileIcon, {
3061
+ className: "h-3.5 w-3.5 text-muted-foreground"
3062
+ }, undefined, false, undefined, this),
3063
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3064
+ className: "truncate max-w-[150px]",
3065
+ children: file.name
3066
+ }, undefined, false, undefined, this)
3067
+ ]
3068
+ }, `file-${idx}`, true, undefined, this))
3069
+ ]
3070
+ }, undefined, true, undefined, this),
3071
+ message.content && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3072
+ className: cn("rounded-2xl rounded-br-md px-4 py-2.5", classNames?.userBubble ?? "bg-primary text-primary-foreground", hasError && "opacity-70"),
3073
+ children: /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("p", {
3074
+ className: "text-sm whitespace-pre-wrap",
3075
+ children: message.content
3076
+ }, undefined, false, undefined, this)
3077
+ }, undefined, false, undefined, this),
3078
+ showTimestamp && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3079
+ className: "flex items-center justify-end gap-1.5 px-1",
3080
+ children: [
3081
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(SmartTimestamp, {
3082
+ date: new Date(message.created_at * 1000),
3083
+ formatShort: isCustomTimestamp ? resolvedFormatTimestamp : undefined,
3084
+ className: "text-[11px] text-muted-foreground"
3085
+ }, undefined, false, undefined, this),
3086
+ hasError && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.AlertCircle, {
3087
+ className: "h-3 w-3 text-destructive"
3088
+ }, undefined, false, undefined, this)
3089
+ ]
3090
+ }, undefined, true, undefined, this)
3091
+ ]
3092
+ }, undefined, true, undefined, this)
3093
+ ]
3094
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3095
+ className: "flex items-start gap-3",
3096
+ children: [
3097
+ assistantAvatar,
3098
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3099
+ className: cn("flex-1 min-w-0 space-y-3", classNames?.assistantContainer),
3100
+ children: [
3101
+ renderContent ? renderContent(message) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(jsx_dev_runtime36.Fragment, {
3102
+ children: [
3103
+ showReasoning && message.extra_data?.reasoning_steps && message.extra_data.reasoning_steps.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3104
+ className: cn("space-y-2 pt-1", classNames?.reasoning),
3105
+ children: [
3106
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3107
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3108
+ children: [
3109
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Lightbulb, {
3110
+ className: "h-3.5 w-3.5"
3111
+ }, undefined, false, undefined, this),
3112
+ "Reasoning (",
3113
+ message.extra_data.reasoning_steps.length,
3114
+ " steps)"
3115
+ ]
3116
+ }, undefined, true, undefined, this),
3117
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(Accordion, {
3118
+ type: "multiple",
3119
+ className: "w-full",
3120
+ children: message.extra_data.reasoning_steps.map((step, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(AccordionItem, {
3121
+ value: `reasoning-${idx}`,
3122
+ className: "border-muted",
3123
+ children: [
3124
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(AccordionTrigger, {
3125
+ className: "text-xs py-1.5 hover:no-underline",
3126
+ children: step.title || `Step ${idx + 1}`
3127
+ }, undefined, false, undefined, this),
3128
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(AccordionContent, {
3129
+ className: "space-y-1.5 text-xs text-muted-foreground",
3130
+ children: [
3131
+ step.action && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3132
+ children: [
3133
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3134
+ className: "font-medium text-foreground",
3135
+ children: "Action:"
3136
+ }, undefined, false, undefined, this),
3137
+ " ",
3138
+ step.action
3139
+ ]
3140
+ }, undefined, true, undefined, this),
3141
+ step.reasoning && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3142
+ children: [
3143
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3144
+ className: "font-medium text-foreground",
3145
+ children: "Reasoning:"
3146
+ }, undefined, false, undefined, this),
3147
+ " ",
3148
+ step.reasoning
3149
+ ]
3150
+ }, undefined, true, undefined, this),
3151
+ step.result && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3152
+ children: [
3153
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3154
+ className: "font-medium text-foreground",
3155
+ children: "Result:"
3156
+ }, undefined, false, undefined, this),
3157
+ " ",
3158
+ step.result
3159
+ ]
3160
+ }, undefined, true, undefined, this),
3161
+ step.confidence !== undefined && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3162
+ children: [
3163
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3164
+ className: "font-medium text-foreground",
3165
+ children: "Confidence:"
3166
+ }, undefined, false, undefined, this),
3167
+ " ",
3168
+ (step.confidence * 100).toFixed(1),
3169
+ "%"
3170
+ ]
3171
+ }, undefined, true, undefined, this)
3172
+ ]
3173
+ }, undefined, true, undefined, this)
3174
+ ]
3175
+ }, idx, true, undefined, this))
3176
+ }, undefined, false, undefined, this)
3177
+ ]
3178
+ }, undefined, true, undefined, this),
3179
+ message.content && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3180
+ className: "prose prose-sm dark:prose-invert max-w-none prose-p:leading-relaxed prose-pre:bg-muted prose-pre:border prose-pre:border-border",
3181
+ children: /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(Response, {
3182
+ children: message.content
3183
+ }, undefined, false, undefined, this)
3184
+ }, undefined, false, undefined, this),
3185
+ showGenerativeUI && toolsWithUI.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3186
+ className: "space-y-3",
3187
+ children: toolsWithUI.map((tool) => {
3188
+ const uiComponent = tool.ui_component;
3189
+ return /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3190
+ children: uiComponent.layout === "artifact" ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(Artifact, {
3191
+ children: /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_agno_react2.GenerativeUIRenderer, {
3192
+ spec: uiComponent,
3193
+ className: "w-full p-2"
3194
+ }, undefined, false, undefined, this)
3195
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_agno_react2.GenerativeUIRenderer, {
3196
+ spec: uiComponent,
3197
+ className: "w-full"
3198
+ }, undefined, false, undefined, this)
3199
+ }, tool.tool_call_id, false, undefined, this);
3200
+ })
3201
+ }, undefined, false, undefined, this),
3202
+ renderMedia ? renderMedia(message) : (() => {
3203
+ const mediaClassName = classNames?.media;
3204
+ return /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(jsx_dev_runtime36.Fragment, {
3205
+ children: [
3206
+ message.images && message.images.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3207
+ className: cn("space-y-2 pt-1", mediaClassName),
3208
+ children: [
3209
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3210
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3211
+ children: [
3212
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Image, {
3213
+ className: "h-3.5 w-3.5"
3214
+ }, undefined, false, undefined, this),
3215
+ "Images (",
3216
+ message.images.length,
3217
+ ")"
3218
+ ]
3219
+ }, undefined, true, undefined, this),
3220
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3221
+ className: "grid grid-cols-2 gap-2",
3222
+ children: message.images.map((img, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3223
+ className: "space-y-1",
3224
+ children: [
3225
+ showImageLightbox ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("button", {
3226
+ type: "button",
3227
+ onClick: () => openImageLightbox(message.images.map((i) => ({ url: i.url, alt: i.revised_prompt })), idx),
3228
+ className: "group relative w-full overflow-hidden rounded-lg border border-border cursor-pointer hover:border-primary/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors",
3229
+ children: /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("img", {
3230
+ src: img.url,
3231
+ alt: img.revised_prompt || "Generated image",
3232
+ className: "w-full rounded-lg"
3233
+ }, undefined, false, undefined, this)
3234
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("img", {
3235
+ src: img.url,
3236
+ alt: img.revised_prompt || "Generated image",
3237
+ className: "w-full rounded-lg border border-border"
3238
+ }, undefined, false, undefined, this),
3239
+ img.revised_prompt && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("p", {
3240
+ className: "text-[11px] text-muted-foreground italic px-0.5",
3241
+ children: img.revised_prompt
3242
+ }, undefined, false, undefined, this)
3243
+ ]
3244
+ }, idx, true, undefined, this))
3245
+ }, undefined, false, undefined, this)
3246
+ ]
3247
+ }, undefined, true, undefined, this),
3248
+ message.videos && message.videos.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3249
+ className: cn("space-y-2 pt-1", mediaClassName),
3250
+ children: [
3251
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3252
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3253
+ children: [
3254
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Video, {
3255
+ className: "h-3.5 w-3.5"
3256
+ }, undefined, false, undefined, this),
3257
+ "Videos (",
3258
+ message.videos.length,
3259
+ ")"
3260
+ ]
3261
+ }, undefined, true, undefined, this),
3262
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3263
+ className: "space-y-2",
3264
+ children: message.videos.map((video, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3265
+ children: video.url ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("video", {
3266
+ src: video.url,
3267
+ controls: true,
3268
+ className: "w-full rounded-lg border border-border"
3269
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3270
+ className: "bg-muted/50 border border-border p-2.5 rounded-lg text-xs text-muted-foreground",
3271
+ children: [
3272
+ "Video ID: ",
3273
+ video.id,
3274
+ " (ETA: ",
3275
+ video.eta,
3276
+ "s)"
3277
+ ]
3278
+ }, undefined, true, undefined, this)
3279
+ }, idx, false, undefined, this))
3280
+ }, undefined, false, undefined, this)
3281
+ ]
3282
+ }, undefined, true, undefined, this),
3283
+ message.audio && message.audio.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3284
+ className: cn("space-y-2 pt-1", mediaClassName),
3285
+ children: [
3286
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3287
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3288
+ children: [
3289
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Music, {
3290
+ className: "h-3.5 w-3.5"
3291
+ }, undefined, false, undefined, this),
3292
+ "Audio (",
3293
+ message.audio.length,
3294
+ ")"
3295
+ ]
3296
+ }, undefined, true, undefined, this),
3297
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3298
+ className: "space-y-2",
3299
+ children: message.audio.map((audio, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3300
+ children: audio.url ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("audio", {
3301
+ src: audio.url,
3302
+ controls: true,
3303
+ className: "w-full"
3304
+ }, undefined, false, undefined, this) : audio.base64_audio ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("audio", {
3305
+ src: `data:${audio.mime_type || "audio/wav"};base64,${audio.base64_audio}`,
3306
+ controls: true,
3307
+ className: "w-full"
3308
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3309
+ className: "bg-muted/50 border border-border p-2.5 rounded-lg text-xs text-muted-foreground",
3310
+ children: "Audio data unavailable"
3311
+ }, undefined, false, undefined, this)
3312
+ }, idx, false, undefined, this))
3313
+ }, undefined, false, undefined, this)
3314
+ ]
3315
+ }, undefined, true, undefined, this),
3316
+ message.files && message.files.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3317
+ className: cn("space-y-2 pt-1", mediaClassName),
3318
+ children: [
3319
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3320
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3321
+ children: [
3322
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Paperclip, {
3323
+ className: "h-3.5 w-3.5"
3324
+ }, undefined, false, undefined, this),
3325
+ "Files (",
3326
+ message.files.length,
3327
+ ")"
3328
+ ]
3329
+ }, undefined, true, undefined, this),
3330
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3331
+ className: "flex flex-wrap gap-2",
3332
+ children: message.files.map((file, idx) => showFilePreview ? /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(FilePreviewCard, {
3333
+ file: { name: file.name, type: file.type, url: file.url, size: file.size },
3334
+ onClick: () => openFilePreview({ name: file.name, type: file.type, url: file.url, size: file.size })
3335
+ }, idx, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3336
+ className: "flex items-center gap-2 rounded-lg border border-border px-3 py-2 text-xs bg-muted/30 hover:bg-muted/50 transition-colors",
3337
+ children: [
3338
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.FileIcon, {
3339
+ className: "h-3.5 w-3.5 shrink-0 text-muted-foreground"
3340
+ }, undefined, false, undefined, this),
3341
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3342
+ className: "truncate max-w-[180px]",
3343
+ children: file.name
3344
+ }, undefined, false, undefined, this),
3345
+ file.size && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3346
+ className: "text-muted-foreground/70",
3347
+ children: [
3348
+ "(",
3349
+ (file.size / 1024).toFixed(1),
3350
+ "KB)"
3351
+ ]
3352
+ }, undefined, true, undefined, this),
3353
+ file.url && /^https?:\/\//i.test(file.url) && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("a", {
3354
+ href: file.url,
3355
+ target: "_blank",
3356
+ rel: "noopener noreferrer",
3357
+ className: "text-primary hover:underline font-medium",
3358
+ children: "View"
3359
+ }, undefined, false, undefined, this)
3360
+ ]
3361
+ }, idx, true, undefined, this))
3362
+ }, undefined, false, undefined, this)
3363
+ ]
3364
+ }, undefined, true, undefined, this),
3365
+ message.response_audio && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3366
+ className: cn("space-y-2 pt-1", mediaClassName),
3367
+ children: [
3368
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3369
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3370
+ children: [
3371
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.Music, {
3372
+ className: "h-3.5 w-3.5"
3373
+ }, undefined, false, undefined, this),
3374
+ "Response Audio"
3375
+ ]
3376
+ }, undefined, true, undefined, this),
3377
+ message.response_audio.transcript && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3378
+ className: "text-xs italic bg-muted/50 border border-border p-2.5 rounded-lg text-muted-foreground",
3379
+ children: [
3380
+ '"',
3381
+ message.response_audio.transcript,
3382
+ '"'
3383
+ ]
3384
+ }, undefined, true, undefined, this),
3385
+ message.response_audio.content && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("audio", {
3386
+ src: `data:audio/wav;base64,${message.response_audio.content}`,
3387
+ controls: true,
3388
+ className: "w-full"
3389
+ }, undefined, false, undefined, this)
3390
+ ]
3391
+ }, undefined, true, undefined, this)
3392
+ ]
3393
+ }, undefined, true, undefined, this);
3394
+ })(),
3395
+ showToolCalls && message.tool_calls && message.tool_calls.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3396
+ className: cn("space-y-2 pt-1", classNames?.toolCalls),
3397
+ children: message.tool_calls.map((tool, idx) => renderToolCall ? renderToolCall(tool, idx) : /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(Tool, {
3398
+ defaultOpen: idx === 0,
3399
+ children: [
3400
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(ToolHeader, {
3401
+ title: tool.tool_name,
3402
+ type: "tool-use",
3403
+ state: getToolState(tool)
3404
+ }, undefined, false, undefined, this),
3405
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(ToolContent, {
3406
+ children: [
3407
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(ToolInput, {
3408
+ input: tool.tool_args
3409
+ }, undefined, false, undefined, this),
3410
+ tool.content && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(ToolOutput, {
3411
+ output: tool.content,
3412
+ errorText: tool.tool_call_error ? "Tool execution failed" : undefined
3413
+ }, undefined, false, undefined, this)
3414
+ ]
3415
+ }, undefined, true, undefined, this)
3416
+ ]
3417
+ }, tool.tool_call_id || idx, true, undefined, this))
3418
+ }, undefined, false, undefined, this),
3419
+ showReferences && message.extra_data?.references && message.extra_data.references.length > 0 && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3420
+ className: cn("space-y-2 pt-1", classNames?.references),
3421
+ children: [
3422
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3423
+ className: "flex items-center gap-2 text-xs font-medium text-muted-foreground",
3424
+ children: [
3425
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.FileText, {
3426
+ className: "h-3.5 w-3.5"
3427
+ }, undefined, false, undefined, this),
3428
+ "References (",
3429
+ message.extra_data.references.length,
3430
+ ")"
3431
+ ]
3432
+ }, undefined, true, undefined, this),
3433
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3434
+ className: "space-y-2",
3435
+ children: message.extra_data.references.map((refData, idx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3436
+ className: "text-xs space-y-1.5",
3437
+ children: [
3438
+ refData.query && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3439
+ className: "font-medium text-foreground",
3440
+ children: [
3441
+ "Query: ",
3442
+ refData.query
3443
+ ]
3444
+ }, undefined, true, undefined, this),
3445
+ refData.references.map((ref, refIdx) => /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3446
+ className: "bg-muted/50 border border-border p-2.5 rounded-lg",
3447
+ children: [
3448
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3449
+ className: "italic text-muted-foreground mb-1",
3450
+ children: [
3451
+ '"',
3452
+ ref.content,
3453
+ '"'
3454
+ ]
3455
+ }, undefined, true, undefined, this),
3456
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3457
+ className: "text-muted-foreground/70",
3458
+ children: [
3459
+ "Source: ",
3460
+ ref.name,
3461
+ " (chunk ",
3462
+ ref.meta_data.chunk,
3463
+ "/",
3464
+ ref.meta_data.chunk_size,
3465
+ ")"
3466
+ ]
3467
+ }, undefined, true, undefined, this)
3468
+ ]
3469
+ }, refIdx, true, undefined, this))
3470
+ ]
3471
+ }, idx, true, undefined, this))
3472
+ }, undefined, false, undefined, this)
3473
+ ]
3474
+ }, undefined, true, undefined, this)
3475
+ ]
3476
+ }, undefined, true, undefined, this),
3477
+ (renderActions || showTimestamp || hasError) && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3478
+ className: "flex items-center gap-2 pt-1",
3479
+ children: [
3480
+ renderActions && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("div", {
3481
+ className: cn("flex items-center gap-1", classNames?.actions),
3482
+ children: renderActions(message)
3483
+ }, undefined, false, undefined, this),
3484
+ hasError && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV("span", {
3485
+ className: "flex items-center gap-1 text-[11px] text-destructive",
3486
+ children: [
3487
+ /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(import_lucide_react19.AlertCircle, {
3488
+ className: "h-3 w-3"
3489
+ }, undefined, false, undefined, this),
3490
+ "Error"
3491
+ ]
3492
+ }, undefined, true, undefined, this),
3493
+ showTimestamp && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(SmartTimestamp, {
3494
+ date: new Date(message.created_at * 1000),
3495
+ formatShort: isCustomTimestamp ? resolvedFormatTimestamp : undefined,
3496
+ className: "text-[11px] text-muted-foreground"
3497
+ }, undefined, false, undefined, this)
3498
+ ]
3499
+ }, undefined, true, undefined, this)
3500
+ ]
3501
+ }, undefined, true, undefined, this)
3502
+ ]
3503
+ }, undefined, true, undefined, this),
3504
+ preview?.type === "image" && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(ImageLightbox, {
3505
+ open: true,
3506
+ onOpenChange: (open) => {
3507
+ if (!open)
3508
+ closePreview();
3509
+ },
3510
+ images: preview.images,
3511
+ initialIndex: preview.initialIndex
3512
+ }, undefined, false, undefined, this),
3513
+ preview?.type === "file" && /* @__PURE__ */ jsx_dev_runtime36.jsxDEV(FilePreviewModal, {
3514
+ open: true,
3515
+ onOpenChange: (open) => {
3516
+ if (!open)
3517
+ closePreview();
3518
+ },
3519
+ file: preview.file
3520
+ }, undefined, false, undefined, this)
3521
+ ]
3522
+ }, undefined, true, undefined, this);
3523
+ }
3524
+
3525
+ // src/ui/composed/agno-chat/suggested-prompts.tsx
3526
+ var jsx_dev_runtime37 = require("react/jsx-dev-runtime");
3527
+ function AgnoChatSuggestedPrompts({ className, prompts }) {
3528
+ const { handleSend } = useAgnoChatContext();
3529
+ if (prompts.length === 0)
3530
+ return null;
3531
+ return /* @__PURE__ */ jsx_dev_runtime37.jsxDEV("div", {
3532
+ className: cn("grid grid-cols-2 gap-2 w-full max-w-md", className),
3533
+ children: prompts.map((prompt, idx) => /* @__PURE__ */ jsx_dev_runtime37.jsxDEV("button", {
3534
+ onClick: () => handleSend(prompt.text),
3535
+ className: "flex items-center gap-2 px-3 py-2.5 rounded-xl border border-border bg-card hover:bg-accent/50 hover:border-primary/20 transition-all duration-200 text-left text-sm group",
3536
+ children: [
3537
+ prompt.icon && /* @__PURE__ */ jsx_dev_runtime37.jsxDEV("span", {
3538
+ className: "text-muted-foreground group-hover:text-primary transition-colors",
3539
+ children: prompt.icon
3540
+ }, undefined, false, undefined, this),
3541
+ /* @__PURE__ */ jsx_dev_runtime37.jsxDEV("span", {
3542
+ className: "text-muted-foreground group-hover:text-foreground transition-colors text-xs leading-snug",
3543
+ children: prompt.text
3544
+ }, undefined, false, undefined, this)
3545
+ ]
3546
+ }, idx, true, undefined, this))
3547
+ }, undefined, false, undefined, this);
3548
+ }
3549
+
3550
+ // src/ui/composed/agno-chat/messages.tsx
3551
+ var import_lucide_react20 = require("lucide-react");
3552
+ var jsx_dev_runtime38 = require("react/jsx-dev-runtime");
3553
+ function ScrollOnNewUserMessage({ messageCount }) {
3554
+ const { scrollToBottom } = import_use_stick_to_bottom2.useStickToBottomContext();
3555
+ const prevCount = import_react17.useRef(messageCount);
3556
+ import_react17.useEffect(() => {
3557
+ if (messageCount > prevCount.current) {
3558
+ scrollToBottom("smooth");
3559
+ }
3560
+ prevCount.current = messageCount;
3561
+ }, [messageCount, scrollToBottom]);
3562
+ return null;
3563
+ }
3564
+ var DEFAULT_PROMPTS = [
3565
+ { text: "What can you help me with?" },
3566
+ { text: "Explain how you work" }
3567
+ ];
3568
+ function AgnoChatMessages({
3569
+ className,
3570
+ renderMessage,
3571
+ userAvatar,
3572
+ assistantAvatar,
3573
+ messageItemProps,
3574
+ emptyState,
3575
+ suggestedPrompts = DEFAULT_PROMPTS,
3576
+ children,
3577
+ showThinkingIndicator = true,
3578
+ renderThinkingIndicator
3579
+ }) {
3580
+ const { messages, isStreaming } = useAgnoChatContext();
3581
+ const lastMessage = messages[messages.length - 1];
3582
+ const isThinking = showThinkingIndicator && isStreaming && (!lastMessage || lastMessage.role !== "user") && !lastMessage?.content;
3583
+ const resolvedEmptyState = children ?? emptyState ?? /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3584
+ className: "flex flex-col items-center gap-6",
3585
+ children: [
3586
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3587
+ className: "relative",
3588
+ children: [
3589
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3590
+ className: "h-16 w-16 rounded-2xl bg-primary/10 flex items-center justify-center",
3591
+ children: /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(import_lucide_react20.Bot, {
3592
+ className: "h-8 w-8 text-primary"
3593
+ }, undefined, false, undefined, this)
3594
+ }, undefined, false, undefined, this),
3595
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3596
+ className: "absolute -bottom-1 -right-1 h-5 w-5 rounded-full bg-green-500 border-2 border-background flex items-center justify-center",
3597
+ children: /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("span", {
3598
+ className: "h-2 w-2 rounded-full bg-white animate-pulse"
3599
+ }, undefined, false, undefined, this)
3600
+ }, undefined, false, undefined, this)
3601
+ ]
3602
+ }, undefined, true, undefined, this),
3603
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3604
+ className: "space-y-2 text-center",
3605
+ children: [
3606
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("h3", {
3607
+ className: "text-xl font-semibold tracking-tight",
3608
+ children: "Welcome to Agno Chat"
3609
+ }, undefined, false, undefined, this),
3610
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("p", {
3611
+ className: "text-muted-foreground text-sm max-w-sm",
3612
+ children: "Start a conversation with your AI agent. Ask questions, explore ideas, or run tools."
3613
+ }, undefined, false, undefined, this)
3614
+ ]
3615
+ }, undefined, true, undefined, this),
3616
+ suggestedPrompts.length > 0 && /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(AgnoChatSuggestedPrompts, {
3617
+ prompts: suggestedPrompts
3618
+ }, undefined, false, undefined, this)
3619
+ ]
3620
+ }, undefined, true, undefined, this);
3621
+ return /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(Conversation, {
3622
+ className: cn("relative flex-1 w-full", className),
3623
+ children: [
3624
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(ScrollOnNewUserMessage, {
3625
+ messageCount: messages.length
3626
+ }, undefined, false, undefined, this),
3627
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(ConversationContent, {
3628
+ className: "max-w-3xl mx-auto",
3629
+ children: [
3630
+ messages.length === 0 ? /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(ConversationEmptyState, {
3631
+ children: resolvedEmptyState
3632
+ }, undefined, false, undefined, this) : messages.map((message, index) => {
3633
+ if (isThinking && index === messages.length - 1 && message === lastMessage)
3634
+ return null;
3635
+ return renderMessage ? renderMessage(message, index) : /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(AgnoMessageItem, {
3636
+ message,
3637
+ userAvatar,
3638
+ assistantAvatar,
3639
+ ...messageItemProps
3640
+ }, `msg-${index}-${message.created_at}`, false, undefined, this);
3641
+ }),
3642
+ isThinking && /* @__PURE__ */ jsx_dev_runtime38.jsxDEV("div", {
3643
+ className: "py-2",
3644
+ children: renderThinkingIndicator ?? /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(StreamingIndicator, {
3645
+ avatar: assistantAvatar
3646
+ }, undefined, false, undefined, this)
3647
+ }, undefined, false, undefined, this)
3648
+ ]
3649
+ }, undefined, true, undefined, this),
3650
+ /* @__PURE__ */ jsx_dev_runtime38.jsxDEV(ConversationScrollButton, {}, undefined, false, undefined, this)
3651
+ ]
3652
+ }, undefined, true, undefined, this);
3653
+ }
3654
+
3655
+ // src/ui/composed/agno-chat/empty-state.tsx
3656
+ var jsx_dev_runtime39 = require("react/jsx-dev-runtime");
3657
+ function AgnoChatEmptyState({ children, className, ...props }) {
3658
+ return /* @__PURE__ */ jsx_dev_runtime39.jsxDEV("div", {
3659
+ className: cn("flex flex-col items-center gap-6", className),
3660
+ ...props,
3661
+ children
3662
+ }, undefined, false, undefined, this);
3663
+ }
3664
+
3665
+ // src/ui/composed/agno-chat/tool-status.tsx
3666
+ var import_lucide_react21 = require("lucide-react");
3667
+ var jsx_dev_runtime40 = require("react/jsx-dev-runtime");
3668
+ function AgnoChatToolStatus({ className }) {
3669
+ const { isPaused, isExecuting, pendingTools } = useAgnoChatContext();
3670
+ if (!isPaused && !isExecuting)
3671
+ return null;
3672
+ return /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("div", {
3673
+ className: cn("px-4 py-2.5 border-t border-border bg-primary/5", className),
3674
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("div", {
3675
+ className: "flex items-center gap-2.5 text-sm max-w-3xl mx-auto",
3676
+ children: isExecuting ? /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(jsx_dev_runtime40.Fragment, {
3677
+ children: [
3678
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("div", {
3679
+ className: "h-5 w-5 rounded-full bg-primary/10 flex items-center justify-center",
3680
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(import_lucide_react21.Loader2, {
3681
+ className: "h-3 w-3 animate-spin text-primary"
3682
+ }, undefined, false, undefined, this)
3683
+ }, undefined, false, undefined, this),
3684
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("span", {
3685
+ className: "text-muted-foreground",
3686
+ children: [
3687
+ "Executing",
3688
+ " ",
3689
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("span", {
3690
+ className: "font-medium text-foreground",
3691
+ children: pendingTools.length
3692
+ }, undefined, false, undefined, this),
3693
+ " tool",
3694
+ pendingTools.length !== 1 ? "s" : "",
3695
+ "..."
3696
+ ]
3697
+ }, undefined, true, undefined, this)
3698
+ ]
3699
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(jsx_dev_runtime40.Fragment, {
3700
+ children: [
3701
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("div", {
3702
+ className: "h-5 w-5 rounded-full bg-amber-500/10 flex items-center justify-center",
3703
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(import_lucide_react21.Wrench, {
3704
+ className: "h-3 w-3 text-amber-600 dark:text-amber-400"
3705
+ }, undefined, false, undefined, this)
3706
+ }, undefined, false, undefined, this),
3707
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("span", {
3708
+ className: "text-muted-foreground",
3709
+ children: [
3710
+ "Preparing",
3711
+ " ",
3712
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV("span", {
3713
+ className: "font-medium text-foreground",
3714
+ children: pendingTools.length
3715
+ }, undefined, false, undefined, this),
3716
+ " tool",
3717
+ pendingTools.length !== 1 ? "s" : "",
3718
+ "..."
3719
+ ]
3720
+ }, undefined, true, undefined, this)
3721
+ ]
3722
+ }, undefined, true, undefined, this)
3723
+ }, undefined, false, undefined, this)
3724
+ }, undefined, false, undefined, this);
3725
+ }
3726
+
3727
+ // src/ui/composed/agno-chat/error-bar.tsx
3728
+ var jsx_dev_runtime41 = require("react/jsx-dev-runtime");
3729
+ function AgnoChatErrorBar({ className }) {
3730
+ const { error, executionError } = useAgnoChatContext();
3731
+ const message = error || executionError;
3732
+ if (!message)
3733
+ return null;
3734
+ return /* @__PURE__ */ jsx_dev_runtime41.jsxDEV("div", {
3735
+ className: cn("px-4 py-2.5 bg-destructive/5 border-t border-destructive/20", className),
3736
+ children: /* @__PURE__ */ jsx_dev_runtime41.jsxDEV("p", {
3737
+ className: "text-sm text-destructive max-w-3xl mx-auto",
3738
+ children: message
3739
+ }, undefined, false, undefined, this)
3740
+ }, undefined, false, undefined, this);
3741
+ }
3742
+
3743
+ // src/ui/composed/AgnoChatInput.tsx
3744
+ var import_lucide_react22 = require("lucide-react");
3745
+ var jsx_dev_runtime42 = require("react/jsx-dev-runtime");
3746
+ var DEFAULT_ACCEPTED_FILE_TYPES = "image/*,audio/*,.pdf,.doc,.docx,.txt,.csv,.xlsx,.xls,.ppt,.pptx,.md,.json,.xml";
3747
+ function dataUrlToBlob(dataUrl) {
3748
+ const [header, base64] = dataUrl.split(",");
3749
+ const mime = header.match(/:(.*?);/)?.[1] || "application/octet-stream";
3750
+ const bytes = atob(base64);
3751
+ const buf = new Uint8Array(bytes.length);
3752
+ for (let i = 0;i < bytes.length; i++) {
3753
+ buf[i] = bytes.charCodeAt(i);
3754
+ }
3755
+ return new Blob([buf], { type: mime });
3756
+ }
3757
+ function CancelButton({ onCancel }) {
3758
+ return /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(Button, {
3759
+ type: "button",
3760
+ variant: "destructive",
3761
+ size: "icon",
3762
+ className: "h-8 w-8 rounded-lg",
3763
+ onClick: onCancel,
3764
+ "aria-label": "Stop",
3765
+ children: /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(import_lucide_react22.CircleStop, {
3766
+ className: "size-4"
3767
+ }, undefined, false, undefined, this)
3768
+ }, undefined, false, undefined, this);
3769
+ }
3770
+ function SubmitButton({ disabled, status }) {
3771
+ const { textInput } = usePromptInputController();
3772
+ const hasText = textInput.value.trim().length > 0;
3773
+ return /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputSubmit, {
3774
+ disabled: disabled || !hasText,
3775
+ status
3776
+ }, undefined, false, undefined, this);
3777
+ }
3778
+ function AttachmentHeader() {
3779
+ const { files } = usePromptInputAttachments();
3780
+ if (files.length === 0)
3781
+ return null;
3782
+ return /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputHeader, {
3783
+ children: /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputAttachments, {
3784
+ children: (attachment) => /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputAttachment, {
3785
+ data: attachment
3786
+ }, undefined, false, undefined, this)
3787
+ }, undefined, false, undefined, this)
3788
+ }, undefined, false, undefined, this);
3789
+ }
3790
+ function TranscribeAudioRecorder({
3791
+ endpoint,
3792
+ headers,
3793
+ disabled,
3794
+ parseResponse,
3795
+ onRequestPermission,
3796
+ labels
3797
+ }) {
3798
+ const { textInput } = usePromptInputController();
3799
+ return /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(AudioRecorder, {
3800
+ mode: "transcribe",
3801
+ transcriptionEndpoint: endpoint,
3802
+ transcriptionHeaders: headers,
3803
+ parseTranscriptionResponse: parseResponse,
3804
+ onRequestPermission,
3805
+ onRecordingComplete: () => {},
3806
+ onTranscriptionComplete: (text) => {
3807
+ const current = textInput.value;
3808
+ textInput.setInput(current + (current ? " " : "") + text);
3809
+ },
3810
+ disabled,
3811
+ labels
3812
+ }, undefined, false, undefined, this);
3813
+ }
3814
+ function AgnoChatInput({
3815
+ onSend,
3816
+ disabled,
3817
+ placeholder,
3818
+ className,
3819
+ fileUpload,
3820
+ showAudioRecorder = false,
3821
+ showAttachments = true,
3822
+ status,
3823
+ isStreaming,
3824
+ onCancel,
3825
+ allowCancelRun = false,
3826
+ extraTools,
3827
+ audioMode = "send",
3828
+ transcriptionEndpoint,
3829
+ transcriptionHeaders,
3830
+ parseTranscriptionResponse,
3831
+ onRequestPermission,
3832
+ audioRecorderLabels,
3833
+ dropZoneContainerRef,
3834
+ dropZoneProps
3835
+ }) {
3836
+ const handleSubmit = (message) => {
3837
+ const text = message.text?.trim() || "";
3838
+ const files = message.files || [];
3839
+ if (!text)
3840
+ return;
3841
+ if (files.length === 0) {
3842
+ onSend(text);
3843
+ return;
3844
+ }
3845
+ const formData = new FormData;
3846
+ formData.append("message", text);
3847
+ for (const file of files) {
3848
+ if (!file.url)
3849
+ continue;
3850
+ const blob = file.url.startsWith("data:") ? dataUrlToBlob(file.url) : null;
3851
+ if (!blob)
3852
+ continue;
3853
+ const fileName = file.filename || "file";
3854
+ formData.append("files", blob, fileName);
3855
+ }
3856
+ onSend(formData);
3857
+ };
3858
+ const handleAudioRecording = (blob) => {
3859
+ const formData = new FormData;
3860
+ formData.append("message", "Audio message");
3861
+ formData.append("files", blob, `recording-${Date.now()}.wav`);
3862
+ onSend(formData);
3863
+ };
3864
+ const computedStatus = status ?? (disabled ? "submitted" : undefined);
3865
+ const showCancelButton = allowCancelRun && isStreaming && onCancel;
3866
+ return /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputProvider, {
3867
+ children: /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInput, {
3868
+ onSubmit: handleSubmit,
3869
+ accept: fileUpload?.accept ?? DEFAULT_ACCEPTED_FILE_TYPES,
3870
+ multiple: fileUpload?.multiple ?? true,
3871
+ maxFiles: fileUpload?.maxFiles,
3872
+ maxFileSize: fileUpload?.maxFileSize,
3873
+ globalDrop: !!dropZoneContainerRef,
3874
+ dragListenerTarget: dropZoneContainerRef,
3875
+ className: cn("w-full", className),
3876
+ children: [
3877
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(AttachmentHeader, {}, undefined, false, undefined, this),
3878
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputBody, {
3879
+ children: /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputTextarea, {
3880
+ placeholder: placeholder || "Type your message... (Enter to send, Shift+Enter for new line)",
3881
+ disabled
3882
+ }, undefined, false, undefined, this)
3883
+ }, undefined, false, undefined, this),
3884
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputFooter, {
3885
+ children: [
3886
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputTools, {
3887
+ children: [
3888
+ showAttachments && /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputActionMenu, {
3889
+ children: [
3890
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputActionMenuTrigger, {}, undefined, false, undefined, this),
3891
+ /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputActionMenuContent, {
3892
+ children: /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputActionAddAttachments, {
3893
+ label: "Add files"
3894
+ }, undefined, false, undefined, this)
3895
+ }, undefined, false, undefined, this)
3896
+ ]
3897
+ }, undefined, true, undefined, this),
3898
+ showAudioRecorder && (audioMode === "transcribe" && transcriptionEndpoint ? /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(TranscribeAudioRecorder, {
3899
+ endpoint: transcriptionEndpoint,
3900
+ headers: transcriptionHeaders,
3901
+ disabled,
3902
+ parseResponse: parseTranscriptionResponse,
3903
+ onRequestPermission,
3904
+ labels: audioRecorderLabels
3905
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(AudioRecorder, {
3906
+ onRecordingComplete: handleAudioRecording,
3907
+ disabled,
3908
+ onRequestPermission,
3909
+ labels: audioRecorderLabels
3910
+ }, undefined, false, undefined, this)),
3911
+ extraTools
3912
+ ]
3913
+ }, undefined, true, undefined, this),
3914
+ showCancelButton ? /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(CancelButton, {
3915
+ onCancel
3916
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(SubmitButton, {
3917
+ disabled,
3918
+ status: computedStatus
3919
+ }, undefined, false, undefined, this)
3920
+ ]
3921
+ }, undefined, true, undefined, this),
3922
+ showAttachments && /* @__PURE__ */ jsx_dev_runtime42.jsxDEV(PromptInputDropZone, {
3923
+ ...dropZoneProps,
3924
+ container: dropZoneContainerRef
3925
+ }, undefined, false, undefined, this)
3926
+ ]
3927
+ }, undefined, true, undefined, this)
3928
+ }, undefined, false, undefined, this);
3929
+ }
3930
+
3931
+ // src/ui/composed/agno-chat/input.tsx
3932
+ var jsx_dev_runtime43 = require("react/jsx-dev-runtime");
3933
+ function AgnoChatInputArea({
3934
+ className,
3935
+ children,
3936
+ placeholder,
3937
+ fileUpload,
3938
+ showAudioRecorder = false,
3939
+ showAttachments,
3940
+ extraTools,
3941
+ chatInputProps,
3942
+ audioMode,
3943
+ transcriptionEndpoint,
3944
+ transcriptionHeaders,
3945
+ parseTranscriptionResponse,
3946
+ onRequestPermission,
3947
+ audioRecorderLabels,
3948
+ allowCancelRun = false,
3949
+ dropZoneProps
3950
+ }) {
3951
+ const { handleSend, inputDisabled, isStreaming, isPaused, cancelRun, dropZoneContainerRef } = useAgnoChatContext();
3952
+ return /* @__PURE__ */ jsx_dev_runtime43.jsxDEV("div", {
3953
+ className: cn("border-t border-border bg-background/80 backdrop-blur-sm", className),
3954
+ children: /* @__PURE__ */ jsx_dev_runtime43.jsxDEV("div", {
3955
+ className: "mx-auto px-4 py-2",
3956
+ children: children ? children({ onSend: handleSend, disabled: inputDisabled, isStreaming, isPaused }) : /* @__PURE__ */ jsx_dev_runtime43.jsxDEV(AgnoChatInput, {
3957
+ ...chatInputProps,
3958
+ onSend: handleSend,
3959
+ disabled: inputDisabled,
3960
+ isStreaming,
3961
+ onCancel: cancelRun,
3962
+ allowCancelRun,
3963
+ placeholder: placeholder ?? chatInputProps?.placeholder ?? "Message your agent...",
3964
+ fileUpload,
3965
+ showAudioRecorder,
3966
+ showAttachments,
3967
+ extraTools,
3968
+ audioMode,
3969
+ transcriptionEndpoint,
3970
+ transcriptionHeaders,
3971
+ parseTranscriptionResponse,
3972
+ onRequestPermission,
3973
+ audioRecorderLabels,
3974
+ dropZoneContainerRef,
3975
+ dropZoneProps
3976
+ }, undefined, false, undefined, this)
3977
+ }, undefined, false, undefined, this)
3978
+ }, undefined, false, undefined, this);
3979
+ }
3980
+
3981
+ // src/ui/composed/agno-chat/index.ts
3982
+ var AgnoChat = Object.assign(AgnoChatRoot, {
3983
+ Messages: AgnoChatMessages,
3984
+ EmptyState: AgnoChatEmptyState,
3985
+ SuggestedPrompts: AgnoChatSuggestedPrompts,
3986
+ ToolStatus: AgnoChatToolStatus,
3987
+ ErrorBar: AgnoChatErrorBar,
3988
+ Input: AgnoChatInputArea
3989
+ });
3990
+
3991
+ // src/ui/composed/AgnoChatInterface.tsx
3992
+ var import_lucide_react23 = require("lucide-react");
3993
+ var jsx_dev_runtime44 = require("react/jsx-dev-runtime");
3994
+ var DEFAULT_PROMPTS2 = [
3995
+ { icon: /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(import_lucide_react23.Sparkles, {
3996
+ className: "h-3.5 w-3.5"
3997
+ }, undefined, false, undefined, this), text: "What can you help me with?" },
3998
+ { icon: /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(import_lucide_react23.Bot, {
3999
+ className: "h-3.5 w-3.5"
4000
+ }, undefined, false, undefined, this), text: "Explain how you work" }
4001
+ ];
4002
+ function AgnoChatInterface({
4003
+ className,
4004
+ classNames,
4005
+ renderMessage,
4006
+ renderInput,
4007
+ emptyState,
4008
+ headerSlot,
4009
+ inputToolbarSlot,
4010
+ suggestedPrompts = DEFAULT_PROMPTS2,
4011
+ toolHandlers = {},
4012
+ autoExecuteTools = true,
4013
+ placeholder,
4014
+ userAvatar,
4015
+ assistantAvatar,
4016
+ fileUpload,
4017
+ showAudioRecorder = true,
4018
+ showAttachments = true,
4019
+ messageItemProps,
4020
+ chatInputProps,
4021
+ dropZoneLabel
4022
+ }) {
4023
+ return /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(AgnoChat, {
4024
+ toolHandlers,
4025
+ autoExecuteTools,
4026
+ className: cn(classNames?.root, className),
4027
+ children: [
4028
+ headerSlot,
4029
+ /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(AgnoChat.Messages, {
4030
+ className: classNames?.messagesArea,
4031
+ renderMessage,
4032
+ userAvatar,
4033
+ assistantAvatar,
4034
+ messageItemProps,
4035
+ emptyState,
4036
+ suggestedPrompts
4037
+ }, undefined, false, undefined, this),
4038
+ /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(AgnoChat.ToolStatus, {
4039
+ className: classNames?.toolStatusBar
4040
+ }, undefined, false, undefined, this),
4041
+ /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(AgnoChat.ErrorBar, {
4042
+ className: classNames?.errorBar
4043
+ }, undefined, false, undefined, this),
4044
+ /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(AgnoChat.Input, {
4045
+ className: classNames?.inputArea,
4046
+ placeholder,
4047
+ fileUpload,
4048
+ showAudioRecorder,
4049
+ showAttachments,
4050
+ extraTools: inputToolbarSlot,
4051
+ chatInputProps,
4052
+ dropZoneProps: { className: classNames?.dropZone, label: dropZoneLabel },
4053
+ children: renderInput ? ({ onSend, disabled }) => renderInput({ onSend, disabled }) : undefined
4054
+ }, undefined, false, undefined, this)
4055
+ ]
4056
+ }, undefined, true, undefined, this);
4057
+ }
4058
+
4059
+ //# debugId=128E98AEB83ACE9C64756E2164756E21