impact-chatbot 2.3.47 → 2.3.48

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.esm.js CHANGED
@@ -5086,6 +5086,15 @@ const sseevent = (message, messageToStoreRef) => {
5086
5086
  }
5087
5087
  return new MessageEvent(type, { data: data });
5088
5088
  }
5089
+ if (parsedData?.status === "notification") {
5090
+ messageToStoreRef.current.notificationData = {
5091
+ message: parsedData?.message || "",
5092
+ chat_id: parsedData?.chat_id || "",
5093
+ session_id: parsedData?.session_id || "",
5094
+ };
5095
+ // Do NOT append notification messages to chatData.response — return early
5096
+ return new MessageEvent(type, { data: data });
5097
+ }
5089
5098
  if (parsedData?.status === "thinking") {
5090
5099
  messageToStoreRef.current.chatData.thinkingResponse.thinkingStream =
5091
5100
  messageToStoreRef.current.chatData.thinkingResponse.thinkingStream +
@@ -5122,13 +5131,6 @@ const sseevent = (message, messageToStoreRef) => {
5122
5131
  ? parsedData.additional_args
5123
5132
  : {};
5124
5133
  }
5125
- if (parsedData?.status === "notification") {
5126
- messageToStoreRef.current.notificationData = {
5127
- message: parsedData?.message || "",
5128
- chat_id: parsedData?.chat_id || "",
5129
- session_id: parsedData?.session_id || "",
5130
- };
5131
- }
5132
5134
  if (parsedData?.status === "completed" ||
5133
5135
  parsedData?.status === "follow-up") {
5134
5136
  messageToStoreRef.current.initValue = true;
@@ -5391,10 +5393,10 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5391
5393
  if (sessionId) {
5392
5394
  stopAgentFlow({ session_id: sessionId }, baseUrl);
5393
5395
  }
5394
- dispatch(setStepFormStreamData({ status: "error", chunks: [...chunksRef] }));
5396
+ dispatch(setStepFormStreamData({ status: "error", chunks: [...chunksRef], sessionId }));
5395
5397
  };
5396
5398
  // Signal that streaming has started (after setting stepFormStreamControl so useEffect sees the flag)
5397
- dispatch(setStepFormStreamData({ status: "streaming_start", chunks: [] }));
5399
+ dispatch(setStepFormStreamData({ status: "streaming_start", chunks: [], sessionId }));
5398
5400
  // Fire DOM event so SmartBot can show stop icon (Redux gets cleared by TabularContent before parent effects run)
5399
5401
  window.dispatchEvent(new CustomEvent("stepFormStreamStart"));
5400
5402
  sourceRef.current = AxiosSource(endPoint, {
@@ -5416,14 +5418,14 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5416
5418
  chunksRef.push(data);
5417
5419
  // Dispatch widget chunks immediately for real-time rendering
5418
5420
  if (data?.status === "widget") {
5419
- dispatch(setStepFormStreamData({ status: "widget_chunk", chunks: [data] }));
5421
+ dispatch(setStepFormStreamData({ status: "widget_chunk", chunks: [data], sessionId }));
5420
5422
  }
5421
5423
  // If this chunk also carries [DONE], dispatch collected chunks now
5422
5424
  if (data?.message === "[DONE]") {
5423
5425
  stepFormStreamControl.isStreaming = false;
5424
5426
  stepFormStreamControl.abort = null;
5425
5427
  window.dispatchEvent(new CustomEvent("stepFormStreamEnd"));
5426
- dispatch(setStepFormStreamData({ status: "done", chunks: [...chunksRef] }));
5428
+ dispatch(setStepFormStreamData({ status: "done", chunks: [...chunksRef], sessionId }));
5427
5429
  }
5428
5430
  }
5429
5431
  else if (data?.status === "completed" || data?.status === "follow-up" || data?.message === "[DONE]") {
@@ -5447,7 +5449,7 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5447
5449
  if (data?.status === "completed" && !hasStepForm) {
5448
5450
  window.dispatchEvent(new CustomEvent("stepFormStreamCompleted"));
5449
5451
  }
5450
- dispatch(setStepFormStreamData({ status: "done", chunks: [...chunksRef] }));
5452
+ dispatch(setStepFormStreamData({ status: "done", chunks: [...chunksRef], sessionId }));
5451
5453
  }
5452
5454
  else if (data?.message) {
5453
5455
  chunksRef.push({ status: "content", message: data.message });
@@ -5462,7 +5464,7 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5462
5464
  stepFormStreamControl.isStreaming = false;
5463
5465
  stepFormStreamControl.abort = null;
5464
5466
  window.dispatchEvent(new CustomEvent("stepFormStreamEnd"));
5465
- dispatch(setStepFormStreamData({ status: "error", chunks: chunksRef }));
5467
+ dispatch(setStepFormStreamData({ status: "error", chunks: chunksRef, sessionId }));
5466
5468
  });
5467
5469
  };
