@mordn/chat-widget 0.7.0 → 0.7.1

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.
package/dist/index.js CHANGED
@@ -43,6 +43,11 @@ __export(src_exports, {
43
43
  Input: () => Input,
44
44
  StarterMessageItem: () => StarterMessageItem,
45
45
  StarterMessages: () => StarterMessages,
46
+ Tool: () => Tool,
47
+ ToolContent: () => ToolContent,
48
+ ToolHeader: () => ToolHeader,
49
+ ToolInput: () => ToolInput,
50
+ ToolOutput: () => ToolOutput,
46
51
  default: () => ChatWidget_default,
47
52
  fontOptions: () => fontOptions,
48
53
  useChatStorageKey: () => useChatStorageKey,
@@ -51,7 +56,7 @@ __export(src_exports, {
51
56
  module.exports = __toCommonJS(src_exports);
52
57
 
53
58
  // src/ChatWidget.tsx
54
- var import_react13 = require("react");
59
+ var import_react14 = require("react");
55
60
 
56
61
  // src/ui/button.tsx
57
62
  var import_react_slot = require("@radix-ui/react-slot");
@@ -259,13 +264,22 @@ function PromptInputAttachment({
259
264
  ...props
260
265
  }) {
261
266
  const attachments = usePromptInputAttachments();
267
+ const isImage = data.mediaType?.startsWith("image/") && !!data.url;
262
268
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
263
269
  "div",
264
270
  {
265
- className: cn("group relative h-14 w-14 rounded-lg border", className),
271
+ className: cn(
272
+ "group relative rounded-lg border",
273
+ // Images keep the square thumbnail. Other files use a wider
274
+ // pill-shaped chip showing icon + filename — without it,
275
+ // non-image attachments rendered as identical paperclip
276
+ // squares with no way to tell them apart.
277
+ isImage ? "h-14 w-14" : "h-14 max-w-[200px]",
278
+ className
279
+ ),
266
280
  ...props,
267
281
  children: [
268
- data.mediaType?.startsWith("image/") && data.url ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
282
+ isImage ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
269
283
  "img",
270
284
  {
271
285
  alt: data.filename || "attachment",
@@ -274,7 +288,7 @@ function PromptInputAttachment({
274
288
  src: data.url,
275
289
  width: 56
276
290
  }
277
- ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex size-full items-center justify-center text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.PaperclipIcon, { className: "size-4" }) }),
291
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NonImageChip, { data }),
278
292
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
279
293
  Button,
280
294
  {
@@ -292,6 +306,34 @@ function PromptInputAttachment({
292
306
  data.id
293
307
  );
294
308
  }
309
+ function NonImageChip({ data }) {
310
+ const { Icon: Icon2, label } = describeFile(data);
311
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex size-full items-center gap-2 px-2.5", children: [
312
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon2, { className: "size-5 flex-shrink-0 text-muted-foreground" }),
313
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "min-w-0 flex flex-col leading-tight", children: [
314
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[12px] font-medium truncate", children: data.filename || "attachment" }),
315
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-muted-foreground uppercase tracking-wide", children: label })
316
+ ] })
317
+ ] });
318
+ }
319
+ function describeFile(data) {
320
+ const mt = (data.mediaType || "").toLowerCase();
321
+ const ext = (data.filename || "").toLowerCase().split(".").pop() || "";
322
+ if (mt === "application/pdf" || ext === "pdf") return { Icon: import_lucide_react4.FileTextIcon, label: "PDF" };
323
+ if (mt.includes("spreadsheet") || mt.includes("excel") || ext === "xlsx" || ext === "xls" || ext === "csv" || ext === "tsv") {
324
+ return { Icon: import_lucide_react4.FileSpreadsheetIcon, label: ext.toUpperCase() || "Spreadsheet" };
325
+ }
326
+ if (mt.includes("presentation") || mt.includes("powerpoint") || ext === "pptx" || ext === "ppt") {
327
+ return { Icon: import_lucide_react4.PresentationIcon, label: ext.toUpperCase() || "Slides" };
328
+ }
329
+ if (mt.includes("wordprocessing") || mt.includes("msword") || ext === "docx" || ext === "doc") {
330
+ return { Icon: import_lucide_react4.FileTextIcon, label: ext.toUpperCase() || "Doc" };
331
+ }
332
+ if (mt.startsWith("text/") || ext === "txt" || ext === "md" || ext === "json") {
333
+ return { Icon: import_lucide_react4.FileTextIcon, label: ext.toUpperCase() || "Text" };
334
+ }
335
+ return { Icon: import_lucide_react4.FileIcon, label: ext.toUpperCase() || "File" };
336
+ }
295
337
  function PromptInputAttachments({
296
338
  className,
297
339
  children,
@@ -356,10 +398,18 @@ var PromptInput = ({
356
398
  if (!accept || accept.trim() === "") {
357
399
  return true;
358
400
  }
359
- if (accept.includes("image/*")) {
360
- return f.type.startsWith("image/");
361
- }
362
- return true;
401
+ const tokens = accept.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
402
+ const fileType = (f.type || "").toLowerCase();
403
+ const fileName = f.name.toLowerCase();
404
+ return tokens.some((token) => {
405
+ if (token === "*/*") return true;
406
+ if (token.startsWith(".")) return fileName.endsWith(token);
407
+ if (token.endsWith("/*")) {
408
+ const prefix = token.slice(0, -1);
409
+ return fileType.startsWith(prefix);
410
+ }
411
+ return fileType === token;
412
+ });
363
413
  },
364
414
  [accept]
365
415
  );
@@ -661,6 +711,8 @@ var PromptInputSubmit = ({
661
711
  variant = "default",
662
712
  size = "icon",
663
713
  status,
714
+ onStop,
715
+ onClick,
664
716
  children,
665
717
  ...props
666
718
  }) => {
@@ -672,13 +724,22 @@ var PromptInputSubmit = ({
672
724
  } else if (status === "error") {
673
725
  Icon2 = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.XIcon, { className: "size-4" });
674
726
  }
727
+ const isStopping = status === "streaming" && !!onStop;
675
728
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
676
729
  Button,
677
730
  {
678
731
  className: cn("gap-1.5 rounded-lg", className),
679
732
  size,
680
- type: "submit",
733
+ type: isStopping ? "button" : "submit",
681
734
  variant,
735
+ onClick: (e) => {
736
+ if (isStopping) {
737
+ e.preventDefault();
738
+ onStop();
739
+ }
740
+ onClick?.(e);
741
+ },
742
+ "aria-label": isStopping ? "Stop generating" : void 0,
682
743
  ...props,
683
744
  children: children ?? Icon2
684
745
  }
@@ -688,55 +749,75 @@ var PromptInputSubmit = ({
688
749
  // src/components/message-attachments.tsx
689
750
  var import_lucide_react5 = require("lucide-react");
690
751
  var import_jsx_runtime9 = require("react/jsx-runtime");
752
+ function openAttachment(attachment) {
753
+ if (attachment.url.startsWith("data:")) {
754
+ const w = window.open("", "_blank");
755
+ if (w) {
756
+ w.document.write(
757
+ `<html><head><title>${attachment.filename}</title></head><body style="margin:0;padding:20px;background:#f5f5f5;display:flex;justify-content:center;align-items:center;min-height:100vh;"><img src="${attachment.url}" alt="${attachment.filename}" style="max-width:100%;max-height:100%;object-fit:contain;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.15);" /></body></html>`
758
+ );
759
+ w.document.close();
760
+ }
761
+ return;
762
+ }
763
+ window.open(attachment.url, "_blank");
764
+ }
765
+ function describeFile2(att) {
766
+ const mt = (att.mediaType || "").toLowerCase();
767
+ const ext = (att.filename || "").toLowerCase().split(".").pop() || "";
768
+ if (mt === "application/pdf" || ext === "pdf") return { Icon: import_lucide_react5.FileTextIcon, label: "PDF" };
769
+ if (mt.includes("spreadsheet") || mt.includes("excel") || ext === "xlsx" || ext === "xls" || ext === "csv" || ext === "tsv") {
770
+ return { Icon: import_lucide_react5.FileSpreadsheetIcon, label: ext.toUpperCase() || "Spreadsheet" };
771
+ }
772
+ if (mt.includes("presentation") || mt.includes("powerpoint") || ext === "pptx" || ext === "ppt") {
773
+ return { Icon: import_lucide_react5.PresentationIcon, label: ext.toUpperCase() || "Slides" };
774
+ }
775
+ if (mt.includes("wordprocessing") || mt.includes("msword") || ext === "docx" || ext === "doc") {
776
+ return { Icon: import_lucide_react5.FileTextIcon, label: ext.toUpperCase() || "Doc" };
777
+ }
778
+ if (mt.startsWith("text/") || ext === "txt" || ext === "md" || ext === "json") {
779
+ return { Icon: import_lucide_react5.FileTextIcon, label: ext.toUpperCase() || "Text" };
780
+ }
781
+ return { Icon: import_lucide_react5.FileIcon, label: ext.toUpperCase() || "File" };
782
+ }
691
783
  function MessageAttachments({ attachments, className }) {
692
784
  if (!attachments || attachments.length === 0) {
693
785
  return null;
694
786
  }
695
- const handleAttachmentClick = (attachment) => {
696
- if (attachment.url.startsWith("data:")) {
697
- const newWindow = window.open("", "_blank");
698
- if (newWindow) {
699
- newWindow.document.write(`
700
- <html>
701
- <head><title>${attachment.filename}</title></head>
702
- <body style="margin:0; padding:20px; background:#f5f5f5; display:flex; justify-content:center; align-items:center; min-height:100vh;">
703
- <img src="${attachment.url}" alt="${attachment.filename}" style="max-width:100%; max-height:100%; object-fit:contain; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.15);" />
704
- </body>
705
- </html>
706
- `);
707
- newWindow.document.close();
708
- }
709
- } else if (attachment.url.startsWith("blob:")) {
710
- window.open(attachment.url, "_blank");
711
- } else if (attachment.url.startsWith("http")) {
712
- window.open(attachment.url, "_blank");
713
- } else {
714
- window.open(attachment.url, "_blank");
715
- }
716
- };
717
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: cn("flex flex-wrap gap-2", className), children: attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
718
- "div",
719
- {
720
- className: "group relative h-14 w-14 rounded-lg",
721
- children: attachment.mediaType.startsWith("image/") ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
787
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: cn("flex flex-wrap gap-2", className), children: attachments.map((attachment, index) => {
788
+ const isImage = attachment.mediaType.startsWith("image/");
789
+ if (isImage) {
790
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "group relative h-14 w-14 rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
722
791
  "img",
723
792
  {
724
793
  src: attachment.url,
725
794
  alt: attachment.filename,
726
795
  className: "size-full rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity",
727
- onClick: () => handleAttachmentClick(attachment)
796
+ onClick: () => openAttachment(attachment)
728
797
  }
729
- ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
730
- "div",
731
- {
732
- className: "flex size-full items-center justify-center text-muted-foreground cursor-pointer hover:bg-secondary/50 rounded-lg transition-colors",
733
- onClick: () => handleAttachmentClick(attachment),
734
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react5.PaperclipIcon, { className: "size-4" })
735
- }
736
- )
737
- },
738
- index
739
- )) });
798
+ ) }, index);
799
+ }
800
+ const { Icon: Icon2, label } = describeFile2(attachment);
801
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
802
+ "button",
803
+ {
804
+ type: "button",
805
+ onClick: () => openAttachment(attachment),
806
+ className: cn(
807
+ "group flex items-center gap-2 px-2.5 h-14 rounded-lg border max-w-[220px]",
808
+ "hover:bg-[hsl(var(--chat-text)/0.04)] transition-colors text-left cursor-pointer"
809
+ ),
810
+ children: [
811
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon2, { className: "size-5 flex-shrink-0 text-muted-foreground" }),
812
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "min-w-0 flex flex-col leading-tight", children: [
813
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-[12px] font-medium truncate", children: attachment.filename }),
814
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-[10px] text-muted-foreground uppercase tracking-wide", children: label })
815
+ ] })
816
+ ]
817
+ },
818
+ index
819
+ );
820
+ }) });
740
821
  }
