impact-chatbot 2.3.64 → 2.3.66

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 CHANGED
@@ -337,7 +337,7 @@ const useBotConfiguration = (setRefreshLoader, setEnableRefreshAction, dispatch)
337
337
  */
338
338
  const parseResponse = (data, type, agentId = "", currentMode = "", disableTimeAndName = false, sessionId = "", utilityData = {}, inputBody = null, utilityObject = {}) => {
339
339
  const timeString = disableTimeAndName ? "" : moment().format("DD-MM-YYYY HH:mm:ss");
340
- const userName = disableTimeAndName ? "" : "Alan";
340
+ const userName = disableTimeAndName ? "" : "Iris";
341
341
  switch (type || data?.type) {
342
342
  case "text":
343
343
  return {
@@ -1414,7 +1414,7 @@ const useAgentFlow = (dateFormat, chatDataRef, currentMode, setShowChatPlacehold
1414
1414
  hasDirectActionType: false,
1415
1415
  };
1416
1416
  const loaderData = {
1417
- userName: "Alan",
1417
+ userName: "Iris",
1418
1418
  timeStamp: currentTimeString,
1419
1419
  userType: "loader",
1420
1420
  };
@@ -1980,7 +1980,7 @@ const useAgentFlow = (dateFormat, chatDataRef, currentMode, setShowChatPlacehold
1980
1980
  const failResponseText = {
1981
1981
  timeStamp: getCurrentDateTimeString(),
1982
1982
  userType: "bot",
1983
- userName: "Alan",
1983
+ userName: "Iris",
1984
1984
  bodyText: error?.response?.data?.data?.error?.response
1985
1985
  ? error?.response?.data?.data?.error?.response
1986
1986
  : "Sorry, chatbot is not available now",
@@ -2224,7 +2224,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2224
2224
  return {
2225
2225
  timeStamp: timeString,
2226
2226
  userType: "bot",
2227
- userName: "Alan",
2227
+ userName: "Iris",
2228
2228
  headerTitle: headerTitle,
2229
2229
  bodyType: "chips",
2230
2230
  bodyText: screens.map((screen) => ({
@@ -2278,7 +2278,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2278
2278
  flow_type: flowType,
2279
2279
  };
2280
2280
  const loaderData = {
2281
- userName: "Alan",
2281
+ userName: "Iris",
2282
2282
  timeStamp: currentTimeString,
2283
2283
  userType: "loader",
2284
2284
  };
@@ -2312,7 +2312,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2312
2312
  const failResponseText = {
2313
2313
  timeStamp: getCurrentDateTimeString(),
2314
2314
  userType: "bot",
2315
- userName: "Alan",
2315
+ userName: "Iris",
2316
2316
  bodyText: options.data.data.message,
2317
2317
  enableLikes: false,
2318
2318
  headerTitle: "",
@@ -2331,7 +2331,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2331
2331
  const failResponseText = {
2332
2332
  timeStamp: getCurrentDateTimeString(),
2333
2333
  userType: "bot",
2334
- userName: "Alan",
2334
+ userName: "Iris",
2335
2335
  bodyText: "Failed to fetch user screens. Please try again later.",
2336
2336
  headerTitle: "",
2337
2337
  enableLikes: false,
@@ -2403,7 +2403,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2403
2403
  hasDirectActionType: fetchQuestions,
2404
2404
  };
2405
2405
  const loaderData = {
2406
- userName: "Alan",
2406
+ userName: "Iris",
2407
2407
  timeStamp: currentTimeString,
2408
2408
  userType: "loader",
2409
2409
  };
@@ -2523,7 +2523,7 @@ const useChatFlow = (chatDataRef, setLoader, setFlowType, setScreenName, setUser
2523
2523
  const failResponseText = {
2524
2524
  timeStamp: getCurrentDateTimeString(),
2525
2525
  userType: "bot",
2526
- userName: "Alan",
2526
+ userName: "Iris",
2527
2527
  bodyText: error?.response?.data?.data?.error?.response
2528
2528
  ? error?.response?.data?.data?.error?.response
2529
2529
  : "Sorry, chatbot is not available now",
@@ -2734,10 +2734,10 @@ const useChatSession = (chatDataRef, setFlowType, setScreenName, setUserInput, s
2734
2734
  {
2735
2735
  timeStamp: getCurrentDateTimeString(),
2736
2736
  userType: "bot",
2737
- userName: "Alan",
2737
+ userName: "Iris",
2738
2738
  headerTitle: `Hi ${getUserName()}!`,
2739
2739
  bodyType: "text",
2740
- bodyText: `I am Alan, your virtual assistant. I am here to help you on anything you are looking for in IA Smart Platform`,
2740
+ bodyText: `I am Iris, your virtual assistant. I am here to help you on anything you are looking for in IA Smart Platform`,
2741
2741
  },
2742
2742
  ];
2743
2743
  // chatDataRef.current[currentMode].conversations[
@@ -4903,7 +4903,7 @@ const ChatPlaceholder = (props) => {
4903
4903
  agentId: card.agentId || card.id
4904
4904
  }));
4905
4905
  const dataToMap = legacyAgentScreen || displayQuestions ? transformedCardList : rectangleData;
4906
- return (jsxRuntime.jsxs("div", { className: classes.placeholderContainer, children: [jsxRuntime.jsx("div", { className: classes.centerIconContainer, children: jsxRuntime.jsx(SvgCenter3D, { className: classes.centerIcon }) }), jsxRuntime.jsxs("div", { className: classes.headingContainer, children: [jsxRuntime.jsx(material.Typography, { variant: "h1", className: classes.heading, children: "Alan's Capabilities" }), jsxRuntime.jsx("span", { className: classes.alphaTag, children: "Beta" })] }), jsxRuntime.jsx(material.Typography, { variant: "body1", className: classes.headingHelperText, children: "Discover potential issues & opportunities Alan can help you with!" }), jsxRuntime.jsx("div", { className: classes.rectanglesContainer, children: dataToMap.map((item, index) => (jsxRuntime.jsx(Rectangle, { type: item.type, icon: item.icon, title: item.title, description: item.description, onClick: () => handleRectangleClick(item?.agentId, item?.title), hoverable: legacyAgentScreen || displayQuestions }, index))) })] }));
4906
+ return (jsxRuntime.jsxs("div", { className: classes.placeholderContainer, children: [jsxRuntime.jsx("div", { className: classes.centerIconContainer, children: jsxRuntime.jsx(SvgCenter3D, { className: classes.centerIcon }) }), jsxRuntime.jsxs("div", { className: classes.headingContainer, children: [jsxRuntime.jsx(material.Typography, { variant: "h1", className: classes.heading, children: "Iris's Capabilities" }), jsxRuntime.jsx("span", { className: classes.alphaTag, children: "Beta" })] }), jsxRuntime.jsx(material.Typography, { variant: "body1", className: classes.headingHelperText, children: "Discover potential issues & opportunities Iris can help you with!" }), jsxRuntime.jsx("div", { className: classes.rectanglesContainer, children: dataToMap.map((item, index) => (jsxRuntime.jsx(Rectangle, { type: item.type, icon: item.icon, title: item.title, description: item.description, onClick: () => handleRectangleClick(item?.agentId, item?.title), hoverable: legacyAgentScreen || displayQuestions }, index))) })] }));
4907
4907
  };
4908
4908
 
4909
4909
  const dateFormat = "DD-MM-YYYY HH:mm:ss";
@@ -7149,15 +7149,43 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7149
7149
  const chatbotFilterOptions = reactRedux.useSelector((state) => state.smartBotReducer.chatbotFilterOptions);
7150
7150
  const dimensionHierarchies = reactRedux.useSelector((state) => state.userRoleManagementService?.dimensionHierarchies);
7151
7151
  const [isFormSubmitted, setIsFormSubmitted] = React.useState(false);
7152
+ const [isTimedOut, setIsTimedOut] = React.useState(false);
7153
+ const timeoutRef = React.useRef(null);
7154
+ // 30-minute inactivity timeout: disable form and switch to agent_response tab
7155
+ const FORM_TIMEOUT_MS = 30 * 60 * 1000;
7156
+ React.useEffect(() => {
7157
+ if (isFormDisabled || isFormSubmitted || isTimedOut)
7158
+ return;
7159
+ const startTime = Date.now();
7160
+ timeoutRef.current = setTimeout(() => {
7161
+ setIsTimedOut(true);
7162
+ const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
7163
+ window.dispatchEvent(new CustomEvent("stepFormTimeout", { detail: { elapsedSeconds } }));
7164
+ }, FORM_TIMEOUT_MS);
7165
+ return () => {
7166
+ if (timeoutRef.current) {
7167
+ clearTimeout(timeoutRef.current);
7168
+ timeoutRef.current = null;
7169
+ }
7170
+ };
7171
+ }, [isFormDisabled, isFormSubmitted, isTimedOut]);
7172
+ // Clear timeout when form is submitted
7173
+ React.useEffect(() => {
7174
+ if (isFormSubmitted && timeoutRef.current) {
7175
+ clearTimeout(timeoutRef.current);
7176
+ timeoutRef.current = null;
7177
+ }
7178
+ }, [isFormSubmitted]);
7152
7179
  React.useEffect(() => {
7153
7180
  if (stepFormStreamData?.status === "streaming_start") {
7154
7181
  setIsFormSubmitted(true);
7155
7182
  }
7156
7183
  }, [stepFormStreamData]);
7157
- // Reset isFormSubmitted when parent signals the form should be enabled (new step_form from restream)
7184
+ // Reset isFormSubmitted and isTimedOut when parent signals the form should be enabled (new step_form from restream)
7158
7185
  React.useEffect(() => {
7159
7186
  if (!isFormDisabled) {
7160
7187
  setIsFormSubmitted(false);
7188
+ setIsTimedOut(false);
7161
7189
  }
7162
7190
  }, [isFormDisabled]);
7163
7191
  const [isFilterSetOpen, setIsFilterSetOpen] = React.useState(false);
@@ -7228,8 +7256,8 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7228
7256
  return val && (Array.isArray(val) ? val.length > 0 : !!val);
7229
7257
  });
7230
7258
  }, [persistedFormValues, messageIndex]);
7231
- const formFieldsDisabled = isFormDisabled || isFilterSelected || isFormSubmitted;
7232
- const savedFilterDisabled = isFormDisabled || isFormFieldUsed || isFormSubmitted;
7259
+ const formFieldsDisabled = isFormDisabled || isFilterSelected || isFormSubmitted || isTimedOut;
7260
+ const savedFilterDisabled = isFormDisabled || isFormFieldUsed || isFormSubmitted || isTimedOut;
7233
7261
  const requiredFieldsFilled = React.useMemo(() => {
7234
7262
  if (!formData || !Array.isArray(formData))
7235
7263
  return false;
@@ -7817,7 +7845,40 @@ const AgentResponse$1 = (props) => {
7817
7845
 
7818
7846
  const StepsResponseTab = (props) => {
7819
7847
  const { steps, setSteps, stepsDone, setStepsDone, finalStepDone, setFinalStepDone, content, isStreaming, stepChange, currentMode, questions, questionsStepsMap, stepFormDataMap, isFormDisabled, streamingWidgetData, isRetrying, } = props;
7848
+ const dispatch = reactRedux.useDispatch();
7849
+ const thinkingContext = reactRedux.useSelector((state) => state.smartBotReducer.thinkingContext);
7850
+ const streamStartTimeRef = React.useRef(thinkingContext?.streamStartTime);
7851
+ // Keep streamStartTime ref in sync with Redux for use in event handler closures
7852
+ React.useEffect(() => {
7853
+ streamStartTimeRef.current = thinkingContext?.streamStartTime;
7854
+ }, [thinkingContext?.streamStartTime]);
7820
7855
  const [tabValue, setTabValue] = React.useState("steps");
7856
+ const [timeoutMessage, setTimeoutMessage] = React.useState("");
7857
+ // Switch to agent_response tab on form inactivity timeout (30 min)
7858
+ React.useEffect(() => {
7859
+ const handleStepFormTimeout = () => {
7860
+ setTimeoutMessage("This session timed out due to inactivity. Please start a new message to continue.");
7861
+ setTabValue("agent_response");
7862
+ dispatch(smartBotActions.setMinimizedStreamData(null));
7863
+ const elapsed = streamStartTimeRef.current
7864
+ ? Math.floor((Date.now() - streamStartTimeRef.current) / 1000)
7865
+ : null;
7866
+ const mins = elapsed != null ? Math.floor(elapsed / 60) : 0;
7867
+ const secs = elapsed != null ? elapsed % 60 : 0;
7868
+ const timedOutLabel = `Worked for ${mins}m:${String(secs).padStart(2, '0')}s`;
7869
+ dispatch(smartBotActions.setThinkingContext({
7870
+ streamStartTime: null,
7871
+ isStreamCompleted: true,
7872
+ finalElapsedSeconds: elapsed,
7873
+ thinkingHeaderMessage: timedOutLabel,
7874
+ thinkingContent: "",
7875
+ }));
7876
+ };
7877
+ window.addEventListener("stepFormTimeout", handleStepFormTimeout);
7878
+ return () => {
7879
+ window.removeEventListener("stepFormTimeout", handleStepFormTimeout);
7880
+ };
7881
+ }, []);
7821
7882
  // When retry countdown starts, switch to agent_response to show it.
7822
7883
  // When retry actually fires (isRetrying goes false + isStreaming goes true), switch back to steps.
7823
7884
  React.useEffect(() => {
@@ -7846,7 +7907,7 @@ const StepsResponseTab = (props) => {
7846
7907
  },
7847
7908
  ], tabPanels: [
7848
7909
  jsxRuntime.jsx(Steps$1, { steps: steps, setSteps: setSteps, done: stepsDone, setDone: setStepsDone, setTabValue: setTabValue, finalStepDone: finalStepDone, setFinalStepDone: setFinalStepDone, stepChange: stepChange, currentMode: currentMode, questions: questions, questionsStepsMap: questionsStepsMap, stepFormDataMap: stepFormDataMap, isFormDisabled: isFormDisabled }),
7849
- jsxRuntime.jsx(AgentResponse$1, { content: content, isStreaming: isStreaming, streamingWidgetData: streamingWidgetData }),
7910
+ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(AgentResponse$1, { content: content, isStreaming: isStreaming, streamingWidgetData: streamingWidgetData }), timeoutMessage && (jsxRuntime.jsx("div", { style: { marginTop: "8px", padding: "0 8px" }, children: jsxRuntime.jsx(TextRenderer, { text: timeoutMessage, thinking: "" }) }))] }),
7850
7911
  ], value: tabValue }) }));
7851
7912
  };