5468
5470
  const renderButtons = () => {
@@ -7347,6 +7349,7 @@ const StreamedContent = ({ botData }) => {
7347
7349
  data: isEmpty(dummyButton)
7348
7350
  ? [textResponseTobeParsed, ...finalData]
7349
7351
  : [textResponseTobeParsed, ...finalData, dummyButton],
7352
+ session_id: messageToStoreRef.current.sessionId || "",
7350
7353
  },
7351
7354
  },
7352
7355
  };
@@ -7431,6 +7434,7 @@ const StreamedContent = ({ botData }) => {
7431
7434
  data: {
7432
7435
  data: {
7433
7436
  data: [textResponseTobeParsed, ...finalData],
7437
+ session_id: messageToStoreRef.current.sessionId || "",
7434
7438
  },
7435
7439
  },
7436
7440
  };
@@ -7851,7 +7855,11 @@ const AgentResponse = ({ children }) => {
7851
7855
  return (jsx("div", { className: classes.agentResponseContainer, children: children }));
7852
7856
  };
7853
7857
 
7854
- const TabularContent = ({ steps: initialSteps, currentTabValue, children, questions: initialQuestions = [], questionsStepsMap: initialQuestionsStepsMap = {}, stepFormDataMap: initialStepFormDataMap = {}, isFormDisabled = false }) => {
7858
+ // Module-level counter and active instance tracker.
7859
+ // Only the active instance should process stepFormStreamData from Redux.
7860
+ let instanceCounter = 0;
7861
+ let activeTabularInstanceId = null;
7862
+ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questions: initialQuestions = [], questionsStepsMap: initialQuestionsStepsMap = {}, stepFormDataMap: initialStepFormDataMap = {}, isFormDisabled = false, sessionId: propSessionId = "" }) => {
7855
7863
  const dispatch = useDispatch();
7856
7864
  const stepFormStreamData = useSelector((state) => state.smartBotReducer.stepFormStreamData);
7857
7865
  const [tabValue, setTabValue] = useState(currentTabValue);
@@ -7875,6 +7883,12 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
7875
7883
  const [stepFormSubmitted, setStepFormSubmitted] = useState(false);
7876
7884
  const [hasNewStepFormFromRestream, setHasNewStepFormFromRestream] = useState(false);
7877
7885
  const [activeFormIntent, setActiveFormIntent] = useState(null);
7886
+ // Stable unique instance ID for this TabularContent mount
7887
+ const instanceIdRef = useRef(null);
7888
+ if (instanceIdRef.current === null) {
7889
+ instanceCounter += 1;
7890
+ instanceIdRef.current = instanceCounter;
7891
+ }
7878
7892
  // Refs for accumulating state during streaming (avoids stale closures)
7879
7893
  const stepsRef = useRef(stepsState);
7880
7894
  const questionsRef = useRef(questionsState);
@@ -7916,10 +7930,21 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
7916
7930
  return null;
7917
7931
  }
7918
7932
  };
7933
+ // Register as active instance when this TabularContent has an active step form
7934
+ useEffect(() => {
7935
+ const hasActiveForm = Object.keys(initialStepFormDataMap).length > 0;
7936
+ if (hasActiveForm) {
7937
+ activeTabularInstanceId = instanceIdRef.current;
7938
+ }
7939
+ }, [initialStepFormDataMap]);
7919
7940
  // Watch Redux for batched SSE chunks dispatched by ButtonContent
7920
7941
  useEffect(() => {
7921
7942
  if (!stepFormStreamData)
7922
7943
  return;
7944
+ // Only the active instance should process stepFormStreamData
7945
+ if (activeTabularInstanceId !== null && activeTabularInstanceId !== instanceIdRef.current) {
7946
+ return;
7947
+ }
7923
7948
  const payload = stepFormStreamData;
7924
7949
  // Clear Redux immediately
7925
7950
  dispatch(setStepFormStreamData(null));
@@ -8073,6 +8098,8 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
8073
8098
  setStepFormSubmitted(false);
8074
8099
  setHasNewStepFormFromRestream(true);
8075
8100
  setActiveFormIntent(latestIntent || null);
8101
+ // Re-register as active instance since this TabularContent now owns the new form
8102
+ activeTabularInstanceId = instanceIdRef.current;
8076
8103
  // Clear stale persisted form values and context so the new form starts fresh
8077
8104
  dispatch(clearPersistedFormValues());
8078
8105
  dispatch(setChatbotContext({}));
@@ -8097,6 +8124,10 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
8097
8124
  jsxs(AgentResponse, { children: [children, renderedWidgets.length > 0 && (jsx("div", { className: "restream-widget-content", children: renderedWidgets }))] }),
8098
8125
  ], value: tabValue }) }));
