@kite-copilot/chat-panel 0.2.48 → 0.2.50
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 +38 -0
- package/dist/auto.cjs +176 -150
- package/dist/auto.d.cts +1 -1
- package/dist/auto.d.ts +1 -1
- package/dist/auto.js +1 -1
- package/dist/{chunk-LOTJ3U5L.js → chunk-BLSVIF7H.js} +168 -142
- package/dist/{createKiteChat-e6BnJS6T.d.cts → createKiteChat-DeQKgFyx.d.cts} +8 -2
- package/dist/{createKiteChat-e6BnJS6T.d.ts → createKiteChat-DeQKgFyx.d.ts} +8 -2
- package/dist/embed.global.js +22 -22
- package/dist/index.cjs +176 -150
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/auto.cjs
CHANGED
|
@@ -35,7 +35,7 @@ __export(auto_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(auto_exports);
|
|
36
36
|
|
|
37
37
|
// src/createKiteChat.tsx
|
|
38
|
-
var
|
|
38
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
39
39
|
var import_client = require("react-dom/client");
|
|
40
40
|
|
|
41
41
|
// src/ChatPanel.tsx
|
|
@@ -348,28 +348,22 @@ function useUserAuth({
|
|
|
348
348
|
}) {
|
|
349
349
|
const [authState, setAuthState] = React4.useState({ status: "idle" });
|
|
350
350
|
const lastSessionIdRef = React4.useRef(null);
|
|
351
|
+
const lastEnabledRef = React4.useRef(enabled);
|
|
351
352
|
const fetchUser = React4.useCallback(async () => {
|
|
352
353
|
if (!productBackendUrl || !enabled) {
|
|
353
|
-
console.log("[useUserAuth] Skipping auth - productBackendUrl:", productBackendUrl, "enabled:", enabled);
|
|
354
354
|
setAuthState({ status: "idle" });
|
|
355
355
|
return;
|
|
356
356
|
}
|
|
357
|
-
console.log("[useUserAuth] Starting auth request to product backend...");
|
|
358
|
-
console.log("[useUserAuth] Product backend URL:", productBackendUrl);
|
|
359
|
-
console.log("[useUserAuth] Full request URL:", `${productBackendUrl}/users/me`);
|
|
360
357
|
setAuthState({ status: "loading" });
|
|
361
358
|
try {
|
|
362
359
|
const response = await fetch(`${productBackendUrl}/users/me`, {
|
|
363
360
|
method: "GET",
|
|
364
361
|
credentials: "include",
|
|
365
|
-
// Include cookies for authentication
|
|
366
362
|
headers: {
|
|
367
363
|
"Accept": "application/json"
|
|
368
364
|
}
|
|
369
365
|
});
|
|
370
|
-
console.log("[useUserAuth] Response received - status:", response.status, "ok:", response.ok);
|
|
371
366
|
if (!response.ok) {
|
|
372
|
-
console.log("[useUserAuth] Auth request failed with status:", response.status);
|
|
373
367
|
if (response.status === 401) {
|
|
374
368
|
throw new Error("Please log in to use the chat assistant.");
|
|
375
369
|
}
|
|
@@ -379,27 +373,36 @@ function useUserAuth({
|
|
|
379
373
|
throw new Error(`Authentication failed (${response.status})`);
|
|
380
374
|
}
|
|
381
375
|
const user = await response.json();
|
|
382
|
-
console.log("[useUserAuth] Auth SUCCESS - parsed user data:");
|
|
383
|
-
console.log("[useUserAuth] id:", user.id);
|
|
384
|
-
console.log("[useUserAuth] email:", user.email);
|
|
385
|
-
console.log("[useUserAuth] name:", user.name);
|
|
386
|
-
console.log("[useUserAuth] role:", user.role);
|
|
387
|
-
console.log("[useUserAuth] isInternal:", user.isInternal);
|
|
388
|
-
console.log("[useUserAuth] agreementsSigned:", user.agreementsSigned);
|
|
389
|
-
console.log("[useUserAuth] lastLoginTime:", user.lastLoginTime);
|
|
390
376
|
setAuthState({ status: "authenticated", user });
|
|
391
377
|
} catch (error) {
|
|
392
|
-
|
|
378
|
+
if (error instanceof Error) {
|
|
379
|
+
const errorMessage = error.message.toLowerCase();
|
|
380
|
+
const isCorsError = errorMessage.includes("cors") || errorMessage.includes("network");
|
|
381
|
+
const is404Error = errorMessage.includes("404");
|
|
382
|
+
if (isCorsError || is404Error) {
|
|
383
|
+
console.warn("[useUserAuth] Auth endpoint unavailable, falling back to unauthenticated mode:", error.message);
|
|
384
|
+
setAuthState({ status: "idle" });
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
393
388
|
const message = error instanceof Error ? error.message : "Unable to verify your identity. Please try again.";
|
|
394
389
|
setAuthState({ status: "error", error: message });
|
|
395
390
|
}
|
|
396
391
|
}, [productBackendUrl, enabled]);
|
|
397
392
|
React4.useEffect(() => {
|
|
398
|
-
|
|
393
|
+
const sessionChanged = sessionId !== lastSessionIdRef.current;
|
|
394
|
+
const enabledChanged = enabled !== lastEnabledRef.current;
|
|
395
|
+
const becameEnabled = enabled && !lastEnabledRef.current;
|
|
396
|
+
if (sessionChanged) {
|
|
399
397
|
lastSessionIdRef.current = sessionId;
|
|
398
|
+
}
|
|
399
|
+
if (enabledChanged) {
|
|
400
|
+
lastEnabledRef.current = enabled;
|
|
401
|
+
}
|
|
402
|
+
if (sessionChanged || becameEnabled) {
|
|
400
403
|
fetchUser();
|
|
401
404
|
}
|
|
402
|
-
}, [sessionId, fetchUser]);
|
|
405
|
+
}, [sessionId, enabled, fetchUser]);
|
|
403
406
|
const retry = React4.useCallback(() => {
|
|
404
407
|
fetchUser();
|
|
405
408
|
}, [fetchUser]);
|
|
@@ -416,13 +419,11 @@ function useOrgConfig({ agentUrl, orgId }) {
|
|
|
416
419
|
});
|
|
417
420
|
React5.useEffect(() => {
|
|
418
421
|
if (!agentUrl || !orgId) {
|
|
419
|
-
console.log("[useOrgConfig] Skipping - missing agentUrl or orgId", { agentUrl, orgId });
|
|
420
422
|
return;
|
|
421
423
|
}
|
|
422
424
|
const fetchConfig = async () => {
|
|
423
425
|
setState({ status: "loading", config: null, error: null });
|
|
424
426
|
const url = `${agentUrl}/org/${orgId}/config`;
|
|
425
|
-
console.log("[useOrgConfig] Fetching org config from:", url);
|
|
426
427
|
try {
|
|
427
428
|
const response = await fetch(url, {
|
|
428
429
|
method: "GET",
|
|
@@ -434,7 +435,6 @@ function useOrgConfig({ agentUrl, orgId }) {
|
|
|
434
435
|
throw new Error(`Failed to fetch org config (${response.status})`);
|
|
435
436
|
}
|
|
436
437
|
const config = await response.json();
|
|
437
|
-
console.log("[useOrgConfig] Received config:", config);
|
|
438
438
|
setState({ status: "success", config, error: null });
|
|
439
439
|
} catch (error) {
|
|
440
440
|
const message = error instanceof Error ? error.message : "Failed to fetch org config";
|
|
@@ -447,6 +447,75 @@ function useOrgConfig({ agentUrl, orgId }) {
|
|
|
447
447
|
return state;
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
+
// src/hooks/useFrontendToolExecutor.ts
|
|
451
|
+
var import_react = require("react");
|
|
452
|
+
function useFrontendToolExecutor({
|
|
453
|
+
productBackendUrl,
|
|
454
|
+
agentUrl,
|
|
455
|
+
sessionId
|
|
456
|
+
}) {
|
|
457
|
+
const sendToolResult = (0, import_react.useCallback)(async (payload) => {
|
|
458
|
+
try {
|
|
459
|
+
await fetch(`${agentUrl}/chat/tool-result`, {
|
|
460
|
+
method: "POST",
|
|
461
|
+
headers: {
|
|
462
|
+
"Content-Type": "application/json"
|
|
463
|
+
},
|
|
464
|
+
body: JSON.stringify(payload)
|
|
465
|
+
});
|
|
466
|
+
} catch (error) {
|
|
467
|
+
console.error("[FrontendToolExecutor] Failed to send tool result:", error);
|
|
468
|
+
}
|
|
469
|
+
}, [agentUrl]);
|
|
470
|
+
const executeToolRequest = (0, import_react.useCallback)(async (toolRequest) => {
|
|
471
|
+
const { call_id, arguments: args, endpoint, method, path_params } = toolRequest;
|
|
472
|
+
try {
|
|
473
|
+
let url = endpoint;
|
|
474
|
+
for (const param of path_params) {
|
|
475
|
+
if (args[param]) {
|
|
476
|
+
url = url.replace(`{${param}}`, encodeURIComponent(args[param]));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
const queryParams = new URLSearchParams();
|
|
480
|
+
for (const [key, value] of Object.entries(args)) {
|
|
481
|
+
if (!path_params.includes(key) && value !== void 0 && value !== null) {
|
|
482
|
+
queryParams.append(key, String(value));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const queryString = queryParams.toString();
|
|
486
|
+
const fullUrl = `${productBackendUrl}${url}${queryString ? "?" + queryString : ""}`;
|
|
487
|
+
const response = await fetch(fullUrl, {
|
|
488
|
+
method,
|
|
489
|
+
credentials: "include",
|
|
490
|
+
headers: {
|
|
491
|
+
"Accept": "application/json",
|
|
492
|
+
"Content-Type": "application/json"
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
let result;
|
|
496
|
+
if (response.ok) {
|
|
497
|
+
result = await response.json();
|
|
498
|
+
} else {
|
|
499
|
+
const errorText = await response.text();
|
|
500
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
501
|
+
}
|
|
502
|
+
await sendToolResult({
|
|
503
|
+
session_id: sessionId,
|
|
504
|
+
call_id,
|
|
505
|
+
result
|
|
506
|
+
});
|
|
507
|
+
} catch (error) {
|
|
508
|
+
console.error("[FrontendToolExecutor] Tool execution failed:", error);
|
|
509
|
+
await sendToolResult({
|
|
510
|
+
session_id: sessionId,
|
|
511
|
+
call_id,
|
|
512
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}, [productBackendUrl, sessionId, sendToolResult]);
|
|
516
|
+
return { executeToolRequest };
|
|
517
|
+
}
|
|
518
|
+
|
|
450
519
|
// src/components/ui/card.tsx
|
|
451
520
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
452
521
|
function Card({ className, ...props }) {
|
|
@@ -1024,7 +1093,6 @@ function TypingIndicator({ className = "" }) {
|
|
|
1024
1093
|
|
|
1025
1094
|
// src/ChatPanel.tsx
|
|
1026
1095
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1027
|
-
var CHAT_PANEL_VERSION = true ? "0.2.48" : "dev";
|
|
1028
1096
|
var DEFAULT_AGENT_URL = "http://localhost:5002";
|
|
1029
1097
|
var PANEL_WIDTH = 400;
|
|
1030
1098
|
var PANEL_HEIGHT = 600;
|
|
@@ -1488,7 +1556,8 @@ function ChatPanel({
|
|
|
1488
1556
|
supabaseAnonKey,
|
|
1489
1557
|
initialCorner = "bottom-left",
|
|
1490
1558
|
onCornerChange,
|
|
1491
|
-
productBackendUrl
|
|
1559
|
+
productBackendUrl,
|
|
1560
|
+
getAuthHeaders
|
|
1492
1561
|
} = {}) {
|
|
1493
1562
|
const [messages, setMessages] = React6.useState(initialMessages);
|
|
1494
1563
|
const [input, setInput] = React6.useState("");
|
|
@@ -1516,37 +1585,11 @@ function ChatPanel({
|
|
|
1516
1585
|
enabled: !!effectiveProductBackendUrl && orgConfigState.status === "success"
|
|
1517
1586
|
// Only enable after config is fetched
|
|
1518
1587
|
});
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
const url = `${effectiveProductBackendUrl}/getDocument/snowkite/categories/`;
|
|
1525
|
-
console.log("[KiteChat TEST] Testing product backend connectivity...");
|
|
1526
|
-
console.log("[KiteChat TEST] URL:", url);
|
|
1527
|
-
try {
|
|
1528
|
-
const response = await fetch(url, {
|
|
1529
|
-
method: "GET",
|
|
1530
|
-
// Note: not using credentials: 'include' to avoid CORS issues with wildcard
|
|
1531
|
-
headers: {
|
|
1532
|
-
"Accept": "application/json"
|
|
1533
|
-
}
|
|
1534
|
-
});
|
|
1535
|
-
console.log("[KiteChat TEST] Response status:", response.status);
|
|
1536
|
-
console.log("[KiteChat TEST] Response ok:", response.ok);
|
|
1537
|
-
if (response.ok) {
|
|
1538
|
-
const data = await response.json();
|
|
1539
|
-
console.log("[KiteChat TEST] SUCCESS - product backend reachable, data:", data);
|
|
1540
|
-
} else {
|
|
1541
|
-
const errorText = await response.text();
|
|
1542
|
-
console.log("[KiteChat TEST] FAILED - status:", response.status, "body:", errorText);
|
|
1543
|
-
}
|
|
1544
|
-
} catch (error) {
|
|
1545
|
-
console.error("[KiteChat TEST] ERROR:", error);
|
|
1546
|
-
}
|
|
1547
|
-
};
|
|
1548
|
-
testProductBackendEndpoint();
|
|
1549
|
-
}, [effectiveProductBackendUrl, orgConfigState.status]);
|
|
1588
|
+
const { executeToolRequest } = useFrontendToolExecutor({
|
|
1589
|
+
productBackendUrl: effectiveProductBackendUrl || "",
|
|
1590
|
+
agentUrl,
|
|
1591
|
+
sessionId
|
|
1592
|
+
});
|
|
1550
1593
|
const effectiveUser = React6.useMemo(() => {
|
|
1551
1594
|
if (sessionUser) {
|
|
1552
1595
|
return sessionUser;
|
|
@@ -1577,7 +1620,6 @@ function ChatPanel({
|
|
|
1577
1620
|
userRole: authState.user.role,
|
|
1578
1621
|
isInternal: authState.user.isInternal
|
|
1579
1622
|
});
|
|
1580
|
-
console.log("[ChatPanel] Session user captured:", authState.user.id);
|
|
1581
1623
|
}
|
|
1582
1624
|
}, [authState, sessionUser]);
|
|
1583
1625
|
const isWaitingForAuth = React6.useMemo(() => {
|
|
@@ -1590,26 +1632,18 @@ function ChatPanel({
|
|
|
1590
1632
|
const supabaseRef = React6.useRef(null);
|
|
1591
1633
|
const typingChannelRef = React6.useRef(null);
|
|
1592
1634
|
const typingTimeoutRef = React6.useRef(null);
|
|
1593
|
-
React6.useEffect(() => {
|
|
1594
|
-
console.log(`[KiteChat] Chat Panel v${CHAT_PANEL_VERSION} loaded`);
|
|
1595
|
-
}, []);
|
|
1596
1635
|
const resetSession = React6.useCallback(() => {
|
|
1597
|
-
console.log("[KiteChat] resetSession called", { isEscalated, hasSupabase: !!supabaseRef.current, sessionId });
|
|
1598
1636
|
if (isEscalated && supabaseRef.current && sessionId) {
|
|
1599
|
-
console.log("[KiteChat] Updating customer_status to disconnected for session:", sessionId);
|
|
1600
1637
|
supabaseRef.current.from("escalations").update({
|
|
1601
1638
|
customer_status: "disconnected",
|
|
1602
1639
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1603
1640
|
}).eq("session_id", sessionId).then(
|
|
1604
|
-
(
|
|
1605
|
-
console.log("[KiteChat] Disconnect update result:", result);
|
|
1641
|
+
() => {
|
|
1606
1642
|
},
|
|
1607
1643
|
(err) => {
|
|
1608
1644
|
console.error("[KiteChat] Disconnect update failed:", err);
|
|
1609
1645
|
}
|
|
1610
1646
|
);
|
|
1611
|
-
} else {
|
|
1612
|
-
console.log("[KiteChat] Skipping disconnect update - conditions not met");
|
|
1613
1647
|
}
|
|
1614
1648
|
setSessionUser(null);
|
|
1615
1649
|
setSessionId(crypto.randomUUID());
|
|
@@ -1635,12 +1669,9 @@ function ChatPanel({
|
|
|
1635
1669
|
}
|
|
1636
1670
|
const channelName = `typing:${sessionId}`;
|
|
1637
1671
|
const channel = supabaseRef.current.channel(channelName);
|
|
1638
|
-
console.log(`[KiteChat] Subscribing to typing channel: ${channelName}`);
|
|
1639
1672
|
channel.on("broadcast", { event: "typing" }, (payload) => {
|
|
1640
|
-
console.log("[KiteChat] Received typing broadcast:", payload);
|
|
1641
1673
|
const { sender, isTyping } = payload.payload;
|
|
1642
1674
|
if (sender === "agent") {
|
|
1643
|
-
console.log(`[KiteChat] Agent typing: ${isTyping}`);
|
|
1644
1675
|
setAgentIsTyping(isTyping);
|
|
1645
1676
|
if (isTyping) {
|
|
1646
1677
|
if (typingTimeoutRef.current) {
|
|
@@ -1652,10 +1683,11 @@ function ChatPanel({
|
|
|
1652
1683
|
}
|
|
1653
1684
|
}
|
|
1654
1685
|
}).subscribe((status) => {
|
|
1655
|
-
console.log(`[KiteChat] Typing channel status: ${status}`);
|
|
1656
1686
|
if (status === "SUBSCRIBED") {
|
|
1657
1687
|
typingChannelRef.current = channel;
|
|
1658
|
-
console.log("[KiteChat] Typing channel
|
|
1688
|
+
console.log("[KiteChat] Typing channel subscribed successfully");
|
|
1689
|
+
} else if (status === "CHANNEL_ERROR") {
|
|
1690
|
+
console.error("[KiteChat] Typing channel subscription failed");
|
|
1659
1691
|
}
|
|
1660
1692
|
});
|
|
1661
1693
|
return () => {
|
|
@@ -1666,6 +1698,20 @@ function ChatPanel({
|
|
|
1666
1698
|
}
|
|
1667
1699
|
};
|
|
1668
1700
|
}, [isEscalated, sessionId]);
|
|
1701
|
+
React6.useEffect(() => {
|
|
1702
|
+
if (!isOpen && isEscalated && supabaseRef.current && sessionId) {
|
|
1703
|
+
console.log("[KiteChat] Panel closed during live chat, marking disconnected");
|
|
1704
|
+
supabaseRef.current.from("escalations").update({
|
|
1705
|
+
customer_status: "disconnected",
|
|
1706
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1707
|
+
}).eq("session_id", sessionId).then(
|
|
1708
|
+
() => console.log("[KiteChat] Successfully marked disconnected on panel close"),
|
|
1709
|
+
(err) => {
|
|
1710
|
+
console.error("[KiteChat] Failed to mark disconnected on panel close:", err);
|
|
1711
|
+
}
|
|
1712
|
+
);
|
|
1713
|
+
}
|
|
1714
|
+
}, [isOpen, isEscalated, sessionId]);
|
|
1669
1715
|
const heartbeatIntervalRef = React6.useRef(null);
|
|
1670
1716
|
const updateCustomerStatus = React6.useCallback(async (status) => {
|
|
1671
1717
|
if (!supabaseRef.current || !sessionId) return;
|
|
@@ -1684,9 +1730,20 @@ function ChatPanel({
|
|
|
1684
1730
|
}
|
|
1685
1731
|
const currentSessionId = sessionId;
|
|
1686
1732
|
const supabase = supabaseRef.current;
|
|
1687
|
-
|
|
1733
|
+
const markActive = () => {
|
|
1734
|
+
supabase.from("escalations").update({
|
|
1735
|
+
customer_status: "active",
|
|
1736
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1737
|
+
}).eq("session_id", currentSessionId).then(
|
|
1738
|
+
() => {
|
|
1739
|
+
},
|
|
1740
|
+
(err) => console.error("[KiteChat] Failed to update customer status:", err)
|
|
1741
|
+
);
|
|
1742
|
+
};
|
|
1743
|
+
console.log("[KiteChat] Starting presence heartbeat for live chat");
|
|
1744
|
+
markActive();
|
|
1688
1745
|
heartbeatIntervalRef.current = window.setInterval(() => {
|
|
1689
|
-
|
|
1746
|
+
markActive();
|
|
1690
1747
|
}, 6e4);
|
|
1691
1748
|
const handleBeforeUnload = () => {
|
|
1692
1749
|
supabase.from("escalations").update({
|
|
@@ -1701,7 +1758,7 @@ function ChatPanel({
|
|
|
1701
1758
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1702
1759
|
}).eq("session_id", currentSessionId);
|
|
1703
1760
|
} else if (document.visibilityState === "visible") {
|
|
1704
|
-
|
|
1761
|
+
markActive();
|
|
1705
1762
|
}
|
|
1706
1763
|
};
|
|
1707
1764
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
@@ -1709,13 +1766,12 @@ function ChatPanel({
|
|
|
1709
1766
|
return () => {
|
|
1710
1767
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
1711
1768
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1769
|
+
console.log("[KiteChat] Escalation ended, marking disconnected");
|
|
1712
1770
|
supabase.from("escalations").update({
|
|
1713
1771
|
customer_status: "disconnected",
|
|
1714
1772
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1715
1773
|
}).eq("session_id", currentSessionId).then(
|
|
1716
|
-
() =>
|
|
1717
|
-
console.log("[KiteChat] Marked customer as disconnected");
|
|
1718
|
-
},
|
|
1774
|
+
() => console.log("[KiteChat] Successfully marked disconnected on escalation end"),
|
|
1719
1775
|
(err) => {
|
|
1720
1776
|
console.error("[KiteChat] Failed to mark disconnected:", err);
|
|
1721
1777
|
}
|
|
@@ -1725,17 +1781,14 @@ function ChatPanel({
|
|
|
1725
1781
|
heartbeatIntervalRef.current = null;
|
|
1726
1782
|
}
|
|
1727
1783
|
};
|
|
1728
|
-
}, [isEscalated, sessionId
|
|
1784
|
+
}, [isEscalated, sessionId]);
|
|
1729
1785
|
const sendTypingIndicator = React6.useCallback((isTyping) => {
|
|
1730
|
-
if (!typingChannelRef.current) {
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
if (!isEscalated) {
|
|
1735
|
-
console.log("[KiteChat] Cannot send typing - not escalated");
|
|
1786
|
+
if (!typingChannelRef.current || !isEscalated) {
|
|
1787
|
+
if (isTyping) {
|
|
1788
|
+
console.warn("[KiteChat] Typing channel not ready, cannot send typing indicator");
|
|
1789
|
+
}
|
|
1736
1790
|
return;
|
|
1737
1791
|
}
|
|
1738
|
-
console.log(`[KiteChat] Sending typing indicator: ${isTyping}`);
|
|
1739
1792
|
typingChannelRef.current.send({
|
|
1740
1793
|
type: "broadcast",
|
|
1741
1794
|
event: "typing",
|
|
@@ -1744,16 +1797,23 @@ function ChatPanel({
|
|
|
1744
1797
|
}, [isEscalated]);
|
|
1745
1798
|
const userTypingTimeoutRef = React6.useRef(null);
|
|
1746
1799
|
const handleTypingStart = React6.useCallback(() => {
|
|
1747
|
-
if (!isEscalated || !supabaseRef.current) return;
|
|
1800
|
+
if (!isEscalated || !supabaseRef.current || !sessionId) return;
|
|
1748
1801
|
sendTypingIndicator(true);
|
|
1749
|
-
|
|
1802
|
+
supabaseRef.current.from("escalations").update({
|
|
1803
|
+
customer_status: "active",
|
|
1804
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1805
|
+
}).eq("session_id", sessionId).then(
|
|
1806
|
+
() => {
|
|
1807
|
+
},
|
|
1808
|
+
(err) => console.error("[KiteChat] Failed to update presence:", err)
|
|
1809
|
+
);
|
|
1750
1810
|
if (userTypingTimeoutRef.current) {
|
|
1751
1811
|
window.clearTimeout(userTypingTimeoutRef.current);
|
|
1752
1812
|
}
|
|
1753
1813
|
userTypingTimeoutRef.current = window.setTimeout(() => {
|
|
1754
1814
|
sendTypingIndicator(false);
|
|
1755
1815
|
}, 1500);
|
|
1756
|
-
}, [isEscalated, sendTypingIndicator,
|
|
1816
|
+
}, [isEscalated, sendTypingIndicator, sessionId]);
|
|
1757
1817
|
const streamIntervals = React6.useRef({});
|
|
1758
1818
|
const isEmpty = messages.length === 0;
|
|
1759
1819
|
const [phase, setPhase] = React6.useState("idle");
|
|
@@ -1788,12 +1848,6 @@ function ChatPanel({
|
|
|
1788
1848
|
const latestBulkSummaryNavigationRef = React6.useRef(null);
|
|
1789
1849
|
const [guideComplete, setGuideComplete] = React6.useState(false);
|
|
1790
1850
|
React6.useEffect(() => {
|
|
1791
|
-
window.resetIntegrationNotification = () => {
|
|
1792
|
-
localStorage.removeItem("gmailNotificationSeen");
|
|
1793
|
-
console.log(
|
|
1794
|
-
"Integration notification reset! Click the Integrations tab to see it again."
|
|
1795
|
-
);
|
|
1796
|
-
};
|
|
1797
1851
|
const handleIntegrationTabClick = () => {
|
|
1798
1852
|
const hasSeenNotification = localStorage.getItem("gmailNotificationSeen");
|
|
1799
1853
|
if (!hasSeenNotification) {
|
|
@@ -1935,17 +1989,7 @@ function ChatPanel({
|
|
|
1935
1989
|
return;
|
|
1936
1990
|
}
|
|
1937
1991
|
const currentBulkNav = latestBulkSummaryNavigationRef.current;
|
|
1938
|
-
console.log(
|
|
1939
|
-
"[DEBUG] Keyboard handler - latestBulkSummaryNavigation:",
|
|
1940
|
-
currentBulkNav,
|
|
1941
|
-
"onNavigate:",
|
|
1942
|
-
!!onNavigate
|
|
1943
|
-
);
|
|
1944
1992
|
if (currentBulkNav && onNavigate) {
|
|
1945
|
-
console.log(
|
|
1946
|
-
"[DEBUG] Navigating via keyboard to:",
|
|
1947
|
-
currentBulkNav.page
|
|
1948
|
-
);
|
|
1949
1993
|
e.preventDefault();
|
|
1950
1994
|
e.stopPropagation();
|
|
1951
1995
|
onNavigate(currentBulkNav.page, currentBulkNav.subtab);
|
|
@@ -1991,7 +2035,6 @@ function ChatPanel({
|
|
|
1991
2035
|
const messageId = data.message_id;
|
|
1992
2036
|
const isDuplicate = messageId ? prev.some((m) => m.serverMessageId === messageId) : prev.slice(-5).some((m) => m.content === content);
|
|
1993
2037
|
if (isDuplicate) {
|
|
1994
|
-
console.debug("[KiteChat] Skipping duplicate agent message:", messageId || content.slice(0, 30));
|
|
1995
2038
|
return prev;
|
|
1996
2039
|
}
|
|
1997
2040
|
return [...prev, {
|
|
@@ -2014,7 +2057,6 @@ function ChatPanel({
|
|
|
2014
2057
|
console.error("[KiteChat] Escalation WebSocket error:", err);
|
|
2015
2058
|
};
|
|
2016
2059
|
ws.onclose = () => {
|
|
2017
|
-
console.log("[KiteChat] Escalation WebSocket closed");
|
|
2018
2060
|
};
|
|
2019
2061
|
escalationWsRef.current = ws;
|
|
2020
2062
|
}, [agentUrl]);
|
|
@@ -2028,13 +2070,22 @@ function ChatPanel({
|
|
|
2028
2070
|
type: "user_message",
|
|
2029
2071
|
content
|
|
2030
2072
|
}));
|
|
2031
|
-
|
|
2073
|
+
if (supabaseRef.current && sessionId) {
|
|
2074
|
+
supabaseRef.current.from("escalations").update({
|
|
2075
|
+
customer_status: "active",
|
|
2076
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
2077
|
+
}).eq("session_id", sessionId).then(
|
|
2078
|
+
() => {
|
|
2079
|
+
},
|
|
2080
|
+
(err) => console.error("[KiteChat] Failed to update presence:", err)
|
|
2081
|
+
);
|
|
2082
|
+
}
|
|
2032
2083
|
return true;
|
|
2033
2084
|
} catch (err) {
|
|
2034
2085
|
console.error("[KiteChat] Failed to send escalated message:", err);
|
|
2035
2086
|
return false;
|
|
2036
2087
|
}
|
|
2037
|
-
}, [
|
|
2088
|
+
}, [sessionId]);
|
|
2038
2089
|
React6.useEffect(() => {
|
|
2039
2090
|
return () => {
|
|
2040
2091
|
if (escalationWsRef.current) {
|
|
@@ -2308,14 +2359,6 @@ function ChatPanel({
|
|
|
2308
2359
|
try {
|
|
2309
2360
|
const controller = new AbortController();
|
|
2310
2361
|
const timeoutId = setTimeout(() => controller.abort(), 6e4);
|
|
2311
|
-
console.log("[ChatPanel] Sending chat request to agent backend...");
|
|
2312
|
-
console.log("[ChatPanel] Agent URL:", agentUrl);
|
|
2313
|
-
console.log("[ChatPanel] User data being sent:");
|
|
2314
|
-
console.log("[ChatPanel] user_id:", effectiveUser.userId);
|
|
2315
|
-
console.log("[ChatPanel] user_name:", effectiveUser.userName);
|
|
2316
|
-
console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
|
|
2317
|
-
console.log("[ChatPanel] org_id:", orgId);
|
|
2318
|
-
console.log("[ChatPanel] authState.status:", authState.status);
|
|
2319
2362
|
const response = await fetch(`${agentUrl}/chat/stream`, {
|
|
2320
2363
|
method: "POST",
|
|
2321
2364
|
headers: {
|
|
@@ -2530,6 +2573,11 @@ function ChatPanel({
|
|
|
2530
2573
|
content: data.message || "You've been connected to our support queue. An agent will be with you shortly."
|
|
2531
2574
|
};
|
|
2532
2575
|
setMessages((prev) => [...prev, escalationMessage]);
|
|
2576
|
+
} else if (eventType === "tool_request") {
|
|
2577
|
+
const toolRequest = data;
|
|
2578
|
+
executeToolRequest(toolRequest).catch((err) => {
|
|
2579
|
+
console.error("[KiteChat] Tool execution failed:", err);
|
|
2580
|
+
});
|
|
2533
2581
|
} else if (eventType === "token") {
|
|
2534
2582
|
}
|
|
2535
2583
|
} catch (parseError) {
|
|
@@ -2844,11 +2892,6 @@ ${userText}`
|
|
|
2844
2892
|
}
|
|
2845
2893
|
});
|
|
2846
2894
|
} else if (eventType === "summary") {
|
|
2847
|
-
console.log("[DEBUG] Received summary event - data:", data);
|
|
2848
|
-
console.log(
|
|
2849
|
-
"[DEBUG] navigationPage from backend:",
|
|
2850
|
-
data.navigationPage
|
|
2851
|
-
);
|
|
2852
2895
|
setPhase("idle");
|
|
2853
2896
|
setProgressSteps([]);
|
|
2854
2897
|
setPendingBulkSession(null);
|
|
@@ -2868,7 +2911,6 @@ ${userText}`
|
|
|
2868
2911
|
navigationPage: data.navigationPage
|
|
2869
2912
|
}
|
|
2870
2913
|
};
|
|
2871
|
-
console.log("[DEBUG] Creating bulkSummary message:", newMsg);
|
|
2872
2914
|
return [...filtered, newMsg];
|
|
2873
2915
|
});
|
|
2874
2916
|
setTimeout(() => {
|
|
@@ -4439,28 +4481,11 @@ ${userText}`
|
|
|
4439
4481
|
onClick: (e) => {
|
|
4440
4482
|
e.preventDefault();
|
|
4441
4483
|
e.stopPropagation();
|
|
4442
|
-
console.log(
|
|
4443
|
-
"[DEBUG] Button clicked - navigationPage:",
|
|
4444
|
-
navigationPage,
|
|
4445
|
-
"onNavigate:",
|
|
4446
|
-
!!onNavigate
|
|
4447
|
-
);
|
|
4448
4484
|
if (onNavigate && navigationPage.page) {
|
|
4449
|
-
console.log(
|
|
4450
|
-
"[DEBUG] Calling onNavigate with page:",
|
|
4451
|
-
navigationPage.page
|
|
4452
|
-
);
|
|
4453
4485
|
onNavigate(
|
|
4454
4486
|
navigationPage.page,
|
|
4455
4487
|
navigationPage.subtab
|
|
4456
4488
|
);
|
|
4457
|
-
} else {
|
|
4458
|
-
console.log(
|
|
4459
|
-
"[DEBUG] Condition failed - onNavigate:",
|
|
4460
|
-
!!onNavigate,
|
|
4461
|
-
"navigationPage.page:",
|
|
4462
|
-
navigationPage.page
|
|
4463
|
-
);
|
|
4464
4489
|
}
|
|
4465
4490
|
},
|
|
4466
4491
|
className: "flex items-center gap-2 text-xs text-gray-500 hover:text-gray-700 transition-colors group cursor-pointer",
|
|
@@ -4720,7 +4745,8 @@ function ChatPanelWithToggle({
|
|
|
4720
4745
|
supabaseAnonKey,
|
|
4721
4746
|
initialCorner,
|
|
4722
4747
|
onCornerChange,
|
|
4723
|
-
productBackendUrl
|
|
4748
|
+
productBackendUrl,
|
|
4749
|
+
getAuthHeaders
|
|
4724
4750
|
}) {
|
|
4725
4751
|
const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
|
|
4726
4752
|
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
@@ -4750,7 +4776,8 @@ function ChatPanelWithToggle({
|
|
|
4750
4776
|
supabaseAnonKey,
|
|
4751
4777
|
initialCorner,
|
|
4752
4778
|
onCornerChange,
|
|
4753
|
-
productBackendUrl
|
|
4779
|
+
productBackendUrl,
|
|
4780
|
+
getAuthHeaders
|
|
4754
4781
|
}
|
|
4755
4782
|
);
|
|
4756
4783
|
}
|
|
@@ -4762,14 +4789,14 @@ function KiteChatWrapper({
|
|
|
4762
4789
|
onConfigUpdate,
|
|
4763
4790
|
onStateUpdate
|
|
4764
4791
|
}) {
|
|
4765
|
-
const [config, setConfig] =
|
|
4766
|
-
const [currentPage, setCurrentPage] =
|
|
4767
|
-
const [isOpen, setIsOpen] =
|
|
4768
|
-
const isOpenRef =
|
|
4769
|
-
|
|
4792
|
+
const [config, setConfig] = import_react2.default.useState(initialConfig);
|
|
4793
|
+
const [currentPage, setCurrentPage] = import_react2.default.useState(initialConfig.currentPage || "dashboard");
|
|
4794
|
+
const [isOpen, setIsOpen] = import_react2.default.useState(false);
|
|
4795
|
+
const isOpenRef = import_react2.default.useRef(false);
|
|
4796
|
+
import_react2.default.useEffect(() => {
|
|
4770
4797
|
isOpenRef.current = isOpen;
|
|
4771
4798
|
}, [isOpen]);
|
|
4772
|
-
|
|
4799
|
+
import_react2.default.useEffect(() => {
|
|
4773
4800
|
onConfigUpdate((newConfig) => {
|
|
4774
4801
|
if (newConfig.currentPage !== void 0) {
|
|
4775
4802
|
setCurrentPage(newConfig.currentPage);
|
|
@@ -4781,7 +4808,7 @@ function KiteChatWrapper({
|
|
|
4781
4808
|
getIsOpen: () => isOpenRef.current
|
|
4782
4809
|
});
|
|
4783
4810
|
}, [onConfigUpdate, onStateUpdate]);
|
|
4784
|
-
|
|
4811
|
+
import_react2.default.useEffect(() => {
|
|
4785
4812
|
const container = document.getElementById("kite-chat-root");
|
|
4786
4813
|
if (!container) return;
|
|
4787
4814
|
if (config.theme === "dark") {
|
|
@@ -4810,7 +4837,8 @@ function KiteChatWrapper({
|
|
|
4810
4837
|
userEmail: config.userEmail,
|
|
4811
4838
|
supabaseUrl: config.supabaseUrl,
|
|
4812
4839
|
supabaseAnonKey: config.supabaseAnonKey,
|
|
4813
|
-
productBackendUrl: config.productBackendUrl
|
|
4840
|
+
productBackendUrl: config.productBackendUrl,
|
|
4841
|
+
getAuthHeaders: config.getAuthHeaders
|
|
4814
4842
|
}
|
|
4815
4843
|
);
|
|
4816
4844
|
}
|
|
@@ -4853,7 +4881,6 @@ function createKiteChat(config) {
|
|
|
4853
4881
|
}
|
|
4854
4882
|
)
|
|
4855
4883
|
);
|
|
4856
|
-
console.log("[KiteChat] Mounted");
|
|
4857
4884
|
},
|
|
4858
4885
|
unmount() {
|
|
4859
4886
|
if (!root) {
|
|
@@ -4865,7 +4892,6 @@ function createKiteChat(config) {
|
|
|
4865
4892
|
containerElement = null;
|
|
4866
4893
|
configUpdater = null;
|
|
4867
4894
|
stateUpdaters = null;
|
|
4868
|
-
console.log("[KiteChat] Unmounted");
|
|
4869
4895
|
},
|
|
4870
4896
|
open() {
|
|
4871
4897
|
stateUpdaters?.setIsOpen(true);
|
package/dist/auto.d.cts
CHANGED
package/dist/auto.d.ts
CHANGED