@iblai/web-utils 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-layer/src/features/call-configurations/api-slice.d.ts +855 -0
- package/dist/data-layer/src/features/call-configurations/constants.d.ts +16 -0
- package/dist/data-layer/src/features/call-configurations/types.d.ts +49 -0
- package/dist/data-layer/src/features/mentor/api-slice.d.ts +824 -0
- package/dist/data-layer/src/index.d.ts +3 -0
- package/dist/index.d.ts +27 -3
- package/dist/index.esm.js +313 -41
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +316 -40
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/web-utils/src/features/chat/slice.d.ts +15 -1
- package/dist/web-utils/src/hooks/chat/use-chat-v2.d.ts +9 -0
- package/dist/web-utils/src/providers/service-worker-provider.d.ts +1 -1
- package/dist/web-utils/src/utils/constants.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -802,6 +802,15 @@ const TOOLS = {
|
|
|
802
802
|
GOOGLE_SLIDES: "google-slides",
|
|
803
803
|
GOOGLE_DOCUMENT: "google-docs",
|
|
804
804
|
};
|
|
805
|
+
// Maps WebSocket tool_call type names to human-readable UI labels
|
|
806
|
+
const TOOL_NAME_MAP = {
|
|
807
|
+
web_search_call: "Searching the web",
|
|
808
|
+
vector_search: "Searching knowledge base",
|
|
809
|
+
calculator: "Calculating",
|
|
810
|
+
file_reader: "Reading file",
|
|
811
|
+
code_executor: "Running code",
|
|
812
|
+
wikipedia: "Searching Wikipedia",
|
|
813
|
+
};
|
|
805
814
|
const REQUIRED_ACTIONS_FOR_GROUPS = {
|
|
806
815
|
NOTIFICATIONS: "Ibl.Notifications/Notification/action",
|
|
807
816
|
};
|
|
@@ -10755,41 +10764,41 @@ async function initServiceWorker(basePath = "") {
|
|
|
10755
10764
|
return getServiceWorkerStatus();
|
|
10756
10765
|
}
|
|
10757
10766
|
|
|
10758
|
-
const CHECK_NETWORK_STATUS_COMMAND =
|
|
10767
|
+
const CHECK_NETWORK_STATUS_COMMAND = "check_network_status";
|
|
10759
10768
|
// CRITICAL: Eagerly import Tauri API to bundle it inline instead of lazy-loading
|
|
10760
10769
|
// webpackMode: "eager" prevents creating a separate chunk (7427.js)
|
|
10761
10770
|
// This ensures the code is in the main bundle and always available offline
|
|
10762
10771
|
let tauriInvoke = null;
|
|
10763
|
-
if (typeof window !==
|
|
10772
|
+
if (typeof window !== "undefined" && isTauri()) {
|
|
10764
10773
|
import(/* webpackMode: "eager" */ '@tauri-apps/api/core')
|
|
10765
10774
|
.then((tauriCore) => {
|
|
10766
10775
|
tauriInvoke = tauriCore.invoke;
|
|
10767
|
-
console.log(
|
|
10776
|
+
console.log("[ServiceWorkerProvider] Tauri API loaded eagerly (bundled inline)");
|
|
10768
10777
|
})
|
|
10769
10778
|
.catch((e) => {
|
|
10770
|
-
console.warn(
|
|
10779
|
+
console.warn("[ServiceWorkerProvider] Failed to load Tauri API:", e);
|
|
10771
10780
|
});
|
|
10772
10781
|
}
|
|
10773
10782
|
// localStorage key set by the Tauri offline shell
|
|
10774
|
-
const TAURI_OFFLINE_MODE_KEY =
|
|
10783
|
+
const TAURI_OFFLINE_MODE_KEY = "tauri_offline_mode";
|
|
10775
10784
|
/**
|
|
10776
10785
|
* Check if the shell has marked us as offline
|
|
10777
10786
|
*/
|
|
10778
10787
|
function isShellOfflineMode() {
|
|
10779
|
-
if (typeof window ===
|
|
10780
|
-
typeof (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) !==
|
|
10788
|
+
if (typeof window === "undefined" ||
|
|
10789
|
+
typeof (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) !== "function")
|
|
10781
10790
|
return false;
|
|
10782
|
-
return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) ===
|
|
10791
|
+
return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) === "true";
|
|
10783
10792
|
}
|
|
10784
10793
|
const ServiceWorkerContext = React.createContext(null);
|
|
10785
10794
|
function useServiceWorker() {
|
|
10786
10795
|
const context = React.useContext(ServiceWorkerContext);
|
|
10787
10796
|
if (!context) {
|
|
10788
|
-
throw new Error(
|
|
10797
|
+
throw new Error("useServiceWorker must be used within ServiceWorkerProvider");
|
|
10789
10798
|
}
|
|
10790
10799
|
return context;
|
|
10791
10800
|
}
|
|
10792
|
-
function ServiceWorkerProvider({ children, basePath =
|
|
10801
|
+
function ServiceWorkerProvider({ children, basePath = "", }) {
|
|
10793
10802
|
// Get initial status, considering the shell's offline flag
|
|
10794
10803
|
const [status, setStatus] = React.useState(() => {
|
|
10795
10804
|
const baseStatus = getServiceWorkerStatus();
|
|
@@ -10806,7 +10815,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10806
10815
|
// Skip service worker registration in Tauri offline mode
|
|
10807
10816
|
// The offline server handles all requests, SW is not needed and will fail to register
|
|
10808
10817
|
if (isTauriApp && shellOffline) {
|
|
10809
|
-
console.log(
|
|
10818
|
+
console.log("[ServiceWorkerProvider] Skipping SW registration - Tauri offline mode");
|
|
10810
10819
|
setStatus({
|
|
10811
10820
|
isSupported: false,
|
|
10812
10821
|
isRegistered: false,
|
|
@@ -10837,11 +10846,11 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10837
10846
|
});
|
|
10838
10847
|
// Subscribe to updates
|
|
10839
10848
|
const unsubscribeUpdate = onUpdate(() => {
|
|
10840
|
-
sonner.toast.info(
|
|
10841
|
-
description:
|
|
10849
|
+
sonner.toast.info("App update available", {
|
|
10850
|
+
description: "A new version is ready. Click to update.",
|
|
10842
10851
|
duration: 10000,
|
|
10843
10852
|
action: {
|
|
10844
|
-
label:
|
|
10853
|
+
label: "Update",
|
|
10845
10854
|
onClick: () => {
|
|
10846
10855
|
skipWaiting();
|
|
10847
10856
|
},
|
|
@@ -10868,7 +10877,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10868
10877
|
const isOnline = (await tauriInvoke(CHECK_NETWORK_STATUS_COMMAND));
|
|
10869
10878
|
setStatus((prev) => {
|
|
10870
10879
|
if (prev.isOnline !== isOnline) {
|
|
10871
|
-
console.log(
|
|
10880
|
+
console.log("[ServiceWorkerProvider] Network status changed:", isOnline ? "online" : "offline");
|
|
10872
10881
|
// Notify service worker of the change
|
|
10873
10882
|
setOfflineStatus(!isOnline);
|
|
10874
10883
|
return { ...prev, isOnline };
|
|
@@ -10881,10 +10890,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10881
10890
|
// If we're offline and the Tauri chunk can't load, just skip network checks
|
|
10882
10891
|
// The error object has a 'name' property for ChunkLoadError
|
|
10883
10892
|
if (error &&
|
|
10884
|
-
typeof error ===
|
|
10885
|
-
|
|
10886
|
-
error.name ===
|
|
10887
|
-
console.warn(
|
|
10893
|
+
typeof error === "object" &&
|
|
10894
|
+
"name" in error &&
|
|
10895
|
+
error.name === "ChunkLoadError") {
|
|
10896
|
+
console.warn("[ServiceWorkerProvider] Tauri API chunk not available (offline), disabling network checks");
|
|
10888
10897
|
// Clear the interval to stop trying
|
|
10889
10898
|
if (networkCheckInterval) {
|
|
10890
10899
|
clearInterval(networkCheckInterval);
|
|
@@ -10892,7 +10901,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10892
10901
|
}
|
|
10893
10902
|
}
|
|
10894
10903
|
else {
|
|
10895
|
-
console.error(
|
|
10904
|
+
console.error("[ServiceWorkerProvider] Failed to check network status:", error);
|
|
10896
10905
|
}
|
|
10897
10906
|
}
|
|
10898
10907
|
};
|
|
@@ -10902,7 +10911,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10902
10911
|
networkCheckInterval = setInterval(checkNetworkStatus, 3000);
|
|
10903
10912
|
// Also listen to browser offline/online events for immediate feedback
|
|
10904
10913
|
offlineHandler = () => {
|
|
10905
|
-
console.log(
|
|
10914
|
+
console.log("[ServiceWorkerProvider] Browser offline event fired");
|
|
10906
10915
|
setStatus((prev) => {
|
|
10907
10916
|
if (prev.isOnline) {
|
|
10908
10917
|
setOfflineStatus(true);
|
|
@@ -10914,12 +10923,12 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10914
10923
|
setTimeout(checkNetworkStatus, 500);
|
|
10915
10924
|
};
|
|
10916
10925
|
onlineHandler = () => {
|
|
10917
|
-
console.log(
|
|
10926
|
+
console.log("[ServiceWorkerProvider] Browser online event fired");
|
|
10918
10927
|
// Verify with Tauri before marking as online
|
|
10919
10928
|
checkNetworkStatus();
|
|
10920
10929
|
};
|
|
10921
|
-
window.addEventListener(
|
|
10922
|
-
window.addEventListener(
|
|
10930
|
+
window.addEventListener("offline", offlineHandler);
|
|
10931
|
+
window.addEventListener("online", onlineHandler);
|
|
10923
10932
|
}
|
|
10924
10933
|
return () => {
|
|
10925
10934
|
unsubscribeUpdate();
|
|
@@ -10928,10 +10937,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10928
10937
|
clearInterval(networkCheckInterval);
|
|
10929
10938
|
}
|
|
10930
10939
|
if (offlineHandler) {
|
|
10931
|
-
window.removeEventListener(
|
|
10940
|
+
window.removeEventListener("offline", offlineHandler);
|
|
10932
10941
|
}
|
|
10933
10942
|
if (onlineHandler) {
|
|
10934
|
-
window.removeEventListener(
|
|
10943
|
+
window.removeEventListener("online", onlineHandler);
|
|
10935
10944
|
}
|
|
10936
10945
|
};
|
|
10937
10946
|
}, [basePath]);
|
|
@@ -10940,8 +10949,8 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10940
10949
|
}, []);
|
|
10941
10950
|
const clearCache = React.useCallback(() => {
|
|
10942
10951
|
clearAllCaches();
|
|
10943
|
-
sonner.toast.success(
|
|
10944
|
-
description:
|
|
10952
|
+
sonner.toast.success("Cache cleared", {
|
|
10953
|
+
description: "All cached data has been cleared.",
|
|
10945
10954
|
});
|
|
10946
10955
|
}, []);
|
|
10947
10956
|
const refreshCacheStatus = React.useCallback(async () => {
|
|
@@ -10973,13 +10982,13 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10973
10982
|
catch (error) {
|
|
10974
10983
|
// CRITICAL: Catch chunk load errors and fall back to navigator.onLine
|
|
10975
10984
|
if (error &&
|
|
10976
|
-
typeof error ===
|
|
10977
|
-
|
|
10978
|
-
error.name ===
|
|
10979
|
-
console.warn(
|
|
10985
|
+
typeof error === "object" &&
|
|
10986
|
+
"name" in error &&
|
|
10987
|
+
error.name === "ChunkLoadError") {
|
|
10988
|
+
console.warn("[ServiceWorkerProvider] Tauri API chunk not available, using navigator.onLine");
|
|
10980
10989
|
return navigator.onLine;
|
|
10981
10990
|
}
|
|
10982
|
-
console.error(
|
|
10991
|
+
console.error("[ServiceWorkerProvider] Failed to check network status:", error);
|
|
10983
10992
|
return navigator.onLine; // Fallback to browser API
|
|
10984
10993
|
}
|
|
10985
10994
|
}, []);
|
|
@@ -11006,6 +11015,9 @@ const initialState$5 = {
|
|
|
11006
11015
|
currentStreamingMessage: {
|
|
11007
11016
|
id: "",
|
|
11008
11017
|
content: "",
|
|
11018
|
+
reasoningContent: "",
|
|
11019
|
+
toolCalls: [],
|
|
11020
|
+
isReasoning: false,
|
|
11009
11021
|
},
|
|
11010
11022
|
currentStreamingArtifact: null,
|
|
11011
11023
|
activeTab: "chat",
|
|
@@ -11029,6 +11041,9 @@ const initialState$5 = {
|
|
|
11029
11041
|
// Buffering state initialized
|
|
11030
11042
|
streamingArtifactContentBuffer: "",
|
|
11031
11043
|
lastArtifactContentFlushTime: 0,
|
|
11044
|
+
// Reasoning buffering state initialized
|
|
11045
|
+
streamingReasoningContentBuffer: "",
|
|
11046
|
+
lastReasoningContentFlushTime: 0,
|
|
11032
11047
|
metadata: {
|
|
11033
11048
|
edxCourseId: "",
|
|
11034
11049
|
edxUsageId: "",
|
|
@@ -11058,6 +11073,8 @@ const chatSlice = createSlice({
|
|
|
11058
11073
|
content: state.currentStreamingMessage.content,
|
|
11059
11074
|
timestamp: new Date().toISOString(),
|
|
11060
11075
|
visible: true,
|
|
11076
|
+
reasoningContent: state.currentStreamingMessage.reasoningContent,
|
|
11077
|
+
toolCalls: state.currentStreamingMessage.toolCalls,
|
|
11061
11078
|
};
|
|
11062
11079
|
state.chats = {
|
|
11063
11080
|
...state.chats,
|
|
@@ -11068,6 +11085,8 @@ const chatSlice = createSlice({
|
|
|
11068
11085
|
const temp = {
|
|
11069
11086
|
...lastMessageInActiveTabMessages,
|
|
11070
11087
|
content: state.currentStreamingMessage.content,
|
|
11088
|
+
reasoningContent: state.currentStreamingMessage.reasoningContent,
|
|
11089
|
+
toolCalls: state.currentStreamingMessage.toolCalls,
|
|
11071
11090
|
};
|
|
11072
11091
|
state.chats = {
|
|
11073
11092
|
...state.chats,
|
|
@@ -11106,8 +11125,58 @@ const chatSlice = createSlice({
|
|
|
11106
11125
|
setCurrentStreamingMessage: (state, action) => {
|
|
11107
11126
|
state.currentStreamingMessage = action.payload;
|
|
11108
11127
|
},
|
|
11128
|
+
// Partial update that only sets id/content without resetting reasoning/tool data
|
|
11129
|
+
setStreamingMessageIdAndContent: (state, action) => {
|
|
11130
|
+
state.currentStreamingMessage.id = action.payload.id;
|
|
11131
|
+
state.currentStreamingMessage.content = action.payload.content;
|
|
11132
|
+
},
|
|
11109
11133
|
resetCurrentStreamingMessage: (state) => {
|
|
11110
|
-
state.currentStreamingMessage = {
|
|
11134
|
+
state.currentStreamingMessage = {
|
|
11135
|
+
id: "",
|
|
11136
|
+
content: "",
|
|
11137
|
+
reasoningContent: "",
|
|
11138
|
+
toolCalls: [],
|
|
11139
|
+
isReasoning: false,
|
|
11140
|
+
};
|
|
11141
|
+
// Reset reasoning buffer as well
|
|
11142
|
+
state.streamingReasoningContentBuffer = "";
|
|
11143
|
+
state.lastReasoningContentFlushTime = 0;
|
|
11144
|
+
},
|
|
11145
|
+
// Buffer reasoning tokens, flush at threshold
|
|
11146
|
+
appendReasoningContent: (state, action) => {
|
|
11147
|
+
// Add to buffer
|
|
11148
|
+
state.streamingReasoningContentBuffer += action.payload;
|
|
11149
|
+
// Check if we should flush (threshold reached)
|
|
11150
|
+
const shouldFlush = state.streamingReasoningContentBuffer.length >=
|
|
11151
|
+
STREAMING_CONTENT_BUFFER_THRESHOLD;
|
|
11152
|
+
if (shouldFlush) {
|
|
11153
|
+
// Flush buffer to actual content
|
|
11154
|
+
state.currentStreamingMessage.reasoningContent +=
|
|
11155
|
+
state.streamingReasoningContentBuffer;
|
|
11156
|
+
state.streamingReasoningContentBuffer = "";
|
|
11157
|
+
state.lastReasoningContentFlushTime = Date.now();
|
|
11158
|
+
}
|
|
11159
|
+
},
|
|
11160
|
+
// Force-flush buffered reasoning to currentStreamingMessage
|
|
11161
|
+
flushReasoningBuffer: (state, _action) => {
|
|
11162
|
+
if (state.streamingReasoningContentBuffer.length > 0) {
|
|
11163
|
+
state.currentStreamingMessage.reasoningContent +=
|
|
11164
|
+
state.streamingReasoningContentBuffer;
|
|
11165
|
+
state.streamingReasoningContentBuffer = "";
|
|
11166
|
+
state.lastReasoningContentFlushTime = Date.now();
|
|
11167
|
+
}
|
|
11168
|
+
},
|
|
11169
|
+
// Set isReasoning flag without touching other fields
|
|
11170
|
+
setIsReasoning: (state, action) => {
|
|
11171
|
+
state.currentStreamingMessage.isReasoning = action.payload;
|
|
11172
|
+
},
|
|
11173
|
+
// Sets isReasoning = false (triggers UI collapse)
|
|
11174
|
+
setReasoningComplete: (state, _action) => {
|
|
11175
|
+
state.currentStreamingMessage.isReasoning = false;
|
|
11176
|
+
},
|
|
11177
|
+
// Appends tool call entry
|
|
11178
|
+
addToolCall: (state, action) => {
|
|
11179
|
+
state.currentStreamingMessage.toolCalls.push(action.payload);
|
|
11111
11180
|
},
|
|
11112
11181
|
updateStreamingMessageId: (state, action) => {
|
|
11113
11182
|
const oldId = state.currentStreamingMessage.id;
|
|
@@ -11265,11 +11334,15 @@ const chatSlice = createSlice({
|
|
|
11265
11334
|
}
|
|
11266
11335
|
const activeMessages = state.chats[state.activeTab];
|
|
11267
11336
|
const lastMessage = activeMessages[activeMessages.length - 1];
|
|
11337
|
+
const toolCalls = state.currentStreamingMessage.toolCalls || [];
|
|
11338
|
+
const reasoningContent = state.currentStreamingMessage.reasoningContent || "";
|
|
11268
11339
|
if (!lastMessage || lastMessage.id !== streamingId) {
|
|
11269
11340
|
const temp = {
|
|
11270
11341
|
id: streamingId,
|
|
11271
11342
|
role: "assistant",
|
|
11272
11343
|
content: state.currentStreamingMessage.content,
|
|
11344
|
+
reasoningContent,
|
|
11345
|
+
toolCalls,
|
|
11273
11346
|
timestamp: new Date().toISOString(),
|
|
11274
11347
|
visible: true,
|
|
11275
11348
|
};
|
|
@@ -11278,6 +11351,19 @@ const chatSlice = createSlice({
|
|
|
11278
11351
|
[state.activeTab]: [...activeMessages, temp],
|
|
11279
11352
|
};
|
|
11280
11353
|
}
|
|
11354
|
+
else {
|
|
11355
|
+
const updatedMessages = [...activeMessages];
|
|
11356
|
+
updatedMessages[activeMessages.length - 1] = {
|
|
11357
|
+
...lastMessage,
|
|
11358
|
+
content: state.currentStreamingMessage.content,
|
|
11359
|
+
reasoningContent,
|
|
11360
|
+
toolCalls,
|
|
11361
|
+
};
|
|
11362
|
+
state.chats = {
|
|
11363
|
+
...state.chats,
|
|
11364
|
+
[state.activeTab]: updatedMessages,
|
|
11365
|
+
};
|
|
11366
|
+
}
|
|
11281
11367
|
},
|
|
11282
11368
|
upsertStreamingArtifactVersionOnLastMessage: (state, action) => {
|
|
11283
11369
|
const { artifactId, title, content, fileExtension, sessionId, versionNumber = 1, username, metadata, isPartial, } = action.payload;
|
|
@@ -11480,6 +11566,16 @@ const selectStreamingArtifactFullContent = (state) => {
|
|
|
11480
11566
|
return null;
|
|
11481
11567
|
return artifact.content + buffer;
|
|
11482
11568
|
};
|
|
11569
|
+
// NEW: Get the full streaming reasoning content including buffer
|
|
11570
|
+
const selectStreamingReasoningContent = (state) => {
|
|
11571
|
+
const reasoningContent = state.chatSliceShared.currentStreamingMessage.reasoningContent;
|
|
11572
|
+
const buffer = state.chatSliceShared.streamingReasoningContentBuffer;
|
|
11573
|
+
return reasoningContent + buffer;
|
|
11574
|
+
};
|
|
11575
|
+
// NEW: Get isReasoning flag
|
|
11576
|
+
const selectIsReasoning = (state) => state.chatSliceShared.currentStreamingMessage.isReasoning;
|
|
11577
|
+
// NEW: Get streaming tool calls
|
|
11578
|
+
const selectStreamingToolCalls = (state) => state.chatSliceShared.currentStreamingMessage.toolCalls;
|
|
11483
11579
|
|
|
11484
11580
|
class TimeTracker {
|
|
11485
11581
|
constructor(config) {
|
|
@@ -12265,6 +12361,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12265
12361
|
const currentStreamingMessage = React.useRef({
|
|
12266
12362
|
id: null,
|
|
12267
12363
|
content: "",
|
|
12364
|
+
reasoningContent: "",
|
|
12365
|
+
toolCalls: [],
|
|
12268
12366
|
});
|
|
12269
12367
|
// Track artifact state during streaming
|
|
12270
12368
|
const currentArtifact = React.useRef(null);
|
|
@@ -12278,6 +12376,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12278
12376
|
lastFlushTime: 0,
|
|
12279
12377
|
flushTimer: null,
|
|
12280
12378
|
});
|
|
12379
|
+
// NEW: Content buffer for batching reasoning streaming updates
|
|
12380
|
+
const reasoningContentBuffer = React.useRef({
|
|
12381
|
+
content: "",
|
|
12382
|
+
lastFlushTime: 0,
|
|
12383
|
+
flushTimer: null,
|
|
12384
|
+
});
|
|
12385
|
+
// NEW: Track if we've seen reasoning tokens to detect transition to response
|
|
12386
|
+
const hasSeenReasoning = React.useRef(false);
|
|
12281
12387
|
const stopGenerationSocket = React.useRef(null);
|
|
12282
12388
|
const isInitialConnection = React.useRef(true);
|
|
12283
12389
|
const connectionAttempts = React.useRef(0);
|
|
@@ -12958,6 +13064,22 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12958
13064
|
}
|
|
12959
13065
|
return;
|
|
12960
13066
|
}
|
|
13067
|
+
// NEW: Handle top-level tool_call messages (separate message type)
|
|
13068
|
+
if (messageData.type === "tool_call" && messageData.value) {
|
|
13069
|
+
const toolCallValue = messageData.value;
|
|
13070
|
+
// Dispatch tool call to Redux
|
|
13071
|
+
dispatch(chatActions.addToolCall({
|
|
13072
|
+
id: toolCallValue.id || "",
|
|
13073
|
+
name: toolCallValue.name || "",
|
|
13074
|
+
input: toolCallValue.tool_input,
|
|
13075
|
+
log: toolCallValue.log || "",
|
|
13076
|
+
result: toolCallValue.result || "",
|
|
13077
|
+
}));
|
|
13078
|
+
// Ensure message exists in array and update it with latest data
|
|
13079
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13080
|
+
// Early return since tool_call messages don't have data/eos fields
|
|
13081
|
+
return;
|
|
13082
|
+
}
|
|
12961
13083
|
// Handle start of new streaming session
|
|
12962
13084
|
if (messageData.generation_id &&
|
|
12963
13085
|
!messageData.data &&
|
|
@@ -12970,6 +13092,21 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12970
13092
|
id: messageData.generation_id,
|
|
12971
13093
|
content: "",
|
|
12972
13094
|
};
|
|
13095
|
+
// Reset Redux streaming message with all fields
|
|
13096
|
+
dispatch(chatActions.setCurrentStreamingMessage({
|
|
13097
|
+
id: messageData.generation_id,
|
|
13098
|
+
content: "",
|
|
13099
|
+
reasoningContent: "",
|
|
13100
|
+
toolCalls: [],
|
|
13101
|
+
isReasoning: false,
|
|
13102
|
+
}));
|
|
13103
|
+
// NEW: Reset reasoning refs and buffer for new generation
|
|
13104
|
+
hasSeenReasoning.current = false;
|
|
13105
|
+
reasoningContentBuffer.current = {
|
|
13106
|
+
content: "",
|
|
13107
|
+
lastFlushTime: 0,
|
|
13108
|
+
flushTimer: null,
|
|
13109
|
+
};
|
|
12973
13110
|
onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
|
|
12974
13111
|
onStatusChange("streaming");
|
|
12975
13112
|
onStreamingChange(true);
|
|
@@ -12992,7 +13129,69 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12992
13129
|
// Handle streaming message content (chat text)
|
|
12993
13130
|
if ((messageData === null || messageData === void 0 ? void 0 : messageData.type) !== "chat_messages" &&
|
|
12994
13131
|
(messageData.data !== undefined || messageData.eos !== undefined)) {
|
|
13132
|
+
// NEW: Handle annotations (reasoning tokens) BEFORE processing data
|
|
13133
|
+
if (messageData.annotations &&
|
|
13134
|
+
Array.isArray(messageData.annotations)) {
|
|
13135
|
+
for (const annotation of messageData.annotations) {
|
|
13136
|
+
if (annotation.type === "reasoning" && annotation.text) {
|
|
13137
|
+
// Mark that we've seen reasoning
|
|
13138
|
+
hasSeenReasoning.current = true;
|
|
13139
|
+
// Set isReasoning to true without overwriting toolCalls
|
|
13140
|
+
dispatch(chatActions.setIsReasoning(true));
|
|
13141
|
+
// Ensure message exists in array immediately so reasoning section appears
|
|
13142
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13143
|
+
// Buffer reasoning content
|
|
13144
|
+
reasoningContentBuffer.current.content += annotation.text;
|
|
13145
|
+
// Check if we should flush (threshold or timer)
|
|
13146
|
+
const shouldFlush = reasoningContentBuffer.current.content.length >=
|
|
13147
|
+
STREAMING_CONTENT_BUFFER_THRESHOLD;
|
|
13148
|
+
const now = Date.now();
|
|
13149
|
+
const timeSinceLastFlush = now - reasoningContentBuffer.current.lastFlushTime;
|
|
13150
|
+
if (shouldFlush ||
|
|
13151
|
+
timeSinceLastFlush >= STREAMING_CONTENT_FLUSH_INTERVAL) {
|
|
13152
|
+
// Flush buffer to Redux
|
|
13153
|
+
dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
|
|
13154
|
+
reasoningContentBuffer.current.content = "";
|
|
13155
|
+
reasoningContentBuffer.current.lastFlushTime = now;
|
|
13156
|
+
// Ensure message exists in array and update it with latest data
|
|
13157
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13158
|
+
}
|
|
13159
|
+
else {
|
|
13160
|
+
// Set up timer to flush if not already set
|
|
13161
|
+
if (!reasoningContentBuffer.current.flushTimer) {
|
|
13162
|
+
reasoningContentBuffer.current.flushTimer = setTimeout(() => {
|
|
13163
|
+
if (reasoningContentBuffer.current.content.length > 0) {
|
|
13164
|
+
dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
|
|
13165
|
+
reasoningContentBuffer.current.content = "";
|
|
13166
|
+
reasoningContentBuffer.current.lastFlushTime =
|
|
13167
|
+
Date.now();
|
|
13168
|
+
// Ensure message exists in array and update it with latest data
|
|
13169
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13170
|
+
}
|
|
13171
|
+
reasoningContentBuffer.current.flushTimer = null;
|
|
13172
|
+
}, STREAMING_CONTENT_FLUSH_INTERVAL);
|
|
13173
|
+
}
|
|
13174
|
+
}
|
|
13175
|
+
}
|
|
13176
|
+
}
|
|
13177
|
+
}
|
|
12995
13178
|
const messageText = messageData.data || "";
|
|
13179
|
+
// NEW: Detect reasoning→response transition (first non-empty data after reasoning)
|
|
13180
|
+
if (messageText && hasSeenReasoning.current) {
|
|
13181
|
+
// Flush remaining reasoning buffer
|
|
13182
|
+
if (reasoningContentBuffer.current.content.length > 0) {
|
|
13183
|
+
dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
|
|
13184
|
+
reasoningContentBuffer.current.content = "";
|
|
13185
|
+
}
|
|
13186
|
+
// Flush reasoning buffer in Redux
|
|
13187
|
+
dispatch(chatActions.flushReasoningBuffer(undefined));
|
|
13188
|
+
// Mark reasoning as complete
|
|
13189
|
+
dispatch(chatActions.setReasoningComplete(undefined));
|
|
13190
|
+
// Update message in array with final reasoning state
|
|
13191
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13192
|
+
// Reset flag so we only do this once
|
|
13193
|
+
hasSeenReasoning.current = false;
|
|
13194
|
+
}
|
|
12996
13195
|
// If we have content to add, update the in-memory streaming message and Redux
|
|
12997
13196
|
if (messageText && currentStreamingMessage.current) {
|
|
12998
13197
|
console.log("[ws-message] Streaming content chunk:", {
|
|
@@ -13006,13 +13205,28 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
13006
13205
|
content: currentStreamingMessage.current.content + messageText,
|
|
13007
13206
|
};
|
|
13008
13207
|
onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
|
|
13009
|
-
// Update or add message in Redux store
|
|
13208
|
+
// Update or add message in Redux store - use ensureStreamingAssistantMessage for consistency
|
|
13010
13209
|
if ((_w = currentStreamingMessage.current) === null || _w === void 0 ? void 0 : _w.id) {
|
|
13011
|
-
|
|
13012
|
-
dispatch(chatActions.appendMessageToActiveTab(undefined));
|
|
13210
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13013
13211
|
}
|
|
13014
13212
|
}
|
|
13015
13213
|
if (messageData.eos) {
|
|
13214
|
+
// NEW: Flush any remaining reasoning buffer on EOS
|
|
13215
|
+
if (reasoningContentBuffer.current.content.length > 0) {
|
|
13216
|
+
dispatch(chatActions.appendReasoningContent(reasoningContentBuffer.current.content));
|
|
13217
|
+
reasoningContentBuffer.current.content = "";
|
|
13218
|
+
}
|
|
13219
|
+
// Flush reasoning buffer in Redux
|
|
13220
|
+
dispatch(chatActions.flushReasoningBuffer(undefined));
|
|
13221
|
+
// Mark reasoning as complete
|
|
13222
|
+
dispatch(chatActions.setReasoningComplete(undefined));
|
|
13223
|
+
// Update message in array with final state
|
|
13224
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13225
|
+
// Clear any pending flush timer
|
|
13226
|
+
if (reasoningContentBuffer.current.flushTimer) {
|
|
13227
|
+
clearTimeout(reasoningContentBuffer.current.flushTimer);
|
|
13228
|
+
reasoningContentBuffer.current.flushTimer = null;
|
|
13229
|
+
}
|
|
13016
13230
|
// Handle end of stream
|
|
13017
13231
|
const hasPendingArtifact = !!pendingArtifactVersion.current;
|
|
13018
13232
|
const hasMessageContent = !!((_x = currentStreamingMessage.current) === null || _x === void 0 ? void 0 : _x.content) &&
|
|
@@ -13627,7 +13841,13 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13627
13841
|
dispatch(chatActions.setStatus(status));
|
|
13628
13842
|
};
|
|
13629
13843
|
const onStreamingMessageUpdate = (message) => {
|
|
13630
|
-
|
|
13844
|
+
// Use setStreamingMessageIdAndContent to avoid resetting reasoning/tool state
|
|
13845
|
+
if (message.id) {
|
|
13846
|
+
dispatch(chatActions.setStreamingMessageIdAndContent({
|
|
13847
|
+
id: message.id,
|
|
13848
|
+
content: message.content,
|
|
13849
|
+
}));
|
|
13850
|
+
}
|
|
13631
13851
|
};
|
|
13632
13852
|
const { sendMessage, stopGenerating, ws, isConnected, messageQueue, resetConnection, } = useChat({
|
|
13633
13853
|
wsUrl,
|
|
@@ -13709,7 +13929,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13709
13929
|
try {
|
|
13710
13930
|
previousChats =
|
|
13711
13931
|
((_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) => {
|
|
13712
|
-
var _a, _b, _c;
|
|
13932
|
+
var _a, _b, _c, _d, _e, _f;
|
|
13713
13933
|
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
13714
13934
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
13715
13935
|
return ({
|
|
@@ -13748,6 +13968,30 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13748
13968
|
fileSize: file.file_size,
|
|
13749
13969
|
uploadUrl: file.url,
|
|
13750
13970
|
}))) || [];
|
|
13971
|
+
// Extract additional_kwargs - check both direct and nested paths
|
|
13972
|
+
const additionalKwargs = result.additional_kwargs ||
|
|
13973
|
+
((_d = (_c = result.message) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.additional_kwargs);
|
|
13974
|
+
// Extract reasoning content from additional_kwargs
|
|
13975
|
+
const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
|
|
13976
|
+
const reasoningContent = Array.isArray(reasoningSummaries)
|
|
13977
|
+
? reasoningSummaries
|
|
13978
|
+
.map((s) => s.text)
|
|
13979
|
+
.filter(Boolean)
|
|
13980
|
+
.join("\n\n")
|
|
13981
|
+
: undefined;
|
|
13982
|
+
// Extract tool calls from additional_kwargs
|
|
13983
|
+
const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
|
|
13984
|
+
const toolCalls = Array.isArray(toolOutputs)
|
|
13985
|
+
? toolOutputs.map((tool) => {
|
|
13986
|
+
var _a;
|
|
13987
|
+
return ({
|
|
13988
|
+
id: tool.id || "",
|
|
13989
|
+
name: tool.type || "",
|
|
13990
|
+
log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
|
|
13991
|
+
result: tool.status || "",
|
|
13992
|
+
});
|
|
13993
|
+
})
|
|
13994
|
+
: undefined;
|
|
13751
13995
|
return {
|
|
13752
13996
|
...result,
|
|
13753
13997
|
role: result.type === "human" ? "user" : "assistant",
|
|
@@ -13755,17 +13999,45 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13755
13999
|
id: result.id || new Date().getTime(),
|
|
13756
14000
|
content: typeof result.content === "object" &&
|
|
13757
14001
|
result.content.length > 0
|
|
13758
|
-
? (
|
|
14002
|
+
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
13759
14003
|
: result.content,
|
|
13760
14004
|
// Add transformed artifact versions
|
|
13761
14005
|
artifactVersions: artifactVersions || undefined,
|
|
13762
14006
|
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
14007
|
+
reasoningContent: reasoningContent || undefined,
|
|
14008
|
+
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
13763
14009
|
};
|
|
13764
14010
|
}).reverse()) || [];
|
|
13765
14011
|
}
|
|
13766
14012
|
catch (error) {
|
|
13767
14013
|
console.error(JSON.stringify(error));
|
|
13768
14014
|
}
|
|
14015
|
+
// Preserve reasoningContent and toolCalls from existing messages
|
|
14016
|
+
// when the session API re-fetch doesn't include additional_kwargs.
|
|
14017
|
+
const existingMessages = chats[activeTab] || [];
|
|
14018
|
+
if (existingMessages.length > 0 && previousChats.length > 0) {
|
|
14019
|
+
const existingByContent = new Map();
|
|
14020
|
+
for (const m of existingMessages) {
|
|
14021
|
+
if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
|
|
14022
|
+
existingByContent.set(m.content, m);
|
|
14023
|
+
}
|
|
14024
|
+
}
|
|
14025
|
+
if (existingByContent.size > 0) {
|
|
14026
|
+
for (const msg of previousChats) {
|
|
14027
|
+
const existing = existingByContent.get(msg.content);
|
|
14028
|
+
if (existing) {
|
|
14029
|
+
if (!msg.reasoningContent && existing.reasoningContent) {
|
|
14030
|
+
msg.reasoningContent = existing.reasoningContent;
|
|
14031
|
+
}
|
|
14032
|
+
if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
|
|
14033
|
+
existing.toolCalls &&
|
|
14034
|
+
existing.toolCalls.length > 0) {
|
|
14035
|
+
msg.toolCalls = existing.toolCalls;
|
|
14036
|
+
}
|
|
14037
|
+
}
|
|
14038
|
+
}
|
|
14039
|
+
}
|
|
14040
|
+
}
|
|
13769
14041
|
dispatch(chatActions.setNewMessages(previousChats));
|
|
13770
14042
|
}
|
|
13771
14043
|
catch (error) {
|
|
@@ -17943,6 +18215,7 @@ exports.ServiceWorkerProvider = ServiceWorkerProvider;
|
|
|
17943
18215
|
exports.SubscriptionFlow = SubscriptionFlow;
|
|
17944
18216
|
exports.SubscriptionFlowV2 = SubscriptionFlowV2;
|
|
17945
18217
|
exports.TOOLS = TOOLS;
|
|
18218
|
+
exports.TOOL_NAME_MAP = TOOL_NAME_MAP;
|
|
17946
18219
|
exports.TenantContext = TenantContext;
|
|
17947
18220
|
exports.TenantContextProvider = TenantContextProvider;
|
|
17948
18221
|
exports.TenantProvider = TenantProvider;
|
|
@@ -18047,6 +18320,7 @@ exports.selectEnableChatActionsPopup = selectEnableChatActionsPopup;
|
|
|
18047
18320
|
exports.selectIframeContext = selectIframeContext;
|
|
18048
18321
|
exports.selectIsError = selectIsError;
|
|
18049
18322
|
exports.selectIsPending = selectIsPending;
|
|
18323
|
+
exports.selectIsReasoning = selectIsReasoning;
|
|
18050
18324
|
exports.selectIsStopped = selectIsStopped;
|
|
18051
18325
|
exports.selectIsTyping = selectIsTyping;
|
|
18052
18326
|
exports.selectLastArtifactContentFlushTime = selectLastArtifactContentFlushTime;
|
|
@@ -18061,6 +18335,8 @@ exports.selectStatus = selectStatus;
|
|
|
18061
18335
|
exports.selectStreaming = selectStreaming;
|
|
18062
18336
|
exports.selectStreamingArtifactContentBuffer = selectStreamingArtifactContentBuffer;
|
|
18063
18337
|
exports.selectStreamingArtifactFullContent = selectStreamingArtifactFullContent;
|
|
18338
|
+
exports.selectStreamingReasoningContent = selectStreamingReasoningContent;
|
|
18339
|
+
exports.selectStreamingToolCalls = selectStreamingToolCalls;
|
|
18064
18340
|
exports.selectToken = selectToken;
|
|
18065
18341
|
exports.selectTokenEnabled = selectTokenEnabled;
|
|
18066
18342
|
exports.selectTools = selectTools;
|