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