@kite-copilot/chat-panel 0.2.49 → 0.2.51
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 +8 -0
- package/dist/auto.cjs +118 -158
- package/dist/auto.d.cts +1 -1
- package/dist/auto.d.ts +1 -1
- package/dist/auto.js +1 -1
- package/dist/{chunk-YZXB3LLU.js → chunk-VBCGW333.js} +118 -158
- 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 +24 -59
- package/dist/index.cjs +118 -158
- 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/README.md
CHANGED
|
@@ -52,6 +52,12 @@ const chat = createKiteChat({
|
|
|
52
52
|
// Optional: Pass user info for session tracking in control center
|
|
53
53
|
userName: 'John Doe',
|
|
54
54
|
userEmail: 'john@example.com',
|
|
55
|
+
// Optional: Provide authentication headers for API requests
|
|
56
|
+
getAuthHeaders: async () => {
|
|
57
|
+
return {
|
|
58
|
+
Authorization: `Bearer ${await getCurrentToken()}`
|
|
59
|
+
};
|
|
60
|
+
},
|
|
55
61
|
onNavigate: (page, subtab) => {
|
|
56
62
|
router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`);
|
|
57
63
|
},
|
|
@@ -320,6 +326,7 @@ Creates a new chat instance with explicit lifecycle control.
|
|
|
320
326
|
| `theme` | `'light' \| 'dark' \| 'system'` | No | Theme preference |
|
|
321
327
|
| `startingQuestions` | `StartingQuestion[]` | No | Custom starting questions |
|
|
322
328
|
| `startingQuestionsEndpoint` | `string` | No | URL to fetch per-user questions |
|
|
329
|
+
| `getAuthHeaders` | `() => Promise<Record<string, string>>` | No | Async function to provide auth headers |
|
|
323
330
|
| `onNavigate` | `(page: string, subtab?: string) => void` | No | Navigation callback |
|
|
324
331
|
| `onActionComplete` | `(actionType: string, data: any) => void` | No | Action completion callback |
|
|
325
332
|
|
|
@@ -360,6 +367,7 @@ import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
|
|
|
360
367
|
| `onOpenChange` | `(isOpen: boolean) => void` | - | Called when open state changes |
|
|
361
368
|
| `startingQuestions` | `StartingQuestion[]` | - | Custom starting questions |
|
|
362
369
|
| `startingQuestionsEndpoint` | `string` | - | URL to fetch questions |
|
|
370
|
+
| `getAuthHeaders` | `() => Promise<Record<string, string>>` | - | Async function to provide auth headers |
|
|
363
371
|
| `onNavigate` | `(page, subtab?) => void` | - | Navigation callback |
|
|
364
372
|
| `onActionComplete` | `(type, data) => void` | - | Action completion callback |
|
|
365
373
|
|
package/dist/auto.cjs
CHANGED
|
@@ -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 isNetworkError = error instanceof TypeError || errorMessage.includes("failed to fetch") || errorMessage.includes("network");
|
|
381
|
+
const is404Error = errorMessage.includes("404");
|
|
382
|
+
if (isNetworkError || 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";
|
|
@@ -468,8 +468,7 @@ function useFrontendToolExecutor({
|
|
|
468
468
|
}
|
|
469
469
|
}, [agentUrl]);
|
|
470
470
|
const executeToolRequest = (0, import_react.useCallback)(async (toolRequest) => {
|
|
471
|
-
const { call_id,
|
|
472
|
-
console.log("[FrontendToolExecutor] Executing tool:", tool_name, "with args:", args);
|
|
471
|
+
const { call_id, arguments: args, endpoint, method, path_params } = toolRequest;
|
|
473
472
|
try {
|
|
474
473
|
let url = endpoint;
|
|
475
474
|
for (const param of path_params) {
|
|
@@ -485,7 +484,6 @@ function useFrontendToolExecutor({
|
|
|
485
484
|
}
|
|
486
485
|
const queryString = queryParams.toString();
|
|
487
486
|
const fullUrl = `${productBackendUrl}${url}${queryString ? "?" + queryString : ""}`;
|
|
488
|
-
console.log("[FrontendToolExecutor] Fetching:", fullUrl);
|
|
489
487
|
const response = await fetch(fullUrl, {
|
|
490
488
|
method,
|
|
491
489
|
credentials: "include",
|
|
@@ -497,7 +495,6 @@ function useFrontendToolExecutor({
|
|
|
497
495
|
let result;
|
|
498
496
|
if (response.ok) {
|
|
499
497
|
result = await response.json();
|
|
500
|
-
console.log("[FrontendToolExecutor] Tool result:", result);
|
|
501
498
|
} else {
|
|
502
499
|
const errorText = await response.text();
|
|
503
500
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
@@ -1096,7 +1093,6 @@ function TypingIndicator({ className = "" }) {
|
|
|
1096
1093
|
|
|
1097
1094
|
// src/ChatPanel.tsx
|
|
1098
1095
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1099
|
-
var CHAT_PANEL_VERSION = true ? "0.2.49" : "dev";
|
|
1100
1096
|
var DEFAULT_AGENT_URL = "http://localhost:5002";
|
|
1101
1097
|
var PANEL_WIDTH = 400;
|
|
1102
1098
|
var PANEL_HEIGHT = 600;
|
|
@@ -1560,7 +1556,8 @@ function ChatPanel({
|
|
|
1560
1556
|
supabaseAnonKey,
|
|
1561
1557
|
initialCorner = "bottom-left",
|
|
1562
1558
|
onCornerChange,
|
|
1563
|
-
productBackendUrl
|
|
1559
|
+
productBackendUrl,
|
|
1560
|
+
getAuthHeaders
|
|
1564
1561
|
} = {}) {
|
|
1565
1562
|
const [messages, setMessages] = React6.useState(initialMessages);
|
|
1566
1563
|
const [input, setInput] = React6.useState("");
|
|
@@ -1582,6 +1579,8 @@ function ChatPanel({
|
|
|
1582
1579
|
const [sessionUser, setSessionUser] = React6.useState(null);
|
|
1583
1580
|
const orgConfigState = useOrgConfig({ agentUrl, orgId: orgId || "" });
|
|
1584
1581
|
const effectiveProductBackendUrl = orgConfigState.config?.productBackendUrl || productBackendUrl;
|
|
1582
|
+
const effectiveSupabaseUrl = orgConfigState.config?.supabaseUrl || supabaseUrl;
|
|
1583
|
+
const effectiveSupabaseAnonKey = orgConfigState.config?.supabaseAnonKey || supabaseAnonKey;
|
|
1585
1584
|
const { authState, retry: retryAuth } = useUserAuth({
|
|
1586
1585
|
productBackendUrl: effectiveProductBackendUrl,
|
|
1587
1586
|
sessionId,
|
|
@@ -1593,37 +1592,6 @@ function ChatPanel({
|
|
|
1593
1592
|
agentUrl,
|
|
1594
1593
|
sessionId
|
|
1595
1594
|
});
|
|
1596
|
-
React6.useEffect(() => {
|
|
1597
|
-
if (!effectiveProductBackendUrl || orgConfigState.status !== "success") {
|
|
1598
|
-
return;
|
|
1599
|
-
}
|
|
1600
|
-
const testProductBackendEndpoint = async () => {
|
|
1601
|
-
const url = `${effectiveProductBackendUrl}/getDocument/snowkite/categories/`;
|
|
1602
|
-
console.log("[KiteChat TEST] Testing product backend connectivity...");
|
|
1603
|
-
console.log("[KiteChat TEST] URL:", url);
|
|
1604
|
-
try {
|
|
1605
|
-
const response = await fetch(url, {
|
|
1606
|
-
method: "GET",
|
|
1607
|
-
// Note: not using credentials: 'include' to avoid CORS issues with wildcard
|
|
1608
|
-
headers: {
|
|
1609
|
-
"Accept": "application/json"
|
|
1610
|
-
}
|
|
1611
|
-
});
|
|
1612
|
-
console.log("[KiteChat TEST] Response status:", response.status);
|
|
1613
|
-
console.log("[KiteChat TEST] Response ok:", response.ok);
|
|
1614
|
-
if (response.ok) {
|
|
1615
|
-
const data = await response.json();
|
|
1616
|
-
console.log("[KiteChat TEST] SUCCESS - product backend reachable, data:", data);
|
|
1617
|
-
} else {
|
|
1618
|
-
const errorText = await response.text();
|
|
1619
|
-
console.log("[KiteChat TEST] FAILED - status:", response.status, "body:", errorText);
|
|
1620
|
-
}
|
|
1621
|
-
} catch (error) {
|
|
1622
|
-
console.error("[KiteChat TEST] ERROR:", error);
|
|
1623
|
-
}
|
|
1624
|
-
};
|
|
1625
|
-
testProductBackendEndpoint();
|
|
1626
|
-
}, [effectiveProductBackendUrl, orgConfigState.status]);
|
|
1627
1595
|
const effectiveUser = React6.useMemo(() => {
|
|
1628
1596
|
if (sessionUser) {
|
|
1629
1597
|
return sessionUser;
|
|
@@ -1654,7 +1622,6 @@ function ChatPanel({
|
|
|
1654
1622
|
userRole: authState.user.role,
|
|
1655
1623
|
isInternal: authState.user.isInternal
|
|
1656
1624
|
});
|
|
1657
|
-
console.log("[ChatPanel] Session user captured:", authState.user.id);
|
|
1658
1625
|
}
|
|
1659
1626
|
}, [authState, sessionUser]);
|
|
1660
1627
|
const isWaitingForAuth = React6.useMemo(() => {
|
|
@@ -1667,26 +1634,18 @@ function ChatPanel({
|
|
|
1667
1634
|
const supabaseRef = React6.useRef(null);
|
|
1668
1635
|
const typingChannelRef = React6.useRef(null);
|
|
1669
1636
|
const typingTimeoutRef = React6.useRef(null);
|
|
1670
|
-
React6.useEffect(() => {
|
|
1671
|
-
console.log(`[KiteChat] Chat Panel v${CHAT_PANEL_VERSION} loaded`);
|
|
1672
|
-
}, []);
|
|
1673
1637
|
const resetSession = React6.useCallback(() => {
|
|
1674
|
-
console.log("[KiteChat] resetSession called", { isEscalated, hasSupabase: !!supabaseRef.current, sessionId });
|
|
1675
1638
|
if (isEscalated && supabaseRef.current && sessionId) {
|
|
1676
|
-
console.log("[KiteChat] Updating customer_status to disconnected for session:", sessionId);
|
|
1677
1639
|
supabaseRef.current.from("escalations").update({
|
|
1678
1640
|
customer_status: "disconnected",
|
|
1679
1641
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1680
1642
|
}).eq("session_id", sessionId).then(
|
|
1681
|
-
(
|
|
1682
|
-
console.log("[KiteChat] Disconnect update result:", result);
|
|
1643
|
+
() => {
|
|
1683
1644
|
},
|
|
1684
1645
|
(err) => {
|
|
1685
1646
|
console.error("[KiteChat] Disconnect update failed:", err);
|
|
1686
1647
|
}
|
|
1687
1648
|
);
|
|
1688
|
-
} else {
|
|
1689
|
-
console.log("[KiteChat] Skipping disconnect update - conditions not met");
|
|
1690
1649
|
}
|
|
1691
1650
|
setSessionUser(null);
|
|
1692
1651
|
setSessionId(crypto.randomUUID());
|
|
@@ -1702,22 +1661,19 @@ function ChatPanel({
|
|
|
1702
1661
|
}
|
|
1703
1662
|
}, [isEscalated, sessionId]);
|
|
1704
1663
|
React6.useEffect(() => {
|
|
1705
|
-
if (
|
|
1706
|
-
supabaseRef.current = (0, import_supabase_js.createClient)(
|
|
1664
|
+
if (effectiveSupabaseUrl && effectiveSupabaseAnonKey && !supabaseRef.current) {
|
|
1665
|
+
supabaseRef.current = (0, import_supabase_js.createClient)(effectiveSupabaseUrl, effectiveSupabaseAnonKey);
|
|
1707
1666
|
}
|
|
1708
|
-
}, [
|
|
1667
|
+
}, [effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
|
|
1709
1668
|
React6.useEffect(() => {
|
|
1710
1669
|
if (!isEscalated || !sessionId || !supabaseRef.current) {
|
|
1711
1670
|
return;
|
|
1712
1671
|
}
|
|
1713
1672
|
const channelName = `typing:${sessionId}`;
|
|
1714
1673
|
const channel = supabaseRef.current.channel(channelName);
|
|
1715
|
-
console.log(`[KiteChat] Subscribing to typing channel: ${channelName}`);
|
|
1716
1674
|
channel.on("broadcast", { event: "typing" }, (payload) => {
|
|
1717
|
-
console.log("[KiteChat] Received typing broadcast:", payload);
|
|
1718
1675
|
const { sender, isTyping } = payload.payload;
|
|
1719
1676
|
if (sender === "agent") {
|
|
1720
|
-
console.log(`[KiteChat] Agent typing: ${isTyping}`);
|
|
1721
1677
|
setAgentIsTyping(isTyping);
|
|
1722
1678
|
if (isTyping) {
|
|
1723
1679
|
if (typingTimeoutRef.current) {
|
|
@@ -1729,10 +1685,11 @@ function ChatPanel({
|
|
|
1729
1685
|
}
|
|
1730
1686
|
}
|
|
1731
1687
|
}).subscribe((status) => {
|
|
1732
|
-
console.log(`[KiteChat] Typing channel status: ${status}`);
|
|
1733
1688
|
if (status === "SUBSCRIBED") {
|
|
1734
1689
|
typingChannelRef.current = channel;
|
|
1735
|
-
console.log("[KiteChat] Typing channel
|
|
1690
|
+
console.log("[KiteChat] Typing channel subscribed successfully");
|
|
1691
|
+
} else if (status === "CHANNEL_ERROR") {
|
|
1692
|
+
console.error("[KiteChat] Typing channel subscription failed");
|
|
1736
1693
|
}
|
|
1737
1694
|
});
|
|
1738
1695
|
return () => {
|
|
@@ -1743,6 +1700,20 @@ function ChatPanel({
|
|
|
1743
1700
|
}
|
|
1744
1701
|
};
|
|
1745
1702
|
}, [isEscalated, sessionId]);
|
|
1703
|
+
React6.useEffect(() => {
|
|
1704
|
+
if (!isOpen && isEscalated && supabaseRef.current && sessionId) {
|
|
1705
|
+
console.log("[KiteChat] Panel closed during live chat, marking disconnected");
|
|
1706
|
+
supabaseRef.current.from("escalations").update({
|
|
1707
|
+
customer_status: "disconnected",
|
|
1708
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1709
|
+
}).eq("session_id", sessionId).then(
|
|
1710
|
+
() => console.log("[KiteChat] Successfully marked disconnected on panel close"),
|
|
1711
|
+
(err) => {
|
|
1712
|
+
console.error("[KiteChat] Failed to mark disconnected on panel close:", err);
|
|
1713
|
+
}
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
}, [isOpen, isEscalated, sessionId]);
|
|
1746
1717
|
const heartbeatIntervalRef = React6.useRef(null);
|
|
1747
1718
|
const updateCustomerStatus = React6.useCallback(async (status) => {
|
|
1748
1719
|
if (!supabaseRef.current || !sessionId) return;
|
|
@@ -1761,24 +1732,50 @@ function ChatPanel({
|
|
|
1761
1732
|
}
|
|
1762
1733
|
const currentSessionId = sessionId;
|
|
1763
1734
|
const supabase = supabaseRef.current;
|
|
1764
|
-
|
|
1735
|
+
const sbUrl = effectiveSupabaseUrl;
|
|
1736
|
+
const sbKey = effectiveSupabaseAnonKey;
|
|
1737
|
+
const markActive = () => {
|
|
1738
|
+
supabase.from("escalations").update({
|
|
1739
|
+
customer_status: "active",
|
|
1740
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1741
|
+
}).eq("session_id", currentSessionId).then(
|
|
1742
|
+
() => {
|
|
1743
|
+
},
|
|
1744
|
+
(err) => console.error("[KiteChat] Failed to update customer status:", err)
|
|
1745
|
+
);
|
|
1746
|
+
};
|
|
1747
|
+
const markDisconnectedWithKeepalive = () => {
|
|
1748
|
+
if (!sbUrl || !sbKey) return;
|
|
1749
|
+
const url = `${sbUrl}/rest/v1/escalations?session_id=eq.${currentSessionId}`;
|
|
1750
|
+
fetch(url, {
|
|
1751
|
+
method: "PATCH",
|
|
1752
|
+
headers: {
|
|
1753
|
+
"Content-Type": "application/json",
|
|
1754
|
+
"apikey": sbKey,
|
|
1755
|
+
"Authorization": `Bearer ${sbKey}`,
|
|
1756
|
+
"Prefer": "return=minimal"
|
|
1757
|
+
},
|
|
1758
|
+
body: JSON.stringify({
|
|
1759
|
+
customer_status: "disconnected",
|
|
1760
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1761
|
+
}),
|
|
1762
|
+
keepalive: true
|
|
1763
|
+
}).catch(() => {
|
|
1764
|
+
});
|
|
1765
|
+
};
|
|
1766
|
+
console.log("[KiteChat] Starting presence heartbeat for live chat");
|
|
1767
|
+
markActive();
|
|
1765
1768
|
heartbeatIntervalRef.current = window.setInterval(() => {
|
|
1766
|
-
|
|
1769
|
+
markActive();
|
|
1767
1770
|
}, 6e4);
|
|
1768
1771
|
const handleBeforeUnload = () => {
|
|
1769
|
-
|
|
1770
|
-
customer_status: "disconnected",
|
|
1771
|
-
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1772
|
-
}).eq("session_id", currentSessionId);
|
|
1772
|
+
markDisconnectedWithKeepalive();
|
|
1773
1773
|
};
|
|
1774
1774
|
const handleVisibilityChange = () => {
|
|
1775
1775
|
if (document.visibilityState === "hidden") {
|
|
1776
|
-
|
|
1777
|
-
customer_status: "disconnected",
|
|
1778
|
-
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1779
|
-
}).eq("session_id", currentSessionId);
|
|
1776
|
+
markDisconnectedWithKeepalive();
|
|
1780
1777
|
} else if (document.visibilityState === "visible") {
|
|
1781
|
-
|
|
1778
|
+
markActive();
|
|
1782
1779
|
}
|
|
1783
1780
|
};
|
|
1784
1781
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
@@ -1786,13 +1783,12 @@ function ChatPanel({
|
|
|
1786
1783
|
return () => {
|
|
1787
1784
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
1788
1785
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1786
|
+
console.log("[KiteChat] Escalation ended, marking disconnected");
|
|
1789
1787
|
supabase.from("escalations").update({
|
|
1790
1788
|
customer_status: "disconnected",
|
|
1791
1789
|
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1792
1790
|
}).eq("session_id", currentSessionId).then(
|
|
1793
|
-
() =>
|
|
1794
|
-
console.log("[KiteChat] Marked customer as disconnected");
|
|
1795
|
-
},
|
|
1791
|
+
() => console.log("[KiteChat] Successfully marked disconnected on escalation end"),
|
|
1796
1792
|
(err) => {
|
|
1797
1793
|
console.error("[KiteChat] Failed to mark disconnected:", err);
|
|
1798
1794
|
}
|
|
@@ -1802,17 +1798,14 @@ function ChatPanel({
|
|
|
1802
1798
|
heartbeatIntervalRef.current = null;
|
|
1803
1799
|
}
|
|
1804
1800
|
};
|
|
1805
|
-
}, [isEscalated, sessionId,
|
|
1801
|
+
}, [isEscalated, sessionId, effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
|
|
1806
1802
|
const sendTypingIndicator = React6.useCallback((isTyping) => {
|
|
1807
|
-
if (!typingChannelRef.current) {
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
if (!isEscalated) {
|
|
1812
|
-
console.log("[KiteChat] Cannot send typing - not escalated");
|
|
1803
|
+
if (!typingChannelRef.current || !isEscalated) {
|
|
1804
|
+
if (isTyping) {
|
|
1805
|
+
console.warn("[KiteChat] Typing channel not ready, cannot send typing indicator");
|
|
1806
|
+
}
|
|
1813
1807
|
return;
|
|
1814
1808
|
}
|
|
1815
|
-
console.log(`[KiteChat] Sending typing indicator: ${isTyping}`);
|
|
1816
1809
|
typingChannelRef.current.send({
|
|
1817
1810
|
type: "broadcast",
|
|
1818
1811
|
event: "typing",
|
|
@@ -1821,16 +1814,23 @@ function ChatPanel({
|
|
|
1821
1814
|
}, [isEscalated]);
|
|
1822
1815
|
const userTypingTimeoutRef = React6.useRef(null);
|
|
1823
1816
|
const handleTypingStart = React6.useCallback(() => {
|
|
1824
|
-
if (!isEscalated || !supabaseRef.current) return;
|
|
1817
|
+
if (!isEscalated || !supabaseRef.current || !sessionId) return;
|
|
1825
1818
|
sendTypingIndicator(true);
|
|
1826
|
-
|
|
1819
|
+
supabaseRef.current.from("escalations").update({
|
|
1820
|
+
customer_status: "active",
|
|
1821
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
1822
|
+
}).eq("session_id", sessionId).then(
|
|
1823
|
+
() => {
|
|
1824
|
+
},
|
|
1825
|
+
(err) => console.error("[KiteChat] Failed to update presence:", err)
|
|
1826
|
+
);
|
|
1827
1827
|
if (userTypingTimeoutRef.current) {
|
|
1828
1828
|
window.clearTimeout(userTypingTimeoutRef.current);
|
|
1829
1829
|
}
|
|
1830
1830
|
userTypingTimeoutRef.current = window.setTimeout(() => {
|
|
1831
1831
|
sendTypingIndicator(false);
|
|
1832
1832
|
}, 1500);
|
|
1833
|
-
}, [isEscalated, sendTypingIndicator,
|
|
1833
|
+
}, [isEscalated, sendTypingIndicator, sessionId]);
|
|
1834
1834
|
const streamIntervals = React6.useRef({});
|
|
1835
1835
|
const isEmpty = messages.length === 0;
|
|
1836
1836
|
const [phase, setPhase] = React6.useState("idle");
|
|
@@ -1865,12 +1865,6 @@ function ChatPanel({
|
|
|
1865
1865
|
const latestBulkSummaryNavigationRef = React6.useRef(null);
|
|
1866
1866
|
const [guideComplete, setGuideComplete] = React6.useState(false);
|
|
1867
1867
|
React6.useEffect(() => {
|
|
1868
|
-
window.resetIntegrationNotification = () => {
|
|
1869
|
-
localStorage.removeItem("gmailNotificationSeen");
|
|
1870
|
-
console.log(
|
|
1871
|
-
"Integration notification reset! Click the Integrations tab to see it again."
|
|
1872
|
-
);
|
|
1873
|
-
};
|
|
1874
1868
|
const handleIntegrationTabClick = () => {
|
|
1875
1869
|
const hasSeenNotification = localStorage.getItem("gmailNotificationSeen");
|
|
1876
1870
|
if (!hasSeenNotification) {
|
|
@@ -2012,17 +2006,7 @@ function ChatPanel({
|
|
|
2012
2006
|
return;
|
|
2013
2007
|
}
|
|
2014
2008
|
const currentBulkNav = latestBulkSummaryNavigationRef.current;
|
|
2015
|
-
console.log(
|
|
2016
|
-
"[DEBUG] Keyboard handler - latestBulkSummaryNavigation:",
|
|
2017
|
-
currentBulkNav,
|
|
2018
|
-
"onNavigate:",
|
|
2019
|
-
!!onNavigate
|
|
2020
|
-
);
|
|
2021
2009
|
if (currentBulkNav && onNavigate) {
|
|
2022
|
-
console.log(
|
|
2023
|
-
"[DEBUG] Navigating via keyboard to:",
|
|
2024
|
-
currentBulkNav.page
|
|
2025
|
-
);
|
|
2026
2010
|
e.preventDefault();
|
|
2027
2011
|
e.stopPropagation();
|
|
2028
2012
|
onNavigate(currentBulkNav.page, currentBulkNav.subtab);
|
|
@@ -2068,7 +2052,6 @@ function ChatPanel({
|
|
|
2068
2052
|
const messageId = data.message_id;
|
|
2069
2053
|
const isDuplicate = messageId ? prev.some((m) => m.serverMessageId === messageId) : prev.slice(-5).some((m) => m.content === content);
|
|
2070
2054
|
if (isDuplicate) {
|
|
2071
|
-
console.debug("[KiteChat] Skipping duplicate agent message:", messageId || content.slice(0, 30));
|
|
2072
2055
|
return prev;
|
|
2073
2056
|
}
|
|
2074
2057
|
return [...prev, {
|
|
@@ -2091,7 +2074,6 @@ function ChatPanel({
|
|
|
2091
2074
|
console.error("[KiteChat] Escalation WebSocket error:", err);
|
|
2092
2075
|
};
|
|
2093
2076
|
ws.onclose = () => {
|
|
2094
|
-
console.log("[KiteChat] Escalation WebSocket closed");
|
|
2095
2077
|
};
|
|
2096
2078
|
escalationWsRef.current = ws;
|
|
2097
2079
|
}, [agentUrl]);
|
|
@@ -2105,13 +2087,22 @@ function ChatPanel({
|
|
|
2105
2087
|
type: "user_message",
|
|
2106
2088
|
content
|
|
2107
2089
|
}));
|
|
2108
|
-
|
|
2090
|
+
if (supabaseRef.current && sessionId) {
|
|
2091
|
+
supabaseRef.current.from("escalations").update({
|
|
2092
|
+
customer_status: "active",
|
|
2093
|
+
customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
|
|
2094
|
+
}).eq("session_id", sessionId).then(
|
|
2095
|
+
() => {
|
|
2096
|
+
},
|
|
2097
|
+
(err) => console.error("[KiteChat] Failed to update presence:", err)
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2109
2100
|
return true;
|
|
2110
2101
|
} catch (err) {
|
|
2111
2102
|
console.error("[KiteChat] Failed to send escalated message:", err);
|
|
2112
2103
|
return false;
|
|
2113
2104
|
}
|
|
2114
|
-
}, [
|
|
2105
|
+
}, [sessionId]);
|
|
2115
2106
|
React6.useEffect(() => {
|
|
2116
2107
|
return () => {
|
|
2117
2108
|
if (escalationWsRef.current) {
|
|
@@ -2385,14 +2376,6 @@ function ChatPanel({
|
|
|
2385
2376
|
try {
|
|
2386
2377
|
const controller = new AbortController();
|
|
2387
2378
|
const timeoutId = setTimeout(() => controller.abort(), 6e4);
|
|
2388
|
-
console.log("[ChatPanel] Sending chat request to agent backend...");
|
|
2389
|
-
console.log("[ChatPanel] Agent URL:", agentUrl);
|
|
2390
|
-
console.log("[ChatPanel] User data being sent:");
|
|
2391
|
-
console.log("[ChatPanel] user_id:", effectiveUser.userId);
|
|
2392
|
-
console.log("[ChatPanel] user_name:", effectiveUser.userName);
|
|
2393
|
-
console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
|
|
2394
|
-
console.log("[ChatPanel] org_id:", orgId);
|
|
2395
|
-
console.log("[ChatPanel] authState.status:", authState.status);
|
|
2396
2379
|
const response = await fetch(`${agentUrl}/chat/stream`, {
|
|
2397
2380
|
method: "POST",
|
|
2398
2381
|
headers: {
|
|
@@ -2609,7 +2592,6 @@ function ChatPanel({
|
|
|
2609
2592
|
setMessages((prev) => [...prev, escalationMessage]);
|
|
2610
2593
|
} else if (eventType === "tool_request") {
|
|
2611
2594
|
const toolRequest = data;
|
|
2612
|
-
console.log("[KiteChat] Received tool_request:", toolRequest);
|
|
2613
2595
|
executeToolRequest(toolRequest).catch((err) => {
|
|
2614
2596
|
console.error("[KiteChat] Tool execution failed:", err);
|
|
2615
2597
|
});
|
|
@@ -2927,11 +2909,6 @@ ${userText}`
|
|
|
2927
2909
|
}
|
|
2928
2910
|
});
|
|
2929
2911
|
} else if (eventType === "summary") {
|
|
2930
|
-
console.log("[DEBUG] Received summary event - data:", data);
|
|
2931
|
-
console.log(
|
|
2932
|
-
"[DEBUG] navigationPage from backend:",
|
|
2933
|
-
data.navigationPage
|
|
2934
|
-
);
|
|
2935
2912
|
setPhase("idle");
|
|
2936
2913
|
setProgressSteps([]);
|
|
2937
2914
|
setPendingBulkSession(null);
|
|
@@ -2951,7 +2928,6 @@ ${userText}`
|
|
|
2951
2928
|
navigationPage: data.navigationPage
|
|
2952
2929
|
}
|
|
2953
2930
|
};
|
|
2954
|
-
console.log("[DEBUG] Creating bulkSummary message:", newMsg);
|
|
2955
2931
|
return [...filtered, newMsg];
|
|
2956
2932
|
});
|
|
2957
2933
|
setTimeout(() => {
|
|
@@ -4522,28 +4498,11 @@ ${userText}`
|
|
|
4522
4498
|
onClick: (e) => {
|
|
4523
4499
|
e.preventDefault();
|
|
4524
4500
|
e.stopPropagation();
|
|
4525
|
-
console.log(
|
|
4526
|
-
"[DEBUG] Button clicked - navigationPage:",
|
|
4527
|
-
navigationPage,
|
|
4528
|
-
"onNavigate:",
|
|
4529
|
-
!!onNavigate
|
|
4530
|
-
);
|
|
4531
4501
|
if (onNavigate && navigationPage.page) {
|
|
4532
|
-
console.log(
|
|
4533
|
-
"[DEBUG] Calling onNavigate with page:",
|
|
4534
|
-
navigationPage.page
|
|
4535
|
-
);
|
|
4536
4502
|
onNavigate(
|
|
4537
4503
|
navigationPage.page,
|
|
4538
4504
|
navigationPage.subtab
|
|
4539
4505
|
);
|
|
4540
|
-
} else {
|
|
4541
|
-
console.log(
|
|
4542
|
-
"[DEBUG] Condition failed - onNavigate:",
|
|
4543
|
-
!!onNavigate,
|
|
4544
|
-
"navigationPage.page:",
|
|
4545
|
-
navigationPage.page
|
|
4546
|
-
);
|
|
4547
4506
|
}
|
|
4548
4507
|
},
|
|
4549
4508
|
className: "flex items-center gap-2 text-xs text-gray-500 hover:text-gray-700 transition-colors group cursor-pointer",
|
|
@@ -4803,7 +4762,8 @@ function ChatPanelWithToggle({
|
|
|
4803
4762
|
supabaseAnonKey,
|
|
4804
4763
|
initialCorner,
|
|
4805
4764
|
onCornerChange,
|
|
4806
|
-
productBackendUrl
|
|
4765
|
+
productBackendUrl,
|
|
4766
|
+
getAuthHeaders
|
|
4807
4767
|
}) {
|
|
4808
4768
|
const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
|
|
4809
4769
|
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
@@ -4833,7 +4793,8 @@ function ChatPanelWithToggle({
|
|
|
4833
4793
|
supabaseAnonKey,
|
|
4834
4794
|
initialCorner,
|
|
4835
4795
|
onCornerChange,
|
|
4836
|
-
productBackendUrl
|
|
4796
|
+
productBackendUrl,
|
|
4797
|
+
getAuthHeaders
|
|
4837
4798
|
}
|
|
4838
4799
|
);
|
|
4839
4800
|
}
|
|
@@ -4893,7 +4854,8 @@ function KiteChatWrapper({
|
|
|
4893
4854
|
userEmail: config.userEmail,
|
|
4894
4855
|
supabaseUrl: config.supabaseUrl,
|
|
4895
4856
|
supabaseAnonKey: config.supabaseAnonKey,
|
|
4896
|
-
productBackendUrl: config.productBackendUrl
|
|
4857
|
+
productBackendUrl: config.productBackendUrl,
|
|
4858
|
+
getAuthHeaders: config.getAuthHeaders
|
|
4897
4859
|
}
|
|
4898
4860
|
);
|
|
4899
4861
|
}
|
|
@@ -4936,7 +4898,6 @@ function createKiteChat(config) {
|
|
|
4936
4898
|
}
|
|
4937
4899
|
)
|
|
4938
4900
|
);
|
|
4939
|
-
console.log("[KiteChat] Mounted");
|
|
4940
4901
|
},
|
|
4941
4902
|
unmount() {
|
|
4942
4903
|
if (!root) {
|
|
@@ -4948,7 +4909,6 @@ function createKiteChat(config) {
|
|
|
4948
4909
|
containerElement = null;
|
|
4949
4910
|
configUpdater = null;
|
|
4950
4911
|
stateUpdaters = null;
|
|
4951
|
-
console.log("[KiteChat] Unmounted");
|
|
4952
4912
|
},
|
|
4953
4913
|
open() {
|
|
4954
4914
|
stateUpdaters?.setIsOpen(true);
|
package/dist/auto.d.cts
CHANGED
package/dist/auto.d.ts
CHANGED