@iblai/web-utils 1.11.2 → 1.11.4
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/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/index.d.ts +4 -1
- package/dist/index.esm.js +312 -202
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +311 -201
- 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/package.json +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type GetSessionIdArgs = {
|
|
2
|
+
org: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
userId?: string;
|
|
5
|
+
page?: number;
|
|
6
|
+
pageSize?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const buildSessionRetrieveUrl: ({ org, sessionId, userId, page, pageSize, }: GetSessionIdArgs) => string;
|
|
9
|
+
export declare const buildSharedSessionRetrieveUrl: ({ org, sessionId, userId, page, pageSize, }: GetSessionIdArgs) => string;
|
|
@@ -50,6 +50,13 @@ export declare const buildEndpointFromDmService: <Args extends Record<string, un
|
|
|
50
50
|
export declare const buildEndpointFromAxdService: <Args extends Record<string, unknown>, Result>(serviceFn: (args: Args) => Promise<Result>, options?: BuildEndpointOptions) => {
|
|
51
51
|
queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Build an endpoint from a hand-assembled URL (rather than a generated service
|
|
55
|
+
* method), routed through `iblFetchBaseQuery`. Defaults to the DM service.
|
|
56
|
+
*/
|
|
57
|
+
export declare const buildEndpointFromDmUrl: <Args extends Record<string, unknown>, Result>(buildUrl: (args: Args) => string, service?: SERVICES) => {
|
|
58
|
+
queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
|
|
59
|
+
};
|
|
53
60
|
export interface CustomQueryArgs extends Omit<FetchArgs, 'url'> {
|
|
54
61
|
url: string;
|
|
55
62
|
service: SERVICES;
|
package/dist/index.d.ts
CHANGED
|
@@ -1101,7 +1101,7 @@ declare const isNode: () => string | false;
|
|
|
1101
1101
|
declare const isExpo: () => any;
|
|
1102
1102
|
declare const isTauri: () => boolean;
|
|
1103
1103
|
declare function isSafariBrowser(): boolean;
|
|
1104
|
-
declare const getPlatform: () => "
|
|
1104
|
+
declare const getPlatform: () => "web" | "react-native" | "node" | "unknown";
|
|
1105
1105
|
declare const safeRequire: (moduleName: string) => any;
|
|
1106
1106
|
declare const getNextNavigation: () => any;
|
|
1107
1107
|
|
|
@@ -1587,6 +1587,9 @@ declare function useAdvancedChat({ tenantKey, mentorId, username, token, wsUrl,
|
|
|
1587
1587
|
resetConnection: () => void;
|
|
1588
1588
|
isLoadingChats: boolean;
|
|
1589
1589
|
refetchChats: () => Promise<void>;
|
|
1590
|
+
loadOlderMessages: () => Promise<void>;
|
|
1591
|
+
hasMore: boolean;
|
|
1592
|
+
isLoadingOlderMessages: boolean;
|
|
1590
1593
|
};
|
|
1591
1594
|
|
|
1592
1595
|
type Props$6 = {
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default, { useRef, useEffect, useState, useLayoutEffect, useCallback, createContext, useContext, useMemo } from 'react';
|
|
3
|
-
import { useRenewSubscriptionMutation, useLazyGetUserAppsQuery, useCreateStripeCustomerPortalMutation, useLazyGetFreeUsageCountQuery, useGetTenantMetadataQuery, useLazyGetStripeContextQuery, useUpdateUserTrialStatusMutation, useLazyGetAccountBillingInfoQuery, useLazyRefreshJwtTokenQuery, useLazyGetUserTenantsQuery, useJoinTenantMutation, useLazyGetTenantMetadataQuery, useGetAppTokensMutation, useGetCustomDomainsQuery, useGetRbacPermissionsMutation, useLazyGetMentorsQuery, useLazySeedMentorsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetRecentlyAccessedMentorsQuery, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useGetMemsearchStatusQuery, useCreateSessionIdMutation,
|
|
3
|
+
import { useRenewSubscriptionMutation, useLazyGetUserAppsQuery, useCreateStripeCustomerPortalMutation, useLazyGetFreeUsageCountQuery, useGetTenantMetadataQuery, useLazyGetStripeContextQuery, useUpdateUserTrialStatusMutation, useLazyGetAccountBillingInfoQuery, useLazyRefreshJwtTokenQuery, useLazyGetUserTenantsQuery, useJoinTenantMutation, useLazyGetTenantMetadataQuery, useGetAppTokensMutation, useGetCustomDomainsQuery, useGetRbacPermissionsMutation, useLazyGetMentorsQuery, useLazySeedMentorsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetRecentlyAccessedMentorsQuery, useLazyGetSessionIdQuery, useLazyGetSharedSessionIdQuery, CHAT_HISTORY_PAGE_SIZE, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useGetMemsearchStatusQuery, useCreateSessionIdMutation, useEditSessionMutation, useGetToolsQuery, useGetPromptsSearchQuery, useUpdateUserAccountMutation, useGetUserMetadataQuery, useUploadProfileImageMutation, useRemoveProfileImageMutation, useLazyGetStripePricingPageSessionQuery, useGetFileUploadUrlMutation, useGetDisclaimersQuery, useAgreeToDisclaimerMutation, useLazyGetGuidedPromptsQuery, useAudioToTextMutation } from '@iblai/data-layer';
|
|
4
4
|
import { toast } from 'sonner';
|
|
5
5
|
import { platform } from '@tauri-apps/plugin-os';
|
|
6
6
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -947,9 +947,9 @@ const BASE_CONFIG = {
|
|
|
947
947
|
},
|
|
948
948
|
{
|
|
949
949
|
slug: "overall_default_mentor",
|
|
950
|
-
label: "Default
|
|
950
|
+
label: "Default Agent",
|
|
951
951
|
defaultValue: "",
|
|
952
|
-
description: "Default
|
|
952
|
+
description: "Default agent to open on the platform",
|
|
953
953
|
type: "string",
|
|
954
954
|
},
|
|
955
955
|
/* {
|
|
@@ -1087,9 +1087,9 @@ const MENTOR_AI_CONFIG = {
|
|
|
1087
1087
|
},
|
|
1088
1088
|
{
|
|
1089
1089
|
slug: "mentor_include_community_mentors",
|
|
1090
|
-
label: "Community
|
|
1090
|
+
label: "Community Agents",
|
|
1091
1091
|
defaultValue: true,
|
|
1092
|
-
description: "Allow users to access the
|
|
1092
|
+
description: "Allow users to access the agents from the community.",
|
|
1093
1093
|
type: "boolean",
|
|
1094
1094
|
},
|
|
1095
1095
|
{
|
|
@@ -11295,6 +11295,23 @@ const chatSlice = createSlice({
|
|
|
11295
11295
|
[state.activeTab]: action.payload,
|
|
11296
11296
|
};
|
|
11297
11297
|
},
|
|
11298
|
+
prependOlderMessages: (state, action) => {
|
|
11299
|
+
var _a;
|
|
11300
|
+
const olderMessages = action.payload;
|
|
11301
|
+
if (!olderMessages || olderMessages.length === 0) {
|
|
11302
|
+
return;
|
|
11303
|
+
}
|
|
11304
|
+
const existing = (_a = state.chats[state.activeTab]) !== null && _a !== void 0 ? _a : [];
|
|
11305
|
+
const existingIds = new Set(existing.map((message) => message.id));
|
|
11306
|
+
const deduped = olderMessages.filter((message) => !existingIds.has(message.id));
|
|
11307
|
+
if (deduped.length === 0) {
|
|
11308
|
+
return;
|
|
11309
|
+
}
|
|
11310
|
+
state.chats = {
|
|
11311
|
+
...state.chats,
|
|
11312
|
+
[state.activeTab]: [...deduped, ...existing],
|
|
11313
|
+
};
|
|
11314
|
+
},
|
|
11298
11315
|
resetChats: (state) => {
|
|
11299
11316
|
state.chats = defaultChatState;
|
|
11300
11317
|
},
|
|
@@ -11343,7 +11360,7 @@ const chatSlice = createSlice({
|
|
|
11343
11360
|
}
|
|
11344
11361
|
},
|
|
11345
11362
|
// Force-flush buffered reasoning to currentStreamingMessage
|
|
11346
|
-
flushReasoningBuffer: (state
|
|
11363
|
+
flushReasoningBuffer: (state) => {
|
|
11347
11364
|
if (state.streamingReasoningContentBuffer.length > 0) {
|
|
11348
11365
|
state.currentStreamingMessage.reasoningContent +=
|
|
11349
11366
|
state.streamingReasoningContentBuffer;
|
|
@@ -11356,7 +11373,7 @@ const chatSlice = createSlice({
|
|
|
11356
11373
|
state.currentStreamingMessage.isReasoning = action.payload;
|
|
11357
11374
|
},
|
|
11358
11375
|
// Sets isReasoning = false (triggers UI collapse)
|
|
11359
|
-
setReasoningComplete: (state
|
|
11376
|
+
setReasoningComplete: (state) => {
|
|
11360
11377
|
state.currentStreamingMessage.isReasoning = false;
|
|
11361
11378
|
},
|
|
11362
11379
|
// Appends tool call entry
|
|
@@ -11503,7 +11520,7 @@ const chatSlice = createSlice({
|
|
|
11503
11520
|
}
|
|
11504
11521
|
},
|
|
11505
11522
|
// Force flush any buffered content (called on artifact end or when UI needs update)
|
|
11506
|
-
flushStreamingArtifactBuffer: (state
|
|
11523
|
+
flushStreamingArtifactBuffer: (state) => {
|
|
11507
11524
|
if (state.currentStreamingArtifact &&
|
|
11508
11525
|
state.streamingArtifactContentBuffer.length > 0) {
|
|
11509
11526
|
state.currentStreamingArtifact.content +=
|
|
@@ -11512,7 +11529,7 @@ const chatSlice = createSlice({
|
|
|
11512
11529
|
state.lastArtifactContentFlushTime = Date.now();
|
|
11513
11530
|
}
|
|
11514
11531
|
},
|
|
11515
|
-
ensureStreamingAssistantMessage: (state
|
|
11532
|
+
ensureStreamingAssistantMessage: (state) => {
|
|
11516
11533
|
const streamingId = state.currentStreamingMessage.id;
|
|
11517
11534
|
if (!streamingId) {
|
|
11518
11535
|
return;
|
|
@@ -11652,7 +11669,7 @@ const chatSlice = createSlice({
|
|
|
11652
11669
|
action.payload.fullContent || state.currentStreamingArtifact.content;
|
|
11653
11670
|
}
|
|
11654
11671
|
},
|
|
11655
|
-
clearStreamingArtifact: (state
|
|
11672
|
+
clearStreamingArtifact: (state) => {
|
|
11656
11673
|
// Clear buffer along with artifact
|
|
11657
11674
|
state.streamingArtifactContentBuffer = "";
|
|
11658
11675
|
state.lastArtifactContentFlushTime = 0;
|
|
@@ -13883,6 +13900,281 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
13883
13900
|
};
|
|
13884
13901
|
};
|
|
13885
13902
|
|
|
13903
|
+
const INITIAL_CHAT_PAGE = 1;
|
|
13904
|
+
function normalizeSessionResult(result) {
|
|
13905
|
+
var _a, _b, _c, _d, _e, _f;
|
|
13906
|
+
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
13907
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
13908
|
+
return ({
|
|
13909
|
+
id: av.id,
|
|
13910
|
+
artifact: {
|
|
13911
|
+
id: (_a = av.artifact) === null || _a === void 0 ? void 0 : _a.id,
|
|
13912
|
+
title: (_b = av.artifact) === null || _b === void 0 ? void 0 : _b.title,
|
|
13913
|
+
content: (_c = av.artifact) === null || _c === void 0 ? void 0 : _c.content,
|
|
13914
|
+
file_extension: (_d = av.artifact) === null || _d === void 0 ? void 0 : _d.file_extension,
|
|
13915
|
+
llm_name: (_e = av.artifact) === null || _e === void 0 ? void 0 : _e.llm_name,
|
|
13916
|
+
llm_provider: (_f = av.artifact) === null || _f === void 0 ? void 0 : _f.llm_provider,
|
|
13917
|
+
date_created: (_g = av.artifact) === null || _g === void 0 ? void 0 : _g.date_created,
|
|
13918
|
+
date_updated: (_h = av.artifact) === null || _h === void 0 ? void 0 : _h.date_updated,
|
|
13919
|
+
metadata: (_j = av.artifact) === null || _j === void 0 ? void 0 : _j.metadata,
|
|
13920
|
+
username: (_k = av.artifact) === null || _k === void 0 ? void 0 : _k.username,
|
|
13921
|
+
session_id: (_l = av.artifact) === null || _l === void 0 ? void 0 : _l.session_id,
|
|
13922
|
+
current_version_number: (_m = av.artifact) === null || _m === void 0 ? void 0 : _m.current_version_number,
|
|
13923
|
+
version_count: (_o = av.artifact) === null || _o === void 0 ? void 0 : _o.version_count,
|
|
13924
|
+
},
|
|
13925
|
+
title: av.title,
|
|
13926
|
+
content: av.content,
|
|
13927
|
+
session_id: av.session_id,
|
|
13928
|
+
content_length: av.content_length,
|
|
13929
|
+
is_current: av.is_current,
|
|
13930
|
+
chat_message: av.chat_message,
|
|
13931
|
+
version_number: av.version_number,
|
|
13932
|
+
date_created: av.date_created,
|
|
13933
|
+
created_by: av.created_by,
|
|
13934
|
+
change_summary: av.change_summary,
|
|
13935
|
+
});
|
|
13936
|
+
});
|
|
13937
|
+
const fileAttachments = ((_b = result.files) === null || _b === void 0 ? void 0 : _b.map((file) => ({
|
|
13938
|
+
fileId: String(file.id),
|
|
13939
|
+
fileName: file.name,
|
|
13940
|
+
fileType: file.content_type,
|
|
13941
|
+
fileSize: file.file_size,
|
|
13942
|
+
uploadUrl: file.url,
|
|
13943
|
+
}))) || [];
|
|
13944
|
+
// Extract additional_kwargs - check both direct and nested paths
|
|
13945
|
+
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);
|
|
13946
|
+
// Extract reasoning content from additional_kwargs
|
|
13947
|
+
const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
|
|
13948
|
+
const reasoningContent = Array.isArray(reasoningSummaries)
|
|
13949
|
+
? reasoningSummaries
|
|
13950
|
+
.map((s) => s.text)
|
|
13951
|
+
.filter(Boolean)
|
|
13952
|
+
.join("\n\n")
|
|
13953
|
+
: undefined;
|
|
13954
|
+
// Extract tool calls from additional_kwargs
|
|
13955
|
+
const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
|
|
13956
|
+
const toolCalls = Array.isArray(toolOutputs)
|
|
13957
|
+
? toolOutputs.map((tool) => {
|
|
13958
|
+
var _a;
|
|
13959
|
+
return ({
|
|
13960
|
+
id: tool.id || "",
|
|
13961
|
+
name: tool.type || "",
|
|
13962
|
+
log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
|
|
13963
|
+
result: tool.status || "",
|
|
13964
|
+
});
|
|
13965
|
+
})
|
|
13966
|
+
: undefined;
|
|
13967
|
+
return {
|
|
13968
|
+
...result,
|
|
13969
|
+
role: result.type === "human" ? "user" : "assistant",
|
|
13970
|
+
visible: true,
|
|
13971
|
+
id: result.id || new Date().getTime(),
|
|
13972
|
+
content: typeof result.content === "object" && result.content.length > 0
|
|
13973
|
+
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
13974
|
+
: result.content,
|
|
13975
|
+
// Add transformed artifact versions
|
|
13976
|
+
artifactVersions: artifactVersions || undefined,
|
|
13977
|
+
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
13978
|
+
reasoningContent: reasoningContent || undefined,
|
|
13979
|
+
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
13980
|
+
};
|
|
13981
|
+
}
|
|
13982
|
+
function normalizeSessionResults(results) {
|
|
13983
|
+
return (results === null || results === void 0 ? void 0 : results.map(normalizeSessionResult).reverse()) || [];
|
|
13984
|
+
}
|
|
13985
|
+
/**
|
|
13986
|
+
* A session re-fetch can omit `additional_kwargs`, dropping reasoning/tool-call
|
|
13987
|
+
* data that is already in memory. Carry those fields forward from the matching
|
|
13988
|
+
* existing message (by content) onto the freshly-fetched message in place.
|
|
13989
|
+
*/
|
|
13990
|
+
function mergeReasoningAndToolCalls(incoming, existing) {
|
|
13991
|
+
if (existing.length === 0 || incoming.length === 0)
|
|
13992
|
+
return;
|
|
13993
|
+
const existingByContent = new Map();
|
|
13994
|
+
for (const m of existing) {
|
|
13995
|
+
if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
|
|
13996
|
+
existingByContent.set(m.content, m);
|
|
13997
|
+
}
|
|
13998
|
+
}
|
|
13999
|
+
if (existingByContent.size === 0)
|
|
14000
|
+
return;
|
|
14001
|
+
for (const msg of incoming) {
|
|
14002
|
+
const match = existingByContent.get(msg.content);
|
|
14003
|
+
if (!match)
|
|
14004
|
+
continue;
|
|
14005
|
+
if (!msg.reasoningContent && match.reasoningContent) {
|
|
14006
|
+
msg.reasoningContent = match.reasoningContent;
|
|
14007
|
+
}
|
|
14008
|
+
if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
|
|
14009
|
+
match.toolCalls &&
|
|
14010
|
+
match.toolCalls.length > 0) {
|
|
14011
|
+
msg.toolCalls = match.toolCalls;
|
|
14012
|
+
}
|
|
14013
|
+
}
|
|
14014
|
+
}
|
|
14015
|
+
|
|
14016
|
+
function useChatHistory({ tenantKey, mentorId, username, cachedSessionId, isOffline = false, }) {
|
|
14017
|
+
const dispatch = useDispatch();
|
|
14018
|
+
const chats = useSelector(selectChats);
|
|
14019
|
+
const activeTab = useSelector(selectActiveTab);
|
|
14020
|
+
const showingSharedChat = useSelector(selectShowingSharedChat);
|
|
14021
|
+
const [isLoadingChats, setIsLoadingChats] = useState(true);
|
|
14022
|
+
// Synchronous mirror of `isLoadingChats`. The state setter is async, so a
|
|
14023
|
+
// consumer effect running in the SAME render cycle as `getChats()`
|
|
14024
|
+
// invocation sees a stale `isLoadingChats=false` in its closure even
|
|
14025
|
+
// though `setIsLoadingChats(true)` has been scheduled. The ref flips
|
|
14026
|
+
// immediately (before `getChats` hits its first `await`), giving the
|
|
14027
|
+
// `initialPrompt` injection effect a reliable "fetch in progress" signal
|
|
14028
|
+
// it can read synchronously inside its body.
|
|
14029
|
+
const isLoadingChatsRef = React__default.useRef(true);
|
|
14030
|
+
const [hasMore, setHasMore] = useState(false);
|
|
14031
|
+
const [isLoadingOlderMessages, setIsLoadingOlderMessages] = useState(false);
|
|
14032
|
+
const currentPageRef = React__default.useRef(INITIAL_CHAT_PAGE);
|
|
14033
|
+
const isLoadingOlderRef = React__default.useRef(false);
|
|
14034
|
+
const [getSessionChats] = useLazyGetSessionIdQuery();
|
|
14035
|
+
const [getSharedSessionChats] = useLazyGetSharedSessionIdQuery();
|
|
14036
|
+
const fetchChatPage = React__default.useCallback((sessionId, page) => {
|
|
14037
|
+
if (showingSharedChat) {
|
|
14038
|
+
return getSharedSessionChats({
|
|
14039
|
+
sessionId,
|
|
14040
|
+
org: tenantKey,
|
|
14041
|
+
page,
|
|
14042
|
+
pageSize: CHAT_HISTORY_PAGE_SIZE,
|
|
14043
|
+
});
|
|
14044
|
+
}
|
|
14045
|
+
if (!username || username === ANONYMOUS_USERNAME) {
|
|
14046
|
+
return undefined;
|
|
14047
|
+
}
|
|
14048
|
+
return getSessionChats({
|
|
14049
|
+
sessionId,
|
|
14050
|
+
org: tenantKey,
|
|
14051
|
+
userId: username,
|
|
14052
|
+
page,
|
|
14053
|
+
pageSize: CHAT_HISTORY_PAGE_SIZE,
|
|
14054
|
+
});
|
|
14055
|
+
}, [
|
|
14056
|
+
showingSharedChat,
|
|
14057
|
+
getSharedSessionChats,
|
|
14058
|
+
getSessionChats,
|
|
14059
|
+
tenantKey,
|
|
14060
|
+
username,
|
|
14061
|
+
]);
|
|
14062
|
+
const getChats = React__default.useCallback(async () => {
|
|
14063
|
+
var _a, _b, _c, _d;
|
|
14064
|
+
// Mark the fetch as in-flight so consumers gated on `isLoadingChats`
|
|
14065
|
+
// (e.g. the `initialPrompt` injection effect) defer until the resulting
|
|
14066
|
+
// `setNewMessages` has landed. The state setter alone is not enough —
|
|
14067
|
+
// it's async and the consumer effect may run in the same render cycle
|
|
14068
|
+
// with the stale closure — so flip the synchronous ref FIRST.
|
|
14069
|
+
isLoadingChatsRef.current = true;
|
|
14070
|
+
setIsLoadingChats(true);
|
|
14071
|
+
let data;
|
|
14072
|
+
try {
|
|
14073
|
+
data = await fetchChatPage((_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : "", INITIAL_CHAT_PAGE);
|
|
14074
|
+
let previousChats = [];
|
|
14075
|
+
try {
|
|
14076
|
+
previousChats = normalizeSessionResults((_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.results);
|
|
14077
|
+
}
|
|
14078
|
+
catch (error) {
|
|
14079
|
+
console.error(JSON.stringify(error));
|
|
14080
|
+
}
|
|
14081
|
+
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;
|
|
14082
|
+
currentPageRef.current = INITIAL_CHAT_PAGE;
|
|
14083
|
+
setHasMore(nextPage !== null);
|
|
14084
|
+
mergeReasoningAndToolCalls(previousChats, chats[activeTab] || []);
|
|
14085
|
+
dispatch(chatActions.setNewMessages(previousChats));
|
|
14086
|
+
}
|
|
14087
|
+
catch (error) {
|
|
14088
|
+
console.error(JSON.stringify(error));
|
|
14089
|
+
}
|
|
14090
|
+
finally {
|
|
14091
|
+
setIsLoadingChats(false);
|
|
14092
|
+
isLoadingChatsRef.current = false;
|
|
14093
|
+
}
|
|
14094
|
+
}, [fetchChatPage, cachedSessionId, mentorId, dispatch]);
|
|
14095
|
+
const loadOlderMessages = React__default.useCallback(async () => {
|
|
14096
|
+
var _a, _b, _c;
|
|
14097
|
+
if (isLoadingOlderRef.current)
|
|
14098
|
+
return;
|
|
14099
|
+
if (!hasMore)
|
|
14100
|
+
return;
|
|
14101
|
+
if (isOffline)
|
|
14102
|
+
return;
|
|
14103
|
+
if (!showingSharedChat && (!username || username === ANONYMOUS_USERNAME)) {
|
|
14104
|
+
return;
|
|
14105
|
+
}
|
|
14106
|
+
const activeSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14107
|
+
if (!activeSessionId)
|
|
14108
|
+
return;
|
|
14109
|
+
isLoadingOlderRef.current = true;
|
|
14110
|
+
setIsLoadingOlderMessages(true);
|
|
14111
|
+
const nextPage = currentPageRef.current + 1;
|
|
14112
|
+
try {
|
|
14113
|
+
const data = await fetchChatPage(activeSessionId, nextPage);
|
|
14114
|
+
let olderChats = [];
|
|
14115
|
+
try {
|
|
14116
|
+
olderChats = normalizeSessionResults((_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.results);
|
|
14117
|
+
}
|
|
14118
|
+
catch (error) {
|
|
14119
|
+
console.error(JSON.stringify(error));
|
|
14120
|
+
}
|
|
14121
|
+
if (olderChats.length > 0) {
|
|
14122
|
+
dispatch(chatActions.prependOlderMessages(olderChats));
|
|
14123
|
+
}
|
|
14124
|
+
currentPageRef.current = nextPage;
|
|
14125
|
+
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);
|
|
14126
|
+
}
|
|
14127
|
+
catch (error) {
|
|
14128
|
+
console.error(JSON.stringify(error));
|
|
14129
|
+
}
|
|
14130
|
+
finally {
|
|
14131
|
+
isLoadingOlderRef.current = false;
|
|
14132
|
+
setIsLoadingOlderMessages(false);
|
|
14133
|
+
}
|
|
14134
|
+
}, [
|
|
14135
|
+
hasMore,
|
|
14136
|
+
isOffline,
|
|
14137
|
+
showingSharedChat,
|
|
14138
|
+
username,
|
|
14139
|
+
cachedSessionId,
|
|
14140
|
+
mentorId,
|
|
14141
|
+
fetchChatPage,
|
|
14142
|
+
dispatch,
|
|
14143
|
+
]);
|
|
14144
|
+
// Depend on the indexed string session id, not the whole `cachedSessionId`
|
|
14145
|
+
// object. Consumers (e.g. `useLocalStorage`) often re-emit a new object
|
|
14146
|
+
// reference on every render even when the underlying value is unchanged,
|
|
14147
|
+
// which would otherwise cause this effect to re-fire `getChats()` per
|
|
14148
|
+
// render — and each `setNewMessages` would wipe any user message
|
|
14149
|
+
// dispatched in between (the URL `initialPrompt` race).
|
|
14150
|
+
const currentMentorSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14151
|
+
useEffect(() => {
|
|
14152
|
+
if (currentMentorSessionId) {
|
|
14153
|
+
dispatch(chatActions.updateSessionIds(currentMentorSessionId));
|
|
14154
|
+
// Skip fetching previous chats when offline
|
|
14155
|
+
if (!isOffline) {
|
|
14156
|
+
getChats();
|
|
14157
|
+
}
|
|
14158
|
+
else {
|
|
14159
|
+
setIsLoadingChats(false);
|
|
14160
|
+
isLoadingChatsRef.current = false;
|
|
14161
|
+
}
|
|
14162
|
+
}
|
|
14163
|
+
else {
|
|
14164
|
+
setIsLoadingChats(false);
|
|
14165
|
+
isLoadingChatsRef.current = false;
|
|
14166
|
+
}
|
|
14167
|
+
}, [currentMentorSessionId, isOffline]);
|
|
14168
|
+
return {
|
|
14169
|
+
getChats,
|
|
14170
|
+
loadOlderMessages,
|
|
14171
|
+
hasMore,
|
|
14172
|
+
isLoadingOlderMessages,
|
|
14173
|
+
isLoadingChats,
|
|
14174
|
+
isLoadingChatsRef,
|
|
14175
|
+
};
|
|
14176
|
+
}
|
|
14177
|
+
|
|
13886
14178
|
function useMentorSettings({ mentorId, tenantKey, isPublicRoute = false, mainTenantKey, }) {
|
|
13887
14179
|
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;
|
|
13888
14180
|
const username = useUsername();
|
|
@@ -14058,7 +14350,13 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14058
14350
|
isOffline,
|
|
14059
14351
|
onOfflineWithoutLocalLLM,
|
|
14060
14352
|
});
|
|
14061
|
-
const
|
|
14353
|
+
const { getChats, loadOlderMessages, hasMore, isLoadingOlderMessages, isLoadingChats, isLoadingChatsRef, } = useChatHistory({
|
|
14354
|
+
tenantKey,
|
|
14355
|
+
mentorId,
|
|
14356
|
+
username,
|
|
14357
|
+
cachedSessionId,
|
|
14358
|
+
isOffline,
|
|
14359
|
+
});
|
|
14062
14360
|
// Tracks whether the optional `initialPrompt` prop has already been
|
|
14063
14361
|
// auto-submitted for this hook instance. Set to `true` the moment the
|
|
14064
14362
|
// effect decides to act (either to send or because the prompt is already
|
|
@@ -14075,197 +14373,6 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14075
14373
|
// that wipes anything dispatched (like `initialPrompt`'s
|
|
14076
14374
|
// `addUserMessage`) between the two `getChats` resolutions.
|
|
14077
14375
|
const startNewChatInFlightRef = React__default.useRef(false);
|
|
14078
|
-
// Synchronous mirror of `isLoadingChats`. The state setter is async, so a
|
|
14079
|
-
// consumer effect running in the SAME render cycle as `getChats()`
|
|
14080
|
-
// invocation sees a stale `isLoadingChats=false` in its closure even
|
|
14081
|
-
// though `setIsLoadingChats(true)` has been scheduled. The ref flips
|
|
14082
|
-
// immediately (before `getChats` hits its first `await`), giving the
|
|
14083
|
-
// `initialPrompt` injection effect a reliable "fetch in progress" signal
|
|
14084
|
-
// it can read synchronously inside its body.
|
|
14085
|
-
const isLoadingChatsRef = React__default.useRef(true);
|
|
14086
|
-
const [getSessionChats] = useLazyGetSessionIdQuery();
|
|
14087
|
-
const [getSharedSessionChats] = useLazyGetSharedSessionIdQuery();
|
|
14088
|
-
const getChats = React__default.useCallback(async () => {
|
|
14089
|
-
var _a, _b, _c, _d;
|
|
14090
|
-
// Mark the fetch as in-flight so consumers gated on `isLoadingChats`
|
|
14091
|
-
// (e.g. the `initialPrompt` injection effect) defer until the resulting
|
|
14092
|
-
// `setNewMessages` has landed. The state setter alone is not enough —
|
|
14093
|
-
// it's async and the consumer effect may run in the same render cycle
|
|
14094
|
-
// with the stale closure — so flip the synchronous ref FIRST.
|
|
14095
|
-
isLoadingChatsRef.current = true;
|
|
14096
|
-
setIsLoadingChats(true);
|
|
14097
|
-
let data;
|
|
14098
|
-
try {
|
|
14099
|
-
if (showingSharedChat) {
|
|
14100
|
-
data = await getSharedSessionChats({
|
|
14101
|
-
sessionId: (_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : "",
|
|
14102
|
-
org: tenantKey,
|
|
14103
|
-
});
|
|
14104
|
-
}
|
|
14105
|
-
else if (!!username && username !== ANONYMOUS_USERNAME) {
|
|
14106
|
-
data = await getSessionChats({
|
|
14107
|
-
sessionId: (_b = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _b !== void 0 ? _b : "",
|
|
14108
|
-
org: tenantKey,
|
|
14109
|
-
// @ts-expect-error - userId is passed but not in generated API types
|
|
14110
|
-
userId: username,
|
|
14111
|
-
});
|
|
14112
|
-
}
|
|
14113
|
-
let previousChats = [];
|
|
14114
|
-
try {
|
|
14115
|
-
previousChats =
|
|
14116
|
-
((_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) => {
|
|
14117
|
-
var _a, _b, _c, _d, _e, _f;
|
|
14118
|
-
const artifactVersions = (_a = result.artifact_versions) === null || _a === void 0 ? void 0 : _a.map((av) => {
|
|
14119
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
14120
|
-
return ({
|
|
14121
|
-
id: av.id,
|
|
14122
|
-
artifact: {
|
|
14123
|
-
id: (_a = av.artifact) === null || _a === void 0 ? void 0 : _a.id,
|
|
14124
|
-
title: (_b = av.artifact) === null || _b === void 0 ? void 0 : _b.title,
|
|
14125
|
-
content: (_c = av.artifact) === null || _c === void 0 ? void 0 : _c.content,
|
|
14126
|
-
file_extension: (_d = av.artifact) === null || _d === void 0 ? void 0 : _d.file_extension,
|
|
14127
|
-
llm_name: (_e = av.artifact) === null || _e === void 0 ? void 0 : _e.llm_name,
|
|
14128
|
-
llm_provider: (_f = av.artifact) === null || _f === void 0 ? void 0 : _f.llm_provider,
|
|
14129
|
-
date_created: (_g = av.artifact) === null || _g === void 0 ? void 0 : _g.date_created,
|
|
14130
|
-
date_updated: (_h = av.artifact) === null || _h === void 0 ? void 0 : _h.date_updated,
|
|
14131
|
-
metadata: (_j = av.artifact) === null || _j === void 0 ? void 0 : _j.metadata,
|
|
14132
|
-
username: (_k = av.artifact) === null || _k === void 0 ? void 0 : _k.username,
|
|
14133
|
-
session_id: (_l = av.artifact) === null || _l === void 0 ? void 0 : _l.session_id,
|
|
14134
|
-
current_version_number: (_m = av.artifact) === null || _m === void 0 ? void 0 : _m.current_version_number,
|
|
14135
|
-
version_count: (_o = av.artifact) === null || _o === void 0 ? void 0 : _o.version_count,
|
|
14136
|
-
},
|
|
14137
|
-
title: av.title,
|
|
14138
|
-
content: av.content,
|
|
14139
|
-
session_id: av.session_id,
|
|
14140
|
-
content_length: av.content_length,
|
|
14141
|
-
is_current: av.is_current,
|
|
14142
|
-
chat_message: av.chat_message,
|
|
14143
|
-
version_number: av.version_number,
|
|
14144
|
-
date_created: av.date_created,
|
|
14145
|
-
created_by: av.created_by,
|
|
14146
|
-
change_summary: av.change_summary,
|
|
14147
|
-
});
|
|
14148
|
-
});
|
|
14149
|
-
const fileAttachments = ((_b = result.files) === null || _b === void 0 ? void 0 : _b.map((file) => ({
|
|
14150
|
-
fileId: String(file.id),
|
|
14151
|
-
fileName: file.name,
|
|
14152
|
-
fileType: file.content_type,
|
|
14153
|
-
fileSize: file.file_size,
|
|
14154
|
-
uploadUrl: file.url,
|
|
14155
|
-
}))) || [];
|
|
14156
|
-
// Extract additional_kwargs - check both direct and nested paths
|
|
14157
|
-
const additionalKwargs = result.additional_kwargs ||
|
|
14158
|
-
((_d = (_c = result.message) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.additional_kwargs);
|
|
14159
|
-
// Extract reasoning content from additional_kwargs
|
|
14160
|
-
const reasoningSummaries = (_e = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.reasoning) === null || _e === void 0 ? void 0 : _e.summary;
|
|
14161
|
-
const reasoningContent = Array.isArray(reasoningSummaries)
|
|
14162
|
-
? reasoningSummaries
|
|
14163
|
-
.map((s) => s.text)
|
|
14164
|
-
.filter(Boolean)
|
|
14165
|
-
.join("\n\n")
|
|
14166
|
-
: undefined;
|
|
14167
|
-
// Extract tool calls from additional_kwargs
|
|
14168
|
-
const toolOutputs = additionalKwargs === null || additionalKwargs === void 0 ? void 0 : additionalKwargs.tool_outputs;
|
|
14169
|
-
const toolCalls = Array.isArray(toolOutputs)
|
|
14170
|
-
? toolOutputs.map((tool) => {
|
|
14171
|
-
var _a;
|
|
14172
|
-
return ({
|
|
14173
|
-
id: tool.id || "",
|
|
14174
|
-
name: tool.type || "",
|
|
14175
|
-
log: ((_a = tool.action) === null || _a === void 0 ? void 0 : _a.query) || "",
|
|
14176
|
-
result: tool.status || "",
|
|
14177
|
-
});
|
|
14178
|
-
})
|
|
14179
|
-
: undefined;
|
|
14180
|
-
return {
|
|
14181
|
-
...result,
|
|
14182
|
-
role: result.type === "human" ? "user" : "assistant",
|
|
14183
|
-
visible: true,
|
|
14184
|
-
id: result.id || new Date().getTime(),
|
|
14185
|
-
content: typeof result.content === "object" &&
|
|
14186
|
-
result.content.length > 0
|
|
14187
|
-
? (_f = result.content.find((item) => item.text)) === null || _f === void 0 ? void 0 : _f.text
|
|
14188
|
-
: result.content,
|
|
14189
|
-
// Add transformed artifact versions
|
|
14190
|
-
artifactVersions: artifactVersions || undefined,
|
|
14191
|
-
fileAttachments: fileAttachments.length > 0 ? fileAttachments : undefined,
|
|
14192
|
-
reasoningContent: reasoningContent || undefined,
|
|
14193
|
-
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
14194
|
-
};
|
|
14195
|
-
}).reverse()) || [];
|
|
14196
|
-
}
|
|
14197
|
-
catch (error) {
|
|
14198
|
-
console.error(JSON.stringify(error));
|
|
14199
|
-
}
|
|
14200
|
-
// Preserve reasoningContent and toolCalls from existing messages
|
|
14201
|
-
// when the session API re-fetch doesn't include additional_kwargs.
|
|
14202
|
-
const existingMessages = chats[activeTab] || [];
|
|
14203
|
-
if (existingMessages.length > 0 && previousChats.length > 0) {
|
|
14204
|
-
const existingByContent = new Map();
|
|
14205
|
-
for (const m of existingMessages) {
|
|
14206
|
-
if (m.reasoningContent || (m.toolCalls && m.toolCalls.length > 0)) {
|
|
14207
|
-
existingByContent.set(m.content, m);
|
|
14208
|
-
}
|
|
14209
|
-
}
|
|
14210
|
-
if (existingByContent.size > 0) {
|
|
14211
|
-
for (const msg of previousChats) {
|
|
14212
|
-
const existing = existingByContent.get(msg.content);
|
|
14213
|
-
if (existing) {
|
|
14214
|
-
if (!msg.reasoningContent && existing.reasoningContent) {
|
|
14215
|
-
msg.reasoningContent = existing.reasoningContent;
|
|
14216
|
-
}
|
|
14217
|
-
if ((!msg.toolCalls || msg.toolCalls.length === 0) &&
|
|
14218
|
-
existing.toolCalls &&
|
|
14219
|
-
existing.toolCalls.length > 0) {
|
|
14220
|
-
msg.toolCalls = existing.toolCalls;
|
|
14221
|
-
}
|
|
14222
|
-
}
|
|
14223
|
-
}
|
|
14224
|
-
}
|
|
14225
|
-
}
|
|
14226
|
-
dispatch(chatActions.setNewMessages(previousChats));
|
|
14227
|
-
}
|
|
14228
|
-
catch (error) {
|
|
14229
|
-
console.error(JSON.stringify(error));
|
|
14230
|
-
}
|
|
14231
|
-
finally {
|
|
14232
|
-
setIsLoadingChats(false);
|
|
14233
|
-
isLoadingChatsRef.current = false;
|
|
14234
|
-
}
|
|
14235
|
-
}, [
|
|
14236
|
-
showingSharedChat,
|
|
14237
|
-
cachedSessionId,
|
|
14238
|
-
mentorId,
|
|
14239
|
-
tenantKey,
|
|
14240
|
-
username,
|
|
14241
|
-
getSharedSessionChats,
|
|
14242
|
-
getSessionChats,
|
|
14243
|
-
dispatch,
|
|
14244
|
-
]);
|
|
14245
|
-
// Depend on the indexed string session id, not the whole `cachedSessionId`
|
|
14246
|
-
// object. Consumers (e.g. `useLocalStorage`) often re-emit a new object
|
|
14247
|
-
// reference on every render even when the underlying value is unchanged,
|
|
14248
|
-
// which would otherwise cause this effect to re-fire `getChats()` per
|
|
14249
|
-
// render — and each `setNewMessages` would wipe any user message
|
|
14250
|
-
// dispatched in between (the URL `initialPrompt` race).
|
|
14251
|
-
const currentMentorSessionId = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId];
|
|
14252
|
-
useEffect(() => {
|
|
14253
|
-
if (currentMentorSessionId) {
|
|
14254
|
-
dispatch(chatActions.updateSessionIds(currentMentorSessionId));
|
|
14255
|
-
// Skip fetching previous chats when offline
|
|
14256
|
-
if (!isOffline) {
|
|
14257
|
-
getChats();
|
|
14258
|
-
}
|
|
14259
|
-
else {
|
|
14260
|
-
setIsLoadingChats(false);
|
|
14261
|
-
isLoadingChatsRef.current = false;
|
|
14262
|
-
}
|
|
14263
|
-
}
|
|
14264
|
-
else {
|
|
14265
|
-
setIsLoadingChats(false);
|
|
14266
|
-
isLoadingChatsRef.current = false;
|
|
14267
|
-
}
|
|
14268
|
-
}, [currentMentorSessionId, isOffline]);
|
|
14269
14376
|
const startNewChat = React__default.useCallback(async () => {
|
|
14270
14377
|
// Reset all chat state
|
|
14271
14378
|
if (!showingSharedChat) {
|
|
@@ -14498,6 +14605,9 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
14498
14605
|
resetConnection,
|
|
14499
14606
|
isLoadingChats,
|
|
14500
14607
|
refetchChats: getChats,
|
|
14608
|
+
loadOlderMessages,
|
|
14609
|
+
hasMore,
|
|
14610
|
+
isLoadingOlderMessages,
|
|
14501
14611
|
};
|
|
14502
14612
|
}
|
|
14503
14613
|
|