741
822
 
742
823
  // src/components/input-plugin-popover.tsx
@@ -1016,23 +1097,150 @@ function PluginPanel({ plugin, items, loading, highlight, onHover, onSelect }) {
1016
1097
  );
1017
1098
  }
1018
1099
 
1100
+ // src/components/chat-error-banner.tsx
1101
+ var import_lucide_react6 = require("lucide-react");
1102
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1103
+ function ChatErrorBanner({
1104
+ error,
1105
+ canRetry = true,
1106
+ onRetry,
1107
+ onDismiss
1108
+ }) {
1109
+ if (!error) return null;
1110
+ const friendly = friendlyErrorMessage(error);
1111
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1112
+ "div",
1113
+ {
1114
+ role: "alert",
1115
+ className: "flex items-start gap-2 px-3 py-2 mb-2 rounded-lg text-[13px]",
1116
+ style: {
1117
+ backgroundColor: "hsl(var(--chat-text)/0.04)",
1118
+ border: "1px solid var(--chat-divider)"
1119
+ },
1120
+ title: error.message,
1121
+ children: [
1122
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1123
+ import_lucide_react6.AlertTriangleIcon,
1124
+ {
1125
+ className: "size-4 mt-0.5 flex-shrink-0",
1126
+ style: { color: "hsl(var(--chat-text)/0.6)" }
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { color: "hsl(var(--chat-text)/0.85)" }, children: friendly }) }),
1130
+ canRetry && onRetry && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1131
+ "button",
1132
+ {
1133
+ type: "button",
1134
+ onClick: onRetry,
1135
+ className: "text-[12px] font-medium underline-offset-2 hover:underline",
1136
+ style: { color: "hsl(var(--chat-text)/0.85)" },
1137
+ children: "Try again"
1138
+ }
1139
+ ),
1140
+ onDismiss && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1141
+ "button",
1142
+ {
1143
+ type: "button",
1144
+ onClick: onDismiss,
1145
+ "aria-label": "Dismiss",
1146
+ className: "flex-shrink-0 -mr-1 -mt-0.5 p-1 rounded hover:bg-[hsl(var(--chat-text)/0.06)] transition-colors",
1147
+ style: { color: "hsl(var(--chat-text)/0.5)" },
1148
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.XIcon, { className: "size-3.5" })
1149
+ }
1150
+ )
1151
+ ]
1152
+ }
1153
+ );
1154
+ }
1155
+ function friendlyErrorMessage(error) {
1156
+ const raw = error.message ?? "";
1157
+ if (/abort/i.test(raw)) return "Stopped.";
1158
+ if (/network|fetch|disconnect|ECONN/i.test(raw)) {
1159
+ return "Connection issue. Check your network and try again.";
1160
+ }
1161
+ if (/rate.?limit|429/i.test(raw)) {
1162
+ return "You're sending messages too fast. Wait a moment and try again.";
1163
+ }
1164
+ if (/timeout/i.test(raw)) return "The response took too long.";
1165
+ return "Something went wrong while generating the response.";
1166
+ }
1167
+
1168
+ // src/components/message-actions.tsx
1169
+ var import_react4 = require("react");
1170
+ var import_lucide_react7 = require("lucide-react");
1171
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1172
+ function MessageActions({
1173
+ text,
1174
+ onRegenerate,
1175
+ regenerateDisabled,
1176
+ className
1177
+ }) {
1178
+ const [copied, setCopied] = (0, import_react4.useState)(false);
1179
+ const handleCopy = async () => {
1180
+ if (!text) return;
1181
+ try {
1182
+ await navigator.clipboard.writeText(text);
1183
+ setCopied(true);
1184
+ setTimeout(() => setCopied(false), 1500);
1185
+ } catch {
1186
+ }
1187
+ };
1188
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1189
+ "div",
1190
+ {
1191
+ className: cn(
1192
+ "flex items-center gap-1 mt-1.5 -ml-1.5",
1193
+ // Pulled left a touch so the icons line up with the message
1194
+ // text edge instead of its padding box.
1195
+ className
1196
+ ),
1197
+ children: [
1198
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ActionButton, { onClick: handleCopy, ariaLabel: "Copy message", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.CheckIcon, { className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.CopyIcon, { className: "size-3.5" }) }),
1199
+ onRegenerate && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1200
+ ActionButton,
1201
+ {
1202
+ onClick: onRegenerate,
1203
+ disabled: regenerateDisabled,
1204
+ ariaLabel: "Regenerate response",
1205
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.RotateCcwIcon, { className: "size-3.5" })
1206
+ }
1207
+ )
1208
+ ]
1209
+ }
1210
+ );
1211
+ }
1212
+ function ActionButton({ onClick, disabled, ariaLabel, children }) {
1213
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1214
+ "button",
1215
+ {
1216
+ type: "button",
1217
+ onClick,
1218
+ disabled,
1219
+ "aria-label": ariaLabel,
1220
+ className: "p-1.5 rounded-md transition-colors hover:bg-[hsl(var(--chat-text)/0.06)] disabled:opacity-40 disabled:cursor-not-allowed",
1221
+ style: { color: "hsl(var(--chat-text)/0.55)" },
1222
+ children
1223
+ }
1224
+ );
1225
+ }
1226
+
1019
1227
  // src/components/interface.tsx
1020
- var import_react10 = require("react");
1021
- var import_lucide_react10 = require("lucide-react");
1022
1228
  var import_react11 = require("react");
1023
- var import_react12 = require("@ai-sdk/react");
1229
+ var import_lucide_react12 = require("lucide-react");
1230
+ var import_react12 = require("react");
1231
+ var import_react13 = require("@ai-sdk/react");
1024
1232
  var import_ai = require("ai");
1025
1233
 
1026
1234
  // src/components/response.tsx
1027
- var import_react5 = require("react");
1235
+ var import_react6 = require("react");
1028
1236
  var import_streamdown = require("streamdown");
1029
1237
 
1030
1238
  // src/hooks/use-code-scroll.ts
