@flamingo-stack/openframe-frontend-core 0.0.212 → 0.0.213

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.
Files changed (91) hide show
  1. package/dist/{chunk-ZFBLC5GV.cjs → chunk-35XIT2CF.cjs} +17 -17
  2. package/dist/{chunk-ZFBLC5GV.cjs.map → chunk-35XIT2CF.cjs.map} +1 -1
  3. package/dist/{chunk-QKFBZLIR.js → chunk-3JWIJJ44.js} +2 -2
  4. package/dist/chunk-CZR7ARBA.js +698 -0
  5. package/dist/chunk-CZR7ARBA.js.map +1 -0
  6. package/dist/{chunk-UYQOPC57.js → chunk-HICZPTRR.js} +4 -351
  7. package/dist/chunk-HICZPTRR.js.map +1 -0
  8. package/dist/{chunk-5BNWGK6D.js → chunk-IK2X5YJU.js} +3 -3
  9. package/dist/{chunk-VTUIMMHO.cjs → chunk-OTKJASSX.cjs} +26 -26
  10. package/dist/{chunk-VTUIMMHO.cjs.map → chunk-OTKJASSX.cjs.map} +1 -1
  11. package/dist/chunk-OZ3GH6OQ.cjs +698 -0
  12. package/dist/chunk-OZ3GH6OQ.cjs.map +1 -0
  13. package/dist/{chunk-EH3RWVF3.cjs → chunk-WT5JV2GS.cjs} +8 -355
  14. package/dist/chunk-WT5JV2GS.cjs.map +1 -0
  15. package/dist/{chunk-WI76ZUBE.cjs → chunk-ZDF6F7ED.cjs} +544 -678
  16. package/dist/chunk-ZDF6F7ED.cjs.map +1 -0
  17. package/dist/{chunk-3E5ANY55.js → chunk-ZTJVRSN5.js} +409 -543
  18. package/dist/{chunk-3E5ANY55.js.map → chunk-ZTJVRSN5.js.map} +1 -1
  19. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts.map +1 -1
  20. package/dist/components/chat/hooks/use-nats-dialog-subscription.d.ts +0 -9
  21. package/dist/components/chat/hooks/use-nats-dialog-subscription.d.ts.map +1 -1
  22. package/dist/components/chat/index.cjs +5 -4
  23. package/dist/components/chat/index.cjs.map +1 -1
  24. package/dist/components/chat/index.js +4 -3
  25. package/dist/components/contact/index.cjs +6 -5
  26. package/dist/components/contact/index.cjs.map +1 -1
  27. package/dist/components/contact/index.js +5 -4
  28. package/dist/components/features/index.cjs +5 -4
  29. package/dist/components/features/index.cjs.map +1 -1
  30. package/dist/components/features/index.js +4 -3
  31. package/dist/components/features/notifications/index.d.ts +2 -2
  32. package/dist/components/features/notifications/index.d.ts.map +1 -1
  33. package/dist/components/features/notifications/notifications-context.d.ts +16 -1
  34. package/dist/components/features/notifications/notifications-context.d.ts.map +1 -1
  35. package/dist/components/features/notifications/types.d.ts +4 -0
  36. package/dist/components/features/notifications/types.d.ts.map +1 -1
  37. package/dist/components/index.cjs +55 -54
  38. package/dist/components/index.cjs.map +1 -1
  39. package/dist/components/index.js +7 -6
  40. package/dist/components/index.js.map +1 -1
  41. package/dist/components/navigation/app-header.d.ts.map +1 -1
  42. package/dist/components/navigation/index.cjs +5 -4
  43. package/dist/components/navigation/index.cjs.map +1 -1
  44. package/dist/components/navigation/index.js +4 -3
  45. package/dist/components/tickets/index.cjs +66 -65
  46. package/dist/components/tickets/index.cjs.map +1 -1
  47. package/dist/components/tickets/index.js +6 -5
  48. package/dist/components/tickets/index.js.map +1 -1
  49. package/dist/components/ui/index.cjs +5 -4
  50. package/dist/components/ui/index.cjs.map +1 -1
  51. package/dist/components/ui/index.js +4 -3
  52. package/dist/embed-shims/index.cjs +3 -3
  53. package/dist/embed-shims/index.cjs.map +1 -1
  54. package/dist/embed-shims/index.js +4 -4
  55. package/dist/hooks/index.cjs +3 -2
  56. package/dist/hooks/index.cjs.map +1 -1
  57. package/dist/hooks/index.js +2 -1
  58. package/dist/index.cjs +5 -4
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.js +4 -3
  61. package/dist/nats/index.cjs +28 -346
  62. package/dist/nats/index.cjs.map +1 -1
  63. package/dist/nats/index.d.ts +3 -0
  64. package/dist/nats/index.d.ts.map +1 -1
  65. package/dist/nats/index.js +30 -346
  66. package/dist/nats/index.js.map +1 -1
  67. package/dist/nats/nats-provider.d.ts +28 -0
  68. package/dist/nats/nats-provider.d.ts.map +1 -0
  69. package/dist/nats/nats.d.ts +1 -0
  70. package/dist/nats/nats.d.ts.map +1 -1
  71. package/dist/nats/shared-connection.d.ts +73 -0
  72. package/dist/nats/shared-connection.d.ts.map +1 -0
  73. package/dist/nats/use-nats-subscription.d.ts +18 -0
  74. package/dist/nats/use-nats-subscription.d.ts.map +1 -0
  75. package/package.json +1 -1
  76. package/src/components/chat/hooks/use-jetstream-dialog-subscription.ts +60 -207
  77. package/src/components/chat/hooks/use-nats-dialog-subscription.ts +71 -214
  78. package/src/components/features/notifications/index.ts +2 -1
  79. package/src/components/features/notifications/notifications-context.tsx +104 -6
  80. package/src/components/features/notifications/types.ts +5 -0
  81. package/src/components/navigation/app-header.tsx +7 -9
  82. package/src/nats/index.ts +3 -0
  83. package/src/nats/nats-provider.tsx +146 -0
  84. package/src/nats/nats.ts +2 -0
  85. package/src/nats/shared-connection.ts +285 -0
  86. package/src/nats/use-nats-subscription.ts +99 -0
  87. package/dist/chunk-EH3RWVF3.cjs.map +0 -1
  88. package/dist/chunk-UYQOPC57.js.map +0 -1
  89. package/dist/chunk-WI76ZUBE.cjs.map +0 -1
  90. /package/dist/{chunk-QKFBZLIR.js.map → chunk-3JWIJJ44.js.map} +0 -0
  91. /package/dist/{chunk-5BNWGK6D.js.map → chunk-IK2X5YJU.js.map} +0 -0
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import {
3
3
  ToolIcon,
4
- createNatsClient,
5
4
  dotColorByVariant,
6
5
  getSmallPlatformIcon,
7
6
  progressColorByVariant,
@@ -17,7 +16,7 @@ import {
17
16
  useNearViewport,
18
17
  useOnboardingState,
19
18
  useToast
20
- } from "./chunk-UYQOPC57.js";
19
+ } from "./chunk-HICZPTRR.js";
21
20
  import {
22
21
  BashIcon,
23
22
  ClickUpIcon,
@@ -68,7 +67,6 @@ import {
68
67
  Arrow02RightIcon,
69
68
  BellIcon,
70
69
  BellOffIcon,
71
- BellRingingIcon,
72
70
  BookIcon,
73
71
  BracketCurlyIcon,
74
72
  BriefcaseIcon,
@@ -140,6 +138,9 @@ import {
140
138
  import {
141
139
  useRequiredChatRuntime
142
140
  } from "./chunk-ZG2YY5E7.js";
141
+ import {
142
+ next_image_default
143
+ } from "./chunk-LXC6P2EO.js";
143
144
  import {
144
145
  dynamic
145
146
  } from "./chunk-EL5YVPD5.js";
@@ -150,8 +151,10 @@ import {
150
151
  useSearchParams
151
152
  } from "./chunk-PLJLE4A4.js";
152
153
  import {
153
- next_image_default
154
- } from "./chunk-LXC6P2EO.js";
154
+ acquireClient,
155
+ releaseClient,
156
+ startConnectionLifecycle
157
+ } from "./chunk-CZR7ARBA.js";
155
158
  import {
156
159
  Button,
157
160
  Checkbox,
@@ -7440,7 +7443,7 @@ function RoadmapVoteButton({
7440
7443
  init_button();
7441
7444
 
7442
7445
  // src/components/ui/image-gallery-modal.tsx
7443
- import { useState as useState70, useEffect as useEffect49 } from "react";
7446
+ import { useState as useState70, useEffect as useEffect50 } from "react";
7444
7447
 
7445
7448
  // src/components/ui/allowed-domains-input.tsx
7446
7449
  init_cn();
@@ -21971,12 +21974,48 @@ function WaitlistForm({
21971
21974
  import * as React73 from "react";
21972
21975
  import { jsx as jsx182 } from "react/jsx-runtime";
21973
21976
  var NotificationsContext = React73.createContext(null);
21977
+ function mergeNotification(base, incoming) {
21978
+ const out = { ...base };
21979
+ for (const key of Object.keys(incoming)) {
21980
+ const value = incoming[key];
21981
+ if (value !== void 0) out[key] = value;
21982
+ }
21983
+ out.read = (incoming.read ?? false) || (base.read ?? false) || false;
21984
+ out.settled = (incoming.settled ?? false) || (base.settled ?? false) || false;
21985
+ return out;
21986
+ }
21974
21987
  function reducer(state, action) {
21975
21988
  switch (action.type) {
21976
21989
  case "add": {
21977
- const next = [action.notification, ...state.filter((n) => n.id !== action.notification.id)];
21990
+ const existing = state.find((n) => n.id === action.notification.id);
21991
+ if (existing) {
21992
+ const merged = mergeNotification(existing, action.notification);
21993
+ return [merged, ...state.filter((n) => n.id !== action.notification.id)];
21994
+ }
21995
+ const next = [action.notification, ...state];
21978
21996
  return next.length > action.max ? next.slice(0, action.max) : next;
21979
21997
  }
21998
+ case "upsert": {
21999
+ const existing = state.find((n) => n.id === action.notification.id);
22000
+ if (existing) {
22001
+ const merged = mergeNotification(existing, action.notification);
22002
+ return state.map((n) => n.id === action.notification.id ? merged : n);
22003
+ }
22004
+ const next = [action.notification, ...state];
22005
+ return next.length > action.max ? next.slice(0, action.max) : next;
22006
+ }
22007
+ case "set": {
22008
+ const existingById = new Map(state.map((n) => [n.id, n]));
22009
+ return action.notifications.map((incoming) => {
22010
+ const existing = existingById.get(incoming.id);
22011
+ if (!existing) return incoming;
22012
+ return {
22013
+ ...incoming,
22014
+ read: incoming.read || existing.read,
22015
+ settled: incoming.settled || existing.settled
22016
+ };
22017
+ });
22018
+ }
21980
22019
  case "markRead":
21981
22020
  return state.map((n) => n.id === action.id ? { ...n, read: true } : n);
21982
22021
  case "markAllRead":
@@ -22003,11 +22042,16 @@ function NotificationsProvider({
22003
22042
  maxNotifications = 50,
22004
22043
  defaultShowPopups = true,
22005
22044
  onShowPopupsChange,
22006
- onHistoryClick
22045
+ onHistoryClick,
22046
+ actions
22007
22047
  }) {
22008
22048
  const [notifications, dispatch] = React73.useReducer(reducer, initialNotifications);
22009
22049
  const [isOpen, setIsOpen] = React73.useState(false);
22010
22050
  const [showPopups, setShowPopupsState] = React73.useState(defaultShowPopups);
22051
+ const actionsRef = React73.useRef(actions);
22052
+ React73.useEffect(() => {
22053
+ actionsRef.current = actions;
22054
+ }, [actions]);
22011
22055
  const addNotification = React73.useCallback(
22012
22056
  (input) => {
22013
22057
  const id = input.id ?? generateId();
@@ -22015,17 +22059,45 @@ function NotificationsProvider({
22015
22059
  ...input,
22016
22060
  id,
22017
22061
  createdAt: input.createdAt ?? Date.now(),
22018
- read: false
22062
+ read: input.read ?? false
22019
22063
  };
22020
22064
  dispatch({ type: "add", notification, max: maxNotifications });
22021
22065
  return id;
22022
22066
  },
22023
22067
  [maxNotifications]
22024
22068
  );
22025
- const markRead = React73.useCallback((id) => dispatch({ type: "markRead", id }), []);
22026
- const markAllRead = React73.useCallback(() => dispatch({ type: "markAllRead" }), []);
22027
- const markSettled = React73.useCallback((id) => dispatch({ type: "markSettled", id }), []);
22028
- const remove = React73.useCallback((id) => dispatch({ type: "remove", id }), []);
22069
+ const upsertNotification = React73.useCallback(
22070
+ (input) => {
22071
+ const notification = {
22072
+ ...input,
22073
+ id: input.id,
22074
+ createdAt: input.createdAt ?? Date.now(),
22075
+ read: input.read ?? false
22076
+ };
22077
+ dispatch({ type: "upsert", notification, max: maxNotifications });
22078
+ return input.id;
22079
+ },
22080
+ [maxNotifications]
22081
+ );
22082
+ const setNotifications = React73.useCallback((list) => {
22083
+ dispatch({ type: "set", notifications: list });
22084
+ }, []);
22085
+ const markRead = React73.useCallback((id) => {
22086
+ dispatch({ type: "markRead", id });
22087
+ void actionsRef.current?.onMarkRead?.(id);
22088
+ }, []);
22089
+ const markAllRead = React73.useCallback(() => {
22090
+ dispatch({ type: "markAllRead" });
22091
+ void actionsRef.current?.onMarkAllRead?.();
22092
+ }, []);
22093
+ const markSettled = React73.useCallback((id) => {
22094
+ dispatch({ type: "markSettled", id });
22095
+ void actionsRef.current?.onMarkSettled?.(id);
22096
+ }, []);
22097
+ const remove = React73.useCallback((id) => {
22098
+ dispatch({ type: "remove", id });
22099
+ void actionsRef.current?.onRemove?.(id);
22100
+ }, []);
22029
22101
  const clear = React73.useCallback(() => dispatch({ type: "clear" }), []);
22030
22102
  const open = React73.useCallback(() => setIsOpen(true), []);
22031
22103
  const close = React73.useCallback(() => setIsOpen(false), []);
@@ -22048,6 +22120,8 @@ function NotificationsProvider({
22048
22120
  isOpen,
22049
22121
  showPopups,
22050
22122
  addNotification,
22123
+ upsertNotification,
22124
+ setNotifications,
22051
22125
  markRead,
22052
22126
  markAllRead,
22053
22127
  markSettled,
@@ -22065,6 +22139,8 @@ function NotificationsProvider({
22065
22139
  isOpen,
22066
22140
  showPopups,
22067
22141
  addNotification,
22142
+ upsertNotification,
22143
+ setNotifications,
22068
22144
  markRead,
22069
22145
  markAllRead,
22070
22146
  markSettled,
@@ -22096,7 +22172,7 @@ init_button();
22096
22172
  init_cn();
22097
22173
 
22098
22174
  // src/components/features/notifications/notification-tile.tsx
22099
- import { useMemo as useMemo16, useEffect as useEffect32 } from "react";
22175
+ import { useMemo as useMemo16, useEffect as useEffect33 } from "react";
22100
22176
  init_button();
22101
22177
  init_cn();
22102
22178
  import { jsx as jsx183, jsxs as jsxs142 } from "react/jsx-runtime";
@@ -22110,7 +22186,7 @@ function NotificationTile({
22110
22186
  const { id, variant = "default", title, description, createdAt, read, settled } = notification;
22111
22187
  const initialElapsed = useMemo16(() => Date.now() - createdAt, [createdAt]);
22112
22188
  const isLive = !read && !settled && initialElapsed < liveDurationMs;
22113
- useEffect32(() => {
22189
+ useEffect33(() => {
22114
22190
  if (!isLive) return;
22115
22191
  const remaining = Math.max(0, liveDurationMs - initialElapsed);
22116
22192
  const timer = window.setTimeout(() => {
@@ -23038,16 +23114,16 @@ function canonicalize(status) {
23038
23114
 
23039
23115
  // src/components/navigation/header.tsx
23040
23116
  init_next_link();
23041
- import React78, { useEffect as useEffect35, useRef as useRef27, useState as useState53 } from "react";
23117
+ import React78, { useEffect as useEffect36, useRef as useRef28, useState as useState53 } from "react";
23042
23118
  init_button2();
23043
23119
  import { Fragment as Fragment26, jsx as jsx190, jsxs as jsxs149 } from "react/jsx-runtime";
23044
23120
  function Header2({ config, platform }) {
23045
23121
  const [show, setShow] = useState53(true);
23046
23122
  const [lastScrollY, setLastScrollY] = useState53(0);
23047
23123
  const [openDropdowns, setOpenDropdowns] = useState53({});
23048
- const dropdownRefs = useRef27({});
23049
- const triggerRefs = useRef27({});
23050
- useEffect35(() => {
23124
+ const dropdownRefs = useRef28({});
23125
+ const triggerRefs = useRef28({});
23126
+ useEffect36(() => {
23051
23127
  const handleClickOutside = (event) => {
23052
23128
  const target = event.target;
23053
23129
  if (!target) return;
@@ -23076,14 +23152,14 @@ function Header2({ config, platform }) {
23076
23152
  document.removeEventListener("keydown", handleEscapeKey);
23077
23153
  };
23078
23154
  }, [openDropdowns]);
23079
- useEffect35(() => {
23155
+ useEffect36(() => {
23080
23156
  return () => {
23081
23157
  setOpenDropdowns({});
23082
23158
  dropdownRefs.current = {};
23083
23159
  triggerRefs.current = {};
23084
23160
  };
23085
23161
  }, []);
23086
- useEffect35(() => {
23162
+ useEffect36(() => {
23087
23163
  if (!config.autoHide) {
23088
23164
  setShow(true);
23089
23165
  return;
@@ -23306,7 +23382,7 @@ function Header2({ config, platform }) {
23306
23382
  }
23307
23383
 
23308
23384
  // src/components/navigation/client-only-header.tsx
23309
- import { useState as useState54, useEffect as useEffect36 } from "react";
23385
+ import { useState as useState54, useEffect as useEffect37 } from "react";
23310
23386
 
23311
23387
  // src/components/navigation/header-skeleton.tsx
23312
23388
  import { jsx as jsx191, jsxs as jsxs150 } from "react/jsx-runtime";
@@ -23355,7 +23431,7 @@ function HeaderSkeleton({ config }) {
23355
23431
  import { jsx as jsx192 } from "react/jsx-runtime";
23356
23432
  function ClientOnlyHeader({ config, skeleton }) {
23357
23433
  const [isClient, setIsClient] = useState54(false);
23358
- useEffect36(() => {
23434
+ useEffect37(() => {
23359
23435
  setIsClient(true);
23360
23436
  }, []);
23361
23437
  if (!isClient) {
@@ -23365,13 +23441,13 @@ function ClientOnlyHeader({ config, skeleton }) {
23365
23441
  }
23366
23442
 
23367
23443
  // src/components/navigation/mobile-nav-panel.tsx
23368
- import { useEffect as useEffect37, useRef as useRef28 } from "react";
23444
+ import { useEffect as useEffect38, useRef as useRef29 } from "react";
23369
23445
  init_button2();
23370
23446
  import { X as X10 } from "lucide-react";
23371
23447
  import { Fragment as Fragment27, jsx as jsx193, jsxs as jsxs151 } from "react/jsx-runtime";
23372
23448
  function MobileNavPanel({ isOpen, config }) {
23373
- const panelRef = useRef28(null);
23374
- useEffect37(() => {
23449
+ const panelRef = useRef29(null);
23450
+ useEffect38(() => {
23375
23451
  if (isOpen) {
23376
23452
  document.body.style.overflow = "hidden";
23377
23453
  } else {
@@ -23381,7 +23457,7 @@ function MobileNavPanel({ isOpen, config }) {
23381
23457
  document.body.style.overflow = "unset";
23382
23458
  };
23383
23459
  }, [isOpen]);
23384
- useEffect37(() => {
23460
+ useEffect38(() => {
23385
23461
  const handleKeyDown = (e) => {
23386
23462
  if (e.key === "Escape" && isOpen) {
23387
23463
  config.onClose?.();
@@ -23489,7 +23565,7 @@ function MobileNavPanel({ isOpen, config }) {
23489
23565
  }
23490
23566
 
23491
23567
  // src/components/navigation/sliding-sidebar.tsx
23492
- import { useState as useState55, useEffect as useEffect38 } from "react";
23568
+ import { useState as useState55, useEffect as useEffect39 } from "react";
23493
23569
  import { motion as motion2, AnimatePresence } from "framer-motion";
23494
23570
  init_button2();
23495
23571
  import { Fragment as Fragment28, jsx as jsx194, jsxs as jsxs152 } from "react/jsx-runtime";
@@ -23497,7 +23573,7 @@ function SlidingSidebar({ config }) {
23497
23573
  const [expandedItems, setExpandedItems] = useState55(/* @__PURE__ */ new Set());
23498
23574
  const [mounted, setMounted] = useState55(false);
23499
23575
  const [headerHeight, setHeaderHeight] = useState55(64);
23500
- useEffect38(() => {
23576
+ useEffect39(() => {
23501
23577
  setMounted(true);
23502
23578
  const calculateHeaderHeight = () => {
23503
23579
  let totalHeight = 0;
@@ -23708,7 +23784,7 @@ function SlidingSidebar({ config }) {
23708
23784
  }
23709
23785
 
23710
23786
  // src/components/navigation/sticky-section-nav.tsx
23711
- import { useEffect as useEffect39, useState as useState56, useCallback as useCallback19, useRef as useRef29 } from "react";
23787
+ import { useEffect as useEffect40, useState as useState56, useCallback as useCallback19, useRef as useRef30 } from "react";
23712
23788
  import { jsx as jsx195, jsxs as jsxs153 } from "react/jsx-runtime";
23713
23789
  function StickySectionNav({
23714
23790
  sections,
@@ -23770,7 +23846,7 @@ function StickySectionNav({
23770
23846
  }
23771
23847
  function useSectionNavigation(sections, options) {
23772
23848
  const [activeSection, setActiveSection] = useState56(sections[0]?.id || "");
23773
- const isScrollingFromClick = useRef29(false);
23849
+ const isScrollingFromClick = useRef30(false);
23774
23850
  const { offset: offset2 = 100 } = options || {};
23775
23851
  const handleSectionClick = useCallback19((sectionId) => {
23776
23852
  const targetElement = document.getElementById(sectionId);
@@ -23782,14 +23858,14 @@ function useSectionNavigation(sections, options) {
23782
23858
  isScrollingFromClick.current = false;
23783
23859
  }, 500);
23784
23860
  }, [offset2]);
23785
- useEffect39(() => {
23861
+ useEffect40(() => {
23786
23862
  sections.forEach((section) => {
23787
23863
  if (section.ref.current && !section.ref.current.id) {
23788
23864
  section.ref.current.id = section.id;
23789
23865
  }
23790
23866
  });
23791
23867
  }, [sections]);
23792
- useEffect39(() => {
23868
+ useEffect40(() => {
23793
23869
  const handleScroll = () => {
23794
23870
  if (isScrollingFromClick.current) return;
23795
23871
  const scrollPosition = window.scrollY + offset2 + 50;
@@ -23822,7 +23898,7 @@ function useSectionNavigation(sections, options) {
23822
23898
  }
23823
23899
 
23824
23900
  // src/components/navigation/navigation-sidebar.tsx
23825
- import { useCallback as useCallback20, useEffect as useEffect40, useLayoutEffect as useLayoutEffect4, useMemo as useMemo19, useState as useState57 } from "react";
23901
+ import { useCallback as useCallback20, useEffect as useEffect41, useLayoutEffect as useLayoutEffect4, useMemo as useMemo19, useState as useState57 } from "react";
23826
23902
 
23827
23903
  // src/components/navigation/navigation-sidebar-header.tsx
23828
23904
  import { jsx as jsx196, jsxs as jsxs154 } from "react/jsx-runtime";
@@ -23975,7 +24051,7 @@ function NavigationSidebar({ config, disabled = false }) {
23975
24051
  config.minimized ?? false
23976
24052
  );
23977
24053
  const [tabletMinimized, setTabletMinimized] = useState57(true);
23978
- useEffect40(() => {
24054
+ useEffect41(() => {
23979
24055
  if (isTablet) setTabletMinimized(true);
23980
24056
  }, [isTablet]);
23981
24057
  const minimized = isTablet ? tabletMinimized : desktopMinimized;
@@ -23993,7 +24069,7 @@ function NavigationSidebar({ config, disabled = false }) {
23993
24069
  const closeOverlay = useCallback20(() => {
23994
24070
  setTabletMinimized(true);
23995
24071
  }, []);
23996
- useEffect40(() => {
24072
+ useEffect41(() => {
23997
24073
  if (!isOverlayOpen) return;
23998
24074
  const handleKeyDown = (e) => {
23999
24075
  if (e.key === "Escape") closeOverlay();
@@ -24403,16 +24479,20 @@ function NotificationsHeaderButton({
24403
24479
  dimmedClass
24404
24480
  }) {
24405
24481
  const ctx = useOptionalNotifications();
24406
- const unreadCount = ctx?.unreadCount ?? fallbackUnreadCount;
24482
+ const hasUnread = (ctx?.unreadCount ?? fallbackUnreadCount) > 0;
24407
24483
  const isActive = ctx?.isOpen ?? false;
24408
24484
  const onClick = ctx?.toggle;
24409
- const Icon2 = unreadCount > 0 ? BellRingingIcon : BellIcon;
24410
24485
  return /* @__PURE__ */ jsx203(
24411
24486
  HeaderButton,
24412
24487
  {
24413
- icon: /* @__PURE__ */ jsxs160("div", { className: "relative w-full h-full flex items-center justify-center", children: [
24414
- /* @__PURE__ */ jsx203(Icon2, { className: "h-4 w-4 md:w-6 md:h-6" }),
24415
- unreadCount > 0 && /* @__PURE__ */ jsx203("span", { className: "absolute top-2 right-2 bg-ods-accent text-ods-text-on-accent text-[8px] rounded-full w-3 h-3 md:w-4 md:h-4 flex items-center justify-center", children: unreadCount > 9 ? "9+" : unreadCount })
24488
+ icon: /* @__PURE__ */ jsxs160("div", { className: "relative w-4 h-4 md:w-6 md:h-6", children: [
24489
+ /* @__PURE__ */ jsx203(BellIcon, { className: "w-full h-full" }),
24490
+ hasUnread && /* @__PURE__ */ jsx203(
24491
+ "span",
24492
+ {
24493
+ className: "absolute top-0 right-0 bg-ods-warning rounded-full w-1.5 h-1.5 md:w-2 md:h-2"
24494
+ }
24495
+ )
24416
24496
  ] }),
24417
24497
  "aria-label": "Notifications",
24418
24498
  onClick,
@@ -24427,7 +24507,7 @@ function NotificationsHeaderButton({
24427
24507
  import { Suspense, useCallback as useCallback22, useState as useState58 } from "react";
24428
24508
 
24429
24509
  // src/components/navigation/mobile-burger-menu.tsx
24430
- import React84, { useCallback as useCallback21, useEffect as useEffect41 } from "react";
24510
+ import React84, { useCallback as useCallback21, useEffect as useEffect42 } from "react";
24431
24511
  import { Fragment as Fragment30, jsx as jsx204, jsxs as jsxs161 } from "react/jsx-runtime";
24432
24512
  var HEADER_HEIGHT = 48;
24433
24513
  var MobileBurgerMenu = React84.memo(function MobileBurgerMenu2({
@@ -24440,7 +24520,7 @@ var MobileBurgerMenu = React84.memo(function MobileBurgerMenu2({
24440
24520
  onLogout,
24441
24521
  disabled = false
24442
24522
  }) {
24443
- useEffect41(() => {
24523
+ useEffect42(() => {
24444
24524
  if (isOpen) {
24445
24525
  document.body.style.overflow = "hidden";
24446
24526
  } else {
@@ -24450,7 +24530,7 @@ var MobileBurgerMenu = React84.memo(function MobileBurgerMenu2({
24450
24530
  document.body.style.overflow = "unset";
24451
24531
  };
24452
24532
  }, [isOpen]);
24453
- useEffect41(() => {
24533
+ useEffect42(() => {
24454
24534
  const handleKeyDown = (e) => {
24455
24535
  if (e.key === "Escape" && isOpen) {
24456
24536
  onClose();
@@ -25010,7 +25090,7 @@ ScriptArguments.displayName = "ScriptArguments";
25010
25090
 
25011
25091
  // src/components/shared/onboarding/onboarding-walkthrough.tsx
25012
25092
  init_button2();
25013
- import React86, { useRef as useRef30, useCallback as useCallback23 } from "react";
25093
+ import React86, { useRef as useRef31, useCallback as useCallback23 } from "react";
25014
25094
 
25015
25095
  // src/components/shared/onboarding/onboarding-step-card.tsx
25016
25096
  import React85 from "react";
@@ -25134,10 +25214,10 @@ function OnboardingWalkthrough({
25134
25214
  allStepsComplete,
25135
25215
  markMultipleComplete
25136
25216
  } = useOnboardingState(storageKey);
25137
- const hasAutoMarkedRef = useRef30(false);
25138
- const autoMarkingInProgressRef = useRef30(false);
25139
- const lastCompletionStatusRef = useRef30(null);
25140
- const actionInProgressRef = useRef30(/* @__PURE__ */ new Set());
25217
+ const hasAutoMarkedRef = useRef31(false);
25218
+ const autoMarkingInProgressRef = useRef31(false);
25219
+ const lastCompletionStatusRef = useRef31(null);
25220
+ const actionInProgressRef = useRef31(/* @__PURE__ */ new Set());
25141
25221
  React86.useEffect(() => {
25142
25222
  if (isLoadingCompletion) {
25143
25223
  hasAutoMarkedRef.current = false;
@@ -25844,7 +25924,7 @@ var ListLoader = (props) => /* @__PURE__ */ jsx223(ContentLoader, { ...props, va
25844
25924
 
25845
25925
  // src/components/ui/table/table.tsx
25846
25926
  init_cn();
25847
- import { useEffect as useEffect42, useRef as useRef32 } from "react";
25927
+ import { useEffect as useEffect43, useRef as useRef33 } from "react";
25848
25928
  init_pagination();
25849
25929
  init_button2();
25850
25930
 
@@ -26595,10 +26675,10 @@ function Table({
26595
26675
  };
26596
26676
  const allSelected = selectedRows.length > 0 && selectedRows.length === data.length;
26597
26677
  const someSelected = selectedRows.length > 0 && selectedRows.length < data.length;
26598
- const sentinelRef = useRef32(null);
26599
- const onLoadMoreRef = useRef32(infiniteScroll?.onLoadMore);
26678
+ const sentinelRef = useRef33(null);
26679
+ const onLoadMoreRef = useRef33(infiniteScroll?.onLoadMore);
26600
26680
  onLoadMoreRef.current = infiniteScroll?.onLoadMore;
26601
- useEffect42(() => {
26681
+ useEffect43(() => {
26602
26682
  if (!infiniteScroll?.hasNextPage || infiniteScroll.isFetchingNextPage) return;
26603
26683
  const sentinel = sentinelRef.current;
26604
26684
  if (!sentinel) return;
@@ -26810,7 +26890,7 @@ import { useMemo as useMemo21 } from "react";
26810
26890
 
26811
26891
  // src/components/ui/query-report-table/query-report-table-header.tsx
26812
26892
  init_cn();
26813
- import { useRef as useRef33, useState as useState60, useCallback as useCallback24 } from "react";
26893
+ import { useRef as useRef34, useState as useState60, useCallback as useCallback24 } from "react";
26814
26894
  import { jsx as jsx235, jsxs as jsxs187 } from "react/jsx-runtime";
26815
26895
  function QueryReportTableHeader({
26816
26896
  columns,
@@ -26839,7 +26919,7 @@ function QueryReportTableHeader({
26839
26919
  );
26840
26920
  }
26841
26921
  function TruncatedHeaderCell({ value, width }) {
26842
- const textRef = useRef33(null);
26922
+ const textRef = useRef34(null);
26843
26923
  const [isTruncated, setIsTruncated] = useState60(false);
26844
26924
  const checkTruncation = useCallback24(() => {
26845
26925
  const el = textRef.current;
@@ -26869,7 +26949,7 @@ function TruncatedHeaderCell({ value, width }) {
26869
26949
 
26870
26950
  // src/components/ui/query-report-table/query-report-table-row.tsx
26871
26951
  init_cn();
26872
- import { useRef as useRef34, useState as useState61, useCallback as useCallback25 } from "react";
26952
+ import { useRef as useRef35, useState as useState61, useCallback as useCallback25 } from "react";
26873
26953
  import { jsx as jsx236, jsxs as jsxs188 } from "react/jsx-runtime";
26874
26954
  function QueryReportTableRow({
26875
26955
  row,
@@ -26915,7 +26995,7 @@ function QueryReportTableRow({
26915
26995
  );
26916
26996
  }
26917
26997
  function TruncatedCell({ value, className }) {
26918
- const textRef = useRef34(null);
26998
+ const textRef = useRef35(null);
26919
26999
  const [isTruncated, setIsTruncated] = useState61(false);
26920
27000
  const checkTruncation = useCallback25(() => {
26921
27001
  const el = textRef.current;
@@ -27434,7 +27514,7 @@ function DataTableEmpty({
27434
27514
  // src/components/ui/data-table/data-table-row.tsx
27435
27515
  init_next_link();
27436
27516
  init_cn();
27437
- import { memo as memo3, useCallback as useCallback27, useRef as useRef35 } from "react";
27517
+ import { memo as memo3, useCallback as useCallback27, useRef as useRef36 } from "react";
27438
27518
  import { flexRender as flexRender2 } from "@tanstack/react-table";
27439
27519
 
27440
27520
  // src/components/ui/data-table/data-table-skeleton.tsx
@@ -27515,7 +27595,7 @@ function DataTableRowImpl({
27515
27595
  className
27516
27596
  }) {
27517
27597
  const isLinkMode = Boolean(href) && !onClick;
27518
- const containerRef = useRef35(null);
27598
+ const containerRef = useRef36(null);
27519
27599
  const handleClick = useCallback27(
27520
27600
  (e) => {
27521
27601
  const target = e.target;
@@ -27664,7 +27744,7 @@ function DataTableBody({
27664
27744
  }
27665
27745
 
27666
27746
  // src/components/ui/data-table/data-table-infinite-footer.tsx
27667
- import { useEffect as useEffect43, useRef as useRef36 } from "react";
27747
+ import { useEffect as useEffect44, useRef as useRef37 } from "react";
27668
27748
  import { Fragment as Fragment38, jsx as jsx246, jsxs as jsxs196 } from "react/jsx-runtime";
27669
27749
  function DataTableInfiniteFooter({
27670
27750
  hasNextPage,
@@ -27673,10 +27753,10 @@ function DataTableInfiniteFooter({
27673
27753
  skeletonRows = 3,
27674
27754
  rootMargin = "200px"
27675
27755
  }) {
27676
- const sentinelRef = useRef36(null);
27677
- const onLoadMoreRef = useRef36(onLoadMore);
27756
+ const sentinelRef = useRef37(null);
27757
+ const onLoadMoreRef = useRef37(onLoadMore);
27678
27758
  onLoadMoreRef.current = onLoadMore;
27679
- useEffect43(() => {
27759
+ useEffect44(() => {
27680
27760
  if (!hasNextPage || isFetchingNextPage) return;
27681
27761
  const sentinel = sentinelRef.current;
27682
27762
  if (!sentinel) return;
@@ -28307,8 +28387,8 @@ function FilterList({
28307
28387
 
28308
28388
  // src/components/ui/tag-search-input.tsx
28309
28389
  import {
28310
- useEffect as useEffect45,
28311
- useRef as useRef38,
28390
+ useEffect as useEffect46,
28391
+ useRef as useRef39,
28312
28392
  useState as useState63
28313
28393
  } from "react";
28314
28394
  init_cn();
@@ -28343,11 +28423,11 @@ function TagSearchInput({
28343
28423
  limitTags,
28344
28424
  placeholder: currentPlaceholder
28345
28425
  });
28346
- const wrapperRef = useRef38(null);
28347
- const hiddenTagsRef = useRef38(null);
28348
- const hiddenTagsPopupRef = useRef38(null);
28426
+ const wrapperRef = useRef39(null);
28427
+ const hiddenTagsRef = useRef39(null);
28428
+ const hiddenTagsPopupRef = useRef39(null);
28349
28429
  const [showHiddenTags, setShowHiddenTags] = useState63(false);
28350
- useEffect45(() => {
28430
+ useEffect46(() => {
28351
28431
  if (!showHiddenTags) return;
28352
28432
  const handleClick = (e) => {
28353
28433
  const target = e.target;
@@ -28502,7 +28582,7 @@ function TagSearchInput({
28502
28582
  }
28503
28583
 
28504
28584
  // src/components/ui/markdown-editor.tsx
28505
- import { useRef as useRef39, useCallback as useCallback28, useState as useState64, useEffect as useEffect46 } from "react";
28585
+ import { useRef as useRef40, useCallback as useCallback28, useState as useState64, useEffect as useEffect47 } from "react";
28506
28586
  init_cn();
28507
28587
  import { Loader2 as Loader28, Upload as Upload8 } from "lucide-react";
28508
28588
  import { jsx as jsx251, jsxs as jsxs201 } from "react/jsx-runtime";
@@ -28533,7 +28613,7 @@ body .w-md-editor .w-md-editor-bar::after { content: '' !important; display: blo
28533
28613
  body .w-md-editor .w-md-editor-bar:hover::after { border-color: var(--color-text-secondary) !important; }
28534
28614
  `;
28535
28615
  function MarkdownEditorStyles() {
28536
- useEffect46(() => {
28616
+ useEffect47(() => {
28537
28617
  if (document.getElementById(MARKDOWN_EDITOR_STYLE_ID)) return;
28538
28618
  const style = document.createElement("style");
28539
28619
  style.id = MARKDOWN_EDITOR_STYLE_ID;
@@ -28557,11 +28637,11 @@ function MarkdownEditor({
28557
28637
  onFileUploaded,
28558
28638
  renderPreview
28559
28639
  }) {
28560
- const fileInputRef = useRef39(null);
28640
+ const fileInputRef = useRef40(null);
28561
28641
  const [isUploading, setIsUploading] = useState64(false);
28562
28642
  const [uploadProgress, setUploadProgress] = useState64("");
28563
28643
  const [defaultExtraCommands, setDefaultExtraCommands] = useState64([]);
28564
- useEffect46(() => {
28644
+ useEffect47(() => {
28565
28645
  import("@uiw/react-md-editor").then((mod) => {
28566
28646
  if (mod.commands?.getExtraCommands) {
28567
28647
  setDefaultExtraCommands(mod.commands.getExtraCommands());
@@ -28650,11 +28730,11 @@ function MarkdownEditor({
28650
28730
  }
28651
28731
  } : null;
28652
28732
  const extraCommands = uploadCommand ? [...defaultExtraCommands, uploadCommand] : defaultExtraCommands;
28653
- const wrapperRef = useRef39(null);
28654
- const isDraggingRef = useRef39(false);
28655
- const mouseYRef = useRef39(0);
28656
- const rafRef = useRef39(0);
28657
- const scrollParentRef = useRef39(window);
28733
+ const wrapperRef = useRef40(null);
28734
+ const isDraggingRef = useRef40(false);
28735
+ const mouseYRef = useRef40(0);
28736
+ const rafRef = useRef40(0);
28737
+ const scrollParentRef = useRef40(window);
28658
28738
  const EDGE_ZONE = 60;
28659
28739
  const MAX_SCROLL_SPEED = 15;
28660
28740
  const findScrollParent = useCallback28((el) => {
@@ -28684,7 +28764,7 @@ function MarkdownEditor({
28684
28764
  }
28685
28765
  rafRef.current = requestAnimationFrame(scrollLoop);
28686
28766
  }, []);
28687
- useEffect46(() => {
28767
+ useEffect47(() => {
28688
28768
  const wrapper = wrapperRef.current;
28689
28769
  if (!wrapper) return;
28690
28770
  const onMouseMove = (e) => {
@@ -29933,7 +30013,7 @@ function ImageGalleryModal({
29933
30013
  initialIndex = 0
29934
30014
  }) {
29935
30015
  const [selectedImageIndex, setSelectedImageIndex] = useState70(initialIndex);
29936
- useEffect49(() => {
30016
+ useEffect50(() => {
29937
30017
  if (isOpen) {
29938
30018
  setSelectedImageIndex(initialIndex);
29939
30019
  }
@@ -29948,7 +30028,7 @@ function ImageGalleryModal({
29948
30028
  setSelectedImageIndex(selectedImageIndex + 1);
29949
30029
  }
29950
30030
  };
29951
- useEffect49(() => {
30031
+ useEffect50(() => {
29952
30032
  const handleKeyPress = (event) => {
29953
30033
  if (!isOpen) return;
29954
30034
  switch (event.key) {
@@ -33702,7 +33782,7 @@ function transformWebinarToProgram(webinar) {
33702
33782
  }
33703
33783
 
33704
33784
  // src/components/chat/hooks/use-chunk-catchup.ts
33705
- import { useCallback as useCallback30, useRef as useRef42 } from "react";
33785
+ import { useCallback as useCallback30, useRef as useRef43 } from "react";
33706
33786
  function makeSeqKey(messageType, chunkType, sequenceId) {
33707
33787
  return `${messageType}:${chunkType}:${sequenceId}`;
33708
33788
  }
@@ -33724,20 +33804,20 @@ function useChunkCatchup({
33724
33804
  chatTypes = [CHAT_TYPE.CLIENT],
33725
33805
  fetchChunks
33726
33806
  }) {
33727
- const processedSequenceKeys = useRef42(/* @__PURE__ */ new Set());
33728
- const lastSequenceId = useRef42(null);
33729
- const fetchingInProgress = useRef42(false);
33730
- const lastFetchParams = useRef42(null);
33731
- const chunkBuffer = useRef42([]);
33732
- const bufferUntilInitialCatchupComplete = useRef42(false);
33733
- const hasCompletedInitialCatchup = useRef42(false);
33734
- const dialogIdRef = useRef42(dialogId);
33807
+ const processedSequenceKeys = useRef43(/* @__PURE__ */ new Set());
33808
+ const lastSequenceId = useRef43(null);
33809
+ const fetchingInProgress = useRef43(false);
33810
+ const lastFetchParams = useRef43(null);
33811
+ const chunkBuffer = useRef43([]);
33812
+ const bufferUntilInitialCatchupComplete = useRef43(false);
33813
+ const hasCompletedInitialCatchup = useRef43(false);
33814
+ const dialogIdRef = useRef43(dialogId);
33735
33815
  dialogIdRef.current = dialogId;
33736
- const chatTypesRef = useRef42(chatTypes);
33816
+ const chatTypesRef = useRef43(chatTypes);
33737
33817
  chatTypesRef.current = chatTypes;
33738
- const fetchChunksRef = useRef42(fetchChunks);
33818
+ const fetchChunksRef = useRef43(fetchChunks);
33739
33819
  fetchChunksRef.current = fetchChunks;
33740
- const onChunkReceivedRef = useRef42(onChunkReceived);
33820
+ const onChunkReceivedRef = useRef43(onChunkReceived);
33741
33821
  onChunkReceivedRef.current = onChunkReceived;
33742
33822
  const processChunk = useCallback30((chunk, messageType, forceProcess = false) => {
33743
33823
  if (bufferUntilInitialCatchupComplete.current && !forceProcess) {
@@ -33914,8 +33994,7 @@ function useChunkCatchup({
33914
33994
  }
33915
33995
 
33916
33996
  // src/components/chat/hooks/use-jetstream-dialog-subscription.ts
33917
- import { useCallback as useCallback31, useEffect as useEffect50, useRef as useRef43, useState as useState73 } from "react";
33918
- var shared = null;
33997
+ import { useEffect as useEffect51, useRef as useRef44, useState as useState73 } from "react";
33919
33998
  var DEFAULT_INACTIVE_THRESHOLD_MS = 5 * 6e4;
33920
33999
  var DEFAULT_STREAM_NAME = "CHAT_CHUNKS";
33921
34000
  function useJetStreamDialogSubscription({
@@ -33938,105 +34017,53 @@ function useJetStreamDialogSubscription({
33938
34017
  const [isSubscribed, setIsSubscribed] = useState73(false);
33939
34018
  const [reconnectionCount, setReconnectionCount] = useState73(0);
33940
34019
  const [currentStreamSeq, setCurrentStreamSeq] = useState73(null);
33941
- const clientRef = useRef43(null);
33942
- const subscriptionRef = useRef43(null);
33943
- const highestStreamSeqRef = useRef43(null);
33944
- const onEventRef = useRef43(onEvent);
33945
- useEffect50(() => {
34020
+ const clientRef = useRef44(null);
34021
+ const subscriptionRef = useRef44(null);
34022
+ const highestStreamSeqRef = useRef44(null);
34023
+ const onEventRef = useRef44(onEvent);
34024
+ useEffect51(() => {
33946
34025
  onEventRef.current = onEvent;
33947
34026
  }, [onEvent]);
33948
- const onConnectRef = useRef43(onConnect);
33949
- useEffect50(() => {
34027
+ const onConnectRef = useRef44(onConnect);
34028
+ useEffect51(() => {
33950
34029
  onConnectRef.current = onConnect;
33951
34030
  }, [onConnect]);
33952
- const onDisconnectRef = useRef43(onDisconnect);
33953
- useEffect50(() => {
34031
+ const onDisconnectRef = useRef44(onDisconnect);
34032
+ useEffect51(() => {
33954
34033
  onDisconnectRef.current = onDisconnect;
33955
34034
  }, [onDisconnect]);
33956
- const onSubscribedRef = useRef43(onSubscribed);
33957
- useEffect50(() => {
34035
+ const onSubscribedRef = useRef44(onSubscribed);
34036
+ useEffect51(() => {
33958
34037
  onSubscribedRef.current = onSubscribed;
33959
34038
  }, [onSubscribed]);
33960
- const onBeforeReconnectRef = useRef43(onBeforeReconnect);
33961
- useEffect50(() => {
34039
+ const onBeforeReconnectRef = useRef44(onBeforeReconnect);
34040
+ useEffect51(() => {
33962
34041
  onBeforeReconnectRef.current = onBeforeReconnect;
33963
34042
  }, [onBeforeReconnect]);
33964
- const getNatsWsUrlRef = useRef43(getNatsWsUrl);
33965
- useEffect50(() => {
34043
+ const getNatsWsUrlRef = useRef44(getNatsWsUrl);
34044
+ useEffect51(() => {
33966
34045
  getNatsWsUrlRef.current = getNatsWsUrl;
33967
34046
  }, [getNatsWsUrl]);
33968
- const reconnectionBackoffRef = useRef43(reconnectionBackoff);
33969
- useEffect50(() => {
34047
+ const reconnectionBackoffRef = useRef44(reconnectionBackoff);
34048
+ useEffect51(() => {
33970
34049
  reconnectionBackoffRef.current = reconnectionBackoff;
33971
34050
  }, [reconnectionBackoff]);
33972
- const optStartSeqRef = useRef43(optStartSeq);
33973
- useEffect50(() => {
34051
+ const optStartSeqRef = useRef44(optStartSeq);
34052
+ useEffect51(() => {
33974
34053
  optStartSeqRef.current = optStartSeq;
33975
34054
  }, [optStartSeq]);
33976
- const inactiveThresholdRef = useRef43(inactiveThresholdMs);
33977
- useEffect50(() => {
34055
+ const inactiveThresholdRef = useRef44(inactiveThresholdMs);
34056
+ useEffect51(() => {
33978
34057
  inactiveThresholdRef.current = inactiveThresholdMs;
33979
34058
  }, [inactiveThresholdMs]);
33980
- const hadConnectionBeforeRef = useRef43(false);
33981
- const acquireClient = useCallback31(
33982
- (url) => {
33983
- if (shared?.wsUrl !== url) {
33984
- if (shared) {
33985
- if (shared.closeTimer) clearTimeout(shared.closeTimer);
33986
- const old = shared;
33987
- shared = null;
33988
- void old.client.close().catch(() => {
33989
- });
33990
- }
33991
- const { name = "openframe-frontend-jetstream", user = "machine", pass = "" } = clientConfig;
33992
- const client = createNatsClient({
33993
- servers: url,
33994
- name,
33995
- user,
33996
- pass,
33997
- connectTimeoutMs: NETWORK_CONFIG.CONNECT_TIMEOUT_MS,
33998
- reconnect: false,
33999
- pingIntervalMs: NETWORK_CONFIG.PING_INTERVAL_MS,
34000
- maxPingOut: NETWORK_CONFIG.MAX_PING_OUT
34001
- });
34002
- shared = {
34003
- wsUrl: url,
34004
- client,
34005
- connectPromise: null,
34006
- refCount: 0,
34007
- closeTimer: null,
34008
- retryTimer: null
34009
- };
34010
- }
34011
- shared.refCount += 1;
34012
- if (shared.closeTimer) {
34013
- clearTimeout(shared.closeTimer);
34014
- shared.closeTimer = null;
34015
- }
34016
- return shared;
34017
- },
34018
- [clientConfig]
34019
- );
34020
- const releaseClient = useCallback31((url) => {
34021
- if (!shared || shared.wsUrl !== url) return;
34022
- shared.refCount = Math.max(0, shared.refCount - 1);
34023
- if (shared.refCount > 0) return;
34024
- shared.closeTimer = setTimeout(() => {
34025
- const s = shared;
34026
- shared = null;
34027
- if (s) {
34028
- if (s.retryTimer) {
34029
- clearTimeout(s.retryTimer);
34030
- s.retryTimer = null;
34031
- }
34032
- void s.client.close().catch(() => {
34033
- });
34034
- }
34035
- }, NETWORK_CONFIG.SHARED_CLOSE_DELAY_MS);
34036
- }, []);
34037
- const currentWsUrlRef = useRef43("");
34038
- useEffect50(() => {
34039
- const wsUrl = getNatsWsUrl();
34059
+ const hadConnectionBeforeRef = useRef44(false);
34060
+ const clientConfigRef = useRef44(clientConfig);
34061
+ useEffect51(() => {
34062
+ clientConfigRef.current = clientConfig;
34063
+ }, [clientConfig]);
34064
+ const currentWsUrlRef = useRef44("");
34065
+ const wsUrl = getNatsWsUrl();
34066
+ useEffect51(() => {
34040
34067
  if (!enabled || !wsUrl) {
34041
34068
  if (currentWsUrlRef.current && clientRef.current) {
34042
34069
  releaseClient(currentWsUrlRef.current);
@@ -34055,127 +34082,69 @@ function useJetStreamDialogSubscription({
34055
34082
  setIsConnected(false);
34056
34083
  }
34057
34084
  currentWsUrlRef.current = wsUrl;
34058
- const sharedConn = acquireClient(wsUrl);
34085
+ const cfg = clientConfigRef.current;
34086
+ const sharedConn = acquireClient(wsUrl, {
34087
+ name: cfg.name ?? "openframe-frontend-jetstream",
34088
+ user: cfg.user ?? "machine",
34089
+ pass: cfg.pass ?? ""
34090
+ });
34059
34091
  const client = sharedConn.client;
34060
34092
  clientRef.current = client;
34061
- setIsConnected(false);
34062
- let closed = false;
34063
- let retryAttempt = 0;
34064
- function scheduleRetry() {
34065
- if (closed) return;
34066
- if (shared !== sharedConn) return;
34067
- if (sharedConn.retryTimer) {
34068
- clearTimeout(sharedConn.retryTimer);
34069
- sharedConn.retryTimer = null;
34070
- }
34071
- const cfg = reconnectionBackoffRef.current ?? {};
34072
- const fastRetries = cfg.fastRetries ?? 0;
34073
- const fastDelay = cfg.fastRetryDelayMs ?? NETWORK_CONFIG.RETRY_INITIAL_DELAY_MS;
34074
- const baseDelay = cfg.initialDelayMs ?? NETWORK_CONFIG.RETRY_INITIAL_DELAY_MS;
34075
- const maxDelay = cfg.maxDelayMs ?? NETWORK_CONFIG.RETRY_MAX_DELAY_MS;
34076
- const multiplier = cfg.multiplier ?? NETWORK_CONFIG.RETRY_BACKOFF_MULTIPLIER;
34077
- const delay2 = retryAttempt < fastRetries ? fastDelay : Math.min(baseDelay * multiplier ** (retryAttempt - fastRetries), maxDelay);
34078
- const jitteredDelay = delay2 * (0.5 + Math.random() * 0.5);
34079
- retryAttempt++;
34080
- sharedConn.retryTimer = setTimeout(async () => {
34081
- sharedConn.retryTimer = null;
34082
- if (closed) return;
34083
- if (shared !== sharedConn) return;
34084
- try {
34085
- await onBeforeReconnectRef.current?.();
34086
- } catch {
34087
- }
34088
- if (closed) return;
34089
- if (shared !== sharedConn) return;
34090
- const freshUrl = getNatsWsUrlRef.current();
34091
- if (freshUrl !== wsUrl) return;
34093
+ setIsConnected(client.isConnected());
34094
+ const tearDownSubscription = () => {
34095
+ if (subscriptionRef.current) {
34092
34096
  try {
34093
- sharedConn.connectPromise = null;
34094
- sharedConn.connectPromise = client.connect();
34095
- await sharedConn.connectPromise;
34096
- if (!closed && shared === sharedConn) {
34097
- retryAttempt = 0;
34098
- setIsConnected(true);
34099
- }
34097
+ subscriptionRef.current.unsubscribe();
34100
34098
  } catch {
34101
- sharedConn.connectPromise = null;
34102
- if (!closed && shared === sharedConn) {
34103
- scheduleRetry();
34104
- }
34105
- }
34106
- }, jitteredDelay);
34107
- }
34108
- const unsubscribeStatus = client.onStatus((event) => {
34109
- const connected = event.status === "connected";
34110
- const disconnected = event.status === "closed" || event.status === "disconnected";
34111
- if (connected) {
34112
- setIsConnected(true);
34113
- if (hadConnectionBeforeRef.current) {
34114
- setReconnectionCount((c) => c + 1);
34115
- }
34116
- hadConnectionBeforeRef.current = true;
34117
- retryAttempt = 0;
34118
- onConnectRef.current?.();
34119
- }
34120
- if (event.status === "error") {
34121
- console.warn("[JetStream] NATS protocol error:", event.data);
34122
- return;
34123
- }
34124
- if (disconnected) {
34125
- setIsConnected(false);
34126
- setIsSubscribed(false);
34127
- if (subscriptionRef.current) {
34128
- try {
34129
- subscriptionRef.current.unsubscribe();
34130
- } catch {
34131
- }
34132
- subscriptionRef.current = null;
34133
34099
  }
34134
- onDisconnectRef.current?.();
34135
- scheduleRetry();
34100
+ subscriptionRef.current = null;
34136
34101
  }
34137
- });
34138
- (async () => {
34139
- try {
34140
- sharedConn.connectPromise || (sharedConn.connectPromise = client.connect());
34141
- await sharedConn.connectPromise;
34142
- if (!closed) {
34102
+ };
34103
+ const lifecycle = startConnectionLifecycle({
34104
+ conn: sharedConn,
34105
+ wsUrl,
34106
+ onBeforeReconnect: () => onBeforeReconnectRef.current?.(),
34107
+ backoff: reconnectionBackoffRef.current,
34108
+ getFreshUrl: () => getNatsWsUrlRef.current(),
34109
+ // JetStream emits 'error' for protocol-level failures (e.g. -ERR Permissions
34110
+ // Violation when CONSUMER.CREATE is denied) without closing the WebSocket.
34111
+ // Retrying on 'error' would loop onBeforeReconnect on every -ERR; let the
34112
+ // subscribe effect surface those via its own rejected promise instead.
34113
+ shouldRetryOn: (status) => status === "closed" || status === "disconnected",
34114
+ onStatusChange: (status, evt) => {
34115
+ if (status === "connected") {
34143
34116
  setIsConnected(true);
34117
+ if (hadConnectionBeforeRef.current) {
34118
+ setReconnectionCount((c) => c + 1);
34119
+ }
34144
34120
  hadConnectionBeforeRef.current = true;
34121
+ onConnectRef.current?.();
34145
34122
  }
34146
- } catch {
34147
- sharedConn.connectPromise = null;
34148
- if (!closed) {
34123
+ if (status === "error") {
34124
+ console.warn("[JetStream] NATS protocol error:", evt.data);
34125
+ return;
34126
+ }
34127
+ if (status === "closed" || status === "disconnected") {
34149
34128
  setIsConnected(false);
34129
+ setIsSubscribed(false);
34130
+ tearDownSubscription();
34150
34131
  onDisconnectRef.current?.();
34151
- scheduleRetry();
34152
34132
  }
34153
34133
  }
34154
- })();
34134
+ });
34155
34135
  return () => {
34156
- closed = true;
34136
+ lifecycle.stop();
34157
34137
  setIsConnected(false);
34158
34138
  setIsSubscribed(false);
34159
- unsubscribeStatus();
34160
- if (sharedConn.retryTimer) {
34161
- clearTimeout(sharedConn.retryTimer);
34162
- sharedConn.retryTimer = null;
34163
- }
34164
- if (subscriptionRef.current) {
34165
- try {
34166
- subscriptionRef.current.unsubscribe();
34167
- } catch {
34168
- }
34169
- subscriptionRef.current = null;
34170
- }
34139
+ tearDownSubscription();
34171
34140
  if (clientRef.current && currentWsUrlRef.current) {
34172
34141
  releaseClient(currentWsUrlRef.current);
34173
34142
  clientRef.current = null;
34174
34143
  currentWsUrlRef.current = "";
34175
34144
  }
34176
34145
  };
34177
- }, [enabled, getNatsWsUrl, acquireClient, releaseClient]);
34178
- useEffect50(() => {
34146
+ }, [enabled, wsUrl]);
34147
+ useEffect51(() => {
34179
34148
  if (!enabled || !dialogId || !isConnected) {
34180
34149
  if (subscriptionRef.current) {
34181
34150
  try {
@@ -34258,7 +34227,7 @@ function useJetStreamDialogSubscription({
34258
34227
  setIsSubscribed(false);
34259
34228
  };
34260
34229
  }, [enabled, dialogId, isConnected, streamName, topic, reconnectionCount]);
34261
- useEffect50(() => {
34230
+ useEffect51(() => {
34262
34231
  highestStreamSeqRef.current = null;
34263
34232
  setCurrentStreamSeq(null);
34264
34233
  }, [dialogId]);
@@ -34266,8 +34235,7 @@ function useJetStreamDialogSubscription({
34266
34235
  }
34267
34236
 
34268
34237
  // src/components/chat/hooks/use-nats-dialog-subscription.ts
34269
- import { useCallback as useCallback32, useEffect as useEffect51, useRef as useRef44, useState as useState74 } from "react";
34270
- var shared2 = null;
34238
+ import { useEffect as useEffect52, useRef as useRef45, useState as useState74 } from "react";
34271
34239
  function useNatsDialogSubscription({
34272
34240
  enabled,
34273
34241
  dialogId,
@@ -34284,84 +34252,44 @@ function useNatsDialogSubscription({
34284
34252
  const [isConnected, setIsConnected] = useState74(false);
34285
34253
  const [isSubscribed, setIsSubscribed] = useState74(false);
34286
34254
  const [reconnectionCount, setReconnectionCount] = useState74(0);
34287
- const clientRef = useRef44(null);
34288
- const subscriptionRefs = useRef44(/* @__PURE__ */ new Map());
34289
- const onEventRef = useRef44(onEvent);
34290
- useEffect51(() => {
34255
+ const clientRef = useRef45(null);
34256
+ const subscriptionRefs = useRef45(/* @__PURE__ */ new Map());
34257
+ const onEventRef = useRef45(onEvent);
34258
+ useEffect52(() => {
34291
34259
  onEventRef.current = onEvent;
34292
34260
  }, [onEvent]);
34293
- const onConnectRef = useRef44(onConnect);
34294
- useEffect51(() => {
34261
+ const onConnectRef = useRef45(onConnect);
34262
+ useEffect52(() => {
34295
34263
  onConnectRef.current = onConnect;
34296
34264
  }, [onConnect]);
34297
- const onDisconnectRef = useRef44(onDisconnect);
34298
- useEffect51(() => {
34265
+ const onDisconnectRef = useRef45(onDisconnect);
34266
+ useEffect52(() => {
34299
34267
  onDisconnectRef.current = onDisconnect;
34300
34268
  }, [onDisconnect]);
34301
- const onSubscribedRef = useRef44(onSubscribed);
34302
- useEffect51(() => {
34269
+ const onSubscribedRef = useRef45(onSubscribed);
34270
+ useEffect52(() => {
34303
34271
  onSubscribedRef.current = onSubscribed;
34304
34272
  }, [onSubscribed]);
34305
- const onBeforeReconnectRef = useRef44(onBeforeReconnect);
34306
- useEffect51(() => {
34273
+ const onBeforeReconnectRef = useRef45(onBeforeReconnect);
34274
+ useEffect52(() => {
34307
34275
  onBeforeReconnectRef.current = onBeforeReconnect;
34308
34276
  }, [onBeforeReconnect]);
34309
- const hadConnectionBeforeRef = useRef44(false);
34310
- const getNatsWsUrlRef = useRef44(getNatsWsUrl);
34311
- useEffect51(() => {
34277
+ const hadConnectionBeforeRef = useRef45(false);
34278
+ const getNatsWsUrlRef = useRef45(getNatsWsUrl);
34279
+ useEffect52(() => {
34312
34280
  getNatsWsUrlRef.current = getNatsWsUrl;
34313
34281
  }, [getNatsWsUrl]);
34314
- const reconnectionBackoffRef = useRef44(reconnectionBackoff);
34315
- useEffect51(() => {
34282
+ const reconnectionBackoffRef = useRef45(reconnectionBackoff);
34283
+ useEffect52(() => {
34316
34284
  reconnectionBackoffRef.current = reconnectionBackoff;
34317
34285
  }, [reconnectionBackoff]);
34318
- const acquireClient = useCallback32((url) => {
34319
- if (shared2?.wsUrl !== url) {
34320
- if (shared2) {
34321
- shared2.closeTimer && clearTimeout(shared2.closeTimer);
34322
- const old = shared2;
34323
- shared2 = null;
34324
- void old.client.close().catch(() => {
34325
- });
34326
- }
34327
- const { name = "openframe-frontend", user = "machine", pass = "" } = clientConfig;
34328
- const client = createNatsClient({
34329
- servers: url,
34330
- name,
34331
- user,
34332
- pass,
34333
- connectTimeoutMs: NETWORK_CONFIG.CONNECT_TIMEOUT_MS,
34334
- reconnect: false,
34335
- pingIntervalMs: NETWORK_CONFIG.PING_INTERVAL_MS,
34336
- maxPingOut: NETWORK_CONFIG.MAX_PING_OUT
34337
- });
34338
- shared2 = { wsUrl: url, client, connectPromise: null, refCount: 0, closeTimer: null, retryTimer: null };
34339
- }
34340
- shared2.refCount += 1;
34341
- shared2.closeTimer && clearTimeout(shared2.closeTimer);
34342
- shared2.closeTimer = null;
34343
- return shared2;
34286
+ const clientConfigRef = useRef45(clientConfig);
34287
+ useEffect52(() => {
34288
+ clientConfigRef.current = clientConfig;
34344
34289
  }, [clientConfig]);
34345
- const releaseClient = useCallback32((url) => {
34346
- if (!shared2 || shared2.wsUrl !== url) return;
34347
- shared2.refCount = Math.max(0, shared2.refCount - 1);
34348
- if (shared2.refCount > 0) return;
34349
- shared2.closeTimer = setTimeout(() => {
34350
- const s = shared2;
34351
- shared2 = null;
34352
- if (s) {
34353
- if (s.retryTimer) {
34354
- clearTimeout(s.retryTimer);
34355
- s.retryTimer = null;
34356
- }
34357
- void s.client.close().catch(() => {
34358
- });
34359
- }
34360
- }, NETWORK_CONFIG.SHARED_CLOSE_DELAY_MS);
34361
- }, []);
34362
- const currentWsUrlRef = useRef44("");
34363
- useEffect51(() => {
34364
- const wsUrl = getNatsWsUrl();
34290
+ const currentWsUrlRef = useRef45("");
34291
+ const wsUrl = getNatsWsUrl();
34292
+ useEffect52(() => {
34365
34293
  if (!enabled || !wsUrl) {
34366
34294
  if (currentWsUrlRef.current && clientRef.current) {
34367
34295
  releaseClient(currentWsUrlRef.current);
@@ -34380,135 +34308,73 @@ function useNatsDialogSubscription({
34380
34308
  setIsConnected(false);
34381
34309
  }
34382
34310
  currentWsUrlRef.current = wsUrl;
34383
- const sharedConn = acquireClient(wsUrl);
34311
+ const cfg = clientConfigRef.current;
34312
+ const sharedConn = acquireClient(wsUrl, {
34313
+ name: cfg.name ?? "openframe-frontend",
34314
+ user: cfg.user ?? "machine",
34315
+ pass: cfg.pass ?? ""
34316
+ });
34384
34317
  const client = sharedConn.client;
34385
34318
  clientRef.current = client;
34386
- setIsConnected(false);
34387
- let closed = false;
34388
- let retryAttempt = 0;
34389
- function scheduleRetry() {
34390
- if (closed) return;
34391
- if (shared2 !== sharedConn) return;
34392
- if (sharedConn.retryTimer) {
34393
- clearTimeout(sharedConn.retryTimer);
34394
- sharedConn.retryTimer = null;
34395
- }
34396
- const cfg = reconnectionBackoffRef.current ?? {};
34397
- const fastRetries = cfg.fastRetries ?? 0;
34398
- const fastDelay = cfg.fastRetryDelayMs ?? NETWORK_CONFIG.RETRY_INITIAL_DELAY_MS;
34399
- const baseDelay = cfg.initialDelayMs ?? NETWORK_CONFIG.RETRY_INITIAL_DELAY_MS;
34400
- const maxDelay = cfg.maxDelayMs ?? NETWORK_CONFIG.RETRY_MAX_DELAY_MS;
34401
- const multiplier = cfg.multiplier ?? NETWORK_CONFIG.RETRY_BACKOFF_MULTIPLIER;
34402
- const delay2 = retryAttempt < fastRetries ? fastDelay : Math.min(baseDelay * multiplier ** (retryAttempt - fastRetries), maxDelay);
34403
- const jitteredDelay = delay2 * (0.5 + Math.random() * 0.5);
34404
- retryAttempt++;
34405
- sharedConn.retryTimer = setTimeout(async () => {
34406
- sharedConn.retryTimer = null;
34407
- if (closed) return;
34408
- if (shared2 !== sharedConn) return;
34409
- try {
34410
- await onBeforeReconnectRef.current?.();
34411
- } catch {
34412
- }
34413
- if (closed) return;
34414
- if (shared2 !== sharedConn) return;
34415
- const freshUrl = getNatsWsUrlRef.current();
34416
- if (freshUrl !== wsUrl) return;
34319
+ setIsConnected(client.isConnected());
34320
+ const tearDownSubscriptions = () => {
34321
+ subscriptionRefs.current.forEach((sub) => {
34417
34322
  try {
34418
- sharedConn.connectPromise = null;
34419
- sharedConn.connectPromise = client.connect();
34420
- await sharedConn.connectPromise;
34421
- if (!closed && shared2 === sharedConn) {
34422
- retryAttempt = 0;
34423
- setIsConnected(true);
34424
- }
34323
+ sub?.unsubscribe();
34425
34324
  } catch {
34426
- sharedConn.connectPromise = null;
34427
- if (!closed && shared2 === sharedConn) {
34428
- scheduleRetry();
34429
- }
34430
- }
34431
- }, jitteredDelay);
34432
- }
34433
- const unsubscribeStatus = client.onStatus((event) => {
34434
- const connected = event.status === "connected";
34435
- const disconnected = ["closed", "disconnected", "error"].includes(event.status);
34436
- if (connected) {
34437
- setIsConnected(true);
34438
- if (hadConnectionBeforeRef.current) {
34439
- setReconnectionCount((c) => c + 1);
34440
34325
  }
34441
- hadConnectionBeforeRef.current = true;
34442
- retryAttempt = 0;
34443
- onConnectRef.current?.();
34444
- }
34445
- if (disconnected) {
34446
- setIsConnected(false);
34447
- setIsSubscribed(false);
34448
- subscriptionRefs.current.forEach((sub) => {
34449
- try {
34450
- sub?.unsubscribe();
34451
- } catch {
34452
- }
34453
- });
34454
- subscriptionRefs.current.clear();
34455
- lastSubscribedDialogIdRef.current = null;
34456
- abortControllerRef.current?.abort();
34457
- abortControllerRef.current = null;
34458
- onDisconnectRef.current?.();
34459
- scheduleRetry();
34460
- }
34461
- });
34462
- (async () => {
34463
- try {
34464
- sharedConn.connectPromise || (sharedConn.connectPromise = client.connect());
34465
- await sharedConn.connectPromise;
34466
- if (!closed) {
34326
+ });
34327
+ subscriptionRefs.current.clear();
34328
+ lastSubscribedDialogIdRef.current = null;
34329
+ abortControllerRef.current?.abort();
34330
+ abortControllerRef.current = null;
34331
+ };
34332
+ const isDisconnectStatus = (status) => status === "closed" || status === "disconnected" || status === "error";
34333
+ const lifecycle = startConnectionLifecycle({
34334
+ conn: sharedConn,
34335
+ wsUrl,
34336
+ onBeforeReconnect: () => onBeforeReconnectRef.current?.(),
34337
+ backoff: reconnectionBackoffRef.current,
34338
+ getFreshUrl: () => getNatsWsUrlRef.current(),
34339
+ shouldRetryOn: isDisconnectStatus,
34340
+ onStatusChange: (status) => {
34341
+ if (status === "connected") {
34467
34342
  setIsConnected(true);
34343
+ if (hadConnectionBeforeRef.current) {
34344
+ setReconnectionCount((c) => c + 1);
34345
+ }
34468
34346
  hadConnectionBeforeRef.current = true;
34347
+ onConnectRef.current?.();
34469
34348
  }
34470
- } catch {
34471
- sharedConn.connectPromise = null;
34472
- if (!closed) {
34349
+ if (isDisconnectStatus(status)) {
34473
34350
  setIsConnected(false);
34351
+ setIsSubscribed(false);
34352
+ tearDownSubscriptions();
34474
34353
  onDisconnectRef.current?.();
34475
- scheduleRetry();
34476
34354
  }
34477
34355
  }
34478
- })();
34356
+ });
34479
34357
  return () => {
34480
- closed = true;
34358
+ lifecycle.stop();
34481
34359
  setIsConnected(false);
34482
34360
  setIsSubscribed(false);
34483
- unsubscribeStatus();
34484
- if (sharedConn.retryTimer) {
34485
- clearTimeout(sharedConn.retryTimer);
34486
- sharedConn.retryTimer = null;
34487
- }
34488
- subscriptionRefs.current.forEach((sub) => {
34489
- try {
34490
- sub?.unsubscribe();
34491
- } catch {
34492
- }
34493
- });
34494
- subscriptionRefs.current.clear();
34495
- lastSubscribedDialogIdRef.current = null;
34361
+ tearDownSubscriptions();
34496
34362
  if (clientRef.current && currentWsUrlRef.current) {
34497
34363
  releaseClient(currentWsUrlRef.current);
34498
34364
  clientRef.current = null;
34499
34365
  currentWsUrlRef.current = "";
34500
34366
  }
34501
34367
  };
34502
- }, [enabled, getNatsWsUrl, acquireClient, releaseClient]);
34368
+ }, [enabled, wsUrl]);
34503
34369
  const topicsKey = topics.join(",");
34504
- const lastSubscribedDialogIdRef = useRef44(null);
34505
- const isConnectedRef = useRef44(isConnected);
34506
- useEffect51(() => {
34370
+ const lastSubscribedDialogIdRef = useRef45(null);
34371
+ const isConnectedRef = useRef45(isConnected);
34372
+ useEffect52(() => {
34507
34373
  isConnectedRef.current = isConnected;
34508
34374
  }, [isConnected]);
34509
- const currentDialogIdRef = useRef44(null);
34510
- const abortControllerRef = useRef44(null);
34511
- useEffect51(() => {
34375
+ const currentDialogIdRef = useRef45(null);
34376
+ const abortControllerRef = useRef45(null);
34377
+ useEffect52(() => {
34512
34378
  currentDialogIdRef.current = dialogId;
34513
34379
  if (!enabled || !dialogId) {
34514
34380
  if (subscriptionRefs.current.size > 0) {
@@ -34589,7 +34455,7 @@ function useNatsDialogSubscription({
34589
34455
  abortControllerRef.current = null;
34590
34456
  };
34591
34457
  }, [enabled, dialogId, topicsKey, topics]);
34592
- useEffect51(() => {
34458
+ useEffect52(() => {
34593
34459
  if (!enabled || !currentDialogIdRef.current || !isConnected) {
34594
34460
  return;
34595
34461
  }
@@ -34639,7 +34505,7 @@ function buildNatsWsUrl(apiBaseUrl, options) {
34639
34505
  }
34640
34506
 
34641
34507
  // src/components/chat/hooks/use-realtime-chunk-processor.ts
34642
- import { useCallback as useCallback33, useRef as useRef45, useEffect as useEffect52 } from "react";
34508
+ import { useCallback as useCallback31, useRef as useRef46, useEffect as useEffect53 } from "react";
34643
34509
 
34644
34510
  // src/components/chat/utils/chunk-parser.ts
34645
34511
  function normalizeToolCalls(raw) {
@@ -35272,14 +35138,14 @@ function useRealtimeChunkProcessor(options) {
35272
35138
  // get the new batch UI; pass `false` explicitly to fall back to legacy.
35273
35139
  batchApprovalsEnabled = true
35274
35140
  } = options;
35275
- const accumulatorRef = useRef45(
35141
+ const accumulatorRef = useRef46(
35276
35142
  createMessageSegmentAccumulator({
35277
35143
  onApprove: callbacks.onApprove,
35278
35144
  onReject: callbacks.onReject
35279
35145
  })
35280
35146
  );
35281
- const hasInitializedWithData = useRef45(false);
35282
- useEffect52(() => {
35147
+ const hasInitializedWithData = useRef46(false);
35148
+ useEffect53(() => {
35283
35149
  if (initialState && !hasInitializedWithData.current) {
35284
35150
  accumulatorRef.current.initializeWithState(initialState);
35285
35151
  if (initialState.escalatedApprovals) {
@@ -35292,10 +35158,10 @@ function useRealtimeChunkProcessor(options) {
35292
35158
  hasInitializedWithData.current = true;
35293
35159
  }
35294
35160
  }, [initialState, callbacks]);
35295
- const isInStreamRef = useRef45(false);
35296
- const hasEverStreamedRef = useRef45(false);
35297
- const pendingEscalatedRef = useRef45(/* @__PURE__ */ new Map());
35298
- const processChunk = useCallback33(
35161
+ const isInStreamRef = useRef46(false);
35162
+ const hasEverStreamedRef = useRef46(false);
35163
+ const pendingEscalatedRef = useRef46(/* @__PURE__ */ new Map());
35164
+ const processChunk = useCallback31(
35299
35165
  (chunk) => {
35300
35166
  if (!enableThinking && chunk && typeof chunk === "object" && chunk.type === MESSAGE_TYPE.THINKING) {
35301
35167
  return;
@@ -35509,21 +35375,21 @@ function useRealtimeChunkProcessor(options) {
35509
35375
  },
35510
35376
  [callbacks, displayApprovalTypes, approvalStatuses, initialState, enableThinking]
35511
35377
  );
35512
- const getSegments = useCallback33(() => {
35378
+ const getSegments = useCallback31(() => {
35513
35379
  return accumulatorRef.current.getSegments();
35514
35380
  }, []);
35515
- const reset = useCallback33(() => {
35381
+ const reset = useCallback31(() => {
35516
35382
  accumulatorRef.current.reset();
35517
35383
  pendingEscalatedRef.current.clear();
35518
35384
  hasInitializedWithData.current = false;
35519
35385
  }, []);
35520
- const updateApprovalStatus = useCallback33(
35386
+ const updateApprovalStatus = useCallback31(
35521
35387
  (requestId, status) => {
35522
35388
  return accumulatorRef.current.updateApprovalStatus(requestId, status);
35523
35389
  },
35524
35390
  []
35525
35391
  );
35526
- const getPendingApprovals = useCallback33(() => {
35392
+ const getPendingApprovals = useCallback31(() => {
35527
35393
  return new Map(pendingEscalatedRef.current);
35528
35394
  }, []);
35529
35395
  return {
@@ -35536,7 +35402,7 @@ function useRealtimeChunkProcessor(options) {
35536
35402
  }
35537
35403
 
35538
35404
  // src/components/chat/hooks/use-slash-commands.ts
35539
- import { useEffect as useEffect53, useState as useState75 } from "react";
35405
+ import { useEffect as useEffect54, useState as useState75 } from "react";
35540
35406
  async function fetchSlashCommands(prefix, signal, commandsUrl) {
35541
35407
  const url = new URL(commandsUrl, window.location.origin);
35542
35408
  if (prefix) url.searchParams.set("q", prefix);
@@ -35548,7 +35414,7 @@ async function fetchSlashCommands(prefix, signal, commandsUrl) {
35548
35414
  function useSlashCommands(prefix, commandsUrl) {
35549
35415
  const [commands, setCommands] = useState75([]);
35550
35416
  const [loading, setLoading] = useState75(false);
35551
- useEffect53(() => {
35417
+ useEffect54(() => {
35552
35418
  if (prefix == null) {
35553
35419
  setCommands([]);
35554
35420
  return;
@@ -35578,7 +35444,7 @@ function useSlashCommands(prefix, commandsUrl) {
35578
35444
  }
35579
35445
 
35580
35446
  // src/components/chat/hooks/use-chat-attachments.ts
35581
- import { useCallback as useCallback34, useMemo as useMemo26, useRef as useRef46, useState as useState76 } from "react";
35447
+ import { useCallback as useCallback32, useMemo as useMemo26, useRef as useRef47, useState as useState76 } from "react";
35582
35448
  import { fileTypeFromBlob } from "file-type";
35583
35449
  var CHAT_ATTACHMENTS_BUCKET = "chat-attachments";
35584
35450
  var CHAT_ATTACHMENTS_FOLDER = "chat";
@@ -35655,11 +35521,11 @@ function useChatAttachments() {
35655
35521
  const runtime = useRequiredChatRuntime();
35656
35522
  const uploadUrlEndpoint = runtime.endpoints.attachmentUploadUrl;
35657
35523
  const [attachments, setAttachments] = useState76([]);
35658
- const controllersRef = useRef46(/* @__PURE__ */ new Map());
35659
- const updateOne = useCallback34((id, patch) => {
35524
+ const controllersRef = useRef47(/* @__PURE__ */ new Map());
35525
+ const updateOne = useCallback32((id, patch) => {
35660
35526
  setAttachments((prev) => prev.map((a) => a.id === id ? { ...a, ...patch } : a));
35661
35527
  }, []);
35662
- const removeAttachment = useCallback34((id) => {
35528
+ const removeAttachment = useCallback32((id) => {
35663
35529
  const ctrl = controllersRef.current.get(id);
35664
35530
  if (ctrl) {
35665
35531
  ctrl.abort();
@@ -35667,12 +35533,12 @@ function useChatAttachments() {
35667
35533
  }
35668
35534
  setAttachments((prev) => prev.filter((a) => a.id !== id));
35669
35535
  }, []);
35670
- const clear = useCallback34(() => {
35536
+ const clear = useCallback32(() => {
35671
35537
  for (const ctrl of controllersRef.current.values()) ctrl.abort();
35672
35538
  controllersRef.current.clear();
35673
35539
  setAttachments([]);
35674
35540
  }, []);
35675
- const uploadOne = useCallback34(
35541
+ const uploadOne = useCallback32(
35676
35542
  async (att) => {
35677
35543
  const ctrl = controllersRef.current.get(att.id);
35678
35544
  try {
@@ -35744,9 +35610,9 @@ function useChatAttachments() {
35744
35610
  },
35745
35611
  [uploadUrlEndpoint, updateOne]
35746
35612
  );
35747
- const attachmentsRef = useRef46([]);
35613
+ const attachmentsRef = useRef47([]);
35748
35614
  attachmentsRef.current = attachments;
35749
- const addFiles = useCallback34(
35615
+ const addFiles = useCallback32(
35750
35616
  (files) => {
35751
35617
  const arr = Array.from(files);
35752
35618
  if (arr.length === 0) return;
@@ -35821,16 +35687,16 @@ function useChatAttachments() {
35821
35687
  }
35822
35688
 
35823
35689
  // src/components/chat/hooks/use-chat-attachment-image-gallery.tsx
35824
- import { useCallback as useCallback35, useEffect as useEffect54, useRef as useRef47, useState as useState77 } from "react";
35690
+ import { useCallback as useCallback33, useEffect as useEffect55, useRef as useRef48, useState as useState77 } from "react";
35825
35691
  import { jsx as jsx271 } from "react/jsx-runtime";
35826
35692
  var CLOSED = { isOpen: false, images: [], initialIndex: 0 };
35827
35693
  function useChatAttachmentImageGallery() {
35828
35694
  const runtime = useRequiredChatRuntime();
35829
35695
  const viewUrlPrefix = runtime.endpoints.attachmentViewUrlPrefix;
35830
- const panelRef = useRef47(null);
35696
+ const panelRef = useRef48(null);
35831
35697
  const [state, setState] = useState77(CLOSED);
35832
- const handleClose = useCallback35(() => setState(CLOSED), []);
35833
- useEffect54(() => {
35698
+ const handleClose = useCallback33(() => setState(CLOSED), []);
35699
+ useEffect55(() => {
35834
35700
  const root = panelRef.current;
35835
35701
  if (!root) return;
35836
35702
  const onClick = (ev) => {
@@ -35876,7 +35742,7 @@ function absolutize(prefix) {
35876
35742
  }
35877
35743
 
35878
35744
  // src/components/chat/hooks/use-chat-identity.ts
35879
- import { useEffect as useEffect55, useState as useState78 } from "react";
35745
+ import { useEffect as useEffect56, useState as useState78 } from "react";
35880
35746
  var ANON_DEFAULTS = {
35881
35747
  authTier: "anon",
35882
35748
  source: null,
@@ -35889,7 +35755,7 @@ function useChatIdentity() {
35889
35755
  const proxyEmail = getEmbedProxyAuth()?.email ?? null;
35890
35756
  const [data, setData] = useState78(ANON_DEFAULTS);
35891
35757
  const [isLoading, setIsLoading] = useState78(true);
35892
- useEffect55(() => {
35758
+ useEffect56(() => {
35893
35759
  let cancelled = false;
35894
35760
  const ctrl = new AbortController();
35895
35761
  setIsLoading(true);
@@ -35917,11 +35783,11 @@ function useChatIdentity() {
35917
35783
  }
35918
35784
 
35919
35785
  // src/components/chat/hooks/use-close-on-navigation.ts
35920
- import { useEffect as useEffect56, useRef as useRef48 } from "react";
35786
+ import { useEffect as useEffect57, useRef as useRef49 } from "react";
35921
35787
  function useCloseOnNavigation(close, pathname) {
35922
- const prevPathnameRef = useRef48(null);
35923
- const initializedRef = useRef48(false);
35924
- useEffect56(() => {
35788
+ const prevPathnameRef = useRef49(null);
35789
+ const initializedRef = useRef49(false);
35790
+ useEffect57(() => {
35925
35791
  if (!initializedRef.current) {
35926
35792
  initializedRef.current = true;
35927
35793
  prevPathnameRef.current = pathname;
@@ -35935,20 +35801,20 @@ function useCloseOnNavigation(close, pathname) {
35935
35801
  }
35936
35802
 
35937
35803
  // src/components/chat/hooks/use-chat.ts
35938
- import { useState as useState80, useCallback as useCallback37, useEffect as useEffect57, useRef as useRef50 } from "react";
35804
+ import { useState as useState80, useCallback as useCallback35, useEffect as useEffect58, useRef as useRef51 } from "react";
35939
35805
 
35940
35806
  // src/components/chat/hooks/use-sse.ts
35941
- import { useState as useState79, useCallback as useCallback36, useRef as useRef49 } from "react";
35807
+ import { useState as useState79, useCallback as useCallback34, useRef as useRef50 } from "react";
35942
35808
  function useSSE({ useMock = true, debugMode = false, streamFn } = {}) {
35943
35809
  const [isStreaming, setIsStreaming] = useState79(false);
35944
35810
  const [error, setError] = useState79(null);
35945
- const abortControllerRef = useRef49(null);
35946
- const fallbackStream = useCallback36(async function* () {
35811
+ const abortControllerRef = useRef50(null);
35812
+ const fallbackStream = useCallback34(async function* () {
35947
35813
  throw new Error(
35948
35814
  "[useSSE] No streamFn provided and `useMock: true` is no longer wired into the lib. Supply a `streamFn` (see `createDocStreamFn` in use-embedded-chat) or migrate the mock to your host code."
35949
35815
  );
35950
35816
  }, []);
35951
- const streamMessage = useCallback36(
35817
+ const streamMessage = useCallback34(
35952
35818
  async function* (message2, extra) {
35953
35819
  setIsStreaming(true);
35954
35820
  setError(null);
@@ -35978,13 +35844,13 @@ function useSSE({ useMock = true, debugMode = false, streamFn } = {}) {
35978
35844
  },
35979
35845
  [streamFn, fallbackStream]
35980
35846
  );
35981
- const abort = useCallback36(() => {
35847
+ const abort = useCallback34(() => {
35982
35848
  if (abortControllerRef.current) {
35983
35849
  abortControllerRef.current.abort();
35984
35850
  }
35985
35851
  setIsStreaming(false);
35986
35852
  }, []);
35987
- const reset = useCallback36(() => {
35853
+ const reset = useCallback34(() => {
35988
35854
  }, []);
35989
35855
  return {
35990
35856
  streamMessage,
@@ -36010,10 +35876,10 @@ function useChat({
36010
35876
  } = {}) {
36011
35877
  const [messages, setMessages] = useState80(() => initialMessages ?? []);
36012
35878
  const [isTyping, setIsTyping] = useState80(false);
36013
- const currentAssistantSegmentsRef = useRef50([]);
36014
- const onMessagesChangeRef = useRef50(onMessagesChange);
35879
+ const currentAssistantSegmentsRef = useRef51([]);
35880
+ const onMessagesChangeRef = useRef51(onMessagesChange);
36015
35881
  onMessagesChangeRef.current = onMessagesChange;
36016
- useEffect57(() => {
35882
+ useEffect58(() => {
36017
35883
  onMessagesChangeRef.current?.(messages);
36018
35884
  }, [messages]);
36019
35885
  const {
@@ -36027,10 +35893,10 @@ function useChat({
36027
35893
  debugMode,
36028
35894
  streamFn
36029
35895
  });
36030
- const addMessage = useCallback37((message2) => {
35896
+ const addMessage = useCallback35((message2) => {
36031
35897
  setMessages((prev) => [...prev, message2]);
36032
35898
  }, []);
36033
- const updateLastAssistantMessage = useCallback37((segments) => {
35899
+ const updateLastAssistantMessage = useCallback35((segments) => {
36034
35900
  setMessages((prev) => {
36035
35901
  const newMessages = [...prev];
36036
35902
  const lastMessage = newMessages[newMessages.length - 1];
@@ -36043,7 +35909,7 @@ function useChat({
36043
35909
  return newMessages;
36044
35910
  });
36045
35911
  }, []);
36046
- const sendMessage = useCallback37(
35912
+ const sendMessage = useCallback35(
36047
35913
  async (text, extra, options) => {
36048
35914
  const userMessage = {
36049
35915
  id: `user-${Date.now()}`,
@@ -36273,18 +36139,18 @@ function useChat({
36273
36139
  },
36274
36140
  [streamMessage, addMessage, updateLastAssistantMessage, assistantName, assistantAvatar]
36275
36141
  );
36276
- const handleQuickAction = useCallback37(
36142
+ const handleQuickAction = useCallback35(
36277
36143
  (actionText) => {
36278
36144
  sendMessage(actionText);
36279
36145
  },
36280
36146
  [sendMessage]
36281
36147
  );
36282
- const clearMessages = useCallback37(() => {
36148
+ const clearMessages = useCallback35(() => {
36283
36149
  setMessages([]);
36284
36150
  setIsTyping(false);
36285
36151
  reset();
36286
36152
  }, [reset]);
36287
- const stopMessage = useCallback37(() => {
36153
+ const stopMessage = useCallback35(() => {
36288
36154
  abort();
36289
36155
  setIsTyping(false);
36290
36156
  }, [abort]);
@@ -36302,7 +36168,7 @@ function useChat({
36302
36168
  }
36303
36169
 
36304
36170
  // src/components/chat/hooks/use-sse-chat-adapter.ts
36305
- import { useState as useState81, useEffect as useEffect58, useCallback as useCallback38, useMemo as useMemo27, useRef as useRef51 } from "react";
36171
+ import { useState as useState81, useEffect as useEffect59, useCallback as useCallback36, useMemo as useMemo27, useRef as useRef52 } from "react";
36306
36172
  function createEmptyTurnMeta() {
36307
36173
  return {
36308
36174
  provider: null,
@@ -36626,23 +36492,23 @@ function useSseChatAdapter(options) {
36626
36492
  );
36627
36493
  }
36628
36494
  const tableIdForDocumentType = options?.tableIdForDocumentType ?? defaultTableIdForDocumentType;
36629
- const persistedRef = useRef51(null);
36495
+ const persistedRef = useRef52(null);
36630
36496
  if (persistedRef.current === null) {
36631
36497
  pruneStaleChatStorage(source);
36632
36498
  persistedRef.current = loadPersistedChat(source) || { messages: [], sources: [], sendCount: 0 };
36633
36499
  }
36634
- const sourcesMapRef = useRef51(
36500
+ const sourcesMapRef = useRef52(
36635
36501
  new Map(persistedRef.current.sources)
36636
36502
  );
36637
- const refsMapRef = useRef51(
36503
+ const refsMapRef = useRef52(
36638
36504
  new Map(persistedRef.current.refs ?? [])
36639
36505
  );
36640
- const metaMapRef = useRef51(/* @__PURE__ */ new Map());
36641
- const messagesRef = useRef51(persistedRef.current.messages);
36642
- const sendCountRef = useRef51(persistedRef.current.sendCount);
36506
+ const metaMapRef = useRef52(/* @__PURE__ */ new Map());
36507
+ const messagesRef = useRef52(persistedRef.current.messages);
36508
+ const sendCountRef = useRef52(persistedRef.current.sendCount);
36643
36509
  const [streamingPhase, setStreamingPhase] = useState81("idle");
36644
36510
  const [metaTick, setMetaTick] = useState81(0);
36645
- const bumpMetaTick = useCallback38(() => setMetaTick((t) => t + 1), []);
36511
+ const bumpMetaTick = useCallback36(() => setMetaTick((t) => t + 1), []);
36646
36512
  const streamFn = useMemo27(
36647
36513
  () => createDocStreamFn(
36648
36514
  source,
@@ -36669,7 +36535,7 @@ function useSseChatAdapter(options) {
36669
36535
  () => /* @__PURE__ */ new Map()
36670
36536
  );
36671
36537
  const commandsUrl = runtime.endpoints.commandsUrl;
36672
- useEffect58(() => {
36538
+ useEffect59(() => {
36673
36539
  let cancelled = false;
36674
36540
  const ctrl = new AbortController();
36675
36541
  fetchSlashCommands("", ctrl.signal, commandsUrl).then((commands) => {
@@ -36705,7 +36571,7 @@ function useSseChatAdapter(options) {
36705
36571
  ctrl.abort();
36706
36572
  };
36707
36573
  }, [source, commandsUrl]);
36708
- const persist = useCallback38(
36574
+ const persist = useCallback36(
36709
36575
  (nextMessages) => {
36710
36576
  savePersistedChat(source, {
36711
36577
  messages: nextMessages,
@@ -36759,7 +36625,7 @@ function useSseChatAdapter(options) {
36759
36625
  ...m.hidden ? { hidden: true } : {}
36760
36626
  };
36761
36627
  });
36762
- const sendMessage = useCallback38(
36628
+ const sendMessage = useCallback36(
36763
36629
  async (text, options2) => {
36764
36630
  const {
36765
36631
  hidden,
@@ -36778,7 +36644,7 @@ function useSseChatAdapter(options) {
36778
36644
  },
36779
36645
  [chatSendMessage]
36780
36646
  );
36781
- const displayRef = useCallback38(
36647
+ const displayRef = useCallback36(
36782
36648
  (reference) => {
36783
36649
  const tableId = tableIdForDocumentType(reference.type);
36784
36650
  if (!tableId) {
@@ -36802,7 +36668,7 @@ function useSseChatAdapter(options) {
36802
36668
  },
36803
36669
  [sendMessage, source, cmdIdByTableId, tableIdForDocumentType]
36804
36670
  );
36805
- const discussRef = useCallback38(
36671
+ const discussRef = useCallback36(
36806
36672
  (reference) => {
36807
36673
  const tableId = tableIdForDocumentType(reference.type);
36808
36674
  if (!tableId) {
@@ -36826,11 +36692,11 @@ function useSseChatAdapter(options) {
36826
36692
  },
36827
36693
  [sendMessage, tableIdForDocumentType]
36828
36694
  );
36829
- const stopMessage = useCallback38(() => {
36695
+ const stopMessage = useCallback36(() => {
36830
36696
  chatStopMessage();
36831
36697
  setStreamingPhase("idle");
36832
36698
  }, [chatStopMessage]);
36833
- const clearMessages = useCallback38(() => {
36699
+ const clearMessages = useCallback36(() => {
36834
36700
  sourcesMapRef.current.clear();
36835
36701
  refsMapRef.current.clear();
36836
36702
  metaMapRef.current.clear();
@@ -36845,7 +36711,7 @@ function useSseChatAdapter(options) {
36845
36711
  }
36846
36712
  }
36847
36713
  }, [chatClearMessages, source, bumpMetaTick]);
36848
- useEffect58(() => {
36714
+ useEffect59(() => {
36849
36715
  if (!isTyping && !isStreaming && streamingPhase !== "idle") {
36850
36716
  setStreamingPhase("idle");
36851
36717
  }
@@ -36883,10 +36749,10 @@ function useSseChatAdapter(options) {
36883
36749
 
36884
36750
  // src/components/chat/hooks/use-nats-chat-adapter.ts
36885
36751
  import {
36886
- useCallback as useCallback39,
36887
- useEffect as useEffect59,
36752
+ useCallback as useCallback37,
36753
+ useEffect as useEffect60,
36888
36754
  useMemo as useMemo28,
36889
- useRef as useRef52,
36755
+ useRef as useRef53,
36890
36756
  useState as useState82
36891
36757
  } from "react";
36892
36758
  function nextId(role) {
@@ -36923,7 +36789,7 @@ function useNatsChatAdapter(config, options = {}) {
36923
36789
  } = config;
36924
36790
  const [messages, setMessages] = useState82([]);
36925
36791
  const [streamingPhase, setStreamingPhase] = useState82("idle");
36926
- const callbacksRef = useRef52({
36792
+ const callbacksRef = useRef53({
36927
36793
  onSegmentsUpdate: (segments) => {
36928
36794
  setMessages((prev) => updateTrailingAssistant(prev, segments));
36929
36795
  },
@@ -36949,7 +36815,7 @@ function useNatsChatAdapter(config, options = {}) {
36949
36815
  onChunkReceived: (chunk) => processChunk(chunk),
36950
36816
  fetchChunks
36951
36817
  });
36952
- useEffect59(() => {
36818
+ useEffect60(() => {
36953
36819
  if (!active || !dialogId) return;
36954
36820
  resetChunkTracking();
36955
36821
  startInitialBuffering();
@@ -36966,7 +36832,7 @@ function useNatsChatAdapter(config, options = {}) {
36966
36832
  catchupProcessChunk(payload, messageType);
36967
36833
  }
36968
36834
  });
36969
- const sendMessage = useCallback39(
36835
+ const sendMessage = useCallback37(
36970
36836
  async (text, sendOptions) => {
36971
36837
  const hidden = sendOptions?.hidden ?? false;
36972
36838
  setMessages((prev) => [
@@ -36989,17 +36855,17 @@ function useNatsChatAdapter(config, options = {}) {
36989
36855
  },
36990
36856
  [publishUserMessage, dialogId]
36991
36857
  );
36992
- const stopMessage = useCallback39(() => {
36858
+ const stopMessage = useCallback37(() => {
36993
36859
  setStreamingPhase("idle");
36994
36860
  }, []);
36995
- const clearMessages = useCallback39(() => {
36861
+ const clearMessages = useCallback37(() => {
36996
36862
  setMessages([]);
36997
36863
  resetAccumulator();
36998
36864
  setStreamingPhase("idle");
36999
36865
  }, [resetAccumulator]);
37000
- const discussRef = useCallback39((_ref) => {
36866
+ const discussRef = useCallback37((_ref) => {
37001
36867
  }, []);
37002
- const displayRef = useCallback39((_ref) => {
36868
+ const displayRef = useCallback37((_ref) => {
37003
36869
  }, []);
37004
36870
  const isLoading = streamingPhase !== "idle";
37005
36871
  return useMemo28(
@@ -37035,7 +36901,7 @@ function useNatsChatAdapter(config, options = {}) {
37035
36901
  }
37036
36902
 
37037
36903
  // src/components/chat/hooks/use-unified-chat.ts
37038
- import { useCallback as useCallback40, useMemo as useMemo29, useRef as useRef53 } from "react";
36904
+ import { useCallback as useCallback38, useMemo as useMemo29, useRef as useRef54 } from "react";
37039
36905
  var EMPTY_SSE_OPTIONS = {};
37040
36906
  function createDisabledNatsConfig() {
37041
36907
  return {
@@ -37050,7 +36916,7 @@ function createDisabledNatsConfig() {
37050
36916
  }
37051
36917
  function useUnifiedChat(options) {
37052
36918
  const { modes, activeMode } = options;
37053
- const disabledNatsRef = useRef53(null);
36919
+ const disabledNatsRef = useRef54(null);
37054
36920
  if (disabledNatsRef.current === null) {
37055
36921
  disabledNatsRef.current = createDisabledNatsConfig();
37056
36922
  }
@@ -37063,20 +36929,20 @@ function useUnifiedChat(options) {
37063
36929
  );
37064
36930
  void sseActive;
37065
36931
  const activeState = activeMode === "guide" ? sseState : natsState;
37066
- const stopMessage = useCallback40(() => activeState.stopMessage(), [activeState]);
37067
- const clearMessages = useCallback40(
36932
+ const stopMessage = useCallback38(() => activeState.stopMessage(), [activeState]);
36933
+ const clearMessages = useCallback38(
37068
36934
  () => activeState.clearMessages(),
37069
36935
  [activeState]
37070
36936
  );
37071
- const sendMessage = useCallback40(
36937
+ const sendMessage = useCallback38(
37072
36938
  (text, opts) => activeState.sendMessage(text, opts),
37073
36939
  [activeState]
37074
36940
  );
37075
- const discussRef = useCallback40(
36941
+ const discussRef = useCallback38(
37076
36942
  (ref) => activeState.discussRef(ref),
37077
36943
  [activeState]
37078
36944
  );
37079
- const displayRef = useCallback40(
36945
+ const displayRef = useCallback38(
37080
36946
  (ref) => activeState.displayRef(ref),
37081
36947
  [activeState]
37082
36948
  );
@@ -37594,7 +37460,7 @@ function chatChipClass({ tone, density = "chip", extra }) {
37594
37460
  }
37595
37461
 
37596
37462
  // src/components/chat/embeddable-chat.tsx
37597
- import { useCallback as useCallback42, useEffect as useEffect62, useMemo as useMemo31, useRef as useRef56, useState as useState84 } from "react";
37463
+ import { useCallback as useCallback40, useEffect as useEffect63, useMemo as useMemo31, useRef as useRef57, useState as useState84 } from "react";
37598
37464
 
37599
37465
  // node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
37600
37466
  import * as React109 from "react";
@@ -38021,7 +37887,7 @@ function EmbeddableChatInner({
38021
37887
  const commandsUrl = runtime.endpoints.commandsUrl;
38022
37888
  const { attachmentsEnabled, user: identityUser } = useChatIdentity();
38023
37889
  const viewUrlPrefix = runtime.endpoints.attachmentViewUrlPrefix;
38024
- useEffect62(() => {
37890
+ useEffect63(() => {
38025
37891
  if (process.env.NODE_ENV !== "production") {
38026
37892
  const hasOpen = open !== void 0;
38027
37893
  const hasHandler = onOpenChange !== void 0;
@@ -38042,8 +37908,8 @@ function EmbeddableChatInner({
38042
37908
  return !window.matchMedia("(pointer: coarse)").matches;
38043
37909
  });
38044
37910
  usePreventScroll({ isDisabled: !isOpen });
38045
- const navigatingAwayRef = useRef56(false);
38046
- useEffect62(() => {
37911
+ const navigatingAwayRef = useRef57(false);
37912
+ useEffect63(() => {
38047
37913
  if (!isOpen) return;
38048
37914
  if (typeof window === "undefined") return;
38049
37915
  if (!isIOS()) return;
@@ -38068,12 +37934,12 @@ function EmbeddableChatInner({
38068
37934
  window.scrollTo(0, scrollY);
38069
37935
  };
38070
37936
  }, [isOpen]);
38071
- const chatInputRef = useRef56(null);
37937
+ const chatInputRef = useRef57(null);
38072
37938
  const [commandsById, setCommandsById] = useState84(
38073
37939
  () => /* @__PURE__ */ new Map()
38074
37940
  );
38075
37941
  const [commandsLoaded, setCommandsLoaded] = useState84(false);
38076
- useEffect62(() => {
37942
+ useEffect63(() => {
38077
37943
  if (!isOpen) return;
38078
37944
  let cancelled = false;
38079
37945
  const ctrl = new AbortController();
@@ -38118,7 +37984,7 @@ function EmbeddableChatInner({
38118
37984
  const initialActiveMode = controlledActiveMode ?? defaultActiveMode ?? (effectiveModes.guide ? "guide" : "mingo");
38119
37985
  const [uncontrolledActiveMode, setUncontrolledActiveMode] = useState84(initialActiveMode);
38120
37986
  const activeMode = controlledActiveMode ?? uncontrolledActiveMode;
38121
- const handleActiveModeChange = useCallback42(
37987
+ const handleActiveModeChange = useCallback40(
38122
37988
  (next) => {
38123
37989
  if (controlledActiveMode === void 0) {
38124
37990
  setUncontrolledActiveMode(next);
@@ -38154,8 +38020,8 @@ function EmbeddableChatInner({
38154
38020
  } = useChatAttachments();
38155
38021
  const { panelRef: galleryPanelRef, modal: galleryModal } = useChatAttachmentImageGallery();
38156
38022
  const resolvedBaseRoute = baseRoute || (source === "flamingo" ? "/knowledge-base" : "/data-room");
38157
- const handleClose = useCallback42(() => setIsOpen(false), [setIsOpen]);
38158
- const handleNavigationClose = useCallback42(() => {
38023
+ const handleClose = useCallback40(() => setIsOpen(false), [setIsOpen]);
38024
+ const handleNavigationClose = useCallback40(() => {
38159
38025
  navigatingAwayRef.current = true;
38160
38026
  setIsOpen(false);
38161
38027
  }, [setIsOpen]);
@@ -38163,7 +38029,7 @@ function EmbeddableChatInner({
38163
38029
  () => ({ closeChat: handleNavigationClose }),
38164
38030
  [handleNavigationClose]
38165
38031
  );
38166
- const renderEntityCard = useCallback42(
38032
+ const renderEntityCard = useCallback40(
38167
38033
  (reference) => renderChatInlineEntityCard(reference, {
38168
38034
  onDiscuss: discussRef,
38169
38035
  onDisplay: displayRef,
@@ -38186,7 +38052,7 @@ function EmbeddableChatInner({
38186
38052
  })),
38187
38053
  [rawMessages]
38188
38054
  );
38189
- const handleSend = useCallback42(
38055
+ const handleSend = useCallback40(
38190
38056
  (text) => {
38191
38057
  let augmentedText = text;
38192
38058
  if (readyAttachments.length > 0) {
@@ -38202,12 +38068,12 @@ function EmbeddableChatInner({
38202
38068
  },
38203
38069
  [sendMessage, readyAttachments, viewUrlPrefix, clearAttachments]
38204
38070
  );
38205
- const handleNewChat = useCallback42(() => {
38071
+ const handleNewChat = useCallback40(() => {
38206
38072
  clearMessages();
38207
38073
  }, [clearMessages]);
38208
- const handleOpen = useCallback42(() => setIsOpen(true), [setIsOpen]);
38074
+ const handleOpen = useCallback40(() => setIsOpen(true), [setIsOpen]);
38209
38075
  useCloseOnNavigation(handleNavigationClose, null);
38210
- useEffect62(() => {
38076
+ useEffect63(() => {
38211
38077
  const handler = (e) => {
38212
38078
  const detail = e.detail;
38213
38079
  if (!detail || detail.source !== source) return;
@@ -39221,4 +39087,4 @@ export {
39221
39087
  LogsList,
39222
39088
  assets
39223
39089
  };
39224
- //# sourceMappingURL=chunk-3E5ANY55.js.map
39090
+ //# sourceMappingURL=chunk-ZTJVRSN5.js.map