@mordn/chat-widget 0.6.2 → 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)
728
- }
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" })
796
+ onClick: () => openAttachment(attachment)
735
797
  }
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
@@ -750,6 +831,7 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
750
831
  const [loading, setLoading] = (0, import_react3.useState)(false);
751
832
  const debounceRef = (0, import_react3.useRef)(null);
752
833
  const requestIdRef = (0, import_react3.useRef)(0);
834
+ const sessionValidatedRef = (0, import_react3.useRef)(false);
753
835
  const pluginsByTrigger = (0, import_react3.useMemo)(() => {
754
836
  const map = /* @__PURE__ */ new Map();
755
837
  for (const p of plugins ?? []) {
@@ -766,9 +848,14 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
766
848
  return value.slice(active.triggerIndex + 1, cursor);
767
849
  }, [active, value, textareaRef]);
768
850
  (0, import_react3.useEffect)(() => {
769
- if (!active) return;
770
- const ta = textareaRef.current;
771
- if (!ta) return;
851
+ if (!active) {
852
+ sessionValidatedRef.current = false;
853
+ return;
854
+ }
855
+ if (value[active.triggerIndex] === active.plugin.trigger) {
856
+ sessionValidatedRef.current = true;
857
+ }
858
+ if (!sessionValidatedRef.current) return;
772
859
  if (value[active.triggerIndex] !== active.plugin.trigger) {
773
860
  setActive(null);
774
861
  return;
@@ -776,7 +863,7 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
776
863
  if (/\s/.test(query)) {
777
864
  setActive(null);
778
865
  }
779
- }, [active, value, query, textareaRef]);
866
+ }, [active, value, query]);
780
867
  (0, import_react3.useEffect)(() => {
781
868
  if (!active) {
782
869
  setItems([]);
@@ -784,13 +871,20 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
784
871
  return;
785
872
  }
786
873
  if (debounceRef.current) clearTimeout(debounceRef.current);
787
- setLoading(true);
788
874
  const reqId = ++requestIdRef.current;
875
+ const result = active.plugin.fetch(query);
876
+ if (Array.isArray(result)) {
877
+ setItems(result);
878
+ setHighlight(0);
879
+ setLoading(false);
880
+ return;
881
+ }
882
+ setLoading(true);
789
883
  debounceRef.current = setTimeout(async () => {
790
884
  try {
791
- const result = await active.plugin.fetch(query);
885
+ const items2 = await result;
792
886
  if (reqId !== requestIdRef.current) return;
793
- setItems(result);
887
+ setItems(items2);
794
888
  setHighlight(0);
795
889
  } catch (err) {
796
890
  console.error("[input-plugin] fetch failed:", err);
@@ -871,14 +965,8 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
871
965
  },
872
966
  [active, items, highlight, selectItem, close, pluginsByTrigger, value]
873
967
  );
874
- (0, import_react3.useEffect)(() => {
875
- if (!active) return;
876
- if (value[active.triggerIndex] !== active.plugin.trigger) {
877
- close();
878
- }
879
- }, [value, active, close]);
880
- const popover = active && (loading || items.length > 0 || active.plugin.emptyText) ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
881
- PluginPopover,
968
+ const panel = active ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
969
+ PluginPanel,
882
970
  {
883
971
  plugin: active.plugin,
884
972
  items,
@@ -888,65 +976,271 @@ function useInputPlugins({ textareaRef, value, setValue, plugins }) {
888
976
  onSelect: selectItem
889
977
  }
890
978
  ) : null;
891
- return { onKeyDown, popover, isOpen: !!active };
979
+ return { onKeyDown, panel, isOpen: !!active };
892
980
  }
893
- function PluginPopover({ plugin, items, loading, highlight, onHover, onSelect }) {
981
+ function PluginPanel({ plugin, items, loading, highlight, onHover, onSelect }) {
982
+ const viewportRef = (0, import_react3.useRef)(null);
983
+ const itemRefs = (0, import_react3.useRef)([]);
984
+ (0, import_react3.useEffect)(() => {
985
+ const btn = itemRefs.current[highlight];
986
+ const viewport = viewportRef.current;
987
+ if (!btn || !viewport) return;
988
+ const btnRect = btn.getBoundingClientRect();
989
+ const viewRect = viewport.getBoundingClientRect();
990
+ if (btnRect.top < viewRect.top) {
991
+ viewport.scrollTop -= viewRect.top - btnRect.top;
992
+ } else if (btnRect.bottom > viewRect.bottom) {
993
+ viewport.scrollTop += btnRect.bottom - viewRect.bottom;
994
+ }
995
+ }, [highlight]);
894
996
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
895
997
  "div",
896
998
  {
897
999
  role: "listbox",
898
- className: cn(
899
- "absolute bottom-full left-0 right-0 mb-2 z-30",
900
- "rounded-md border border-border bg-popover text-popover-foreground shadow-md",
901
- "max-h-64 overflow-y-auto"
902
- ),
1000
+ className: "rounded-t-xl bg-[hsl(var(--chat-background))] overflow-hidden mx-auto",
903
1001
  onMouseDown: (e) => e.preventDefault(),
1002
+ style: {
1003
+ width: "96%",
1004
+ borderTop: "1px solid var(--chat-divider)",
1005
+ borderLeft: "1px solid var(--chat-divider)",
1006
+ borderRight: "1px solid var(--chat-divider)",
1007
+ // Pull down 1px so our bottom edge overlaps the form's top
1008
+ // border, removing the visible seam between the two surfaces.
1009
+ marginBottom: -1
1010
+ },
1011
+ children: [
1012
+ plugin.heading && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1013
+ "div",
1014
+ {
1015
+ className: "px-3 py-1.5 text-[11px] font-semibold uppercase tracking-wide",
1016
+ style: {
1017
+ color: "hsl(var(--chat-text)/0.5)",
1018
+ borderBottom: "1px solid var(--chat-divider)"
1019
+ },
1020
+ children: plugin.heading
1021
+ }
1022
+ ),
1023
+ loading && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1024
+ "div",
1025
+ {
1026
+ className: "px-3 py-2 text-[13px]",
1027
+ style: { color: "hsl(var(--chat-text)/0.5)" },
1028
+ children: "Loading\u2026"
1029
+ }
1030
+ ),
1031
+ !loading && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1032
+ "div",
1033
+ {
1034
+ className: "px-3 py-2 text-[13px]",
1035
+ style: { color: "hsl(var(--chat-text)/0.5)" },
1036
+ children: plugin.emptyText ?? "No results"
1037
+ }
1038
+ ),
1039
+ items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1040
+ "div",
1041
+ {
1042
+ ref: viewportRef,
1043
+ className: "max-h-[200px] overflow-y-auto",
1044
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "py-1", children: items.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1045
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1046
+ "button",
1047
+ {
1048
+ ref: (el) => {
1049
+ itemRefs.current[idx] = el;
1050
+ },
1051
+ type: "button",
1052
+ role: "option",
1053
+ "aria-selected": idx === highlight,
1054
+ onMouseEnter: () => onHover(idx),
1055
+ onClick: () => onSelect(item),
1056
+ className: cn(
1057
+ "w-full text-left px-3 py-2",
1058
+ "flex items-center justify-between gap-3",
1059
+ "transition-colors duration-150 ease-out",
1060
+ "cursor-pointer"
1061
+ ),
1062
+ style: {
1063
+ backgroundColor: idx === highlight ? "hsl(var(--chat-text)/0.06)" : "transparent"
1064
+ },
1065
+ children: [
1066
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1067
+ "span",
1068
+ {
1069
+ className: "text-[13px] truncate",
1070
+ style: { color: "hsl(var(--chat-text)/0.85)" },
1071
+ children: item.label
1072
+ }
1073
+ ),
1074
+ item.sublabel && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1075
+ "span",
1076
+ {
1077
+ className: "text-[11px] flex-shrink-0",
1078
+ style: { color: "hsl(var(--chat-text)/0.4)" },
1079
+ children: item.sublabel
1080
+ }
1081
+ )
1082
+ ]
1083
+ }
1084
+ ),
1085
+ idx < items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1086
+ "div",
1087
+ {
1088
+ className: "h-px mx-3",
1089
+ style: { backgroundColor: "var(--chat-divider)" }
1090
+ }
1091
+ )
1092
+ ] }, item.id)) })
1093
+ }
1094
+ )
1095
+ ]
1096
+ }
1097
+ );
1098
+ }
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,
904
1121
  children: [
905
- plugin.heading && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "px-3 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground border-b border-border", children: plugin.heading }),
906
- loading && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "px-3 py-2 text-xs text-muted-foreground", children: "Loading\u2026" }),
907
- !loading && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "px-3 py-2 text-xs text-muted-foreground", children: plugin.emptyText ?? "No results" }),
908
- items.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
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)(
909
1131
  "button",
910
1132
  {
911
1133
  type: "button",
912
- role: "option",
913
- "aria-selected": idx === highlight,
914
- onMouseEnter: () => onHover(idx),
915
- onClick: () => onSelect(item),
916
- className: cn(
917
- "w-full text-left px-3 py-2 text-sm transition-colors",
918
- "flex flex-col gap-0.5",
919
- idx === highlight ? "bg-accent text-accent-foreground" : "hover:bg-muted"
920
- ),
921
- children: [
922
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-medium leading-tight", children: item.label }),
923
- item.sublabel && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-[11px] text-muted-foreground leading-tight", children: item.sublabel })
924
- ]
925
- },
926
- item.id
927
- ))
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
+ )
928
1151
  ]