1031
- var import_react4 = require("react");
1239
+ var import_react5 = require("react");
1032
1240
  function useCodeBlockAutoScroll(isStreaming) {
1033
- const observerRef = (0, import_react4.useRef)(null);
1034
- const containerRef = (0, import_react4.useRef)(null);
1035
- (0, import_react4.useEffect)(() => {
1241
+ const observerRef = (0, import_react5.useRef)(null);
1242
+ const containerRef = (0, import_react5.useRef)(null);
1243
+ (0, import_react5.useEffect)(() => {
1036
1244
  if (!isStreaming || !containerRef.current) {
1037
1245
  if (observerRef.current) {
1038
1246
  observerRef.current.disconnect();
@@ -1062,11 +1270,11 @@ function useCodeBlockAutoScroll(isStreaming) {
1062
1270
  }
1063
1271
 
1064
1272
  // src/components/response.tsx
1065
- var import_jsx_runtime11 = require("react/jsx-runtime");
1066
- var Response = (0, import_react5.memo)(
1273
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1274
+ var Response = (0, import_react6.memo)(
1067
1275
  ({ className, isStreaming = false, ...props }) => {
1068
1276
  const containerRef = useCodeBlockAutoScroll(isStreaming);
1069
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ref: containerRef, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1277
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { ref: containerRef, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1070
1278
  import_streamdown.Streamdown,
1071
1279
  {
1072
1280
  className: cn(
@@ -1083,16 +1291,16 @@ Response.displayName = "Response";
1083
1291
 
1084
1292
  // src/ui/collapsible.tsx
1085
1293
  var CollapsiblePrimitive = __toESM(require("@radix-ui/react-collapsible"));
1086
- var import_jsx_runtime12 = require("react/jsx-runtime");
1294
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1087
1295
  function Collapsible({
1088
1296
  ...props
1089
1297
  }) {
1090
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
1091
1299
  }
1092
1300
  function CollapsibleTrigger2({
1093
1301
  ...props
1094
1302
  }) {
1095
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1303
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1096
1304
  CollapsiblePrimitive.CollapsibleTrigger,
1097
1305
  {
1098
1306
  "data-slot": "collapsible-trigger",
@@ -1103,7 +1311,7 @@ function CollapsibleTrigger2({
1103
1311
  function CollapsibleContent2({
1104
1312
  ...props
1105
1313
  }) {
1106
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1314
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1107
1315
  CollapsiblePrimitive.CollapsibleContent,
1108
1316
  {
1109
1317
  "data-slot": "collapsible-content",
@@ -1113,9 +1321,9 @@ function CollapsibleContent2({
1113
1321
  }
1114
1322
 
1115
1323
  // src/components/sources.tsx
1116
- var import_lucide_react6 = require("lucide-react");
1117
- var import_jsx_runtime13 = require("react/jsx-runtime");
1118
- var Sources = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1324
+ var import_lucide_react8 = require("lucide-react");
1325
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1326
+ var Sources = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1119
1327
  Collapsible,
1120
1328
  {
1121
1329
  className: cn("not-prose mb-4 text-primary text-xs", className),
@@ -1127,25 +1335,25 @@ var SourcesTrigger = ({
1127
1335
  count,
1128
1336
  children,
1129
1337
  ...props
1130
- }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1338
+ }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1131
1339
  CollapsibleTrigger2,
1132
1340
  {
1133
1341
  className: cn("flex items-center gap-2", className),
1134
1342
  ...props,
1135
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1136
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "font-medium", children: [
1343
+ children: children ?? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
1344
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: "font-medium", children: [
1137
1345
  "Used ",
1138
1346
  count,
1139
1347
  " sources"
1140
1348
  ] }),
1141
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.ChevronDownIcon, { className: "h-4 w-4" })
1349
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.ChevronDownIcon, { className: "h-4 w-4" })
1142
1350
  ] })
1143
1351
  }
1144
1352
  );
1145
1353
  var SourcesContent = ({
1146
1354
  className,
1147
1355
  ...props
1148
- }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1356
+ }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1149
1357
  CollapsibleContent2,
1150
1358
  {
1151
1359
  className: cn(
@@ -1156,7 +1364,7 @@ var SourcesContent = ({
1156
1364
  ...props
1157
1365
  }
1158
1366
  );
1159
- var Source = ({ href, title, children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1367
+ var Source = ({ href, title, children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1160
1368
  "a",
1161
1369
  {
1162
1370
  className: "flex items-center gap-2",
@@ -1164,21 +1372,21 @@ var Source = ({ href, title, children, ...props }) => /* @__PURE__ */ (0, import
1164
1372
  rel: "noreferrer",
1165
1373
  target: "_blank",
1166
1374
  ...props,
1167
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1168
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.BookIcon, { className: "h-4 w-4" }),
1169
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "block font-medium", children: title })
1375
+ children: children ?? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
1376
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.BookIcon, { className: "h-4 w-4" }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "block font-medium", children: title })
1170
1378
  ] })
1171
1379
  }
1172
1380
  );
1173
1381
 
1174
1382
  // src/components/reasoning.tsx
1175
1383
  var import_react_use_controllable_state = require("@radix-ui/react-use-controllable-state");
1176
- var import_lucide_react7 = require("lucide-react");
1177
- var import_react6 = require("react");
1178
- var import_jsx_runtime14 = require("react/jsx-runtime");
1179
- var ReasoningContext = (0, import_react6.createContext)(null);
1384
+ var import_lucide_react9 = require("lucide-react");
1385
+ var import_react7 = require("react");
1386
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1387
+ var ReasoningContext = (0, import_react7.createContext)(null);
1180
1388
  var useReasoning = () => {
1181
- const context = (0, import_react6.useContext)(ReasoningContext);
1389
+ const context = (0, import_react7.useContext)(ReasoningContext);
1182
1390
  if (!context) {
1183
1391
  throw new Error("Reasoning components must be used within Reasoning");
1184
1392
  }
@@ -1186,7 +1394,7 @@ var useReasoning = () => {
1186
1394
  };
1187
1395
  var AUTO_CLOSE_DELAY = 1e3;
1188
1396
  var MS_IN_S = 1e3;
1189
- var Reasoning = (0, import_react6.memo)(
1397
+ var Reasoning = (0, import_react7.memo)(
1190
1398
  ({
1191
1399
  className,
1192
1400
  isStreaming = false,
@@ -1206,9 +1414,9 @@ var Reasoning = (0, import_react6.memo)(
1206
1414
  prop: durationProp,
1207
1415
  defaultProp: void 0
1208
1416
  });
1209
- const [hasAutoClosed, setHasAutoClosed] = (0, import_react6.useState)(false);
1210
- const [startTime, setStartTime] = (0, import_react6.useState)(null);
1211
- (0, import_react6.useEffect)(() => {
1417
+ const [hasAutoClosed, setHasAutoClosed] = (0, import_react7.useState)(false);
1418
+ const [startTime, setStartTime] = (0, import_react7.useState)(null);
1419
+ (0, import_react7.useEffect)(() => {
1212
1420
  if (isStreaming) {
1213
1421
  if (startTime === null) {
1214
1422
  setStartTime(Date.now());
@@ -1218,7 +1426,7 @@ var Reasoning = (0, import_react6.memo)(
1218
1426
  setStartTime(null);
1219
1427
  }
1220
1428
  }, [isStreaming, startTime, setDuration]);
1221
- (0, import_react6.useEffect)(() => {
1429
+ (0, import_react7.useEffect)(() => {
1222
1430
  if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed && durationProp !== void 0) {
1223
1431
  const timer = setTimeout(() => {
1224
1432
  setIsOpen(false);
@@ -1230,11 +1438,11 @@ var Reasoning = (0, import_react6.memo)(
1230
1438
  const handleOpenChange = (newOpen) => {
1231
1439
  setIsOpen(newOpen);
1232
1440
  };
1233
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1441
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1234
1442
  ReasoningContext.Provider,
1235
1443
  {
1236
1444
  value: { isStreaming, isOpen, setIsOpen, duration },
1237
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1445
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1238
1446
  Collapsible,
1239
1447
  {
1240
1448
  className: cn("not-prose", className),
@@ -1250,24 +1458,24 @@ var Reasoning = (0, import_react6.memo)(
1250
1458
  );
1251
1459
  var getThinkingMessage = (isStreaming, duration) => {
1252
1460
  if (isStreaming) {
1253
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: "Thinking..." });
1461
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: "Thinking..." });
1254
1462
  }
1255
1463
  if (duration === void 0) {
1256
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: "Thought process" });
1464
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: "Thought process" });
1257
1465
  }
1258
1466
  if (duration === 0) {
1259
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: "Thought process" });
1467
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: "Thought process" });
1260
1468
  }
1261
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1469
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
1262
1470
  "Thought for ",
1263
1471
  duration,
1264
1472
  " seconds"
1265
1473
  ] });
1266
1474
  };
1267
- var ReasoningTrigger = (0, import_react6.memo)(
1475
+ var ReasoningTrigger = (0, import_react7.memo)(
1268
1476
  ({ className, children, ...props }) => {
1269
1477
  const { isStreaming, isOpen, duration } = useReasoning();
1270
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1478
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1271
1479
  CollapsibleTrigger2,
1272
1480
  {
1273
1481
  className: cn(
@@ -1275,11 +1483,11 @@ var ReasoningTrigger = (0, import_react6.memo)(
1275
1483
  className
1276
1484
  ),
1277
1485
  ...props,
1278
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1279
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.BrainIcon, { className: "size-4 flex-shrink-0" }),
1486
+ children: children ?? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
1487
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.BrainIcon, { className: "size-4 flex-shrink-0" }),
1280
1488
  getThinkingMessage(isStreaming, duration),
1281
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1282
- import_lucide_react7.ChevronDownIcon,
1489
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1490
+ import_lucide_react9.ChevronDownIcon,
1283
1491
  {
1284
1492
  className: cn(
1285
1493
  "size-4 flex-shrink-0 transition-transform ml-1",
@@ -1292,8 +1500,8 @@ var ReasoningTrigger = (0, import_react6.memo)(
1292
1500
  );
1293
1501
  }
1294
1502
  );
1295
- var ReasoningContent = (0, import_react6.memo)(
1296
- ({ className, children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1503
+ var ReasoningContent = (0, import_react7.memo)(
1504
+ ({ className, children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1297
1505
  CollapsibleContent2,
1298
1506
  {
1299
1507
  className: cn(
@@ -1302,7 +1510,7 @@ var ReasoningContent = (0, import_react6.memo)(
1302
1510
  className
1303
1511
  ),
1304
1512
  ...props,
1305
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Response, { className: "grid gap-2", children })
1513
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Response, { className: "grid gap-2", children })
1306
1514
  }
1307
1515
  )
1308
1516
  );
@@ -1311,8 +1519,8 @@ ReasoningTrigger.displayName = "ReasoningTrigger";
1311
1519
  ReasoningContent.displayName = "ReasoningContent";
1312
1520
 
1313
1521
  // src/components/loader.tsx
1314
- var import_jsx_runtime15 = require("react/jsx-runtime");
1315
- var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1522
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1523
+ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1316
1524
  "svg",
1317
1525
  {
1318
1526
  height: size,
@@ -1321,10 +1529,10 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1321
1529
  viewBox: "0 0 16 16",
1322
1530
  width: size,
1323
1531
  children: [
1324
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("title", { children: "Loader" }),
1325
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { clipPath: "url(#clip0_2393_1490)", children: [
1326
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M8 0V4", stroke: "currentColor", strokeWidth: "1.5" }),
1327
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1532
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("title", { children: "Loader" }),
1533
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { clipPath: "url(#clip0_2393_1490)", children: [
1534
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M8 0V4", stroke: "currentColor", strokeWidth: "1.5" }),
1535
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1328
1536
  "path",
1329
1537
  {
1330
1538
  d: "M8 16V12",
@@ -1333,7 +1541,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1333
1541
  strokeWidth: "1.5"
1334
1542
  }
1335
1543
  ),
1336
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1544
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1337
1545
  "path",
1338
1546
  {
1339
1547
  d: "M3.29773 1.52783L5.64887 4.7639",
@@ -1342,7 +1550,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1342
1550
  strokeWidth: "1.5"
1343
1551
  }
1344
1552
  ),
1345
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1553
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1346
1554
  "path",
1347
1555
  {
1348
1556
  d: "M12.7023 1.52783L10.3511 4.7639",
@@ -1351,7 +1559,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1351
1559
  strokeWidth: "1.5"
1352
1560
  }
1353
1561
  ),
1354
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1562
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1355
1563
  "path",
1356
1564
  {
1357
1565
  d: "M12.7023 14.472L10.3511 11.236",
@@ -1360,7 +1568,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1360
1568
  strokeWidth: "1.5"
1361
1569
  }
1362
1570
  ),
1363
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1571
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1364
1572
  "path",
1365
1573
  {
1366
1574
  d: "M3.29773 14.472L5.64887 11.236",
@@ -1369,7 +1577,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1369
1577
  strokeWidth: "1.5"
1370
1578
  }
1371
1579
  ),
1372
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1580
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1373
1581
  "path",
1374
1582
  {
1375
1583
  d: "M15.6085 5.52783L11.8043 6.7639",
@@ -1378,7 +1586,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1378
1586
  strokeWidth: "1.5"
1379
1587
  }
1380
1588
  ),
1381
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1589
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1382
1590
  "path",
1383
1591
  {
1384
1592
  d: "M0.391602 10.472L4.19583 9.23598",
@@ -1387,7 +1595,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1387
1595
  strokeWidth: "1.5"
1388
1596
  }
1389
1597
  ),
1390
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1598
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1391
1599
  "path",
1392
1600
  {
1393
1601
  d: "M15.6085 10.4722L11.8043 9.2361",
@@ -1396,7 +1604,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1396
1604
  strokeWidth: "1.5"
1397
1605
  }
1398
1606
  ),
1399
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1607
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1400
1608
  "path",
1401
1609
  {
1402
1610
  d: "M0.391602 5.52783L4.19583 6.7639",
@@ -1406,11 +1614,11 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1406
1614
  }
1407
1615
  )
1408
1616
  ] }),
1409
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("clipPath", { id: "clip0_2393_1490", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("rect", { fill: "white", height: "16", width: "16" }) }) })
1617
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("clipPath", { id: "clip0_2393_1490", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("rect", { fill: "white", height: "16", width: "16" }) }) })
1410
1618
  ]
1411
1619
  }
1412
1620
  );
1413
- var Loader = ({ className, size = 16, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1621
+ var Loader = ({ className, size = 16, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1414
1622
  "div",
1415
1623
  {
1416
1624
  className: cn(
@@ -1418,14 +1626,14 @@ var Loader = ({ className, size = 16, ...props }) => /* @__PURE__ */ (0, import_
1418
1626
  className
1419
1627
  ),
1420
1628
  ...props,
1421
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LoaderIcon, { size })
1629
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LoaderIcon, { size })
1422
1630
  }
1423
1631
  );
1424
1632
 
1425
1633
  // src/ui/badge.tsx
1426
1634
  var import_react_slot2 = require("@radix-ui/react-slot");
1427
1635
  var import_class_variance_authority3 = require("class-variance-authority");
1428
- var import_jsx_runtime16 = require("react/jsx-runtime");
1636
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1429
1637
  var badgeVariants = (0, import_class_variance_authority3.cva)(
1430
1638
  "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
1431
1639
  {
@@ -1449,7 +1657,7 @@ function Badge({
1449
1657
  ...props
1450
1658
  }) {
1451
1659
  const Comp = asChild ? import_react_slot2.Slot : "span";
1452
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1660
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1453
1661
  Comp,
1454
1662
  {
1455
1663
  "data-slot": "badge",
@@ -1460,16 +1668,16 @@ function Badge({
1460
1668
  }
1461
1669
 
1462
1670
  // src/components/tool.tsx
1463
- var import_lucide_react9 = require("lucide-react");
1464
- var import_react8 = require("react");
1671
+ var import_lucide_react11 = require("lucide-react");
1672
+ var import_react9 = require("react");
1465
1673
 
1466
1674
  // src/components/code-block.tsx
1467
- var import_lucide_react8 = require("lucide-react");
1468
- var import_react7 = require("react");
1675
+ var import_lucide_react10 = require("lucide-react");
1676
+ var import_react8 = require("react");
1469
1677
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
1470
1678
  var import_prism = require("react-syntax-highlighter/dist/esm/styles/prism");
1471
- var import_jsx_runtime17 = require("react/jsx-runtime");
1472
- var CodeBlockContext = (0, import_react7.createContext)({
1679
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1680
+ var CodeBlockContext = (0, import_react8.createContext)({
1473
1681
  code: ""
1474
1682
  });
1475
1683
  var CodeBlock = ({
@@ -1479,7 +1687,7 @@ var CodeBlock = ({
1479
1687
  className,
1480
1688
  children,
1481
1689
  ...props
1482
- }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CodeBlockContext.Provider, { value: { code }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1690
+ }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CodeBlockContext.Provider, { value: { code }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1483
1691
  "div",
1484
1692
  {
1485
1693
  className: cn(
@@ -1487,8 +1695,8 @@ var CodeBlock = ({
1487
1695
  className
1488
1696
  ),
1489
1697
  ...props,
1490
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative max-h-96 overflow-y-auto", children: [
1491
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1698
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative max-h-96 overflow-y-auto", children: [
1699
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1492
1700
  import_react_syntax_highlighter.Prism,
1493
1701
  {
1494
1702
  className: "overflow-hidden dark:hidden",
@@ -1514,7 +1722,7 @@ var CodeBlock = ({
1514
1722
  children: code
1515
1723
  }
1516
1724
  ),
1517
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1725
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1518
1726
  import_react_syntax_highlighter.Prism,
1519
1727
  {
1520
1728
  className: "hidden overflow-hidden dark:block",
@@ -1540,36 +1748,42 @@ var CodeBlock = ({
1540
1748
  children: code
1541
1749
  }
1542
1750
  ),
1543
- children && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "absolute top-2 right-2 flex items-center gap-2", children })
1751
+ children && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "absolute top-2 right-2 flex items-center gap-2", children })
1544
1752
  ] })
1545
1753
  }
1546
1754
  ) });
1547
1755
 
1548
1756
  // src/components/tool.tsx
1549
- var import_jsx_runtime18 = require("react/jsx-runtime");
1550
- var Tool = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1757
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1758
+ var Tool = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1551
1759
  Collapsible,
1552
1760
  {
1553
1761
  className: cn("not-prose w-full rounded-md border border-[var(--chat-divider)]", className),
1554
1762
  ...props
1555
1763
  }
1556
1764
  );
1765
+ var STATUS_LABELS = {
1766
+ "input-streaming": "Pending",
1767
+ "input-available": "Running",
1768
+ "output-available": "Completed",
1769
+ "output-error": "Error",
1770
+ "approval-requested": "Awaiting approval",
1771
+ "approval-responded": "Approved",
1772
+ "output-denied": "Denied"
1773
+ };
1774
+ var STATUS_ICONS = {
1775
+ "input-streaming": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.CircleIcon, { className: "size-4" }),
1776
+ "input-available": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.ClockIcon, { className: "size-4 animate-pulse" }),
1777
+ "output-available": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.CheckCircleIcon, { className: "size-4 text-green-600" }),
1778
+ "output-error": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.XCircleIcon, { className: "size-4 text-red-600" }),
1779
+ "approval-requested": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.ClockIcon, { className: "size-4 text-amber-600" }),
1780
+ "approval-responded": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.CheckCircleIcon, { className: "size-4 text-amber-600" }),
1781
+ "output-denied": /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.XCircleIcon, { className: "size-4 text-muted-foreground" })
1782
+ };
1557
1783
  var getStatusBadge = (status) => {
1558
- const labels = {
1559
- "input-streaming": "Pending",
1560
- "input-available": "Running",
1561
- "output-available": "Completed",
1562
- "output-error": "Error"
1563
- };
1564
- const icons = {
1565
- "input-streaming": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.CircleIcon, { className: "size-4" }),
1566
- "input-available": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ClockIcon, { className: "size-4 animate-pulse" }),
1567
- "output-available": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.CheckCircleIcon, { className: "size-4 text-green-600" }),
1568
- "output-error": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.XCircleIcon, { className: "size-4 text-red-600" })
1569
- };
1570
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Badge, { className: "gap-1.5 rounded-full text-xs", variant: "secondary", children: [
1571
- icons[status],
1572
- labels[status]
1784
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Badge, { className: "gap-1.5 rounded-full text-xs", variant: "secondary", children: [
1785
+ STATUS_ICONS[status],
1786
+ STATUS_LABELS[status]
1573
1787
  ] });
1574
1788
  };
1575
1789
  var ToolHeader = ({
@@ -1579,7 +1793,7 @@ var ToolHeader = ({
1579
1793
  toolName,
1580
1794
  state,
1581
1795
  ...props
1582
- }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1796
+ }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1583
1797
  CollapsibleTrigger2,
1584
1798
  {
1585
1799
  className: cn(
@@ -1588,16 +1802,16 @@ var ToolHeader = ({
1588
1802
  ),
1589
1803
  ...props,
1590
1804
  children: [
1591
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
1592
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.WrenchIcon, { className: "size-4 text-muted-foreground" }),
1593
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-sm", children: title ?? toolName ?? type.split("-").slice(1).join("-") }),
1805
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-2", children: [
1806
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.WrenchIcon, { className: "size-4 text-muted-foreground" }),
1807
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "font-medium text-sm", children: title ?? toolName ?? type.split("-").slice(1).join("-") }),
1594
1808
  getStatusBadge(state)
1595
1809
  ] }),
1596
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ChevronDownIcon, { className: "size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" })
1810
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.ChevronDownIcon, { className: "size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" })
1597
1811
  ]
