@iblai/web-utils 1.11.0 → 1.11.3
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/chat-privacy/api-slice.d.ts +1398 -0
- package/dist/data-layer/src/features/chat-privacy/constants.d.ts +13 -0
- package/dist/data-layer/src/features/sessions/api-slice.d.ts +122 -252
- package/dist/data-layer/src/features/sessions/constants.d.ts +3 -0
- package/dist/data-layer/src/features/sessions/url.d.ts +9 -0
- package/dist/data-layer/src/features/utils.d.ts +7 -0
- package/dist/data-layer/src/index.d.ts +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +308 -198
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +307 -197
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/web-utils/src/hooks/chat/__tests__/chat-history.utils.test.d.ts +1 -0
- package/dist/web-utils/src/hooks/chat/chat-history.utils.d.ts +10 -0
- package/dist/web-utils/src/hooks/chat/use-advanced-chat.d.ts +3 -0
- package/dist/web-utils/src/hooks/chat/use-chat-history.d.ts +17 -0
- package/dist/web-utils/src/index.mobile.d.ts +8 -0
- package/dist/web-utils/src/index.web.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11315,6 +11315,23 @@ const chatSlice = createSlice({
|
|
|
11315
11315
|
[state.activeTab]: action.payload,
|
|
11316
11316
|
};
|
|
11317
11317
|
},
|
|
11318
|
+
prependOlderMessages: (state, action) => {
|
|
11319
|
+
var _a;
|
|
11320
|
+
const olderMessages = action.payload;
|
|
11321
|
+
if (!olderMessages || olderMessages.length === 0) {
|
|
11322
|
+
return;
|
|
11323
|
+
}
|
|
11324
|
+
const existing = (_a = state.chats[state.activeTab]) !== null && _a !== void 0 ? _a : [];
|
|
11325
|
+
const existingIds = new Set(existing.map((message) => message.id));
|
|
11326
|
+
const deduped = olderMessages.filter((message) => !existingIds.has(message.id));
|
|
11327
|
+
if (deduped.length === 0) {
|
|
11328
|
+
return;
|
|
11329
|
+
}
|
|
11330
|
+
state.chats = {
|
|
11331
|
+
...state.chats,
|
|
11332
|
+
[state.activeTab]: [...deduped, ...existing],
|
|
11333
|
+
};
|
|
11334
|
+
},
|
|
11318
11335
|
resetChats: (state) => {
|
|
11319
11336
|
state.chats = defaultChatState;
|
|
11320
11337
|
},
|
|
@@ -11363,7 +11380,7 @@ const chatSlice = createSlice({
|
|
|
11363
11380
|
}
|
|
11364
11381
|
},
|
|
11365
11382
|
// Force-flush buffered reasoning to currentStreamingMessage
|
|
11366
|
-
flushReasoningBuffer: (state
|
|
11383
|
+
flushReasoningBuffer: (state) => {
|
|
11367
11384
|
if (state.streamingReasoningContentBuffer.length > 0) {
|
|
11368
11385
|
state.currentStreamingMessage.reasoningContent +=
|
|
11369
11386
|
state.streamingReasoningContentBuffer;
|
|
@@ -11376,7 +11393,7 @@ const chatSlice = createSlice({
|
|
|
11376
11393
|
state.currentStreamingMessage.isReasoning = action.payload;
|
|
11377
11394
|
},
|
|
11378
11395
|
// Sets isReasoning = false (triggers UI collapse)
|
|
11379
|
-
setReasoningComplete: (state
|
|
11396
|
+
setReasoningComplete: (state) => {
|
|
11380
11397
|
state.currentStreamingMessage.isReasoning = false;
|
|
11381
11398
|
},
|
|
11382
11399
|
// Appends tool call entry
|
|
@@ -11523,7 +11540,7 @@ const chatSlice = createSlice({
|
|
|
11523
11540
|
}
|
|
11524
11541
|
},
|
|
11525
11542
|
// Force flush any buffered content (called on artifact end or when UI needs update)
|
|
11526
|
-
flushStreamingArtifactBuffer: (state
|
|
11543
|
+
flushStreamingArtifactBuffer: (state) => {
|
|
11527
11544
|
if (state.currentStreamingArtifact &&
|
|
11528
11545
|
state.streamingArtifactContentBuffer.length > 0) {
|
|
11529
11546
|
state.currentStreamingArtifact.content +=
|
|
@@ -11532,7 +11549,7 @@ const chatSlice = createSlice({
|
|
|
11532
11549
|
state.lastArtifactContentFlushTime = Date.now();
|
|
11533
11550
|
}
|
|
11534
11551
|
},
|
|
11535
|
-
ensureStreamingAssistantMessage: (state
|
|
11552
|
+
ensureStreamingAssistantMessage: (state) => {
|
|
11536
11553
|
const streamingId = state.currentStreamingMessage.id;
|
|
11537
11554
|
if (!streamingId) {
|
|
11538
11555
|
return;
|
|
@@ -11672,7 +11689,7 @@ const chatSlice = createSlice({
|
|
|
11672
11689
|
action.payload.fullContent || state.currentStreamingArtifact.content;
|
|
11673
11690
|
}
|
|
11674
11691
|
},
|
|
11675
|
-
clearStreamingArtifact: (state
|
|
11692
|
+
clearStreamingArtifact: (state) => {
|
|
11676
11693
|
// Clear buffer along with artifact
|
|
11677
11694
|
state.streamingArtifactContentBuffer = "";
|
|
11678
11695
|
state.lastArtifactContentFlushTime = 0;
|
|
@@ -13903,6 +13920,281 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
13903
13920
|
};
|
|
13904
13921
|
};
|
|
13905
13922
|
|
|
13923
|
+
const INITIAL_CHAT_PAGE = 1;
|
|
13924
|
+
function normalizeSessionResult(result) {
|
|
13925
|
+
var _a, _b, _c, _d, _e, _f;
|
|
13926
|
+
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
13927
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
13928
|
+
return ({
|
|
13929
|
+
id: av.id,
|
|
13930
|
+
artifact: {
|
|
13931
|
+
id: (_a = av.artifact) === null || _a === void 0 ? void 0 : _a.id,
|
|
13932
|
+
title: (_b = av.artifact) === null || _b === void 0 ? void 0 : _b.title,
|
|
13933
|
+
content: (_c = av.artifact) === null || _c === void 0 ? void 0 : _c.content,
|
|
13934
|
+
file_extension: (_d = av.artifact) === null || _d === void 0 ? void 0 : _d.file_extension,
|
|
13935
|
+
llm_name: (_e = av.artifact) === null || _e === void 0 ? void 0 : _e.llm_name,
|
|
13936
|
+
llm_provider: (_f = av.artifact) === null || _f === void 0 ? void 0 : _f.llm_provider,
|
|
13937
|
+
date_created: (_g = av.artifact) === null || _g === void 0 ? void 0 : _g.date_created,
|
|
13938
|
+
date_updated: (_h = av.artifact) === null || _h === void 0 ? void 0 : _h.date_updated,
|
|
13939
|
+
metadata: (_j = av.artifact) === null || _j === void 0 ? void 0 : _j.metadata,
|
|
13940
|
+
username: (_k = av.artifact) === null || _k === void 0 ? void 0 : _k.username,
|
|
13941
|
+
session_id: (_l = av.artifact) === null || _l === void 0 ? void 0 : _l.session_id,
|
|
13942
|
+
current_version_number: (_m = av.artifact) === null || _m === void 0 ? void 0 : _m.current_version_number,
|
|
13943
|
+
version_count: (_o = av.artifact) === null || _o === void 0 ? void 0 : _o.version_count,
|
|
13944
|
+
},
|
|
13945
|
+
title: av.title,
|
|
13946
|
+
content: av.content,
|
|
13947
|
+
session_id: av.session_id,
|
|
13948
|
+
content_length: av.content_length,
|
|
13949
|
+
is_current: av.is_current,
|
|
13950
|
+
chat_message: av.chat_message,
|
|
13951
|
+
version_number: av.version_number,
|
|
13952
|
+
date_created: av.date_created,
|
|
13953
|
+
created_by: av.created_by,
|
|
13954
|
+
change_summary: av.change_summary,
|
|
13955
|
+
});
|
|
13956
|
+
});
|
|
13957
|
+
const fileAttachments = ((_b = result.files) === null || _b === void 0 ? void 0 : _b.map((file) => ({
|
|
13958
|
+
fileId: String(file.id),
|
|
13959
|
+
fileName: file.name,
|
|
13960
|
+
fileType: file.content_type,
|
|
13961
|
+
fileSize: file.file_size,
|
|
13962
|
+
uploadUrl: file.url,
|
|
13963
|
+
}))) || [];
|
|
13964
|
+
// Extract additional_kwargs - check both direct and nested paths
|
|
13965
|
+
const additionalKwargs = result.additional_kwargs || ((_d = (_c = result.message) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.additional_kwargs);
|
|
13966
|
+
// Extract reasoning content from additional_kwargs
|
|
13967
|
+
const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
|
|
13968
|
+
const reasoningContent = Array.isArray(reasoningSummaries)
|
|
13969
|
+
? reasoningSummaries
|
|
13970
|
+
.map((s) => s.text)
|
|
13971
|
+
.filter(Boolean)
|
|
13972
|
+
.join("\n\n")
|
|
13973
|
+
: undefined;
|
|
13974
|
+
// Extract tool calls from additional_kwargs
|
|
13975
|
+
const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
|
|
13976
|
+
const toolCalls = Array.isArray(toolOutputs)
|
|
13977
|
+
? toolOutputs.map((tool) => {
|
|
13978
|
+
var _a;
|
|
13979
|
+
return ({
|
|
13980
|
+
id: tool.id || "",
|
|
13981
|
+
name: tool.type || "",
|
|
13982
|
+
log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
|
|
13983
|
+
result: tool.status || "",
|
|
13984
|
+
});
|
|
13985
|
+
})
|
|
13986
|
+
: undefined;
|
|
13987
|
+
return {
|
|
13988
|
+
...result,
|
|
13989
|
+
role: result.type === "human" ? "user" : "assistant",
|
|
13990
|
+
visible: true,
|
|
13991
|
+
id: result.id || new Date().getTime(),
|
|
13992
|
+
content: typeof result.content === "object" && result.content.length > 0
|
|
13993
|
+
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
13994
|
+
: result.content,
|
|
13995
|
+
// Add transformed artifact versions
|
|
13996
|
+
artifactVersions: artifactVersions || undefined,
|
|
13997
|
+
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
13998
|
+
reasoningContent: reasoningContent || undefined,
|
|
13999
|
+
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
14000
|
+
};
|
|
14001
|
+
}
|
|
14002
|
+
function normalizeSessionResults(results) {
|
|
14003
|
+
return (results === null || results === void 0 ? void 0 : results.map(normalizeSessionResult).reverse()) || [];
|
|
14004
|
+
}
|
|
14005
|
+
/**
|
|
14006
|
+
* A session re-fetch can omit `additional_kwargs`, dropping reasoning/tool-call
|
|
14007
|
+
* data that is already in memory. Carry those fields forward from the matching
|
|
14008
|
+
* existing message (by content) onto the freshly-fetched message in place.
|
|
14009
|
+
*/
|
|
14010
|
+
function mergeReasoningAndToolCalls(incoming, existing) {
|
|
14011
|
+
if (existing.length === 0 || incoming.length === 0)
|
|
14012
|
+
return;
|
|
14013
|
+
const existingByContent = new Map();
|
|
14014
|
+
for (const m of existing) {
|
|
14015
|
+
if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
|
|
14016
|
+
existingByContent.set(m.content, m);
|
|
14017
|
+
}
|
|
14018
|
+
}
|
|
14019
|
+
if (existingByContent.size === 0)
|
|
14020
|
+
return;
|
|
14021
|
+
for (const msg of incoming) {
|
|
14022
|
+
const match = existingByContent.get(msg.content);
|
|
14023
|
+
if (!match)
|
|
14024
|
+
continue;
|
|
14025
|
+
if (!msg.reasoningContent && match.reasoningContent) {
|
|
14026
|
+
msg.reasoningContent = match.reasoningContent;
|
|
14027
|
+
}
|
|
14028
|
+
if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
|
|
14029
|
+
match.toolCalls &&
|
|
14030
|
+
match.toolCalls.length > 0) {
|
|
14031
|
+
msg.toolCalls = match.toolCalls;
|
|
14032
|
+
}
|
|
14033
|
+
}
|
|
14034
|
+
}
|
|
14035
|
+
|
|
14036
|
+
function useChatHistory({ tenantKey, mentorId, username, cachedSessionId, isOffline = false, }) {
|
|
14037
|
+
const dispatch = useDispatch();
|
|
14038
|
+
const chats = useSelector(selectChats);
|
|
14039
|
+
const activeTab = useSelector(selectActiveTab);
|
|
14040
|
+
const showingSharedChat = useSelector(selectShowingSharedChat);
|
|
14041
|
+
const [isLoadingChats, setIsLoadingChats] = React.useState(true);
|
|
14042
|
+
// Synchronous mirror of `isLoadingChats`. The state setter is async, so a
|
|
14043
|
+
// consumer effect running in the SAME render cycle as `getChats()`
|
|
14044
|
+
// invocation sees a stale `isLoadingChats=false` in its closure even
|
|
14045
|
+
// though `setIsLoadingChats(true)` has been scheduled. The ref flips
|
|
14046
|
+
// immediately (before `getChats` hits its first `await`), giving the
|
|
14047
|
+
// `initialPrompt` injection effect a reliable "fetch in progress" signal
|
|
14048
|
+
// it can read synchronously inside its body.
|
|
14049
|
+
const isLoadingChatsRef = React.useRef(true);
|
|
14050
|
+
const [hasMore, setHasMore] = React.useState(false);
|
|
14051
|
+
const [isLoadingOlderMessages, setIsLoadingOlderMessages] = React.useState(false);
|
|
14052
|
+
const currentPageRef = React.useRef(INITIAL_CHAT_PAGE);
|
|
14053
|
+
const isLoadingOlderRef = React.useRef(false);
|
|
14054
|
+
const [getSessionChats] = dataLayer.useLazyGetSessionIdQuery();
|
|
14055
|
+
const [getSharedSessionChats] = dataLayer.useLazyGetSharedSessionIdQuery();
|
|
14056
|
+
const fetchChatPage = React.useCallback((sessionId, page) => {
|
|
14057
|
+
if (showingSharedChat) {
|
|
14058
|
+
return getSharedSessionChats({
|
|
14059
|
+
sessionId,
|
|
14060
|
+
org: tenantKey,
|
|
14061
|
+
page,
|
|
14062
|
+
pageSize: dataLayer.CHAT_HISTORY_PAGE_SIZE,
|
|
14063
|
+
});
|
|
14064
|
+
}
|
|
14065
|
+
if (!username || username === ANONYMOUS_USERNAME) {
|
|
14066
|
+
return undefined;
|
|
14067
|
+
}
|
|
14068
|
+
return getSessionChats({
|
|
14069
|
+
sessionId,
|
|
14070
|
+
org: tenantKey,
|
|
14071
|
+
userId: username,
|
|
14072
|
+
page,
|
|
14073
|
+
pageSize: dataLayer.CHAT_HISTORY_PAGE_SIZE,
|
|
14074
|
+
});
|
|
14075
|
+
}, [
|
|
14076
|
+
showingSharedChat,
|
|
14077
|
+
getSharedSessionChats,
|
|
14078
|
+
getSessionChats,
|
|
14079
|
+
tenantKey,
|
|
14080
|
+
username,
|
|
14081
|
+
]);
|
|
14082
|
+
const getChats = React.useCallback(async () => {
|
|
14083
|
+
var _a, _b, _c, _d;
|
|
14084
|
+
// Mark the fetch as in-flight so consumers gated on `isLoadingChats`
|
|
14085
|
+
// (e.g. the `initialPrompt` injection effect) defer until the resulting
|
|
14086
|
+
// `setNewMessages` has landed. The state setter alone is not enough —
|
|
14087
|
+
// it's async and the consumer effect may run in the same render cycle
|
|
14088
|
+
// with the stale closure — so flip the synchronous ref FIRST.
|
|
14089
|
+
isLoadingChatsRef.current = true;
|
|
14090
|
+
setIsLoadingChats(true);
|
|
14091
|
+
let data;
|
|
14092
|
+
try {
|
|
14093
|
+
data = await fetchChatPage((_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : "", INITIAL_CHAT_PAGE);
|
|
14094
|
+
let previousChats = [];
|
|
14095
|
+
try {
|
|
14096
|
+
previousChats = normalizeSessionResults((_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.results);
|
|
14097
|
+
}
|
|
14098
|
+
catch (error) {
|
|
14099
|
+
console.error(JSON.stringify(error));
|
|
14100
|
+
}
|
|
14101
|
+
const nextPage = (_d = (_c = data === null || data === void 0 ? void 0 : data.data) === null || _c === void 0 ? void 0 : _c.next) !== null && _d !== void 0 ? _d : null;
|
|
14102
|
+
currentPageRef.current = INITIAL_CHAT_PAGE;
|
|
14103
|
+
setHasMore(nextPage !== null);
|
|
14104
|
+
mergeReasoningAndToolCalls(previousChats, chats[activeTab] || []);
|
|
14105
|
+
dispatch(chatActions.setNewMessages(previousChats));
|
|
14106
|
+
}
|
|
14107
|
+
catch (error) {
|
|
14108
|
+
console.error(JSON.stringify(error));
|
|
14109
|
+
}
|
|
14110
|
+
finally {
|
|
14111
|
+
setIsLoadingChats(false);
|
|
14112
|
+
isLoadingChatsRef.current = false;
|
|
14113
|
+
}
|
|
14114
|
+
}, [fetchChatPage, cachedSessionId, mentorId, dispatch]);
|
|
14115
|
+
const loadOlderMessages = React.useCallback(async () => {
|
|
14116
|
+
var _a, _b, _c;
|
|
14117
|
+
if (isLoadingOlderRef.current)
|
|
14118
|
+
return;
|
|
14119
|
+
if (!hasMore)
|
|
14120
|
+
return;
|
|
14121
|
+
if (isOffline)
|
|
14122
|
+
return;
|
|
14123
|
+
if (!showingSharedChat && (!username || username === ANONYMOUS_USERNAME)) {
|
|
14124
|
+
return;
|
|
14125
|
+
}
|
|
14126
|
+
const activeSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14127
|
+
if (!activeSessionId)
|
|
14128
|
+
return;
|
|
14129
|
+
isLoadingOlderRef.current = true;
|
|
14130
|
+
setIsLoadingOlderMessages(true);
|
|
14131
|
+
const nextPage = currentPageRef.current + 1;
|
|
14132
|
+
try {
|
|
14133
|
+
const data = await fetchChatPage(activeSessionId, nextPage);
|
|
14134
|
+
let olderChats = [];
|
|
14135
|
+
try {
|
|
14136
|
+
olderChats = normalizeSessionResults((_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.results);
|
|
14137
|
+
}
|
|
14138
|
+
catch (error) {
|
|
14139
|
+
console.error(JSON.stringify(error));
|
|
14140
|
+
}
|
|
14141
|
+
if (olderChats.length > 0) {
|
|
14142
|
+
dispatch(chatActions.prependOlderMessages(olderChats));
|
|
14143
|
+
}
|
|
14144
|
+
currentPageRef.current = nextPage;
|
|
14145
|
+
setHasMore(((_c = (_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.next) !== null && _c !== void 0 ? _c : null) !== null);
|
|
14146
|
+
}
|
|
14147
|
+
catch (error) {
|
|
14148
|
+
console.error(JSON.stringify(error));
|
|
14149
|
+
}
|
|
14150
|
+
finally {
|
|
14151
|
+
isLoadingOlderRef.current = false;
|
|
14152
|
+
setIsLoadingOlderMessages(false);
|
|
14153
|
+
}
|
|
14154
|
+
}, [
|
|
14155
|
+
hasMore,
|
|
14156
|
+
isOffline,
|
|
14157
|
+
showingSharedChat,
|
|
14158
|
+
username,
|
|
14159
|
+
cachedSessionId,
|
|
14160
|
+
mentorId,
|
|
14161
|
+
fetchChatPage,
|
|
14162
|
+
dispatch,
|
|
14163
|
+
]);
|
|
14164
|
+
// Depend on the indexed string session id, not the whole `cachedSessionId`
|
|
14165
|
+
// object. Consumers (e.g. `useLocalStorage`) often re-emit a new object
|
|
14166
|
+
// reference on every render even when the underlying value is unchanged,
|
|
14167
|
+
// which would otherwise cause this effect to re-fire `getChats()` per
|
|
14168
|
+
// render — and each `setNewMessages` would wipe any user message
|
|
14169
|
+
// dispatched in between (the URL `initialPrompt` race).
|
|
14170
|
+
const currentMentorSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14171
|
+
React.useEffect(() => {
|
|
14172
|
+
if (currentMentorSessionId) {
|
|
14173
|
+
dispatch(chatActions.updateSessionIds(currentMentorSessionId));
|
|
14174
|
+
// Skip fetching previous chats when offline
|
|
14175
|
+
if (!isOffline) {
|
|
14176
|
+
getChats();
|
|
14177
|
+
}
|
|
14178
|
+
else {
|
|
14179
|
+
setIsLoadingChats(false);
|
|
14180
|
+
isLoadingChatsRef.current = false;
|
|
14181
|
+
}
|
|
14182
|
+
}
|
|
14183
|
+
else {
|
|
14184
|
+
setIsLoadingChats(false);
|
|
14185
|
+
isLoadingChatsRef.current = false;
|
|
14186
|
+
}
|
|
14187
|
+
}, [currentMentorSessionId, isOffline]);
|
|
14188
|
+
return {
|
|
14189
|
+
getChats,
|
|
14190
|
+
loadOlderMessages,
|
|
14191
|
+
hasMore,
|
|
14192
|
+
isLoadingOlderMessages,
|
|
14193
|
+
isLoadingChats,
|
|
14194
|
+
isLoadingChatsRef,
|
|
14195
|
+
};
|
|
14196
|
+
}
|
|
14197
|
+
|
|
13906
14198
|
function useMentorSettings({ mentorId, tenantKey, isPublicRoute = false, mainTenantKey, }) {
|
|
13907
14199
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
|
|
13908
14200
|
const username = useUsername();
|
|
@@ -14078,7 +14370,13 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14078
14370
|
isOffline,
|
|
14079
14371
|
onOfflineWithoutLocalLLM,
|
|
14080
14372
|
});
|
|
14081
|
-
const
|
|
14373
|
+
const { getChats, loadOlderMessages, hasMore, isLoadingOlderMessages, isLoadingChats, isLoadingChatsRef, } = useChatHistory({
|
|
14374
|
+
tenantKey,
|
|
14375
|
+
mentorId,
|
|
14376
|
+
username,
|
|
14377
|
+
cachedSessionId,
|
|
14378
|
+
isOffline,
|
|
14379
|
+
});
|
|
14082
14380
|
// Tracks whether the optional `initialPrompt` prop has already been
|
|
14083
14381
|
// auto-submitted for this hook instance. Set to `true` the moment the
|
|
14084
14382
|
// effect decides to act (either to send or because the prompt is already
|
|
@@ -14095,197 +14393,6 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14095
14393
|
// that wipes anything dispatched (like `initialPrompt`'s
|
|
14096
14394
|
// `addUserMessage`) between the two `getChats` resolutions.
|
|
14097
14395
|
const startNewChatInFlightRef = React.useRef(false);
|
|
14098
|
-
// Synchronous mirror of `isLoadingChats`. The state setter is async, so a
|
|
14099
|
-
// consumer effect running in the SAME render cycle as `getChats()`
|
|
14100
|
-
// invocation sees a stale `isLoadingChats=false` in its closure even
|
|
14101
|
-
// though `setIsLoadingChats(true)` has been scheduled. The ref flips
|
|
14102
|
-
// immediately (before `getChats` hits its first `await`), giving the
|
|
14103
|
-
// `initialPrompt` injection effect a reliable "fetch in progress" signal
|
|
14104
|
-
// it can read synchronously inside its body.
|
|
14105
|
-
const isLoadingChatsRef = React.useRef(true);
|
|
14106
|
-
const [getSessionChats] = dataLayer.useLazyGetSessionIdQuery();
|
|
14107
|
-
const [getSharedSessionChats] = dataLayer.useLazyGetSharedSessionIdQuery();
|
|
14108
|
-
const getChats = React.useCallback(async () => {
|
|
14109
|
-
var _a, _b, _c, _d;
|
|
14110
|
-
// Mark the fetch as in-flight so consumers gated on `isLoadingChats`
|
|
14111
|
-
// (e.g. the `initialPrompt` injection effect) defer until the resulting
|
|
14112
|
-
// `setNewMessages` has landed. The state setter alone is not enough —
|
|
14113
|
-
// it's async and the consumer effect may run in the same render cycle
|
|
14114
|
-
// with the stale closure — so flip the synchronous ref FIRST.
|
|
14115
|
-
isLoadingChatsRef.current = true;
|
|
14116
|
-
setIsLoadingChats(true);
|
|
14117
|
-
let data;
|
|
14118
|
-
try {
|
|
14119
|
-
if (showingSharedChat) {
|
|
14120
|
-
data = await getSharedSessionChats({
|
|
14121
|
-
sessionId: (_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : "",
|
|
14122
|
-
org: tenantKey,
|
|
14123
|
-
});
|
|
14124
|
-
}
|
|
14125
|
-
else if (!!username && username !== ANONYMOUS_USERNAME) {
|
|
14126
|
-
data = await getSessionChats({
|
|
14127
|
-
sessionId: (_b = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _b !== void 0 ? _b : "",
|
|
14128
|
-
org: tenantKey,
|
|
14129
|
-
// @ts-expect-error - userId is passed but not in generated API types
|
|
14130
|
-
userId: username,
|
|
14131
|
-
});
|
|
14132
|
-
}
|
|
14133
|
-
let previousChats = [];
|
|
14134
|
-
try {
|
|
14135
|
-
previousChats =
|
|
14136
|
-
((_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) => {
|
|
14137
|
-
var _a, _b, _c, _d, _e, _f;
|
|
14138
|
-
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
14139
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
14140
|
-
return ({
|
|
14141
|
-
id: av.id,
|
|
14142
|
-
artifact: {
|
|
14143
|
-
id: (_a = av.artifact) === null || _a === void 0 ? void 0 : _a.id,
|
|
14144
|
-
title: (_b = av.artifact) === null || _b === void 0 ? void 0 : _b.title,
|
|
14145
|
-
content: (_c = av.artifact) === null || _c === void 0 ? void 0 : _c.content,
|
|
14146
|
-
file_extension: (_d = av.artifact) === null || _d === void 0 ? void 0 : _d.file_extension,
|
|
14147
|
-
llm_name: (_e = av.artifact) === null || _e === void 0 ? void 0 : _e.llm_name,
|
|
14148
|
-
llm_provider: (_f = av.artifact) === null || _f === void 0 ? void 0 : _f.llm_provider,
|
|
14149
|
-
date_created: (_g = av.artifact) === null || _g === void 0 ? void 0 : _g.date_created,
|
|
14150
|
-
date_updated: (_h = av.artifact) === null || _h === void 0 ? void 0 : _h.date_updated,
|
|
14151
|
-
metadata: (_j = av.artifact) === null || _j === void 0 ? void 0 : _j.metadata,
|
|
14152
|
-
username: (_k = av.artifact) === null || _k === void 0 ? void 0 : _k.username,
|
|
14153
|
-
session_id: (_l = av.artifact) === null || _l === void 0 ? void 0 : _l.session_id,
|
|
14154
|
-
current_version_number: (_m = av.artifact) === null || _m === void 0 ? void 0 : _m.current_version_number,
|
|
14155
|
-
version_count: (_o = av.artifact) === null || _o === void 0 ? void 0 : _o.version_count,
|
|
14156
|
-
},
|
|
14157
|
-
title: av.title,
|
|
14158
|
-
content: av.content,
|
|
14159
|
-
session_id: av.session_id,
|
|
14160
|
-
content_length: av.content_length,
|
|
14161
|
-
is_current: av.is_current,
|
|
14162
|
-
chat_message: av.chat_message,
|
|
14163
|
-
version_number: av.version_number,
|
|
14164
|
-
date_created: av.date_created,
|
|
14165
|
-
created_by: av.created_by,
|
|
14166
|
-
change_summary: av.change_summary,
|
|
14167
|
-
});
|
|
14168
|
-
});
|
|
14169
|
-
const fileAttachments = ((_b = result.files) === null || _b === void 0 ? void 0 : _b.map((file) => ({
|
|
14170
|
-
fileId: String(file.id),
|
|
14171
|
-
fileName: file.name,
|
|
14172
|
-
fileType: file.content_type,
|
|
14173
|
-
fileSize: file.file_size,
|
|
14174
|
-
uploadUrl: file.url,
|
|
14175
|
-
}))) || [];
|
|
14176
|
-
// Extract additional_kwargs - check both direct and nested paths
|
|
14177
|
-
const additionalKwargs = result.additional_kwargs ||
|
|
14178
|
-
((_d = (_c = result.message) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.additional_kwargs);
|
|
14179
|
-
// Extract reasoning content from additional_kwargs
|
|
14180
|
-
const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
|
|
14181
|
-
const reasoningContent = Array.isArray(reasoningSummaries)
|
|
14182
|
-
? reasoningSummaries
|
|
14183
|
-
.map((s) => s.text)
|
|
14184
|
-
.filter(Boolean)
|
|
14185
|
-
.join("\n\n")
|
|
14186
|
-
: undefined;
|
|
14187
|
-
// Extract tool calls from additional_kwargs
|
|
14188
|
-
const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
|
|
14189
|
-
const toolCalls = Array.isArray(toolOutputs)
|
|
14190
|
-
? toolOutputs.map((tool) => {
|
|
14191
|
-
var _a;
|
|
14192
|
-
return ({
|
|
14193
|
-
id: tool.id || "",
|
|
14194
|
-
name: tool.type || "",
|
|
14195
|
-
log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
|
|
14196
|
-
result: tool.status || "",
|
|
14197
|
-
});
|
|
14198
|
-
})
|
|
14199
|
-
: undefined;
|
|
14200
|
-
return {
|
|
14201
|
-
...result,
|
|
14202
|
-
role: result.type === "human" ? "user" : "assistant",
|
|
14203
|
-
visible: true,
|
|
14204
|
-
id: result.id || new Date().getTime(),
|
|
14205
|
-
content: typeof result.content === "object" &&
|
|
14206
|
-
result.content.length > 0
|
|
14207
|
-
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
14208
|
-
: result.content,
|
|
14209
|
-
// Add transformed artifact versions
|
|
14210
|
-
artifactVersions: artifactVersions || undefined,
|
|
14211
|
-
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
14212
|
-
reasoningContent: reasoningContent || undefined,
|
|
14213
|
-
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
14214
|
-
};
|
|
14215
|
-
}).reverse()) || [];
|
|
14216
|
-
}
|
|
14217
|
-
catch (error) {
|
|
14218
|
-
console.error(JSON.stringify(error));
|
|
14219
|
-
}
|
|
14220
|
-
// Preserve reasoningContent and toolCalls from existing messages
|
|
14221
|
-
// when the session API re-fetch doesn't include additional_kwargs.
|
|
14222
|
-
const existingMessages = chats[activeTab] || [];
|
|
14223
|
-
if (existingMessages.length > 0 && previousChats.length > 0) {
|
|
14224
|
-
const existingByContent = new Map();
|
|
14225
|
-
for (const m of existingMessages) {
|
|
14226
|
-
if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
|
|
14227
|
-
existingByContent.set(m.content, m);
|
|
14228
|
-
}
|
|
14229
|
-
}
|
|
14230
|
-
if (existingByContent.size > 0) {
|
|
14231
|
-
for (const msg of previousChats) {
|
|
14232
|
-
const existing = existingByContent.get(msg.content);
|
|
14233
|
-
if (existing) {
|
|
14234
|
-
if (!msg.reasoningContent && existing.reasoningContent) {
|
|
14235
|
-
msg.reasoningContent = existing.reasoningContent;
|
|
14236
|
-
}
|
|
14237
|
-
if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
|
|
14238
|
-
existing.toolCalls &&
|
|
14239
|
-
existing.toolCalls.length > 0) {
|
|
14240
|
-
msg.toolCalls = existing.toolCalls;
|
|
14241
|
-
}
|
|
14242
|
-
}
|
|
14243
|
-
}
|
|
14244
|
-
}
|
|
14245
|
-
}
|
|
14246
|
-
dispatch(chatActions.setNewMessages(previousChats));
|
|
14247
|
-
}
|
|
14248
|
-
catch (error) {
|
|
14249
|
-
console.error(JSON.stringify(error));
|
|
14250
|
-
}
|
|
14251
|
-
finally {
|
|
14252
|
-
setIsLoadingChats(false);
|
|
14253
|
-
isLoadingChatsRef.current = false;
|
|
14254
|
-
}
|
|
14255
|
-
}, [
|
|
14256
|
-
showingSharedChat,
|
|
14257
|
-
cachedSessionId,
|
|
14258
|
-
mentorId,
|
|
14259
|
-
tenantKey,
|
|
14260
|
-
username,
|
|
14261
|
-
getSharedSessionChats,
|
|
14262
|
-
getSessionChats,
|
|
14263
|
-
dispatch,
|
|
14264
|
-
]);
|
|
14265
|
-
// Depend on the indexed string session id, not the whole `cachedSessionId`
|
|
14266
|
-
// object. Consumers (e.g. `useLocalStorage`) often re-emit a new object
|
|
14267
|
-
// reference on every render even when the underlying value is unchanged,
|
|
14268
|
-
// which would otherwise cause this effect to re-fire `getChats()` per
|
|
14269
|
-
// render — and each `setNewMessages` would wipe any user message
|
|
14270
|
-
// dispatched in between (the URL `initialPrompt` race).
|
|
14271
|
-
const currentMentorSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14272
|
-
React.useEffect(() => {
|
|
14273
|
-
if (currentMentorSessionId) {
|
|
14274
|
-
dispatch(chatActions.updateSessionIds(currentMentorSessionId));
|
|
14275
|
-
// Skip fetching previous chats when offline
|
|
14276
|
-
if (!isOffline) {
|
|
14277
|
-
getChats();
|
|
14278
|
-
}
|
|
14279
|
-
else {
|
|
14280
|
-
setIsLoadingChats(false);
|
|
14281
|
-
isLoadingChatsRef.current = false;
|
|
14282
|
-
}
|
|
14283
|
-
}
|
|
14284
|
-
else {
|
|
14285
|
-
setIsLoadingChats(false);
|
|
14286
|
-
isLoadingChatsRef.current = false;
|
|
14287
|
-
}
|
|
14288
|
-
}, [currentMentorSessionId, isOffline]);
|
|
14289
14396
|
const startNewChat = React.useCallback(async () => {
|
|
14290
14397
|
// Reset all chat state
|
|
14291
14398
|
if (!showingSharedChat) {
|
|
@@ -14518,6 +14625,9 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14518
14625
|
resetConnection,
|
|
14519
14626
|
isLoadingChats,
|
|
14520
14627
|
refetchChats: getChats,
|
|
14628
|
+
loadOlderMessages,
|
|
14629
|
+
hasMore,
|
|
14630
|
+
isLoadingOlderMessages,
|
|
14521
14631
|
};
|
|
14522
14632
|
}
|
|
14523
14633
|
|