929
1152
  }
930
1153
  );
931
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
+ }
932
1226
 
933
1227
  // src/components/interface.tsx
934
- var import_react10 = require("react");
935
- var import_lucide_react10 = require("lucide-react");
936
1228
  var import_react11 = require("react");
937
- 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");
938
1232
  var import_ai = require("ai");
939
1233
 
940
1234
  // src/components/response.tsx
941
- var import_react5 = require("react");
1235
+ var import_react6 = require("react");
942
1236
  var import_streamdown = require("streamdown");
943
1237
 
944
1238
  // src/hooks/use-code-scroll.ts
945
- var import_react4 = require("react");
1239
+ var import_react5 = require("react");
946
1240
  function useCodeBlockAutoScroll(isStreaming) {
947
- const observerRef = (0, import_react4.useRef)(null);
948
- const containerRef = (0, import_react4.useRef)(null);
949
- (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)(() => {
950
1244
  if (!isStreaming || !containerRef.current) {
951
1245
  if (observerRef.current) {
952
1246
  observerRef.current.disconnect();
@@ -976,11 +1270,11 @@ function useCodeBlockAutoScroll(isStreaming) {
976
1270
  }
977
1271
 
978
1272
  // src/components/response.tsx
979
- var import_jsx_runtime11 = require("react/jsx-runtime");
980
- var Response = (0, import_react5.memo)(
1273
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1274
+ var Response = (0, import_react6.memo)(
981
1275
  ({ className, isStreaming = false, ...props }) => {
982
1276
  const containerRef = useCodeBlockAutoScroll(isStreaming);
983
- 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)(
984
1278
  import_streamdown.Streamdown,
985
1279
  {
986
1280
  className: cn(
@@ -997,16 +1291,16 @@ Response.displayName = "Response";
997
1291
 
998
1292
  // src/ui/collapsible.tsx
999
1293
  var CollapsiblePrimitive = __toESM(require("@radix-ui/react-collapsible"));
1000
- var import_jsx_runtime12 = require("react/jsx-runtime");
1294
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1001
1295
  function Collapsible({
1002
1296
  ...props
1003
1297
  }) {
1004
- 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 });
1005
1299
  }
1006
1300
  function CollapsibleTrigger2({
1007
1301
  ...props
1008
1302
  }) {
1009
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1303
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1010
1304
  CollapsiblePrimitive.CollapsibleTrigger,
1011
1305
  {
1012
1306
  "data-slot": "collapsible-trigger",
@@ -1017,7 +1311,7 @@ function CollapsibleTrigger2({
1017
1311
  function CollapsibleContent2({
1018
1312
  ...props
1019
1313
  }) {
1020
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1314
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1021
1315
  CollapsiblePrimitive.CollapsibleContent,
1022
1316
  {
1023
1317
  "data-slot": "collapsible-content",
@@ -1027,9 +1321,9 @@ function CollapsibleContent2({
1027
1321
  }
1028
1322
 
1029
1323
  // src/components/sources.tsx
1030
- var import_lucide_react6 = require("lucide-react");
1031
- var import_jsx_runtime13 = require("react/jsx-runtime");
1032
- 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)(
1033
1327
  Collapsible,
1034
1328
  {
1035
1329
  className: cn("not-prose mb-4 text-primary text-xs", className),
@@ -1041,25 +1335,25 @@ var SourcesTrigger = ({
1041
1335
  count,
1042
1336
  children,
1043
1337
  ...props
1044
- }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1338
+ }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1045
1339
  CollapsibleTrigger2,
1046
1340
  {
1047
1341
  className: cn("flex items-center gap-2", className),
1048
1342
  ...props,
1049
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1050
- /* @__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: [
1051
1345
  "Used ",
1052
1346
  count,
1053
1347
  " sources"
1054
1348
  ] }),
1055
- /* @__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" })
1056
1350
  ] })
1057
1351
  }
1058
1352
  );
1059
1353
  var SourcesContent = ({
1060
1354
  className,
1061
1355
  ...props
1062
- }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1356
+ }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1063
1357
  CollapsibleContent2,
1064
1358
  {
1065
1359
  className: cn(
@@ -1070,7 +1364,7 @@ var SourcesContent = ({
1070
1364
  ...props
1071
1365
  }
1072
1366
  );
1073
- 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)(
1074
1368
  "a",
1075
1369
  {
1076
1370
  className: "flex items-center gap-2",
@@ -1078,21 +1372,21 @@ var Source = ({ href, title, children, ...props }) => /* @__PURE__ */ (0, import
1078
1372
  rel: "noreferrer",
1079
1373
  target: "_blank",
1080
1374
  ...props,
1081
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1082
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.BookIcon, { className: "h-4 w-4" }),
1083
- /* @__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 })
1084
1378
  ] })
1085
1379
  }
1086
1380
  );
1087
1381
 
1088
1382
  // src/components/reasoning.tsx
1089
1383
  var import_react_use_controllable_state = require("@radix-ui/react-use-controllable-state");
1090
- var import_lucide_react7 = require("lucide-react");
1091
- var import_react6 = require("react");
1092
- var import_jsx_runtime14 = require("react/jsx-runtime");
1093
- 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);
1094
1388
  var useReasoning = () => {
1095
- const context = (0, import_react6.useContext)(ReasoningContext);
1389
+ const context = (0, import_react7.useContext)(ReasoningContext);
1096
1390
  if (!context) {
1097
1391
  throw new Error("Reasoning components must be used within Reasoning");
1098
1392
  }
@@ -1100,7 +1394,7 @@ var useReasoning = () => {
1100
1394
  };
1101
1395
  var AUTO_CLOSE_DELAY = 1e3;
1102
1396
  var MS_IN_S = 1e3;
1103
- var Reasoning = (0, import_react6.memo)(
1397
+ var Reasoning = (0, import_react7.memo)(
1104
1398
  ({
1105
1399
  className,
1106
1400
  isStreaming = false,
@@ -1120,9 +1414,9 @@ var Reasoning = (0, import_react6.memo)(
1120
1414
  prop: durationProp,
1121
1415
  defaultProp: void 0
1122
1416
  });
1123
- const [hasAutoClosed, setHasAutoClosed] = (0, import_react6.useState)(false);
1124
- const [startTime, setStartTime] = (0, import_react6.useState)(null);
1125
- (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)(() => {
1126
1420
  if (isStreaming) {
1127
1421
  if (startTime === null) {
1128
1422
  setStartTime(Date.now());
@@ -1132,7 +1426,7 @@ var Reasoning = (0, import_react6.memo)(
1132
1426
  setStartTime(null);
1133
1427
  }
1134
1428
  }, [isStreaming, startTime, setDuration]);
1135
- (0, import_react6.useEffect)(() => {
1429
+ (0, import_react7.useEffect)(() => {
1136
1430
  if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed && durationProp !== void 0) {
1137
1431
  const timer = setTimeout(() => {
1138
1432
  setIsOpen(false);
@@ -1144,11 +1438,11 @@ var Reasoning = (0, import_react6.memo)(
1144
1438
  const handleOpenChange = (newOpen) => {
1145
1439
  setIsOpen(newOpen);
1146
1440
  };
1147
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1441
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1148
1442
  ReasoningContext.Provider,
1149
1443
  {
1150
1444
  value: { isStreaming, isOpen, setIsOpen, duration },
1151
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1445
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1152
1446
  Collapsible,
1153
1447
  {
1154
1448
  className: cn("not-prose", className),
@@ -1164,24 +1458,24 @@ var Reasoning = (0, import_react6.memo)(
1164
1458
  );
1165
1459
  var getThinkingMessage = (isStreaming, duration) => {
1166
1460
  if (isStreaming) {
1167
- 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..." });
1168
1462
  }
1169
1463
  if (duration === void 0) {
1170
- 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" });
1171
1465
  }
1172
1466
  if (duration === 0) {
1173
- 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" });
1174
1468
  }
1175
- 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: [
1176
1470
  "Thought for ",
1177
1471
  duration,
1178
1472
  " seconds"
1179
1473
  ] });
1180
1474
  };
1181
- var ReasoningTrigger = (0, import_react6.memo)(
1475
+ var ReasoningTrigger = (0, import_react7.memo)(
1182
1476
  ({ className, children, ...props }) => {
1183
1477
  const { isStreaming, isOpen, duration } = useReasoning();
1184
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1478
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1185
1479
  CollapsibleTrigger2,
1186
1480
  {
1187
1481
  className: cn(
@@ -1189,11 +1483,11 @@ var ReasoningTrigger = (0, import_react6.memo)(
1189
1483
  className
1190
1484
  ),
1191
1485
  ...props,
1192
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1193
- /* @__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" }),
1194
1488
  getThinkingMessage(isStreaming, duration),
1195
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1196
- import_lucide_react7.ChevronDownIcon,
1489
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1490
+ import_lucide_react9.ChevronDownIcon,
1197
1491
  {
1198
1492
  className: cn(
1199
1493
  "size-4 flex-shrink-0 transition-transform ml-1",
@@ -1206,8 +1500,8 @@ var ReasoningTrigger = (0, import_react6.memo)(
1206
1500
  );
1207
1501
  }
1208
1502
  );
1209
- var ReasoningContent = (0, import_react6.memo)(
1210
- ({ 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)(
1211
1505
  CollapsibleContent2,
1212
1506
  {
1213
1507
  className: cn(
@@ -1216,7 +1510,7 @@ var ReasoningContent = (0, import_react6.memo)(
1216
1510
  className
1217
1511
  ),
1218
1512
  ...props,
1219
- 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 })
1220
1514
  }
1221
1515
  )
1222
1516
  );
@@ -1225,8 +1519,8 @@ ReasoningTrigger.displayName = "ReasoningTrigger";
1225
1519
  ReasoningContent.displayName = "ReasoningContent";
1226
1520
 
1227
1521
  // src/components/loader.tsx
1228
- var import_jsx_runtime15 = require("react/jsx-runtime");
1229
- 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)(
1230
1524
  "svg",
1231
1525
  {
1232
1526
  height: size,
@@ -1235,10 +1529,10 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1235
1529
  viewBox: "0 0 16 16",
1236
1530
  width: size,
1237
1531
  children: [
1238
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("title", { children: "Loader" }),
1239
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { clipPath: "url(#clip0_2393_1490)", children: [
1240
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M8 0V4", stroke: "currentColor", strokeWidth: "1.5" }),
1241
- /* @__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)(
1242
1536
  "path",
1243
1537
  {
1244
1538
  d: "M8 16V12",
@@ -1247,7 +1541,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1247
1541
  strokeWidth: "1.5"
1248
1542
  }
1249
1543
  ),
1250
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1544
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1251
1545
  "path",
1252
1546
  {
1253
1547
  d: "M3.29773 1.52783L5.64887 4.7639",
@@ -1256,7 +1550,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1256
1550
  strokeWidth: "1.5"
1257
1551
  }
1258
1552
  ),
1259
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1553
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1260
1554
  "path",
1261
1555
  {
1262
1556
  d: "M12.7023 1.52783L10.3511 4.7639",
@@ -1265,7 +1559,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1265
1559
  strokeWidth: "1.5"
1266
1560
  }
1267
1561
  ),
1268
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1562
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1269
1563
  "path",
1270
1564
  {
1271
1565
  d: "M12.7023 14.472L10.3511 11.236",
@@ -1274,7 +1568,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1274
1568
  strokeWidth: "1.5"
1275
1569
  }
1276
1570
  ),
1277
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1571
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1278
1572
  "path",
1279
1573
  {
1280
1574
  d: "M3.29773 14.472L5.64887 11.236",
@@ -1283,7 +1577,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1283
1577
  strokeWidth: "1.5"
1284
1578
  }
1285
1579
  ),
1286
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1580
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1287
1581
  "path",
1288
1582
  {
1289
1583
  d: "M15.6085 5.52783L11.8043 6.7639",
@@ -1292,7 +1586,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1292
1586
  strokeWidth: "1.5"
1293
1587
  }
1294
1588
  ),
1295
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1589
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1296
1590
  "path",
1297
1591
  {
1298
1592
  d: "M0.391602 10.472L4.19583 9.23598",
@@ -1301,7 +1595,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1301
1595
  strokeWidth: "1.5"
1302
1596
  }
1303
1597
  ),
1304
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1598
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1305
1599
  "path",
1306
1600
  {
1307
1601
  d: "M15.6085 10.4722L11.8043 9.2361",
@@ -1310,7 +1604,7 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1310
1604
  strokeWidth: "1.5"
1311
1605
  }
1312
1606
  ),
1313
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1607
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1314
1608
  "path",
1315
1609
  {
1316
1610
  d: "M0.391602 5.52783L4.19583 6.7639",
@@ -1320,11 +1614,11 @@ var LoaderIcon = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx
1320
1614
  }
1321
1615
  )
1322
1616
  ] }),
1323
- /* @__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" }) }) })
1324
1618
  ]
1325
1619
  }
1326
1620
  );
1327
- 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)(
1328
1622
  "div",
1329
1623
  {
1330
1624
  className: cn(
@@ -1332,14 +1626,14 @@ var Loader = ({ className, size = 16, ...props }) => /* @__PURE__ */ (0, import_
1332
1626
  className
1333
1627
  ),
1334
1628
  ...props,
1335
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LoaderIcon, { size })
1629
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LoaderIcon, { size })
1336
1630
  }
1337
1631
  );
1338
1632
 
1339
1633
  // src/ui/badge.tsx
1340
1634
  var import_react_slot2 = require("@radix-ui/react-slot");
1341
1635
  var import_class_variance_authority3 = require("class-variance-authority");
1342
- var import_jsx_runtime16 = require("react/jsx-runtime");
1636
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1343
1637
  var badgeVariants = (0, import_class_variance_authority3.cva)(
1344
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",
1345
1639
  {
@@ -1363,7 +1657,7 @@ function Badge({
1363
1657
  ...props
1364
1658
  }) {
1365
1659
  const Comp = asChild ? import_react_slot2.Slot : "span";
1366
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1660
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1367
1661
  Comp,
1368
1662
  {
1369
1663
  "data-slot": "badge",
@@ -1374,16 +1668,16 @@ function Badge({
1374
1668
  }
1375
1669
 
1376
1670
  // src/components/tool.tsx
1377
- var import_lucide_react9 = require("lucide-react");
1378
- var import_react8 = require("react");
1671
+ var import_lucide_react11 = require("lucide-react");
1672
+ var import_react9 = require("react");
1379
1673
 
1380
1674
  // src/components/code-block.tsx
1381
- var import_lucide_react8 = require("lucide-react");
1382
- var import_react7 = require("react");
1675
+ var import_lucide_react10 = require("lucide-react");
1676
+ var import_react8 = require("react");
1383
1677
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
1384
1678
  var import_prism = require("react-syntax-highlighter/dist/esm/styles/prism");
1385
- var import_jsx_runtime17 = require("react/jsx-runtime");
1386
- var CodeBlockContext = (0, import_react7.createContext)({
1679
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1680
+ var CodeBlockContext = (0, import_react8.createContext)({
1387
1681
  code: ""
1388
1682
  });
1389
1683
  var CodeBlock = ({
@@ -1393,7 +1687,7 @@ var CodeBlock = ({
1393
1687
  className,
1394
1688
  children,
1395
1689
  ...props
1396
- }) => /* @__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)(
1397
1691
  "div",
1398
1692
  {
1399
1693
  className: cn(
@@ -1401,8 +1695,8 @@ var CodeBlock = ({
1401
1695
  className
1402
1696
  ),
1403
1697
  ...props,
1404
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative max-h-96 overflow-y-auto", children: [
1405
- /* @__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)(
1406
1700
  import_react_syntax_highlighter.Prism,
1407
1701
  {
1408
1702
  className: "overflow-hidden dark:hidden",
@@ -1428,7 +1722,7 @@ var CodeBlock = ({
1428
1722
  children: code
1429
1723
  }
1430
1724
  ),
1431
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1725
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1432
1726
  import_react_syntax_highlighter.Prism,
1433
1727
  {
1434
1728
  className: "hidden overflow-hidden dark:block",
@@ -1454,36 +1748,42 @@ var CodeBlock = ({
1454
1748
  children: code
1455
1749
  }
1456
1750
  ),
1457
- 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 })
1458
1752
  ] })
1459
1753
  }
1460
1754
  ) });
1461
1755
 
1462
1756
  // src/components/tool.tsx
1463
- var import_jsx_runtime18 = require("react/jsx-runtime");
1464
- 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)(
1465
1759
  Collapsible,
1466
1760
  {
1467
1761
  className: cn("not-prose w-full rounded-md border border-[var(--chat-divider)]", className),
1468
1762
  ...props
1469
1763
  }
1470
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
+ };
1471
1783
  var getStatusBadge = (status) => {
1472
- const labels = {
1473
- "input-streaming": "Pending",
1474
- "input-available": "Running",
1475
- "output-available": "Completed",
1476
- "output-error": "Error"
1477
- };
1478
- const icons = {
1479
- "input-streaming": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.CircleIcon, { className: "size-4" }),
1480
- "input-available": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ClockIcon, { className: "size-4 animate-pulse" }),
1481
- "output-available": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.CheckCircleIcon, { className: "size-4 text-green-600" }),
1482
- "output-error": /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.XCircleIcon, { className: "size-4 text-red-600" })
1483
- };
1484
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Badge, { className: "gap-1.5 rounded-full text-xs", variant: "secondary", children: [
1485
- icons[status],
1486
- 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]
1487
1787
  ] });
1488
1788
  };
1489
1789
  var ToolHeader = ({
@@ -1493,7 +1793,7 @@ var ToolHeader = ({
1493
1793
  toolName,
1494
1794
  state,
1495
1795
  ...props
1496
- }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1796
+ }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1497
1797
  CollapsibleTrigger2,
1498
1798
  {
1499
1799
  className: cn(
@@ -1502,16 +1802,16 @@ var ToolHeader = ({
1502
1802
  ),
1503
1803
  ...props,
1504
1804
  children: [
1505
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
1506
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.WrenchIcon, { className: "size-4 text-muted-foreground" }),
1507
- /* @__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("-") }),
1508
1808
  getStatusBadge(state)
1509
1809
  ] }),
1510
- /* @__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" })
1511
1811
  ]
1512
1812
  }
1513
1813
  );
1514
- var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1814
+ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1515
1815
  CollapsibleContent2,
1516
1816
  {
1517
1817
  className: cn(
@@ -1521,9 +1821,9 @@ var ToolContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_ru
1521
1821
  ...props
1522
1822
  }
1523
1823
  );
1524
- var ToolInput = ({ className, input, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cn("space-y-2 overflow-hidden p-2", className), ...props, children: [
1525
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Parameters" }),
1526
- /* @__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" }) })
1527
1827
  ] });
1528
1828
  var ToolOutput = ({
1529
1829
  className,
@@ -1534,15 +1834,15 @@ var ToolOutput = ({
1534
1834
  if (!(output || errorText)) {
1535
1835
  return null;
1536
1836
  }
1537
- let Output = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: output });
1538
- if (typeof output === "object" && !(0, import_react8.isValidElement)(output)) {
1539
- 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" });
1540
1840
  } else if (typeof output === "string") {
1541
- 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" });
1542
1842
  }
1543
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cn("space-y-2 p-2", className), ...props, children: [
1544
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: errorText ? "Error" : "Result" }),
1545
- /* @__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)(
1546
1846
  "div",
1547
1847
  {
1548
1848
  className: cn(
@@ -1550,7 +1850,7 @@ var ToolOutput = ({
1550
1850
  errorText ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground"
1551
1851
  ),
1552
1852
  children: [
1553
- errorText && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: errorText }),
1853
+ errorText && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: errorText }),
1554
1854
  Output
1555
1855
  ]
1556
1856
  }
@@ -1559,7 +1859,7 @@ var ToolOutput = ({
1559
1859
  };
1560
1860
 
1561
1861
  // src/components/suggestion2.tsx
1562
- var import_jsx_runtime19 = require("react/jsx-runtime");
1862
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1563
1863
  function StarterMessages({
1564
1864
  className,
1565
1865
  prompts,
@@ -1567,7 +1867,7 @@ function StarterMessages({
1567
1867
  ...props
1568
1868
  }) {
1569
1869
  if (prompts.length === 0) return null;
1570
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1870
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1571
1871
  "div",
1572
1872
  {
1573
1873
  className: cn(
@@ -1575,8 +1875,8 @@ function StarterMessages({
1575
1875
  className
1576
1876
  ),
1577
1877
  ...props,
1578
- children: prompts.map((prompt, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
1579
- /* @__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)(
1580
1880
  StarterMessageItem,
1581
1881
  {
1582
1882
  prompt,
@@ -1586,7 +1886,7 @@ function StarterMessages({
1586
1886
  index < prompts.length - 1 && // 1px-tall element used as a divider — same --chat-divider token
1587
1887
  // every other separator in the widget uses, so consumers only
1588
1888
  // need to override one variable to recolour all of them.
1589
- /* @__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)" } })
1590
1890
  ] }, index))
1591
1891
  }
1592
1892
  );
@@ -1597,7 +1897,7 @@ function StarterMessageItem({
1597
1897
  onClick,
1598
1898
  ...props
1599
1899
  }) {
1600
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1900
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1601
1901
  "button",
1602
1902
  {
1603
1903
  type: "button",
@@ -1612,17 +1912,17 @@ function StarterMessageItem({
1612
1912
  ),
1613
1913
  ...props,
1614
1914
  children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[13px] text-[hsl(var(--chat-text)/0.7)]", children: prompt.title }),
1616
- 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 })
1617
1917
  ]
1618
1918
  }
1619
1919
  );
1620
1920
  }
1621
1921
 
1622
1922
  // src/contexts/chat-storage-context.tsx
1623
- var import_react9 = require("react");
1624
- var import_jsx_runtime20 = require("react/jsx-runtime");
1625
- 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)({
1626
1926
  storageKeyPrefix: ""
1627
1927
  });
1628
1928
  function ChatStorageProvider({
@@ -1630,46 +1930,46 @@ function ChatStorageProvider({
1630
1930
  userId
1631
1931
  }) {
1632
1932
  const storageKeyPrefix = userId || "";
1633
- 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 });
1634
1934
  }
1635
1935
  function useChatStorageKey() {
1636
- return (0, import_react9.useContext)(ChatStorageContext);
1936
+ return (0, import_react10.useContext)(ChatStorageContext);
1637
1937
  }
1638
1938
 
1639
1939
  // src/components/interface.tsx
1640
- var import_jsx_runtime21 = require("react/jsx-runtime");
1940
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1641
1941
  function ChatInterface({ id, initialMessages, config, onClose, headerActions } = {}) {
1642
1942
  const { storageKeyPrefix } = useChatStorageKey();
1643
1943
  const storageKey = (key) => storageKeyPrefix ? `chat-${storageKeyPrefix}-${key}` : `chat-${key}`;
1644
1944
  const themeMode = config?.theme?.mode || "light";
1645
- const [input, setInput] = (0, import_react10.useState)("");
1646
- const inputRef = (0, import_react10.useRef)(null);
1945
+ const [input, setInput] = (0, import_react11.useState)("");
1946
+ const inputRef = (0, import_react11.useRef)(null);
1647
1947
  const inputPlugins = useInputPlugins({
1648
1948
  textareaRef: inputRef,
1649
1949
  value: input,
1650
1950
  setValue: setInput,
1651
1951
  plugins: config?.inputPlugins
1652
1952
  });
1653
- const [showHistory, setShowHistory] = (0, import_react10.useState)(false);
1654
- const [conversations, setConversations] = (0, import_react10.useState)([]);
1655
- const [loadingHistory, setLoadingHistory] = (0, import_react10.useState)(false);
1656
- const [historyLoaded, setHistoryLoaded] = (0, import_react10.useState)(false);
1657
- const [searchQuery, setSearchQuery] = (0, import_react10.useState)("");
1658
- const [uploadError, setUploadError] = (0, import_react10.useState)(null);
1659
- (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)(() => {
1660
1960
  if (uploadError) {
1661
1961
  const timeoutId = setTimeout(() => setUploadError(null), 5e3);
1662
1962
  return () => clearTimeout(timeoutId);
1663
1963
  }
1664
1964
  }, [uploadError]);
1665
- const [tabs, setTabs] = (0, import_react10.useState)([]);
1666
- const [activeTabId, setActiveTabId] = (0, import_react10.useState)("");
1667
- const [initialTabCreated, setInitialTabCreated] = (0, import_react10.useState)(false);
1668
- const [isInitializing, setIsInitializing] = (0, import_react10.useState)(true);
1669
- const [isLoadingMessages, setIsLoadingMessages] = (0, import_react10.useState)(false);
1670
- const lastSyncedTabId = (0, import_react10.useRef)("");
1671
- const hasInitialized = (0, import_react10.useRef)(false);
1672
- 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)({
1673
1973
  id: activeTabId || "temp-id",
1674
1974
  transport: new import_ai.DefaultChatTransport({
1675
1975
  api: "/api/chat",
@@ -1716,8 +2016,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1716
2016
  mediaType: uploadResult.mediaType,
1717
2017
  size: uploadResult.size
1718
2018
  };
1719
- } catch (error) {
1720
- console.error(`Error uploading ${file.filename}:`, error);
2019
+ } catch (error2) {
2020
+ console.error(`Error uploading ${file.filename}:`, error2);
1721
2021
  return null;
1722
2022
  }
1723
2023
  });
@@ -1734,10 +2034,10 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1734
2034
  setUploadError(warnMsg);
1735
2035
  console.warn(warnMsg);
1736
2036
  }
1737
- } catch (error) {
2037
+ } catch (error2) {
1738
2038
  const errorMsg = "Error uploading files. Please try again.";
1739
2039
  setUploadError(errorMsg);
1740
- console.error("Error in file upload process:", error);
2040
+ console.error("Error in file upload process:", error2);
1741
2041
  return;
1742
2042
  }
1743
2043
  }
@@ -1758,12 +2058,12 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1758
2058
  };
1759
2059
  const AttachButton = () => {
1760
2060
  const attachments = usePromptInputAttachments();
1761
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2061
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1762
2062
  PromptInputButton,
1763
2063
  {
1764
2064
  variant: "ghost",
1765
2065
  onClick: () => attachments.openFileDialog(),
1766
- 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" })
1767
2067
  }
1768
2068
  );
1769
2069
  };
@@ -1786,8 +2086,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1786
2086
  } else {
1787
2087
  console.error("Error loading messages:", response.status, response.statusText);
1788
2088
  }
1789
- } catch (error) {
1790
- console.error("Error loading conversation:", error);
2089
+ } catch (error2) {
2090
+ console.error("Error loading conversation:", error2);
1791
2091
  }
1792
2092
  };
1793
2093
  const generateUniqueTabId = () => {
@@ -1802,7 +2102,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1802
2102
  }
1803
2103
  return newTabId;
1804
2104
  };
1805
- const createNewTab = (0, import_react10.useCallback)(() => {
2105
+ const createNewTab = (0, import_react11.useCallback)(() => {
1806
2106
  if (!initialTabCreated) {
1807
2107
  console.warn("Cannot create new tab while initializing");
1808
2108
  return;
@@ -1829,10 +2129,10 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1829
2129
  setMessages([]);
1830
2130
  setInput("");
1831
2131
  }, [initialTabCreated]);
1832
- const startNewConversation = (0, import_react10.useCallback)(() => {
2132
+ const startNewConversation = (0, import_react11.useCallback)(() => {
1833
2133
  createNewTab();
1834
2134
  }, [createNewTab]);
1835
- (0, import_react10.useEffect)(() => {
2135
+ (0, import_react11.useEffect)(() => {
1836
2136
  return () => {
1837
2137
  };
1838
2138
  }, []);
@@ -1891,23 +2191,23 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1891
2191
  const errorText = await response.text();
1892
2192
  console.error("[ChatInterface] Error response:", errorText);
1893
2193
  }
1894
- } catch (error) {
1895
- console.error("[ChatInterface] Error fetching chat history:", error);
2194
+ } catch (error2) {
2195
+ console.error("[ChatInterface] Error fetching chat history:", error2);
1896
2196
  } finally {
1897
2197
  setLoadingHistory(false);
1898
2198
  }
1899
2199
  };
1900
- (0, import_react10.useEffect)(() => {
2200
+ (0, import_react11.useEffect)(() => {
1901
2201
  if (showHistory && !historyLoaded && config?.userId) {
1902
2202
  fetchConversations();
1903
2203
  }
1904
2204
  }, [showHistory, historyLoaded, config?.userId]);
1905
- (0, import_react10.useEffect)(() => {
2205
+ (0, import_react11.useEffect)(() => {
1906
2206
  if (!historyLoaded && config?.userId) {
1907
2207
  fetchConversations();
1908
2208
  }
1909
2209
  }, [historyLoaded, config?.userId]);
1910
- (0, import_react10.useEffect)(() => {
2210
+ (0, import_react11.useEffect)(() => {
1911
2211
  if (tabs.length > 0) {
1912
2212
  const timeoutId = setTimeout(() => {
1913
2213
  localStorage.setItem(storageKey("tabs"), JSON.stringify(tabs));
@@ -1916,7 +2216,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1916
2216
  return () => clearTimeout(timeoutId);
1917
2217
  }
1918
2218
  }, [tabs, activeTabId, storageKey]);
1919
- (0, import_react10.useEffect)(() => {
2219
+ (0, import_react11.useEffect)(() => {
1920
2220
  if (hasInitialized.current) return;
1921
2221
  const loadInitialTabs = () => {
1922
2222
  const savedTabs = localStorage.getItem(storageKey("tabs"));
@@ -1943,8 +2243,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1943
2243
  }
1944
2244
  hasInitialized.current = true;
1945
2245
  }, []);
1946
- const hasLoadedInitialMessages = (0, import_react10.useRef)(false);
1947
- (0, import_react10.useEffect)(() => {
2246
+ const hasLoadedInitialMessages = (0, import_react11.useRef)(false);
2247
+ (0, import_react11.useEffect)(() => {
1948
2248
  if (hasLoadedInitialMessages.current) return;
1949
2249
  if (!config?.userId) return;
1950
2250
  if (!activeTabId) return;
@@ -1957,14 +2257,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
1957
2257
  }
1958
2258
  })();
1959
2259
  }, [config?.userId, activeTabId]);
1960
- (0, import_react10.useEffect)(() => {
2260
+ (0, import_react11.useEffect)(() => {
1961
2261
  if (isInitializing) return;
1962
2262
  if (activeTabId && tabs.length > 0 && activeTabId !== lastSyncedTabId.current) {
1963
2263
  lastSyncedTabId.current = activeTabId;
1964
2264
  setInput("");
1965
2265
  }
1966
2266
  }, [activeTabId, isInitializing, tabs.length]);
1967
- const groupedConversations = (0, import_react10.useMemo)(() => {
2267
+ const groupedConversations = (0, import_react11.useMemo)(() => {
1968
2268
  const filtered = conversations.filter(
1969
2269
  (conv) => searchQuery === "" || conv.title.toLowerCase().includes(searchQuery.toLowerCase())
1970
2270
  );
@@ -2025,22 +2325,27 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2025
2325
  const renderMessages = () => messages.map((message, index) => {
2026
2326
  const sourceParts = message.parts?.filter((part) => part.type === "source-url") || [];
2027
2327
  const fileParts = message.parts?.filter((part) => part.type === "file") || [];
2028
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: index > 0 ? "mt-6" : "", children: [
2029
- message.role === "assistant" && sourceParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Sources, { children: [
2030
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SourcesTrigger, { count: sourceParts.length }),
2031
- 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)(
2032
2337
  Source,
2033
2338
  {
2034
2339
  href: part.url,
2035
2340
  title: part.url
2036
2341
  },
2037
- `${message.id}-${i}`
2038
- ) }, `${message.id}-${i}`))
2342
+ `${message.id}-source-${i}`
2343
+ )) })
2039
2344
  ] }),
2040
- 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(
2041
2346
  "flex mb-1",
2042
2347
  message.role === "user" ? "justify-end" : "justify-start"
2043
- ), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2348
+ ), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2044
2349
  MessageAttachments,
2045
2350
  {
2046
2351
  attachments: fileParts.map((part) => ({
@@ -2051,14 +2356,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2051
2356
  }))
2052
2357
  }
2053
2358
  ) }),
2054
- 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) => {
2055
2360
  switch (part.type) {
2056
2361
  case "text":
2057
2362
  const isTextStreaming = status === "streaming" && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;
2058
- 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}`);
2059
2364
  case "reasoning":
2060
2365
  const isCurrentlyStreaming = status === "streaming" && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;
2061
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2366
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2062
2367
  Reasoning,
2063
2368
  {
2064
2369
  className: "w-full",
@@ -2066,8 +2371,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2066
2371
  defaultOpen: false,
2067
2372
  open: isCurrentlyStreaming ? true : void 0,
2068
2373
  children: [
2069
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReasoningTrigger, {}),
2070
- /* @__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 })
2071
2376
  ]
2072
2377
  },
2073
2378
  `${message.id}-${i}`
@@ -2075,8 +2380,24 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2075
2380
  default:
2076
2381
  if (part.type.startsWith("tool-") || part.type === "dynamic-tool") {
2077
2382
  const toolPart = part;
2078
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tool, { children: [
2079
- /* @__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)(
2080
2401
  ToolHeader,
2081
2402
  {
2082
2403
  type: part.type,
@@ -2084,9 +2405,9 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2084
2405
  state: toolPart.state
2085
2406
  }
2086
2407
  ),
2087
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ToolContent, { children: [
2088
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolInput, { input: toolPart.input }),
2089
- /* @__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 })
2090
2411
  ] })
2091
2412
  ] }, `${message.id}-${i}`);
2092
2413
  }
@@ -2094,7 +2415,14 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2094
2415
  }
2095
2416
  }) }) : (
2096
2417
  /* Handle standard AI SDK messages with content or text property */
2097
- /* @__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
+ }
2098
2426
  )
2099
2427
  ] }, message.id);
2100
2428
  });
@@ -2122,12 +2450,12 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2122
2450
  setActiveTabId(selectedConversationId);
2123
2451
  await loadConversation(selectedConversationId);
2124
2452
  setShowHistory(false);
2125
- } catch (error) {
2126
- console.error("Error loading conversation:", error);
2453
+ } catch (error2) {
2454
+ console.error("Error loading conversation:", error2);
2127
2455
  }
2128
2456
  };
2129
- const dropdownRef = (0, import_react10.useRef)(null);
2130
- (0, import_react10.useEffect)(() => {
2457
+ const dropdownRef = (0, import_react11.useRef)(null);
2458
+ (0, import_react11.useEffect)(() => {
2131
2459
  const handleClickOutside = (event) => {
2132
2460
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2133
2461
  setShowHistory(false);
@@ -2140,7 +2468,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2140
2468
  document.removeEventListener("mousedown", handleClickOutside);
2141
2469
  };
2142
2470
  }, [showHistory]);
2143
- 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)(
2144
2472
  "div",
2145
2473
  {
2146
2474
  className: cn(
@@ -2148,11 +2476,11 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2148
2476
  themeMode === "dark" && "dark"
2149
2477
  ),
2150
2478
  children: [
2151
- /* @__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: {
2152
2480
  borderColor: "var(--chat-divider)",
2153
2481
  backgroundColor: "var(--chat-header-bg)"
2154
2482
  }, children: [
2155
- /* @__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)(
2156
2484
  "div",
2157
2485
  {
2158
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",
@@ -2175,8 +2503,8 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2175
2503
  switchToTab(tab.id);
2176
2504
  },
2177
2505
  children: [
2178
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate max-w-28 text-[13px] font-medium transition-colors", children: tab.title }),
2179
- 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)(
2180
2508
  "button",
2181
2509
  {
2182
2510
  onClick: (e) => {
@@ -2195,15 +2523,15 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2195
2523
  e.currentTarget.style.opacity = tab.isActive ? "0.6" : "0";
2196
2524
  e.currentTarget.style.backgroundColor = "transparent";
2197
2525
  },
2198
- 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 })
2199
2527
  }
2200
2528
  )
2201
2529
  ]
2202
2530
  },
2203
2531
  tab.id
2204
2532
  )) }),
2205
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-0.5 flex-shrink-0", children: [
2206
- /* @__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)(
2207
2535
  "button",
2208
2536
  {
2209
2537
  onClick: createNewTab,
@@ -2220,11 +2548,11 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2220
2548
  e.currentTarget.style.backgroundColor = "transparent";
2221
2549
  },
2222
2550
  title: "New Chat",
2223
- 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 })
2224
2552
  }
2225
2553
  ),
2226
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
2227
- /* @__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)(
2228
2556
  "button",
2229
2557
  {
2230
2558
  onClick: () => setShowHistory(!showHistory),
@@ -2246,17 +2574,17 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2246
2574
  }
2247
2575
  },
2248
2576
  title: "Chat History",
2249
- 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 })
2250
2578
  }
2251
2579
  ),
2252
- 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: {
2253
2581
  backgroundColor: "hsl(var(--chat-background))",
2254
2582
  border: `1px solid ${"var(--chat-divider)"}`
2255
2583
  }, children: [
2256
- /* @__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: {
2257
2585
  borderColor: "var(--chat-divider)",
2258
2586
  backgroundColor: "var(--chat-overlay)"
2259
- }, 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)(
2260
2588
  "input",
2261
2589
  {
2262
2590
  type: "text",
@@ -2271,25 +2599,25 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2271
2599
  }
2272
2600
  }
2273
2601
  ) }) }),
2274
- /* @__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: [
2275
- /* @__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: {
2276
2604
  backgroundColor: "hsl(var(--chat-surface))"
2277
- }, 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 }) }),
2278
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2279
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2280
- ] }) : 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: [
2281
- /* @__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: {
2282
2610
  backgroundColor: "hsl(var(--chat-surface))"
2283
- }, 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 }) }),
2284
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2285
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2286
- ] }) : /* @__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: [
2287
- /* @__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: {
2288
2616
  backgroundColor: "var(--chat-header-bg-strong)"
2289
- }, 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 }) }),
2290
- /* @__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) => {
2291
2619
  const isActiveConversation = activeTabId === conversation.id;
2292
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2620
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2293
2621
  "button",
2294
2622
  {
2295
2623
  className: "w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative",
@@ -2307,13 +2635,13 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2307
2635
  }
2308
2636
  },
2309
2637
  onClick: () => handleSelectConversation(conversation.id, conversation.title),
2310
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2311
- /* @__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: {
2312
2640
  fontWeight: isActiveConversation ? 500 : 400,
2313
2641
  color: isActiveConversation ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-strong))"
2314
2642
  }, children: conversation.title }) }),
2315
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2316
- import_lucide_react10.ChevronRightIcon,
2643
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2644
+ import_lucide_react12.ChevronRightIcon,
2317
2645
  {
2318
2646
  className: "h-3 w-3 transition-all duration-150 flex-shrink-0",
2319
2647
  style: {
@@ -2332,7 +2660,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2332
2660
  ] })
2333
2661
  ] }),
2334
2662
  headerActions,
2335
- onClose && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2663
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2336
2664
  "button",
2337
2665
  {
2338
2666
  onClick: onClose,
@@ -2349,21 +2677,21 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2349
2677
  e.currentTarget.style.backgroundColor = "transparent";
2350
2678
  },
2351
2679
  title: "Close Chat",
2352
- 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 })
2353
2681
  }
2354
2682
  )
2355
2683
  ] })
2356
2684
  ] }),
2357
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Conversation, { className: "flex-1 max-w-full ai-assistant-scrollbar", children: [
2358
- /* @__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: [
2359
2687
  renderMessages(),
2360
- 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 }) }) }) })
2361
2689
  ] }),
2362
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ConversationScrollButton, {})
2690
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ConversationScrollButton, {})
2363
2691
  ] }),
2364
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "px-5 pb-5", children: [
2365
- 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 }),
2366
- 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)(
2367
2695
  StarterMessages,
2368
2696
  {
2369
2697
  prompts: config.starterPrompts,
@@ -2372,27 +2700,67 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2372
2700
  }
2373
2701
  }
2374
2702
  ),
2375
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInput, { onSubmit: handleSubmit, globalDrop: true, multiple: true, accept: "image/*", children: [
2376
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInputBody, { children: [
2377
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputAttachments, { children: (attachment) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputAttachment, { data: attachment }) }),
2378
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
2379
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2380
- PromptInputTextarea,
2381
- {
2382
- ref: inputRef,
2383
- onChange: (e) => setInput(e.target.value),
2384
- onKeyDown: inputPlugins.onKeyDown,
2385
- value: input
2386
- }
2387
- ),
2388
- inputPlugins.popover
2389
- ] })
2390
- ] }),
2391
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(PromptInputToolbar, { children: [
2392
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputTools, { children: config?.features?.fileUpload === true && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AttachButton, {}) }),
2393
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptInputSubmit, { disabled: !input, status })
2394
- ] })
2395
- ] })
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
+ ),
2715
+ inputPlugins.panel,
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.");
2735
+ }
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
+ )
2396
2764
  ] })
2397
2765
  ]
2398
2766
  }
@@ -2400,7 +2768,7 @@ function ChatInterface({ id, initialMessages, config, onClose, headerActions } =
2400
2768
  }
2401
2769
 
2402
2770
  // src/ChatWidget.tsx
2403
- var import_lucide_react11 = require("lucide-react");
2771
+ var import_lucide_react13 = require("lucide-react");
2404
2772
 
2405
2773
  // src/utils/color.ts
2406
2774
  function toHslTripletIfHex(value) {
@@ -2438,7 +2806,7 @@ function toHslTripletIfHex(value) {
2438
2806
  }
2439
2807
 
2440
2808
  // src/ChatWidget.tsx
2441
- var import_jsx_runtime22 = require("react/jsx-runtime");
2809
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2442
2810
  function ChatWidget({
2443
2811
  userId,
2444
2812
  conversationId,
@@ -2455,14 +2823,15 @@ function ChatWidget({
2455
2823
  headerActions,
2456
2824
  open,
2457
2825
  onOpenChange,
2458
- inputPlugins
2826
+ inputPlugins,
2827
+ toolRenderers
2459
2828
  }) {
2460
2829
  const layout = display?.layout || "popup";
2461
2830
  const isControlled = open !== void 0;
2462
2831
  const showToggleButton = !isControlled && display?.showToggleButton !== false;
2463
2832
  const resizable = layout === "popup" && display?.resizable !== false;
2464
2833
  const size = display?.size || "default";
2465
- const [internalIsOpen, setInternalIsOpen] = (0, import_react13.useState)(
2834
+ const [internalIsOpen, setInternalIsOpen] = (0, import_react14.useState)(
2466
2835
  layout !== "popup" ? true : display?.defaultOpen || false
2467
2836
  );
2468
2837
  const isOpen = isControlled ? open : internalIsOpen;
@@ -2473,9 +2842,9 @@ function ChatWidget({
2473
2842
  setInternalIsOpen(next);
2474
2843
  }
2475
2844
  };
2476
- const [isResizing, setIsResizing] = (0, import_react13.useState)(false);
2477
- const containerRef = (0, import_react13.useRef)(null);
2478
- 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)(() => {
2479
2848
  const styles = {};
2480
2849
  if (display?.width) {
2481
2850
  styles["--chat-widget-width"] = display.width;
@@ -2494,14 +2863,14 @@ function ChatWidget({
2494
2863
  }
2495
2864
  return styles;
2496
2865
  }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);
2497
- const handleMouseDown = (0, import_react13.useCallback)((e) => {
2866
+ const handleMouseDown = (0, import_react14.useCallback)((e) => {
2498
2867
  if (!resizable) return;
2499
2868
  e.preventDefault();
2500
2869
  setIsResizing(true);
2501
2870
  document.body.style.cursor = "ew-resize";
2502
2871
  document.body.style.userSelect = "none";
2503
2872
  }, [resizable]);
2504
- (0, import_react13.useEffect)(() => {
2873
+ (0, import_react14.useEffect)(() => {
2505
2874
  if (!isResizing) return;
2506
2875
  const handleMouseMove = (e) => {
2507
2876
  if (!containerRef.current) return;
@@ -2523,7 +2892,7 @@ function ChatWidget({
2523
2892
  document.removeEventListener("mouseup", handleMouseUp);
2524
2893
  };
2525
2894
  }, [isResizing]);
2526
- const config = (0, import_react13.useMemo)(() => ({
2895
+ const config = (0, import_react14.useMemo)(() => ({
2527
2896
  userId,
2528
2897
  model,
2529
2898
  systemPrompt,
@@ -2531,18 +2900,19 @@ function ChatWidget({
2531
2900
  theme,
2532
2901
  features,
2533
2902
  starterPrompts,
2534
- inputPlugins
2535
- }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts, inputPlugins]);
2903
+ inputPlugins,
2904
+ toolRenderers
2905
+ }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts, inputPlugins, toolRenderers]);
2536
2906
  const togglePosition = display?.toggleButtonPosition || { bottom: "24px", right: "24px" };
2537
2907
  const themeClass = theme?.mode === "dark" ? "dark" : "";
2538
2908
  if (layout === "inline") {
2539
- 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)(
2540
2910
  "div",
2541
2911
  {
2542
2912
  ref: containerRef,
2543
2913
  className: `chat-widget-container chat-widget-inline chat-widget-content ${themeClass} ${className || ""}`,
2544
2914
  style: customStyles,
2545
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2915
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2546
2916
  ChatInterface,
2547
2917
  {
2548
2918
  id: conversationId,
@@ -2556,13 +2926,13 @@ function ChatWidget({
2556
2926
  ) });
2557
2927
  }
2558
2928
  if (layout === "page") {
2559
- 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)(
2560
2930
  "div",
2561
2931
  {
2562
2932
  ref: containerRef,
2563
2933
  className: `chat-widget-container chat-widget-page chat-widget-content ${themeClass} ${className || ""}`,
2564
2934
  style: customStyles,
2565
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2935
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2566
2936
  ChatInterface,
2567
2937
  {
2568
2938
  id: conversationId,
@@ -2575,18 +2945,18 @@ function ChatWidget({
2575
2945
  }
2576
2946
  ) });
2577
2947
  }
2578
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ChatStorageProvider, { userId, children: [
2579
- 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)(
2580
2950
  "button",
2581
2951
  {
2582
2952
  onClick: () => setIsOpen(true),
2583
2953
  className: "fixed z-50 rounded-full bg-primary text-primary-foreground shadow-lg hover:opacity-90 transition-all p-4",
2584
2954
  style: togglePosition,
2585
2955
  "aria-label": "Open chat",
2586
- 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" })
2587
2957
  }
2588
2958
  ),
2589
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2959
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2590
2960
  "div",
2591
2961
  {
2592
2962
  ref: containerRef,
@@ -2595,7 +2965,7 @@ function ChatWidget({
2595
2965
  "data-resizing": isResizing,
2596
2966
  style: customStyles,
2597
2967
  children: [
2598
- resizable && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2968
+ resizable && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2599
2969
  "div",
2600
2970
  {
2601
2971
  onMouseDown: handleMouseDown,
@@ -2603,7 +2973,7 @@ function ChatWidget({
2603
2973
  "aria-label": "Resize chat widget"
2604
2974
  }
2605
2975
  ),
2606
- /* @__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)(
2607
2977
  ChatInterface,
2608
2978
  {
2609
2979
  id: conversationId,
@@ -2624,7 +2994,7 @@ function ChatWidget({
2624
2994
  var ChatWidget_default = ChatWidget;
2625
2995
 
2626
2996
  // src/hooks/use-chat-theme.ts
2627
- var import_react14 = require("react");
2997
+ var import_react15 = require("react");
2628
2998
 
2629
2999
  // src/utils/models.ts
2630
3000
  var MODELS = [
@@ -2744,13 +3114,13 @@ var defaultThemeMode = "light";
2744
3114
  function useChatTheme() {
2745
3115
  const { storageKeyPrefix } = useChatStorageKey();
2746
3116
  const keyPrefix = storageKeyPrefix ? `chat-${storageKeyPrefix}-` : "chat-";
2747
- const [theme, setTheme] = (0, import_react14.useState)(defaultTheme);
2748
- const [conversationStarters, setConversationStarters] = (0, import_react14.useState)(defaultConversationStarters);
2749
- const [model, setModel] = (0, import_react14.useState)(defaultModel);
2750
- const [systemPrompt, setSystemPrompt] = (0, import_react14.useState)(defaultSystemPrompt);
2751
- const [temperature, setTemperature] = (0, import_react14.useState)(defaultTemperature);
2752
- const [themeMode, setThemeMode] = (0, import_react14.useState)(defaultThemeMode);
2753
- (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)(() => {
2754
3124
  const savedTheme = localStorage.getItem(`${keyPrefix}theme`);
2755
3125
  if (savedTheme) {
2756
3126
  try {
@@ -2838,7 +3208,7 @@ function useChatTheme() {
2838
3208
  window.removeEventListener("chat-theme-mode-change", handleThemeModeChange);
2839
3209
  };
2840
3210
  }, [keyPrefix]);
2841
- (0, import_react14.useEffect)(() => {
3211
+ (0, import_react15.useEffect)(() => {
2842
3212
  localStorage.setItem(`${keyPrefix}theme`, JSON.stringify(theme));
2843
3213
  const root = document.documentElement;
2844
3214
  if (themeMode === "light") {
@@ -2854,23 +3224,23 @@ function useChatTheme() {
2854
3224
  root.style.setProperty("--chat-font-size", `${theme.fontSize}px`);
2855
3225
  window.dispatchEvent(new CustomEvent("chat-theme-change", { detail: theme }));
2856
3226
  }, [theme, themeMode, keyPrefix]);
2857
- (0, import_react14.useEffect)(() => {
3227
+ (0, import_react15.useEffect)(() => {
2858
3228
  localStorage.setItem(`${keyPrefix}conversation-starters`, JSON.stringify(conversationStarters));
2859
3229
  window.dispatchEvent(new CustomEvent("chat-starters-change", { detail: conversationStarters }));
2860
3230
  }, [conversationStarters, keyPrefix]);
2861
- (0, import_react14.useEffect)(() => {
3231
+ (0, import_react15.useEffect)(() => {
2862
3232
  localStorage.setItem(`${keyPrefix}model`, model);
2863
3233
  window.dispatchEvent(new CustomEvent("chat-model-change", { detail: model }));
2864
3234
  }, [model, keyPrefix]);
2865
- (0, import_react14.useEffect)(() => {
3235
+ (0, import_react15.useEffect)(() => {
2866
3236
  localStorage.setItem(`${keyPrefix}system-prompt`, systemPrompt);
2867
3237
  window.dispatchEvent(new CustomEvent("chat-system-prompt-change", { detail: systemPrompt }));
2868
3238
  }, [systemPrompt, keyPrefix]);
2869
- (0, import_react14.useEffect)(() => {
3239
+ (0, import_react15.useEffect)(() => {
2870
3240
  localStorage.setItem(`${keyPrefix}temperature`, temperature.toString());
2871
3241
  window.dispatchEvent(new CustomEvent("chat-temperature-change", { detail: temperature }));
2872
3242
  }, [temperature, keyPrefix]);
2873
- (0, import_react14.useEffect)(() => {
3243
+ (0, import_react15.useEffect)(() => {
2874
3244
  localStorage.setItem(`${keyPrefix}theme-mode`, themeMode);
2875
3245
  window.dispatchEvent(new CustomEvent("chat-theme-mode-change", { detail: themeMode }));
2876
3246
  }, [themeMode, keyPrefix]);
@@ -2940,10 +3310,10 @@ function useChatTheme() {
2940
3310
 
2941
3311
  // src/ui/input.tsx
2942
3312
  var React3 = __toESM(require("react"));
2943
- var import_jsx_runtime23 = require("react/jsx-runtime");
3313
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2944
3314
  var Input = React3.forwardRef(
2945
3315
  ({ className, type, ...props }, ref) => {
2946
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3316
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2947
3317
  "input",
2948
3318
  {
2949
3319
  type,
@@ -2961,23 +3331,23 @@ Input.displayName = "Input";
2961
3331
 
2962
3332
  // src/ui/dialog.tsx
2963
3333
  var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
2964
- var import_lucide_react12 = require("lucide-react");
2965
- 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");
2966
3336
  function Dialog({
2967
3337
  ...props
2968
3338
  }) {
2969
- 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 });
2970
3340
  }
2971
3341
  function DialogPortal({
2972
3342
  ...props
2973
3343
  }) {
2974
- 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 });
2975
3345
  }
2976
3346
  function DialogOverlay({
2977
3347
  className,
2978
3348
  ...props
2979
3349
  }) {
2980
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3350
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2981
3351
  DialogPrimitive.Overlay,
2982
3352
  {
2983
3353
  "data-slot": "dialog-overlay",
@@ -2995,9 +3365,9 @@ function DialogContent({
2995
3365
  showCloseButton = true,
2996
3366
  ...props
2997
3367
  }) {
2998
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { "data-slot": "dialog-portal", children: [
2999
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, {}),
3000
- /* @__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)(
3001
3371
  DialogPrimitive.Content,
3002
3372
  {
3003
3373
  "data-slot": "dialog-content",
@@ -3008,14 +3378,14 @@ function DialogContent({
3008
3378
  ...props,
3009
3379
  children: [
3010
3380
  children,
3011
- showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3381
+ showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3012
3382
  DialogPrimitive.Close,
3013
3383
  {
3014
3384
  "data-slot": "dialog-close",
3015
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",
3016
3386
  children: [
3017
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.XIcon, {}),
3018
- /* @__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" })
3019
3389
  ]
3020
3390
  }
3021
3391
  )
@@ -3025,7 +3395,7 @@ function DialogContent({
3025
3395
  ] });
3026
3396
  }
3027
3397
  function DialogHeader({ className, ...props }) {
3028
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3398
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3029
3399
  "div",
3030
3400
  {
3031
3401
  "data-slot": "dialog-header",
@@ -3038,7 +3408,7 @@ function DialogTitle({
3038
3408
  className,
3039
3409
  ...props
3040
3410
  }) {
3041
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3411
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3042
3412
  DialogPrimitive.Title,
3043
3413
  {
3044
3414
  "data-slot": "dialog-title",
@@ -3051,7 +3421,7 @@ function DialogDescription({
3051
3421
  className,
3052
3422
  ...props
3053
3423
  }) {
3054
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3424
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3055
3425
  DialogPrimitive.Description,
3056
3426
  {
3057
3427
  "data-slot": "dialog-description",
@@ -3073,6 +3443,11 @@ function DialogDescription({
3073
3443
  Input,
3074
3444
  StarterMessageItem,
3075
3445
  StarterMessages,
3446
+ Tool,
3447
+ ToolContent,
3448
+ ToolHeader,
3449
+ ToolInput,
3450
+ ToolOutput,
3076
3451
  fontOptions,
3077
3452
  useChatStorageKey,
3078
3453
  useChatTheme