1598
1812
  }
1599
1813
  );
1600
- var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1814
+ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1601
1815
  CollapsibleContent2,
1602
1816
  {
1603
1817
  className: cn(
@@ -1607,9 +1821,9 @@ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_ru
1607
1821
  ...props
1608
1822
  }
1609
1823
  );
1610
- var ToolInput = ({ className, input, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cn("space-y-2 overflow-hidden p-2", className), ...props, children: [
1611
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Parameters" }),
1612
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "rounded-md bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CodeBlock, { code: JSON.stringify(input, null, 2), language: "json" }) })
1824
+ var ToolInput = ({ className, input, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("space-y-2 overflow-hidden p-2", className), ...props, children: [
1825
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Parameters" }),
1826
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "rounded-md bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CodeBlock, { code: JSON.stringify(input, null, 2), language: "json" }) })
1613
1827
  ] });
1614
1828
  var ToolOutput = ({
1615
1829
  className,
@@ -1620,15 +1834,15 @@ var ToolOutput = ({
1620
1834
  if (!(output || errorText)) {
1621
1835
  return null;
1622
1836
  }
1623
- let Output = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: output });
1624
- if (typeof output === "object" && !(0, import_react8.isValidElement)(output)) {
1625
- Output = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CodeBlock, { code: JSON.stringify(output, null, 2), language: "json" });
1837
+ let Output = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: output });
1838
+ if (typeof output === "object" && !(0, import_react9.isValidElement)(output)) {
1839
+ Output = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CodeBlock, { code: JSON.stringify(output, null, 2), language: "json" });
1626
1840
  } else if (typeof output === "string") {
1627
- Output = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CodeBlock, { code: output, language: "json" });
1841
+ Output = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CodeBlock, { code: output, language: "json" });
1628
1842
  }
1629
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cn("space-y-2 p-2", className), ...props, children: [
1630
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: errorText ? "Error" : "Result" }),
1631
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1843
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("space-y-2 p-2", className), ...props, children: [
1844
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: errorText ? "Error" : "Result" }),
1845
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1632
1846
  "div",
1633
1847
  {
1634
1848
  className: cn(
@@ -1636,7 +1850,7 @@ var ToolOutput = ({
1636
1850
  errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground"
1637
1851
  ),
1638
1852
  children: [
1639
- errorText && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: errorText }),
1853
+ errorText && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: errorText }),
1640
1854
  Output
1641
1855
  ]
1642
1856
  }
