@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 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
- console.log("[useUserAuth] Auth ERROR:", error);
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
- if (sessionId !== lastSessionIdRef.current) {
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, tool_name, arguments: args, endpoint, method, path_params } = toolRequest;
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
- (result) => {
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 (supabaseUrl && supabaseAnonKey && !supabaseRef.current) {
1706
- supabaseRef.current = (0, import_supabase_js.createClient)(supabaseUrl, supabaseAnonKey);
1664
+ if (effectiveSupabaseUrl && effectiveSupabaseAnonKey && !supabaseRef.current) {
1665
+ supabaseRef.current = (0, import_supabase_js.createClient)(effectiveSupabaseUrl, effectiveSupabaseAnonKey);
1707
1666
  }
1708
- }, [supabaseUrl, supabaseAnonKey]);
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 ready");
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
- updateCustomerStatus("active");
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
- updateCustomerStatus("active");
1769
+ markActive();
1767
1770
  }, 6e4);
1768
1771
  const handleBeforeUnload = () => {
1769
- supabase.from("escalations").update({
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
- supabase.from("escalations").update({
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
- updateCustomerStatus("active");
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, updateCustomerStatus]);
1801
+ }, [isEscalated, sessionId, effectiveSupabaseUrl, effectiveSupabaseAnonKey]);
1806
1802
  const sendTypingIndicator = React6.useCallback((isTyping) => {
1807
- if (!typingChannelRef.current) {
1808
- console.log("[KiteChat] Cannot send typing - channel not ready");
1809
- return;
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
- updateCustomerStatus("active");
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, updateCustomerStatus]);
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
- updateCustomerStatus("active");
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
- }, [updateCustomerStatus]);
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
@@ -1,4 +1,4 @@
1
- import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-e6BnJS6T.cjs';
1
+ import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-DeQKgFyx.cjs';
2
2
  import 'react/jsx-runtime';
3
3
 
4
4
  /**
package/dist/auto.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-e6BnJS6T.js';
1
+ import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-DeQKgFyx.js';
2
2
  import 'react/jsx-runtime';
3
3
 
4
4
  /**
package/dist/auto.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createKiteChat
3
- } from "./chunk-YZXB3LLU.js";
3
+ } from "./chunk-VBCGW333.js";
4
4
 
5
5
  // src/auto.ts
6
6
  function mountKiteChat(config) {