impact-chatbot 2.3.84 → 2.3.86
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 +79 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +80 -17
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -19,7 +19,7 @@ import remarkGfm from 'remark-gfm';
|
|
|
19
19
|
import DOMPurify from 'dompurify';
|
|
20
20
|
import { useNavigate, useLocation } from 'react-router-dom-v5-compat';
|
|
21
21
|
import { setSelectedFilters, setFilterConfiguration, getFilterUserConfiguration } from 'core/actions/filterAction';
|
|
22
|
-
import { setChatbotContext, setStepFormStreamData, setMinimizedStreamData,
|
|
22
|
+
import { setThinkingContext, setChatbotContext, setStepFormStreamData, setMinimizedStreamData, setPersistedFormValues, clearPersistedFormValues, setCurrentAgentChatId, setHierarchyKeyValue, setChatbotFilterOptions, setSavedFilterSets } from 'core/actions/smartBotActions';
|
|
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';
|
|
@@ -653,8 +653,11 @@ const handleMessageLike = async (question, liked, setLoadingState, displaySnackM
|
|
|
653
653
|
try {
|
|
654
654
|
let request;
|
|
655
655
|
if (currentMode === "agent") {
|
|
656
|
+
// Use the session stored on this specific message. The live sessionId is
|
|
657
|
+
// reset once a flow completes / awaits follow-up, so relying on it would
|
|
658
|
+
// send an empty session_id or the session of a newer chat.
|
|
656
659
|
const agentPayload = {
|
|
657
|
-
session_id: sessionId,
|
|
660
|
+
session_id: activeMessage?.chatSessionId || activeMessage?.sessionId || sessionId,
|
|
658
661
|
liked,
|
|
659
662
|
};
|
|
660
663
|
request = await likeDislikeCommentForAgent(agentPayload, baseUrl);
|
|
@@ -1417,31 +1420,50 @@ const ThinkinHeaderInfo = (props) => {
|
|
|
1417
1420
|
});
|
|
1418
1421
|
const { streamStartTime, isStreamCompleted, finalElapsedSeconds, thinkingHeaderMessage } = thinkingContext;
|
|
1419
1422
|
const [elapsed, setElapsed] = useState(0);
|
|
1423
|
+
const [frozenText, setFrozenText] = useState(null);
|
|
1420
1424
|
const intervalRef = useRef(null);
|
|
1421
1425
|
// Once this instance sees "completed", freeze it permanently so a future
|
|
1422
1426
|
// chat's streamStartTime doesn't cause it to start ticking again.
|
|
1423
1427
|
const frozenRef = useRef(false);
|
|
1424
1428
|
const frozenTextRef = useRef(null);
|
|
1425
|
-
|
|
1429
|
+
// The streamStartTime this instance latched onto. Used to detect when a
|
|
1430
|
+
// different stream has taken over (e.g. the user asked a new question while
|
|
1431
|
+
// this message's step form was still waiting for input).
|
|
1432
|
+
const ownStartTimeRef = useRef(null);
|
|
1433
|
+
/**
|
|
1434
|
+
* Freezes this instance permanently on a final label and elapsed value.
|
|
1435
|
+
*/
|
|
1436
|
+
const freeze = (text, seconds) => {
|
|
1437
|
+
frozenRef.current = true;
|
|
1438
|
+
frozenTextRef.current = text;
|
|
1439
|
+
setFrozenText(text);
|
|
1440
|
+
setElapsed(seconds);
|
|
1441
|
+
};
|
|
1426
1442
|
useEffect(() => {
|
|
1427
1443
|
// If already frozen (stream completed), NEVER unfreeze.
|
|
1428
1444
|
// This prevents a new chat's streamStartTime from restarting this timer.
|
|
1429
1445
|
if (frozenRef.current)
|
|
1430
1446
|
return;
|
|
1431
|
-
//
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1447
|
+
// Adopt the first non-null streamStartTime we see as this instance's own
|
|
1448
|
+
if (ownStartTimeRef.current === null && streamStartTime) {
|
|
1449
|
+
ownStartTimeRef.current = streamStartTime;
|
|
1434
1450
|
}
|
|
1451
|
+
const ownStartTime = ownStartTimeRef.current;
|
|
1435
1452
|
// Clear any existing interval
|
|
1436
1453
|
if (intervalRef.current) {
|
|
1437
1454
|
clearInterval(intervalRef.current);
|
|
1438
1455
|
intervalRef.current = null;
|
|
1439
1456
|
}
|
|
1440
1457
|
if (isStreamCompleted && typeof finalElapsedSeconds === 'number') {
|
|
1441
|
-
// Freeze this instance
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1458
|
+
// Freeze this instance - it will never tick again
|
|
1459
|
+
freeze(`Completed in ${formatElapsedTime(finalElapsedSeconds)}`, finalElapsedSeconds);
|
|
1460
|
+
}
|
|
1461
|
+
else if (ownStartTime !== null && streamStartTime !== ownStartTime) {
|
|
1462
|
+
// A different stream has started (new question) while this one never
|
|
1463
|
+
// completed - typically an abandoned step form. Freeze on this
|
|
1464
|
+
// instance's OWN elapsed time instead of following the new stream.
|
|
1465
|
+
const ownElapsed = Math.floor((Date.now() - ownStartTime) / 1000);
|
|
1466
|
+
freeze(`Completed in ${formatElapsedTime(ownElapsed)}`, ownElapsed);
|
|
1445
1467
|
}
|
|
1446
1468
|
else if (streamStartTime && !isStreamCompleted) {
|
|
1447
1469
|
// Live timer — update every second
|
|
@@ -1462,8 +1484,8 @@ const ThinkinHeaderInfo = (props) => {
|
|
|
1462
1484
|
}, [streamStartTime, isStreamCompleted, finalElapsedSeconds]);
|
|
1463
1485
|
// Determine display text
|
|
1464
1486
|
let displayText = thinkingHeaderMessage || '';
|
|
1465
|
-
if (frozenRef.current && frozenTextRef.current) {
|
|
1466
|
-
displayText = frozenTextRef.current;
|
|
1487
|
+
if (frozenText || (frozenRef.current && frozenTextRef.current)) {
|
|
1488
|
+
displayText = frozenText || frozenTextRef.current;
|
|
1467
1489
|
}
|
|
1468
1490
|
else if (streamStartTime && !isStreamCompleted) {
|
|
1469
1491
|
displayText = `Working for ${formatElapsedTime(elapsed)}`;
|
|
@@ -2457,6 +2479,20 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
|
|
|
2457
2479
|
}
|
|
2458
2480
|
if (data.flow_type === "agent" && data.actionType === "direct") {
|
|
2459
2481
|
data.baseUrl = baseUrl;
|
|
2482
|
+
// Reset the timer before the request goes out (same as index.jsx
|
|
2483
|
+
// handleSendMessage). Without this the new ThinkinHeaderInfo mounts while
|
|
2484
|
+
// the previous response's "completed" state is still in Redux and freezes
|
|
2485
|
+
// itself on that stale elapsed time.
|
|
2486
|
+
// streamStartTime stays null here: processStream sets it, so a question
|
|
2487
|
+
// has exactly one start time (two would make the new header look like a
|
|
2488
|
+
// superseded one and freeze it at 0m:00s).
|
|
2489
|
+
dispatch(setThinkingContext({
|
|
2490
|
+
thinkingContent: "",
|
|
2491
|
+
thinkingHeaderMessage: "Working for 0m:00s",
|
|
2492
|
+
streamStartTime: null,
|
|
2493
|
+
isStreamCompleted: false,
|
|
2494
|
+
finalElapsedSeconds: null,
|
|
2495
|
+
}));
|
|
2460
2496
|
prepareDataAndSendToAgent(data, false, {
|
|
2461
2497
|
chatbotContext: chatbotContext,
|
|
2462
2498
|
setChatbotContext: setChatbotContext,
|
|
@@ -5315,6 +5351,13 @@ const sseevent = (message, messageToStoreRef) => {
|
|
|
5315
5351
|
? parsedData.chat_id
|
|
5316
5352
|
: "";
|
|
5317
5353
|
messageToStoreRef.current.sessionId = parsedData?.session_id;
|
|
5354
|
+
// Sticky copy of the session id this message belongs to. sessionId gets
|
|
5355
|
+
// cleared on completed/follow-up so the next user message starts a fresh
|
|
5356
|
+
// session, but message level actions (like/dislike) still need to refer
|
|
5357
|
+
// to the session that actually produced this response.
|
|
5358
|
+
if (parsedData?.session_id) {
|
|
5359
|
+
messageToStoreRef.current.chatSessionId = parsedData.session_id;
|
|
5360
|
+
}
|
|
5318
5361
|
}
|
|
5319
5362
|
if (messageToStoreRef.current.currentMode === "navigation" &&
|
|
5320
5363
|
parsedData?.session_id) {
|
|
@@ -8663,7 +8706,7 @@ const StreamedContent = ({ botData, botProps }) => {
|
|
|
8663
8706
|
const retryTimerRef = useRef(null); // Interval ref for countdown
|
|
8664
8707
|
const retryCountdownRef = useRef(0); // Non-state countdown for interval callback
|
|
8665
8708
|
const thinkingContentRef = useRef("");
|
|
8666
|
-
useSelector((state) => {
|
|
8709
|
+
const thinkingContext = useSelector((state) => {
|
|
8667
8710
|
return state.smartBotReducer.thinkingContext;
|
|
8668
8711
|
});
|
|
8669
8712
|
const stepRef = useRef(_isAbortedRemount
|
|
@@ -8686,7 +8729,10 @@ const StreamedContent = ({ botData, botProps }) => {
|
|
|
8686
8729
|
const thinkingStartTimeRef = useRef(null);
|
|
8687
8730
|
const thinkingTimeFinalRef = useRef(0);
|
|
8688
8731
|
const thinkingHeaderMessageRef = useRef("Working for 0m:00s");
|
|
8689
|
-
|
|
8732
|
+
// Inherit the in-flight start time so a remount (e.g. tab switch, where
|
|
8733
|
+
// processStream is not re-run) keeps the original one instead of resetting.
|
|
8734
|
+
// Null for a fresh question - processStream sets it.
|
|
8735
|
+
const streamStartTimeRef = useRef(thinkingContext?.isStreamCompleted ? null : thinkingContext?.streamStartTime || null);
|
|
8690
8736
|
const thinkingDoneRef = useRef(false);
|
|
8691
8737
|
const thinkingStartedRef = useRef(false);
|
|
8692
8738
|
const setThinkingContentRef = useRef(setThinkingContent); // Store current setThinkingContent function
|
|
@@ -9661,7 +9707,12 @@ const StreamedContent = ({ botData, botProps }) => {
|
|
|
9661
9707
|
},
|
|
9662
9708
|
};
|
|
9663
9709
|
const hasStepFormWidgets = !isEmpty(stepFormDataMapRef.current);
|
|
9664
|
-
|
|
9710
|
+
// response.session_id is intentionally blank once the flow completes, so
|
|
9711
|
+
// keep the retained session separately and stamp it on the stored message.
|
|
9712
|
+
const messageChatSessionId = messageToStoreRef.current.chatSessionId ||
|
|
9713
|
+
messageToStoreRef.current.sessionId ||
|
|
9714
|
+
"";
|
|
9715
|
+
Promise.resolve(processResponse(response, botData.inputBody, currentMode, botData.utilityObject.customChatConfig, {
|
|
9665
9716
|
newChatData: chatDataInfoRef,
|
|
9666
9717
|
isTabEnabled: true,
|
|
9667
9718
|
steps: stepRef.current.map(s => ({ ...s })),
|
|
@@ -9669,7 +9720,15 @@ const StreamedContent = ({ botData, botProps }) => {
|
|
|
9669
9720
|
questions: [...questionsRef.current],
|
|
9670
9721
|
questionsStepsMap: { ...questionsStepsMapRef.current },
|
|
9671
9722
|
stepFormDataMap: { ...stepFormDataMapRef.current },
|
|
9672
|
-
}, activeConversationId)
|
|
9723
|
+
}, activeConversationId)).then(() => {
|
|
9724
|
+
if (!messageChatSessionId)
|
|
9725
|
+
return;
|
|
9726
|
+
const storedMessages = chatDataInfoRef.current?.[currentMode]?.conversations?.[activeConversationId]?.messages;
|
|
9727
|
+
if (storedMessages?.length) {
|
|
9728
|
+
storedMessages[storedMessages.length - 1].chatSessionId =
|
|
9729
|
+
messageChatSessionId;
|
|
9730
|
+
}
|
|
9731
|
+
});
|
|
9673
9732
|
// [
|
|
9674
9733
|
// {
|
|
9675
9734
|
// header: "Finding relevant information",
|
|
@@ -15833,10 +15892,14 @@ const SmartBot = (props) => {
|
|
|
15833
15892
|
answerMode: answerMode,
|
|
15834
15893
|
};
|
|
15835
15894
|
// if(!isEmpty(userInput)) {
|
|
15895
|
+
// Clear the previous response's completed state so the incoming
|
|
15896
|
+
// ThinkinHeaderInfo doesn't freeze on it. streamStartTime stays null
|
|
15897
|
+
// here: processStream sets it, so a question has exactly one start
|
|
15898
|
+
// time (two would make the new header look like a superseded one).
|
|
15836
15899
|
dispatch(setThinkingContext({
|
|
15837
15900
|
thinkingContent: "",
|
|
15838
15901
|
thinkingHeaderMessage: "Working for 0m:00s",
|
|
15839
|
-
streamStartTime:
|
|
15902
|
+
streamStartTime: null,
|
|
15840
15903
|
isStreamCompleted: false,
|
|
15841
15904
|
finalElapsedSeconds: null,
|
|
15842
15905
|
}));
|