@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/dist/index.cjs CHANGED
@@ -66,7 +66,7 @@ __export(src_exports, {
66
66
  module.exports = __toCommonJS(src_exports);
67
67
 
68
68
  // src/createKiteChat.tsx
69
- var import_react = __toESM(require("react"), 1);
69
+ var import_react2 = __toESM(require("react"), 1);
70
70
  var import_client = require("react-dom/client");
71
71
 
72
72
  // src/ChatPanel.tsx
@@ -379,28 +379,22 @@ function useUserAuth({
379
379
  }) {
380
380
  const [authState, setAuthState] = React4.useState({ status: "idle" });
381
381
  const lastSessionIdRef = React4.useRef(null);
382
+ const lastEnabledRef = React4.useRef(enabled);
382
383
  const fetchUser = React4.useCallback(async () => {
383
384
  if (!productBackendUrl || !enabled) {
384
- console.log("[useUserAuth] Skipping auth - productBackendUrl:", productBackendUrl, "enabled:", enabled);
385
385
  setAuthState({ status: "idle" });
386
386
  return;
387
387
  }
388
- console.log("[useUserAuth] Starting auth request to product backend...");
389
- console.log("[useUserAuth] Product backend URL:", productBackendUrl);
390
- console.log("[useUserAuth] Full request URL:", `${productBackendUrl}/users/me`);
391
388
  setAuthState({ status: "loading" });
392
389
  try {
393
390
  const response = await fetch(`${productBackendUrl}/users/me`, {
394
391
  method: "GET",
395
392
  credentials: "include",
396
- // Include cookies for authentication
397
393
  headers: {
398
394
  "Accept": "application/json"
399
395
  }
400
396
  });
401
- console.log("[useUserAuth] Response received - status:", response.status, "ok:", response.ok);
402
397
  if (!response.ok) {
403
- console.log("[useUserAuth] Auth request failed with status:", response.status);
404
398
  if (response.status === 401) {
405
399
  throw new Error("Please log in to use the chat assistant.");
406
400
  }
@@ -410,27 +404,36 @@ function useUserAuth({
410
404
  throw new Error(`Authentication failed (${response.status})`);
411
405
  }
412
406
  const user = await response.json();
413
- console.log("[useUserAuth] Auth SUCCESS - parsed user data:");
414
- console.log("[useUserAuth] id:", user.id);
415
- console.log("[useUserAuth] email:", user.email);
416
- console.log("[useUserAuth] name:", user.name);
417
- console.log("[useUserAuth] role:", user.role);
418
- console.log("[useUserAuth] isInternal:", user.isInternal);
419
- console.log("[useUserAuth] agreementsSigned:", user.agreementsSigned);
420
- console.log("[useUserAuth] lastLoginTime:", user.lastLoginTime);
421
407
  setAuthState({ status: "authenticated", user });
422
408
  } catch (error) {
423
- console.log("[useUserAuth] Auth ERROR:", error);
409
+ if (error instanceof Error) {
410
+ const errorMessage = error.message.toLowerCase();
411
+ const isCorsError = errorMessage.includes("cors") || errorMessage.includes("network");
412
+ const is404Error = errorMessage.includes("404");
413
+ if (isCorsError || is404Error) {
414
+ console.warn("[useUserAuth] Auth endpoint unavailable, falling back to unauthenticated mode:", error.message);
415
+ setAuthState({ status: "idle" });
416
+ return;
417
+ }
418
+ }
424
419
  const message = error instanceof Error ? error.message : "Unable to verify your identity. Please try again.";
425
420
  setAuthState({ status: "error", error: message });
426
421
  }
427
422
  }, [productBackendUrl, enabled]);
428
423
  React4.useEffect(() => {
429
- if (sessionId !== lastSessionIdRef.current) {
424
+ const sessionChanged = sessionId !== lastSessionIdRef.current;
425
+ const enabledChanged = enabled !== lastEnabledRef.current;
426
+ const becameEnabled = enabled && !lastEnabledRef.current;
427
+ if (sessionChanged) {
430
428
  lastSessionIdRef.current = sessionId;
429
+ }
430
+ if (enabledChanged) {
431
+ lastEnabledRef.current = enabled;
432
+ }
433
+ if (sessionChanged || becameEnabled) {
431
434
  fetchUser();
432
435
  }
433
- }, [sessionId, fetchUser]);
436
+ }, [sessionId, enabled, fetchUser]);
434
437
  const retry = React4.useCallback(() => {
435
438
  fetchUser();
436
439
  }, [fetchUser]);
@@ -447,13 +450,11 @@ function useOrgConfig({ agentUrl, orgId }) {
447
450
  });
448
451
  React5.useEffect(() => {
449
452
  if (!agentUrl || !orgId) {
450
- console.log("[useOrgConfig] Skipping - missing agentUrl or orgId", { agentUrl, orgId });
451
453
  return;
452
454
  }
453
455
  const fetchConfig = async () => {
454
456
  setState({ status: "loading", config: null, error: null });
455
457
  const url = `${agentUrl}/org/${orgId}/config`;
456
- console.log("[useOrgConfig] Fetching org config from:", url);
457
458
  try {
458
459
  const response = await fetch(url, {
459
460
  method: "GET",
@@ -465,7 +466,6 @@ function useOrgConfig({ agentUrl, orgId }) {
465
466
  throw new Error(`Failed to fetch org config (${response.status})`);
466
467
  }
467
468
  const config = await response.json();
468
- console.log("[useOrgConfig] Received config:", config);
469
469
  setState({ status: "success", config, error: null });
470
470
  } catch (error) {
471
471
  const message = error instanceof Error ? error.message : "Failed to fetch org config";
@@ -478,6 +478,75 @@ function useOrgConfig({ agentUrl, orgId }) {
478
478
  return state;
479
479
  }
480
480
 
481
+ // src/hooks/useFrontendToolExecutor.ts
482
+ var import_react = require("react");
483
+ function useFrontendToolExecutor({
484
+ productBackendUrl,
485
+ agentUrl,
486
+ sessionId
487
+ }) {
488
+ const sendToolResult = (0, import_react.useCallback)(async (payload) => {
489
+ try {
490
+ await fetch(`${agentUrl}/chat/tool-result`, {
491
+ method: "POST",
492
+ headers: {
493
+ "Content-Type": "application/json"
494
+ },
495
+ body: JSON.stringify(payload)
496
+ });
497
+ } catch (error) {
498
+ console.error("[FrontendToolExecutor] Failed to send tool result:", error);
499
+ }
500
+ }, [agentUrl]);
501
+ const executeToolRequest = (0, import_react.useCallback)(async (toolRequest) => {
502
+ const { call_id, arguments: args, endpoint, method, path_params } = toolRequest;
503
+ try {
504
+ let url = endpoint;
505
+ for (const param of path_params) {
506
+ if (args[param]) {
507
+ url = url.replace(`{${param}}`, encodeURIComponent(args[param]));
508
+ }
509
+ }
510
+ const queryParams = new URLSearchParams();
511
+ for (const [key, value] of Object.entries(args)) {
512
+ if (!path_params.includes(key) && value !== void 0 && value !== null) {
513
+ queryParams.append(key, String(value));
514
+ }
515
+ }
516
+ const queryString = queryParams.toString();
517
+ const fullUrl = `${productBackendUrl}${url}${queryString ? "?" + queryString : ""}`;
518
+ const response = await fetch(fullUrl, {
519
+ method,
520
+ credentials: "include",
521
+ headers: {
522
+ "Accept": "application/json",
523
+ "Content-Type": "application/json"
524
+ }
525
+ });
526
+ let result;
527
+ if (response.ok) {
528
+ result = await response.json();
529
+ } else {
530
+ const errorText = await response.text();
531
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
532
+ }
533
+ await sendToolResult({
534
+ session_id: sessionId,
535
+ call_id,
536
+ result
537
+ });
538
+ } catch (error) {
539
+ console.error("[FrontendToolExecutor] Tool execution failed:", error);
540
+ await sendToolResult({
541
+ session_id: sessionId,
542
+ call_id,
543
+ error: error instanceof Error ? error.message : "Unknown error"
544
+ });
545
+ }
546
+ }, [productBackendUrl, sessionId, sendToolResult]);
547
+ return { executeToolRequest };
548
+ }
549
+
481
550
  // src/components/ui/card.tsx
482
551
  var import_jsx_runtime7 = require("react/jsx-runtime");
483
552
  function Card({ className, ...props }) {
@@ -1078,7 +1147,6 @@ function TypingIndicator({ className = "" }) {
1078
1147
 
1079
1148
  // src/ChatPanel.tsx
1080
1149
  var import_jsx_runtime10 = require("react/jsx-runtime");
1081
- var CHAT_PANEL_VERSION = true ? "0.2.48" : "dev";
1082
1150
  var DEFAULT_AGENT_URL = "http://localhost:5002";
1083
1151
  var PANEL_WIDTH = 400;
1084
1152
  var PANEL_HEIGHT = 600;
@@ -1542,7 +1610,8 @@ function ChatPanel({
1542
1610
  supabaseAnonKey,
1543
1611
  initialCorner = "bottom-left",
1544
1612
  onCornerChange,
1545
- productBackendUrl
1613
+ productBackendUrl,
1614
+ getAuthHeaders
1546
1615
  } = {}) {
1547
1616
  const [messages, setMessages] = React6.useState(initialMessages);
1548
1617
  const [input, setInput] = React6.useState("");
@@ -1570,37 +1639,11 @@ function ChatPanel({
1570
1639
  enabled: !!effectiveProductBackendUrl && orgConfigState.status === "success"
1571
1640
  // Only enable after config is fetched
1572
1641
  });
1573
- React6.useEffect(() => {
1574
- if (!effectiveProductBackendUrl || orgConfigState.status !== "success") {
1575
- return;
1576
- }
1577
- const testProductBackendEndpoint = async () => {
1578
- const url = `${effectiveProductBackendUrl}/getDocument/snowkite/categories/`;
1579
- console.log("[KiteChat TEST] Testing product backend connectivity...");
1580
- console.log("[KiteChat TEST] URL:", url);
1581
- try {
1582
- const response = await fetch(url, {
1583
- method: "GET",
1584
- // Note: not using credentials: 'include' to avoid CORS issues with wildcard
1585
- headers: {
1586
- "Accept": "application/json"
1587
- }
1588
- });
1589
- console.log("[KiteChat TEST] Response status:", response.status);
1590
- console.log("[KiteChat TEST] Response ok:", response.ok);
1591
- if (response.ok) {
1592
- const data = await response.json();
1593
- console.log("[KiteChat TEST] SUCCESS - product backend reachable, data:", data);
1594
- } else {
1595
- const errorText = await response.text();
1596
- console.log("[KiteChat TEST] FAILED - status:", response.status, "body:", errorText);
1597
- }
1598
- } catch (error) {
1599
- console.error("[KiteChat TEST] ERROR:", error);
1600
- }
1601
- };
1602
- testProductBackendEndpoint();
1603
- }, [effectiveProductBackendUrl, orgConfigState.status]);
1642
+ const { executeToolRequest } = useFrontendToolExecutor({
1643
+ productBackendUrl: effectiveProductBackendUrl || "",
1644
+ agentUrl,
1645
+ sessionId
1646
+ });
1604
1647
  const effectiveUser = React6.useMemo(() => {
1605
1648
  if (sessionUser) {
1606
1649
  return sessionUser;
@@ -1631,7 +1674,6 @@ function ChatPanel({
1631
1674
  userRole: authState.user.role,
1632
1675
  isInternal: authState.user.isInternal
1633
1676
  });
1634
- console.log("[ChatPanel] Session user captured:", authState.user.id);
1635
1677
  }
1636
1678
  }, [authState, sessionUser]);
1637
1679
  const isWaitingForAuth = React6.useMemo(() => {
@@ -1644,26 +1686,18 @@ function ChatPanel({
1644
1686
  const supabaseRef = React6.useRef(null);
1645
1687
  const typingChannelRef = React6.useRef(null);
1646
1688
  const typingTimeoutRef = React6.useRef(null);
1647
- React6.useEffect(() => {
1648
- console.log(`[KiteChat] Chat Panel v${CHAT_PANEL_VERSION} loaded`);
1649
- }, []);
1650
1689
  const resetSession = React6.useCallback(() => {
1651
- console.log("[KiteChat] resetSession called", { isEscalated, hasSupabase: !!supabaseRef.current, sessionId });
1652
1690
  if (isEscalated && supabaseRef.current && sessionId) {
1653
- console.log("[KiteChat] Updating customer_status to disconnected for session:", sessionId);
1654
1691
  supabaseRef.current.from("escalations").update({
1655
1692
  customer_status: "disconnected",
1656
1693
  customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1657
1694
  }).eq("session_id", sessionId).then(
1658
- (result) => {
1659
- console.log("[KiteChat] Disconnect update result:", result);
1695
+ () => {
1660
1696
  },
1661
1697
  (err) => {
1662
1698
  console.error("[KiteChat] Disconnect update failed:", err);
1663
1699
  }
1664
1700
  );
1665
- } else {
1666
- console.log("[KiteChat] Skipping disconnect update - conditions not met");
1667
1701
  }
1668
1702
  setSessionUser(null);
1669
1703
  setSessionId(crypto.randomUUID());
@@ -1689,12 +1723,9 @@ function ChatPanel({
1689
1723
  }
1690
1724
  const channelName = `typing:${sessionId}`;
1691
1725
  const channel = supabaseRef.current.channel(channelName);
1692
- console.log(`[KiteChat] Subscribing to typing channel: ${channelName}`);
1693
1726
  channel.on("broadcast", { event: "typing" }, (payload) => {
1694
- console.log("[KiteChat] Received typing broadcast:", payload);
1695
1727
  const { sender, isTyping } = payload.payload;
1696
1728
  if (sender === "agent") {
1697
- console.log(`[KiteChat] Agent typing: ${isTyping}`);
1698
1729
  setAgentIsTyping(isTyping);
1699
1730
  if (isTyping) {
1700
1731
  if (typingTimeoutRef.current) {
@@ -1706,10 +1737,11 @@ function ChatPanel({
1706
1737
  }
1707
1738
  }
1708
1739
  }).subscribe((status) => {
1709
- console.log(`[KiteChat] Typing channel status: ${status}`);
1710
1740
  if (status === "SUBSCRIBED") {
1711
1741
  typingChannelRef.current = channel;
1712
- console.log("[KiteChat] Typing channel ready");
1742
+ console.log("[KiteChat] Typing channel subscribed successfully");
1743
+ } else if (status === "CHANNEL_ERROR") {
1744
+ console.error("[KiteChat] Typing channel subscription failed");
1713
1745
  }
1714
1746
  });
1715
1747
  return () => {
@@ -1720,6 +1752,20 @@ function ChatPanel({
1720
1752
  }
1721
1753
  };
1722
1754
  }, [isEscalated, sessionId]);
1755
+ React6.useEffect(() => {
1756
+ if (!isOpen && isEscalated && supabaseRef.current && sessionId) {
1757
+ console.log("[KiteChat] Panel closed during live chat, marking disconnected");
1758
+ supabaseRef.current.from("escalations").update({
1759
+ customer_status: "disconnected",
1760
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1761
+ }).eq("session_id", sessionId).then(
1762
+ () => console.log("[KiteChat] Successfully marked disconnected on panel close"),
1763
+ (err) => {
1764
+ console.error("[KiteChat] Failed to mark disconnected on panel close:", err);
1765
+ }
1766
+ );
1767
+ }
1768
+ }, [isOpen, isEscalated, sessionId]);
1723
1769
  const heartbeatIntervalRef = React6.useRef(null);
1724
1770
  const updateCustomerStatus = React6.useCallback(async (status) => {
1725
1771
  if (!supabaseRef.current || !sessionId) return;
@@ -1738,9 +1784,20 @@ function ChatPanel({
1738
1784
  }
1739
1785
  const currentSessionId = sessionId;
1740
1786
  const supabase = supabaseRef.current;
1741
- updateCustomerStatus("active");
1787
+ const markActive = () => {
1788
+ supabase.from("escalations").update({
1789
+ customer_status: "active",
1790
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1791
+ }).eq("session_id", currentSessionId).then(
1792
+ () => {
1793
+ },
1794
+ (err) => console.error("[KiteChat] Failed to update customer status:", err)
1795
+ );
1796
+ };
1797
+ console.log("[KiteChat] Starting presence heartbeat for live chat");
1798
+ markActive();
1742
1799
  heartbeatIntervalRef.current = window.setInterval(() => {
1743
- updateCustomerStatus("active");
1800
+ markActive();
1744
1801
  }, 6e4);
1745
1802
  const handleBeforeUnload = () => {
1746
1803
  supabase.from("escalations").update({
@@ -1755,7 +1812,7 @@ function ChatPanel({
1755
1812
  customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1756
1813
  }).eq("session_id", currentSessionId);
1757
1814
  } else if (document.visibilityState === "visible") {
1758
- updateCustomerStatus("active");
1815
+ markActive();
1759
1816
  }
1760
1817
  };
1761
1818
  window.addEventListener("beforeunload", handleBeforeUnload);
@@ -1763,13 +1820,12 @@ function ChatPanel({
1763
1820
  return () => {
1764
1821
  window.removeEventListener("beforeunload", handleBeforeUnload);
1765
1822
  document.removeEventListener("visibilitychange", handleVisibilityChange);
1823
+ console.log("[KiteChat] Escalation ended, marking disconnected");
1766
1824
  supabase.from("escalations").update({
1767
1825
  customer_status: "disconnected",
1768
1826
  customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1769
1827
  }).eq("session_id", currentSessionId).then(
1770
- () => {
1771
- console.log("[KiteChat] Marked customer as disconnected");
1772
- },
1828
+ () => console.log("[KiteChat] Successfully marked disconnected on escalation end"),
1773
1829
  (err) => {
1774
1830
  console.error("[KiteChat] Failed to mark disconnected:", err);
1775
1831
  }
@@ -1779,17 +1835,14 @@ function ChatPanel({
1779
1835
  heartbeatIntervalRef.current = null;
1780
1836
  }
1781
1837
  };
1782
- }, [isEscalated, sessionId, updateCustomerStatus]);
1838
+ }, [isEscalated, sessionId]);
1783
1839
  const sendTypingIndicator = React6.useCallback((isTyping) => {
1784
- if (!typingChannelRef.current) {
1785
- console.log("[KiteChat] Cannot send typing - channel not ready");
1786
- return;
1787
- }
1788
- if (!isEscalated) {
1789
- console.log("[KiteChat] Cannot send typing - not escalated");
1840
+ if (!typingChannelRef.current || !isEscalated) {
1841
+ if (isTyping) {
1842
+ console.warn("[KiteChat] Typing channel not ready, cannot send typing indicator");
1843
+ }
1790
1844
  return;
1791
1845
  }
1792
- console.log(`[KiteChat] Sending typing indicator: ${isTyping}`);
1793
1846
  typingChannelRef.current.send({
1794
1847
  type: "broadcast",
1795
1848
  event: "typing",
@@ -1798,16 +1851,23 @@ function ChatPanel({
1798
1851
  }, [isEscalated]);
1799
1852
  const userTypingTimeoutRef = React6.useRef(null);
1800
1853
  const handleTypingStart = React6.useCallback(() => {
1801
- if (!isEscalated || !supabaseRef.current) return;
1854
+ if (!isEscalated || !supabaseRef.current || !sessionId) return;
1802
1855
  sendTypingIndicator(true);
1803
- updateCustomerStatus("active");
1856
+ supabaseRef.current.from("escalations").update({
1857
+ customer_status: "active",
1858
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1859
+ }).eq("session_id", sessionId).then(
1860
+ () => {
1861
+ },
1862
+ (err) => console.error("[KiteChat] Failed to update presence:", err)
1863
+ );
1804
1864
  if (userTypingTimeoutRef.current) {
1805
1865
  window.clearTimeout(userTypingTimeoutRef.current);
1806
1866
  }
1807
1867
  userTypingTimeoutRef.current = window.setTimeout(() => {
1808
1868
  sendTypingIndicator(false);
1809
1869
  }, 1500);
1810
- }, [isEscalated, sendTypingIndicator, updateCustomerStatus]);
1870
+ }, [isEscalated, sendTypingIndicator, sessionId]);
1811
1871
  const streamIntervals = React6.useRef({});
1812
1872
  const isEmpty = messages.length === 0;
1813
1873
  const [phase, setPhase] = React6.useState("idle");
@@ -1842,12 +1902,6 @@ function ChatPanel({
1842
1902
  const latestBulkSummaryNavigationRef = React6.useRef(null);
1843
1903
  const [guideComplete, setGuideComplete] = React6.useState(false);
1844
1904
  React6.useEffect(() => {
1845
- window.resetIntegrationNotification = () => {
1846
- localStorage.removeItem("gmailNotificationSeen");
1847
- console.log(
1848
- "Integration notification reset! Click the Integrations tab to see it again."
1849
- );
1850
- };
1851
1905
  const handleIntegrationTabClick = () => {
1852
1906
  const hasSeenNotification = localStorage.getItem("gmailNotificationSeen");
1853
1907
  if (!hasSeenNotification) {
@@ -1989,17 +2043,7 @@ function ChatPanel({
1989
2043
  return;
1990
2044
  }
1991
2045
  const currentBulkNav = latestBulkSummaryNavigationRef.current;
1992
- console.log(
1993
- "[DEBUG] Keyboard handler - latestBulkSummaryNavigation:",
1994
- currentBulkNav,
1995
- "onNavigate:",
1996
- !!onNavigate
1997
- );
1998
2046
  if (currentBulkNav && onNavigate) {
1999
- console.log(
2000
- "[DEBUG] Navigating via keyboard to:",
2001
- currentBulkNav.page
2002
- );
2003
2047
  e.preventDefault();
2004
2048
  e.stopPropagation();
2005
2049
  onNavigate(currentBulkNav.page, currentBulkNav.subtab);
@@ -2045,7 +2089,6 @@ function ChatPanel({
2045
2089
  const messageId = data.message_id;
2046
2090
  const isDuplicate = messageId ? prev.some((m) => m.serverMessageId === messageId) : prev.slice(-5).some((m) => m.content === content);
2047
2091
  if (isDuplicate) {
2048
- console.debug("[KiteChat] Skipping duplicate agent message:", messageId || content.slice(0, 30));
2049
2092
  return prev;
2050
2093
  }
2051
2094
  return [...prev, {
@@ -2068,7 +2111,6 @@ function ChatPanel({
2068
2111
  console.error("[KiteChat] Escalation WebSocket error:", err);
2069
2112
  };
2070
2113
  ws.onclose = () => {
2071
- console.log("[KiteChat] Escalation WebSocket closed");
2072
2114
  };
2073
2115
  escalationWsRef.current = ws;
2074
2116
  }, [agentUrl]);
@@ -2082,13 +2124,22 @@ function ChatPanel({
2082
2124
  type: "user_message",
2083
2125
  content
2084
2126
  }));
2085
- updateCustomerStatus("active");
2127
+ if (supabaseRef.current && sessionId) {
2128
+ supabaseRef.current.from("escalations").update({
2129
+ customer_status: "active",
2130
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
2131
+ }).eq("session_id", sessionId).then(
2132
+ () => {
2133
+ },
2134
+ (err) => console.error("[KiteChat] Failed to update presence:", err)
2135
+ );
2136
+ }
2086
2137
  return true;
2087
2138
  } catch (err) {
2088
2139
  console.error("[KiteChat] Failed to send escalated message:", err);
2089
2140
  return false;
2090
2141
  }
2091
- }, [updateCustomerStatus]);
2142
+ }, [sessionId]);
2092
2143
  React6.useEffect(() => {
2093
2144
  return () => {
2094
2145
  if (escalationWsRef.current) {
@@ -2362,14 +2413,6 @@ function ChatPanel({
2362
2413
  try {
2363
2414
  const controller = new AbortController();
2364
2415
  const timeoutId = setTimeout(() => controller.abort(), 6e4);
2365
- console.log("[ChatPanel] Sending chat request to agent backend...");
2366
- console.log("[ChatPanel] Agent URL:", agentUrl);
2367
- console.log("[ChatPanel] User data being sent:");
2368
- console.log("[ChatPanel] user_id:", effectiveUser.userId);
2369
- console.log("[ChatPanel] user_name:", effectiveUser.userName);
2370
- console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
2371
- console.log("[ChatPanel] org_id:", orgId);
2372
- console.log("[ChatPanel] authState.status:", authState.status);
2373
2416
  const response = await fetch(`${agentUrl}/chat/stream`, {
2374
2417
  method: "POST",
2375
2418
  headers: {
@@ -2584,6 +2627,11 @@ function ChatPanel({
2584
2627
  content: data.message || "You've been connected to our support queue. An agent will be with you shortly."
2585
2628
  };
2586
2629
  setMessages((prev) => [...prev, escalationMessage]);
2630
+ } else if (eventType === "tool_request") {
2631
+ const toolRequest = data;
2632
+ executeToolRequest(toolRequest).catch((err) => {
2633
+ console.error("[KiteChat] Tool execution failed:", err);
2634
+ });
2587
2635
  } else if (eventType === "token") {
2588
2636
  }
2589
2637
  } catch (parseError) {
@@ -2898,11 +2946,6 @@ ${userText}`
2898
2946
  }
2899
2947
  });
2900
2948
  } else if (eventType === "summary") {
2901
- console.log("[DEBUG] Received summary event - data:", data);
2902
- console.log(
2903
- "[DEBUG] navigationPage from backend:",
2904
- data.navigationPage
2905
- );
2906
2949
  setPhase("idle");
2907
2950
  setProgressSteps([]);
2908
2951
  setPendingBulkSession(null);
@@ -2922,7 +2965,6 @@ ${userText}`
2922
2965
  navigationPage: data.navigationPage
2923
2966
  }
2924
2967
  };
2925
- console.log("[DEBUG] Creating bulkSummary message:", newMsg);
2926
2968
  return [...filtered, newMsg];
2927
2969
  });
2928
2970
  setTimeout(() => {
@@ -4493,28 +4535,11 @@ ${userText}`
4493
4535
  onClick: (e) => {
4494
4536
  e.preventDefault();
4495
4537
  e.stopPropagation();
4496
- console.log(
4497
- "[DEBUG] Button clicked - navigationPage:",
4498
- navigationPage,
4499
- "onNavigate:",
4500
- !!onNavigate
4501
- );
4502
4538
  if (onNavigate && navigationPage.page) {
4503
- console.log(
4504
- "[DEBUG] Calling onNavigate with page:",
4505
- navigationPage.page
4506
- );
4507
4539
  onNavigate(
4508
4540
  navigationPage.page,
4509
4541
  navigationPage.subtab
4510
4542
  );
4511
- } else {
4512
- console.log(
4513
- "[DEBUG] Condition failed - onNavigate:",
4514
- !!onNavigate,
4515
- "navigationPage.page:",
4516
- navigationPage.page
4517
- );
4518
4543
  }
4519
4544
  },
4520
4545
  className: "flex items-center gap-2 text-xs text-gray-500 hover:text-gray-700 transition-colors group cursor-pointer",
@@ -4794,7 +4819,8 @@ function ChatPanelWithToggle({
4794
4819
  supabaseAnonKey,
4795
4820
  initialCorner,
4796
4821
  onCornerChange,
4797
- productBackendUrl
4822
+ productBackendUrl,
4823
+ getAuthHeaders
4798
4824
  }) {
4799
4825
  const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
4800
4826
  const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
@@ -4824,7 +4850,8 @@ function ChatPanelWithToggle({
4824
4850
  supabaseAnonKey,
4825
4851
  initialCorner,
4826
4852
  onCornerChange,
4827
- productBackendUrl
4853
+ productBackendUrl,
4854
+ getAuthHeaders
4828
4855
  }
4829
4856
  );
4830
4857
  }
@@ -4848,14 +4875,14 @@ function KiteChatWrapper({
4848
4875
  onConfigUpdate,
4849
4876
  onStateUpdate
4850
4877
  }) {
4851
- const [config, setConfig] = import_react.default.useState(initialConfig);
4852
- const [currentPage, setCurrentPage] = import_react.default.useState(initialConfig.currentPage || "dashboard");
4853
- const [isOpen, setIsOpen] = import_react.default.useState(false);
4854
- const isOpenRef = import_react.default.useRef(false);
4855
- import_react.default.useEffect(() => {
4878
+ const [config, setConfig] = import_react2.default.useState(initialConfig);
4879
+ const [currentPage, setCurrentPage] = import_react2.default.useState(initialConfig.currentPage || "dashboard");
4880
+ const [isOpen, setIsOpen] = import_react2.default.useState(false);
4881
+ const isOpenRef = import_react2.default.useRef(false);
4882
+ import_react2.default.useEffect(() => {
4856
4883
  isOpenRef.current = isOpen;
4857
4884
  }, [isOpen]);
4858
- import_react.default.useEffect(() => {
4885
+ import_react2.default.useEffect(() => {
4859
4886
  onConfigUpdate((newConfig) => {
4860
4887
  if (newConfig.currentPage !== void 0) {
4861
4888
  setCurrentPage(newConfig.currentPage);
@@ -4867,7 +4894,7 @@ function KiteChatWrapper({
4867
4894
  getIsOpen: () => isOpenRef.current
4868
4895
  });
4869
4896
  }, [onConfigUpdate, onStateUpdate]);
4870
- import_react.default.useEffect(() => {
4897
+ import_react2.default.useEffect(() => {
4871
4898
  const container = document.getElementById("kite-chat-root");
4872
4899
  if (!container) return;
4873
4900
  if (config.theme === "dark") {
@@ -4896,7 +4923,8 @@ function KiteChatWrapper({
4896
4923
  userEmail: config.userEmail,
4897
4924
  supabaseUrl: config.supabaseUrl,
4898
4925
  supabaseAnonKey: config.supabaseAnonKey,
4899
- productBackendUrl: config.productBackendUrl
4926
+ productBackendUrl: config.productBackendUrl,
4927
+ getAuthHeaders: config.getAuthHeaders
4900
4928
  }
4901
4929
  );
4902
4930
  }
@@ -4939,7 +4967,6 @@ function createKiteChat(config) {
4939
4967
  }
4940
4968
  )
4941
4969
  );
4942
- console.log("[KiteChat] Mounted");
4943
4970
  },
4944
4971
  unmount() {
4945
4972
  if (!root) {
@@ -4951,7 +4978,6 @@ function createKiteChat(config) {
4951
4978
  containerElement = null;
4952
4979
  configUpdater = null;
4953
4980
  stateUpdaters = null;
4954
- console.log("[KiteChat] Unmounted");
4955
4981
  },
4956
4982
  open() {
4957
4983
  stateUpdaters?.setIsOpen(true);
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { i as ActionData, A as ActionType, C as ChatPanel, d as ChatPanelProps, b as ChatPanelWithToggle, e as ChatPanelWithToggleProps, H as HelpButton, g as HelpButtonProps, K as KiteChatConfig, a as KiteChatInstance, N as NavigationTarget, h as Page, k as PanelCorner, P as PanelToggle, f as PanelToggleProps, S as SettingsTab, j as StartingQuestion, c as createKiteChat } from './createKiteChat-e6BnJS6T.cjs';
1
+ export { i as ActionData, A as ActionType, C as ChatPanel, d as ChatPanelProps, b as ChatPanelWithToggle, e as ChatPanelWithToggleProps, H as HelpButton, g as HelpButtonProps, K as KiteChatConfig, a as KiteChatInstance, N as NavigationTarget, h as Page, k as PanelCorner, P as PanelToggle, f as PanelToggleProps, S as SettingsTab, j as StartingQuestion, c as createKiteChat } from './createKiteChat-DeQKgFyx.cjs';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import * as React from 'react';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { i as ActionData, A as ActionType, C as ChatPanel, d as ChatPanelProps, b as ChatPanelWithToggle, e as ChatPanelWithToggleProps, H as HelpButton, g as HelpButtonProps, K as KiteChatConfig, a as KiteChatInstance, N as NavigationTarget, h as Page, k as PanelCorner, P as PanelToggle, f as PanelToggleProps, S as SettingsTab, j as StartingQuestion, c as createKiteChat } from './createKiteChat-e6BnJS6T.js';
1
+ export { i as ActionData, A as ActionType, C as ChatPanel, d as ChatPanelProps, b as ChatPanelWithToggle, e as ChatPanelWithToggleProps, H as HelpButton, g as HelpButtonProps, K as KiteChatConfig, a as KiteChatInstance, N as NavigationTarget, h as Page, k as PanelCorner, P as PanelToggle, f as PanelToggleProps, S as SettingsTab, j as StartingQuestion, c as createKiteChat } from './createKiteChat-DeQKgFyx.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import * as React from 'react';
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  cn,
32
32
  createKiteChat,
33
33
  useGuideCursor
34
- } from "./chunk-LOTJ3U5L.js";
34
+ } from "./chunk-BLSVIF7H.js";
35
35
  export {
36
36
  ApiKeyList,
37
37
  AssistantActivity,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kite-copilot/chat-panel",
3
- "version": "0.2.48",
3
+ "version": "0.2.50",
4
4
  "description": "AI-powered chat panel SDK with programmatic lifecycle control",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",