@iblai/web-utils 1.8.0 → 1.9.0

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 (34) hide show
  1. package/dist/auth/index.d.ts +202 -0
  2. package/dist/auth/index.esm.js +363 -0
  3. package/dist/auth/index.esm.js.map +1 -0
  4. package/dist/auth/index.js +379 -0
  5. package/dist/auth/index.js.map +1 -0
  6. package/dist/auth/web-utils/src/utils/auth.d.ts +199 -0
  7. package/dist/auth/web-utils/tests/hooks/chat/use-mentor-tools.test.d.ts +1 -0
  8. package/dist/auth/web-utils/tests/hooks/subscription/class-subscription-flow.test.d.ts +1 -0
  9. package/dist/auth/web-utils/tests/hooks/subscription/constants.test.d.ts +1 -0
  10. package/dist/auth/web-utils/tests/hooks/subscription/use-subscription-handler.test.d.ts +1 -0
  11. package/dist/auth/web-utils/tests/hooks/subscription-v2/use-subscription-handler.test.d.ts +1 -0
  12. package/dist/auth/web-utils/tests/hooks/use-day-js.test.d.ts +1 -0
  13. package/dist/auth/web-utils/tests/hooks/use-mentor-settings.test.d.ts +1 -0
  14. package/dist/auth/web-utils/tests/providers/mentor-provider.test.d.ts +1 -0
  15. package/dist/auth/web-utils/tests/providers/tenant-provider.test.d.ts +1 -0
  16. package/dist/auth/web-utils/tests/setupTests.d.ts +5 -0
  17. package/dist/auth/web-utils/tests/utils/helpers.test.d.ts +1 -0
  18. package/dist/data-layer/src/features/call-configurations/api-slice.d.ts +855 -0
  19. package/dist/data-layer/src/features/call-configurations/constants.d.ts +16 -0
  20. package/dist/data-layer/src/features/call-configurations/types.d.ts +49 -0
  21. package/dist/data-layer/src/features/mentor/api-slice.d.ts +824 -0
  22. package/dist/data-layer/src/index.d.ts +3 -0
  23. package/dist/index.d.ts +26 -2
  24. package/dist/index.esm.js +313 -41
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/index.js +316 -40
  27. package/dist/index.js.map +1 -1
  28. package/dist/package.json +6 -1
  29. package/dist/web-utils/src/features/chat/slice.d.ts +15 -1
  30. package/dist/web-utils/src/hooks/chat/use-chat-v2.d.ts +9 -0
  31. package/dist/web-utils/src/providers/service-worker-provider.d.ts +1 -1
  32. package/dist/web-utils/src/utils/constants.d.ts +1 -0
  33. package/dist/web-utils/tsconfig.tsbuildinfo +1 -0
  34. package/package.json +18 -11
package/dist/index.esm.js CHANGED
@@ -782,6 +782,15 @@ const TOOLS = {
782
782
  GOOGLE_SLIDES: "google-slides",
783
783
  GOOGLE_DOCUMENT: "google-docs",
784
784
  };
785
+ // Maps WebSocket tool_call type names to human-readable UI labels
786
+ const TOOL_NAME_MAP = {
787
+ web_search_call: "Searching the web",
788
+ vector_search: "Searching knowledge base",
789
+ calculator: "Calculating",
790
+ file_reader: "Reading file",
791
+ code_executor: "Running code",
792
+ wikipedia: "Searching Wikipedia",
793
+ };
785
794
  const REQUIRED_ACTIONS_FOR_GROUPS = {
786
795
  NOTIFICATIONS: "Ibl.Notifications/Notification/action",
787
796
  };
@@ -10735,41 +10744,41 @@ async function initServiceWorker(basePath = "") {
10735
10744
  return getServiceWorkerStatus();
10736
10745
  }
10737
10746
 
10738
- const CHECK_NETWORK_STATUS_COMMAND = 'check_network_status';
10747
+ const CHECK_NETWORK_STATUS_COMMAND = "check_network_status";
10739
10748
  // CRITICAL: Eagerly import Tauri API to bundle it inline instead of lazy-loading
10740
10749
  // webpackMode: "eager" prevents creating a separate chunk (7427.js)
10741
10750
  // This ensures the code is in the main bundle and always available offline
10742
10751
  let tauriInvoke = null;
10743
- if (typeof window !== 'undefined' && isTauri()) {
10752
+ if (typeof window !== "undefined" && isTauri()) {
10744
10753
  import(/* webpackMode: "eager" */ '@tauri-apps/api/core')
10745
10754
  .then((tauriCore) => {
10746
10755
  tauriInvoke = tauriCore.invoke;
10747
- console.log('[ServiceWorkerProvider] Tauri API loaded eagerly (bundled inline)');
10756
+ console.log("[ServiceWorkerProvider] Tauri API loaded eagerly (bundled inline)");
10748
10757
  })
10749
10758
  .catch((e) => {
10750
- console.warn('[ServiceWorkerProvider] Failed to load Tauri API:', e);
10759
+ console.warn("[ServiceWorkerProvider] Failed to load Tauri API:", e);
10751
10760
  });
10752
10761
  }
10753
10762
  // localStorage key set by the Tauri offline shell
10754
- const TAURI_OFFLINE_MODE_KEY = 'tauri_offline_mode';
10763
+ const TAURI_OFFLINE_MODE_KEY = "tauri_offline_mode";
10755
10764
  /**
10756
10765
  * Check if the shell has marked us as offline
10757
10766
  */
10758
10767
  function isShellOfflineMode() {
10759
- if (typeof window === 'undefined' ||
10760
- typeof (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) !== 'function')
10768
+ if (typeof window === "undefined" ||
10769
+ typeof (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) !== "function")
10761
10770
  return false;
10762
- return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) === 'true';
10771
+ return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) === "true";
10763
10772
  }
