@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.
@@ -896,28 +896,22 @@ function useUserAuth({
896
896
  }) {
897
897
  const [authState, setAuthState] = React4.useState({ status: "idle" });
898
898
  const lastSessionIdRef = React4.useRef(null);
899
+ const lastEnabledRef = React4.useRef(enabled);
899
900
  const fetchUser = React4.useCallback(async () => {
900
901
  if (!productBackendUrl || !enabled) {
901
- console.log("[useUserAuth] Skipping auth - productBackendUrl:", productBackendUrl, "enabled:", enabled);
902
902
  setAuthState({ status: "idle" });
903
903
  return;
904
904
  }
905
- console.log("[useUserAuth] Starting auth request to product backend...");
906
- console.log("[useUserAuth] Product backend URL:", productBackendUrl);
907
- console.log("[useUserAuth] Full request URL:", `${productBackendUrl}/users/me`);
908
905
  setAuthState({ status: "loading" });
909
906
  try {
910
907
  const response = await fetch(`${productBackendUrl}/users/me`, {
911
908
  method: "GET",
912
909
  credentials: "include",
913
- // Include cookies for authentication
914
910
  headers: {
915
911
  "Accept": "application/json"
916
912
  }
917
913
  });
918
- console.log("[useUserAuth] Response received - status:", response.status, "ok:", response.ok);
919
914
  if (!response.ok) {
920
- console.log("[useUserAuth] Auth request failed with status:", response.status);
921
915
  if (response.status === 401) {
922
916
  throw new Error("Please log in to use the chat assistant.");
923
917
  }
@@ -927,27 +921,36 @@ function useUserAuth({
927
921
  throw new Error(`Authentication failed (${response.status})`);
928
922
  }
929
923
  const user = await response.json();
930
- console.log("[useUserAuth] Auth SUCCESS - parsed user data:");
931
- console.log("[useUserAuth] id:", user.id);
932
- console.log("[useUserAuth] email:", user.email);
933
- console.log("[useUserAuth] name:", user.name);
934
- console.log("[useUserAuth] role:", user.role);
935
- console.log("[useUserAuth] isInternal:", user.isInternal);
936
- console.log("[useUserAuth] agreementsSigned:", user.agreementsSigned);
937
- console.log("[useUserAuth] lastLoginTime:", user.lastLoginTime);
938
924
  setAuthState({ status: "authenticated", user });
939
925
  } catch (error) {
940
- console.log("[useUserAuth] Auth ERROR:", error);
926
+ if (error instanceof Error) {
927
+ const errorMessage = error.message.toLowerCase();
928
+ const isNetworkError = error instanceof TypeError || errorMessage.includes("failed to fetch") || errorMessage.includes("network");
929
+ const is404Error = errorMessage.includes("404");
930
+ if (isNetworkError || is404Error) {
931
+ console.warn("[useUserAuth] Auth endpoint unavailable, falling back to unauthenticated mode:", error.message);
932
+ setAuthState({ status: "idle" });
933
+ return;
934
+ }
935
+ }
941
936
  const message = error instanceof Error ? error.message : "Unable to verify your identity. Please try again.";
942
937
  setAuthState({ status: "error", error: message });
943
938
  }
944
939
  }, [productBackendUrl, enabled]);
945
940
  React4.useEffect(() => {
946
- if (sessionId !== lastSessionIdRef.current) {
941
+ const sessionChanged = sessionId !== lastSessionIdRef.current;
942
+ const enabledChanged = enabled !== lastEnabledRef.current;
943
+ const becameEnabled = enabled && !lastEnabledRef.current;
944
+ if (sessionChanged) {
947
945
  lastSessionIdRef.current = sessionId;
946
+ }
947
+ if (enabledChanged) {
948
+ lastEnabledRef.current = enabled;
949
+ }
950
+ if (sessionChanged || becameEnabled) {
948
951
  fetchUser();
949
952
  }
950
- }, [sessionId, fetchUser]);
953
+ }, [sessionId, enabled, fetchUser]);
951
954
  const retry = React4.useCallback(() => {
952
955
  fetchUser();
953
956
  }, [fetchUser]);
@@ -964,13 +967,11 @@ function useOrgConfig({ agentUrl, orgId }) {
964
967
  });
965
968
  React5.useEffect(() => {
966
969
  if (!agentUrl || !orgId) {
967
- console.log("[useOrgConfig] Skipping - missing agentUrl or orgId", { agentUrl, orgId });
968
970
  return;
969
971
  }
970
972
  const fetchConfig = async () => {
971
973
  setState({ status: "loading", config: null, error: null });
972
974
  const url = `${agentUrl}/org/${orgId}/config`;
973
- console.log("[useOrgConfig] Fetching org config from:", url);
974
975
  try {
975
976
  const response = await fetch(url, {
976
977
  method: "GET",
@@ -982,7 +983,6 @@ function useOrgConfig({ agentUrl, orgId }) {
982
983
  throw new Error(`Failed to fetch org config (${response.status})`);
983
984
  }
984
985
  const config = await response.json();
985
- console.log("[useOrgConfig] Received config:", config);
986
986
  setState({ status: "success", config, error: null });
987
987
  } catch (error) {
988
988
  const message = error instanceof Error ? error.message : "Failed to fetch org config";
@@ -1016,8 +1016,7 @@ function useFrontendToolExecutor({
1016
1016
  }
1017
1017
  }, [agentUrl]);
1018
1018
  const executeToolRequest = useCallback3(async (toolRequest) => {
1019
- const { call_id, tool_name, arguments: args, endpoint, method, path_params } = toolRequest;
1020
- console.log("[FrontendToolExecutor] Executing tool:", tool_name, "with args:", args);
1019
+ const { call_id, arguments: args, endpoint, method, path_params } = toolRequest;
1021
1020
  try {
1022
1021
  let url = endpoint;
1023
1022
  for (const param of path_params) {
@@ -1033,7 +1032,6 @@ function useFrontendToolExecutor({
1033
1032
  }
1034
1033
  const queryString = queryParams.toString();
1035
1034
  const fullUrl = `${productBackendUrl}${url}${queryString ? "?" + queryString : ""}`;
1036
- console.log("[FrontendToolExecutor] Fetching:", fullUrl);
1037
1035
  const response = await fetch(fullUrl, {
1038
1036
  method,
1039
1037
  credentials: "include",
@@ -1045,7 +1043,6 @@ function useFrontendToolExecutor({
1045
1043
  let result;
1046
1044
  if (response.ok) {
1047
1045
  result = await response.json();
1048
- console.log("[FrontendToolExecutor] Tool result:", result);
1049
1046
  } else {
1050
1047
  const errorText = await response.text();
1051
1048
  throw new Error(`HTTP ${response.status}: ${errorText}`);
@@ -1097,7 +1094,6 @@ function TypingIndicator({ className = "" }) {
1097
1094
 
1098
1095
  // src/ChatPanel.tsx
1099
1096
  import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1100
- var CHAT_PANEL_VERSION = true ? "0.2.49" : "dev";
1101
1097
  var DEFAULT_AGENT_URL = "http://localhost:5002";
1102
1098
  var PANEL_WIDTH = 400;
1103
1099
  var PANEL_HEIGHT = 600;
@@ -1561,7 +1557,8 @@ function ChatPanel({
1561
1557
  supabaseAnonKey,
1562
1558
  initialCorner = "bottom-left",
1563
1559
  onCornerChange,
1564
- productBackendUrl
1560
+ productBackendUrl,
1561
+ getAuthHeaders
1565
1562
  } = {}) {
1566
1563
  const [messages, setMessages] = React6.useState(initialMessages);
1567
1564
  const [input, setInput] = React6.useState("");
@@ -1583,6 +1580,8 @@ function ChatPanel({
1583
1580
  const [sessionUser, setSessionUser] = React6.useState(null);
1584
1581
  const orgConfigState = useOrgConfig({ agentUrl, orgId: orgId || "" });
1585
1582
  const effectiveProductBackendUrl = orgConfigState.config?.productBackendUrl || productBackendUrl;
1583
+ const effectiveSupabaseUrl = orgConfigState.config?.supabaseUrl || supabaseUrl;
1584
+ const effectiveSupabaseAnonKey = orgConfigState.config?.supabaseAnonKey || supabaseAnonKey;
1586
1585
  const { authState, retry: retryAuth } = useUserAuth({
1587
1586
  productBackendUrl: effectiveProductBackendUrl,
1588
1587
  sessionId,
@@ -1594,37 +1593,6 @@ function ChatPanel({
1594
1593
  agentUrl,
1595
1594
  sessionId
1596
1595
  });
1597
- React6.useEffect(() => {
1598
- if (!effectiveProductBackendUrl || orgConfigState.status !== "success") {
1599
- return;
1600
- }
1601
- const testProductBackendEndpoint = async () => {
1602
- const url = `${effectiveProductBackendUrl}/getDocument/snowkite/categories/`;
1603
- console.log("[KiteChat TEST] Testing product backend connectivity...");
1604
- console.log("[KiteChat TEST] URL:", url);
1605
- try {
1606
- const response = await fetch(url, {
1607
- method: "GET",
1608
- // Note: not using credentials: 'include' to avoid CORS issues with wildcard
1609
- headers: {
1610
- "Accept": "application/json"
1611
- }
1612
- });
1613
- console.log("[KiteChat TEST] Response status:", response.status);
1614
- console.log("[KiteChat TEST] Response ok:", response.ok);
1615
- if (response.ok) {
1616
- const data = await response.json();
1617
- console.log("[KiteChat TEST] SUCCESS - product backend reachable, data:", data);
1618
- } else {
1619
- const errorText = await response.text();
1620
- console.log("[KiteChat TEST] FAILED - status:", response.status, "body:", errorText);
1621
- }
1622
- } catch (error) {
1623
- console.error("[KiteChat TEST] ERROR:", error);
1624
- }
1625
- };
1626
- testProductBackendEndpoint();
1627
- }, [effectiveProductBackendUrl, orgConfigState.status]);
1628
1596
  const effectiveUser = React6.useMemo(() => {
1629
1597
  if (sessionUser) {
1630
1598
  return sessionUser;
@@ -1655,7 +1623,6 @@ function ChatPanel({
1655
1623
  userRole: authState.user.role,
1656
1624
  isInternal: authState.user.isInternal
1657
1625
  });
1658
- console.log("[ChatPanel] Session user captured:", authState.user.id);
1659
1626
  }
1660
1627
  }, [authState, sessionUser]);
1661
1628
  const isWaitingForAuth = React6.useMemo(() => {
@@ -1668,26 +1635,18 @@ function ChatPanel({
1668
1635
  const supabaseRef = React6.useRef(null);
1669
1636
  const typingChannelRef = React6.useRef(null);
1670
1637
  const typingTimeoutRef = React6.useRef(null);
1671
- React6.useEffect(() => {
1672
- console.log(`[KiteChat] Chat Panel v${CHAT_PANEL_VERSION} loaded`);
1673
- }, []);
1674
1638
  const resetSession = React6.useCallback(() => {
1675
- console.log("[KiteChat] resetSession called", { isEscalated, hasSupabase: !!supabaseRef.current, sessionId });
1676
1639
  if (isEscalated && supabaseRef.current && sessionId) {
1677
- console.log("[KiteChat] Updating customer_status to disconnected for session:", sessionId);
1678
1640
  supabaseRef.current.from("escalations").update({
1679
1641
  customer_status: "disconnected",
1680
1642
  customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1681
1643
  }).eq("session_id", sessionId).then(
1682
- (result) => {
1683
- console.log("[KiteChat] Disconnect update result:", result);
1644
+ () => {
1684
1645
  },
1685
1646
  (err) => {
1686
1647
  console.error("[KiteChat] Disconnect update failed:", err);
1687
1648
  }
1688
1649
  );
1689
- } else {
1690
- console.log("[KiteChat] Skipping disconnect update - conditions not met");
1691
1650
  }
1692
1651
  setSessionUser(null);
1693
1652
  setSessionId(crypto.randomUUID());
@@ -1703,22 +1662,19 @@ function ChatPanel({
1703
1662
  }
1704
1663
  }, [isEscalated, sessionId]);
1705
1664
  React6.useEffect(() => {
1706
- if (supabaseUrl && supabaseAnonKey && !supabaseRef.current) {
1707
- supabaseRef.current = createClient(supabaseUrl, supabaseAnonKey);
1665
+ if (effectiveSupabaseUrl && effectiveSupabaseAnonKey && !supabaseRef.current) {
1666
+ supabaseRef.current = createClient(effectiveSupabaseUrl, effectiveSupabaseAnonKey);
1708
1667
  }
1709
- }, [supabaseUrl, supabaseAnonKey]);
1668
+ }, [effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
1710
1669
  React6.useEffect(() => {
1711
1670
  if (!isEscalated || !sessionId || !supabaseRef.current) {
1712
1671
  return;
1713
1672
  }
1714
1673
  const channelName = `typing:${sessionId}`;
1715
1674
  const channel = supabaseRef.current.channel(channelName);
1716
- console.log(`[KiteChat] Subscribing to typing channel: ${channelName}`);
1717
1675
  channel.on("broadcast", { event: "typing" }, (payload) => {
1718
- console.log("[KiteChat] Received typing broadcast:", payload);
1719
1676
  const { sender, isTyping } = payload.payload;
1720
1677
  if (sender === "agent") {
1721
- console.log(`[KiteChat] Agent typing: ${isTyping}`);
1722
1678
  setAgentIsTyping(isTyping);
1723
1679
  if (isTyping) {
1724
1680
  if (typingTimeoutRef.current) {
@@ -1730,10 +1686,11 @@ function ChatPanel({
1730
1686
  }
1731
1687
  }
1732
1688
  }).subscribe((status) => {
1733
- console.log(`[KiteChat] Typing channel status: ${status}`);
1734
1689
  if (status === "SUBSCRIBED") {
1735
1690
  typingChannelRef.current = channel;
1736
- console.log("[KiteChat] Typing channel ready");
1691
+ console.log("[KiteChat] Typing channel subscribed successfully");
1692
+ } else if (status === "CHANNEL_ERROR") {
1693
+ console.error("[KiteChat] Typing channel subscription failed");
1737
1694
  }
1738
1695
  });
1739
1696
  return () => {
@@ -1744,6 +1701,20 @@ function ChatPanel({
1744
1701
  }
1745
1702
  };
1746
1703
  }, [isEscalated, sessionId]);
1704
+ React6.useEffect(() => {
1705
+ if (!isOpen && isEscalated && supabaseRef.current && sessionId) {
1706
+ console.log("[KiteChat] Panel closed during live chat, marking disconnected");
1707
+ supabaseRef.current.from("escalations").update({
1708
+ customer_status: "disconnected",
1709
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1710
+ }).eq("session_id", sessionId).then(
1711
+ () => console.log("[KiteChat] Successfully marked disconnected on panel close"),
1712
+ (err) => {
1713
+ console.error("[KiteChat] Failed to mark disconnected on panel close:", err);
1714
+ }
1715
+ );
1716
+ }
1717
+ }, [isOpen, isEscalated, sessionId]);
1747
1718
  const heartbeatIntervalRef = React6.useRef(null);
1748
1719
  const updateCustomerStatus = React6.useCallback(async (status) => {
1749
1720
  if (!supabaseRef.current || !sessionId) return;
@@ -1762,24 +1733,50 @@ function ChatPanel({
1762
1733
  }
1763
1734
  const currentSessionId = sessionId;
1764
1735
  const supabase = supabaseRef.current;
1765
- updateCustomerStatus("active");
1736
+ const sbUrl = effectiveSupabaseUrl;
1737
+ const sbKey = effectiveSupabaseAnonKey;
1738
+ const markActive = () => {
1739
+ supabase.from("escalations").update({
1740
+ customer_status: "active",
1741
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1742
+ }).eq("session_id", currentSessionId).then(
1743
+ () => {
1744
+ },
1745
+ (err) => console.error("[KiteChat] Failed to update customer status:", err)
1746
+ );
1747
+ };
1748
+ const markDisconnectedWithKeepalive = () => {
1749
+ if (!sbUrl || !sbKey) return;
1750
+ const url = `${sbUrl}/rest/v1/escalations?session_id=eq.${currentSessionId}`;
1751
+ fetch(url, {
1752
+ method: "PATCH",
1753
+ headers: {
1754
+ "Content-Type": "application/json",
1755
+ "apikey": sbKey,
1756
+ "Authorization": `Bearer ${sbKey}`,
1757
+ "Prefer": "return=minimal"
1758
+ },
1759
+ body: JSON.stringify({
1760
+ customer_status: "disconnected",
1761
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1762
+ }),
1763
+ keepalive: true
1764
+ }).catch(() => {
1765
+ });
1766
+ };
1767
+ console.log("[KiteChat] Starting presence heartbeat for live chat");
1768
+ markActive();
1766
1769
  heartbeatIntervalRef.current = window.setInterval(() => {
1767
- updateCustomerStatus("active");
1770
+ markActive();
1768
1771
  }, 6e4);
1769
1772
  const handleBeforeUnload = () => {
1770
- supabase.from("escalations").update({
1771
- customer_status: "disconnected",
1772
- customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1773
- }).eq("session_id", currentSessionId);
1773
+ markDisconnectedWithKeepalive();
1774
1774
  };
1775
1775
  const handleVisibilityChange = () => {
1776
1776
  if (document.visibilityState === "hidden") {
1777
- supabase.from("escalations").update({
1778
- customer_status: "disconnected",
1779
- customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1780
- }).eq("session_id", currentSessionId);
1777
+ markDisconnectedWithKeepalive();
1781
1778
  } else if (document.visibilityState === "visible") {
1782
- updateCustomerStatus("active");
1779
+ markActive();
1783
1780
  }
1784
1781
  };
1785
1782
  window.addEventListener("beforeunload", handleBeforeUnload);
@@ -1787,13 +1784,12 @@ function ChatPanel({
1787
1784
  return () => {
1788
1785
  window.removeEventListener("beforeunload", handleBeforeUnload);
1789
1786
  document.removeEventListener("visibilitychange", handleVisibilityChange);
1787
+ console.log("[KiteChat] Escalation ended, marking disconnected");
1790
1788
  supabase.from("escalations").update({
1791
1789
  customer_status: "disconnected",
1792
1790
  customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1793
1791
  }).eq("session_id", currentSessionId).then(
1794
- () => {
1795
- console.log("[KiteChat] Marked customer as disconnected");
1796
- },
1792
+ () => console.log("[KiteChat] Successfully marked disconnected on escalation end"),
1797
1793
  (err) => {
1798
1794
  console.error("[KiteChat] Failed to mark disconnected:", err);
1799
1795
  }
@@ -1803,17 +1799,14 @@ function ChatPanel({
1803
1799
  heartbeatIntervalRef.current = null;
1804
1800
  }
1805
1801
  };
1806
- }, [isEscalated, sessionId, updateCustomerStatus]);
1802
+ }, [isEscalated, sessionId, effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
1807
1803
  const sendTypingIndicator = React6.useCallback((isTyping) => {
1808
- if (!typingChannelRef.current) {
1809
- console.log("[KiteChat] Cannot send typing - channel not ready");
1810
- return;
1811
- }
1812
- if (!isEscalated) {
1813
- console.log("[KiteChat] Cannot send typing - not escalated");
1804
+ if (!typingChannelRef.current || !isEscalated) {
1805
+ if (isTyping) {
1806
+ console.warn("[KiteChat] Typing channel not ready, cannot send typing indicator");
1807
+ }
1814
1808
  return;
1815
1809
  }
1816
- console.log(`[KiteChat] Sending typing indicator: ${isTyping}`);
1817
1810
  typingChannelRef.current.send({
1818
1811
  type: "broadcast",
1819
1812
  event: "typing",
@@ -1822,16 +1815,23 @@ function ChatPanel({
1822
1815
  }, [isEscalated]);
1823
1816
  const userTypingTimeoutRef = React6.useRef(null);
1824
1817
  const handleTypingStart = React6.useCallback(() => {
1825
- if (!isEscalated || !supabaseRef.current) return;
1818
+ if (!isEscalated || !supabaseRef.current || !sessionId) return;
1826
1819
  sendTypingIndicator(true);
1827
- updateCustomerStatus("active");
1820
+ supabaseRef.current.from("escalations").update({
1821
+ customer_status: "active",
1822
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
1823
+ }).eq("session_id", sessionId).then(
1824
+ () => {
1825
+ },
1826
+ (err) => console.error("[KiteChat] Failed to update presence:", err)
1827
+ );
1828
1828
  if (userTypingTimeoutRef.current) {
1829
1829
  window.clearTimeout(userTypingTimeoutRef.current);
1830
1830
  }
1831
1831
  userTypingTimeoutRef.current = window.setTimeout(() => {
1832
1832
  sendTypingIndicator(false);
1833
1833
  }, 1500);
1834
- }, [isEscalated, sendTypingIndicator, updateCustomerStatus]);
1834
+ }, [isEscalated, sendTypingIndicator, sessionId]);
1835
1835
  const streamIntervals = React6.useRef({});
1836
1836
  const isEmpty = messages.length === 0;
1837
1837
  const [phase, setPhase] = React6.useState("idle");
@@ -1866,12 +1866,6 @@ function ChatPanel({
1866
1866
  const latestBulkSummaryNavigationRef = React6.useRef(null);
1867
1867
  const [guideComplete, setGuideComplete] = React6.useState(false);
1868
1868
  React6.useEffect(() => {
1869
- window.resetIntegrationNotification = () => {
1870
- localStorage.removeItem("gmailNotificationSeen");
1871
- console.log(
1872
- "Integration notification reset! Click the Integrations tab to see it again."
1873
- );
1874
- };
1875
1869
  const handleIntegrationTabClick = () => {
1876
1870
  const hasSeenNotification = localStorage.getItem("gmailNotificationSeen");
1877
1871
  if (!hasSeenNotification) {
@@ -2013,17 +2007,7 @@ function ChatPanel({
2013
2007
  return;
2014
2008
  }
2015
2009
  const currentBulkNav = latestBulkSummaryNavigationRef.current;
2016
- console.log(
2017
- "[DEBUG] Keyboard handler - latestBulkSummaryNavigation:",
2018
- currentBulkNav,
2019
- "onNavigate:",
2020
- !!onNavigate
2021
- );
2022
2010
  if (currentBulkNav && onNavigate) {
2023
- console.log(
2024
- "[DEBUG] Navigating via keyboard to:",
2025
- currentBulkNav.page
2026
- );
2027
2011
  e.preventDefault();
2028
2012
  e.stopPropagation();
2029
2013
  onNavigate(currentBulkNav.page, currentBulkNav.subtab);
@@ -2069,7 +2053,6 @@ function ChatPanel({
2069
2053
  const messageId = data.message_id;
2070
2054
  const isDuplicate = messageId ? prev.some((m) => m.serverMessageId === messageId) : prev.slice(-5).some((m) => m.content === content);
2071
2055
  if (isDuplicate) {
2072
- console.debug("[KiteChat] Skipping duplicate agent message:", messageId || content.slice(0, 30));
2073
2056
  return prev;
2074
2057
  }
2075
2058
  return [...prev, {
@@ -2092,7 +2075,6 @@ function ChatPanel({
2092
2075
  console.error("[KiteChat] Escalation WebSocket error:", err);
2093
2076
  };
2094
2077
  ws.onclose = () => {
2095
- console.log("[KiteChat] Escalation WebSocket closed");
2096
2078
  };
2097
2079
  escalationWsRef.current = ws;
2098
2080
  }, [agentUrl]);
@@ -2106,13 +2088,22 @@ function ChatPanel({
2106
2088
  type: "user_message",
2107
2089
  content
2108
2090
  }));
2109
- updateCustomerStatus("active");
2091
+ if (supabaseRef.current && sessionId) {
2092
+ supabaseRef.current.from("escalations").update({
2093
+ customer_status: "active",
2094
+ customer_last_seen: (/* @__PURE__ */ new Date()).toISOString()
2095
+ }).eq("session_id", sessionId).then(
2096
+ () => {
2097
+ },
2098
+ (err) => console.error("[KiteChat] Failed to update presence:", err)
2099
+ );
2100
+ }
2110
2101
  return true;
2111
2102
  } catch (err) {
2112
2103
  console.error("[KiteChat] Failed to send escalated message:", err);
2113
2104
  return false;
2114
2105
  }
2115
- }, [updateCustomerStatus]);
2106
+ }, [sessionId]);
2116
2107
  React6.useEffect(() => {
2117
2108
  return () => {
2118
2109
  if (escalationWsRef.current) {
@@ -2386,14 +2377,6 @@ function ChatPanel({
2386
2377
  try {
2387
2378
  const controller = new AbortController();
2388
2379
  const timeoutId = setTimeout(() => controller.abort(), 6e4);
2389
- console.log("[ChatPanel] Sending chat request to agent backend...");
2390
- console.log("[ChatPanel] Agent URL:", agentUrl);
2391
- console.log("[ChatPanel] User data being sent:");
2392
- console.log("[ChatPanel] user_id:", effectiveUser.userId);
2393
- console.log("[ChatPanel] user_name:", effectiveUser.userName);
2394
- console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
2395
- console.log("[ChatPanel] org_id:", orgId);
2396
- console.log("[ChatPanel] authState.status:", authState.status);
2397
2380
  const response = await fetch(`${agentUrl}/chat/stream`, {
2398
2381
  method: "POST",
2399
2382
  headers: {
@@ -2610,7 +2593,6 @@ function ChatPanel({
2610
2593
  setMessages((prev) => [...prev, escalationMessage]);
2611
2594
  } else if (eventType === "tool_request") {
2612
2595
  const toolRequest = data;
2613
- console.log("[KiteChat] Received tool_request:", toolRequest);
2614
2596
  executeToolRequest(toolRequest).catch((err) => {
2615
2597
  console.error("[KiteChat] Tool execution failed:", err);
2616
2598
  });
@@ -2928,11 +2910,6 @@ ${userText}`
2928
2910
  }
2929
2911
  });
2930
2912
  } else if (eventType === "summary") {
2931
- console.log("[DEBUG] Received summary event - data:", data);
2932
- console.log(
2933
- "[DEBUG] navigationPage from backend:",
2934
- data.navigationPage
2935
- );
2936
2913
  setPhase("idle");
2937
2914
  setProgressSteps([]);
2938
2915
  setPendingBulkSession(null);
@@ -2952,7 +2929,6 @@ ${userText}`
2952
2929
  navigationPage: data.navigationPage
2953
2930
  }
2954
2931
  };
2955
- console.log("[DEBUG] Creating bulkSummary message:", newMsg);
2956
2932
  return [...filtered, newMsg];
2957
2933
  });
2958
2934
  setTimeout(() => {
@@ -4523,28 +4499,11 @@ ${userText}`
4523
4499
  onClick: (e) => {
4524
4500
  e.preventDefault();
4525
4501
  e.stopPropagation();
4526
- console.log(
4527
- "[DEBUG] Button clicked - navigationPage:",
4528
- navigationPage,
4529
- "onNavigate:",
4530
- !!onNavigate
4531
- );
4532
4502
  if (onNavigate && navigationPage.page) {
4533
- console.log(
4534
- "[DEBUG] Calling onNavigate with page:",
4535
- navigationPage.page
4536
- );
4537
4503
  onNavigate(
4538
4504
  navigationPage.page,
4539
4505
  navigationPage.subtab
4540
4506
  );
4541
- } else {
4542
- console.log(
4543
- "[DEBUG] Condition failed - onNavigate:",
4544
- !!onNavigate,
4545
- "navigationPage.page:",
4546
- navigationPage.page
4547
- );
4548
4507
  }
4549
4508
  },
4550
4509
  className: "flex items-center gap-2 text-xs text-gray-500 hover:text-gray-700 transition-colors group cursor-pointer",
@@ -4824,7 +4783,8 @@ function ChatPanelWithToggle({
4824
4783
  supabaseAnonKey,
4825
4784
  initialCorner,
4826
4785
  onCornerChange,
4827
- productBackendUrl
4786
+ productBackendUrl,
4787
+ getAuthHeaders
4828
4788
  }) {
4829
4789
  const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
4830
4790
  const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
@@ -4854,7 +4814,8 @@ function ChatPanelWithToggle({
4854
4814
  supabaseAnonKey,
4855
4815
  initialCorner,
4856
4816
  onCornerChange,
4857
- productBackendUrl
4817
+ productBackendUrl,
4818
+ getAuthHeaders
4858
4819
  }
4859
4820
  );
4860
4821
  }
@@ -4928,7 +4889,8 @@ function KiteChatWrapper({
4928
4889
  userEmail: config.userEmail,
4929
4890
  supabaseUrl: config.supabaseUrl,
4930
4891
  supabaseAnonKey: config.supabaseAnonKey,
4931
- productBackendUrl: config.productBackendUrl
4892
+ productBackendUrl: config.productBackendUrl,
4893
+ getAuthHeaders: config.getAuthHeaders
4932
4894
  }
4933
4895
  );
4934
4896
  }
@@ -4971,7 +4933,6 @@ function createKiteChat(config) {
4971
4933
  }
4972
4934
  )
4973
4935
  );
4974
- console.log("[KiteChat] Mounted");
4975
4936
  },
4976
4937
  unmount() {
4977
4938
  if (!root) {
@@ -4983,7 +4944,6 @@ function createKiteChat(config) {
4983
4944
  containerElement = null;
4984
4945
  configUpdater = null;
4985
4946
  stateUpdaters = null;
4986
- console.log("[KiteChat] Unmounted");
4987
4947
  },
4988
4948
  open() {
4989
4949
  stateUpdaters?.setIsOpen(true);
@@ -118,8 +118,10 @@ interface ChatPanelProps {
118
118
  onCornerChange?: (corner: PanelCorner) => void;
119
119
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
120
120
  productBackendUrl?: string;
121
+ /** Optional async function to provide authentication headers for API requests */
122
+ getAuthHeaders?: () => Promise<Record<string, string>>;
121
123
  }
122
- declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
124
+ declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, getAuthHeaders, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
123
125
  /**
124
126
  * PanelToggle - An arrow button on the right edge that toggles the side panel
125
127
  * Shows left arrow when closed (click to open), right arrow when open (click to close)
@@ -182,8 +184,10 @@ interface ChatPanelWithToggleProps {
182
184
  onCornerChange?: (corner: PanelCorner) => void;
183
185
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
184
186
  productBackendUrl?: string;
187
+ /** Optional async function to provide authentication headers for API requests */
188
+ getAuthHeaders?: () => Promise<Record<string, string>>;
185
189
  }
186
- declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
190
+ declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, getAuthHeaders, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
187
191
  /**
188
192
  * @deprecated Use ChatPanelWithToggle instead for the new side panel UX
189
193
  */
@@ -253,6 +257,8 @@ interface KiteChatConfig {
253
257
  supabaseAnonKey?: string;
254
258
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
255
259
  productBackendUrl?: string;
260
+ /** Optional async function to provide authentication headers for API requests */
261
+ getAuthHeaders?: () => Promise<Record<string, string>>;
256
262
  }
257
263
  /**
258
264
  * Instance returned by createKiteChat with lifecycle control methods.
@@ -118,8 +118,10 @@ interface ChatPanelProps {
118
118
  onCornerChange?: (corner: PanelCorner) => void;
119
119
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
120
120
  productBackendUrl?: string;
121
+ /** Optional async function to provide authentication headers for API requests */
122
+ getAuthHeaders?: () => Promise<Record<string, string>>;
121
123
  }
122
- declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
124
+ declare function ChatPanel({ isOpen, onClose, onOpen, onBack, onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions: startingQuestionsProp, startingQuestionsEndpoint, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, getAuthHeaders, }?: ChatPanelProps): react_jsx_runtime.JSX.Element;
123
125
  /**
124
126
  * PanelToggle - An arrow button on the right edge that toggles the side panel
125
127
  * Shows left arrow when closed (click to open), right arrow when open (click to close)
@@ -182,8 +184,10 @@ interface ChatPanelWithToggleProps {
182
184
  onCornerChange?: (corner: PanelCorner) => void;
183
185
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
184
186
  productBackendUrl?: string;
187
+ /** Optional async function to provide authentication headers for API requests */
188
+ getAuthHeaders?: () => Promise<Record<string, string>>;
185
189
  }
186
- declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
190
+ declare function ChatPanelWithToggle({ onNavigate, onActionComplete, currentPage, agentUrl, startingQuestions, startingQuestionsEndpoint, defaultOpen, isOpen: controlledIsOpen, onOpenChange, userId, orgId, userName, userEmail, supabaseUrl, supabaseAnonKey, initialCorner, onCornerChange, productBackendUrl, getAuthHeaders, }: ChatPanelWithToggleProps): react_jsx_runtime.JSX.Element;
187
191
  /**
188
192
  * @deprecated Use ChatPanelWithToggle instead for the new side panel UX
189
193
  */
@@ -253,6 +257,8 @@ interface KiteChatConfig {
253
257
  supabaseAnonKey?: string;
254
258
  /** Product backend URL for user authentication (e.g., https://dev.api.rocketalumnisolutions.com) */
255
259
  productBackendUrl?: string;
260
+ /** Optional async function to provide authentication headers for API requests */
261
+ getAuthHeaders?: () => Promise<Record<string, string>>;
256
262
  }
257
263
  /**
258
264
  * Instance returned by createKiteChat with lifecycle control methods.