@@ -1645,7 +1859,7 @@ var ToolOutput = ({
1645
1859
  };
1646
1860
 
1647
1861
  // src/components/suggestion2.tsx
1648
- var import_jsx_runtime19 = require("react/jsx-runtime");
1862
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1649
1863
  function StarterMessages({
1650
1864
  className,
1651
1865
  prompts,
@@ -1653,7 +1867,7 @@ function StarterMessages({
1653
1867
  ...props
1654
1868
  }) {
1655
1869
  if (prompts.length === 0) return null;
1656
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1870
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1657
1871
  "div",
1658
1872
  {
1659
1873
  className: cn(
@@ -1661,8 +1875,8 @@ function StarterMessages({
1661
1875
  className
1662
1876
  ),
1663
1877
  ...props,
1664
- children: prompts.map((prompt, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
1665
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1878
+ children: prompts.map((prompt, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
1879
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1666
1880
  StarterMessageItem,
1667
1881
  {
1668
1882
  prompt,
@@ -1672,7 +1886,7 @@ function StarterMessages({
1672
1886
  index < prompts.length - 1 && // 1px-tall element used as a divider — same --chat-divider token
1673
1887
  // every other separator in the widget uses, so consumers only
1674
1888
  // need to override one variable to recolour all of them.
1675
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "h-px mx-3", style: { backgroundColor: "var(--chat-divider)" } })
1889
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "h-px mx-3", style: { backgroundColor: "var(--chat-divider)" } })
1676
1890
  ] }, index))
1677
1891
  }
1678
1892
  );
@@ -1683,7 +1897,7 @@ function StarterMessageItem({
1683
1897
  onClick,
1684
1898
  ...props
1685
1899
  }) {
1686
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1900
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1687
1901
  "button",
1688
1902
  {
1689
1903
  type: "button",
@@ -1698,17 +1912,17 @@ function StarterMessageItem({
1698
1912
  ),
1699
1913
  ...props,
1700
1914
  children: [
1701
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[13px] text-[hsl(var(--chat-text)/0.7)]", children: prompt.title }),
1702
- prompt.subtitle && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block text-[11px] text-[hsl(var(--chat-text)/0.4)] mt-0.5", children: prompt.subtitle })
1915
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[13px] text-[hsl(var(--chat-text)/0.7)]", children: prompt.title }),
1916
+ prompt.subtitle && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block text-[11px] text-[hsl(var(--chat-text)/0.4)] mt-0.5", children: prompt.subtitle })
1703
1917
  ]
1704
1918
  }
1705
1919
  );
1706
1920
  }
1707
1921
 
1708
1922
  // src/contexts/chat-storage-context.tsx
1709
- var import_react9 = require("react");
1710
- var import_jsx_runtime20 = require("react/jsx-runtime");
1711
- var ChatStorageContext = (0, import_react9.createContext)({
1923
+ var import_react10 = require("react");
1924
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1925
+ var ChatStorageContext = (0, import_react10.createContext)({
1712
1926
  storageKeyPrefix: ""
1713
1927
  });
1714
1928
  function ChatStorageProvider({
@@ -1716,46 +1930,46 @@ function ChatStorageProvider({
1716
1930
  userId
1717
1931
  }) {
1718
1932
  const storageKeyPrefix = userId || "";
1719
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChatStorageContext.Provider, { value: { storageKeyPrefix }, children });
1933
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChatStorageContext.Provider, { value: { storageKeyPrefix }, children });
1720
1934
  }
1721
1935
  function useChatStorageKey() {
1722
- return (0, import_react9.useContext)(ChatStorageContext);
1936
+ return (0, import_react10.useContext)(ChatStorageContext);
1723
1937
  }
1724
1938
 
1725
1939
  // src/components/interface.tsx
1726
- var import_jsx_runtime21 = require("react/jsx-runtime");
1940
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1727
1941
  function ChatInterface({ id, initialMessages, config, onClose, headerActions } = {}) {
1728
1942
  const { storageKeyPrefix } = useChatStorageKey();
1729
1943
  const storageKey = (key) => storageKeyPrefix ? `chat-${storageKeyPrefix}-${key}` : `chat-${key}`;
1730
1944
  const themeMode = config?.theme?.mode || "light";
1731
- const [input, setInput] = (0, import_react10.useState)("");
1732
- const inputRef = (0, import_react10.useRef)(null);
1945
+ const [input, setInput] = (0, import_react11.useState)("");
1946
+ const inputRef = (0, import_react11.useRef)(null);
1733
1947
  const inputPlugins = useInputPlugins({
1734
1948
  textareaRef: inputRef,
1735
1949
  value: input,
1736
1950
  setValue: setInput,
1737
1951
  plugins: config?.inputPlugins
1738
1952
  });
1739
- const [showHistory, setShowHistory] = (0, import_react10.useState)(false);
1740
- const [conversations, setConversations] = (0, import_react10.useState)([]);
1741
- const [loadingHistory, setLoadingHistory] = (0, import_react10.useState)(false);
1742
- const [historyLoaded, setHistoryLoaded] = (0, import_react10.useState)(false);
1743
- const [searchQuery, setSearchQuery] = (0, import_react10.useState)("");
1744
- const [uploadError, setUploadError] = (0, import_react10.useState)(null);
1745
- (0, import_react10.useEffect)(() => {
1953
+ const [showHistory, setShowHistory] = (0, import_react11.useState)(false);
1954
+ const [conversations, setConversations] = (0, import_react11.useState)([]);
1955
+ const [loadingHistory, setLoadingHistory] = (0, import_react11.useState)(false);
1956
+ const [historyLoaded, setHistoryLoaded] = (0, import_react11.useState)(false);
1957
+ const [searchQuery, setSearchQuery] = (0, import_react11.useState)("");
1958
+ const [uploadError, setUploadError] = (0, import_react11.useState)(null);
1959
+ (0, import_react11.useEffect)(() => {
1746
1960
  if (uploadError) {
1747
1961
  const timeoutId = setTimeout(() => setUploadError(null), 5e3);
1748
1962
  return () => clearTimeout(timeoutId);
1749
1963
  }
1750
1964
  }, [uploadError]);
1751
- const [tabs, setTabs] = (0, import_react10.useState)([]);
1752
- const [activeTabId, setActiveTabId] = (0, import_react10.useState)("");
1753
- const [initialTabCreated, setInitialTabCreated] = (0, import_react10.useState)(false);
1754
- const [isInitializing, setIsInitializing] = (0, import_react10.useState)(true);
1755
- const [isLoadingMessages, setIsLoadingMessages] = (0, import_react10.useState)(false);
1756
- const lastSyncedTabId = (0, import_react10.useRef)("");
1757
- const hasInitialized = (0, import_react10.useRef)(false);
1758
- const { messages, sendMessage, status, setMessages } = (0, import_react12.useChat)({
1965
+ const [tabs, setTabs] = (0, import_react11.useState)([]);
1966
+ const [activeTabId, setActiveTabId] = (0, import_react11.useState)("");
1967
+ const [initialTabCreated, setInitialTabCreated] = (0, import_react11.useState)(false);
1968
+ const [isInitializing, setIsInitializing] = (0, import_react11.useState)(true);
1969
+ const [isLoadingMessages, setIsLoadingMessages] = (0, import_react11.useState)(false);
1970
+ const lastSyncedTabId = (0, import_react11.useRef)("");
1971
+ const hasInitialized = (0, import_react11.useRef)(false);
1972
+ const { messages, sendMessage, status, setMessages, stop, regenerate, error, clearError } = (0, import_react13.useChat)({
1759
1973
  id: activeTabId || "temp-id",
1760
1974
  transport: new import_ai.DefaultChatTransport({
1761
1975
  api: "/api/chat",
@@ -1802,8 +2016,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1802
2016
  mediaType: uploadResult.mediaType,
1803
2017
  size: uploadResult.size
1804
2018
  };
1805
- } catch (error) {
1806
- console.error(`Error uploading ${file.filename}:`, error);
2019
+ } catch (error2) {
2020
+ console.error(`Error uploading ${file.filename}:`, error2);
1807
2021
  return null;
1808
2022
  }
1809
2023
  });
@@ -1820,10 +2034,10 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1820
2034
  setUploadError(warnMsg);
1821
2035
  console.warn(warnMsg);
1822
2036
  }
1823
- } catch (error) {
2037
+ } catch (error2) {
1824
2038
  const errorMsg = "Error uploading files. Please try again.";
1825
2039
  setUploadError(errorMsg);
1826
- console.error("Error in file upload process:", error);
2040
+ console.error("Error in file upload process:", error2);
1827
2041
  return;
1828
2042
  }
1829
2043
  }
@@ -1844,12 +2058,12 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1844
2058
  };
1845
2059
  const AttachButton = () => {
1846
2060
  const attachments = usePromptInputAttachments();
1847
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2061
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1848
2062
  PromptInputButton,
1849
2063
  {
1850
2064
  variant: "ghost",
1851
2065
  onClick: () => attachments.openFileDialog(),
1852
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.PlusIcon, { className: "size-4" })
2066
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.PlusIcon, { className: "size-4" })
1853
2067
  }
1854
2068
  );
1855
2069
  };
@@ -1872,8 +2086,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1872
2086
  } else {
1873
2087
  console.error("Error loading messages:", response.status, response.statusText);
1874
2088
  }
1875
- } catch (error) {
1876
- console.error("Error loading conversation:", error);
2089
+ } catch (error2) {
2090
+ console.error("Error loading conversation:", error2);
1877
2091
  }
1878
2092
  };
1879
2093
  const generateUniqueTabId = () => {
@@ -1888,7 +2102,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1888
2102
  }
1889
2103
  return newTabId;
1890
2104
  };
1891
- const createNewTab = (0, import_react10.useCallback)(() => {
2105
+ const createNewTab = (0, import_react11.useCallback)(() => {
1892
2106
  if (!initialTabCreated) {
1893
2107
  console.warn("Cannot create new tab while initializing");
1894
2108
  return;
@@ -1915,10 +2129,10 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1915
2129
  setMessages([]);
1916
2130
  setInput("");
1917
2131
  }, [initialTabCreated]);
1918
- const startNewConversation = (0, import_react10.useCallback)(() => {
2132
+ const startNewConversation = (0, import_react11.useCallback)(() => {
1919
2133
  createNewTab();
1920
2134
  }, [createNewTab]);
1921
- (0, import_react10.useEffect)(() => {
2135
+ (0, import_react11.useEffect)(() => {
1922
2136
  return () => {
1923
2137
  };
1924
2138
  }, []);
@@ -1977,23 +2191,23 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1977
2191
  const errorText = await response.text();
1978
2192
  console.error("[ChatInterface] Error response:", errorText);
1979
2193
  }
1980
- } catch (error) {
1981
- console.error("[ChatInterface] Error fetching chat history:", error);
2194
+ } catch (error2) {
2195
+ console.error("[ChatInterface] Error fetching chat history:", error2);
1982
2196
  } finally {
1983
2197
  setLoadingHistory(false);
1984
2198
  }
1985
2199
  };
1986
- (0, import_react10.useEffect)(() => {
2200
+ (0, import_react11.useEffect)(() => {
1987
2201
  if (showHistory && !historyLoaded && config?.userId) {
1988
2202
  fetchConversations();
1989
2203
  }
1990
2204
  }, [showHistory, historyLoaded, config?.userId]);
1991
- (0, import_react10.useEffect)(() => {
2205
+ (0, import_react11.useEffect)(() => {
1992
2206
  if (!historyLoaded && config?.userId) {
1993
2207
  fetchConversations();
1994
2208
  }
1995
2209
  }, [historyLoaded, config?.userId]);
1996
- (0, import_react10.useEffect)(() => {
2210
+ (0, import_react11.useEffect)(() => {
1997
2211
  if (tabs.length > 0) {
1998
2212
  const timeoutId = setTimeout(() => {
1999
2213
  localStorage.setItem(storageKey("tabs"), JSON.stringify(tabs));
@@ -2002,7 +2216,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2002
2216
  return () => clearTimeout(timeoutId);
2003
2217
  }
2004
2218
  }, [tabs, activeTabId, storageKey]);
2005
- (0, import_react10.useEffect)(() => {
2219
+ (0, import_react11.useEffect)(() => {
2006
2220
  if (hasInitialized.current) return;
2007
2221
  const loadInitialTabs = () => {
2008
2222
  const savedTabs = localStorage.getItem(storageKey("tabs"));
@@ -2029,8 +2243,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2029
2243
  }
2030
2244
  hasInitialized.current = true;
2031
2245
  }, []);
2032
- const hasLoadedInitialMessages = (0, import_react10.useRef)(false);
2033
- (0, import_react10.useEffect)(() => {
2246
+ const hasLoadedInitialMessages = (0, import_react11.useRef)(false);
2247
+ (0, import_react11.useEffect)(() => {
2034
2248
  if (hasLoadedInitialMessages.current) return;
2035
2249
  if (!config?.userId) return;
2036
2250
  if (!activeTabId) return;
@@ -2043,14 +2257,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2043
2257
  }
2044
2258
  })();
2045
2259
  }, [config?.userId, activeTabId]);
2046
- (0, import_react10.useEffect)(() => {
2260
+ (0, import_react11.useEffect)(() => {
2047
2261
  if (isInitializing) return;
2048
2262
  if (activeTabId && tabs.length > 0 && activeTabId !== lastSyncedTabId.current) {
2049
2263
  lastSyncedTabId.current = activeTabId;
2050
2264
  setInput("");
2051
2265
  }
2052
2266
  }, [activeTabId, isInitializing, tabs.length]);
2053
- const groupedConversations = (0, import_react10.useMemo)(() => {
2267
+ const groupedConversations = (0, import_react11.useMemo)(() => {
2054
2268
  const filtered = conversations.filter(
2055
2269
  (conv) => searchQuery === "" || conv.title.toLowerCase().includes(searchQuery.toLowerCase())
2056
2270
  );
@@ -2111,22 +2325,27 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2111
2325
  const renderMessages = () => messages.map((message, index) => {
2112
2326
  const sourceParts = message.parts?.filter((part) => part.type === "source-url") || [];
2113
2327
  const fileParts = message.parts?.filter((part) => part.type === "file") || [];
2114
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: index > 0 ? "mt-6" : "", children: [
2115
- message.role === "assistant" && sourceParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Sources, { children: [
2116
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SourcesTrigger, { count: sourceParts.length }),
2117
- sourceParts.map((part, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SourcesContent, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2328
+ const isLastMessage = index === messages.length - 1;
2329
+ const isStreamingThisMessage = isLastMessage && message.role === "assistant" && status !== "ready";
2330
+ const showActions = message.role === "assistant" && !isStreamingThisMessage;
2331
+ const showRegenerate = showActions && isLastMessage && status === "ready";
2332
+ const messageText = showActions ? (message.parts ?? []).filter((p) => p.type === "text").map((p) => p.text).join("\n\n") : "";
2333
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: index > 0 ? "mt-6" : "", children: [
2334
+ message.role === "assistant" && sourceParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Sources, { children: [
2335
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SourcesTrigger, { count: sourceParts.length }),
2336
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SourcesContent, { children: sourceParts.map((part, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2118
2337
  Source,
2119
2338
  {
2120
2339
  href: part.url,
2121
2340
  title: part.url
2122
2341
  },
2123
- `${message.id}-${i}`
2124
- ) }, `${message.id}-${i}`))
2342
+ `${message.id}-source-${i}`
2343
+ )) })
2125
2344
  ] }),
2126
- fileParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn(
2345
+ fileParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn(
2127
2346
  "flex mb-1",
2128
2347
  message.role === "user" ? "justify-end" : "justify-start"
2129
- ), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2348
+ ), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2130
2349
  MessageAttachments,
2131
2350
  {
2132
2351
  attachments: fileParts.map((part) => ({
@@ -2137,14 +2356,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2137
2356
  }))
2138
2357
  }
2139
2358
  ) }),
2140
- message.parts ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-2", children: message.parts.map((part, i) => {
2359
+ message.parts ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "space-y-2", children: message.parts.map((part, i) => {
2141
2360
  switch (part.type) {
2142
2361
  case "text":
2143
2362
  const isTextStreaming = status === "streaming" && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;
2144
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react11.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Message, { from: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Response, { isStreaming: isTextStreaming, children: part.text }) }) }) }, `${message.id}-${i}`);
2363
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react12.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Message, { from: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Response, { isStreaming: isTextStreaming, children: part.text }) }) }) }, `${message.id}-${i}`);
2145
2364
  case "reasoning":
2146
2365
  const isCurrentlyStreaming = status === "streaming" && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;
2147
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2366
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2148
2367
  Reasoning,
2149
2368
  {
2150
2369
  className: "w-full",
@@ -2152,8 +2371,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2152
2371
  defaultOpen: false,
2153
2372
  open: isCurrentlyStreaming ? true : void 0,
2154
2373
  children: [
2155
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReasoningTrigger, {}),
2156
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReasoningContent, { children: part.text })
2374
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReasoningTrigger, {}),
2375
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReasoningContent, { children: part.text })
2157
2376
  ]
2158
2377
  },
2159
2378
  `${message.id}-${i}`
@@ -2161,8 +2380,24 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2161
2380
  default:
2162
2381
  if (part.type.startsWith("tool-") || part.type === "dynamic-tool") {
2163
2382
  const toolPart = part;
2164
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tool, { children: [
2165
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2383
+ const resolvedToolName = toolPart.toolName ?? (part.type.startsWith("tool-") ? part.type.slice(5) : "");
2384
+ const customRenderer = config?.toolRenderers?.[resolvedToolName];
2385
+ if (customRenderer) {
2386
+ const rendered = customRenderer({
2387
+ type: part.type,
2388
+ toolName: resolvedToolName,
2389
+ toolCallId: toolPart.toolCallId,
2390
+ state: toolPart.state,
2391
+ input: toolPart.input,
2392
+ output: toolPart.output,
2393
+ errorText: toolPart.errorText
2394
+ });
2395
+ if (rendered !== null && rendered !== void 0) {
2396
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react12.Fragment, { children: rendered }, `${message.id}-${i}`);
2397
+ }
2398
+ }
2399
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tool, { children: [
2400
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2166
2401
  ToolHeader,
2167
2402
  {
2168
2403
  type: part.type,
@@ -2170,9 +2405,9 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2170
2405
  state: toolPart.state
2171
2406
  }
2172
2407
  ),
2173
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ToolContent, { children: [
2174
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolInput, { input: toolPart.input }),
2175
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolOutput, { output: toolPart.output, errorText: toolPart.errorText })
2408
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ToolContent, { children: [
2409
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToolInput, { input: toolPart.input }),
2410
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToolOutput, { output: toolPart.output, errorText: toolPart.errorText })
2176
2411
  ] })
2177
2412
  ] }, `${message.id}-${i}`);