8099
8126
  };
8127
+ /** Reset the active instance tracker (call when a new conversation starts from the input field) */
8128
+ const resetActiveTabularInstance = () => {
8129
+ activeTabularInstanceId = null;
8130
+ };
8100
8131
 
8101
8132
  const CombinedContent = ({ botData, props }) => {
8102
8133
  const isFormDisabled = botData?.isFormDisabled || false;
@@ -8165,7 +8196,7 @@ const CombinedContent = ({ botData, props }) => {
8165
8196
  const validContent = renderedContent.filter(content => content !== null);
8166
8197
  const renderCombinedContent = () => (jsx("div", { className: "combined-content-container", children: validContent.length > 0 ? (validContent.map((content, index) => (jsx("div", { className: "combined-content-item", children: content }, `wrapper-${index}`)))) : (jsx("div", { children: "No valid content to display" })) }));
8167
8198
  if (isTabEnabled) {
8168
- return (jsx(TabularContent, { steps: botData?.utilityData?.steps || [], currentTabValue: botData?.utilityData?.currentTabValue || "steps", questions: botData?.utilityData?.questions || [], questionsStepsMap: botData?.utilityData?.questionsStepsMap || {}, stepFormDataMap: botData?.utilityData?.stepFormDataMap || {}, isFormDisabled: isFormDisabled, children: renderCombinedContent() }));
8199
+ return (jsx(TabularContent, { steps: botData?.utilityData?.steps || [], currentTabValue: botData?.utilityData?.currentTabValue || "steps", questions: botData?.utilityData?.questions || [], questionsStepsMap: botData?.utilityData?.questionsStepsMap || {}, stepFormDataMap: botData?.utilityData?.stepFormDataMap || {}, isFormDisabled: isFormDisabled, sessionId: botData?.sessionId || "", children: renderCombinedContent() }));
8169
8200
  }
8170
8201
  return renderCombinedContent();
8171
8202
  };
@@ -11692,7 +11723,7 @@ const useStyles = makeStyles({
11692
11723
  });
11693
11724
  const ChatbotSaveFilterComponent = (props) => {
11694
11725
  const classes = useStyles();
11695
- const { savedFilterSets, partialClose } = props;
11726
+ const { savedFilterSets, partialClose, chatBotWidth } = props;
11696
11727
  const [showFilter, setShowFilter] = useState(!isEmpty$1(savedFilterSets));
11697
11728
  /**
11698
11729
  * onFilterDashboardClick function is called when we click the apply filter
@@ -11765,11 +11796,13 @@ const ChatbotSaveFilterComponent = (props) => {
11765
11796
  }
11766
11797
  const filterContainer = document.querySelector(".impact_drawer_filter_container.impact_drawer_filter_container_large");
11767
11798
  if (filterContainer) {
11768
- filterContainer.style.setProperty("width", "616px");
11799
+ const computedWidth = chatBotWidth ? `${chatBotWidth - 86}px` : "616px";
11800
+ filterContainer.style.setProperty("width", computedWidth);
11769
11801
  }
11770
11802
  const rightPanel = document.querySelector(".impact_drawer_filter_container .impact_drawer_filter_container_right_panel");
11771
11803
  if (rightPanel) {
11772
11804
  rightPanel.style.setProperty("height", "600px");
11805
+ rightPanel.style.setProperty("width", "100%");
11773
11806
  }
11774
11807
  const backdrop = document.querySelector(".MuiBackdrop-root.MuiModal-backdrop");
11775
11808
  if (backdrop) {
@@ -11803,7 +11836,7 @@ const ChatbotSaveFilterComponent = (props) => {
11803
11836
  const observer = new MutationObserver(patchDrawer);
11804
11837
  observer.observe(document.body, { childList: true, subtree: true });
11805
11838
  return () => observer.disconnect();
11806
- }, [showFilter]);
11839
+ }, [showFilter, chatBotWidth]);
11807
11840
  return (jsx("div", { className: partialClose ? classes.hidden : undefined, children: !showFilter ?
11808
11841
  jsxs("div", { className: classes.container, children: [jsx(NoFilterSetSavedIcon, { width: "189px", height: "126px", className: classes.icon }), jsx("p", { className: classes.title, children: "No filter set saved!" }), jsx("p", { className: classes.subtitle, children: "Create and save a filter set to use as your default scope or apply it anytime during a conversation" }), jsx("div", { className: classes.buttonWrapper, children: jsx(Button, { variant: "primary", onClick: () => setShowFilter(true), children: "Create A Filter Set" }) })] }) :
11809
11842
  jsx("div", { children: jsx(CoreComponentScreen, { showPageHeader: false,
@@ -11837,6 +11870,7 @@ const SmartBot = (props) => {
11837
11870
  // Per-mode conversation ID tracking — prevents cross-mode contamination when
11838
11871
  // switching tabs while streams are pending.
11839
11872
  useRef({});
11873
+ const activeConversationIdRef = useRef(activeConversationId);
11840
11874
  const activeTab = useRef({
11841
11875
  activeTab: "dashboard",
11842
11876
  });
@@ -11855,6 +11889,7 @@ const SmartBot = (props) => {
11855
11889
  const [filterOptions, setFilterOptions] = useState([]);
11856
11890
  const [savedFilterSets, setSavedFilterSets$1] = useState([]);
11857
11891
  const [selectedFilterSet, setSelectedFilterSet] = useState(null);
11892
+ const [chatBotWidth, setChatBotWidth] = useState(null);
11858
11893
  useRef(0);
11859
11894
  const { setUserFlow, setUserScreenAndFlow, fetchUserResultsFromQuery, getCurrentDateTimeString, setLink, } = useChatFlow(chatDataRef, setLoader, setFlowType, setScreenName, setUserInput, setQuestionIndex, setCurrentAppLink, flowType, screenName, questionIndex, userInput, dateFormat, currentMode, activeConversationId, setIsModuleChanged, chatBodyRef, filterReducerState, dispatch, navigate, setShowChatPlaceholder, baseUrl, setChatDataState, setCurrentSessionId, customChatConfig, chatDataInfoRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, initValue, sessionId, fieldNumber, setFieldNumber, additionalArgs, setActiveConversationId, navSessionId, setNavSessionId);
11860
11895
  const { parseSavedFlow, saveCurrentChanges, endCurrentSession, clearChatSession, initiateNewChat, hasUnsavedChanges, } = useChatSession(chatDataRef, setFlowType, setScreenName, setUserInput, setTemplateData, chatDataScreenLinkRef, setShowModal, setMinimizedMode, setSelectedModule, setChatDataState, currentMode, setUserFlow, getCurrentDateTimeString, setCurrentAppLink, selectedModule, fetchUserResultsFromQuery, props.closeBot, activeConversationId, setActiveConversationId, setShowChatPlaceholder);
@@ -11887,6 +11922,10 @@ const SmartBot = (props) => {
11887
11922
  setFieldNumber,
11888
11923
  setAdditionalArgs,
11889
11924
  });
11925
+ // Keep activeConversationIdRef in sync so event handlers with [] deps can access the latest value
11926
+ useEffect(() => {
11927
+ activeConversationIdRef.current = activeConversationId;
11928
+ }, [activeConversationId]);
11890
11929
  // Show/hide stop icon when step-form restream (second init API from ButtonContent) starts/ends.
11891
11930
  // Must live here (SmartBot) because StreamedContent unmounts after the first stream completes.
11892
11931
  useEffect(() => {
@@ -11908,6 +11947,23 @@ const SmartBot = (props) => {
11908
11947
  };
11909
11948
  const handleStepFormStreamEnd = () => {
11910
11949
  setIsStop(false);
11950
+ // Update the timestamp on the last bot message to reflect when the restream completed
11951
+ try {
11952
+ const mode = localStorage.getItem("currentModeData") || "agent";
11953
+ const convId = activeConversationIdRef.current;
11954
+ const messages = chatDataInfoRef?.current?.[mode]?.conversations?.[convId]?.messages;
11955
+ if (messages && messages.length > 0) {
11956
+ const lastBotIdx = messages.reduce((lastIdx, msg, idx) => msg.userType === "bot" ? idx : lastIdx, -1);
11957
+ if (lastBotIdx !== -1) {
11958
+ messages[lastBotIdx].timeStamp = moment().format(dateFormat);
11959
+ // Trigger re-render so the UI reflects the updated timestamp
11960
+ setChatDataState((prev) => ({ ...prev }));
11961
+ }
11962
+ }
11963
+ }
11964
+ catch (e) {
11965
+ console.error("Error updating timestamp after step form stream:", e);
11966
+ }
11911
11967
  };
11912
11968
  window.addEventListener("stepFormStreamStart", handleStepFormStreamStart);
11913
11969
  window.addEventListener("stepFormStreamEnd", handleStepFormStreamEnd);
@@ -12344,6 +12400,9 @@ const SmartBot = (props) => {
12344
12400
  };
12345
12401
  const onSendIconClick = (params, params2) => {
12346
12402
  try {
12403
+ // Reset step form stream state so old TabularContent instances don't process new data
12404
+ dispatch(setStepFormStreamData(null));
12405
+ resetActiveTabularInstance();
12347
12406
  // dispatch(setChatbotContext({}));
12348
12407
  setUserInput(params?.text);
12349
12408
  handleSendMessage(params?.text, params?.userExplicitInput, params?.textWithColumnNames);
@@ -12510,6 +12569,8 @@ const SmartBot = (props) => {
12510
12569
  localStorage.setItem("isStreaming", "false");
12511
12570
  dispatch(setChatbotContext({}));
12512
12571
  dispatch(clearPersistedFormValues());
12572
+ dispatch(setStepFormStreamData(null));
12573
+ resetActiveTabularInstance();
12513
12574
  setConversation([]);
12514
12575
  chatDataInfoRef.current[currentMode] = {
12515
12576
  conversations: {},
@@ -12702,7 +12763,7 @@ const SmartBot = (props) => {
12702
12763
  ], utilityList: utilityList, isAssistantThinking: false, isCustomScreen: showChatPlaceholder ? showChatPlaceholder : showSavedFilters, customScreenJsx: showChatPlaceholder ?
12703
12764
  jsx(ChatPlaceholder, { dateFormat: dateFormat, chatDataRef: chatDataRef, currentMode: currentMode, setShowChatPlaceholder: setShowChatPlaceholder, setLoader: setLoader, setCurrentAgentId: setCurrentAgentId, baseUrl: baseUrl, setBaseUrl: setBaseUrl, setCurrentSessionId: setCurrentSessionId, customChatConfig: customChatConfig, chatDataInfoRef: chatDataInfoRef, setChatDataState: setChatDataState, userInput: userInput, legacyAgentScreen: legacyAgentScreen, activeConversationId: activeConversationId, chatBodyRef: chatBodyRef, chatbotContext: chatbotContext, setInitValue: setInitValue, setSessionId: setSessionId, thinkingContent: thinkingContext?.thinkingContent, setThinkingContent: setThinkingContent, isThinking: isThinking, setIsThinking: setIsThinking, chatId: chatId, setChatId: setChatId, isStop: isStop, setIsStop: setIsStop, functionsRef: functionsRef, functionsState: functionsState, setFunctionsState: setFunctionsState, thinkingHeaderMessage: thinkingContext?.thinkingHeaderMessage, setThinkingHeaderMessage: setThinkingHeaderMessage, uniqueChatId: uniqueChatId, setUniqueChatId: setUniqueChatId, fieldNumber: fieldNumber, setFieldNumber: setFieldNumber, setAdditionalArgs: setAdditionalArgs, displayQuestions: displayQuestions, questions: questions, setActiveConversationId: setActiveConversationId })
12704
12765
  :
12705
- jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
12766
+ jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose, chatBotWidth: chatBotWidth }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
12706
12767
  freeTextHeading: "Try adding more details :",
12707
12768
  freeTextContent: "Alan works better when you provide more context and pointed questions",
12708
12769
  }, isStopIcon: isStop, onStopIconClick: onStopIconClick, footerText: "AI-generated responses may contain errors\u2014please verify important information", showSuggestionBanner: showSavedFilters ? false : showSuggestionBanner, onCloseSuggestionBanner: () => {
@@ -12722,7 +12783,9 @@ const SmartBot = (props) => {
12722
12783
  }, handleSaveChat: () => {
12723
12784
  // Handle save chat logic here
12724
12785
  saveCurrentChat();
12725
- } })] }));
12786
+ }, onChatBotResize: (params) => {
12787
+ setChatBotWidth(params);
12788
+ }, onMinimiseChatBot: null })] }));
12726
12789
  };
12727
12790
 
12728
12791
  export { SmartBot as default };