@iblai/web-utils 1.7.3 → 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 +28 -3
- package/dist/index.esm.js +321 -46
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +324 -45
- 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/auth.d.ts +1 -0
- 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
|
};
|
|
@@ -1181,17 +1190,19 @@ async function redirectToAuthSpa(options) {
|
|
|
1181
1190
|
logoutTimestamp: "ibl_logout_timestamp",
|
|
1182
1191
|
loginTimestamp: "ibl_login_timestamp",
|
|
1183
1192
|
tenantSwitching: "ibl_tenant_switching",
|
|
1184
|
-
}, hasNonExpiredAuthToken, isOffline, preserveTokenKey, authRedirectProxy, isNativeApp, } = options;
|
|
1185
|
-
console.log("[redirectToAuthSpa] starting redirect to auth spa", redirectTo, platformKey, logout, saveRedirect);
|
|
1193
|
+
}, hasNonExpiredAuthToken, isOffline, preserveTokenKey, authRedirectProxy, isNativeApp, forceRedirect = false, } = options;
|
|
1194
|
+
console.log("[redirectToAuthSpa] starting redirect to auth spa", redirectTo, platformKey, logout, saveRedirect, forceRedirect);
|
|
1186
1195
|
// Skip if a tenant switch is already in progress
|
|
1187
|
-
if (
|
|
1196
|
+
if (!forceRedirect &&
|
|
1197
|
+
cookieNames.tenantSwitching &&
|
|
1188
1198
|
document.cookie.includes(cookieNames.tenantSwitching)) {
|
|
1189
1199
|
console.log("[redirectToAuthSpa] Tenant switch in progress, skipping redirect");
|
|
1190
1200
|
return;
|
|
1191
1201
|
}
|
|
1192
1202
|
// Skip if a login occurred after the last logout (login takes precedence)
|
|
1193
1203
|
// but only if this app actually has a valid auth token
|
|
1194
|
-
if (
|
|
1204
|
+
if (!forceRedirect &&
|
|
1205
|
+
hasNonExpiredAuthToken &&
|
|
1195
1206
|
cookieNames.loginTimestamp &&
|
|
1196
1207
|
cookieNames.logoutTimestamp) {
|
|
1197
1208
|
const loginTs = getCookieValue(cookieNames.loginTimestamp);
|
|
@@ -1203,7 +1214,8 @@ async function redirectToAuthSpa(options) {
|
|
|
1203
1214
|
hasValidToken,
|
|
1204
1215
|
loginAhead: loginTs && logoutTs ? Number(loginTs) > Number(logoutTs) : false,
|
|
1205
1216
|
});
|
|
1206
|
-
if (
|
|
1217
|
+
if (!forceRedirect &&
|
|
1218
|
+
hasValidToken &&
|
|
1207
1219
|
loginTs &&
|
|
1208
1220
|
logoutTs &&
|
|
1209
1221
|
Number(loginTs) > Number(logoutTs)) {
|
|
@@ -10752,41 +10764,41 @@ async function initServiceWorker(basePath = "") {
|
|
|
10752
10764
|
return getServiceWorkerStatus();
|
|
10753
10765
|
}
|
|
10754
10766
|
|
|
10755
|
-
const CHECK_NETWORK_STATUS_COMMAND =
|
|
10767
|
+
const CHECK_NETWORK_STATUS_COMMAND = "check_network_status";
|
|
10756
10768
|
// CRITICAL: Eagerly import Tauri API to bundle it inline instead of lazy-loading
|
|
10757
10769
|
// webpackMode: "eager" prevents creating a separate chunk (7427.js)
|
|
10758
10770
|
// This ensures the code is in the main bundle and always available offline
|
|
10759
10771
|
let tauriInvoke = null;
|
|
10760
|
-
if (typeof window !==
|
|
10772
|
+
if (typeof window !== "undefined" && isTauri()) {
|
|
10761
10773
|
import(/* webpackMode: "eager" */ '@tauri-apps/api/core')
|
|
10762
10774
|
.then((tauriCore) => {
|
|
10763
10775
|
tauriInvoke = tauriCore.invoke;
|
|
10764
|
-
console.log(
|
|
10776
|
+
console.log("[ServiceWorkerProvider] Tauri API loaded eagerly (bundled inline)");
|
|
10765
10777
|
})
|
|
10766
10778
|
.catch((e) => {
|
|
10767
|
-
console.warn(
|
|
10779
|
+
console.warn("[ServiceWorkerProvider] Failed to load Tauri API:", e);
|
|
10768
10780
|
});
|
|
10769
10781
|
}
|
|
10770
10782
|
// localStorage key set by the Tauri offline shell
|
|
10771
|
-
const TAURI_OFFLINE_MODE_KEY =
|
|
10783
|
+
const TAURI_OFFLINE_MODE_KEY = "tauri_offline_mode";
|
|
10772
10784
|
/**
|
|
10773
10785
|
* Check if the shell has marked us as offline
|
|
10774
10786
|
*/
|
|
10775
10787
|
function isShellOfflineMode() {
|
|
10776
|
-
if (typeof window ===
|
|
10777
|
-
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")
|
|
10778
10790
|
return false;
|
|
10779
|
-
return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) ===
|
|
10791
|
+
return localStorage.getItem(TAURI_OFFLINE_MODE_KEY) === "true";
|
|
10780
10792
|
}
|
|
10781
10793
|
const ServiceWorkerContext = React.createContext(null);
|
|
10782
10794
|
function useServiceWorker() {
|
|
10783
10795
|
const context = React.useContext(ServiceWorkerContext);
|
|
10784
10796
|
if (!context) {
|
|
10785
|
-
throw new Error(
|
|
10797
|
+
throw new Error("useServiceWorker must be used within ServiceWorkerProvider");
|
|
10786
10798
|
}
|
|
10787
10799
|
return context;
|
|
10788
10800
|
}
|
|
10789
|
-
function ServiceWorkerProvider({ children, basePath =
|
|
10801
|
+
function ServiceWorkerProvider({ children, basePath = "", }) {
|
|
10790
10802
|
// Get initial status, considering the shell's offline flag
|
|
10791
10803
|
const [status, setStatus] = React.useState(() => {
|
|
10792
10804
|
const baseStatus = getServiceWorkerStatus();
|
|
@@ -10803,7 +10815,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10803
10815
|
// Skip service worker registration in Tauri offline mode
|
|
10804
10816
|
// The offline server handles all requests, SW is not needed and will fail to register
|
|
10805
10817
|
if (isTauriApp && shellOffline) {
|
|
10806
|
-
console.log(
|
|
10818
|
+
console.log("[ServiceWorkerProvider] Skipping SW registration - Tauri offline mode");
|
|
10807
10819
|
setStatus({
|
|
10808
10820
|
isSupported: false,
|
|
10809
10821
|
isRegistered: false,
|
|
@@ -10834,11 +10846,11 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10834
10846
|
});
|
|
10835
10847
|
// Subscribe to updates
|
|
10836
10848
|
const unsubscribeUpdate = onUpdate(() => {
|
|
10837
|
-
sonner.toast.info(
|
|
10838
|
-
description:
|
|
10849
|
+
sonner.toast.info("App update available", {
|
|
10850
|
+
description: "A new version is ready. Click to update.",
|
|
10839
10851
|
duration: 10000,
|
|
10840
10852
|
action: {
|
|
10841
|
-
label:
|
|
10853
|
+
label: "Update",
|
|
10842
10854
|
onClick: () => {
|
|
10843
10855
|
skipWaiting();
|
|
10844
10856
|
},
|
|
@@ -10865,7 +10877,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10865
10877
|
const isOnline = (await tauriInvoke(CHECK_NETWORK_STATUS_COMMAND));
|
|
10866
10878
|
setStatus((prev) => {
|
|
10867
10879
|
if (prev.isOnline !== isOnline) {
|
|
10868
|
-
console.log(
|
|
10880
|
+
console.log("[ServiceWorkerProvider] Network status changed:", isOnline ? "online" : "offline");
|
|
10869
10881
|
// Notify service worker of the change
|
|
10870
10882
|
setOfflineStatus(!isOnline);
|
|
10871
10883
|
return { ...prev, isOnline };
|
|
@@ -10878,10 +10890,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10878
10890
|
// If we're offline and the Tauri chunk can't load, just skip network checks
|
|
10879
10891
|
// The error object has a 'name' property for ChunkLoadError
|
|
10880
10892
|
if (error &&
|
|
10881
|
-
typeof error ===
|
|
10882
|
-
|
|
10883
|
-
error.name ===
|
|
10884
|
-
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");
|
|
10885
10897
|
// Clear the interval to stop trying
|
|
10886
10898
|
if (networkCheckInterval) {
|
|
10887
10899
|
clearInterval(networkCheckInterval);
|
|
@@ -10889,7 +10901,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10889
10901
|
}
|
|
10890
10902
|
}
|
|
10891
10903
|
else {
|
|
10892
|
-
console.error(
|
|
10904
|
+
console.error("[ServiceWorkerProvider] Failed to check network status:", error);
|
|
10893
10905
|
}
|
|
10894
10906
|
}
|
|
10895
10907
|
};
|
|
@@ -10899,7 +10911,7 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10899
10911
|
networkCheckInterval = setInterval(checkNetworkStatus, 3000);
|
|
10900
10912
|
// Also listen to browser offline/online events for immediate feedback
|
|
10901
10913
|
offlineHandler = () => {
|
|
10902
|
-
console.log(
|
|
10914
|
+
console.log("[ServiceWorkerProvider] Browser offline event fired");
|
|
10903
10915
|
setStatus((prev) => {
|
|
10904
10916
|
if (prev.isOnline) {
|
|
10905
10917
|
setOfflineStatus(true);
|
|
@@ -10911,12 +10923,12 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10911
10923
|
setTimeout(checkNetworkStatus, 500);
|
|
10912
10924
|
};
|
|
10913
10925
|
onlineHandler = () => {
|
|
10914
|
-
console.log(
|
|
10926
|
+
console.log("[ServiceWorkerProvider] Browser online event fired");
|
|
10915
10927
|
// Verify with Tauri before marking as online
|
|
10916
10928
|
checkNetworkStatus();
|
|
10917
10929
|
};
|
|
10918
|
-
window.addEventListener(
|
|
10919
|
-
window.addEventListener(
|
|
10930
|
+
window.addEventListener("offline", offlineHandler);
|
|
10931
|
+
window.addEventListener("online", onlineHandler);
|
|
10920
10932
|
}
|
|
10921
10933
|
return () => {
|
|
10922
10934
|
unsubscribeUpdate();
|
|
@@ -10925,10 +10937,10 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10925
10937
|
clearInterval(networkCheckInterval);
|
|
10926
10938
|
}
|
|
10927
10939
|
if (offlineHandler) {
|
|
10928
|
-
window.removeEventListener(
|
|
10940
|
+
window.removeEventListener("offline", offlineHandler);
|
|
10929
10941
|
}
|
|
10930
10942
|
if (onlineHandler) {
|
|
10931
|
-
window.removeEventListener(
|
|
10943
|
+
window.removeEventListener("online", onlineHandler);
|
|
10932
10944
|
}
|
|
10933
10945
|
};
|
|
10934
10946
|
}, [basePath]);
|
|
@@ -10937,8 +10949,8 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10937
10949
|
}, []);
|
|
10938
10950
|
const clearCache = React.useCallback(() => {
|
|
10939
10951
|
clearAllCaches();
|
|
10940
|
-
sonner.toast.success(
|
|
10941
|
-
description:
|
|
10952
|
+
sonner.toast.success("Cache cleared", {
|
|
10953
|
+
description: "All cached data has been cleared.",
|
|
10942
10954
|
});
|
|
10943
10955
|
}, []);
|
|
10944
10956
|
const refreshCacheStatus = React.useCallback(async () => {
|
|
@@ -10970,13 +10982,13 @@ function ServiceWorkerProvider({ children, basePath = '', }) {
|
|
|
10970
10982
|
catch (error) {
|
|
10971
10983
|
// CRITICAL: Catch chunk load errors and fall back to navigator.onLine
|
|
10972
10984
|
if (error &&
|
|
10973
|
-
typeof error ===
|
|
10974
|
-
|
|
10975
|
-
error.name ===
|
|
10976
|
-
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");
|
|
10977
10989
|
return navigator.onLine;
|
|
10978
10990
|
}
|
|
10979
|
-
console.error(
|
|
10991
|
+
console.error("[ServiceWorkerProvider] Failed to check network status:", error);
|
|
10980
10992
|
return navigator.onLine; // Fallback to browser API
|
|
10981
10993
|
}
|
|
10982
10994
|
}, []);
|
|
@@ -11003,6 +11015,9 @@ const initialState$5 = {
|
|
|
11003
11015
|
currentStreamingMessage: {
|
|
11004
11016
|
id: "",
|
|
11005
11017
|
content: "",
|
|
11018
|
+
reasoningContent: "",
|
|
11019
|
+
toolCalls: [],
|
|
11020
|
+
isReasoning: false,
|
|
11006
11021
|
},
|
|
11007
11022
|
currentStreamingArtifact: null,
|
|
11008
11023
|
activeTab: "chat",
|
|
@@ -11026,6 +11041,9 @@ const initialState$5 = {
|
|
|
11026
11041
|
// Buffering state initialized
|
|
11027
11042
|
streamingArtifactContentBuffer: "",
|
|
11028
11043
|
lastArtifactContentFlushTime: 0,
|
|
11044
|
+
// Reasoning buffering state initialized
|
|
11045
|
+
streamingReasoningContentBuffer: "",
|
|
11046
|
+
lastReasoningContentFlushTime: 0,
|
|
11029
11047
|
metadata: {
|
|
11030
11048
|
edxCourseId: "",
|
|
11031
11049
|
edxUsageId: "",
|
|
@@ -11055,6 +11073,8 @@ const chatSlice = createSlice({
|
|
|
11055
11073
|
content: state.currentStreamingMessage.content,
|
|
11056
11074
|
timestamp: new Date().toISOString(),
|
|
11057
11075
|
visible: true,
|
|
11076
|
+
reasoningContent: state.currentStreamingMessage.reasoningContent,
|
|
11077
|
+
toolCalls: state.currentStreamingMessage.toolCalls,
|
|
11058
11078
|
};
|
|
11059
11079
|
state.chats = {
|
|
11060
11080
|
...state.chats,
|
|
@@ -11065,6 +11085,8 @@ const chatSlice = createSlice({
|
|
|
11065
11085
|
const temp = {
|
|
11066
11086
|
...lastMessageInActiveTabMessages,
|
|
11067
11087
|
content: state.currentStreamingMessage.content,
|
|
11088
|
+
reasoningContent: state.currentStreamingMessage.reasoningContent,
|
|
11089
|
+
toolCalls: state.currentStreamingMessage.toolCalls,
|
|
11068
11090
|
};
|
|
11069
11091
|
state.chats = {
|
|
11070
11092
|
...state.chats,
|
|
@@ -11103,8 +11125,58 @@ const chatSlice = createSlice({
|
|
|
11103
11125
|
setCurrentStreamingMessage: (state, action) => {
|
|
11104
11126
|
state.currentStreamingMessage = action.payload;
|
|
11105
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
|
+
},
|
|
11106
11133
|
resetCurrentStreamingMessage: (state) => {
|
|
11107
|
-
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);
|
|
11108
11180
|
},
|
|
11109
11181
|
updateStreamingMessageId: (state, action) => {
|
|
11110
11182
|
const oldId = state.currentStreamingMessage.id;
|
|
@@ -11262,11 +11334,15 @@ const chatSlice = createSlice({
|
|
|
11262
11334
|
}
|
|
11263
11335
|
const activeMessages = state.chats[state.activeTab];
|
|
11264
11336
|
const lastMessage = activeMessages[activeMessages.length - 1];
|
|
11337
|
+
const toolCalls = state.currentStreamingMessage.toolCalls || [];
|
|
11338
|
+
const reasoningContent = state.currentStreamingMessage.reasoningContent || "";
|
|
11265
11339
|
if (!lastMessage || lastMessage.id !== streamingId) {
|
|
11266
11340
|
const temp = {
|
|
11267
11341
|
id: streamingId,
|
|
11268
11342
|
role: "assistant",
|
|
11269
11343
|
content: state.currentStreamingMessage.content,
|
|
11344
|
+
reasoningContent,
|
|
11345
|
+
toolCalls,
|
|
11270
11346
|
timestamp: new Date().toISOString(),
|
|
11271
11347
|
visible: true,
|
|
11272
11348
|
};
|
|
@@ -11275,6 +11351,19 @@ const chatSlice = createSlice({
|
|
|
11275
11351
|
[state.activeTab]: [...activeMessages, temp],
|
|
11276
11352
|
};
|
|
11277
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
|
+
}
|
|
11278
11367
|
},
|
|
11279
11368
|
upsertStreamingArtifactVersionOnLastMessage: (state, action) => {
|
|
11280
11369
|
const { artifactId, title, content, fileExtension, sessionId, versionNumber = 1, username, metadata, isPartial, } = action.payload;
|
|
@@ -11477,6 +11566,16 @@ const selectStreamingArtifactFullContent = (state) => {
|
|
|
11477
11566
|
return null;
|
|
11478
11567
|
return artifact.content + buffer;
|
|
11479
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;
|
|
11480
11579
|
|
|
11481
11580
|
class TimeTracker {
|
|
11482
11581
|
constructor(config) {
|
|
@@ -12262,6 +12361,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12262
12361
|
const currentStreamingMessage = React.useRef({
|
|
12263
12362
|
id: null,
|
|
12264
12363
|
content: "",
|
|
12364
|
+
reasoningContent: "",
|
|
12365
|
+
toolCalls: [],
|
|
12265
12366
|
});
|
|
12266
12367
|
// Track artifact state during streaming
|
|
12267
12368
|
const currentArtifact = React.useRef(null);
|
|
@@ -12275,6 +12376,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12275
12376
|
lastFlushTime: 0,
|
|
12276
12377
|
flushTimer: null,
|
|
12277
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);
|
|
12278
12387
|
const stopGenerationSocket = React.useRef(null);
|
|
12279
12388
|
const isInitialConnection = React.useRef(true);
|
|
12280
12389
|
const connectionAttempts = React.useRef(0);
|
|
@@ -12955,6 +13064,22 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12955
13064
|
}
|
|
12956
13065
|
return;
|
|
12957
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
|
+
}
|
|
12958
13083
|
// Handle start of new streaming session
|
|
12959
13084
|
if (messageData.generation_id &&
|
|
12960
13085
|
!messageData.data &&
|
|
@@ -12967,6 +13092,21 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12967
13092
|
id: messageData.generation_id,
|
|
12968
13093
|
content: "",
|
|
12969
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
|
+
};
|
|
12970
13110
|
onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
|
|
12971
13111
|
onStatusChange("streaming");
|
|
12972
13112
|
onStreamingChange(true);
|
|
@@ -12989,7 +13129,69 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12989
13129
|
// Handle streaming message content (chat text)
|
|
12990
13130
|
if ((messageData === null || messageData === void 0 ? void 0 : messageData.type) !== "chat_messages" &&
|
|
12991
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
|
+
}
|
|
12992
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
|
+
}
|
|
12993
13195
|
// If we have content to add, update the in-memory streaming message and Redux
|
|
12994
13196
|
if (messageText && currentStreamingMessage.current) {
|
|
12995
13197
|
console.log("[ws-message] Streaming content chunk:", {
|
|
@@ -13003,13 +13205,28 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
13003
13205
|
content: currentStreamingMessage.current.content + messageText,
|
|
13004
13206
|
};
|
|
13005
13207
|
onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
|
|
13006
|
-
// Update or add message in Redux store
|
|
13208
|
+
// Update or add message in Redux store - use ensureStreamingAssistantMessage for consistency
|
|
13007
13209
|
if ((_w = currentStreamingMessage.current) === null || _w === void 0 ? void 0 : _w.id) {
|
|
13008
|
-
|
|
13009
|
-
dispatch(chatActions.appendMessageToActiveTab(undefined));
|
|
13210
|
+
dispatch(chatActions.ensureStreamingAssistantMessage(undefined));
|
|
13010
13211
|
}
|
|
13011
13212
|
}
|
|
13012
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
|
+
}
|
|
13013
13230
|
// Handle end of stream
|
|
13014
13231
|
const hasPendingArtifact = !!pendingArtifactVersion.current;
|
|
13015
13232
|
const hasMessageContent = !!((_x = currentStreamingMessage.current) === null || _x === void 0 ? void 0 : _x.content) &&
|
|
@@ -13624,7 +13841,13 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13624
13841
|
dispatch(chatActions.setStatus(status));
|
|
13625
13842
|
};
|
|
13626
13843
|
const onStreamingMessageUpdate = (message) => {
|
|
13627
|
-
|
|
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
|
+
}
|
|
13628
13851
|
};
|
|
13629
13852
|
const { sendMessage, stopGenerating, ws, isConnected, messageQueue, resetConnection, } = useChat({
|
|
13630
13853
|
wsUrl,
|
|
@@ -13706,7 +13929,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13706
13929
|
try {
|
|
13707
13930
|
previousChats =
|
|
13708
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) => {
|
|
13709
|
-
var _a, _b, _c;
|
|
13932
|
+
var _a, _b, _c, _d, _e, _f;
|
|
13710
13933
|
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
13711
13934
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
13712
13935
|
return ({
|
|
@@ -13745,6 +13968,30 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13745
13968
|
fileSize: file.file_size,
|
|
13746
13969
|
uploadUrl: file.url,
|
|
13747
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;
|
|
13748
13995
|
return {
|
|
13749
13996
|
...result,
|
|
13750
13997
|
role: result.type === "human" ? "user" : "assistant",
|
|
@@ -13752,17 +13999,45 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13752
13999
|
id: result.id || new Date().getTime(),
|
|
13753
14000
|
content: typeof result.content === "object" &&
|
|
13754
14001
|
result.content.length > 0
|
|
13755
|
-
? (
|
|
14002
|
+
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
13756
14003
|
: result.content,
|
|
13757
14004
|
// Add transformed artifact versions
|
|
13758
14005
|
artifactVersions: artifactVersions || undefined,
|
|
13759
14006
|
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
14007
|
+
reasoningContent: reasoningContent || undefined,
|
|
14008
|
+
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
13760
14009
|
};
|
|
13761
14010
|
}).reverse()) || [];
|
|
13762
14011
|
}
|
|
13763
14012
|
catch (error) {
|
|
13764
14013
|
console.error(JSON.stringify(error));
|
|
13765
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
|
+
}
|
|
13766
14041
|
dispatch(chatActions.setNewMessages(previousChats));
|
|
13767
14042
|
}
|
|
13768
14043
|
catch (error) {
|
|
@@ -17940,6 +18215,7 @@ exports.ServiceWorkerProvider = ServiceWorkerProvider;
|
|
|
17940
18215
|
exports.SubscriptionFlow = SubscriptionFlow;
|
|
17941
18216
|
exports.SubscriptionFlowV2 = SubscriptionFlowV2;
|
|
17942
18217
|
exports.TOOLS = TOOLS;
|
|
18218
|
+
exports.TOOL_NAME_MAP = TOOL_NAME_MAP;
|
|
17943
18219
|
exports.TenantContext = TenantContext;
|
|
17944
18220
|
exports.TenantContextProvider = TenantContextProvider;
|
|
17945
18221
|
exports.TenantProvider = TenantProvider;
|
|
@@ -18044,6 +18320,7 @@ exports.selectEnableChatActionsPopup = selectEnableChatActionsPopup;
|
|
|
18044
18320
|
exports.selectIframeContext = selectIframeContext;
|
|
18045
18321
|
exports.selectIsError = selectIsError;
|
|
18046
18322
|
exports.selectIsPending = selectIsPending;
|
|
18323
|
+
exports.selectIsReasoning = selectIsReasoning;
|
|
18047
18324
|
exports.selectIsStopped = selectIsStopped;
|
|
18048
18325
|
exports.selectIsTyping = selectIsTyping;
|
|
18049
18326
|
exports.selectLastArtifactContentFlushTime = selectLastArtifactContentFlushTime;
|
|
@@ -18058,6 +18335,8 @@ exports.selectStatus = selectStatus;
|
|
|
18058
18335
|
exports.selectStreaming = selectStreaming;
|
|
18059
18336
|
exports.selectStreamingArtifactContentBuffer = selectStreamingArtifactContentBuffer;
|
|
18060
18337
|
exports.selectStreamingArtifactFullContent = selectStreamingArtifactFullContent;
|
|
18338
|
+
exports.selectStreamingReasoningContent = selectStreamingReasoningContent;
|
|
18339
|
+
exports.selectStreamingToolCalls = selectStreamingToolCalls;
|
|
18061
18340
|
exports.selectToken = selectToken;
|
|
18062
18341
|
exports.selectTokenEnabled = selectTokenEnabled;
|
|
18063
18342
|
exports.selectTools = selectTools;
|