2178
2413
  }
@@ -2180,7 +2415,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2180
2415
  }
2181
2416
  }) }) : (
2182
2417
  /* Handle standard AI SDK messages with content or text property */
2183
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react11.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Message, { from: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Response, { children: message.content || message.text }) }) }) }, `${message.id}-content`)
2418
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react12.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Message, { from: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Response, { children: message.content || message.text }) }) }) }, `${message.id}-content`)
2419
+ ),
2420
+ showActions && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2421
+ MessageActions,
2422
+ {
2423
+ text: messageText,
2424
+ onRegenerate: showRegenerate && regenerate ? () => regenerate() : void 0
2425
+ }
2184
2426
  )
2185
2427
  ] }, message.id);
2186
2428
  });
@@ -2208,12 +2450,12 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2208
2450
  setActiveTabId(selectedConversationId);
2209
2451
  await loadConversation(selectedConversationId);
2210
2452
  setShowHistory(false);
2211
- } catch (error) {
2212
- console.error("Error loading conversation:", error);
2453
+ } catch (error2) {
2454
+ console.error("Error loading conversation:", error2);
2213
2455
  }
2214
2456
  };
2215
- const dropdownRef = (0, import_react10.useRef)(null);
2216
- (0, import_react10.useEffect)(() => {
2457
+ const dropdownRef = (0, import_react11.useRef)(null);
2458
+ (0, import_react11.useEffect)(() => {
2217
2459
  const handleClickOutside = (event) => {
2218
2460
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2219
2461
  setShowHistory(false);
@@ -2226,7 +2468,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2226
2468
  document.removeEventListener("mousedown", handleClickOutside);
2227
2469
  };
2228
2470
  }, [showHistory]);
2229
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("w-full h-full flex flex-col bg-white dark:bg-gray-900 overflow-hidden ring-1 ring-black/[0.02] dark:ring-white/[0.03]", themeMode === "dark" && "dark"), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2471
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn("w-full h-full flex flex-col bg-white dark:bg-gray-900 overflow-hidden ring-1 ring-black/[0.02] dark:ring-white/[0.03]", themeMode === "dark" && "dark"), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2230
2472
  "div",
2231
2473
  {
2232
2474
  className: cn(
@@ -2234,11 +2476,11 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2234
2476
  themeMode === "dark" && "dark"
2235
2477
  ),
2236
2478
  children: [
2237
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20", style: {
2479
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20", style: {
2238
2480
  borderColor: "var(--chat-divider)",
2239
2481
  backgroundColor: "var(--chat-header-bg)"
2240
2482
  }, children: [
2241
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-hide py-0.5 scroll-smooth", children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2483
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-hide py-0.5 scroll-smooth", children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2242
2484
  "div",
2243
2485
  {
2244
2486
  className: "relative flex items-center gap-1.5 px-3 py-1.5 rounded-lg cursor-pointer transition-all duration-150 group flex-shrink-0 min-w-0",
@@ -2261,8 +2503,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2261
2503
  switchToTab(tab.id);
2262
2504
  },
2263
2505
  children: [
2264
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate max-w-28 text-[13px] font-medium transition-colors", children: tab.title }),
2265
- tabs.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2506
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate max-w-28 text-[13px] font-medium transition-colors", children: tab.title }),
2507
+ tabs.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2266
2508
  "button",
2267
2509
  {
2268
2510
  onClick: (e) => {
@@ -2281,15 +2523,15 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2281
2523
  e.currentTarget.style.opacity = tab.isActive ? "0.6" : "0";
2282
2524
  e.currentTarget.style.backgroundColor = "transparent";
2283
2525
  },
2284
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.XIcon, { className: "h-3 w-3", strokeWidth: 2.5 })
2526
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.XIcon, { className: "h-3 w-3", strokeWidth: 2.5 })
2285
2527
  }
2286
2528
  )
2287
2529
  ]
2288
2530
  },
2289
2531
  tab.id
2290
2532
  )) }),
2291
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-0.5 flex-shrink-0", children: [
2292
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2533
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-0.5 flex-shrink-0", children: [
2534
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2293
2535
  "button",
2294
2536
  {
2295
2537
  onClick: createNewTab,
@@ -2306,11 +2548,11 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2306
2548
  e.currentTarget.style.backgroundColor = "transparent";
2307
2549
  },
2308
2550
  title: "New Chat",
2309
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.PlusIcon, { className: "h-4 w-4", strokeWidth: 2 })
2551
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.PlusIcon, { className: "h-4 w-4", strokeWidth: 2 })
2310
2552
  }
2311
2553
  ),
2312
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
2313
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2554
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
2555
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2314
2556
  "button",
2315
2557
  {
2316
2558
  onClick: () => setShowHistory(!showHistory),
@@ -2332,17 +2574,17 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2332
2574
  }
2333
2575
  },
2334
2576
  title: "Chat History",
2335
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.HistoryIcon, { className: "h-4 w-4", strokeWidth: 2 })
2577
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.HistoryIcon, { className: "h-4 w-4", strokeWidth: 2 })
2336
2578
  }
2337
2579
  ),
2338
- showHistory && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-72 rounded-xl shadow-[0_4px_24px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] z-50 animate-in fade-in slide-in-from-top-1 duration-150 overflow-hidden", style: {
2580
+ showHistory && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-72 rounded-xl shadow-[0_4px_24px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] z-50 animate-in fade-in slide-in-from-top-1 duration-150 overflow-hidden", style: {
2339
2581
  backgroundColor: "hsl(var(--chat-background))",
2340
2582
  border: `1px solid ${"var(--chat-divider)"}`
2341
2583
  }, children: [
2342
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "p-2.5 border-b", style: {
2584
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "p-2.5 border-b", style: {
2343
2585
  borderColor: "var(--chat-divider)",
2344
2586
  backgroundColor: "var(--chat-overlay)"
2345
- }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2587
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2346
2588
  "input",
2347
2589
  {
2348
2590
  type: "text",
@@ -2357,25 +2599,25 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2357
2599
  }
2358
2600
  }
2359
2601
  ) }) }),
2360
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-[13px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2361
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2602
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "text-[13px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2603
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2362
2604
  backgroundColor: "hsl(var(--chat-surface))"
2363
- }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.MessageSquareIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2364
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2365
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2366
- ] }) : groupedConversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2367
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2605
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.MessageSquareIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2606
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2607
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2608
+ ] }) : groupedConversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2609
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2368
2610
  backgroundColor: "hsl(var(--chat-surface))"
2369
- }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.SearchIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2370
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2371
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2372
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "py-0.5", children: groupedConversations.map(([groupName, groupConversations]) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mb-0.5", children: [
2373
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10", style: {
2611
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.SearchIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2612
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2613
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2614
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "py-0.5", children: groupedConversations.map(([groupName, groupConversations]) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "mb-0.5", children: [
2615
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10", style: {
2374
2616
  backgroundColor: "var(--chat-header-bg-strong)"
2375
- }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: "hsl(var(--chat-text-muted))" }, children: groupName }) }),
2376
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-1 space-y-0.5", children: groupConversations.map((conversation) => {
2617
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: "hsl(var(--chat-text-muted))" }, children: groupName }) }),
2618
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-1 space-y-0.5", children: groupConversations.map((conversation) => {
2377
2619
  const isActiveConversation = activeTabId === conversation.id;
