impact-chatbot 2.3.51 → 2.3.53
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/index.cjs.js +180 -48
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +181 -49
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -18,13 +18,14 @@ import remarkBreaks from 'remark-breaks';
|
|
|
18
18
|
import remarkGfm from 'remark-gfm';
|
|
19
19
|
import DOMPurify from 'dompurify';
|
|
20
20
|
import { setSelectedFilters, setFilterConfiguration, getFilterUserConfiguration } from 'core/actions/filterAction';
|
|
21
|
-
import { setChatbotContext, setStepFormStreamData, setPersistedFormValues, clearPersistedFormValues, setCurrentAgentChatId,
|
|
21
|
+
import { setChatbotContext, setStepFormStreamData, setThinkingContext, setPersistedFormValues, clearPersistedFormValues, setCurrentAgentChatId, setHierarchyKeyValue, setSavedFilterSets } from 'core/actions/smartBotActions';
|
|
22
22
|
import { useNavigate, useLocation } from 'react-router-dom-v5-compat';
|
|
23
23
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
24
24
|
import styled from 'styled-components';
|
|
25
25
|
import { CircularProgress, Typography, Grid } from '@mui/material';
|
|
26
26
|
import { fetchBaseUrl, replaceSpecialCharacter as replaceSpecialCharacter$1, fetchLegacyAgentScreen } from 'core/Utils/functions/utils';
|
|
27
27
|
import { Button, Modal, Slider, Select, DatePicker, DateRangePicker, Checkbox, RadioButtonGroup, Input, Tabs, Loader, Tooltip, ChatBotComponent } from 'impact-ui-v3';
|
|
28
|
+
import axios from 'axios';
|
|
28
29
|
import isArray$2 from 'lodash/isArray';
|
|
29
30
|
import { stopAgentFlow } from 'core/commonComponents/smartBot/services/chatbot-services';
|
|
30
31
|
import AgGridComponent from 'core/Utils/agGrid';
|
|
@@ -1277,12 +1278,70 @@ const ThinkingIndicator = (props) => {
|
|
|
1277
1278
|
return (jsx("div", { children: jsx("div", { children: thinkingContentState ? (jsx("div", { children: jsx(TextRenderer, { text: thinkingContentState, thinking: true }) })) : (jsxs("div", { className: classes.thinkingSpinner, children: [jsx("span", { className: classes.thinkingDot }), jsx("span", { className: classes.thinkingDot }), jsx("span", { className: classes.thinkingDot })] })) }) }));
|
|
1278
1279
|
};
|
|
1279
1280
|
|
|
1281
|
+
/**
|
|
1282
|
+
* Formats elapsed seconds into "Xm:Ys" display string.
|
|
1283
|
+
* e.g. 0 -> "0m:00s", 65 -> "1m:05s", 130 -> "2m:10s"
|
|
1284
|
+
*/
|
|
1285
|
+
const formatElapsedTime = (totalSeconds) => {
|
|
1286
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
1287
|
+
const seconds = totalSeconds % 60;
|
|
1288
|
+
return `${minutes}m:${String(seconds).padStart(2, '0')}s`;
|
|
1289
|
+
};
|
|
1280
1290
|
const ThinkinHeaderInfo = (props) => {
|
|
1281
1291
|
const thinkingContext = useSelector((state) => {
|
|
1282
1292
|
return state.smartBotReducer.thinkingContext;
|
|
1283
1293
|
});
|
|
1284
|
-
const { thinkingHeaderMessage } = thinkingContext;
|
|
1285
|
-
|
|
1294
|
+
const { streamStartTime, isStreamCompleted, finalElapsedSeconds, thinkingHeaderMessage } = thinkingContext;
|
|
1295
|
+
const [elapsed, setElapsed] = useState(0);
|
|
1296
|
+
const intervalRef = useRef(null);
|
|
1297
|
+
// Once this instance sees "completed", freeze it permanently so a future
|
|
1298
|
+
// chat's streamStartTime doesn't cause it to start ticking again.
|
|
1299
|
+
const frozenRef = useRef(false);
|
|
1300
|
+
const frozenTextRef = useRef(null);
|
|
1301
|
+
useEffect(() => {
|
|
1302
|
+
// If already frozen, ignore all future Redux changes
|
|
1303
|
+
if (frozenRef.current)
|
|
1304
|
+
return;
|
|
1305
|
+
// Clear any existing interval
|
|
1306
|
+
if (intervalRef.current) {
|
|
1307
|
+
clearInterval(intervalRef.current);
|
|
1308
|
+
intervalRef.current = null;
|
|
1309
|
+
}
|
|
1310
|
+
if (isStreamCompleted && typeof finalElapsedSeconds === 'number') {
|
|
1311
|
+
// Freeze this instance — it will never tick again
|
|
1312
|
+
frozenRef.current = true;
|
|
1313
|
+
frozenTextRef.current = `Completed in ${formatElapsedTime(finalElapsedSeconds)}`;
|
|
1314
|
+
setElapsed(finalElapsedSeconds);
|
|
1315
|
+
}
|
|
1316
|
+
else if (streamStartTime && !isStreamCompleted) {
|
|
1317
|
+
// Live timer — update every second
|
|
1318
|
+
const tick = () => {
|
|
1319
|
+
const now = Date.now();
|
|
1320
|
+
const diffSeconds = Math.floor((now - streamStartTime) / 1000);
|
|
1321
|
+
setElapsed(diffSeconds);
|
|
1322
|
+
};
|
|
1323
|
+
tick(); // immediate first tick
|
|
1324
|
+
intervalRef.current = setInterval(tick, 1000);
|
|
1325
|
+
}
|
|
1326
|
+
return () => {
|
|
1327
|
+
if (intervalRef.current) {
|
|
1328
|
+
clearInterval(intervalRef.current);
|
|
1329
|
+
intervalRef.current = null;
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
}, [streamStartTime, isStreamCompleted, finalElapsedSeconds]);
|
|
1333
|
+
// Determine display text
|
|
1334
|
+
let displayText = thinkingHeaderMessage || '';
|
|
1335
|
+
if (frozenRef.current && frozenTextRef.current) {
|
|
1336
|
+
displayText = frozenTextRef.current;
|
|
1337
|
+
}
|
|
1338
|
+
else if (streamStartTime && !isStreamCompleted) {
|
|
1339
|
+
displayText = `Working for ${formatElapsedTime(elapsed)}`;
|
|
1340
|
+
}
|
|
1341
|
+
else if (isStreamCompleted && typeof finalElapsedSeconds === 'number') {
|
|
1342
|
+
displayText = `Completed in ${formatElapsedTime(finalElapsedSeconds)}`;
|
|
1343
|
+
}
|
|
1344
|
+
return (jsx("div", { className: "thinkin-header-info", children: displayText }));
|
|
1286
1345
|
};
|
|
1287
1346
|
|
|
1288
1347
|
// import { exampleGraphData } from "../examples/GraphExample";
|
|
@@ -4052,7 +4111,7 @@ const useChatState = () => {
|
|
|
4052
4111
|
const [chatId, setChatId] = useState("");
|
|
4053
4112
|
const [isStop, setIsStop] = useState(false);
|
|
4054
4113
|
const [functionsState, setFunctionsState] = useState({});
|
|
4055
|
-
const [thinkingHeaderMessage, setThinkingHeaderMessage] = useState("
|
|
4114
|
+
const [thinkingHeaderMessage, setThinkingHeaderMessage] = useState("Working… 0m:00s");
|
|
4056
4115
|
const [legacyAgentScreen, setLegacyAgentScreen] = useState(false);
|
|
4057
4116
|
const [uniqueChatId, setUniqueChatId] = useState("");
|
|
4058
4117
|
const [fieldNumber, setFieldNumber] = useState(0);
|
|
@@ -5277,9 +5336,9 @@ const AxiosSource = (url, opts, messageToStoreRef) => {
|
|
|
5277
5336
|
headers: opts.headers,
|
|
5278
5337
|
data: opts.body,
|
|
5279
5338
|
signal: controller.signal,
|
|
5280
|
-
responseType: "
|
|
5339
|
+
responseType: "text",
|
|
5281
5340
|
onDownloadProgress: (progressEvent) => {
|
|
5282
|
-
const response = progressEvent.currentTarget;
|
|
5341
|
+
const response = progressEvent.currentTarget || progressEvent.target;
|
|
5283
5342
|
// Emit 'open' event when the connection is first established
|
|
5284
5343
|
if (!progressEvent.loaded) {
|
|
5285
5344
|
eventTarget.dispatchEvent(new Event("open", {
|
|
@@ -5314,8 +5373,9 @@ const AxiosSource = (url, opts, messageToStoreRef) => {
|
|
|
5314
5373
|
})
|
|
5315
5374
|
.catch((error) => {
|
|
5316
5375
|
let reason = "Network request failed";
|
|
5376
|
+
console.error("[AxiosSource] Request failed:", error);
|
|
5317
5377
|
// Determine specific error reasons
|
|
5318
|
-
if (
|
|
5378
|
+
if (axios.isCancel(error)) {
|
|
5319
5379
|
reason = "Network request aborted";
|
|
5320
5380
|
}
|
|
5321
5381
|
else if (error.code === "ECONNABORTED") {
|
|
@@ -5386,6 +5446,7 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5386
5446
|
status: "",
|
|
5387
5447
|
});
|
|
5388
5448
|
const chatbotContext = useSelector((state) => state.smartBotReducer.chatbotContext);
|
|
5449
|
+
const thinkingContext = useSelector((state) => state.smartBotReducer.thinkingContext);
|
|
5389
5450
|
const handleButtonClick = (button) => {
|
|
5390
5451
|
if (isStepFormSubmit) {
|
|
5391
5452
|
// Build the user_input from chatbotContext
|
|
@@ -5400,7 +5461,6 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5400
5461
|
: typeof value === 'number' ? value : String(value);
|
|
5401
5462
|
}
|
|
5402
5463
|
}
|
|
5403
|
-
console.log("[ButtonContent] step form submit, calling init API with userInput:", userInput);
|
|
5404
5464
|
dispatch(setChatbotContext({}));
|
|
5405
5465
|
// Call the init API via SSE directly
|
|
5406
5466
|
callInitApiStream(userInput);
|
|
@@ -5459,6 +5519,9 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5459
5519
|
dispatch(setStepFormStreamData({ status: "streaming_start", chunks: [], sessionId }));
|
|
5460
5520
|
// Fire DOM event so SmartBot can show stop icon (Redux gets cleared by TabularContent before parent effects run)
|
|
5461
5521
|
window.dispatchEvent(new CustomEvent("stepFormStreamStart"));
|
|
5522
|
+
// Capture start time for computing elapsed on completion.
|
|
5523
|
+
// Timer keeps running from the original streamStartTime (set when first API was hit).
|
|
5524
|
+
const stepFormStreamStartTime = Date.now();
|
|
5462
5525
|
sourceRef.current = AxiosSource(endPoint, {
|
|
5463
5526
|
method: "POST",
|
|
5464
5527
|
headers: {
|
|
@@ -5473,7 +5536,6 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5473
5536
|
sourceRef.current.addEventListener("message", (event) => {
|
|
5474
5537
|
try {
|
|
5475
5538
|
const data = JSON.parse(event.data);
|
|
5476
|
-
console.log("[ButtonContent] SSE chunk:", data);
|
|
5477
5539
|
// Always keep stepFormStreamControl.sessionId in sync with the latest chunk's session_id
|
|
5478
5540
|
if (data?.session_id) {
|
|
5479
5541
|
stepFormStreamControl.sessionId = data.session_id;
|
|
@@ -5514,6 +5576,22 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5514
5576
|
stepFormStreamControl.isStreaming = false;
|
|
5515
5577
|
stepFormStreamControl.abort = null;
|
|
5516
5578
|
window.dispatchEvent(new CustomEvent("stepFormStreamEnd"));
|
|
5579
|
+
// Stop the timer only when status:"completed" is received
|
|
5580
|
+
if (data?.status === "completed") {
|
|
5581
|
+
// Use the original streamStartTime from Redux (set when first API was hit)
|
|
5582
|
+
const originalStartTime = thinkingContext?.streamStartTime || stepFormStreamStartTime;
|
|
5583
|
+
const totalElapsed = Math.floor((Date.now() - originalStartTime) / 1000);
|
|
5584
|
+
const sfMin = Math.floor(totalElapsed / 60);
|
|
5585
|
+
const sfSec = totalElapsed % 60;
|
|
5586
|
+
const sfWorkedLabel = `Completed in ${sfMin}m:${String(sfSec).padStart(2, '0')}s`;
|
|
5587
|
+
dispatch(setThinkingContext({
|
|
5588
|
+
streamStartTime: originalStartTime,
|
|
5589
|
+
isStreamCompleted: true,
|
|
5590
|
+
finalElapsedSeconds: totalElapsed,
|
|
5591
|
+
thinkingHeaderMessage: sfWorkedLabel,
|
|
5592
|
+
thinkingContent: "",
|
|
5593
|
+
}));
|
|
5594
|
+
}
|
|
5517
5595
|
// Signal tab switch to agent_response when status is "completed",
|
|
5518
5596
|
// but only if the response doesn't contain a new step_form that needs user interaction
|
|
5519
5597
|
const hasStepForm = chunksRef.some((c) => c.status === "step_form");
|
|
@@ -6972,24 +7050,6 @@ function clearTabNotification() {
|
|
|
6972
7050
|
* This survives the cloneDeep replacement of botData in SmartBot's useEffect.
|
|
6973
7051
|
*/
|
|
6974
7052
|
const streamStateMap = new Map();
|
|
6975
|
-
/**
|
|
6976
|
-
* Formats thinking time to display minutes when appropriate
|
|
6977
|
-
* @param {number} seconds - Time in seconds
|
|
6978
|
-
* @returns {string} Formatted time string
|
|
6979
|
-
*/
|
|
6980
|
-
const formatThinkingTime = (seconds) => {
|
|
6981
|
-
if (seconds < 60) {
|
|
6982
|
-
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
6983
|
-
}
|
|
6984
|
-
const minutes = Math.floor(seconds / 60);
|
|
6985
|
-
const remainingSeconds = seconds % 60;
|
|
6986
|
-
if (remainingSeconds === 0) {
|
|
6987
|
-
return `${minutes} minute${minutes !== 1 ? 's' : ''}`;
|
|
6988
|
-
}
|
|
6989
|
-
else {
|
|
6990
|
-
return `${minutes} min ${remainingSeconds} sec`;
|
|
6991
|
-
}
|
|
6992
|
-
};
|
|
6993
7053
|
/**
|
|
6994
7054
|
* StreamedContent Component
|
|
6995
7055
|
* Handles real-time streaming of chat messages with a typing-like effect
|
|
@@ -7053,7 +7113,8 @@ const StreamedContent = ({ botData }) => {
|
|
|
7053
7113
|
useRef(""); // Tracks the last received message
|
|
7054
7114
|
const thinkingStartTimeRef = useRef(null);
|
|
7055
7115
|
const thinkingTimeFinalRef = useRef(0);
|
|
7056
|
-
const thinkingHeaderMessageRef = useRef("
|
|
7116
|
+
const thinkingHeaderMessageRef = useRef("Working for 0m:00s");
|
|
7117
|
+
const streamStartTimeRef = useRef(null);
|
|
7057
7118
|
const thinkingDoneRef = useRef(false);
|
|
7058
7119
|
const setThinkingContentRef = useRef(setThinkingContent); // Store current setThinkingContent function
|
|
7059
7120
|
const streamTimeoutRef = useRef(null); // Ref for stream timeout
|
|
@@ -7119,6 +7180,17 @@ const StreamedContent = ({ botData }) => {
|
|
|
7119
7180
|
? botData?.utilityObject?.method
|
|
7120
7181
|
: "PUT";
|
|
7121
7182
|
delete botData.inputBody.chat_input;
|
|
7183
|
+
// Start the timer immediately when the API is called
|
|
7184
|
+
if (!streamStartTimeRef.current) {
|
|
7185
|
+
streamStartTimeRef.current = Date.now();
|
|
7186
|
+
dispatch(setThinkingContext({
|
|
7187
|
+
streamStartTime: streamStartTimeRef.current,
|
|
7188
|
+
isStreamCompleted: false,
|
|
7189
|
+
finalElapsedSeconds: null,
|
|
7190
|
+
thinkingHeaderMessage: "Working for 0m:00s",
|
|
7191
|
+
thinkingContent: "",
|
|
7192
|
+
}));
|
|
7193
|
+
}
|
|
7122
7194
|
// Initialize SSE connection with API endpoint
|
|
7123
7195
|
sourceRef.current = AxiosSource(endPoint, {
|
|
7124
7196
|
method: method,
|
|
@@ -7207,7 +7279,7 @@ const StreamedContent = ({ botData }) => {
|
|
|
7207
7279
|
setQuestionsStepsMap(cloneDeep(initialMap));
|
|
7208
7280
|
}
|
|
7209
7281
|
else if (data.status === "thinking") {
|
|
7210
|
-
messageToStoreRef.current.chatData.thinkingResponse.thinkingHeading = "
|
|
7282
|
+
messageToStoreRef.current.chatData.thinkingResponse.thinkingHeading = (jsx(ThinkinHeaderInfo, { thinkingHeaderMessage: "Working for 0m:00s" }));
|
|
7211
7283
|
// Start thinking if not already started
|
|
7212
7284
|
if (!isThinking) {
|
|
7213
7285
|
setIsThinking(true);
|
|
@@ -7218,6 +7290,9 @@ const StreamedContent = ({ botData }) => {
|
|
|
7218
7290
|
thinkingContentRef.current = thinkingContentRef.current + data.message;
|
|
7219
7291
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingStream = newValue;
|
|
7220
7292
|
dispatch(setThinkingContext({
|
|
7293
|
+
streamStartTime: streamStartTimeRef.current,
|
|
7294
|
+
isStreamCompleted: false,
|
|
7295
|
+
finalElapsedSeconds: null,
|
|
7221
7296
|
thinkingHeaderMessage: thinkingHeaderMessageRef.current,
|
|
7222
7297
|
thinkingContent: thinkingContentRef.current,
|
|
7223
7298
|
}));
|
|
@@ -7350,7 +7425,8 @@ const StreamedContent = ({ botData }) => {
|
|
|
7350
7425
|
stepFormStreamControl.baseUrl = _burl;
|
|
7351
7426
|
// If this is the [DONE] chunk, mark streaming as complete
|
|
7352
7427
|
if (data.message === "[DONE]") {
|
|
7353
|
-
|
|
7428
|
+
// Do NOT set stepsDone here — step_form [DONE] is not status:"completed".
|
|
7429
|
+
// stepsDone should only be true when status:"completed" arrives.
|
|
7354
7430
|
setIsStreamingDone(true);
|
|
7355
7431
|
const doneState = streamStateMap.get(streamKey);
|
|
7356
7432
|
if (doneState)
|
|
@@ -7379,10 +7455,13 @@ const StreamedContent = ({ botData }) => {
|
|
|
7379
7455
|
// Store thinking time in messageToStoreRef for persistence
|
|
7380
7456
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingTime = finalThinkingTime;
|
|
7381
7457
|
thinkingTimeFinalRef.current = finalThinkingTime;
|
|
7382
|
-
|
|
7383
|
-
|
|
7458
|
+
// Keep timer running — do NOT set "Worked for" here.
|
|
7459
|
+
// Timer continues showing "Working for Xm:Ys" until status:"completed" arrives.
|
|
7384
7460
|
dispatch(setThinkingContext({
|
|
7385
|
-
|
|
7461
|
+
streamStartTime: streamStartTimeRef.current,
|
|
7462
|
+
isStreamCompleted: false,
|
|
7463
|
+
finalElapsedSeconds: null,
|
|
7464
|
+
thinkingHeaderMessage: thinkingHeaderMessageRef.current,
|
|
7386
7465
|
thinkingContent: thinkingContentRef.current,
|
|
7387
7466
|
}));
|
|
7388
7467
|
}
|
|
@@ -7496,11 +7575,31 @@ const StreamedContent = ({ botData }) => {
|
|
|
7496
7575
|
if (currentMode === "agent") {
|
|
7497
7576
|
setIsStop(false);
|
|
7498
7577
|
// Use thinkingTime state instead of thinkingTimeFinalRef.current to ensure we have the correct value
|
|
7499
|
-
thinkingTime || thinkingTimeFinalRef.current || 1;
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7578
|
+
const finalThinkingTime = thinkingTime || thinkingTimeFinalRef.current || 1;
|
|
7579
|
+
const completedElapsed = streamStartTimeRef.current
|
|
7580
|
+
? Math.floor((Date.now() - streamStartTimeRef.current) / 1000)
|
|
7581
|
+
: finalThinkingTime;
|
|
7582
|
+
const compMin = Math.floor(completedElapsed / 60);
|
|
7583
|
+
const compSec = completedElapsed % 60;
|
|
7584
|
+
const workedForLabel = `Completed in ${compMin}m:${String(compSec).padStart(2, '0')}s`;
|
|
7585
|
+
// Only stop the timer if we got status:"completed" (stepsDone=true).
|
|
7586
|
+
// If stream ended with step_form [DONE], keep timer running for the next restream.
|
|
7587
|
+
if (stepsDone) {
|
|
7588
|
+
// Completed — use a static string so this chat's heading won't
|
|
7589
|
+
// re-animate when a future chat dispatches a new streamStartTime.
|
|
7590
|
+
messageToStoreRef.current.chatData.thinkingResponse.thinkingHeading = workedForLabel;
|
|
7591
|
+
dispatch(setThinkingContext({
|
|
7592
|
+
streamStartTime: streamStartTimeRef.current,
|
|
7593
|
+
isStreamCompleted: true,
|
|
7594
|
+
finalElapsedSeconds: completedElapsed,
|
|
7595
|
+
thinkingHeaderMessage: workedForLabel,
|
|
7596
|
+
thinkingContent: thinkingContentRef.current,
|
|
7597
|
+
}));
|
|
7598
|
+
}
|
|
7599
|
+
else {
|
|
7600
|
+
// step_form case: keep heading as the live ThinkinHeaderInfo component so the timer keeps ticking
|
|
7601
|
+
messageToStoreRef.current.chatData.thinkingResponse.thinkingHeading = (jsx(ThinkinHeaderInfo, { thinkingHeaderMessage: "Working for 0m:00s" }));
|
|
7602
|
+
}
|
|
7504
7603
|
let actualResponse = cloneDeep(messageToStoreRef.current.chatData.thinkingResponse.thinkingStream);
|
|
7505
7604
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingContent = actualResponse;
|
|
7506
7605
|
parseResponse(messageToStoreRef.current.chatData, "text");
|
|
@@ -7741,6 +7840,20 @@ const StreamedContent = ({ botData }) => {
|
|
|
7741
7840
|
setShowThoughtDropdown(true);
|
|
7742
7841
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingTime = finalThinkingTime;
|
|
7743
7842
|
}
|
|
7843
|
+
// Stop the timer on abort
|
|
7844
|
+
const abortElapsed = streamStartTimeRef.current
|
|
7845
|
+
? Math.floor((Date.now() - streamStartTimeRef.current) / 1000)
|
|
7846
|
+
: 0;
|
|
7847
|
+
const abortMin = Math.floor(abortElapsed / 60);
|
|
7848
|
+
const abortSec = abortElapsed % 60;
|
|
7849
|
+
const abortLabel = `Completed in ${abortMin}m:${String(abortSec).padStart(2, '0')}s`;
|
|
7850
|
+
dispatch(setThinkingContext({
|
|
7851
|
+
streamStartTime: streamStartTimeRef.current,
|
|
7852
|
+
isStreamCompleted: true,
|
|
7853
|
+
finalElapsedSeconds: abortElapsed,
|
|
7854
|
+
thinkingHeaderMessage: abortLabel,
|
|
7855
|
+
thinkingContent: thinkingContentRef.current,
|
|
7856
|
+
}));
|
|
7744
7857
|
// If no content yet, show aborted message
|
|
7745
7858
|
// if (isEmpty(messageToStoreRef.current.chatData?.response)) {
|
|
7746
7859
|
messageToStoreRef.current.chatData.response =
|
|
@@ -7789,14 +7902,12 @@ const StreamedContent = ({ botData }) => {
|
|
|
7789
7902
|
};
|
|
7790
7903
|
}, [isStreaming, isStreamingDone]);
|
|
7791
7904
|
/**
|
|
7792
|
-
* Auto-abort previous stream when starting a new one
|
|
7905
|
+
* Auto-abort previous stream when starting a new one.
|
|
7906
|
+
* NOTE: This is intentionally removed. In axios 0.32.0, signal/abort is properly
|
|
7907
|
+
* supported, and this effect was firing on mount causing immediate cancellation.
|
|
7908
|
+
* Stream abort on "new chat" is already handled by handleNewChatClick calling
|
|
7909
|
+
* functionsState.abortStreaming(). The streamStateMap logic handles all other cases.
|
|
7793
7910
|
*/
|
|
7794
|
-
useEffect(() => {
|
|
7795
|
-
// If we already have a source and it's streaming, abort it before starting new one
|
|
7796
|
-
if (sourceRef.current && isStreaming) {
|
|
7797
|
-
sourceRef.current.close();
|
|
7798
|
-
}
|
|
7799
|
-
}, [botData.inputBody]); // Trigger when new input is provided
|
|
7800
7911
|
/**
|
|
7801
7912
|
* Set up timeout for auto-abort (optional - can be configured)
|
|
7802
7913
|
*/
|
|
@@ -11628,7 +11739,7 @@ const useConversationManagement = (chatDataRef, currentMode, activeConversationI
|
|
|
11628
11739
|
thinkingStream: item.data,
|
|
11629
11740
|
thinkingContent: item.data,
|
|
11630
11741
|
thinkingTime: 1,
|
|
11631
|
-
thinkingHeading: "
|
|
11742
|
+
thinkingHeading: "Completed in 0m:00s",
|
|
11632
11743
|
};
|
|
11633
11744
|
}
|
|
11634
11745
|
else if (item.chatType === "steps") {
|
|
@@ -11823,7 +11934,9 @@ const useConversationManagement = (chatDataRef, currentMode, activeConversationI
|
|
|
11823
11934
|
thinkingResponse: msg.thinkingResponse ? {
|
|
11824
11935
|
thinkingStream: msg.thinkingResponse.thinkingStream,
|
|
11825
11936
|
thinkingTime: msg.thinkingResponse.thinkingTime,
|
|
11826
|
-
thinkingHeading: msg.thinkingResponse.thinkingHeading
|
|
11937
|
+
thinkingHeading: typeof msg.thinkingResponse.thinkingHeading === 'string'
|
|
11938
|
+
? msg.thinkingResponse.thinkingHeading
|
|
11939
|
+
: "Completed in 0m:00s",
|
|
11827
11940
|
} : undefined,
|
|
11828
11941
|
}
|
|
11829
11942
|
}))
|
|
@@ -12488,10 +12601,14 @@ const SmartBot = (props) => {
|
|
|
12488
12601
|
message.isFormDisabled = index !== lastBotMessageIndex;
|
|
12489
12602
|
message.messageIndex = index;
|
|
12490
12603
|
let originalUtilityObject = message.utilityObject;
|
|
12604
|
+
let originalThinkingResponse = message.thinkingResponse;
|
|
12491
12605
|
let newMessage = cloneDeep(message);
|
|
12492
12606
|
if (originalUtilityObject) {
|
|
12493
12607
|
newMessage.utilityObject = originalUtilityObject;
|
|
12494
12608
|
}
|
|
12609
|
+
if (originalThinkingResponse) {
|
|
12610
|
+
newMessage.thinkingResponse = originalThinkingResponse;
|
|
12611
|
+
}
|
|
12495
12612
|
message.jsx = (jsx(BotMessage, { botData: newMessage, state: loadingState, handleLikeDislike: handleLikeDislike, props: properties }));
|
|
12496
12613
|
let actualProps = {
|
|
12497
12614
|
botData: newMessage,
|
|
@@ -12506,6 +12623,15 @@ const SmartBot = (props) => {
|
|
|
12506
12623
|
});
|
|
12507
12624
|
// Create a deep clone and remove JSX properties to avoid circular references
|
|
12508
12625
|
let newChat = cloneDeep(chatDataInfoRef?.current[currentMode]);
|
|
12626
|
+
// Restore thinkingResponse (may contain JSX components like ThinkinHeaderInfo)
|
|
12627
|
+
// which cloneDeep serializes into plain objects
|
|
12628
|
+
const originalMessages = chatDataInfoRef?.current[currentMode]?.conversations?.[activeConversationId]?.messages || [];
|
|
12629
|
+
const clonedMessages = newChat?.conversations?.[activeConversationId]?.messages || [];
|
|
12630
|
+
originalMessages.forEach((origMsg, idx) => {
|
|
12631
|
+
if (origMsg.thinkingResponse && clonedMessages[idx]) {
|
|
12632
|
+
clonedMessages[idx].thinkingResponse = origMsg.thinkingResponse;
|
|
12633
|
+
}
|
|
12634
|
+
});
|
|
12509
12635
|
setConversation(newChat);
|
|
12510
12636
|
}
|
|
12511
12637
|
else if (showModal) {
|
|
@@ -12599,7 +12725,10 @@ const SmartBot = (props) => {
|
|
|
12599
12725
|
// if(!isEmpty(userInput)) {
|
|
12600
12726
|
dispatch(setThinkingContext({
|
|
12601
12727
|
thinkingContent: "",
|
|
12602
|
-
thinkingHeaderMessage: "
|
|
12728
|
+
thinkingHeaderMessage: "Working for 0m:00s",
|
|
12729
|
+
streamStartTime: Date.now(),
|
|
12730
|
+
isStreamCompleted: false,
|
|
12731
|
+
finalElapsedSeconds: null,
|
|
12603
12732
|
}));
|
|
12604
12733
|
// }
|
|
12605
12734
|
prepareDataAndSendToAgent(data, true, {
|
|
@@ -12814,7 +12943,10 @@ const SmartBot = (props) => {
|
|
|
12814
12943
|
setShowChatPlaceholder(true);
|
|
12815
12944
|
dispatch(setThinkingContext({
|
|
12816
12945
|
thinkingContent: "",
|
|
12817
|
-
thinkingHeaderMessage: "
|
|
12946
|
+
thinkingHeaderMessage: "Working for 0m:00s",
|
|
12947
|
+
streamStartTime: null,
|
|
12948
|
+
isStreamCompleted: false,
|
|
12949
|
+
finalElapsedSeconds: null,
|
|
12818
12950
|
}));
|
|
12819
12951
|
setInitValue(true);
|
|
12820
12952
|
setSessionId("");
|