10764
10773
  const ServiceWorkerContext = createContext(null);
10765
10774
  function useServiceWorker() {
10766
10775
  const context = useContext(ServiceWorkerContext);
10767
10776
  if (!context) {
10768
- throw new Error('useServiceWorker must be used within ServiceWorkerProvider');
10777
+ throw new Error("useServiceWorker must be used within ServiceWorkerProvider");
10769
10778
  }
10770
10779
  return context;
10771
10780
  }
10772
- function ServiceWorkerProvider({ children, basePath = '', }) {
10781
+ function ServiceWorkerProvider({ children, basePath = "", }) {
10773
10782
  // Get initial status, considering the shell's offline flag
10774
10783
  const [status, setStatus] = useState(() => {
10775
10784
  const baseStatus = getServiceWorkerStatus();
@@ -10786,7 +10795,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10786
10795
  // Skip service worker registration in Tauri offline mode
10787
10796
  // The offline server handles all requests, SW is not needed and will fail to register
10788
10797
  if (isTauriApp && shellOffline) {
10789
- console.log('[ServiceWorkerProvider] Skipping SW registration - Tauri offline mode');
10798
+ console.log("[ServiceWorkerProvider] Skipping SW registration - Tauri offline mode");
10790
10799
  setStatus({
10791
10800
  isSupported: false,
10792
10801
  isRegistered: false,
@@ -10817,11 +10826,11 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10817
10826
  });
10818
10827
  // Subscribe to updates
10819
10828
  const unsubscribeUpdate = onUpdate(() => {
10820
- toast.info('App update available', {
10821
- description: 'A new version is ready. Click to update.',
10829
+ toast.info("App update available", {
10830
+ description: "A new version is ready. Click to update.",
10822
10831
  duration: 10000,
10823
10832
  action: {
10824
- label: 'Update',
10833
+ label: "Update",
10825
10834
  onClick: () => {
10826
10835
  skipWaiting();
10827
10836
  },
@@ -10848,7 +10857,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10848
10857
  const isOnline = (await tauriInvoke(CHECK_NETWORK_STATUS_COMMAND));
10849
10858
  setStatus((prev) => {
10850
10859
  if (prev.isOnline !== isOnline) {
10851
- console.log('[ServiceWorkerProvider] Network status changed:', isOnline ? 'online' : 'offline');
10860
+ console.log("[ServiceWorkerProvider] Network status changed:", isOnline ? "online" : "offline");
10852
10861
  // Notify service worker of the change
10853
10862
  setOfflineStatus(!isOnline);
10854
10863
  return { ...prev, isOnline };
@@ -10861,10 +10870,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10861
10870
  // If we're offline and the Tauri chunk can't load, just skip network checks
10862
10871
  // The error object has a 'name' property for ChunkLoadError
10863
10872
  if (error &&
10864
- typeof error === 'object' &&
10865
- 'name' in error &&
10866
- error.name === 'ChunkLoadError') {
10867
- console.warn('[ServiceWorkerProvider] Tauri API chunk not available (offline), disabling network checks');
10873
+ typeof error === "object" &&
10874
+ "name" in error &&
10875
+ error.name === "ChunkLoadError") {
10876
+ console.warn("[ServiceWorkerProvider] Tauri API chunk not available (offline), disabling network checks");
10868
10877
  // Clear the interval to stop trying
10869
10878
  if (networkCheckInterval) {
10870
10879
  clearInterval(networkCheckInterval);
@@ -10872,7 +10881,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10872
10881
  }
10873
10882
  }
10874
10883
  else {
10875
- console.error('[ServiceWorkerProvider] Failed to check network status:', error);
10884
+ console.error("[ServiceWorkerProvider] Failed to check network status:", error);
10876
10885
  }
10877
10886
  }
10878
10887
  };
@@ -10882,7 +10891,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10882
10891
  networkCheckInterval = setInterval(checkNetworkStatus, 3000);
10883
10892
  // Also listen to browser offline/online events for immediate feedback
10884
10893
  offlineHandler = () => {
10885
- console.log('[ServiceWorkerProvider] Browser offline event fired');
10894
+ console.log("[ServiceWorkerProvider] Browser offline event fired");
10886
10895
  setStatus((prev) => {
10887
10896
  if (prev.isOnline) {
10888
10897
  setOfflineStatus(true);
@@ -10894,12 +10903,12 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10894
10903
  setTimeout(checkNetworkStatus, 500);
10895
10904
  };
10896
10905
  onlineHandler = () => {
10897
- console.log('[ServiceWorkerProvider] Browser online event fired');
10906
+ console.log("[ServiceWorkerProvider] Browser online event fired");
10898
10907
  // Verify with Tauri before marking as online
10899
10908
  checkNetworkStatus();
10900
10909
  };
10901
- window.addEventListener('offline', offlineHandler);
10902
- window.addEventListener('online', onlineHandler);
10910
+ window.addEventListener("offline", offlineHandler);
10911
+ window.addEventListener("online", onlineHandler);
10903
10912
  }
10904
10913
  return () => {
10905
10914
  unsubscribeUpdate();
@@ -10908,10 +10917,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10908
10917
  clearInterval(networkCheckInterval);
10909
10918
  }
10910
10919
  if (offlineHandler) {
10911
- window.removeEventListener('offline', offlineHandler);
10920
+ window.removeEventListener("offline", offlineHandler);
10912
10921
  }
10913
10922
  if (onlineHandler) {
10914
- window.removeEventListener('online', onlineHandler);
10923
+ window.removeEventListener("online", onlineHandler);
10915
10924
  }
10916
10925
  };
10917
10926
  }, [basePath]);
@@ -10920,8 +10929,8 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10920
10929
  }, []);
10921
10930
  const clearCache = useCallback(() => {
10922
10931
  clearAllCaches();
10923
- toast.success('Cache cleared', {
10924
- description: 'All cached data has been cleared.',
10932
+ toast.success("Cache cleared", {
10933
+ description: "All cached data has been cleared.",
10925
10934
  });
10926
10935
  }, []);
10927
10936
  const refreshCacheStatus = useCallback(async () => {
@@ -10953,13 +10962,13 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
10953
10962
  catch (error) {
10954
10963
  // CRITICAL: Catch chunk load errors and fall back to navigator.onLine
10955
10964
  if (error &&
10956
- typeof error === 'object' &&
10957
- 'name' in error &&
10958
- error.name === 'ChunkLoadError') {
10959
- console.warn('[ServiceWorkerProvider] Tauri API chunk not available, using navigator.onLine');
10965
+ typeof error === "object" &&
10966
+ "name" in error &&
10967
+ error.name === "ChunkLoadError") {
10968
+ console.warn("[ServiceWorkerProvider] Tauri API chunk not available, using navigator.onLine");
10960
10969
  return navigator.onLine;
10961
10970
  }
10962
- console.error('[ServiceWorkerProvider] Failed to check network status:', error);
10971
+ console.error("[ServiceWorkerProvider] Failed to check network status:", error);
10963
10972
  return navigator.onLine; // Fallback to browser API
10964
10973
  }
10965
10974
  }, []);
@@ -10986,6 +10995,9 @@ const initialState$5 = {
10986
10995
  currentStreamingMessage: {
10987
10996
  id: "",
10988
10997
  content: "",
10998
+ reasoningContent: "",
10999
+ toolCalls: [],
11000
+ isReasoning: false,
10989
11001
  },
10990
11002
  currentStreamingArtifact: null,
10991
11003
  activeTab: "chat",
@@ -11009,6 +11021,9 @@ const initialState$5 = {
11009
11021
  // Buffering state initialized
11010
11022
  streamingArtifactContentBuffer: "",
11011
11023
  lastArtifactContentFlushTime: 0,
11024
+ // Reasoning buffering state initialized
11025
+ streamingReasoningContentBuffer: "",
11026
+ lastReasoningContentFlushTime: 0,
11012
11027
  metadata: {
11013
11028
  edxCourseId: "",
11014
11029
  edxUsageId: "",
@@ -11038,6 +11053,8 @@ const chatSlice = createSlice({
11038
11053
  content: state.currentStreamingMessage.content,
11039
11054
  timestamp: new Date().toISOString(),
11040
11055
  visible: true,
11056
+ reasoningContent: state.currentStreamingMessage.reasoningContent,
11057
+ toolCalls: state.currentStreamingMessage.toolCalls,
11041
11058
  };
11042
11059
  state.chats = {
11043
11060
  ...state.chats,
@@ -11048,6 +11065,8 @@ const chatSlice = createSlice({
11048
11065
  const temp = {
11049
11066
  ...lastMessageInActiveTabMessages,
11050
11067
  content: state.currentStreamingMessage.content,
11068
+ reasoningContent: state.currentStreamingMessage.reasoningContent,
11069
+ toolCalls: state.currentStreamingMessage.toolCalls,
11051
11070
  };
11052
11071
  state.chats = {
11053
11072
  ...state.chats,
@@ -11086,8 +11105,58 @@ const chatSlice = createSlice({
11086
11105
  setCurrentStreamingMessage: (state, action) => {
11087
11106
  state.currentStreamingMessage = action.payload;
11088
11107
  },
11108
+ // Partial update that only sets id/content without resetting reasoning/tool data
11109
+ setStreamingMessageIdAndContent: (state, action) => {
11110
+ state.currentStreamingMessage.id = action.payload.id;
11111
+ state.currentStreamingMessage.content = action.payload.content;
11112
+ },
11089
11113
  resetCurrentStreamingMessage: (state) => {
11090
- state.currentStreamingMessage = { id: "", content: "" };
11114
+ state.currentStreamingMessage = {
11115
+ id: "",
11116
+ content: "",
11117
+ reasoningContent: "",
11118
+ toolCalls: [],
11119
+ isReasoning: false,
11120
+ };
11121
+ // Reset reasoning buffer as well
11122
+ state.streamingReasoningContentBuffer = "";
11123
+ state.lastReasoningContentFlushTime = 0;
11124
+ },
11125
+ // Buffer reasoning tokens, flush at threshold
11126
+ appendReasoningContent: (state, action) => {
11127
+ // Add to buffer
11128
+ state.streamingReasoningContentBuffer += action.payload;
11129
+ // Check if we should flush (threshold reached)
11130
+ const shouldFlush = state.streamingReasoningContentBuffer.length >=
11131
+ STREAMING_CONTENT_BUFFER_THRESHOLD;
11132
+ if (shouldFlush) {
11133
+ // Flush buffer to actual content
11134
+ state.currentStreamingMessage.reasoningContent +=
11135
+ state.streamingReasoningContentBuffer;
11136
+ state.streamingReasoningContentBuffer = "";
11137
+ state.lastReasoningContentFlushTime = Date.now();
11138
+ }
11139
+ },
11140
+ // Force-flush buffered reasoning to currentStreamingMessage
11141
+ flushReasoningBuffer: (state, _action) => {
11142
+ if (state.streamingReasoningContentBuffer.length > 0) {
11143
+ state.currentStreamingMessage.reasoningContent +=
11144
+ state.streamingReasoningContentBuffer;
11145
+ state.streamingReasoningContentBuffer = "";
11146
+ state.lastReasoningContentFlushTime = Date.now();
11147
+ }
11148
+ },
11149
+ // Set isReasoning flag without touching other fields
11150
+ setIsReasoning: (state, action) => {
11151
+ state.currentStreamingMessage.isReasoning = action.payload;
11152
+ },
11153
+ // Sets isReasoning = false (triggers UI collapse)
11154
+ setReasoningComplete: (state, _action) => {
11155
+ state.currentStreamingMessage.isReasoning = false;
11156
+ },
11157
+ // Appends tool call entry
11158
+ addToolCall: (state, action) => {
11159
+ state.currentStreamingMessage.toolCalls.push(action.payload);
11091
11160
  },
11092
11161
  updateStreamingMessageId: (state, action) => {
11093
11162
  const oldId = state.currentStreamingMessage.id;
@@ -11245,11 +11314,15 @@ const chatSlice = createSlice({
11245
11314
  }
11246
11315
  const activeMessages = state.chats[state.activeTab];
11247
11316
  const lastMessage = activeMessages[activeMessages.length - 1];
11317
+ const toolCalls = state.currentStreamingMessage.toolCalls || [];
11318
+ const reasoningContent = state.currentStreamingMessage.reasoningContent || "";
11248
11319
  if (!lastMessage || lastMessage.id !== streamingId) {
11249
11320
  const temp = {
11250
11321
  id: streamingId,
11251
11322
  role: "assistant",
11252
11323
  content: state.currentStreamingMessage.content,
11324
+ reasoningContent,
11325
+ toolCalls,
11253
11326
  timestamp: new Date().toISOString(),
11254
11327
  visible: true,
11255
11328
  };
@@ -11258,6 +11331,19 @@ const chatSlice = createSlice({
11258
11331
  [state.activeTab]: [...activeMessages, temp],
11259
11332
  };
11260
11333
  }
11334
+ else {
11335
+ const updatedMessages = [...activeMessages];
11336
+ updatedMessages[activeMessages.length - 1] = {
11337
+ ...lastMessage,
11338
+ content: state.currentStreamingMessage.content,
11339
+ reasoningContent,
11340
+ toolCalls,
11341
+ };
11342
+ state.chats = {
11343
+ ...state.chats,
11344
+ [state.activeTab]: updatedMessages,
11345
+ };
11346
+ }
11261
11347
  },
11262
11348
  upsertStreamingArtifactVersionOnLastMessage: (state, action) => {
11263
11349
  const { artifactId, title, content, fileExtension, sessionId, versionNumber = 1, username, metadata, isPartial, } = action.payload;
@@ -11460,6 +11546,16 @@ const selectStreamingArtifactFullContent = (state) => {
11460
11546
  return null;
11461
11547
  return artifact.content + buffer;
11462
11548
  };
11549
+ // NEW: Get the full streaming reasoning content including buffer
11550
+ const selectStreamingReasoningContent = (state) => {
11551
+ const reasoningContent = state.chatSliceShared.currentStreamingMessage.reasoningContent;
11552
+ const buffer = state.chatSliceShared.streamingReasoningContentBuffer;
11553
+ return reasoningContent + buffer;
11554
+ };
11555
+ // NEW: Get isReasoning flag
11556
+ const selectIsReasoning = (state) => state.chatSliceShared.currentStreamingMessage.isReasoning;
11557
+ // NEW: Get streaming tool calls
11558
+ const selectStreamingToolCalls = (state) => state.chatSliceShared.currentStreamingMessage.toolCalls;
11463
11559
 
11464
11560
  class TimeTracker {
11465
11561
  constructor(config) {
@@ -12245,6 +12341,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12245
12341
  const currentStreamingMessage = useRef({
12246
12342
  id: null,
12247
12343
  content: "",
12344
+ reasoningContent: "",
12345
+ toolCalls: [],
12248
12346
  });
12249
12347
  // Track artifact state during streaming
12250
12348
  const currentArtifact = useRef(null);
@@ -12258,6 +12356,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12258
12356
  lastFlushTime: 0,
12259
12357
  flushTimer: null,
12260
12358
  });
12359
+ // NEW: Content buffer for batching reasoning streaming updates
12360
+ const reasoningContentBuffer = useRef({
12361
+ content: "",
12362
+ lastFlushTime: 0,
12363
+ flushTimer: null,
12364
+ });
12365
+ // NEW: Track if we've seen reasoning tokens to detect transition to response
12366
+ const hasSeenReasoning = useRef(false);
12261
12367
  const stopGenerationSocket = useRef(null);
12262
12368
  const isInitialConnection = useRef(true);
12263
12369
  const connectionAttempts = useRef(0);
@@ -12938,6 +13044,22 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12938
13044
  }
12939
13045
  return;
12940
13046
  }
13047
+ // NEW: Handle top-level tool_call messages (separate message type)
13048
+ if (messageData.type === "tool_call" && messageData.value) {
13049
+ const toolCallValue = messageData.value;
13050
+ // Dispatch tool call to Redux
13051
+ dispatch(chatActions.addToolCall({
13052
+ id: toolCallValue.id || "",
13053
+ name: toolCallValue.name || "",
13054
+ input: toolCallValue.tool_input,
13055
+ log: toolCallValue.log || "",
13056
+ result: toolCallValue.result || "",
13057
+ }));
13058
+ // Ensure message exists in array and update it with latest data
13059
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13060
+ // Early return since tool_call messages don't have data/eos fields
13061
+ return;
13062
+ }
12941
13063
  // Handle start of new streaming session
12942
13064
  if (messageData.generation_id &&
12943
13065
  !messageData.data &&
@@ -12950,6 +13072,21 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12950
13072
  id: messageData.generation_id,
12951
13073
  content: "",
12952
13074
  };
13075
+ // Reset Redux streaming message with all fields
13076
+ dispatch(chatActions.setCurrentStreamingMessage({
13077
+ id: messageData.generation_id,
13078
+ content: "",
13079
+ reasoningContent: "",
13080
+ toolCalls: [],
13081
+ isReasoning: false,
13082
+ }));
13083
+ // NEW: Reset reasoning refs and buffer for new generation
13084
+ hasSeenReasoning.current = false;
13085
+ reasoningContentBuffer.current = {
13086
+ content: "",
13087
+ lastFlushTime: 0,
13088
+ flushTimer: null,
13089
+ };
12953
13090
  onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
12954
13091
  onStatusChange("streaming");
12955
13092
  onStreamingChange(true);
@@ -12972,7 +13109,69 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12972
13109
  // Handle streaming message content (chat text)
12973
13110
  if ((messageData === null || messageData === void 0 ? void 0 : messageData.type) !== "chat_messages" &&
12974
13111
  (messageData.data !== undefined || messageData.eos !== undefined)) {
13112
+ // NEW: Handle annotations (reasoning tokens) BEFORE processing data
13113
+ if (messageData.annotations &&
13114
+ Array.isArray(messageData.annotations)) {
13115
+ for (const annotation of messageData.annotations) {
13116
+ if (annotation.type === "reasoning" && annotation.text) {
13117
+ // Mark that we've seen reasoning
13118
+ hasSeenReasoning.current = true;
13119
+ // Set isReasoning to true without overwriting toolCalls
13120
+ dispatch(chatActions.setIsReasoning(true));
13121
+ // Ensure message exists in array immediately so reasoning section appears
13122
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13123
+ // Buffer reasoning content
13124
+ reasoningContentBuffer.current.content += annotation.text;
13125
+ // Check if we should flush (threshold or timer)
13126
+ const shouldFlush = reasoningContentBuffer.current.content.length >=
13127
+ STREAMING_CONTENT_BUFFER_THRESHOLD;
13128
+ const now = Date.now();
13129
+ const timeSinceLastFlush = now - reasoningContentBuffer.current.lastFlushTime;
13130
+ if (shouldFlush ||
13131
+ timeSinceLastFlush >= STREAMING_CONTENT_FLUSH_INTERVAL) {
13132
+ // Flush buffer to Redux
13133
+ dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
13134
+ reasoningContentBuffer.current.content = "";
13135
+ reasoningContentBuffer.current.lastFlushTime = now;
13136
+ // Ensure message exists in array and update it with latest data
13137
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13138
+ }
13139
+ else {
13140
+ // Set up timer to flush if not already set
13141
+ if (!reasoningContentBuffer.current.flushTimer) {
13142
+ reasoningContentBuffer.current.flushTimer = setTimeout(() => {
13143
+ if (reasoningContentBuffer.current.content.length > 0) {
13144
+ dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
13145
+ reasoningContentBuffer.current.content = "";
13146
+ reasoningContentBuffer.current.lastFlushTime =
13147
+ Date.now();
13148
+ // Ensure message exists in array and update it with latest data
13149
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13150
+ }
13151
+ reasoningContentBuffer.current.flushTimer = null;
13152
+ }, STREAMING_CONTENT_FLUSH_INTERVAL);
13153
+ }
13154
+ }
13155
+ }
13156
+ }
13157
+ }
12975
13158
  const messageText = messageData.data || "";
13159
+ // NEW: Detect reasoning→response transition (first non-empty data after reasoning)
13160
+ if (messageText && hasSeenReasoning.current) {
13161
+ // Flush remaining reasoning buffer
13162
+ if (reasoningContentBuffer.current.content.length > 0) {
13163
+ dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
13164
+ reasoningContentBuffer.current.content = "";
13165
+ }
13166
+ // Flush reasoning buffer in Redux
13167
+ dispatch(chatActions.flushReasoningBuffer(undefined));
13168
+ // Mark reasoning as complete
13169
+ dispatch(chatActions.setReasoningComplete(undefined));
13170
+ // Update message in array with final reasoning state
13171
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13172
+ // Reset flag so we only do this once
13173
+ hasSeenReasoning.current = false;
13174
+ }
12976
13175
  // If we have content to add, update the in-memory streaming message and Redux
12977
13176
  if (messageText && currentStreamingMessage.current) {
12978
13177
  console.log("[ws-message] Streaming content chunk:", {
@@ -12986,13 +13185,28 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12986
13185
  content: currentStreamingMessage.current.content + messageText,
12987
13186
  };
12988
13187
  onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
12989
- // Update or add message in Redux store
13188
+ // Update or add message in Redux store - use ensureStreamingAssistantMessage for consistency
12990
13189
  if ((_w = currentStreamingMessage.current) === null || _w === void 0 ? void 0 : _w.id) {
12991
- // TODO: Investigate why `appendMessageToActiveTab` is consuming this action payload
12992
- dispatch(chatActions.appendMessageToActiveTab(undefined));
13190
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
12993
13191
  }
12994
13192
  }
12995
13193
  if (messageData.eos) {
13194
+ // NEW: Flush any remaining reasoning buffer on EOS
13195
+ if (reasoningContentBuffer.current.content.length > 0) {
13196
+ dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
13197
+ reasoningContentBuffer.current.content = "";
13198
+ }
13199
+ // Flush reasoning buffer in Redux
13200
+ dispatch(chatActions.flushReasoningBuffer(undefined));
13201
+ // Mark reasoning as complete
13202
+ dispatch(chatActions.setReasoningComplete(undefined));
13203
+ // Update message in array with final state
13204
+ dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
13205
+ // Clear any pending flush timer
13206
+ if (reasoningContentBuffer.current.flushTimer) {
13207
+ clearTimeout(reasoningContentBuffer.current.flushTimer);
13208
+ reasoningContentBuffer.current.flushTimer = null;
13209
+ }
12996
13210
  // Handle end of stream
12997
13211
  const hasPendingArtifact = !!pendingArtifactVersion.current;
12998
13212
  const hasMessageContent = !!((_x = currentStreamingMessage.current) === null || _x === void 0 ? void 0 : _x.content) &&
@@ -13607,7 +13821,13 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13607
13821
  dispatch(chatActions.setStatus(status));
13608
13822
  };
13609
13823
  const onStreamingMessageUpdate = (message) => {
13610
- dispatch(chatActions.setCurrentStreamingMessage(message));
13824
+ // Use setStreamingMessageIdAndContent to avoid resetting reasoning/tool state
13825
+ if (message.id) {
13826
+ dispatch(chatActions.setStreamingMessageIdAndContent({
13827
+ id: message.id,
13828
+ content: message.content,
13829
+ }));
13830
+ }
13611
13831
  };
13612
13832
  const { sendMessage, stopGenerating, ws, isConnected, messageQueue, resetConnection, } = useChat({
13613
13833
  wsUrl,
@@ -13689,7 +13909,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13689
13909
  try {
13690
13910
  previousChats =
13691
13911
  ((_d = (_c = data === null || data === void 0 ? void 0 : data.data) === null || _c === void 0 ? void 0 : _c.results) === null || _d === void 0 ? void 0 : _d.map((result) => {
13692
- var _a, _b, _c;
13912
+ var _a, _b, _c, _d, _e, _f;
13693
13913
  const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
13694
13914
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
13695
13915
  return ({
@@ -13728,6 +13948,30 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13728
13948
  fileSize: file.file_size,
13729
13949
  uploadUrl: file.url,
13730
13950
  }))) || [];
13951
+ // Extract additional_kwargs - check both direct and nested paths
13952
+ const additionalKwargs = result.additional_kwargs ||
13953
+ ((_d = (_c = result.message) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.additional_kwargs);
13954
+ // Extract reasoning content from additional_kwargs
13955
+ const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
13956
+ const reasoningContent = Array.isArray(reasoningSummaries)
13957
+ ? reasoningSummaries
13958
+ .map((s) => s.text)
13959
+ .filter(Boolean)
13960
+ .join("\n\n")
13961
+ : undefined;
13962
+ // Extract tool calls from additional_kwargs
13963
+ const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
13964
+ const toolCalls = Array.isArray(toolOutputs)
13965
+ ? toolOutputs.map((tool) => {
13966
+ var _a;
13967
+ return ({
13968
+ id: tool.id || "",
13969
+ name: tool.type || "",
13970
+ log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
13971
+ result: tool.status || "",
13972
+ });
13973
+ })
13974
+ : undefined;
13731
13975
  return {
13732
13976
  ...result,
13733
13977
  role: result.type === "human" ? "user" : "assistant",
@@ -13735,17 +13979,45 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13735
13979
  id: result.id || new Date().getTime(),
13736
13980
  content: typeof result.content === "object" &&
13737
13981
  result.content.length > 0
13738
- ? (_c = result.content.find((item) => item.text)) === null || _c === void 0 ? void 0 : _c.text
13982
+ ? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
13739
13983
  : result.content,
13740
13984
  // Add transformed artifact versions
13741
13985
  artifactVersions: artifactVersions || undefined,
13742
13986
  fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
13987
+ reasoningContent: reasoningContent || undefined,
13988
+ toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
13743
13989
  };
13744
13990
  }).reverse()) || [];
13745
13991
  }
13746
13992
  catch (error) {
13747
13993
  console.error(JSON.stringify(error));
13748
13994
  }
13995
+ // Preserve reasoningContent and toolCalls from existing messages
13996
+ // when the session API re-fetch doesn't include additional_kwargs.
13997
+ const existingMessages = chats[activeTab] || [];
13998
+ if (existingMessages.length > 0 && previousChats.length > 0) {
13999
+ const existingByContent = new Map();
14000
+ for (const m of existingMessages) {
14001
+ if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
14002
+ existingByContent.set(m.content, m);
14003
+ }
14004
+ }
14005
+ if (existingByContent.size > 0) {
14006
+ for (const msg of previousChats) {
14007
+ const existing = existingByContent.get(msg.content);
14008
+ if (existing) {
14009
+ if (!msg.reasoningContent && existing.reasoningContent) {
14010
+ msg.reasoningContent = existing.reasoningContent;
14011
+ }
14012
+ if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
14013
+ existing.toolCalls &&
14014
+ existing.toolCalls.length > 0) {
14015
+ msg.toolCalls = existing.toolCalls;
14016
+ }
14017
+ }
14018
+ }
14019
+ }
14020
+ }
13749
14021
  dispatch(chatActions.setNewMessages(previousChats));
13750
14022
  }
13751
14023
  catch (error) {
@@ -17896,5 +18168,5 @@ const checkRbacPermission = (rbacPermissions, rbacResource, enableRBAC = true) =
17896
18168
  return checkRbacPermissionInternal(rbacPermissions, rbacResource);
17897
18169
  };
17898
18170
 
17899
- export { ALPHANUMERIC_32_REGEX, ANONYMOUS_USERNAME, AuthContext, AuthContextProvider, AuthProvider, CHAT_AREA_SIZE, CacheKeys, DEFAULT_DISCLAIMER_CONTENT, LOCAL_STORAGE_KEYS, MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, MENTOR_VISIBILITY, MENTOR_VISIBILITY_VALUES, METADATAS, MentorProvider, REQUIRED_ACTIONS_FOR_GROUPS, RemoteEvents, STREAMING_CONTENT_BUFFER_THRESHOLD, STREAMING_CONTENT_FLUSH_INTERVAL, SUBSCRIPTION_MESSAGES, SUBSCRIPTION_PACKAGES, SUBSCRIPTION_PACKAGES_V2, SUBSCRIPTION_TRIGGERS, SUBSCRIPTION_V2_TRIGGERS, ServiceWorkerProvider, SubscriptionFlow, SubscriptionFlowV2, TOOLS, TenantContext, TenantContextProvider, TenantProvider, TimeTracker, WithFormPermissions, WithPermissions, addFiles, addMessage, addProtocolToUrl, advancedTabs, advancedTabsProperties, appleRestrictionReducer, appleRestrictionSlice, chatActions, chatInputSlice, chatInputSliceActions, chatInputSliceReducer, chatInputSliceSelectors, chatSliceReducerShared, checkModelAvailable, checkOllamaHealth, checkRbacPermission, clearAllCaches, clearApiCache, clearAuthCookies, clearCookies, clearCurrentTenantCookie, clearFiles, clearMessages, combineCSVData, convertToOllamaMessages, createFileReference, createMultipleFileReferences, csvDataToText, defaultSessionIds, deleteCookie, deleteCookieOnAllDomains, enableChatActionsPopup, eventBus, fetchWithCache, filesReducer, filesSlice, formatRelativeTime, getAuthSpaJoinUrl, getCacheStatus, getCachedApiResponse, getCookieValue, getDomainParts, getFileInfo, getInitials, getLocalLLMSystemPrompt, getNextNavigation, getParentDomain, getPlatform, getPlatformKey, getServiceWorkerStatus, getStoredUserName, getTimeAgo, getUserEmail, getUserName, handleLogout, hostChatReducer, hostChatSlice, initServiceWorker, isAlphaNumeric32, isExpo, isFileAccepted, isInIframe, isJSON, isLoggedIn, isNode, isReactNative, isSafariBrowser, isServiceWorkerSupported, isStripeActivated, isTauri, isTauriOfflineMode, isWeb$2 as isWeb, loadMetadataConfig, markdownToPlainText, monetizationSlice, onStatusChange, onUpdate, parseCSV, preCacheMentorData, rbacReducer, redirectToAuthSpa, redirectToAuthSpaJoinTenant, registerServiceWorker, removeFile, requestPresignedUrl, safeRequire, selectActiveChatMessages, selectActiveTab, selectArtifactsEnabled, selectAttachedFiles, selectChats, selectCurrentStreamingArtifact, selectCurrentStreamingMessage, selectDocumentFilter, selectEnableChatActionsPopup, selectIframeContext, selectIsError, selectIsPending, selectIsStopped, selectIsTyping, selectLastArtifactContentFlushTime, selectMetadata, selectNumberOfActiveChatMessages, selectRbacPermissions, selectSessionId, selectSessionIds, selectShouldStartNewChat, selectShowingSharedChat, selectStatus, selectStreaming, selectStreamingArtifactContentBuffer, selectStreamingArtifactFullContent, selectToken, selectTokenEnabled, selectTools, sendMessageToParentWebsite, setAccessCheckResponse, setAdvancedDisplayMonetizationCheckoutModal, setCachedApiResponse, setCookieForAuth, setDisplayMonetizationCheckoutModal, setError402Detected, setFreeTrialUsageOptions, setOfflineStatus, setOpenAppleRestrictionModal, setOpenPricingModal, setPricingModalData, setSubscriptionStatus, setTauriMode, setTopBannerOptions, setupNetworkListeners, showMonetizationCheckoutModal, skipWaiting, streamOllamaChat, subscriptionReducer, subscriptionSlice, syncAuthToCookies, tenantKeySchema, tenantSchema, topBannerReducer, topBannerSlice, translatePrompt, unregisterServiceWorker, updateFileMetadata, updateFileProgress, updateFileRetryCount, updateFileStatus, updateFileUrl, updateFileUrlFromWebSocket, updateRbacPermissions, uploadToS3, use402ErrorCheck, useAccessingPublicRoute, useAdvancedChat, useAuthContext, useAuthProvider, useAxdToken, useCachedSessionId, useChat, useChatFileUpload, useCurrentTenant, useDayJs, useDmToken, useEmbedMode, useEventCallback, useEventListener, useExternalPricingPlan, useFileDragDrop, useIsAdmin, useIsomorphicLayoutEffect, useLocalStorage, useMentorSettings, useMentorTools, useModelFileUploadCapabilities, useOS, useProfileImageUpload, useResponsive, useServiceWorker, useShowAttachment, useShowFreeTrialDialog, useShowVoiceCall, useShowVoiceRecorder, useStripeUpgrade, useSubscriptionHandler, useSubscriptionHandlerV2, useTenantContext, useTenantMetadata, useTimeTracker, useTimeTrackerNative, useTimer, useUserAgreement, useUserData, useUserProfileUpdate, useUserTenants, useUsername, useVisitingTenant, useVoiceChat, useWelcome as useWelcomeMessage, userDataSchema, validateFile };
18171
+ export { ALPHANUMERIC_32_REGEX, ANONYMOUS_USERNAME, AuthContext, AuthContextProvider, AuthProvider, CHAT_AREA_SIZE, CacheKeys, DEFAULT_DISCLAIMER_CONTENT, LOCAL_STORAGE_KEYS, MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, MENTOR_VISIBILITY, MENTOR_VISIBILITY_VALUES, METADATAS, MentorProvider, REQUIRED_ACTIONS_FOR_GROUPS, RemoteEvents, STREAMING_CONTENT_BUFFER_THRESHOLD, STREAMING_CONTENT_FLUSH_INTERVAL, SUBSCRIPTION_MESSAGES, SUBSCRIPTION_PACKAGES, SUBSCRIPTION_PACKAGES_V2, SUBSCRIPTION_TRIGGERS, SUBSCRIPTION_V2_TRIGGERS, ServiceWorkerProvider, SubscriptionFlow, SubscriptionFlowV2, TOOLS, TOOL_NAME_MAP, TenantContext, TenantContextProvider, TenantProvider, TimeTracker, WithFormPermissions, WithPermissions, addFiles, addMessage, addProtocolToUrl, advancedTabs, advancedTabsProperties, appleRestrictionReducer, appleRestrictionSlice, chatActions, chatInputSlice, chatInputSliceActions, chatInputSliceReducer, chatInputSliceSelectors, chatSliceReducerShared, checkModelAvailable, checkOllamaHealth, checkRbacPermission, clearAllCaches, clearApiCache, clearAuthCookies, clearCookies, clearCurrentTenantCookie, clearFiles, clearMessages, combineCSVData, convertToOllamaMessages, createFileReference, createMultipleFileReferences, csvDataToText, defaultSessionIds, deleteCookie, deleteCookieOnAllDomains, enableChatActionsPopup, eventBus, fetchWithCache, filesReducer, filesSlice, formatRelativeTime, getAuthSpaJoinUrl, getCacheStatus, getCachedApiResponse, getCookieValue, getDomainParts, getFileInfo, getInitials, getLocalLLMSystemPrompt, getNextNavigation, getParentDomain, getPlatform, getPlatformKey, getServiceWorkerStatus, getStoredUserName, getTimeAgo, getUserEmail, getUserName, handleLogout, hostChatReducer, hostChatSlice, initServiceWorker, isAlphaNumeric32, isExpo, isFileAccepted, isInIframe, isJSON, isLoggedIn, isNode, isReactNative, isSafariBrowser, isServiceWorkerSupported, isStripeActivated, isTauri, isTauriOfflineMode, isWeb$2 as isWeb, loadMetadataConfig, markdownToPlainText, monetizationSlice, onStatusChange, onUpdate, parseCSV, preCacheMentorData, rbacReducer, redirectToAuthSpa, redirectToAuthSpaJoinTenant, registerServiceWorker, removeFile, requestPresignedUrl, safeRequire, selectActiveChatMessages, selectActiveTab, selectArtifactsEnabled, selectAttachedFiles, selectChats, selectCurrentStreamingArtifact, selectCurrentStreamingMessage, selectDocumentFilter, selectEnableChatActionsPopup, selectIframeContext, selectIsError, selectIsPending, selectIsReasoning, selectIsStopped, selectIsTyping, selectLastArtifactContentFlushTime, selectMetadata, selectNumberOfActiveChatMessages, selectRbacPermissions, selectSessionId, selectSessionIds, selectShouldStartNewChat, selectShowingSharedChat, selectStatus, selectStreaming, selectStreamingArtifactContentBuffer, selectStreamingArtifactFullContent, selectStreamingReasoningContent, selectStreamingToolCalls, selectToken, selectTokenEnabled, selectTools, sendMessageToParentWebsite, setAccessCheckResponse, setAdvancedDisplayMonetizationCheckoutModal, setCachedApiResponse, setCookieForAuth, setDisplayMonetizationCheckoutModal, setError402Detected, setFreeTrialUsageOptions, setOfflineStatus, setOpenAppleRestrictionModal, setOpenPricingModal, setPricingModalData, setSubscriptionStatus, setTauriMode, setTopBannerOptions, setupNetworkListeners, showMonetizationCheckoutModal, skipWaiting, streamOllamaChat, subscriptionReducer, subscriptionSlice, syncAuthToCookies, tenantKeySchema, tenantSchema, topBannerReducer, topBannerSlice, translatePrompt, unregisterServiceWorker, updateFileMetadata, updateFileProgress, updateFileRetryCount, updateFileStatus, updateFileUrl, updateFileUrlFromWebSocket, updateRbacPermissions, uploadToS3, use402ErrorCheck, useAccessingPublicRoute, useAdvancedChat, useAuthContext, useAuthProvider, useAxdToken, useCachedSessionId, useChat, useChatFileUpload, useCurrentTenant, useDayJs, useDmToken, useEmbedMode, useEventCallback, useEventListener, useExternalPricingPlan, useFileDragDrop, useIsAdmin, useIsomorphicLayoutEffect, useLocalStorage, useMentorSettings, useMentorTools, useModelFileUploadCapabilities, useOS, useProfileImageUpload, useResponsive, useServiceWorker, useShowAttachment, useShowFreeTrialDialog, useShowVoiceCall, useShowVoiceRecorder, useStripeUpgrade, useSubscriptionHandler, useSubscriptionHandlerV2, useTenantContext, useTenantMetadata, useTimeTracker, useTimeTrackerNative, useTimer, useUserAgreement, useUserData, useUserProfileUpdate, useUserTenants, useUsername, useVisitingTenant, useVoiceChat, useWelcome as useWelcomeMessage, userDataSchema, validateFile };
17900
18172
  //# sourceMappingURL=index.esm.js.map