2378
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2620
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2379
2621
  "button",
2380
2622
  {
2381
2623
  className: "w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative",
@@ -2393,13 +2635,13 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2393
2635
  }
2394
2636
  },
2395
2637
  onClick: () => handleSelectConversation(conversation.id, conversation.title),
2396
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2397
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[12px] line-clamp-1 transition-colors leading-tight", style: {
2638
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2639
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[12px] line-clamp-1 transition-colors leading-tight", style: {
2398
2640
  fontWeight: isActiveConversation ? 500 : 400,
2399
2641
  color: isActiveConversation ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-strong))"
2400
2642
  }, children: conversation.title }) }),
2401
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2402
- import_lucide_react10.ChevronRightIcon,
2643
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2644
+ import_lucide_react12.ChevronRightIcon,
2403
2645
  {
2404
2646
  className: "h-3 w-3 transition-all duration-150 flex-shrink-0",
2405
2647
  style: {
@@ -2418,7 +2660,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2418
2660
  ] })
2419
2661
  ] }),
2420
2662
  headerActions,
2421
- onClose && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2663
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2422
2664
  "button",
2423
2665
  {
2424
2666
  onClick: onClose,
@@ -2435,21 +2677,21 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2435
2677
  e.currentTarget.style.backgroundColor = "transparent";
2436
2678
  },
2437
2679
  title: "Close Chat",
2438
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.XIcon, { className: "h-4 w-4", strokeWidth: 2 })
2680
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.XIcon, { className: "h-4 w-4", strokeWidth: 2 })
2439
2681
  }
2440
2682
  )
2441
2683
  ] })
2442
2684
  ] }),
2443
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Conversation, { className: "flex-1 max-w-full ai-assistant-scrollbar", children: [
2444
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ConversationContent, { className: "max-w-[96%] mx-auto py-6", children: [
2685
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Conversation, { className: "flex-1 max-w-full ai-assistant-scrollbar", children: [
2686
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ConversationContent, { className: "max-w-[96%] mx-auto py-6", children: [
2445
2687
  renderMessages(),
2446
- status === "submitted" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Message, { from: "assistant", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Loader, { size: 16 }) }) }) })
2688
+ status === "submitted" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Message, { from: "assistant", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MessageContent, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Loader, { size: 16 }) }) }) })
2447
2689
  ] }),
2448
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ConversationScrollButton, {})
2690
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ConversationScrollButton, {})
2449
2691
  ] }),
2450
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "px-5 pb-5", children: [
2451
- uploadError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mb-3 px-4 py-3 bg-red-50 dark:bg-red-900/20 border border-red-200/60 dark:border-red-800/60 rounded-2xl text-sm text-red-700 dark:text-red-400 shadow-sm", children: uploadError }),
2452
- isInitializing || isLoadingMessages ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center py-8", role: "status", "aria-label": "Loading conversation", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "h-4 w-4 rounded-full border-2 border-current border-t-transparent animate-spin", style: { color: "hsl(var(--chat-text-muted))" } }) }) : messages.length === 0 && status !== "submitted" && config?.starterPrompts && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2692
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "px-5 pb-5", children: [
2693
+ uploadError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mb-3 px-4 py-3 bg-red-50 dark:bg-red-900/20 border border-red-200/60 dark:border-red-800/60 rounded-2xl text-sm text-red-700 dark:text-red-400 shadow-sm", children: uploadError }),
2694
+ isInitializing || isLoadingMessages ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center py-8", role: "status", "aria-label": "Loading conversation", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "h-4 w-4 rounded-full border-2 border-current border-t-transparent animate-spin", style: { color: "hsl(var(--chat-text-muted))" } }) }) : messages.length === 0 && status !== "submitted" && config?.starterPrompts && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2453
2695
  StarterMessages,
2454
2696
  {
2455
2697
  prompts: config.starterPrompts,
@@ -2458,25 +2700,67 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2458
2700
  }
2459
2701
  }
2460
2702
  ),
2703
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2704
+ ChatErrorBanner,
2705
+ {
2706
+ error: error ?? null,
2707
+ canRetry: messages.some((m) => m.role === "user"),
2708
+ onRetry: () => {
2709
+ clearError?.();
2710
+ regenerate?.();
2711
+ },
2712
+ onDismiss: clearError
2713
+ }
2714
+ ),
2461
2715
  inputPlugins.panel,
2462
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInput, { onSubmit: handleSubmit, globalDrop: true, multiple: true, accept: "image/*", children: [
2463
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInputBody, { children: [
2464
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputAttachments, { children: (attachment) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputAttachment, { data: attachment }) }),
2465
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2466
- PromptInputTextarea,
2467
- {
2468
- ref: inputRef,
2469
- onChange: (e) => setInput(e.target.value),
2470
- onKeyDown: inputPlugins.onKeyDown,
2471
- value: input
2716
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2717
+ PromptInput,
2718
+ {
2719
+ onSubmit: handleSubmit,
2720
+ globalDrop: true,
2721
+ multiple: true,
2722
+ accept: config?.features?.fileUploadAccept ?? "image/*",
2723
+ maxFileSize: config?.features?.fileUploadMaxBytes,
2724
+ onError: (err) => {
2725
+ if (err.code === "max_file_size") {
2726
+ setUploadError(
2727
+ config?.features?.fileUploadMaxBytes ? `File too large (max ${Math.floor(
2728
+ config.features.fileUploadMaxBytes / 1024 / 1024
2729
+ )} MB).` : "File too large."
2730
+ );
2731
+ } else if (err.code === "accept") {
2732
+ setUploadError("That file type is not supported.");
2733
+ } else if (err.code === "max_files") {
2734
+ setUploadError("Too many files attached.");
2472
2735
  }
2473
- )
2474
- ] }),
2475
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInputToolbar, { children: [
2476
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputTools, { children: config?.features?.fileUpload === true && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AttachButton, {}) }),
2477
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputSubmit, { disabled: !input, status })
2478
- ] })
2479
- ] })
2736
+ },
2737
+ children: [
2738
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(PromptInputBody, { children: [
2739
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptInputAttachments, { children: (attachment) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptInputAttachment, { data: attachment }) }),
2740
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2741
+ PromptInputTextarea,
2742
+ {
2743
+ ref: inputRef,
2744
+ onChange: (e) => setInput(e.target.value),
2745
+ onKeyDown: inputPlugins.onKeyDown,
2746
+ value: input
2747
+ }
2748
+ )
2749
+ ] }),
2750
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(PromptInputToolbar, { children: [
2751
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptInputTools, { children: config?.features?.fileUpload === true && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AttachButton, {}) }),
2752
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2753
+ PromptInputSubmit,
2754
+ {
2755
+ disabled: status === "streaming" || status === "submitted" ? false : !input,
2756
+ status,
2757
+ onStop: stop
2758
+ }
2759
+ )
2760
+ ] })
2761
+ ]
2762
+ }
2763
+ )
2480
2764
  ] })
2481
2765
  ]
2482
2766
  }
@@ -2484,7 +2768,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2484
2768
  }
2485
2769
 
2486
2770
  // src/ChatWidget.tsx
2487
- var import_lucide_react11 = require("lucide-react");
2771
+ var import_lucide_react13 = require("lucide-react");
2488
2772
 
2489
2773
  // src/utils/color.ts
