@kite-copilot/chat-panel 0.2.38 → 0.2.40
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 +247 -72
- package/dist/auto.d.cts +1 -1
- package/dist/auto.d.ts +1 -1
- package/dist/auto.js +1 -1
- package/dist/{chunk-QSVOPKVC.js → chunk-XMA5S556.js} +255 -80
- package/dist/{createKiteChat-jmAPjuv_.d.cts → createKiteChat-o5u-5Sor.d.cts} +8 -2
- package/dist/{createKiteChat-jmAPjuv_.d.ts → createKiteChat-o5u-5Sor.d.ts} +8 -2
- package/dist/embed.global.js +35 -64
- package/dist/index.cjs +247 -72
- 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
|
@@ -882,10 +882,62 @@ function DataRenderer({ type, data }) {
|
|
|
882
882
|
}
|
|
883
883
|
|
|
884
884
|
// src/ChatPanel.tsx
|
|
885
|
-
import * as
|
|
885
|
+
import * as React5 from "react";
|
|
886
886
|
import { createClient } from "@supabase/supabase-js";
|
|
887
887
|
import { ArrowLeft, ArrowUp, Command, CornerDownLeft, CheckCircle2 as CheckCircle23, SquarePen, Paperclip, X, FileSpreadsheet, Loader2 as Loader22, ChevronLeft, ChevronRight, Sparkles, Minus } from "lucide-react";
|
|
888
888
|
|
|
889
|
+
// src/hooks/useUserAuth.ts
|
|
890
|
+
import * as React4 from "react";
|
|
891
|
+
function useUserAuth({
|
|
892
|
+
productBackendUrl,
|
|
893
|
+
sessionId,
|
|
894
|
+
enabled = true
|
|
895
|
+
}) {
|
|
896
|
+
const [authState, setAuthState] = React4.useState({ status: "idle" });
|
|
897
|
+
const lastSessionIdRef = React4.useRef(null);
|
|
898
|
+
const fetchUser = React4.useCallback(async () => {
|
|
899
|
+
if (!productBackendUrl || !enabled) {
|
|
900
|
+
setAuthState({ status: "idle" });
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
setAuthState({ status: "loading" });
|
|
904
|
+
try {
|
|
905
|
+
const response = await fetch(`${productBackendUrl}/users/me`, {
|
|
906
|
+
method: "GET",
|
|
907
|
+
credentials: "include",
|
|
908
|
+
// Include cookies for authentication
|
|
909
|
+
headers: {
|
|
910
|
+
"Accept": "application/json"
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
if (!response.ok) {
|
|
914
|
+
if (response.status === 401) {
|
|
915
|
+
throw new Error("Please log in to use the chat assistant.");
|
|
916
|
+
}
|
|
917
|
+
if (response.status === 403) {
|
|
918
|
+
throw new Error("You do not have permission to access this feature.");
|
|
919
|
+
}
|
|
920
|
+
throw new Error(`Authentication failed (${response.status})`);
|
|
921
|
+
}
|
|
922
|
+
const user = await response.json();
|
|
923
|
+
setAuthState({ status: "authenticated", user });
|
|
924
|
+
} catch (error) {
|
|
925
|
+
const message = error instanceof Error ? error.message : "Unable to verify your identity. Please try again.";
|
|
926
|
+
setAuthState({ status: "error", error: message });
|
|
927
|
+
}
|
|
928
|
+
}, [productBackendUrl, enabled]);
|
|
929
|
+
React4.useEffect(() => {
|
|
930
|
+
if (sessionId !== lastSessionIdRef.current) {
|
|
931
|
+
lastSessionIdRef.current = sessionId;
|
|
932
|
+
fetchUser();
|
|
933
|
+
}
|
|
934
|
+
}, [sessionId, fetchUser]);
|
|
935
|
+
const retry = React4.useCallback(() => {
|
|
936
|
+
fetchUser();
|
|
937
|
+
}, [fetchUser]);
|
|
938
|
+
return { authState, retry };
|
|
939
|
+
}
|
|
940
|
+
|
|
889
941
|
// src/components/TypingIndicator.tsx
|
|
890
942
|
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
891
943
|
function TypingIndicator({ className = "" }) {
|
|
@@ -916,7 +968,7 @@ function TypingIndicator({ className = "" }) {
|
|
|
916
968
|
|
|
917
969
|
// src/ChatPanel.tsx
|
|
918
970
|
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
919
|
-
var CHAT_PANEL_VERSION = true ? "0.2.
|
|
971
|
+
var CHAT_PANEL_VERSION = true ? "0.2.40" : "dev";
|
|
920
972
|
var DEFAULT_AGENT_URL = "http://localhost:5002";
|
|
921
973
|
var PANEL_WIDTH = 340;
|
|
922
974
|
function unescapeJsonString(str) {
|
|
@@ -1334,6 +1386,32 @@ var guides = {
|
|
|
1334
1386
|
}
|
|
1335
1387
|
};
|
|
1336
1388
|
var initialMessages = [];
|
|
1389
|
+
function AuthLoadingState() {
|
|
1390
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center h-full p-6", children: [
|
|
1391
|
+
/* @__PURE__ */ jsx10(Loader22, { className: "h-8 w-8 animate-spin text-gray-400 mb-3" }),
|
|
1392
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-gray-500", children: "Verifying your identity..." })
|
|
1393
|
+
] });
|
|
1394
|
+
}
|
|
1395
|
+
function AuthErrorState({
|
|
1396
|
+
error,
|
|
1397
|
+
onRetry
|
|
1398
|
+
}) {
|
|
1399
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center h-full p-6 text-center", children: [
|
|
1400
|
+
/* @__PURE__ */ jsx10("div", { className: "w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx10(X, { className: "h-6 w-6 text-red-600" }) }),
|
|
1401
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-gray-900 mb-2", children: "Unable to Start Chat" }),
|
|
1402
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-gray-500 mb-4 max-w-[240px]", children: error }),
|
|
1403
|
+
/* @__PURE__ */ jsx10(
|
|
1404
|
+
Button,
|
|
1405
|
+
{
|
|
1406
|
+
variant: "secondary",
|
|
1407
|
+
size: "sm",
|
|
1408
|
+
onClick: onRetry,
|
|
1409
|
+
className: "h-8 px-4 text-xs",
|
|
1410
|
+
children: "Try Again"
|
|
1411
|
+
}
|
|
1412
|
+
)
|
|
1413
|
+
] });
|
|
1414
|
+
}
|
|
1337
1415
|
function ChatPanel({
|
|
1338
1416
|
isOpen = true,
|
|
1339
1417
|
onClose,
|
|
@@ -1351,26 +1429,62 @@ function ChatPanel({
|
|
|
1351
1429
|
userEmail,
|
|
1352
1430
|
userOrganization,
|
|
1353
1431
|
supabaseUrl,
|
|
1354
|
-
supabaseAnonKey
|
|
1432
|
+
supabaseAnonKey,
|
|
1433
|
+
productBackendUrl
|
|
1355
1434
|
} = {}) {
|
|
1356
|
-
const [messages, setMessages] =
|
|
1357
|
-
const [input, setInput] =
|
|
1358
|
-
const [sessionId, setSessionId] =
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1435
|
+
const [messages, setMessages] = React5.useState(initialMessages);
|
|
1436
|
+
const [input, setInput] = React5.useState("");
|
|
1437
|
+
const [sessionId, setSessionId] = React5.useState(() => crypto.randomUUID());
|
|
1438
|
+
const { authState, retry: retryAuth } = useUserAuth({
|
|
1439
|
+
productBackendUrl,
|
|
1440
|
+
sessionId,
|
|
1441
|
+
enabled: !!productBackendUrl
|
|
1442
|
+
// Only enable if URL is provided
|
|
1443
|
+
});
|
|
1444
|
+
const effectiveUser = React5.useMemo(() => {
|
|
1445
|
+
if (authState.status === "authenticated") {
|
|
1446
|
+
return {
|
|
1447
|
+
userId: authState.user.id,
|
|
1448
|
+
userName: authState.user.name,
|
|
1449
|
+
userEmail: authState.user.email,
|
|
1450
|
+
userRole: authState.user.role,
|
|
1451
|
+
isInternal: authState.user.isInternal
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
return {
|
|
1455
|
+
userId: userId || "anonymous",
|
|
1456
|
+
userName: userName || "Anonymous User",
|
|
1457
|
+
userEmail: userEmail || "Not provided",
|
|
1458
|
+
userRole: void 0,
|
|
1459
|
+
isInternal: false
|
|
1460
|
+
};
|
|
1461
|
+
}, [authState, userId, userName, userEmail]);
|
|
1462
|
+
const [isEscalated, setIsEscalated] = React5.useState(false);
|
|
1463
|
+
const escalationWsRef = React5.useRef(null);
|
|
1464
|
+
const [agentIsTyping, setAgentIsTyping] = React5.useState(false);
|
|
1465
|
+
const supabaseRef = React5.useRef(null);
|
|
1466
|
+
const typingChannelRef = React5.useRef(null);
|
|
1467
|
+
const typingTimeoutRef = React5.useRef(null);
|
|
1468
|
+
React5.useEffect(() => {
|
|
1366
1469
|
console.log(`[KiteChat] Chat Panel v${CHAT_PANEL_VERSION} loaded`);
|
|
1367
1470
|
}, []);
|
|
1368
|
-
const resetSession =
|
|
1471
|
+
const resetSession = React5.useCallback(() => {
|
|
1472
|
+
console.log("[KiteChat] resetSession called", { isEscalated, hasSupabase: !!supabaseRef.current, sessionId });
|
|
1369
1473
|
if (isEscalated && supabaseRef.current && sessionId) {
|
|
1474
|
+
console.log("[KiteChat] Updating customer_status to disconnected for session:", sessionId);
|
|
1370
1475
|
supabaseRef.current.from("escalations").update({
|
|
1371
1476
|
customer_status: "disconnected",
|
|
1372
1477
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1373
|
-
}).eq("session_id", sessionId)
|
|
1478
|
+
}).eq("session_id", sessionId).then(
|
|
1479
|
+
(result) => {
|
|
1480
|
+
console.log("[KiteChat] Disconnect update result:", result);
|
|
1481
|
+
},
|
|
1482
|
+
(err) => {
|
|
1483
|
+
console.error("[KiteChat] Disconnect update failed:", err);
|
|
1484
|
+
}
|
|
1485
|
+
);
|
|
1486
|
+
} else {
|
|
1487
|
+
console.log("[KiteChat] Skipping disconnect update - conditions not met");
|
|
1374
1488
|
}
|
|
1375
1489
|
setSessionId(crypto.randomUUID());
|
|
1376
1490
|
setIsEscalated(false);
|
|
@@ -1384,12 +1498,12 @@ function ChatPanel({
|
|
|
1384
1498
|
typingChannelRef.current = null;
|
|
1385
1499
|
}
|
|
1386
1500
|
}, [isEscalated, sessionId]);
|
|
1387
|
-
|
|
1501
|
+
React5.useEffect(() => {
|
|
1388
1502
|
if (supabaseUrl && supabaseAnonKey && !supabaseRef.current) {
|
|
1389
1503
|
supabaseRef.current = createClient(supabaseUrl, supabaseAnonKey);
|
|
1390
1504
|
}
|
|
1391
1505
|
}, [supabaseUrl, supabaseAnonKey]);
|
|
1392
|
-
|
|
1506
|
+
React5.useEffect(() => {
|
|
1393
1507
|
if (!isEscalated || !sessionId || !supabaseRef.current) {
|
|
1394
1508
|
return;
|
|
1395
1509
|
}
|
|
@@ -1426,8 +1540,8 @@ function ChatPanel({
|
|
|
1426
1540
|
}
|
|
1427
1541
|
};
|
|
1428
1542
|
}, [isEscalated, sessionId]);
|
|
1429
|
-
const heartbeatIntervalRef =
|
|
1430
|
-
const updateCustomerStatus =
|
|
1543
|
+
const heartbeatIntervalRef = React5.useRef(null);
|
|
1544
|
+
const updateCustomerStatus = React5.useCallback(async (status) => {
|
|
1431
1545
|
if (!supabaseRef.current || !sessionId) return;
|
|
1432
1546
|
try {
|
|
1433
1547
|
await supabaseRef.current.from("escalations").update({
|
|
@@ -1438,7 +1552,7 @@ function ChatPanel({
|
|
|
1438
1552
|
console.error("[KiteChat] Failed to update customer status:", err);
|
|
1439
1553
|
}
|
|
1440
1554
|
}, [sessionId]);
|
|
1441
|
-
|
|
1555
|
+
React5.useEffect(() => {
|
|
1442
1556
|
if (!isEscalated || !sessionId || !supabaseRef.current) {
|
|
1443
1557
|
return;
|
|
1444
1558
|
}
|
|
@@ -1486,7 +1600,7 @@ function ChatPanel({
|
|
|
1486
1600
|
}
|
|
1487
1601
|
};
|
|
1488
1602
|
}, [isEscalated, sessionId, updateCustomerStatus]);
|
|
1489
|
-
const sendTypingIndicator =
|
|
1603
|
+
const sendTypingIndicator = React5.useCallback((isTyping) => {
|
|
1490
1604
|
if (!typingChannelRef.current) {
|
|
1491
1605
|
console.log("[KiteChat] Cannot send typing - channel not ready");
|
|
1492
1606
|
return;
|
|
@@ -1502,8 +1616,8 @@ function ChatPanel({
|
|
|
1502
1616
|
payload: { sender: "user", isTyping }
|
|
1503
1617
|
});
|
|
1504
1618
|
}, [isEscalated]);
|
|
1505
|
-
const userTypingTimeoutRef =
|
|
1506
|
-
const handleTypingStart =
|
|
1619
|
+
const userTypingTimeoutRef = React5.useRef(null);
|
|
1620
|
+
const handleTypingStart = React5.useCallback(() => {
|
|
1507
1621
|
if (!isEscalated || !supabaseRef.current) return;
|
|
1508
1622
|
sendTypingIndicator(true);
|
|
1509
1623
|
updateCustomerStatus("active");
|
|
@@ -1514,19 +1628,19 @@ function ChatPanel({
|
|
|
1514
1628
|
sendTypingIndicator(false);
|
|
1515
1629
|
}, 1500);
|
|
1516
1630
|
}, [isEscalated, sendTypingIndicator, updateCustomerStatus]);
|
|
1517
|
-
const streamIntervals =
|
|
1631
|
+
const streamIntervals = React5.useRef({});
|
|
1518
1632
|
const isEmpty = messages.length === 0;
|
|
1519
|
-
const [phase, setPhase] =
|
|
1520
|
-
const [progressSteps, setProgressSteps] =
|
|
1521
|
-
const phaseTimers =
|
|
1633
|
+
const [phase, setPhase] = React5.useState("idle");
|
|
1634
|
+
const [progressSteps, setProgressSteps] = React5.useState([]);
|
|
1635
|
+
const phaseTimers = React5.useRef([]);
|
|
1522
1636
|
const lastRole = messages.length ? messages[messages.length - 1].role : void 0;
|
|
1523
|
-
const [panelView, setPanelView] =
|
|
1637
|
+
const [panelView, setPanelView] = React5.useState(
|
|
1524
1638
|
"landing"
|
|
1525
1639
|
);
|
|
1526
|
-
const [currentFolderId, setCurrentFolderId] =
|
|
1527
|
-
const [startingQuestions, setStartingQuestions] =
|
|
1528
|
-
const [loadingQuestions, setLoadingQuestions] =
|
|
1529
|
-
|
|
1640
|
+
const [currentFolderId, setCurrentFolderId] = React5.useState(void 0);
|
|
1641
|
+
const [startingQuestions, setStartingQuestions] = React5.useState(startingQuestionsProp || defaultStartingQuestions);
|
|
1642
|
+
const [loadingQuestions, setLoadingQuestions] = React5.useState(false);
|
|
1643
|
+
React5.useEffect(() => {
|
|
1530
1644
|
if (startingQuestionsEndpoint && !startingQuestionsProp) {
|
|
1531
1645
|
setLoadingQuestions(true);
|
|
1532
1646
|
fetch(startingQuestionsEndpoint).then((res) => res.json()).then((data) => {
|
|
@@ -1538,16 +1652,16 @@ function ChatPanel({
|
|
|
1538
1652
|
}).finally(() => setLoadingQuestions(false));
|
|
1539
1653
|
}
|
|
1540
1654
|
}, [startingQuestionsEndpoint, startingQuestionsProp]);
|
|
1541
|
-
|
|
1655
|
+
React5.useEffect(() => {
|
|
1542
1656
|
if (startingQuestionsProp) {
|
|
1543
1657
|
setStartingQuestions(startingQuestionsProp);
|
|
1544
1658
|
}
|
|
1545
1659
|
}, [startingQuestionsProp]);
|
|
1546
|
-
const [activeGuide, setActiveGuide] =
|
|
1547
|
-
const activeGuideRef =
|
|
1548
|
-
const latestBulkSummaryNavigationRef =
|
|
1549
|
-
const [guideComplete, setGuideComplete] =
|
|
1550
|
-
|
|
1660
|
+
const [activeGuide, setActiveGuide] = React5.useState(void 0);
|
|
1661
|
+
const activeGuideRef = React5.useRef(void 0);
|
|
1662
|
+
const latestBulkSummaryNavigationRef = React5.useRef(null);
|
|
1663
|
+
const [guideComplete, setGuideComplete] = React5.useState(false);
|
|
1664
|
+
React5.useEffect(() => {
|
|
1551
1665
|
window.resetIntegrationNotification = () => {
|
|
1552
1666
|
localStorage.removeItem("gmailNotificationSeen");
|
|
1553
1667
|
console.log(
|
|
@@ -1581,7 +1695,7 @@ function ChatPanel({
|
|
|
1581
1695
|
);
|
|
1582
1696
|
};
|
|
1583
1697
|
}, []);
|
|
1584
|
-
|
|
1698
|
+
React5.useEffect(() => {
|
|
1585
1699
|
if (activeGuide) {
|
|
1586
1700
|
if (!activeGuideRef.current || activeGuideRef.current.id !== activeGuide.id || activeGuideRef.current.stepIndex !== activeGuide.stepIndex) {
|
|
1587
1701
|
activeGuideRef.current = activeGuide;
|
|
@@ -1590,21 +1704,21 @@ function ChatPanel({
|
|
|
1590
1704
|
activeGuideRef.current = void 0;
|
|
1591
1705
|
}
|
|
1592
1706
|
}, [activeGuide]);
|
|
1593
|
-
const [pendingNavigation, setPendingNavigation] =
|
|
1594
|
-
const [pendingAction, setPendingAction] =
|
|
1595
|
-
const [actionFormData, setActionFormData] =
|
|
1596
|
-
const messagesEndRef =
|
|
1597
|
-
const messagesContainerRef =
|
|
1598
|
-
const currentStepRef =
|
|
1707
|
+
const [pendingNavigation, setPendingNavigation] = React5.useState(null);
|
|
1708
|
+
const [pendingAction, setPendingAction] = React5.useState(null);
|
|
1709
|
+
const [actionFormData, setActionFormData] = React5.useState({});
|
|
1710
|
+
const messagesEndRef = React5.useRef(null);
|
|
1711
|
+
const messagesContainerRef = React5.useRef(null);
|
|
1712
|
+
const currentStepRef = React5.useRef(null);
|
|
1599
1713
|
const { cursorState, moveTo, hide } = useGuideCursor();
|
|
1600
|
-
const [pendingFile, setPendingFile] =
|
|
1601
|
-
const [pendingBulkSession, setPendingBulkSession] =
|
|
1602
|
-
const pendingBulkSessionRef =
|
|
1603
|
-
const fileInputRef =
|
|
1604
|
-
const [searchExpanded, setSearchExpanded] =
|
|
1605
|
-
const [searchInput, setSearchInput] =
|
|
1606
|
-
const searchInputRef =
|
|
1607
|
-
|
|
1714
|
+
const [pendingFile, setPendingFile] = React5.useState(null);
|
|
1715
|
+
const [pendingBulkSession, setPendingBulkSession] = React5.useState(null);
|
|
1716
|
+
const pendingBulkSessionRef = React5.useRef(null);
|
|
1717
|
+
const fileInputRef = React5.useRef(null);
|
|
1718
|
+
const [searchExpanded, setSearchExpanded] = React5.useState(false);
|
|
1719
|
+
const [searchInput, setSearchInput] = React5.useState("");
|
|
1720
|
+
const searchInputRef = React5.useRef(null);
|
|
1721
|
+
React5.useEffect(() => {
|
|
1608
1722
|
if (!activeGuide || activeGuide.id !== "add-api-key" || activeGuide.stepIndex !== 2) {
|
|
1609
1723
|
return;
|
|
1610
1724
|
}
|
|
@@ -1630,7 +1744,7 @@ function ChatPanel({
|
|
|
1630
1744
|
const interval = setInterval(checkForDialogOpen, 300);
|
|
1631
1745
|
return () => clearInterval(interval);
|
|
1632
1746
|
}, [activeGuide, hide]);
|
|
1633
|
-
|
|
1747
|
+
React5.useEffect(() => {
|
|
1634
1748
|
return () => {
|
|
1635
1749
|
Object.values(streamIntervals.current).forEach(
|
|
1636
1750
|
(id) => window.clearInterval(id)
|
|
@@ -1640,7 +1754,7 @@ function ChatPanel({
|
|
|
1640
1754
|
phaseTimers.current = [];
|
|
1641
1755
|
};
|
|
1642
1756
|
}, []);
|
|
1643
|
-
|
|
1757
|
+
React5.useEffect(() => {
|
|
1644
1758
|
if (activeGuide && messages.length > 0) {
|
|
1645
1759
|
const lastMessage = messages[messages.length - 1];
|
|
1646
1760
|
if (lastMessage.kind === "guideStep" || lastMessage.kind === "guideComplete") {
|
|
@@ -1657,7 +1771,7 @@ function ChatPanel({
|
|
|
1657
1771
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1658
1772
|
}
|
|
1659
1773
|
}, [messages, phase, activeGuide]);
|
|
1660
|
-
const latestBulkSummaryNavigation =
|
|
1774
|
+
const latestBulkSummaryNavigation = React5.useMemo(() => {
|
|
1661
1775
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1662
1776
|
const msg = messages[i];
|
|
1663
1777
|
if (msg.kind === "bulkSummary" && msg.bulkSummary?.navigationPage && msg.bulkSummary.successes > 0) {
|
|
@@ -1666,13 +1780,13 @@ function ChatPanel({
|
|
|
1666
1780
|
}
|
|
1667
1781
|
return null;
|
|
1668
1782
|
}, [messages]);
|
|
1669
|
-
|
|
1783
|
+
React5.useEffect(() => {
|
|
1670
1784
|
latestBulkSummaryNavigationRef.current = latestBulkSummaryNavigation;
|
|
1671
1785
|
}, [latestBulkSummaryNavigation]);
|
|
1672
|
-
|
|
1786
|
+
React5.useEffect(() => {
|
|
1673
1787
|
pendingBulkSessionRef.current = pendingBulkSession;
|
|
1674
1788
|
}, [pendingBulkSession]);
|
|
1675
|
-
|
|
1789
|
+
React5.useEffect(() => {
|
|
1676
1790
|
const handleKeyDown = (e) => {
|
|
1677
1791
|
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
1678
1792
|
const currentBulkSession = pendingBulkSessionRef.current;
|
|
@@ -1735,7 +1849,7 @@ function ChatPanel({
|
|
|
1735
1849
|
guideComplete,
|
|
1736
1850
|
onNavigate
|
|
1737
1851
|
]);
|
|
1738
|
-
const connectToEscalationWs =
|
|
1852
|
+
const connectToEscalationWs = React5.useCallback((currentSessionId) => {
|
|
1739
1853
|
if (!agentUrl) return;
|
|
1740
1854
|
if (escalationWsRef.current) {
|
|
1741
1855
|
escalationWsRef.current.close();
|
|
@@ -1778,7 +1892,7 @@ function ChatPanel({
|
|
|
1778
1892
|
};
|
|
1779
1893
|
escalationWsRef.current = ws;
|
|
1780
1894
|
}, [agentUrl]);
|
|
1781
|
-
const sendEscalatedMessage =
|
|
1895
|
+
const sendEscalatedMessage = React5.useCallback(async (content) => {
|
|
1782
1896
|
if (!escalationWsRef.current || escalationWsRef.current.readyState !== WebSocket.OPEN) {
|
|
1783
1897
|
console.error("[KiteChat] Escalation WebSocket not connected");
|
|
1784
1898
|
return false;
|
|
@@ -1795,14 +1909,14 @@ function ChatPanel({
|
|
|
1795
1909
|
return false;
|
|
1796
1910
|
}
|
|
1797
1911
|
}, [updateCustomerStatus]);
|
|
1798
|
-
|
|
1912
|
+
React5.useEffect(() => {
|
|
1799
1913
|
return () => {
|
|
1800
1914
|
if (escalationWsRef.current) {
|
|
1801
1915
|
escalationWsRef.current.close();
|
|
1802
1916
|
}
|
|
1803
1917
|
};
|
|
1804
1918
|
}, []);
|
|
1805
|
-
|
|
1919
|
+
React5.useEffect(() => {
|
|
1806
1920
|
if (isEscalated && sessionId) {
|
|
1807
1921
|
connectToEscalationWs(sessionId);
|
|
1808
1922
|
}
|
|
@@ -2077,9 +2191,9 @@ function ChatPanel({
|
|
|
2077
2191
|
session_id: sessionId,
|
|
2078
2192
|
message: userText,
|
|
2079
2193
|
current_page: currentPage || "dashboard",
|
|
2080
|
-
user_id: userId,
|
|
2081
|
-
user_name: userName,
|
|
2082
|
-
user_email: userEmail,
|
|
2194
|
+
user_id: effectiveUser.userId,
|
|
2195
|
+
user_name: effectiveUser.userName,
|
|
2196
|
+
user_email: effectiveUser.userEmail,
|
|
2083
2197
|
user_organization: userOrganization,
|
|
2084
2198
|
org_id: orgId
|
|
2085
2199
|
}),
|
|
@@ -3022,6 +3136,64 @@ ${userText}`
|
|
|
3022
3136
|
] })
|
|
3023
3137
|
] }) }) });
|
|
3024
3138
|
}
|
|
3139
|
+
if (productBackendUrl) {
|
|
3140
|
+
if (authState.status === "loading") {
|
|
3141
|
+
return /* @__PURE__ */ jsxs6(
|
|
3142
|
+
"section",
|
|
3143
|
+
{
|
|
3144
|
+
className: `fixed top-0 right-0 z-40 flex flex-col bg-white border-l border-gray-200 h-full overflow-hidden transition-transform duration-300 ${isOpen ? "translate-x-0" : "translate-x-full"}`,
|
|
3145
|
+
style: { width: `${PANEL_WIDTH}px` },
|
|
3146
|
+
children: [
|
|
3147
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0", children: [
|
|
3148
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2.5", children: [
|
|
3149
|
+
/* @__PURE__ */ jsx10(Sparkles, { className: "h-3.5 w-3.5 text-black", fill: "currentColor" }),
|
|
3150
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-gray-800", children: "Copilot" })
|
|
3151
|
+
] }),
|
|
3152
|
+
/* @__PURE__ */ jsx10(
|
|
3153
|
+
Button,
|
|
3154
|
+
{
|
|
3155
|
+
variant: "ghost",
|
|
3156
|
+
size: "sm",
|
|
3157
|
+
className: "h-7 w-7 p-0 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-full",
|
|
3158
|
+
onClick: () => onClose?.(),
|
|
3159
|
+
children: /* @__PURE__ */ jsx10(Minus, { className: "h-3.5 w-3.5" })
|
|
3160
|
+
}
|
|
3161
|
+
)
|
|
3162
|
+
] }),
|
|
3163
|
+
/* @__PURE__ */ jsx10(AuthLoadingState, {})
|
|
3164
|
+
]
|
|
3165
|
+
}
|
|
3166
|
+
);
|
|
3167
|
+
}
|
|
3168
|
+
if (authState.status === "error") {
|
|
3169
|
+
return /* @__PURE__ */ jsxs6(
|
|
3170
|
+
"section",
|
|
3171
|
+
{
|
|
3172
|
+
className: `fixed top-0 right-0 z-40 flex flex-col bg-white border-l border-gray-200 h-full overflow-hidden transition-transform duration-300 ${isOpen ? "translate-x-0" : "translate-x-full"}`,
|
|
3173
|
+
style: { width: `${PANEL_WIDTH}px` },
|
|
3174
|
+
children: [
|
|
3175
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0", children: [
|
|
3176
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2.5", children: [
|
|
3177
|
+
/* @__PURE__ */ jsx10(Sparkles, { className: "h-3.5 w-3.5 text-black", fill: "currentColor" }),
|
|
3178
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-gray-800", children: "Copilot" })
|
|
3179
|
+
] }),
|
|
3180
|
+
/* @__PURE__ */ jsx10(
|
|
3181
|
+
Button,
|
|
3182
|
+
{
|
|
3183
|
+
variant: "ghost",
|
|
3184
|
+
size: "sm",
|
|
3185
|
+
className: "h-7 w-7 p-0 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-full",
|
|
3186
|
+
onClick: () => onClose?.(),
|
|
3187
|
+
children: /* @__PURE__ */ jsx10(Minus, { className: "h-3.5 w-3.5" })
|
|
3188
|
+
}
|
|
3189
|
+
)
|
|
3190
|
+
] }),
|
|
3191
|
+
/* @__PURE__ */ jsx10(AuthErrorState, { error: authState.error, onRetry: retryAuth })
|
|
3192
|
+
]
|
|
3193
|
+
}
|
|
3194
|
+
);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3025
3197
|
return /* @__PURE__ */ jsxs6(
|
|
3026
3198
|
"section",
|
|
3027
3199
|
{
|
|
@@ -4139,7 +4311,7 @@ ${userText}`
|
|
|
4139
4311
|
message.id
|
|
4140
4312
|
);
|
|
4141
4313
|
}
|
|
4142
|
-
return /* @__PURE__ */ jsx10(
|
|
4314
|
+
return /* @__PURE__ */ jsx10(React5.Fragment, { children: /* @__PURE__ */ jsxs6(
|
|
4143
4315
|
"div",
|
|
4144
4316
|
{
|
|
4145
4317
|
ref: isCurrentGuideStep ? currentStepRef : null,
|
|
@@ -4393,9 +4565,10 @@ function ChatPanelWithToggle({
|
|
|
4393
4565
|
userEmail,
|
|
4394
4566
|
userOrganization,
|
|
4395
4567
|
supabaseUrl,
|
|
4396
|
-
supabaseAnonKey
|
|
4568
|
+
supabaseAnonKey,
|
|
4569
|
+
productBackendUrl
|
|
4397
4570
|
}) {
|
|
4398
|
-
const [internalIsOpen, setInternalIsOpen] =
|
|
4571
|
+
const [internalIsOpen, setInternalIsOpen] = React5.useState(defaultOpen);
|
|
4399
4572
|
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
4400
4573
|
const setIsOpen = (open) => {
|
|
4401
4574
|
if (controlledIsOpen === void 0) {
|
|
@@ -4403,7 +4576,7 @@ function ChatPanelWithToggle({
|
|
|
4403
4576
|
}
|
|
4404
4577
|
onOpenChange?.(open);
|
|
4405
4578
|
};
|
|
4406
|
-
|
|
4579
|
+
React5.useEffect(() => {
|
|
4407
4580
|
const originalPadding = document.body.style.paddingRight;
|
|
4408
4581
|
const originalTransition = document.body.style.transition;
|
|
4409
4582
|
document.body.style.transition = "padding-right 0.3s ease";
|
|
@@ -4431,7 +4604,8 @@ function ChatPanelWithToggle({
|
|
|
4431
4604
|
userEmail,
|
|
4432
4605
|
userOrganization,
|
|
4433
4606
|
supabaseUrl,
|
|
4434
|
-
supabaseAnonKey
|
|
4607
|
+
supabaseAnonKey,
|
|
4608
|
+
productBackendUrl
|
|
4435
4609
|
}
|
|
4436
4610
|
);
|
|
4437
4611
|
}
|
|
@@ -4449,7 +4623,7 @@ function HelpButton({ onClick, className = "" }) {
|
|
|
4449
4623
|
}
|
|
4450
4624
|
|
|
4451
4625
|
// src/createKiteChat.tsx
|
|
4452
|
-
import
|
|
4626
|
+
import React6 from "react";
|
|
4453
4627
|
import { createRoot } from "react-dom/client";
|
|
4454
4628
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
4455
4629
|
function KiteChatWrapper({
|
|
@@ -4457,14 +4631,14 @@ function KiteChatWrapper({
|
|
|
4457
4631
|
onConfigUpdate,
|
|
4458
4632
|
onStateUpdate
|
|
4459
4633
|
}) {
|
|
4460
|
-
const [config, setConfig] =
|
|
4461
|
-
const [currentPage, setCurrentPage] =
|
|
4462
|
-
const [isOpen, setIsOpen] =
|
|
4463
|
-
const isOpenRef =
|
|
4464
|
-
|
|
4634
|
+
const [config, setConfig] = React6.useState(initialConfig);
|
|
4635
|
+
const [currentPage, setCurrentPage] = React6.useState(initialConfig.currentPage || "dashboard");
|
|
4636
|
+
const [isOpen, setIsOpen] = React6.useState(false);
|
|
4637
|
+
const isOpenRef = React6.useRef(false);
|
|
4638
|
+
React6.useEffect(() => {
|
|
4465
4639
|
isOpenRef.current = isOpen;
|
|
4466
4640
|
}, [isOpen]);
|
|
4467
|
-
|
|
4641
|
+
React6.useEffect(() => {
|
|
4468
4642
|
onConfigUpdate((newConfig) => {
|
|
4469
4643
|
if (newConfig.currentPage !== void 0) {
|
|
4470
4644
|
setCurrentPage(newConfig.currentPage);
|
|
@@ -4476,7 +4650,7 @@ function KiteChatWrapper({
|
|
|
4476
4650
|
getIsOpen: () => isOpenRef.current
|
|
4477
4651
|
});
|
|
4478
4652
|
}, [onConfigUpdate, onStateUpdate]);
|
|
4479
|
-
|
|
4653
|
+
React6.useEffect(() => {
|
|
4480
4654
|
const container = document.getElementById("kite-chat-root");
|
|
4481
4655
|
if (!container) return;
|
|
4482
4656
|
if (config.theme === "dark") {
|
|
@@ -4505,7 +4679,8 @@ function KiteChatWrapper({
|
|
|
4505
4679
|
userEmail: config.userEmail,
|
|
4506
4680
|
userOrganization: config.userOrganization,
|
|
4507
4681
|
supabaseUrl: config.supabaseUrl,
|
|
4508
|
-
supabaseAnonKey: config.supabaseAnonKey
|
|
4682
|
+
supabaseAnonKey: config.supabaseAnonKey,
|
|
4683
|
+
productBackendUrl: config.productBackendUrl
|
|
4509
4684
|
}
|
|
4510
4685
|
);
|
|
4511
4686
|
}
|
|
@@ -112,8 +112,10 @@ interface ChatPanelProps {
|
|
|
112
112
|
supabaseUrl?: string;
|
|
113
113
|
/** Supabase anonymous key for realtime features */
|
|
114
114
|
supabaseAnonKey?: string;
|
|
115
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
116
|
+
productBackendUrl?: string;
|
|
115
117
|
}
|
|
116
|
-
declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
|
|
118
|
+
declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, productBackendUrl, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
|
|
117
119
|
/**
|
|
118
120
|
* PanelToggle - An arrow button on the right edge that toggles the side panel
|
|
119
121
|
* Shows left arrow when closed (click to open), right arrow when open (click to close)
|
|
@@ -172,8 +174,10 @@ interface ChatPanelWithToggleProps {
|
|
|
172
174
|
supabaseUrl?: string;
|
|
173
175
|
/** Supabase anonymous key for realtime features */
|
|
174
176
|
supabaseAnonKey?: string;
|
|
177
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
178
|
+
productBackendUrl?: string;
|
|
175
179
|
}
|
|
176
|
-
declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
|
|
180
|
+
declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, productBackendUrl, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
|
|
177
181
|
/**
|
|
178
182
|
* @deprecated Use ChatPanelWithToggle instead for the new side panel UX
|
|
179
183
|
*/
|
|
@@ -244,6 +248,8 @@ interface KiteChatConfig {
|
|
|
244
248
|
supabaseUrl?: string;
|
|
245
249
|
/** Supabase anonymous key for realtime features */
|
|
246
250
|
supabaseAnonKey?: string;
|
|
251
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
252
|
+
productBackendUrl?: string;
|
|
247
253
|
}
|
|
248
254
|
/**
|
|
249
255
|
* Instance returned by createKiteChat with lifecycle control methods.
|
|
@@ -112,8 +112,10 @@ interface ChatPanelProps {
|
|
|
112
112
|
supabaseUrl?: string;
|
|
113
113
|
/** Supabase anonymous key for realtime features */
|
|
114
114
|
supabaseAnonKey?: string;
|
|
115
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
116
|
+
productBackendUrl?: string;
|
|
115
117
|
}
|
|
116
|
-
declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
|
|
118
|
+
declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, productBackendUrl, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
|
|
117
119
|
/**
|
|
118
120
|
* PanelToggle - An arrow button on the right edge that toggles the side panel
|
|
119
121
|
* Shows left arrow when closed (click to open), right arrow when open (click to close)
|
|
@@ -172,8 +174,10 @@ interface ChatPanelWithToggleProps {
|
|
|
172
174
|
supabaseUrl?: string;
|
|
173
175
|
/** Supabase anonymous key for realtime features */
|
|
174
176
|
supabaseAnonKey?: string;
|
|
177
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
178
|
+
productBackendUrl?: string;
|
|
175
179
|
}
|
|
176
|
-
declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
|
|
180
|
+
declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, userOrganization, supabaseUrl, supabaseAnonKey, productBackendUrl, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
|
|
177
181
|
/**
|
|
178
182
|
* @deprecated Use ChatPanelWithToggle instead for the new side panel UX
|
|
179
183
|
*/
|
|
@@ -244,6 +248,8 @@ interface KiteChatConfig {
|
|
|
244
248
|
supabaseUrl?: string;
|
|
245
249
|
/** Supabase anonymous key for realtime features */
|
|
246
250
|
supabaseAnonKey?: string;
|
|
251
|
+
/** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
|
|
252
|
+
productBackendUrl?: string;
|
|
247
253
|
}
|
|
248
254
|
/**
|
|
249
255
|
* Instance returned by createKiteChat with lifecycle control methods.
|