7852
7913
 
@@ -8674,6 +8735,7 @@ const StreamedContent = ({ botData }) => {
8674
8735
  // Check if this is a user-initiated abort (should not trigger retry)
8675
8736
  const isUserAbort = event.reason === "Network request aborted";
8676
8737
  event.statusCode === 503;
8738
+ const isAgentUnavailable = event.statusCode === 502 || event.statusCode === 404;
8677
8739
  if (isThinking) {
8678
8740
  setIsThinking(false);
8679
8741
  const endTime = Date.now();
@@ -8684,8 +8746,50 @@ const StreamedContent = ({ botData }) => {
8684
8746
  thinkingStartTimeRef.current = finalThinkingTime;
8685
8747
  messageToStoreRef.current.chatData.thinkingResponse.thinkingTime = finalThinkingTime;
8686
8748
  }
8749
+ // Agent unavailable (502/404) — show specific message, no retry
8750
+ if (isAgentUnavailable) {
8751
+ setWasStreamingAborted(true);
8752
+ wasStreamingAbortedRef.current = true;
8753
+ const currentSteps = stepRef.current;
8754
+ if (currentSteps.length > 0) {
8755
+ const lastStep = currentSteps[currentSteps.length - 1];
8756
+ if (lastStep.step_status === "not-completed") {
8757
+ lastStep.step_status = "completed";
8758
+ }
8759
+ stepRef.current = [...currentSteps];
8760
+ setSteps([...currentSteps]);
8761
+ }
8762
+ const agentUnavailableMessage = "Agent isn't available right now. Please contact your administrator or try again later.";
8763
+ const hasExistingWidgetsOnUnavail = messageToStoreRef.current.appendedData &&
8764
+ (isArray(messageToStoreRef.current.appendedData)
8765
+ ? messageToStoreRef.current.appendedData.length > 0
8766
+ : Object.keys(messageToStoreRef.current.appendedData).length > 0);
8767
+ if (hasExistingWidgetsOnUnavail) {
8768
+ const errorWidget = { type: "text", response: agentUnavailableMessage };
8769
+ if (isArray(messageToStoreRef.current.appendedData)) {
8770
+ messageToStoreRef.current.appendedData.push(errorWidget);
8771
+ }
8772
+ else {
8773
+ messageToStoreRef.current.appendedData = [messageToStoreRef.current.appendedData, errorWidget];
8774
+ }
8775
+ }
8776
+ else {
8777
+ messageToStoreRef.current.chatData.response = agentUnavailableMessage;
8778
+ }
8779
+ setContent(agentUnavailableMessage);
8780
+ dispatch(smartBotActions.setMinimizedStreamData({
8781
+ isStreaming: false,
8782
+ stepHeader: questionsRef.current[questionsRef.current.length - 1] || "Agent unavailable",
8783
+ stepSubHeader: "Connection closed",
8784
+ stepStatus: "completed",
8785
+ streamStartTime: streamStartTimeRef.current,
8786
+ actionCount: questionsRef.current.length || 1,
8787
+ }));
8788
+ setStepsDone(true);
8789
+ setIsStreamingDone(true);
8790
+ }
8687
8791
  // Check if we can auto-retry (abrupt close or 503, but not user abort)
8688
- if (!isUserAbort && retryCountRef.current < MAX_RETRY_COUNT) {
8792
+ else if (!isUserAbort && retryCountRef.current < MAX_RETRY_COUNT) {
8689
8793
  // Still have retries left — start countdown instead of showing final error
8690
8794
  setStepsDone(true); // Switch to agent_response tab to show countdown
8691
8795
  const retryMessage = "The service is temporarily unavailable because of an unusual load. Please wait a moment and try again.";
@@ -8705,8 +8809,26 @@ const StreamedContent = ({ botData }) => {
8705
8809
  stepRef.current = [...currentSteps];
8706
8810
  setSteps([...currentSteps]);
8707
8811
  }
8708
- const finalMessage = "Please reach out to IA for this, as this didn't work even after retry";
8709
- messageToStoreRef.current.chatData.response = finalMessage;
8812
+ // Append the error message at the bottom of any existing content.
8813
+ // If widgets already exist in appendedData, append as the last widget
8814
+ // so it renders AFTER the already-received content (not at the top).
8815
+ const finalMessage = "The service is temporarily unavailable because of an unusual load. Please wait a moment and try again.";
8816
+ const hasExistingWidgetsOnErr = messageToStoreRef.current.appendedData &&
8817
+ (isArray(messageToStoreRef.current.appendedData)
8818
+ ? messageToStoreRef.current.appendedData.length > 0
8819
+ : Object.keys(messageToStoreRef.current.appendedData).length > 0);
8820
+ if (hasExistingWidgetsOnErr) {
8821
+ const errorWidget = { type: "text", response: finalMessage };
8822
+ if (isArray(messageToStoreRef.current.appendedData)) {
8823
+ messageToStoreRef.current.appendedData.push(errorWidget);
8824
+ }
8825
+ else {
8826
+ messageToStoreRef.current.appendedData = [messageToStoreRef.current.appendedData, errorWidget];
8827
+ }
8828
+ }
8829
+ else {
8830
+ messageToStoreRef.current.chatData.response = finalMessage;
8831
+ }
8710
8832
  setContent(finalMessage);
8711
8833
  dispatch(smartBotActions.setMinimizedStreamData({
8712
8834
  isStreaming: false,
@@ -8748,9 +8870,10 @@ const StreamedContent = ({ botData }) => {
8748
8870
  startRetryCountdown();
8749
8871
  }
8750
8872
  else {
8751
- // Retries exhausted — show final elegant message
8873
+ // Retries exhausted — show final message
8752
8874
  setWasStreamingAborted(true);
8753
8875
  wasStreamingAbortedRef.current = true;
8876
+ // Mark the last in-progress step as completed
8754
8877
  const currentSteps = stepRef.current;
8755
8878
  if (currentSteps.length > 0) {
8756
8879
  const lastStep = currentSteps[currentSteps.length - 1];
@@ -8760,8 +8883,26 @@ const StreamedContent = ({ botData }) => {
8760
8883
  stepRef.current = [...currentSteps];
8761
8884
  setSteps([...currentSteps]);
8762
8885
  }
8763
- const finalMessage = "Please reach out to IA for this, as this didn't work even after retry";
8764
- messageToStoreRef.current.chatData.response = finalMessage;
8886
+ // Append the error message at the bottom of any existing content.
8887
+ // If widgets already exist in appendedData, append as the last widget
8888
+ // so it renders AFTER the already-received content (not at the top).
8889
+ const finalMessage = "The service is temporarily unavailable because of an unusual load. Please wait a moment and try again.";
8890
+ const hasExistingWidgets = messageToStoreRef.current.appendedData &&
8891
+ (isArray(messageToStoreRef.current.appendedData)
8892
+ ? messageToStoreRef.current.appendedData.length > 0
8893
+ : Object.keys(messageToStoreRef.current.appendedData).length > 0);
8894
+ if (hasExistingWidgets) {
8895
+ const errorWidget = { type: "text", response: finalMessage };
8896
+ if (isArray(messageToStoreRef.current.appendedData)) {
8897
+ messageToStoreRef.current.appendedData.push(errorWidget);
8898
+ }
8899
+ else {
8900
+ messageToStoreRef.current.appendedData = [messageToStoreRef.current.appendedData, errorWidget];
8901
+ }
8902
+ }
8903
+ else {
8904
+ messageToStoreRef.current.chatData.response = finalMessage;
8905
+ }
8765
8906
  setContent(finalMessage);
8766
8907
  dispatch(smartBotActions.setMinimizedStreamData({
8767
8908
  isStreaming: false,
@@ -8966,19 +9107,19 @@ const StreamedContent = ({ botData }) => {
8966
9107
  // [
8967
9108
  // {
8968
9109
  // header: "Finding relevant information",
8969
- // sub_header: "Alan is working to identify relevant information to user answer user query",
9110
+ // sub_header: "Iris is working to identify relevant information to user answer user query",
8970
9111
  // step_status: "not-completed",
8971
9112
  // },
8972
9113
  // ];
8973
9114
  // [
8974
9115
  // {
8975
9116
  // header: "Finding relevant information",
8976
- // sub_header: "Alan is working to identify relevant information to user answer user query",
9117
+ // sub_header: "Iris is working to identify relevant information to user answer user query",
8977
9118
  // step_status: "completed",
8978
9119
  // },
8979
9120
  // {
8980
9121
  // header: "Output Generation",
8981
- // sub_header: "Alan is finalizing response to user query",
9122
+ // sub_header: "Iris is finalizing response to user query",
8982
9123
  // step_status: "not-completed",
8983
9124
  // },
8984
9125
  // ];
@@ -9218,7 +9359,7 @@ const StreamedContent = ({ botData }) => {
9218
9359
  * @returns {JSX.Element} Rendered content with optional blinking cursor
9219
9360
  */
9220
9361
  const renderContent = () => {
9221
- return (jsxRuntime.jsxs("div", { className: classes.streamContainer, children: [jsxRuntime.jsx(StepsResponseTab, { steps: steps, stepChange: stepChange, setSteps: setSteps, stepsDone: stepsDone, setStepsDone: setStepsDone, finalStepDone: finalStepDone, setFinalStepDone: setFinalStepDone, content: content, isStreaming: isStreaming, currentMode: currentMode, questions: questions, questionsStepsMap: questionsStepsMap, stepFormDataMap: stepFormDataMap, isFormDisabled: botData?.isFormDisabled || false, streamingWidgetData: streamingWidgetData, isRetrying: isRetrying }), isRetrying && (jsxRuntime.jsx("div", { className: classes.retryContainer, children: jsxRuntime.jsxs("span", { className: classes.retryMessage, children: ["Auto re-trying in ", retryCountdown, "s"] }) }))] }));
9362
+ return (jsxRuntime.jsxs("div", { className: classes.streamContainer, children: [jsxRuntime.jsx(StepsResponseTab, { steps: steps, stepChange: stepChange, setSteps: setSteps, stepsDone: stepsDone, setStepsDone: setStepsDone, finalStepDone: finalStepDone, setFinalStepDone: setFinalStepDone, content: content, isStreaming: isStreaming, currentMode: currentMode, questions: questions, questionsStepsMap: questionsStepsMap, stepFormDataMap: stepFormDataMap, isFormDisabled: botData?.isFormDisabled || false, streamingWidgetData: streamingWidgetData, isRetrying: isRetrying }), isRetrying && (jsxRuntime.jsx("div", { className: classes.retryContainer, children: jsxRuntime.jsx(TextRenderer, { text: `Auto re-trying in ${retryCountdown}s`, thinking: "" }) }))] }));
9222
9363
  };
9223
9364
  if (currentMode === "agent") {
9224
9365
  return renderContent();
@@ -9489,6 +9630,12 @@ let activeTabularInstanceId = null;
9489
9630
  const TabularContent = ({ steps: initialSteps, currentTabValue, children, questions: initialQuestions = [], questionsStepsMap: initialQuestionsStepsMap = {}, stepFormDataMap: initialStepFormDataMap = {}, isFormDisabled = false, sessionId: propSessionId = "" }) => {
9490
9631
  const dispatch = reactRedux.useDispatch();
9491
9632
  const stepFormStreamData = reactRedux.useSelector((state) => state.smartBotReducer.stepFormStreamData);
9633
+ const thinkingContext = reactRedux.useSelector((state) => state.smartBotReducer.thinkingContext);
9634
+ const streamStartTimeRef = React.useRef(thinkingContext?.streamStartTime);
9635
+ // Keep streamStartTime ref in sync with Redux for use in event handler closures
9636
+ React.useEffect(() => {
9637
+ streamStartTimeRef.current = thinkingContext?.streamStartTime;
9638
+ }, [thinkingContext?.streamStartTime]);
9492
9639
  const [tabValue, setTabValue] = React.useState(currentTabValue);
9493
9640
  // Local state — initialized from props, updated by SSE chunks
9494
9641
  const [stepsState, setStepsState] = React.useState(() => {
@@ -9511,6 +9658,7 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
9511
9658
  const [hasNewStepFormFromRestream, setHasNewStepFormFromRestream] = React.useState(false);
9512
9659
  const [activeFormIntent, setActiveFormIntent] = React.useState(null);
9513
9660
  const [retryCountdown, setRetryCountdown] = React.useState(0);
9661
+ const [timeoutMessage, setTimeoutMessage] = React.useState("");
9514
9662
  // Stable unique instance ID for this TabularContent mount
9515
9663
  const instanceIdRef = React.useRef(null);
9516
9664
  if (instanceIdRef.current === null) {
@@ -9535,6 +9683,32 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
9535
9683
  window.removeEventListener("stepFormStreamCompleted", handleStepFormCompleted);
9536
9684
  };
9537
9685
  }, []);
9686
+ // Switch to agent_response tab on form inactivity timeout (30 min)
9687
+ React.useEffect(() => {
9688
+ const handleStepFormTimeout = () => {
9689
+ setTimeoutMessage("This session timed out due to inactivity. Please start a new message to continue.");
9690
+ setStepFormSubmitted(true);
9691
+ setTabValue("agent_response");
9692
+ dispatch(smartBotActions.setMinimizedStreamData(null));
9693
+ const elapsed = streamStartTimeRef.current
9694
+ ? Math.floor((Date.now() - streamStartTimeRef.current) / 1000)
9695
+ : null;
9696
+ const mins = elapsed != null ? Math.floor(elapsed / 60) : 0;
9697
+ const secs = elapsed != null ? elapsed % 60 : 0;
9698
+ const timedOutLabel = `Worked for ${mins}m:${String(secs).padStart(2, '0')}s`;
9699
+ dispatch(smartBotActions.setThinkingContext({
9700
+ streamStartTime: null,
9701
+ isStreamCompleted: true,
9702
+ finalElapsedSeconds: elapsed,
9703
+ thinkingHeaderMessage: timedOutLabel,
9704
+ thinkingContent: "",
9705
+ }));
9706
+ };
9707
+ window.addEventListener("stepFormTimeout", handleStepFormTimeout);
9708
+ return () => {
9709
+ window.removeEventListener("stepFormTimeout", handleStepFormTimeout);
9710
+ };
9711
+ }, []);
9538
9712
  // Render a widget item from SSE data
9539
9713
  const renderWidget = (item, index) => {
9540
9714
  try {
@@ -9874,7 +10048,7 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
9874
10048
  },
9875
10049
  ], tabPanels: [
9876
10050
  jsxRuntime.jsx(Steps, { steps: stepsState, questions: questionsState, questionsStepsMap: questionsStepsMapState, stepFormDataMap: stepFormDataMapState, isFormDisabled: (isFormDisabled && !isRestreaming) || stepFormSubmitted, activeFormIntent: hasNewStepFormFromRestream ? activeFormIntent : null, isRestreaming: isRestreaming }),
9877
- jsxRuntime.jsxs(AgentResponse, { children: [children, renderedWidgets.length > 0 && (jsxRuntime.jsx("div", { className: "restream-widget-content", children: renderedWidgets })), retryCountdown > 0 && (jsxRuntime.jsx("div", { style: { marginTop: "8px" }, children: jsxRuntime.jsxs("span", { style: { fontFamily: "Manrope", fontSize: "13px", fontWeight: 500, color: "#374151" }, children: ["Auto re-trying in ", retryCountdown, "s"] }) }))] }),
10051
+ jsxRuntime.jsxs(AgentResponse, { children: [children, renderedWidgets.length > 0 && (jsxRuntime.jsx("div", { className: "restream-widget-content", children: renderedWidgets })), retryCountdown > 0 && (jsxRuntime.jsx("div", { style: { marginTop: "8px" }, children: jsxRuntime.jsx(TextRenderer, { text: `Auto re-trying in ${retryCountdown}s`, thinking: "" }) })), timeoutMessage && (jsxRuntime.jsx("div", { style: { marginTop: "8px" }, children: jsxRuntime.jsx(TextRenderer, { text: timeoutMessage, thinking: "" }) }))] }),
9878
10052
  ], value: tabValue }) }));
9879
10053
  };
9880
10054
  /** Reset the active instance tracker (call when a new conversation starts from the input field) */
@@ -12924,7 +13098,7 @@ let singleConversationNewData = [
12924
13098
  {
12925
13099
  header: "Creating Plan of Action",
12926
13100
  step_status: "completed",
12927
- sub_header: "Alan is working to determine the best approach to answer user query",
13101
+ sub_header: "Iris is working to determine the best approach to answer user query",
12928
13102
  current_intent: "List the products which are about to change status in next 10 days"
12929
13103
  },
12930
13104
  {
@@ -14848,7 +15022,7 @@ const SmartBot = (props) => {
14848
15022
  try {
14849
15023
  // if (localStorage.getItem("isStreaming") === "true") {
14850
15024
  // displaySnackMessages(
14851
- // "Alan is processing request in another tab, This request can be processed once Alan is available",
15025
+ // "Iris is processing request in another tab, This request can be processed once Iris is available",
14852
15026
  // "warning"
14853
15027
  // );
14854
15028
  // return;
@@ -15190,7 +15364,7 @@ const SmartBot = (props) => {
15190
15364
  :
15191
15365
  jsxRuntime.jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose, chatBotWidth: chatBotWidth }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
15192
15366
  freeTextHeading: "Try adding more details :",
15193
- freeTextContent: "Alan works better when you provide more context and pointed questions",
15367
+ freeTextContent: "Iris works better when you provide more context and pointed questions",
15194
15368
  }, isStopIcon: isStop, onStopIconClick: onStopIconClick, footerText: "AI-generated responses may contain errors\u2014please verify important information", showSuggestionBanner: showSavedFilters ? false : showSuggestionBanner, onCloseSuggestionBanner: () => {
15195
15369
  setShowSuggestionBanner(false);
15196
15370
  }, landingScreen: isLandingScreen, onLikeClick: (params, params2) => {