2490
2774
  function toHslTripletIfHex(value) {
@@ -2522,7 +2806,7 @@ function toHslTripletIfHex(value) {
2522
2806
  }
2523
2807
 
2524
2808
  // src/ChatWidget.tsx
2525
- var import_jsx_runtime22 = require("react/jsx-runtime");
2809
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2526
2810
  function ChatWidget({
2527
2811
  userId,
2528
2812
  conversationId,
@@ -2539,14 +2823,15 @@ function ChatWidget({
2539
2823
  headerActions,
2540
2824
  open,
2541
2825
  onOpenChange,
2542
- inputPlugins
2826
+ inputPlugins,
2827
+ toolRenderers
2543
2828
  }) {
2544
2829
  const layout = display?.layout || "popup";
2545
2830
  const isControlled = open !== void 0;
2546
2831
  const showToggleButton = !isControlled && display?.showToggleButton !== false;
2547
2832
  const resizable = layout === "popup" && display?.resizable !== false;
2548
2833
  const size = display?.size || "default";
2549
- const [internalIsOpen, setInternalIsOpen] = (0, import_react13.useState)(
2834
+ const [internalIsOpen, setInternalIsOpen] = (0, import_react14.useState)(
2550
2835
  layout !== "popup" ? true : display?.defaultOpen || false
2551
2836
  );
2552
2837
  const isOpen = isControlled ? open : internalIsOpen;
@@ -2557,9 +2842,9 @@ function ChatWidget({
2557
2842
  setInternalIsOpen(next);
2558
2843
  }
2559
2844
  };
2560
- const [isResizing, setIsResizing] = (0, import_react13.useState)(false);
2561
- const containerRef = (0, import_react13.useRef)(null);
2562
- const customStyles = (0, import_react13.useMemo)(() => {
2845
+ const [isResizing, setIsResizing] = (0, import_react14.useState)(false);
2846
+ const containerRef = (0, import_react14.useRef)(null);
2847
+ const customStyles = (0, import_react14.useMemo)(() => {
2563
2848
  const styles = {};
2564
2849
  if (display?.width) {
2565
2850
  styles["--chat-widget-width"] = display.width;
@@ -2578,14 +2863,14 @@ function ChatWidget({
2578
2863
  }
2579
2864
  return styles;
2580
2865
  }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);
2581
- const handleMouseDown = (0, import_react13.useCallback)((e) => {
2866
+ const handleMouseDown = (0, import_react14.useCallback)((e) => {
2582
2867
  if (!resizable) return;
2583
2868
  e.preventDefault();
2584
2869
  setIsResizing(true);
2585
2870
  document.body.style.cursor = "ew-resize";
2586
2871
  document.body.style.userSelect = "none";
2587
2872
  }, [resizable]);
2588
- (0, import_react13.useEffect)(() => {
2873
+ (0, import_react14.useEffect)(() => {
2589
2874
  if (!isResizing) return;
2590
2875
  const handleMouseMove = (e) => {
2591
2876
  if (!containerRef.current) return;
@@ -2607,7 +2892,7 @@ function ChatWidget({
2607
2892
  document.removeEventListener("mouseup", handleMouseUp);
2608
2893
  };
2609
2894
  }, [isResizing]);
2610
- const config = (0, import_react13.useMemo)(() => ({
2895
+ const config = (0, import_react14.useMemo)(() => ({
2611
2896
  userId,
2612
2897
  model,
2613
2898
  systemPrompt,
@@ -2615,18 +2900,19 @@ function ChatWidget({
2615
2900
  theme,
2616
2901
  features,
2617
2902
  starterPrompts,
2618
- inputPlugins
2619
- }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts, inputPlugins]);
2903
+ inputPlugins,
2904
+ toolRenderers
2905
+ }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts, inputPlugins, toolRenderers]);
2620
2906
  const togglePosition = display?.toggleButtonPosition || { bottom: "24px", right: "24px" };
2621
2907
  const themeClass = theme?.mode === "dark" ? "dark" : "";
2622
2908
  if (layout === "inline") {
2623
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChatStorageProvider, { userId, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2909
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChatStorageProvider, { userId, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2624
2910
  "div",
2625
2911
  {
2626
2912
  ref: containerRef,
2627
2913
  className: `chat-widget-container chat-widget-inline chat-widget-content ${themeClass} ${className || ""}`,
2628
2914
  style: customStyles,
2629
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2915
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2630
2916
  ChatInterface,
2631
2917
  {
2632
2918
  id: conversationId,
@@ -2640,13 +2926,13 @@ function ChatWidget({
2640
2926
  ) });
2641
2927
  }
2642
2928
  if (layout === "page") {
2643
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChatStorageProvider, { userId, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2929
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChatStorageProvider, { userId, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2644
2930
  "div",
2645
2931
  {
2646
2932
  ref: containerRef,
2647
2933
  className: `chat-widget-container chat-widget-page chat-widget-content ${themeClass} ${className || ""}`,
2648
2934
  style: customStyles,
2649
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2935
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2650
2936
  ChatInterface,
2651
2937
  {
2652
2938
  id: conversationId,
@@ -2659,18 +2945,18 @@ function ChatWidget({
2659
2945
  }
2660
2946
  ) });
2661
2947
  }
2662
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ChatStorageProvider, { userId, children: [
2663
- showToggleButton && !isOpen && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2948
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(ChatStorageProvider, { userId, children: [
2949
+ showToggleButton && !isOpen && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2664
2950
  "button",
2665
2951
  {
2666
2952
  onClick: () => setIsOpen(true),
2667
2953
  className: "fixed z-50 rounded-full bg-primary text-primary-foreground shadow-lg hover:opacity-90 transition-all p-4",
2668
2954
  style: togglePosition,
2669
2955
  "aria-label": "Open chat",
2670
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.MessageCircle, { className: "h-6 w-6" })
2956
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.MessageCircle, { className: "h-6 w-6" })
2671
2957
  }
2672
2958
  ),
2673
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2959
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2674
2960
  "div",
2675
2961
  {
2676
2962
  ref: containerRef,
@@ -2679,7 +2965,7 @@ function ChatWidget({
2679
2965
  "data-resizing": isResizing,
2680
2966
  style: customStyles,
2681
2967
  children: [
2682
- resizable && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2968
+ resizable && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2683
2969
  "div",
2684
2970
  {
2685
2971
  onMouseDown: handleMouseDown,
@@ -2687,7 +2973,7 @@ function ChatWidget({
2687
2973
  "aria-label": "Resize chat widget"
2688
2974
  }
2689
2975
  ),
2690
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "w-full h-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2976
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "w-full h-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2691
2977
  ChatInterface,
2692
2978
  {
2693
2979
  id: conversationId,
@@ -2708,7 +2994,7 @@ function ChatWidget({
2708
2994
  var ChatWidget_default = ChatWidget;
2709
2995
 
2710
2996
  // src/hooks/use-chat-theme.ts
2711
- var import_react14 = require("react");
2997
+ var import_react15 = require("react");
2712
2998
 
2713
2999
  // src/utils/models.ts
2714
3000
  var MODELS = [
@@ -2828,13 +3114,13 @@ var defaultThemeMode = "light";
2828
3114
  function useChatTheme() {
2829
3115
  const { storageKeyPrefix } = useChatStorageKey();
2830
3116
  const keyPrefix = storageKeyPrefix ? `chat-${storageKeyPrefix}-` : "chat-";
2831
- const [theme, setTheme] = (0, import_react14.useState)(defaultTheme);
2832
- const [conversationStarters, setConversationStarters] = (0, import_react14.useState)(defaultConversationStarters);
2833
- const [model, setModel] = (0, import_react14.useState)(defaultModel);
2834
- const [systemPrompt, setSystemPrompt] = (0, import_react14.useState)(defaultSystemPrompt);
2835
- const [temperature, setTemperature] = (0, import_react14.useState)(defaultTemperature);
2836
- const [themeMode, setThemeMode] = (0, import_react14.useState)(defaultThemeMode);
2837
- (0, import_react14.useEffect)(() => {
3117
+ const [theme, setTheme] = (0, import_react15.useState)(defaultTheme);
3118
+ const [conversationStarters, setConversationStarters] = (0, import_react15.useState)(defaultConversationStarters);
3119
+ const [model, setModel] = (0, import_react15.useState)(defaultModel);
3120
+ const [systemPrompt, setSystemPrompt] = (0, import_react15.useState)(defaultSystemPrompt);
3121
+ const [temperature, setTemperature] = (0, import_react15.useState)(defaultTemperature);
3122
+ const [themeMode, setThemeMode] = (0, import_react15.useState)(defaultThemeMode);
3123
+ (0, import_react15.useEffect)(() => {
2838
3124
  const savedTheme = localStorage.getItem(`${keyPrefix}theme`);
2839
3125
  if (savedTheme) {
2840
3126
  try {
@@ -2922,7 +3208,7 @@ function useChatTheme() {
2922
3208
  window.removeEventListener("chat-theme-mode-change", handleThemeModeChange);
2923
3209
  };
2924
3210
  }, [keyPrefix]);
2925
- (0, import_react14.useEffect)(() => {
3211
+ (0, import_react15.useEffect)(() => {
2926
3212
  localStorage.setItem(`${keyPrefix}theme`, JSON.stringify(theme));
2927
3213
  const root = document.documentElement;
2928
3214
  if (themeMode === "light") {
@@ -2938,23 +3224,23 @@ function useChatTheme() {
2938
3224
  root.style.setProperty("--chat-font-size", `${theme.fontSize}px`);
2939
3225
  window.dispatchEvent(new CustomEvent("chat-theme-change", { detail: theme }));
2940
3226
  }, [theme, themeMode, keyPrefix]);
2941
- (0, import_react14.useEffect)(() => {
3227
+ (0, import_react15.useEffect)(() => {
2942
3228
  localStorage.setItem(`${keyPrefix}conversation-starters`, JSON.stringify(conversationStarters));
2943
3229
  window.dispatchEvent(new CustomEvent("chat-starters-change", { detail: conversationStarters }));
2944
3230
  }, [conversationStarters, keyPrefix]);
2945
- (0, import_react14.useEffect)(() => {
3231
+ (0, import_react15.useEffect)(() => {
2946
3232
  localStorage.setItem(`${keyPrefix}model`, model);
2947
3233
  window.dispatchEvent(new CustomEvent("chat-model-change", { detail: model }));
2948
3234
  }, [model, keyPrefix]);
2949
- (0, import_react14.useEffect)(() => {
3235
+ (0, import_react15.useEffect)(() => {
2950
3236
  localStorage.setItem(`${keyPrefix}system-prompt`, systemPrompt);
2951
3237
  window.dispatchEvent(new CustomEvent("chat-system-prompt-change", { detail: systemPrompt }));
2952
3238
  }, [systemPrompt, keyPrefix]);
2953
- (0, import_react14.useEffect)(() => {
3239
+ (0, import_react15.useEffect)(() => {
2954
3240
  localStorage.setItem(`${keyPrefix}temperature`, temperature.toString());
2955
3241
  window.dispatchEvent(new CustomEvent("chat-temperature-change", { detail: temperature }));
2956
3242
  }, [temperature, keyPrefix]);
2957
- (0, import_react14.useEffect)(() => {
3243
+ (0, import_react15.useEffect)(() => {
2958
3244
  localStorage.setItem(`${keyPrefix}theme-mode`, themeMode);
2959
3245
  window.dispatchEvent(new CustomEvent("chat-theme-mode-change", { detail: themeMode }));
2960
3246
  }, [themeMode, keyPrefix]);
@@ -3024,10 +3310,10 @@ function useChatTheme() {
3024
3310
 
3025
3311
  // src/ui/input.tsx
3026
3312
  var React3 = __toESM(require("react"));
3027
- var import_jsx_runtime23 = require("react/jsx-runtime");
3313
+ var import_jsx_runtime25 = require("react/jsx-runtime");
3028
3314
  var Input = React3.forwardRef(
3029
3315
  ({ className, type, ...props }, ref) => {
3030
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3316
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3031
3317
  "input",
3032
3318
  {
3033
3319
  type,
@@ -3045,23 +3331,23 @@ Input.displayName = "Input";
3045
3331
 
3046
3332
  // src/ui/dialog.tsx
3047
3333
  var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
3048
- var import_lucide_react12 = require("lucide-react");
3049
- var import_jsx_runtime24 = require("react/jsx-runtime");
3334
+ var import_lucide_react14 = require("lucide-react");
3335
+ var import_jsx_runtime26 = require("react/jsx-runtime");
3050
3336
  function Dialog({
3051
3337
  ...props
3052
3338
  }) {
3053
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
3339
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
3054
3340
  }
3055
3341
  function DialogPortal({
3056
3342
  ...props
3057
3343
  }) {
3058
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
3344
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
3059
3345
  }
3060
3346
  function DialogOverlay({
3061
3347
  className,
3062
3348
  ...props
3063
3349
  }) {
3064
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3350
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3065
3351
  DialogPrimitive.Overlay,
3066
3352
  {
3067
3353
  "data-slot": "dialog-overlay",
@@ -3079,9 +3365,9 @@ function DialogContent({
3079
3365
  showCloseButton = true,
3080
3366
  ...props
3081
3367
  }) {
3082
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { "data-slot": "dialog-portal", children: [
3083
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, {}),
3084
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3368
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogPortal, { "data-slot": "dialog-portal", children: [
3369
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogOverlay, {}),
3370
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3085
3371
  DialogPrimitive.Content,
3086
3372
  {
3087
3373
  "data-slot": "dialog-content",
@@ -3092,14 +3378,14 @@ function DialogContent({
3092
3378
  ...props,
3093
3379
  children: [
3094
3380
  children,
3095
- showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3381
+ showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3096
3382
  DialogPrimitive.Close,
3097
3383
  {
3098
3384
  "data-slot": "dialog-close",
3099
3385
  className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3100
3386
  children: [
3101
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.XIcon, {}),
3102
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "sr-only", children: "Close" })
3387
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react14.XIcon, {}),
3388
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "sr-only", children: "Close" })
3103
3389
  ]
3104
3390
  }
3105
3391
  )
@@ -3109,7 +3395,7 @@ function DialogContent({
3109
3395
  ] });
3110
3396
  }
3111
3397
  function DialogHeader({ className, ...props }) {
3112
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3398
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3113
3399
  "div",
3114
3400
  {
3115
3401
  "data-slot": "dialog-header",
@@ -3122,7 +3408,7 @@ function DialogTitle({
3122
3408
  className,
3123
3409
  ...props
3124
3410
  }) {
3125
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3411
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3126
3412
  DialogPrimitive.Title,
3127
3413
  {
3128
3414
  "data-slot": "dialog-title",
@@ -3135,7 +3421,7 @@ function DialogDescription({
3135
3421
  className,
3136
3422
  ...props
3137
3423
  }) {
3138
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3424
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3139
3425
  DialogPrimitive.Description,
3140
3426
  {
3141
3427
  "data-slot": "dialog-description",
@@ -3157,6 +3443,11 @@ function DialogDescription({
3157
3443
  Input,
3158
3444
  StarterMessageItem,
3159
3445
  StarterMessages,
3446
+ Tool,
3447
+ ToolContent,
3448
+ ToolHeader,
3449
+ ToolInput,
3450
+ ToolOutput,
3160
3451
  fontOptions,
3161
3452
  useChatStorageKey,
3162
3453
  useChatTheme