@flamingo-stack/openframe-frontend-core 0.0.488 → 0.0.489

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 (117) hide show
  1. package/dist/{chunk-FOQV6RCO.cjs → chunk-2IHN7NNB.cjs} +29 -29
  2. package/dist/{chunk-FOQV6RCO.cjs.map → chunk-2IHN7NNB.cjs.map} +1 -1
  3. package/dist/{chunk-GQX6LFFA.cjs → chunk-2RNJYJWO.cjs} +42 -42
  4. package/dist/{chunk-GQX6LFFA.cjs.map → chunk-2RNJYJWO.cjs.map} +1 -1
  5. package/dist/{chunk-RZSA6MZL.cjs → chunk-3OIB763B.cjs} +15 -15
  6. package/dist/{chunk-RZSA6MZL.cjs.map → chunk-3OIB763B.cjs.map} +1 -1
  7. package/dist/{chunk-LLWBPPZ4.js → chunk-5VSEMWWE.js} +6 -6
  8. package/dist/{chunk-DX6AOHNU.cjs → chunk-5YMY4BAW.cjs} +77 -77
  9. package/dist/{chunk-DX6AOHNU.cjs.map → chunk-5YMY4BAW.cjs.map} +1 -1
  10. package/dist/{chunk-KFQXO7QB.js → chunk-6GT557KN.js} +1 -1
  11. package/dist/chunk-6GT557KN.js.map +1 -0
  12. package/dist/{chunk-3BFX6HJM.js → chunk-B4YR342L.js} +6 -6
  13. package/dist/{chunk-SCCTJ2UI.js → chunk-BGWDDB7Y.js} +4 -4
  14. package/dist/{chunk-A7IPON2V.cjs → chunk-BIKOJ4FH.cjs} +5 -5
  15. package/dist/{chunk-A7IPON2V.cjs.map → chunk-BIKOJ4FH.cjs.map} +1 -1
  16. package/dist/{chunk-PNXNWGBY.js → chunk-EU6QNO4S.js} +2 -2
  17. package/dist/{chunk-F6BYUO5U.js → chunk-FKPXFTZT.js} +3 -3
  18. package/dist/{chunk-EUYIFALO.cjs → chunk-H3YRJ3LZ.cjs} +14 -14
  19. package/dist/{chunk-EUYIFALO.cjs.map → chunk-H3YRJ3LZ.cjs.map} +1 -1
  20. package/dist/{chunk-5RXKOGH6.cjs → chunk-IN4IO7BL.cjs} +386 -327
  21. package/dist/chunk-IN4IO7BL.cjs.map +1 -0
  22. package/dist/{chunk-V3CNNMY3.cjs → chunk-J7H32E3R.cjs} +18 -18
  23. package/dist/{chunk-V3CNNMY3.cjs.map → chunk-J7H32E3R.cjs.map} +1 -1
  24. package/dist/{chunk-AJNDDXKC.js → chunk-K7MNWYYI.js} +3 -3
  25. package/dist/{chunk-PECGZWQR.cjs → chunk-KP5KRRD6.cjs} +3 -3
  26. package/dist/{chunk-PECGZWQR.cjs.map → chunk-KP5KRRD6.cjs.map} +1 -1
  27. package/dist/{chunk-2B6773QM.cjs → chunk-LILQJ3UZ.cjs} +1 -1
  28. package/dist/chunk-LILQJ3UZ.cjs.map +1 -0
  29. package/dist/{chunk-H7JX2BG7.cjs → chunk-LLEDO4P7.cjs} +75 -75
  30. package/dist/{chunk-H7JX2BG7.cjs.map → chunk-LLEDO4P7.cjs.map} +1 -1
  31. package/dist/{chunk-AHDJMEEN.js → chunk-N4MTNTSX.js} +7 -7
  32. package/dist/{chunk-KLYHZRAD.js → chunk-PB3BTZDU.js} +2 -2
  33. package/dist/{chunk-YEEHB4T6.cjs → chunk-RO7Q56ZK.cjs} +40 -40
  34. package/dist/{chunk-YEEHB4T6.cjs.map → chunk-RO7Q56ZK.cjs.map} +1 -1
  35. package/dist/{chunk-CWQACI4Z.js → chunk-RW2LPL72.js} +2 -2
  36. package/dist/{chunk-HQYJINFV.js → chunk-TWGYBXYV.js} +4 -4
  37. package/dist/{chunk-YJSKQ2ZV.js → chunk-VL4LUO32.js} +3 -3
  38. package/dist/{chunk-FZOBQG6M.cjs → chunk-VLOE7MI2.cjs} +35 -35
  39. package/dist/{chunk-FZOBQG6M.cjs.map → chunk-VLOE7MI2.cjs.map} +1 -1
  40. package/dist/{chunk-S52LJNMU.js → chunk-W6ZUOWSB.js} +7 -7
  41. package/dist/{chunk-PXF5J24T.js → chunk-X2YF5TJS.js} +2 -2
  42. package/dist/{chunk-77DFPD35.js → chunk-YMJZOANX.js} +268 -209
  43. package/dist/chunk-YMJZOANX.js.map +1 -0
  44. package/dist/{chunk-SIKCXKGB.cjs → chunk-Z7Y63IFU.cjs} +7 -7
  45. package/dist/{chunk-SIKCXKGB.cjs.map → chunk-Z7Y63IFU.cjs.map} +1 -1
  46. package/dist/{chunk-EYEIVYYF.cjs → chunk-ZIAS5NNL.cjs} +7 -7
  47. package/dist/{chunk-EYEIVYYF.cjs.map → chunk-ZIAS5NNL.cjs.map} +1 -1
  48. package/dist/components/case-studies/index.cjs +10 -10
  49. package/dist/components/case-studies/index.js +4 -4
  50. package/dist/components/chat/hooks/use-chat-history-hydration.d.ts +47 -0
  51. package/dist/components/chat/hooks/use-chat-history-hydration.d.ts.map +1 -0
  52. package/dist/components/chat/hooks/use-chat.d.ts +1 -0
  53. package/dist/components/chat/hooks/use-chat.d.ts.map +1 -1
  54. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +4 -0
  55. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  56. package/dist/components/chat/index.cjs +4 -4
  57. package/dist/components/chat/index.js +3 -3
  58. package/dist/components/chat/types/unified-chat-state.types.d.ts +5 -0
  59. package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
  60. package/dist/components/chat/utils/chat-conversation-storage.d.ts +34 -0
  61. package/dist/components/chat/utils/chat-conversation-storage.d.ts.map +1 -0
  62. package/dist/components/contact/index.cjs +5 -5
  63. package/dist/components/contact/index.js +4 -4
  64. package/dist/components/docs/index.cjs +7 -7
  65. package/dist/components/docs/index.js +6 -6
  66. package/dist/components/embeds/index.cjs +5 -5
  67. package/dist/components/embeds/index.js +4 -4
  68. package/dist/components/faq/index.cjs +6 -6
  69. package/dist/components/faq/index.js +5 -5
  70. package/dist/components/features/index.cjs +4 -4
  71. package/dist/components/features/index.js +3 -3
  72. package/dist/components/help-center-pages/index.cjs +23 -23
  73. package/dist/components/help-center-pages/index.js +14 -14
  74. package/dist/components/index.cjs +140 -140
  75. package/dist/components/index.js +12 -12
  76. package/dist/components/navigation/index.cjs +4 -4
  77. package/dist/components/navigation/index.js +3 -3
  78. package/dist/components/onboarding-guides/index.cjs +8 -8
  79. package/dist/components/onboarding-guides/index.js +7 -7
  80. package/dist/components/related-content/index.cjs +6 -6
  81. package/dist/components/related-content/index.js +5 -5
  82. package/dist/components/tickets/index.cjs +7 -7
  83. package/dist/components/tickets/index.js +6 -6
  84. package/dist/components/ui/index.cjs +4 -4
  85. package/dist/components/ui/index.js +3 -3
  86. package/dist/contexts/chat-runtime-context.d.ts +8 -0
  87. package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
  88. package/dist/contexts/index.cjs +2 -2
  89. package/dist/contexts/index.js +1 -1
  90. package/dist/hooks/index.cjs +3 -3
  91. package/dist/hooks/index.js +2 -2
  92. package/dist/index.cjs +4 -4
  93. package/dist/index.js +3 -3
  94. package/package.json +1 -1
  95. package/src/components/chat/hooks/use-chat-history-hydration.ts +142 -0
  96. package/src/components/chat/hooks/use-chat.ts +12 -0
  97. package/src/components/chat/hooks/use-sse-chat-adapter.ts +109 -162
  98. package/src/components/chat/types/unified-chat-state.types.ts +6 -0
  99. package/src/components/chat/utils/chat-conversation-storage.ts +83 -0
  100. package/src/contexts/chat-runtime-context.tsx +8 -0
  101. package/dist/chunk-2B6773QM.cjs.map +0 -1
  102. package/dist/chunk-5RXKOGH6.cjs.map +0 -1
  103. package/dist/chunk-77DFPD35.js.map +0 -1
  104. package/dist/chunk-KFQXO7QB.js.map +0 -1
  105. /package/dist/{chunk-LLWBPPZ4.js.map → chunk-5VSEMWWE.js.map} +0 -0
  106. /package/dist/{chunk-3BFX6HJM.js.map → chunk-B4YR342L.js.map} +0 -0
  107. /package/dist/{chunk-SCCTJ2UI.js.map → chunk-BGWDDB7Y.js.map} +0 -0
  108. /package/dist/{chunk-PNXNWGBY.js.map → chunk-EU6QNO4S.js.map} +0 -0
  109. /package/dist/{chunk-F6BYUO5U.js.map → chunk-FKPXFTZT.js.map} +0 -0
  110. /package/dist/{chunk-AJNDDXKC.js.map → chunk-K7MNWYYI.js.map} +0 -0
  111. /package/dist/{chunk-AHDJMEEN.js.map → chunk-N4MTNTSX.js.map} +0 -0
  112. /package/dist/{chunk-KLYHZRAD.js.map → chunk-PB3BTZDU.js.map} +0 -0
  113. /package/dist/{chunk-CWQACI4Z.js.map → chunk-RW2LPL72.js.map} +0 -0
  114. /package/dist/{chunk-HQYJINFV.js.map → chunk-TWGYBXYV.js.map} +0 -0
  115. /package/dist/{chunk-YJSKQ2ZV.js.map → chunk-VL4LUO32.js.map} +0 -0
  116. /package/dist/{chunk-S52LJNMU.js.map → chunk-W6ZUOWSB.js.map} +0 -0
  117. /package/dist/{chunk-PXF5J24T.js.map → chunk-X2YF5TJS.js.map} +0 -0
