@kite-copilot/chat-panel 0.2.51 → 0.2.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto.cjs +446 -138
- package/dist/auto.d.cts +1 -1
- package/dist/auto.d.ts +1 -1
- package/dist/auto.js +1 -1
- package/dist/{chunk-VBCGW333.js → chunk-VXJQZR5G.js} +447 -139
- package/dist/{createKiteChat-DeQKgFyx.d.cts → createKiteChat-Cl1sNjam.d.cts} +6 -2
- package/dist/{createKiteChat-DeQKgFyx.d.ts → createKiteChat-Cl1sNjam.d.ts} +6 -2
- package/dist/embed.global.js +26 -22
- package/dist/index.cjs +446 -138
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -884,7 +884,7 @@ function DataRenderer({ type, data }) {
|
|
|
884
884
|
// src/ChatPanel.tsx
|
|
885
885
|
import * as React6 from "react";
|
|
886
886
|
import { createClient } from "@supabase/supabase-js";
|
|
887
|
-
import { ArrowLeft, ArrowUp, Command, CornerDownLeft, CheckCircle2 as CheckCircle23, SquarePen, Paperclip, X, FileSpreadsheet, Loader2 as Loader22, ChevronLeft, ChevronRight, Sparkles, Minus } from "lucide-react";
|
|
887
|
+
import { ArrowLeft, ArrowUp, Command, CornerDownLeft, CheckCircle2 as CheckCircle23, SquarePen, Paperclip, X, FileSpreadsheet, Loader2 as Loader22, ChevronLeft, ChevronRight, Sparkles, Minus, Download } from "lucide-react";
|
|
888
888
|
import { motion as motion2, useAnimationControls } from "framer-motion";
|
|
889
889
|
|
|
890
890
|
// src/hooks/useUserAuth.ts
|
|
@@ -1067,29 +1067,29 @@ function useFrontendToolExecutor({
|
|
|
1067
1067
|
// src/components/TypingIndicator.tsx
|
|
1068
1068
|
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1069
1069
|
function TypingIndicator({ className = "" }) {
|
|
1070
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ jsxs5("div", { className: `flex items-center gap-1.5 ${className}`, children: [
|
|
1071
1071
|
/* @__PURE__ */ jsx9(
|
|
1072
1072
|
"span",
|
|
1073
1073
|
{
|
|
1074
|
-
className: "w-2 h-2 bg-gray-
|
|
1074
|
+
className: "w-2 h-2 bg-gray-500 rounded-full animate-bounce",
|
|
1075
1075
|
style: { animationDelay: "0ms", animationDuration: "600ms" }
|
|
1076
1076
|
}
|
|
1077
1077
|
),
|
|
1078
1078
|
/* @__PURE__ */ jsx9(
|
|
1079
1079
|
"span",
|
|
1080
1080
|
{
|
|
1081
|
-
className: "w-2 h-2 bg-gray-
|
|
1081
|
+
className: "w-2 h-2 bg-gray-500 rounded-full animate-bounce",
|
|
1082
1082
|
style: { animationDelay: "150ms", animationDuration: "600ms" }
|
|
1083
1083
|
}
|
|
1084
1084
|
),
|
|
1085
1085
|
/* @__PURE__ */ jsx9(
|
|
1086
1086
|
"span",
|
|
1087
1087
|
{
|
|
1088
|
-
className: "w-2 h-2 bg-gray-
|
|
1088
|
+
className: "w-2 h-2 bg-gray-500 rounded-full animate-bounce",
|
|
1089
1089
|
style: { animationDelay: "300ms", animationDuration: "600ms" }
|
|
1090
1090
|
}
|
|
1091
1091
|
)
|
|
1092
|
-
] })
|
|
1092
|
+
] });
|
|
1093
1093
|
}
|
|
1094
1094
|
|
|
1095
1095
|
// src/ChatPanel.tsx
|
|
@@ -1538,6 +1538,78 @@ function AuthErrorState({
|
|
|
1538
1538
|
)
|
|
1539
1539
|
] });
|
|
1540
1540
|
}
|
|
1541
|
+
function ImageLightbox({
|
|
1542
|
+
imageUrl,
|
|
1543
|
+
onClose
|
|
1544
|
+
}) {
|
|
1545
|
+
const handleDownload = async () => {
|
|
1546
|
+
try {
|
|
1547
|
+
const response = await fetch(imageUrl);
|
|
1548
|
+
const blob = await response.blob();
|
|
1549
|
+
const url = window.URL.createObjectURL(blob);
|
|
1550
|
+
const a = document.createElement("a");
|
|
1551
|
+
a.href = url;
|
|
1552
|
+
const urlParts = imageUrl.split("/");
|
|
1553
|
+
const filename = urlParts[urlParts.length - 1] || "image.jpg";
|
|
1554
|
+
a.download = filename;
|
|
1555
|
+
document.body.appendChild(a);
|
|
1556
|
+
a.click();
|
|
1557
|
+
document.body.removeChild(a);
|
|
1558
|
+
window.URL.revokeObjectURL(url);
|
|
1559
|
+
} catch (error) {
|
|
1560
|
+
console.error("Failed to download image:", error);
|
|
1561
|
+
window.open(imageUrl, "_blank");
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
return /* @__PURE__ */ jsx10(
|
|
1565
|
+
"div",
|
|
1566
|
+
{
|
|
1567
|
+
className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/80",
|
|
1568
|
+
onClick: onClose,
|
|
1569
|
+
children: /* @__PURE__ */ jsxs6(
|
|
1570
|
+
"div",
|
|
1571
|
+
{
|
|
1572
|
+
className: "relative max-w-[90vw] max-h-[90vh] flex flex-col items-center",
|
|
1573
|
+
onClick: (e) => e.stopPropagation(),
|
|
1574
|
+
children: [
|
|
1575
|
+
/* @__PURE__ */ jsx10(
|
|
1576
|
+
"img",
|
|
1577
|
+
{
|
|
1578
|
+
src: imageUrl,
|
|
1579
|
+
alt: "Full size preview",
|
|
1580
|
+
className: "max-w-full max-h-[80vh] object-contain rounded-lg"
|
|
1581
|
+
}
|
|
1582
|
+
),
|
|
1583
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex gap-3 mt-4", children: [
|
|
1584
|
+
/* @__PURE__ */ jsxs6(
|
|
1585
|
+
"button",
|
|
1586
|
+
{
|
|
1587
|
+
onClick: handleDownload,
|
|
1588
|
+
className: "flex items-center gap-2 px-4 py-2 bg-white text-gray-800 rounded-lg hover:bg-gray-100 transition-colors text-sm font-medium",
|
|
1589
|
+
children: [
|
|
1590
|
+
/* @__PURE__ */ jsx10(Download, { className: "h-4 w-4" }),
|
|
1591
|
+
"Download"
|
|
1592
|
+
]
|
|
1593
|
+
}
|
|
1594
|
+
),
|
|
1595
|
+
/* @__PURE__ */ jsxs6(
|
|
1596
|
+
"button",
|
|
1597
|
+
{
|
|
1598
|
+
onClick: onClose,
|
|
1599
|
+
className: "flex items-center gap-2 px-4 py-2 bg-gray-700 text-white rounded-lg hover:bg-gray-600 transition-colors text-sm font-medium",
|
|
1600
|
+
children: [
|
|
1601
|
+
/* @__PURE__ */ jsx10(X, { className: "h-4 w-4" }),
|
|
1602
|
+
"Close"
|
|
1603
|
+
]
|
|
1604
|
+
}
|
|
1605
|
+
)
|
|
1606
|
+
] })
|
|
1607
|
+
]
|
|
1608
|
+
}
|
|
1609
|
+
)
|
|
1610
|
+
}
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1541
1613
|
function ChatPanel({
|
|
1542
1614
|
isOpen = true,
|
|
1543
1615
|
onClose,
|
|
@@ -1558,7 +1630,8 @@ function ChatPanel({
|
|
|
1558
1630
|
initialCorner = "bottom-left",
|
|
1559
1631
|
onCornerChange,
|
|
1560
1632
|
productBackendUrl,
|
|
1561
|
-
getAuthHeaders
|
|
1633
|
+
getAuthHeaders,
|
|
1634
|
+
isEval = false
|
|
1562
1635
|
} = {}) {
|
|
1563
1636
|
const [messages, setMessages] = React6.useState(initialMessages);
|
|
1564
1637
|
const [input, setInput] = React6.useState("");
|
|
@@ -1668,13 +1741,20 @@ function ChatPanel({
|
|
|
1668
1741
|
}, [effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
|
|
1669
1742
|
React6.useEffect(() => {
|
|
1670
1743
|
if (!isEscalated || !sessionId || !supabaseRef.current) {
|
|
1744
|
+
console.log("[KiteChat] Typing channel skip - isEscalated:", isEscalated, "sessionId:", sessionId, "supabase:", !!supabaseRef.current);
|
|
1671
1745
|
return;
|
|
1672
1746
|
}
|
|
1673
1747
|
const channelName = `typing:${sessionId}`;
|
|
1674
|
-
|
|
1748
|
+
console.log("[KiteChat] Subscribing to typing channel:", channelName, "sessionId:", sessionId);
|
|
1749
|
+
const channel = supabaseRef.current.channel(channelName, {
|
|
1750
|
+
config: { broadcast: { self: true } }
|
|
1751
|
+
});
|
|
1675
1752
|
channel.on("broadcast", { event: "typing" }, (payload) => {
|
|
1753
|
+
console.log("[KiteChat] Received typing event:", payload);
|
|
1676
1754
|
const { sender, isTyping } = payload.payload;
|
|
1755
|
+
console.log("[KiteChat] Typing event - sender:", sender, "isTyping:", isTyping);
|
|
1677
1756
|
if (sender === "agent") {
|
|
1757
|
+
console.log("[KiteChat] Setting agentIsTyping to:", isTyping);
|
|
1678
1758
|
setAgentIsTyping(isTyping);
|
|
1679
1759
|
if (isTyping) {
|
|
1680
1760
|
if (typingTimeoutRef.current) {
|
|
@@ -1686,6 +1766,7 @@ function ChatPanel({
|
|
|
1686
1766
|
}
|
|
1687
1767
|
}
|
|
1688
1768
|
}).subscribe((status) => {
|
|
1769
|
+
console.log("[KiteChat] Typing channel subscription status:", status);
|
|
1689
1770
|
if (status === "SUBSCRIBED") {
|
|
1690
1771
|
typingChannelRef.current = channel;
|
|
1691
1772
|
console.log("[KiteChat] Typing channel subscribed successfully");
|
|
@@ -1700,7 +1781,7 @@ function ChatPanel({
|
|
|
1700
1781
|
window.clearTimeout(typingTimeoutRef.current);
|
|
1701
1782
|
}
|
|
1702
1783
|
};
|
|
1703
|
-
}, [isEscalated, sessionId]);
|
|
1784
|
+
}, [isEscalated, sessionId, effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
|
|
1704
1785
|
React6.useEffect(() => {
|
|
1705
1786
|
if (!isOpen && isEscalated && supabaseRef.current && sessionId) {
|
|
1706
1787
|
console.log("[KiteChat] Panel closed during live chat, marking disconnected");
|
|
@@ -1773,9 +1854,7 @@ function ChatPanel({
|
|
|
1773
1854
|
markDisconnectedWithKeepalive();
|
|
1774
1855
|
};
|
|
1775
1856
|
const handleVisibilityChange = () => {
|
|
1776
|
-
if (document.visibilityState === "
|
|
1777
|
-
markDisconnectedWithKeepalive();
|
|
1778
|
-
} else if (document.visibilityState === "visible") {
|
|
1857
|
+
if (document.visibilityState === "visible") {
|
|
1779
1858
|
markActive();
|
|
1780
1859
|
}
|
|
1781
1860
|
};
|
|
@@ -1913,6 +1992,77 @@ function ChatPanel({
|
|
|
1913
1992
|
const [pendingBulkSession, setPendingBulkSession] = React6.useState(null);
|
|
1914
1993
|
const pendingBulkSessionRef = React6.useRef(null);
|
|
1915
1994
|
const fileInputRef = React6.useRef(null);
|
|
1995
|
+
const [pendingImages, setPendingImages] = React6.useState([]);
|
|
1996
|
+
const [isUploadingImage, setIsUploadingImage] = React6.useState(false);
|
|
1997
|
+
const [isDragOver, setIsDragOver] = React6.useState(false);
|
|
1998
|
+
const imageInputRef = React6.useRef(null);
|
|
1999
|
+
const [lightboxImageUrl, setLightboxImageUrl] = React6.useState(null);
|
|
2000
|
+
const uploadImageToStorage = React6.useCallback(async (file) => {
|
|
2001
|
+
if (!supabaseRef.current) {
|
|
2002
|
+
console.error("[KiteChat] Supabase client not available for file upload");
|
|
2003
|
+
return null;
|
|
2004
|
+
}
|
|
2005
|
+
const fileExt = file.name.split(".").pop();
|
|
2006
|
+
const fileName = `${sessionId}/${Date.now()}-${Math.random().toString(36).substring(7)}.${fileExt}`;
|
|
2007
|
+
const bucketName = "chat-attachments";
|
|
2008
|
+
try {
|
|
2009
|
+
const { data, error } = await supabaseRef.current.storage.from(bucketName).upload(fileName, file, {
|
|
2010
|
+
cacheControl: "3600",
|
|
2011
|
+
upsert: false
|
|
2012
|
+
});
|
|
2013
|
+
if (error) {
|
|
2014
|
+
console.error("[KiteChat] Upload error:", error);
|
|
2015
|
+
return null;
|
|
2016
|
+
}
|
|
2017
|
+
const { data: urlData } = supabaseRef.current.storage.from(bucketName).getPublicUrl(fileName);
|
|
2018
|
+
return urlData?.publicUrl || null;
|
|
2019
|
+
} catch (err) {
|
|
2020
|
+
console.error("[KiteChat] Upload failed:", err);
|
|
2021
|
+
return null;
|
|
2022
|
+
}
|
|
2023
|
+
}, [sessionId]);
|
|
2024
|
+
const handleImageSelect = React6.useCallback((files) => {
|
|
2025
|
+
if (!files) return;
|
|
2026
|
+
const imageFiles = Array.from(files).filter(
|
|
2027
|
+
(file) => file.type.startsWith("image/") || file.type === "application/pdf"
|
|
2028
|
+
);
|
|
2029
|
+
const newImages = imageFiles.map((file) => ({
|
|
2030
|
+
file,
|
|
2031
|
+
preview: file.type.startsWith("image/") ? URL.createObjectURL(file) : ""
|
|
2032
|
+
}));
|
|
2033
|
+
setPendingImages((prev) => [...prev, ...newImages]);
|
|
2034
|
+
}, []);
|
|
2035
|
+
const handleDragOver = React6.useCallback((e) => {
|
|
2036
|
+
e.preventDefault();
|
|
2037
|
+
e.stopPropagation();
|
|
2038
|
+
setIsDragOver(true);
|
|
2039
|
+
}, []);
|
|
2040
|
+
const handleDragLeave = React6.useCallback((e) => {
|
|
2041
|
+
e.preventDefault();
|
|
2042
|
+
e.stopPropagation();
|
|
2043
|
+
setIsDragOver(false);
|
|
2044
|
+
}, []);
|
|
2045
|
+
const handleDrop = React6.useCallback((e) => {
|
|
2046
|
+
e.preventDefault();
|
|
2047
|
+
e.stopPropagation();
|
|
2048
|
+
setIsDragOver(false);
|
|
2049
|
+
const files = e.dataTransfer.files;
|
|
2050
|
+
if (files.length > 0) {
|
|
2051
|
+
const csvFile = Array.from(files).find((f) => f.name.endsWith(".csv"));
|
|
2052
|
+
if (csvFile && !isEscalated) {
|
|
2053
|
+
setPendingFile(csvFile);
|
|
2054
|
+
} else {
|
|
2055
|
+
handleImageSelect(files);
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
}, [isEscalated, handleImageSelect]);
|
|
2059
|
+
React6.useEffect(() => {
|
|
2060
|
+
return () => {
|
|
2061
|
+
pendingImages.forEach((img) => {
|
|
2062
|
+
if (img.preview) URL.revokeObjectURL(img.preview);
|
|
2063
|
+
});
|
|
2064
|
+
};
|
|
2065
|
+
}, [pendingImages]);
|
|
1916
2066
|
const [searchExpanded, setSearchExpanded] = React6.useState(false);
|
|
1917
2067
|
const [searchInput, setSearchInput] = React6.useState("");
|
|
1918
2068
|
const searchInputRef = React6.useRef(null);
|
|
@@ -1969,6 +2119,11 @@ function ChatPanel({
|
|
|
1969
2119
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1970
2120
|
}
|
|
1971
2121
|
}, [messages, phase, activeGuide]);
|
|
2122
|
+
React6.useEffect(() => {
|
|
2123
|
+
if (isEscalated && agentIsTyping && !activeGuide) {
|
|
2124
|
+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2125
|
+
}
|
|
2126
|
+
}, [isEscalated, agentIsTyping, activeGuide]);
|
|
1972
2127
|
const latestBulkSummaryNavigation = React6.useMemo(() => {
|
|
1973
2128
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1974
2129
|
const msg = messages[i];
|
|
@@ -2205,7 +2360,7 @@ function ChatPanel({
|
|
|
2205
2360
|
setPanelView("landing");
|
|
2206
2361
|
setCurrentFolderId(void 0);
|
|
2207
2362
|
}
|
|
2208
|
-
function handleSubmit(e) {
|
|
2363
|
+
async function handleSubmit(e) {
|
|
2209
2364
|
e.preventDefault();
|
|
2210
2365
|
const trimmed = input.trim();
|
|
2211
2366
|
if (pendingFile) {
|
|
@@ -2225,6 +2380,49 @@ function ChatPanel({
|
|
|
2225
2380
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
2226
2381
|
return;
|
|
2227
2382
|
}
|
|
2383
|
+
if (pendingImages.length > 0) {
|
|
2384
|
+
setIsUploadingImage(true);
|
|
2385
|
+
try {
|
|
2386
|
+
const uploadedUrls = [];
|
|
2387
|
+
for (const img of pendingImages) {
|
|
2388
|
+
const url = await uploadImageToStorage(img.file);
|
|
2389
|
+
if (url) {
|
|
2390
|
+
uploadedUrls.push(url);
|
|
2391
|
+
}
|
|
2392
|
+
if (img.preview) URL.revokeObjectURL(img.preview);
|
|
2393
|
+
}
|
|
2394
|
+
if (uploadedUrls.length > 0) {
|
|
2395
|
+
const imageMarkdown = uploadedUrls.map((url) => ``).join("\n");
|
|
2396
|
+
const messageContent = trimmed ? `${trimmed}
|
|
2397
|
+
|
|
2398
|
+
${imageMarkdown}` : imageMarkdown;
|
|
2399
|
+
const userMessage = {
|
|
2400
|
+
id: Date.now(),
|
|
2401
|
+
role: "user",
|
|
2402
|
+
content: messageContent,
|
|
2403
|
+
imageUrls: uploadedUrls
|
|
2404
|
+
};
|
|
2405
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
2406
|
+
if (isEscalated) {
|
|
2407
|
+
sendEscalatedMessage(messageContent);
|
|
2408
|
+
sendTypingIndicator(false);
|
|
2409
|
+
if (userTypingTimeoutRef.current) {
|
|
2410
|
+
window.clearTimeout(userTypingTimeoutRef.current);
|
|
2411
|
+
userTypingTimeoutRef.current = null;
|
|
2412
|
+
}
|
|
2413
|
+
} else {
|
|
2414
|
+
startChatFlow(messageContent);
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
} catch (err) {
|
|
2418
|
+
console.error("[KiteChat] Failed to upload images:", err);
|
|
2419
|
+
} finally {
|
|
2420
|
+
setIsUploadingImage(false);
|
|
2421
|
+
setPendingImages([]);
|
|
2422
|
+
setInput("");
|
|
2423
|
+
}
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2228
2426
|
if (!trimmed) return;
|
|
2229
2427
|
if (isEscalated) {
|
|
2230
2428
|
const userMessage = {
|
|
@@ -2389,7 +2587,8 @@ function ChatPanel({
|
|
|
2389
2587
|
user_id: userId,
|
|
2390
2588
|
org_id: orgId,
|
|
2391
2589
|
user_name: userName,
|
|
2392
|
-
user_email: userEmail
|
|
2590
|
+
user_email: userEmail,
|
|
2591
|
+
is_eval: isEval
|
|
2393
2592
|
}),
|
|
2394
2593
|
signal: controller.signal
|
|
2395
2594
|
});
|
|
@@ -3282,19 +3481,23 @@ ${userText}`
|
|
|
3282
3481
|
)
|
|
3283
3482
|
] }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3284
3483
|
/* @__PURE__ */ jsx10(
|
|
3285
|
-
"
|
|
3484
|
+
"textarea",
|
|
3286
3485
|
{
|
|
3287
3486
|
ref: searchInputRef,
|
|
3288
|
-
type: "text",
|
|
3289
3487
|
value: searchInput,
|
|
3290
|
-
onChange: (e) =>
|
|
3488
|
+
onChange: (e) => {
|
|
3489
|
+
setSearchInput(e.target.value);
|
|
3490
|
+
e.target.style.height = "auto";
|
|
3491
|
+
e.target.style.height = Math.min(e.target.scrollHeight, 120) + "px";
|
|
3492
|
+
},
|
|
3291
3493
|
onKeyDown: (e) => {
|
|
3292
|
-
if (e.key === "Enter" && searchInput.trim()) {
|
|
3494
|
+
if (e.key === "Enter" && !e.shiftKey && searchInput.trim()) {
|
|
3293
3495
|
e.preventDefault();
|
|
3294
3496
|
onOpen?.();
|
|
3295
3497
|
startChatFlow(searchInput.trim());
|
|
3296
3498
|
setSearchInput("");
|
|
3297
3499
|
setSearchExpanded(false);
|
|
3500
|
+
e.currentTarget.style.height = "auto";
|
|
3298
3501
|
} else if (e.key === "Escape") {
|
|
3299
3502
|
setSearchExpanded(false);
|
|
3300
3503
|
setSearchInput("");
|
|
@@ -3306,7 +3509,8 @@ ${userText}`
|
|
|
3306
3509
|
}
|
|
3307
3510
|
},
|
|
3308
3511
|
placeholder: "Ask a question...",
|
|
3309
|
-
|
|
3512
|
+
rows: 1,
|
|
3513
|
+
className: "flex-1 text-sm text-gray-700 outline-none bg-transparent resize-none min-h-[20px] max-h-[120px]"
|
|
3310
3514
|
}
|
|
3311
3515
|
),
|
|
3312
3516
|
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
@@ -3566,12 +3770,55 @@ ${userText}`
|
|
|
3566
3770
|
return null;
|
|
3567
3771
|
}
|
|
3568
3772
|
if (isUser) {
|
|
3569
|
-
return /* @__PURE__ */
|
|
3773
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col items-end gap-2 ${isRoleChange ? "mt-3" : ""}`, children: [
|
|
3774
|
+
message.imageUrls && message.imageUrls.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-1 justify-end max-w-[260px]", children: message.imageUrls.map((url, imgIndex) => /* @__PURE__ */ jsx10(
|
|
3775
|
+
"button",
|
|
3776
|
+
{
|
|
3777
|
+
onClick: () => setLightboxImageUrl(url),
|
|
3778
|
+
className: "block cursor-pointer",
|
|
3779
|
+
children: /* @__PURE__ */ jsx10(
|
|
3780
|
+
"img",
|
|
3781
|
+
{
|
|
3782
|
+
src: url,
|
|
3783
|
+
alt: `Attachment ${imgIndex + 1}`,
|
|
3784
|
+
className: "max-h-32 max-w-[200px] rounded-lg object-cover border border-gray-700 hover:opacity-90 transition-opacity"
|
|
3785
|
+
}
|
|
3786
|
+
)
|
|
3787
|
+
},
|
|
3788
|
+
imgIndex
|
|
3789
|
+
)) }),
|
|
3790
|
+
message.content && !message.content.match(/^!\[image\]\([^)]+\)(\n!\[image\]\([^)]+\))*$/) && /* @__PURE__ */ jsx10("div", { className: "max-w-[260px] rounded-2xl rounded-br-md bg-gray-900 px-3 py-2 text-sm text-white shadow-sm", children: message.content.replace(/!\[image\]\([^)]+\)\n*/g, "").trim() })
|
|
3791
|
+
] }, message.id);
|
|
3570
3792
|
}
|
|
3571
3793
|
if (message.role === "agent") {
|
|
3572
|
-
|
|
3794
|
+
const imageRegex = /!\[image\]\(([^)]+)\)/g;
|
|
3795
|
+
const extractedImageUrls = [];
|
|
3796
|
+
let match;
|
|
3797
|
+
const contentStr = message.content || "";
|
|
3798
|
+
while ((match = imageRegex.exec(contentStr)) !== null) {
|
|
3799
|
+
extractedImageUrls.push(match[1]);
|
|
3800
|
+
}
|
|
3801
|
+
const agentImageUrls = message.imageUrls || extractedImageUrls;
|
|
3802
|
+
const agentTextContent = contentStr.replace(/!\[image\]\([^)]+\)\n*/g, "").trim();
|
|
3803
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col items-start gap-2 ${isRoleChange ? "mt-3" : ""}`, children: [
|
|
3573
3804
|
isRoleChange && /* @__PURE__ */ jsx10("span", { className: "text-[10px] text-gray-500 mb-1 ml-1", children: "Agent" }),
|
|
3574
|
-
/* @__PURE__ */ jsx10("div", { className: "
|
|
3805
|
+
agentImageUrls.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-1 justify-start max-w-[300px]", children: agentImageUrls.map((url, imgIndex) => /* @__PURE__ */ jsx10(
|
|
3806
|
+
"button",
|
|
3807
|
+
{
|
|
3808
|
+
onClick: () => setLightboxImageUrl(url),
|
|
3809
|
+
className: "block cursor-pointer",
|
|
3810
|
+
children: /* @__PURE__ */ jsx10(
|
|
3811
|
+
"img",
|
|
3812
|
+
{
|
|
3813
|
+
src: url,
|
|
3814
|
+
alt: `Attachment ${imgIndex + 1}`,
|
|
3815
|
+
className: "max-h-32 max-w-[200px] rounded-lg object-cover border border-gray-300 hover:opacity-90 transition-opacity"
|
|
3816
|
+
}
|
|
3817
|
+
)
|
|
3818
|
+
},
|
|
3819
|
+
imgIndex
|
|
3820
|
+
)) }),
|
|
3821
|
+
agentTextContent && /* @__PURE__ */ jsx10("div", { className: "max-w-[300px] rounded-2xl rounded-bl-md bg-gray-100 px-4 py-3 text-sm text-gray-700", children: agentTextContent })
|
|
3575
3822
|
] }, message.id);
|
|
3576
3823
|
}
|
|
3577
3824
|
if (message.kind === "searchSummary") {
|
|
@@ -4607,131 +4854,183 @@ ${userText}`
|
|
|
4607
4854
|
progressSteps
|
|
4608
4855
|
}
|
|
4609
4856
|
) }),
|
|
4610
|
-
isEscalated && agentIsTyping && /* @__PURE__ */ jsx10("div", { className: "mt-2", children: /* @__PURE__ */ jsx10(TypingIndicator, {}) }),
|
|
4857
|
+
isEscalated && agentIsTyping && /* @__PURE__ */ jsx10("div", { className: "flex items-start mt-2", children: /* @__PURE__ */ jsx10("div", { className: "bg-gray-200 rounded-2xl rounded-bl-md px-4 py-3", children: /* @__PURE__ */ jsx10(TypingIndicator, {}) }) }),
|
|
4611
4858
|
!activeGuide && /* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
|
|
4612
4859
|
] }) }) }) })
|
|
4613
4860
|
}
|
|
4614
4861
|
),
|
|
4615
|
-
/* @__PURE__ */ jsxs6(
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
ref: fileInputRef,
|
|
4637
|
-
type: "file",
|
|
4638
|
-
accept: ".csv",
|
|
4639
|
-
className: "hidden",
|
|
4640
|
-
onChange: (e) => {
|
|
4641
|
-
const file = e.target.files?.[0];
|
|
4642
|
-
if (file) {
|
|
4643
|
-
setPendingFile(file);
|
|
4862
|
+
/* @__PURE__ */ jsxs6(
|
|
4863
|
+
"div",
|
|
4864
|
+
{
|
|
4865
|
+
className: `px-4 py-3 bg-white shrink-0 ${isDragOver ? "ring-2 ring-blue-400 ring-inset bg-blue-50" : ""}`,
|
|
4866
|
+
onDragOver: handleDragOver,
|
|
4867
|
+
onDragLeave: handleDragLeave,
|
|
4868
|
+
onDrop: handleDrop,
|
|
4869
|
+
children: [
|
|
4870
|
+
pendingFile && /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-center gap-2 rounded-xl bg-blue-50 border border-blue-200 px-3 py-2", children: [
|
|
4871
|
+
/* @__PURE__ */ jsx10(FileSpreadsheet, { className: "h-4 w-4 text-blue-600" }),
|
|
4872
|
+
/* @__PURE__ */ jsx10("span", { className: "text-xs text-blue-700 flex-1 truncate", children: pendingFile.name }),
|
|
4873
|
+
/* @__PURE__ */ jsx10(
|
|
4874
|
+
"button",
|
|
4875
|
+
{
|
|
4876
|
+
type: "button",
|
|
4877
|
+
onClick: () => {
|
|
4878
|
+
setPendingFile(null);
|
|
4879
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
4880
|
+
},
|
|
4881
|
+
className: "text-blue-600 hover:text-blue-800",
|
|
4882
|
+
children: /* @__PURE__ */ jsx10(X, { className: "h-4 w-4" })
|
|
4644
4883
|
}
|
|
4645
|
-
|
|
4646
|
-
}
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
onClick: () => fileInputRef.current?.click(),
|
|
4656
|
-
className: "h-5 w-5 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100",
|
|
4657
|
-
title: "Upload CSV for bulk operations",
|
|
4658
|
-
children: /* @__PURE__ */ jsx10(Paperclip, { className: "h-2.5 w-2.5" })
|
|
4659
|
-
}
|
|
4660
|
-
),
|
|
4661
|
-
/* @__PURE__ */ jsx10(
|
|
4662
|
-
"textarea",
|
|
4663
|
-
{
|
|
4664
|
-
placeholder: pendingFile ? "Describe what to do with this CSV..." : "Ask anything...",
|
|
4665
|
-
value: input,
|
|
4666
|
-
onChange: (e) => {
|
|
4667
|
-
setInput(e.target.value);
|
|
4668
|
-
if (e.target.value.length > 0) {
|
|
4669
|
-
handleTypingStart();
|
|
4884
|
+
)
|
|
4885
|
+
] }),
|
|
4886
|
+
pendingImages.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex flex-wrap gap-2", children: [
|
|
4887
|
+
pendingImages.map((img, index) => /* @__PURE__ */ jsxs6("div", { className: "relative group", children: [
|
|
4888
|
+
img.preview ? /* @__PURE__ */ jsx10(
|
|
4889
|
+
"img",
|
|
4890
|
+
{
|
|
4891
|
+
src: img.preview,
|
|
4892
|
+
alt: `Preview ${index + 1}`,
|
|
4893
|
+
className: "h-16 w-16 object-cover rounded-lg border border-gray-200"
|
|
4670
4894
|
}
|
|
4671
|
-
},
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
e.preventDefault();
|
|
4683
|
-
if (input.trim() || pendingFile) {
|
|
4684
|
-
const form = e.currentTarget.closest("form");
|
|
4685
|
-
if (form) {
|
|
4686
|
-
form.requestSubmit();
|
|
4687
|
-
}
|
|
4688
|
-
}
|
|
4689
|
-
return;
|
|
4895
|
+
) : /* @__PURE__ */ jsx10("div", { className: "h-16 w-16 rounded-lg border border-gray-200 bg-gray-100 flex items-center justify-center", children: /* @__PURE__ */ jsx10(FileSpreadsheet, { className: "h-6 w-6 text-gray-400" }) }),
|
|
4896
|
+
/* @__PURE__ */ jsx10(
|
|
4897
|
+
"button",
|
|
4898
|
+
{
|
|
4899
|
+
type: "button",
|
|
4900
|
+
onClick: () => {
|
|
4901
|
+
if (img.preview) URL.revokeObjectURL(img.preview);
|
|
4902
|
+
setPendingImages((prev) => prev.filter((_, i) => i !== index));
|
|
4903
|
+
},
|
|
4904
|
+
className: "absolute -top-1 -right-1 h-4 w-4 rounded-full bg-gray-800 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
4905
|
+
children: /* @__PURE__ */ jsx10(X, { className: "h-2.5 w-2.5" })
|
|
4690
4906
|
}
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
if (
|
|
4706
|
-
|
|
4707
|
-
e.stopPropagation();
|
|
4708
|
-
handleConfirmNavigation(pendingNavigation);
|
|
4709
|
-
return;
|
|
4710
|
-
}
|
|
4711
|
-
const currentGuide = activeGuideRef.current;
|
|
4712
|
-
if (currentGuide) {
|
|
4713
|
-
e.preventDefault();
|
|
4714
|
-
e.stopPropagation();
|
|
4715
|
-
advanceGuide();
|
|
4716
|
-
return;
|
|
4907
|
+
)
|
|
4908
|
+
] }, index)),
|
|
4909
|
+
isUploadingImage && /* @__PURE__ */ jsx10("div", { className: "h-16 w-16 rounded-lg border border-gray-200 bg-gray-50 flex items-center justify-center", children: /* @__PURE__ */ jsx10(Loader22, { className: "h-5 w-5 animate-spin text-gray-400" }) })
|
|
4910
|
+
] }),
|
|
4911
|
+
/* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "w-full", children: [
|
|
4912
|
+
/* @__PURE__ */ jsx10(
|
|
4913
|
+
"input",
|
|
4914
|
+
{
|
|
4915
|
+
ref: fileInputRef,
|
|
4916
|
+
type: "file",
|
|
4917
|
+
accept: ".csv",
|
|
4918
|
+
className: "hidden",
|
|
4919
|
+
onChange: (e) => {
|
|
4920
|
+
const file = e.target.files?.[0];
|
|
4921
|
+
if (file) {
|
|
4922
|
+
setPendingFile(file);
|
|
4717
4923
|
}
|
|
4718
4924
|
}
|
|
4719
4925
|
}
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4926
|
+
),
|
|
4927
|
+
/* @__PURE__ */ jsx10(
|
|
4928
|
+
"input",
|
|
4929
|
+
{
|
|
4930
|
+
ref: imageInputRef,
|
|
4931
|
+
type: "file",
|
|
4932
|
+
accept: "image/*,.pdf",
|
|
4933
|
+
multiple: true,
|
|
4934
|
+
className: "hidden",
|
|
4935
|
+
onChange: (e) => handleImageSelect(e.target.files)
|
|
4936
|
+
}
|
|
4937
|
+
),
|
|
4938
|
+
/* @__PURE__ */ jsxs6("div", { className: `flex w-full items-start gap-2 rounded-xl border bg-white px-3 py-2 shadow-sm ${isDragOver ? "border-blue-400" : "border-gray-200"}`, children: [
|
|
4939
|
+
/* @__PURE__ */ jsx10(
|
|
4940
|
+
Button,
|
|
4941
|
+
{
|
|
4942
|
+
type: "button",
|
|
4943
|
+
size: "icon",
|
|
4944
|
+
variant: "ghost",
|
|
4945
|
+
onClick: () => {
|
|
4946
|
+
if (isEscalated) {
|
|
4947
|
+
imageInputRef.current?.click();
|
|
4948
|
+
} else {
|
|
4949
|
+
fileInputRef.current?.click();
|
|
4950
|
+
}
|
|
4951
|
+
},
|
|
4952
|
+
className: "h-5 w-5 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100",
|
|
4953
|
+
title: isEscalated ? "Attach image or file" : "Upload CSV for bulk operations",
|
|
4954
|
+
disabled: isUploadingImage,
|
|
4955
|
+
children: /* @__PURE__ */ jsx10(Paperclip, { className: "h-2.5 w-2.5" })
|
|
4956
|
+
}
|
|
4957
|
+
),
|
|
4958
|
+
/* @__PURE__ */ jsx10(
|
|
4959
|
+
"textarea",
|
|
4960
|
+
{
|
|
4961
|
+
placeholder: pendingFile ? "Describe what to do with this CSV..." : pendingImages.length > 0 ? "Add a message (optional)..." : isDragOver ? "Drop files here..." : "Ask anything...",
|
|
4962
|
+
value: input,
|
|
4963
|
+
onChange: (e) => {
|
|
4964
|
+
setInput(e.target.value);
|
|
4965
|
+
if (e.target.value.length > 0) {
|
|
4966
|
+
handleTypingStart();
|
|
4967
|
+
}
|
|
4968
|
+
},
|
|
4969
|
+
rows: 1,
|
|
4970
|
+
className: "flex-1 border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 text-sm placeholder:text-gray-400 resize-none overflow-hidden outline-none",
|
|
4971
|
+
style: { minHeight: "20px", maxHeight: "120px" },
|
|
4972
|
+
onInput: (e) => {
|
|
4973
|
+
const target = e.target;
|
|
4974
|
+
target.style.height = "auto";
|
|
4975
|
+
target.style.height = Math.min(target.scrollHeight, 120) + "px";
|
|
4976
|
+
},
|
|
4977
|
+
onKeyDown: (e) => {
|
|
4978
|
+
if (e.key === "Enter" && !e.shiftKey && !e.metaKey && !e.ctrlKey) {
|
|
4979
|
+
e.preventDefault();
|
|
4980
|
+
if (input.trim() || pendingFile || pendingImages.length > 0) {
|
|
4981
|
+
const form = e.currentTarget.closest("form");
|
|
4982
|
+
if (form) {
|
|
4983
|
+
form.requestSubmit();
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
return;
|
|
4987
|
+
}
|
|
4988
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
4989
|
+
const currentBulkSession = pendingBulkSessionRef.current;
|
|
4990
|
+
if (currentBulkSession) {
|
|
4991
|
+
e.preventDefault();
|
|
4992
|
+
e.stopPropagation();
|
|
4993
|
+
confirmBulkOperation(currentBulkSession);
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
if (pendingAction) {
|
|
4997
|
+
e.preventDefault();
|
|
4998
|
+
e.stopPropagation();
|
|
4999
|
+
handleActionSubmit();
|
|
5000
|
+
return;
|
|
5001
|
+
}
|
|
5002
|
+
if (pendingNavigation) {
|
|
5003
|
+
e.preventDefault();
|
|
5004
|
+
e.stopPropagation();
|
|
5005
|
+
handleConfirmNavigation(pendingNavigation);
|
|
5006
|
+
return;
|
|
5007
|
+
}
|
|
5008
|
+
const currentGuide = activeGuideRef.current;
|
|
5009
|
+
if (currentGuide) {
|
|
5010
|
+
e.preventDefault();
|
|
5011
|
+
e.stopPropagation();
|
|
5012
|
+
advanceGuide();
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
}
|
|
5017
|
+
}
|
|
5018
|
+
),
|
|
5019
|
+
/* @__PURE__ */ jsx10(
|
|
5020
|
+
Button,
|
|
5021
|
+
{
|
|
5022
|
+
type: "submit",
|
|
5023
|
+
size: "icon",
|
|
5024
|
+
disabled: !input.trim() && !pendingFile || isWaitingForAuth,
|
|
5025
|
+
className: "h-6 w-6 rounded-full bg-gray-700 hover:bg-gray-600 disabled:bg-gray-300",
|
|
5026
|
+
children: /* @__PURE__ */ jsx10(ArrowUp, { className: "h-2.5 w-2.5 text-white" })
|
|
5027
|
+
}
|
|
5028
|
+
)
|
|
5029
|
+
] })
|
|
5030
|
+
] })
|
|
5031
|
+
]
|
|
5032
|
+
}
|
|
5033
|
+
),
|
|
4735
5034
|
/* @__PURE__ */ jsx10(
|
|
4736
5035
|
GuideCursor,
|
|
4737
5036
|
{
|
|
@@ -4740,6 +5039,13 @@ ${userText}`
|
|
|
4740
5039
|
visible: cursorState.visible,
|
|
4741
5040
|
onClick: cursorState.onClick
|
|
4742
5041
|
}
|
|
5042
|
+
),
|
|
5043
|
+
lightboxImageUrl && /* @__PURE__ */ jsx10(
|
|
5044
|
+
ImageLightbox,
|
|
5045
|
+
{
|
|
5046
|
+
imageUrl: lightboxImageUrl,
|
|
5047
|
+
onClose: () => setLightboxImageUrl(null)
|
|
5048
|
+
}
|
|
4743
5049
|
)
|
|
4744
5050
|
]
|
|
4745
5051
|
}
|
|
@@ -4784,7 +5090,8 @@ function ChatPanelWithToggle({
|
|
|
4784
5090
|
initialCorner,
|
|
4785
5091
|
onCornerChange,
|
|
4786
5092
|
productBackendUrl,
|
|
4787
|
-
getAuthHeaders
|
|
5093
|
+
getAuthHeaders,
|
|
5094
|
+
isEval
|
|
4788
5095
|
}) {
|
|
4789
5096
|
const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
|
|
4790
5097
|
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
@@ -4815,7 +5122,8 @@ function ChatPanelWithToggle({
|
|
|
4815
5122
|
initialCorner,
|
|
4816
5123
|
onCornerChange,
|
|
4817
5124
|
productBackendUrl,
|
|
4818
|
-
getAuthHeaders
|
|
5125
|
+
getAuthHeaders,
|
|
5126
|
+
isEval
|
|
4819
5127
|
}
|
|
4820
5128
|
);
|
|
4821
5129
|
}
|