@@ -34,7 +34,7 @@ import {
34
34
  useResetOnPageHidden,
35
35
  useSuppressCloneFocus,
36
36
  useToast
37
- } from "./chunk-KLYHZRAD.js";
37
+ } from "./chunk-PB3BTZDU.js";
38
38
  import {
39
39
  AlertCircleIcon,
40
40
  AnthropicLogoGreyIcon,
@@ -160,7 +160,7 @@ import {
160
160
  import {
161
161
  useChatRuntime,
162
162
  useRequiredChatRuntime
163
- } from "./chunk-KFQXO7QB.js";
163
+ } from "./chunk-6GT557KN.js";
164
164
  import {
165
165
  dynamic
166
166
  } from "./chunk-EL5YVPD5.js";
@@ -51609,6 +51609,9 @@ function useChat({
51609
51609
  setIsTyping(false);
51610
51610
  reset();
51611
51611
  }, [reset]);
51612
+ const hydrateMessages = useCallback53((history) => {
51613
+ setMessages((prev) => prev.length === 0 ? history : [...history, ...prev]);
51614
+ }, []);
51612
51615
  const stopMessage = useCallback53(() => {
51613
51616
  abort();
51614
51617
  setIsTyping(false);
@@ -51622,12 +51625,125 @@ function useChat({
51622
51625
  stopMessage,
51623
51626
  handleQuickAction,
51624
51627
  clearMessages,
51628
+ hydrateMessages,
51625
51629
  hasMessages: messages.length > 0
51626
51630
  };
51627
51631
  }
51628
51632
 
51629
51633
  // src/components/chat/hooks/use-sse-chat-adapter.ts
51630
- import { useState as useState122, useEffect as useEffect91, useCallback as useCallback54, useMemo as useMemo48, useRef as useRef77 } from "react";
51634
+ import { useState as useState123, useEffect as useEffect92, useCallback as useCallback54, useMemo as useMemo48, useRef as useRef78 } from "react";
51635
+
51636
+ // src/components/chat/utils/chat-conversation-storage.ts
51637
+ var STORAGE_KEY2 = "conversation";
51638
+ var namespaceFor = (source) => {
51639
+ const base = `mingo-chat-${source}`;
51640
+ const auth = getEmbedProxyAuth();
51641
+ return auth?.email ? `${base}-u-${encodeURIComponent(auth.email.toLowerCase())}` : base;
51642
+ };
51643
+ function createChatConversationStorage(source) {
51644
+ return createLocalStorageAdapter({
51645
+ key: STORAGE_KEY2,
51646
+ namespace: () => namespaceFor(source),
51647
+ validate: (parsed) => !!parsed && typeof parsed.conversationId === "string" && parsed.conversationId.length > 0,
51648
+ logTag: "[chat-conversation-storage]"
51649
+ });
51650
+ }
51651
+ function pruneStaleChatConversationStorage(source) {
51652
+ if (typeof window === "undefined") return;
51653
+ try {
51654
+ const base = `mingo-chat-${source}`;
51655
+ const currentKey = `${namespaceFor(source)}.${STORAGE_KEY2}`;
51656
+ const ownedKey = (k) => k === base || // retired raw key (pre-adapter shape)
51657
+ k === `${base}.${STORAGE_KEY2}` || // current no-identity shape
51658
+ k.startsWith(`${base}-u-`) || // per-identity shapes (current + retired)
51659
+ k.startsWith(`${base}-v`);
51660
+ const toRemove = [];
51661
+ for (let i = 0; i < window.localStorage.length; i++) {
51662
+ const k = window.localStorage.key(i);
51663
+ if (!k) continue;
51664
+ if (ownedKey(k) && k !== currentKey) toRemove.push(k);
51665
+ }
51666
+ for (const k of toRemove) {
51667
+ window.localStorage.removeItem(k);
51668
+ }
51669
+ } catch {
51670
+ }
51671
+ }
51672
+
51673
+ // src/components/chat/hooks/use-chat-history-hydration.ts
51674
+ import { useEffect as useEffect91, useRef as useRef77, useState as useState122 } from "react";
51675
+ function useChatHistoryHydration({
51676
+ active,
51677
+ source,
51678
+ historyUrl,
51679
+ conversationIdRef,
51680
+ refsMapRef,
51681
+ sendCountRef,
51682
+ hydrateMessages,
51683
+ bumpMetaTick
51684
+ }) {
51685
+ const [isHydratingHistory, setIsHydratingHistory] = useState122(false);
51686
+ const hydratedKeyRef = useRef77(null);
51687
+ useEffect91(() => {
51688
+ if (!active) return;
51689
+ const conversationId = conversationIdRef.current;
51690
+ if (!conversationId) return;
51691
+ const key = `${source}:${conversationId}`;
51692
+ if (hydratedKeyRef.current === key) return;
51693
+ hydratedKeyRef.current = key;
51694
+ let cancelled = false;
51695
+ setIsHydratingHistory(true);
51696
+ (async () => {
51697
+ try {
51698
+ const res = await embedAuthedFetch(
51699
+ `${historyUrl}?conversationId=${encodeURIComponent(conversationId)}`,
51700
+ { method: "GET" }
51701
+ );
51702
+ if (!res.ok) return;
51703
+ const payload = await res.json().catch(() => null);
51704
+ const body = payload?.data ?? payload;
51705
+ const rows = Array.isArray(body?.messages) ? body.messages : [];
51706
+ if (cancelled || rows.length === 0) return;
51707
+ const hydrated = [];
51708
+ let userTurns = 0;
51709
+ for (const row of rows) {
51710
+ const role = row.role === "assistant" ? "assistant" : row.role === "user" ? "user" : null;
51711
+ if (!role) continue;
51712
+ const content = typeof row.content === "string" ? row.content : "";
51713
+ const hidden = role === "user" && (content === "" || content.startsWith(AUTO_CONTINUATION_DIRECTIVE_PREFIX));
51714
+ if (role === "user") {
51715
+ userTurns += 1;
51716
+ } else if (row.chat_refs && typeof row.chat_refs === "object") {
51717
+ refsMapRef.current.set(
51718
+ Math.max(0, userTurns - 1),
51719
+ row.chat_refs
51720
+ );
51721
+ }
51722
+ hydrated.push({
51723
+ id: `hydrated-${String(row.seq ?? hydrated.length)}`,
51724
+ role,
51725
+ content,
51726
+ ...typeof row.created_at === "string" ? { timestamp: new Date(row.created_at) } : {},
51727
+ ...hidden ? { hidden: true } : {}
51728
+ });
51729
+ }
51730
+ if (cancelled || hydrated.length === 0) return;
51731
+ sendCountRef.current = userTurns;
51732
+ hydrateMessages(hydrated);
51733
+ bumpMetaTick();
51734
+ } catch {
51735
+ } finally {
51736
+ if (!cancelled) setIsHydratingHistory(false);
51737
+ }
51738
+ })();
51739
+ return () => {
51740
+ cancelled = true;
51741
+ };
51742
+ }, [active, source, historyUrl, hydrateMessages, bumpMetaTick]);
51743
+ return { isHydratingHistory, hydratedKeyRef };
51744
+ }
51745
+
51746
+ // src/components/chat/hooks/use-sse-chat-adapter.ts
51631
51747
  function createEmptyTurnMeta() {
51632
51748
  return {
51633
51749
  provider: null,
@@ -51639,34 +51755,28 @@ function createEmptyTurnMeta() {
51639
51755
  breakdown: null,
51640
51756
  scrollAnchor: null,
51641
51757
  routedComplexity: null,
51642
- routedThinkingBudget: null
51758
+ routedThinkingBudget: null,
51759
+ conversationId: null
51643
51760
  };
51644
51761
  }
51645
51762
  function escapeThinkingTags(text) {
51646
51763
  return text.replace(/</g, "&lt;");
51647
51764
  }
51648
- function createDocStreamFn(source, endpoints, messagesRef, sourcesMapRef, refsMapRef, metaMapRef, setStreamingPhase, bumpMetaTick, sendCountRef) {
51765
+ function createDocStreamFn(source, endpoints, sourcesMapRef, refsMapRef, metaMapRef, setStreamingPhase, bumpMetaTick, sendCountRef, conversationIdRef, conversationStorage) {
51649
51766
  return async function* (message2, signal, extra) {
51650
- const currentMessages = messagesRef.current || [];
51651
- const apiMessages = [
51652
- ...currentMessages.filter((m) => (m.role === "user" || m.role === "assistant") && !m.hidden).map((m) => ({
51653
- role: m.role,
51654
- content: typeof m.content === "string" ? m.content : flattenAssistantContent(m.content)
51655
- })),
51656
- { role: "user", content: message2 }
51657
- ];
51658
51767
  const targetPath = extra?.approvalAction ? endpoints.approvalToolUrl : endpoints.chatStreamUrl;
51768
+ const conversationId = conversationIdRef.current;
51659
51769
  const requestBody = extra?.approvalAction ? {
51660
51770
  proposal_id: extra.approvalAction.proposalId,
51661
51771
  action: extra.approvalAction.action,
51662
- messages: currentMessages.filter((m) => (m.role === "user" || m.role === "assistant") && !m.hidden).map((m) => ({
51663
- role: m.role,
51664
- content: typeof m.content === "string" ? m.content : flattenAssistantContent(m.content)
51665
- }))
51772
+ // Always present here an approval can only happen inside an
51773
+ // established conversation (the proposal turn captured the id).
51774
+ conversationId
51666
51775
  } : {
51667
- messages: apiMessages,
51776
+ messages: [{ role: "user", content: message2 }],
51668
51777
  ...extra?.commandOverride ? { commandOverride: extra.commandOverride } : {},
51669
- ...extra?.pendingAttachments && extra.pendingAttachments.length > 0 ? { pendingAttachments: extra.pendingAttachments } : {}
51778
+ ...extra?.pendingAttachments && extra.pendingAttachments.length > 0 ? { pendingAttachments: extra.pendingAttachments } : {},
51779
+ ...conversationId ? { conversationId } : {}
51670
51780
  };
51671
51781
  const response = await embedAuthedFetch(targetPath, {
51672
51782
  method: "POST",
@@ -51829,6 +51939,14 @@ function createDocStreamFn(source, endpoints, messagesRef, sourcesMapRef, refsMa
51829
51939
  });
51830
51940
  bumpMetaTick();
51831
51941
  }
51942
+ if (typeof meta.conversationId === "string" && meta.conversationId) {
51943
+ if (conversationIdRef.current !== meta.conversationId) {
51944
+ conversationIdRef.current = meta.conversationId;
51945
+ conversationStorage.save({ conversationId: meta.conversationId });
51946
+ }
51947
+ mergeTurnMeta(metaMapRef, sendIdx, { conversationId: meta.conversationId });
51948
+ bumpMetaTick();
51949
+ }
51832
51950
  const parsedAnchor = parseScrollAnchor(meta.scrollAnchor);
51833
51951
  if (parsedAnchor !== null) {
51834
51952
  mergeTurnMeta(metaMapRef, sendIdx, { scrollAnchor: parsedAnchor });
@@ -51887,83 +52005,26 @@ function mergeTurnMeta(ref, sendIdx, partial) {
51887
52005
  );
51888
52006
  ref.current.set(sendIdx, { ...prev, ...filtered });
51889
52007
  }
51890
- var CHAT_STORAGE_VERSION = 1;
51891
52008
  var DEFAULT_CHAT_SOURCE = "embed";
51892
- var chatStorageKey = (source) => {
51893
- const base = `mingo-chat-${source}-v${CHAT_STORAGE_VERSION}`;
51894
- const auth = getEmbedProxyAuth();
51895
- if (auth?.email) {
51896
- return `${base}-u-${encodeURIComponent(auth.email.toLowerCase())}`;
51897
- }
51898
- return base;
51899
- };
51900
- function pruneStaleChatStorage(source) {
51901
- if (typeof window === "undefined") return;
51902
- try {
51903
- const currentKey = chatStorageKey(source);
51904
- const prefix = `mingo-chat-${source}-v${CHAT_STORAGE_VERSION}-u-`;
51905
- const legacy = `mingo-chat-${source}-v${CHAT_STORAGE_VERSION}`;
51906
- const toRemove = [];
51907
- for (let i = 0; i < window.localStorage.length; i++) {
51908
- const k = window.localStorage.key(i);
51909
- if (!k) continue;
51910
- if (!k.startsWith(prefix)) continue;
51911
- if (k === currentKey) continue;
51912
- if (k === legacy) continue;
51913
- toRemove.push(k);
51914
- }
51915
- for (const k of toRemove) {
51916
- window.localStorage.removeItem(k);
51917
- }
51918
- } catch {
51919
- }
51920
- }
51921
- function loadPersistedChat(source) {
51922
- if (typeof window === "undefined") return null;
51923
- try {
51924
- const raw = window.localStorage.getItem(chatStorageKey(source));
51925
- if (!raw) return null;
51926
- const parsed = JSON.parse(raw);
51927
- if (!parsed || !Array.isArray(parsed.messages)) return null;
51928
- for (const m of parsed.messages) {
51929
- if (typeof m.timestamp === "string") m.timestamp = new Date(m.timestamp);
51930
- if (m.role === "user" && !m.hidden && typeof m.content === "string" && m.content.startsWith(AUTO_CONTINUATION_DIRECTIVE_PREFIX)) {
51931
- m.hidden = true;
51932
- }
51933
- }
51934
- return parsed;
51935
- } catch {
51936
- return null;
51937
- }
51938
- }
51939
- function savePersistedChat(source, state) {
51940
- if (typeof window === "undefined") return;
51941
- try {
51942
- window.localStorage.setItem(chatStorageKey(source), JSON.stringify(state));
51943
- } catch {
51944
- }
51945
- }
51946
52009
  function useSseChatAdapter(options, runtimeOptions = {}) {
51947
52010
  const { active = true } = runtimeOptions;
51948
52011
  const runtime = useRequiredChatRuntime();
51949
52012
  const source = runtime.source || DEFAULT_CHAT_SOURCE;
51950
52013
  const tableIdForDocumentType = options?.tableIdForDocumentType ?? defaultTableIdForDocumentType;
51951
- const persistedRef = useRef77(null);
51952
- if (persistedRef.current === null) {
51953
- pruneStaleChatStorage(source);
51954
- persistedRef.current = loadPersistedChat(source) || { messages: [], sources: [], sendCount: 0 };
51955
- }
51956
- const sourcesMapRef = useRef77(
51957
- new Map(persistedRef.current.sources)
51958
- );
51959
- const refsMapRef = useRef77(
51960
- new Map(persistedRef.current.refs ?? [])
51961
- );
51962
- const metaMapRef = useRef77(/* @__PURE__ */ new Map());
51963
- const messagesRef = useRef77(persistedRef.current.messages);
51964
- const sendCountRef = useRef77(persistedRef.current.sendCount);
51965
- const [streamingPhase, setStreamingPhase] = useState122("idle");
51966
- const [metaTick, setMetaTick] = useState122(0);
52014
+ const conversationStorage = useMemo48(() => createChatConversationStorage(source), [source]);
52015
+ const conversationIdRef = useRef78(null);
52016
+ const restoredConversationRef = useRef78(false);
52017
+ if (!restoredConversationRef.current) {
52018
+ restoredConversationRef.current = true;
52019
+ pruneStaleChatConversationStorage(source);
52020
+ conversationIdRef.current = conversationStorage.load()?.conversationId ?? null;
52021
+ }
52022
+ const sourcesMapRef = useRef78(/* @__PURE__ */ new Map());
52023
+ const refsMapRef = useRef78(/* @__PURE__ */ new Map());
52024
+ const metaMapRef = useRef78(/* @__PURE__ */ new Map());
52025
+ const sendCountRef = useRef78(0);
52026
+ const [streamingPhase, setStreamingPhase] = useState123("idle");
52027
+ const [metaTick, setMetaTick] = useState123(0);
51967
52028
  const bumpMetaTick = useCallback54(() => setMetaTick((t) => t + 1), []);
51968
52029
  const streamFn = useMemo48(
51969
52030
  () => createDocStreamFn(
@@ -51972,19 +52033,21 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
51972
52033
  chatStreamUrl: runtime.endpoints.chatStreamUrl,
51973
52034
  approvalToolUrl: runtime.endpoints.approvalToolUrl
51974
52035
  },
51975
- messagesRef,
51976
52036
  sourcesMapRef,
51977
52037
  refsMapRef,
51978
52038
  metaMapRef,
51979
52039
  setStreamingPhase,
51980
52040
  bumpMetaTick,
51981
- sendCountRef
52041
+ sendCountRef,
52042
+ conversationIdRef,
52043
+ conversationStorage
51982
52044
  ),
51983
52045
  [
51984
52046
  source,
51985
52047
  runtime.endpoints.chatStreamUrl,
51986
52048
  runtime.endpoints.approvalToolUrl,
51987
- bumpMetaTick
52049
+ bumpMetaTick,
52050
+ conversationStorage
51988
52051
  ]
51989
52052
  );
51990
52053
  const commandsUrl = runtime.endpoints.commandsUrl;
@@ -52011,17 +52074,6 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
52011
52074
  }
52012
52075
  return map;
52013
52076
  }, [slashCommands]);
52014
- const persist = useCallback54(
52015
- (nextMessages) => {
52016
- savePersistedChat(source, {
52017
- messages: nextMessages,
52018
- sources: Array.from(sourcesMapRef.current.entries()),
52019
- refs: Array.from(refsMapRef.current.entries()),
52020
- sendCount: sendCountRef.current
52021
- });
52022
- },
52023
- [source]
52024
- );
52025
52077
  const {
52026
52078
  messages,
52027
52079
  isTyping,
@@ -52029,15 +52081,24 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
52029
52081
  sendMessage: chatSendMessage,
52030
52082
  stopMessage: chatStopMessage,
52031
52083
  clearMessages: chatClearMessages,
52084
+ hydrateMessages,
52032
52085
  hasMessages
52033
52086
  } = useChat({
52034
52087
  useMock: false,
52035
52088
  assistantName: "Mingo AI",
52036
- streamFn,
52037
- initialMessages: persistedRef.current.messages,
52038
- onMessagesChange: persist
52089
+ streamFn
52090
+ });
52091
+ const historyUrl = runtime.endpoints.chatHistoryUrl ?? `${runtime.endpoints.chatStreamUrl.replace(/\/+$/, "")}/history`;
52092
+ const { isHydratingHistory, hydratedKeyRef } = useChatHistoryHydration({
52093
+ active,
52094
+ source,
52095
+ historyUrl,
52096
+ conversationIdRef,
52097
+ refsMapRef,
52098
+ sendCountRef,
52099
+ hydrateMessages,
52100
+ bumpMetaTick
52039
52101
  });
52040
- messagesRef.current = messages;
52041
52102
  let sendIdx = -1;
52042
52103
  const docMessages = messages.map((m) => {
52043
52104
  const segments = Array.isArray(m.content) ? m.content : void 0;
@@ -52141,17 +52202,14 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
52141
52202
  refsMapRef.current.clear();
52142
52203
  metaMapRef.current.clear();
52143
52204
  sendCountRef.current = 0;
52205
+ conversationIdRef.current = null;
52206
+ conversationStorage.clear();
52207
+ hydratedKeyRef.current = null;
52144
52208
  setStreamingPhase("idle");
52145
52209
  bumpMetaTick();
52146
52210
  chatClearMessages();
52147
- if (typeof window !== "undefined") {
52148
- try {
52149
- window.localStorage.removeItem(chatStorageKey(source));
52150
- } catch {
52151
- }
52152
- }
52153
- }, [chatClearMessages, source, bumpMetaTick]);
52154
- useEffect91(() => {
52211
+ }, [chatClearMessages, conversationStorage, hydratedKeyRef, bumpMetaTick]);
52212
+ useEffect92(() => {
52155
52213
  if (!isTyping && !isStreaming && streamingPhase !== "idle") {
52156
52214
  setStreamingPhase("idle");
52157
52215
  }
@@ -52171,6 +52229,8 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
52171
52229
  stopMessage,
52172
52230
  clearMessages,
52173
52231
  streamingPhase,
52232
+ /** True while the mount-time rebuild from the server transcript runs. */
52233
+ isHydratingHistory,
52174
52234
  /** Provider key for the lib's `<ModelDisplay>` icon. */
52175
52235
  currentProvider: latestMeta?.provider ?? null,
52176
52236
  currentModelLabel: latestMeta?.modelLabel ?? null,
@@ -52185,12 +52245,11 @@ function useSseChatAdapter(options, runtimeOptions = {}) {
52185
52245
  * token counts). null until the trailing usage frame lands. */
52186
52246
  currentUsageBreakdown: latestMeta?.breakdown ?? null,
52187
52247
  // ─── Dialog management — stubs for v1 ────────────────────────────────
52188
- // Guide mode currently keeps its history in `localStorage` opaquely
52189
- // under the hood (`runtime.source` namespaced key). Surfacing that
52190
- // history as a structured dialog list is a follow-up; for now the
52191
- // shape is satisfied with empty defaults so the unified contract
52192
- // type-checks and EmbeddableChat hides sidebar affordances when
52193
- // `dialogs.length === 0`.
52248
+ // Guide mode keeps ONE server-side conversation per stored id
52249
+ // (`chat_conversations`, hydrated on mount). Surfacing multiple threads
52250
+ // as a structured dialog list is a follow-up; for now the shape is
52251
+ // satisfied with empty defaults so the unified contract type-checks and
52252
+ // EmbeddableChat hides sidebar affordances when `dialogs.length === 0`.
52194
52253
  dialogs: SSE_EMPTY_DIALOGS,
52195
52254
  activeDialogId: null,
52196
52255
  selectDialog: noopSelectDialog,
@@ -52233,10 +52292,10 @@ var noopRejectRequest = async (_id, _reason) => {
52233
52292
  // src/components/chat/hooks/use-nats-chat-adapter.ts
52234
52293
  import {
52235
52294
  useCallback as useCallback55,
52236
- useEffect as useEffect92,
52295
+ useEffect as useEffect93,
52237
52296
  useMemo as useMemo49,
52238
- useRef as useRef78,
52239
- useState as useState123
52297
+ useRef as useRef79,
52298
+ useState as useState124
52240
52299
  } from "react";
52241
52300
 
52242
52301
  // src/components/chat/utils/process-historical-messages.ts
@@ -52936,32 +52995,32 @@ function useNatsChatAdapter(config, options = {}) {
52936
52995
  modelLabel = null
52937
52996
  } = config;
52938
52997
  const isManagedMode = fetchDialogs !== void 0;
52939
- const [internalDialogId, setInternalDialogId] = useState123(null);
52998
+ const [internalDialogId, setInternalDialogId] = useState124(null);
52940
52999
  const dialogId = isManagedMode ? internalDialogId : controlledDialogId !== void 0 ? controlledDialogId : null;
52941
- const currentDialogIdRef = useRef78(dialogId);
53000
+ const currentDialogIdRef = useRef79(dialogId);
52942
53001
  currentDialogIdRef.current = dialogId;
52943
- const [messages, setMessages] = useState123([]);
52944
- const [streamingPhase, setStreamingPhase] = useState123("idle");
52945
- const streamingPhaseRef = useRef78(streamingPhase);
53002
+ const [messages, setMessages] = useState124([]);
53003
+ const [streamingPhase, setStreamingPhase] = useState124("idle");
53004
+ const streamingPhaseRef = useRef79(streamingPhase);
52946
53005
  streamingPhaseRef.current = streamingPhase;
52947
- const suppressAgentBusyRef = useRef78(0);
52948
- const adoptTrailingAssistantRef = useRef78(false);
52949
- const hasConnectedOnceRef = useRef78(false);
52950
- const seenParticipantSeqsRef = useRef78(/* @__PURE__ */ new Set());
52951
- const pendingEchoTextsRef = useRef78([]);
52952
- const [approvalStatuses, setApprovalStatuses] = useState123({});
52953
- const [dialogs, setDialogs] = useState123([]);
52954
- const [dialogsNextCursor, setDialogsNextCursor] = useState123(null);
52955
- const [isDialogsLoading, setIsDialogsLoading] = useState123(false);
52956
- const [dialogsError, setDialogsError] = useState123(false);
52957
- const [isCreatingDialog, setIsCreatingDialog] = useState123(false);
52958
- const [messagesNextCursor, setMessagesNextCursor] = useState123(null);
52959
- const [isMessagesLoading, setIsMessagesLoading] = useState123(false);
52960
- const [dialogTokenUsage, setDialogTokenUsage] = useState123(
53006
+ const suppressAgentBusyRef = useRef79(0);
53007
+ const adoptTrailingAssistantRef = useRef79(false);
53008
+ const hasConnectedOnceRef = useRef79(false);
53009
+ const seenParticipantSeqsRef = useRef79(/* @__PURE__ */ new Set());
53010
+ const pendingEchoTextsRef = useRef79([]);
53011
+ const [approvalStatuses, setApprovalStatuses] = useState124({});
53012
+ const [dialogs, setDialogs] = useState124([]);
53013
+ const [dialogsNextCursor, setDialogsNextCursor] = useState124(null);
53014
+ const [isDialogsLoading, setIsDialogsLoading] = useState124(false);
53015
+ const [dialogsError, setDialogsError] = useState124(false);
53016
+ const [isCreatingDialog, setIsCreatingDialog] = useState124(false);
53017
+ const [messagesNextCursor, setMessagesNextCursor] = useState124(null);
53018
+ const [isMessagesLoading, setIsMessagesLoading] = useState124(false);
53019
+ const [dialogTokenUsage, setDialogTokenUsage] = useState124(
52961
53020
  null
52962
53021
  );
52963
- const [liveModel, setLiveModel] = useState123(null);
52964
- const [connectionState, setConnectionState] = useState123("connecting");
53022
+ const [liveModel, setLiveModel] = useState124(null);
53023
+ const [connectionState, setConnectionState] = useState124("connecting");
52965
53024
  const handleApprove = useCallback55(
52966
53025
  async (requestId) => {
52967
53026
  if (!approveRequestCallback) return;
@@ -53001,9 +53060,9 @@ function useNatsChatAdapter(config, options = {}) {
53001
53060
  },
53002
53061
  [rejectRequestCallback]
53003
53062
  );
53004
- const handleApproveRef = useRef78(handleApprove);
53063
+ const handleApproveRef = useRef79(handleApprove);
53005
53064
  handleApproveRef.current = handleApprove;
53006
- const handleRejectRef = useRef78(handleReject);
53065
+ const handleRejectRef = useRef79(handleReject);
53007
53066
  handleRejectRef.current = handleReject;
53008
53067
  const accumApprove = useCallback55((requestId) => {
53009
53068
  if (!requestId) return;
@@ -53013,7 +53072,7 @@ function useNatsChatAdapter(config, options = {}) {
53013
53072
  if (!requestId) return;
53014
53073
  return handleRejectRef.current(requestId);
53015
53074
  }, []);
53016
- const callbacksRef = useRef78({
53075
+ const callbacksRef = useRef79({
53017
53076
  onSegmentsUpdate: (segments, meta) => {
53018
53077
  if (meta?.append && meta.isCompacting) {
53019
53078
  setMessages((prev) => upsertTrailingCompaction(prev, segments));
@@ -53231,7 +53290,7 @@ function useNatsChatAdapter(config, options = {}) {
53231
53290
  onChunkReceived: (chunk) => processChunk(chunk),
53232
53291
  fetchChunks
53233
53292
  });
53234
- const historyLoadSeqRef = useRef78(0);
53293
+ const historyLoadSeqRef = useRef79(0);
53235
53294
  const loadDialogHistory = useCallback55(
53236
53295
  async (id, cursor) => {
53237
53296
  if (!fetchDialogMessages) return;
@@ -53290,8 +53349,8 @@ function useNatsChatAdapter(config, options = {}) {
53290
53349
  isBufferingActive
53291
53350
  ]
53292
53351
  );
53293
- const prevDialogIdRef = useRef78(void 0);
53294
- useEffect92(() => {
53352
+ const prevDialogIdRef = useRef79(void 0);
53353
+ useEffect93(() => {
53295
53354
  if (prevDialogIdRef.current === dialogId) return;
53296
53355
  prevDialogIdRef.current = dialogId;
53297
53356
  historyLoadSeqRef.current += 1;
@@ -53308,7 +53367,7 @@ function useNatsChatAdapter(config, options = {}) {
53308
53367
  if (!active || !dialogId) return;
53309
53368
  void loadDialogHistory(dialogId);
53310
53369
  }, [active, dialogId, loadDialogHistory, resetAccumulator]);
53311
- useEffect92(() => {
53370
+ useEffect93(() => {
53312
53371
  if (!active || !dialogId) return;
53313
53372
  suppressAgentBusyRef.current += 1;
53314
53373
  resetChunkTracking();
@@ -53360,14 +53419,14 @@ function useNatsChatAdapter(config, options = {}) {
53360
53419
  })();
53361
53420
  }
53362
53421
  });
53363
- useEffect92(() => {
53422
+ useEffect93(() => {
53364
53423
  if (!active || !dialogId) {
53365
53424
  setConnectionState("connected");
53366
53425
  return;
53367
53426
  }
53368
53427
  setConnectionState("connecting");
53369
53428
  }, [active, dialogId]);
53370
- const initialDialogsLoadedRef = useRef78(false);
53429
+ const initialDialogsLoadedRef = useRef79(false);
53371
53430
  const loadDialogsPage = useCallback55(
53372
53431
  async (cursor) => {
53373
53432
  if (!fetchDialogs) return;
@@ -53399,7 +53458,7 @@ function useNatsChatAdapter(config, options = {}) {
53399
53458
  const reloadDialogs = useCallback55(() => {
53400
53459
  void loadDialogsPage();
53401
53460
  }, [loadDialogsPage]);
53402
- useEffect92(() => {
53461
+ useEffect93(() => {
53403
53462
  if (!fetchDialogs) return;
53404
53463
  if (!active) return;
53405
53464
  if (initialDialogsLoadedRef.current) return;
@@ -53642,7 +53701,7 @@ function useNatsChatAdapter(config, options = {}) {
53642
53701
  }
53643
53702
 
53644
53703
  // src/components/chat/hooks/use-unified-chat.ts
53645
- import { useCallback as useCallback56, useMemo as useMemo50, useRef as useRef79 } from "react";
53704
+ import { useCallback as useCallback56, useMemo as useMemo50, useRef as useRef80 } from "react";
53646
53705
  var EMPTY_SSE_OPTIONS = {};
53647
53706
  function createDisabledNatsConfig() {
53648
53707
  return {
@@ -53657,7 +53716,7 @@ function createDisabledNatsConfig() {
53657
53716
  }
53658
53717
  function useUnifiedChat(options) {
53659
53718
  const { modes, activeMode, mingoStateOverride } = options;
53660
- const disabledNatsRef = useRef79(null);
53719
+ const disabledNatsRef = useRef80(null);
53661
53720
  if (disabledNatsRef.current === null) {
53662
53721
  disabledNatsRef.current = createDisabledNatsConfig();
53663
53722
  }
@@ -53671,7 +53730,7 @@ function useUnifiedChat(options) {
53671
53730
  { active: natsActive }
53672
53731
  );
53673
53732
  const activeState = activeMode === "guide" ? sseState : mingoStateOverride ?? natsState;
53674
- const activeStateRef = useRef79(activeState);
53733
+ const activeStateRef = useRef80(activeState);
53675
53734
  activeStateRef.current = activeState;
53676
53735
  const stopMessage = useCallback56(() => activeStateRef.current.stopMessage(), []);
53677
53736
  const clearMessages = useCallback56(
@@ -54035,7 +54094,7 @@ function buildStreamFrames(messages) {
54035
54094
 
54036
54095
  // src/components/chat/embeddable-chat.tsx
54037
54096
  init_cn();
54038
- import { useCallback as useCallback58, useEffect as useEffect93, useMemo as useMemo52, useRef as useRef81, useState as useState125 } from "react";
54097
+ import { useCallback as useCallback58, useEffect as useEffect94, useMemo as useMemo52, useRef as useRef82, useState as useState126 } from "react";
54039
54098
  import * as DialogPrimitive5 from "@radix-ui/react-dialog";
54040
54099
  import { usePreventScroll as usePreventScroll6 } from "@react-aria/overlays";
54041
54100
  import { isIOS } from "@react-aria/utils";
@@ -54122,7 +54181,7 @@ init_button2();
54122
54181
  import { FileText as FileText8, MessageSquare as MessageSquare3 } from "lucide-react";
54123
54182
 
54124
54183
  // src/components/chat/hooks/use-chat-dialog-manager.ts
54125
- import { useCallback as useCallback57, useMemo as useMemo51, useRef as useRef80, useState as useState124 } from "react";
54184
+ import { useCallback as useCallback57, useMemo as useMemo51, useRef as useRef81, useState as useState125 } from "react";
54126
54185
  function useChatDialogManager({
54127
54186
  dialogs,
54128
54187
  activeDialogId,
@@ -54133,8 +54192,8 @@ function useChatDialogManager({
54133
54192
  fetchArchivedDialogs,
54134
54193
  unarchiveDialog
54135
54194
  }) {
54136
- const [renameTarget, setRenameTarget] = useState124(null);
54137
- const [archiveTarget, setArchiveTarget] = useState124(null);
54195
+ const [renameTarget, setRenameTarget] = useState125(null);
54196
+ const [archiveTarget, setArchiveTarget] = useState125(null);
54138
54197
  const handleConfirmRename = useCallback57(
54139
54198
  (name) => {
54140
54199
  if (renameTarget) void renameDialog(renameTarget.id, name);
@@ -54157,12 +54216,12 @@ function useChatDialogManager({
54157
54216
  }
54158
54217
  setArchiveTarget(null);
54159
54218
  }, [archiveTarget, archiveDialog, activeDialogId, clearMessages]);
54160
- const [archiveOpen, setArchiveOpen] = useState124(false);
54161
- const [archivedDialogs, setArchivedDialogs] = useState124([]);
54162
- const [archivedCursor, setArchivedCursor] = useState124(null);
54163
- const [archivedLoading, setArchivedLoading] = useState124(false);
54164
- const [archivedPending, setArchivedPending] = useState124(false);
54165
- const archivedRequestIdRef = useRef80(0);
54219
+ const [archiveOpen, setArchiveOpen] = useState125(false);
54220
+ const [archivedDialogs, setArchivedDialogs] = useState125([]);
54221
+ const [archivedCursor, setArchivedCursor] = useState125(null);
54222
+ const [archivedLoading, setArchivedLoading] = useState125(false);
54223
+ const [archivedPending, setArchivedPending] = useState125(false);
54224
+ const archivedRequestIdRef = useRef81(0);
54166
54225
  const loadArchivedPage = useCallback57(
54167
54226
  async (cursor) => {
54168
54227
  if (!fetchArchivedDialogs) return;
@@ -54203,10 +54262,10 @@ function useChatDialogManager({
54203
54262
  void loadArchivedPage();
54204
54263
  }, [loadArchivedPage]);
54205
54264
  const closeArchive = useCallback57(() => setArchiveOpen(false), []);
54206
- const [viewingArchivedId, setViewingArchivedId] = useState124(
54265
+ const [viewingArchivedId, setViewingArchivedId] = useState125(
54207
54266
  null
54208
54267
  );
54209
- const [openingDialogId, setOpeningDialogId] = useState124(null);
54268
+ const [openingDialogId, setOpeningDialogId] = useState125(null);
54210
54269
  const handleSelectDialog = useCallback57(
54211
54270
  (id) => {
54212
54271
  setViewingArchivedId(null);
@@ -54225,7 +54284,7 @@ function useChatDialogManager({
54225
54284
  },
54226
54285
  [selectDialog]
54227
54286
  );
54228
- const [restoreTarget, setRestoreTarget] = useState124(null);
54287
+ const [restoreTarget, setRestoreTarget] = useState125(null);
54229
54288
  const handleConfirmRestore = useCallback57(async () => {
54230
54289
  if (restoreTarget) {
54231
54290
  try {
@@ -54318,9 +54377,9 @@ var SPLIT_MIN_WIDTH = HISTORY_RAIL_WIDTH + CHAT_BLOCK_MIN_WIDTH;
54318
54377
  var RAIL_COLLAPSED_STORAGE_KEY = "mingo-chat-history-collapsed";
54319
54378
  var RAIL_ANIM_MS = 320;
54320
54379
  function useRailPresence(open) {
54321
- const [mounted, setMounted] = useState125(open);
54322
- const [active, setActive] = useState125(false);
54323
- useEffect93(() => {
54380
+ const [mounted, setMounted] = useState126(open);
54381
+ const [active, setActive] = useState126(false);
54382
+ useEffect94(() => {
54324
54383
  if (open) {
54325
54384
  setMounted(true);
54326
54385
  let raf2 = 0;
@@ -54538,7 +54597,7 @@ function SourceChips({
54538
54597
  onClose,
54539
54598
  onDiscuss
54540
54599
  }) {
54541
- const [expanded, setExpanded] = useState125(false);
54600
+ const [expanded, setExpanded] = useState126(false);
54542
54601
  if (cited.length === 0) {
54543
54602
  const fallback = uncited.slice(0, FALLBACK_TOP_RETRIEVED);
54544
54603
  if (fallback.length === 0) return null;
@@ -54646,7 +54705,7 @@ function EmbeddableChatInner({
54646
54705
  const commandsUrl = runtime.endpoints.commandsUrl;
54647
54706
  const { attachmentsEnabled, user: identityUser } = useChatIdentity();
54648
54707
  const viewUrlPrefix = runtime.endpoints.attachmentViewUrlPrefix;
54649
- useEffect93(() => {
54708
+ useEffect94(() => {
54650
54709
  if (process.env.NODE_ENV !== "production") {
54651
54710
  const hasOpen = open !== void 0;
54652
54711
  const hasHandler = onOpenChange !== void 0;
@@ -54662,13 +54721,13 @@ function EmbeddableChatInner({
54662
54721
  defaultProp: defaultOpen ?? false,
54663
54722
  onChange: onOpenChange
54664
54723
  });
54665
- const [autoFocusInput] = useState125(() => {
54724
+ const [autoFocusInput] = useState126(() => {
54666
54725
  if (typeof window === "undefined") return false;
54667
54726
  return !window.matchMedia("(pointer: coarse)").matches;
54668
54727
  });
54669
54728
  usePreventScroll6({ isDisabled: !isOpen || shellLess });
54670
- const navigatingAwayRef = useRef81(false);
54671
- useEffect93(() => {
54729
+ const navigatingAwayRef = useRef82(false);
54730
+ useEffect94(() => {
54672
54731
  if (!isOpen) return;
54673
54732
  if (shellLess) return;
54674
54733
  if (typeof window === "undefined") return;
@@ -54694,8 +54753,8 @@ function EmbeddableChatInner({
54694
54753
  window.scrollTo(0, scrollY);
54695
54754
  };
54696
54755
  }, [isOpen, shellLess]);
54697
- const chatInputRef = useRef81(null);
54698
- const [quickActionPreview, setQuickActionPreview] = useState125(null);
54756
+ const chatInputRef = useRef82(null);
54757
+ const [quickActionPreview, setQuickActionPreview] = useState126(null);
54699
54758
  const slashCommandsProp = useMemo52(
54700
54759
  () => ({
54701
54760
  fetchCommands: (prefix, signal) => fetchSlashCommands(prefix, signal, commandsUrl),
@@ -54738,7 +54797,7 @@ function EmbeddableChatInner({
54738
54797
  }, [mingoState, mingoDialogCapabilities, effectiveModes]);
54739
54798
  const hasMingoMode = !!effectiveModes.mingo || !!mingoState;
54740
54799
  const initialActiveMode = controlledActiveMode ?? defaultActiveMode ?? (effectiveModes.guide ? "guide" : "mingo");
54741
- const [uncontrolledActiveMode, setUncontrolledActiveMode] = useState125(initialActiveMode);
54800
+ const [uncontrolledActiveMode, setUncontrolledActiveMode] = useState126(initialActiveMode);
54742
54801
  const activeMode = controlledActiveMode ?? uncontrolledActiveMode;
54743
54802
  const handleActiveModeChange = useCallback58(
54744
54803
  (next) => {
@@ -54800,8 +54859,8 @@ function EmbeddableChatInner({
54800
54859
  hasMoreMessages,
54801
54860
  loadMoreMessages
54802
54861
  } = useUnifiedChat({ modes: effectiveModes, activeMode, mingoStateOverride: mingoState });
54803
- const guidePromptSentRef = useRef81(false);
54804
- useEffect93(() => {
54862
+ const guidePromptSentRef = useRef82(false);
54863
+ useEffect94(() => {
54805
54864
  if (!guidePendingPrompt) {
54806
54865
  guidePromptSentRef.current = false;
54807
54866
  return;
@@ -54822,15 +54881,15 @@ function EmbeddableChatInner({
54822
54881
  const { panelRef: galleryPanelRef, modal: galleryModal } = useChatAttachmentImageGallery();
54823
54882
  const contextMaxItems = contextPicker?.maxItems ?? 10;
54824
54883
  const contextPickerForMode = activeMode === "mingo" ? contextPicker : void 0;
54825
- const [contextItems, setContextItems] = useState125([]);
54826
- const [contextPickerOpen, setContextPickerOpen] = useState125(false);
54827
- const [mentionQuery, setMentionQuery] = useState125(null);
54828
- const mentionActiveRef = useRef81(false);
54829
- useEffect93(() => {
54884
+ const [contextItems, setContextItems] = useState126([]);
54885
+ const [contextPickerOpen, setContextPickerOpen] = useState126(false);
54886
+ const [mentionQuery, setMentionQuery] = useState126(null);
54887
+ const mentionActiveRef = useRef82(false);
54888
+ useEffect94(() => {
54830
54889
  mentionActiveRef.current = mentionQuery !== null;
54831
54890
  }, [mentionQuery]);
54832
- const mentionKeysRef = useRef81(/* @__PURE__ */ new Set());
54833
- useEffect93(() => {
54891
+ const mentionKeysRef = useRef82(/* @__PURE__ */ new Set());
54892
+ useEffect94(() => {
54834
54893
  setContextItems([]);
54835
54894
  setMentionQuery(null);
54836
54895
  mentionKeysRef.current.clear();
@@ -54926,7 +54985,7 @@ function EmbeddableChatInner({
54926
54985
  () => effectiveAssistantIcon ? /* @__PURE__ */ jsx369(EntityIcon, { icon: effectiveAssistantIcon, size: 24 }) : /* @__PURE__ */ jsx369(MingoIcon, { className: "h-6 w-6", cornerColor: "var(--ods-flamingo-cyan-base)" }),
54927
54986
  [effectiveAssistantIcon]
54928
54987
  );
54929
- const timestampCacheRef = useRef81(/* @__PURE__ */ new Map());
54988
+ const timestampCacheRef = useRef82(/* @__PURE__ */ new Map());
54930
54989
  const guideUserName = activeMode === "guide" ? [identityUser?.firstName, identityUser?.lastName].filter(Boolean).join(" ").trim() || identityUser?.name?.trim() || void 0 : void 0;
54931
54990
  const guideUserAvatar = activeMode === "guide" ? identityUser?.avatarUrl?.trim() || void 0 : void 0;
54932
54991
  const messages = useMemo52(() => {
@@ -55053,7 +55112,7 @@ function EmbeddableChatInner({
55053
55112
  });
55054
55113
  const handleOpen = useCallback58(() => setIsOpen(true), [setIsOpen]);
55055
55114
  useCloseOnNavigation(handleNavigationClose, null);
55056
- useEffect93(() => {
55115
+ useEffect94(() => {
55057
55116
  const handler = (e) => {
55058
55117
  const detail = e.detail;
55059
55118
  if (!detail || detail.source !== source) return;
@@ -55063,7 +55122,7 @@ function EmbeddableChatInner({
55063
55122
  window.addEventListener("ask-ai:open-with-ref", handler);
55064
55123
  return () => window.removeEventListener("ask-ai:open-with-ref", handler);
55065
55124
  }, [source, discussRef, setIsOpen]);
55066
- useEffect93(() => {
55125
+ useEffect94(() => {
55067
55126
  const handler = (e) => {
55068
55127
  const detail = e.detail;
55069
55128
  if (!detail || detail.source !== source) return;
@@ -55080,7 +55139,7 @@ function EmbeddableChatInner({
55080
55139
  const contentViewKey = hasConversation ? "conversation" : activeMode;
55081
55140
  const isGuideEmpty = !hasConversation && activeMode === "guide";
55082
55141
  const isQuickActionEmpty = !hasConversation && (activeMode === "guide" || activeMode === "mingo");
55083
- useEffect93(() => {
55142
+ useEffect94(() => {
55084
55143
  if (!isQuickActionEmpty) setQuickActionPreview(null);
55085
55144
  }, [isQuickActionEmpty]);
55086
55145
  const guideCanReturnToMingo = isGuideEmpty && hasMingoMode;
@@ -55122,10 +55181,10 @@ function EmbeddableChatInner({
55122
55181
  const uncited = sources.filter((s) => !seenOrder.has(s.index));
55123
55182
  return { cited, uncited };
55124
55183
  }, [lastAssistantMsg, chatLoading]);
55125
- const [portalHost, setPortalHost] = useState125(null);
55126
- const [panelWidth, setPanelWidth] = useState125(0);
55127
- const panelMeasureRef = useRef81(null);
55128
- useEffect93(() => {
55184
+ const [portalHost, setPortalHost] = useState126(null);
55185
+ const [panelWidth, setPanelWidth] = useState126(0);
55186
+ const panelMeasureRef = useRef82(null);
55187
+ useEffect94(() => {
55129
55188
  const el = panelMeasureRef.current;
55130
55189
  if (!el || typeof ResizeObserver === "undefined") return;
55131
55190
  const ro = new ResizeObserver((entries) => {
@@ -55136,8 +55195,8 @@ function EmbeddableChatInner({
55136
55195
  setPanelWidth(el.clientWidth);
55137
55196
  return () => ro.disconnect();
55138
55197
  }, []);
55139
- const [railCollapsed, setRailCollapsed] = useState125(false);
55140
- useEffect93(() => {
55198
+ const [railCollapsed, setRailCollapsed] = useState126(false);
55199
+ useEffect94(() => {
55141
55200
  try {
55142
55201
  if (window.localStorage.getItem(RAIL_COLLAPSED_STORAGE_KEY) === "1")
55143
55202
  setRailCollapsed(true);
@@ -55154,15 +55213,15 @@ function EmbeddableChatInner({
55154
55213
  return next;
55155
55214
  });
55156
55215
  }, []);
55157
- const [railSearchOpen, setRailSearchOpen] = useState125(false);
55216
+ const [railSearchOpen, setRailSearchOpen] = useState126(false);
55158
55217
  const splitEligible = activeMode === "mingo";
55159
55218
  const canSplit = panelWidth >= SPLIT_MIN_WIDTH;
55160
55219
  const wideMingo = splitEligible && canSplit && !previewMode;
55161
55220
  const splitActive = wideMingo && !railCollapsed;
55162
55221
  const railPresence = useRailPresence(splitActive);
55163
55222
  const showWideHeader = wideMingo || railPresence.mounted;
55164
- const [composeOpen, setComposeOpen] = useState125(false);
55165
- useEffect93(() => {
55223
+ const [composeOpen, setComposeOpen] = useState126(false);
55224
+ useEffect94(() => {
55166
55225
  if (hasConversation) setComposeOpen(false);
55167
55226
  }, [hasConversation]);
55168
55227
  const isMingoMode = activeMode === "mingo";
@@ -56279,11 +56338,10 @@ export {
56279
56338
  useCloseOnNavigation,
56280
56339
  useSSE,
56281
56340
  useChat,
56282
- SCROLL_ANCHOR_WIRE_KEY,
56283
- parseScrollAnchor,
56284
56341
  AUTO_CONTINUATION_DIRECTIVE_PREFIX,
56285
56342
  buildAutoContinuationDirective,
56286
- flattenAssistantContent,
56343
+ SCROLL_ANCHOR_WIRE_KEY,
56344
+ parseScrollAnchor,
56287
56345
  parseWireCommandOverride,
56288
56346
  sanitizeTitleForChat,
56289
56347
  formatSingularLookupInvocation,
@@ -56308,6 +56366,7 @@ export {
56308
56366
  computeHistoryPrepend,
56309
56367
  CHIP_ACTION_BUTTON_CLASS,
56310
56368
  chatChipClass,
56369
+ flattenAssistantContent,
56311
56370
  clickupTaskUrl,
56312
56371
  normalizeHistoricalMessageData,
56313
56372
  isHistoricalUserTurn,
@@ -56739,4 +56798,4 @@ export {
56739
56798
  LogsList,
56740
56799
  assets
56741
56800
  };
56742
- //# sourceMappingURL=chunk-77DFPD35.js.map
56801
+ //# sourceMappingURL=chunk-YMJZOANX.js.map