impact-chatbot 2.3.66 → 2.3.68

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
@@ -471,7 +471,8 @@ const parseResponse = (data, type, agentId = "", currentMode = "", disableTimeAn
471
471
  minDate: data?.data?.minDate,
472
472
  maxDate: data?.data?.maxDate,
473
473
  isDisabled: data?.data?.isDisabled,
474
- paramName: data?.data?.param_name
474
+ paramName: data?.data?.param_name,
475
+ minStartDate: data?.data?.minStartDate
475
476
  }
476
477
  };
477
478
  case "dateRangePicker":
@@ -491,7 +492,8 @@ const parseResponse = (data, type, agentId = "", currentMode = "", disableTimeAn
491
492
  maxDate: data?.data?.maxDate,
492
493
  isDisabled: data?.data?.isDisabled,
493
494
  showMonthYearSelect: data?.data?.showMonthYearSelect,
494
- paramName: data?.data?.param_name
495
+ paramName: data?.data?.param_name,
496
+ minStartDate: data?.data?.minStartDate
495
497
  }
496
498
  };
497
499
  case "checkbox":
@@ -5865,8 +5867,10 @@ const TableContent = ({ bodyText }) => {
5865
5867
  const onSelectionChanged = (event) => {
5866
5868
  try {
5867
5869
  const selectedList = event.api.getSelectedRows();
5868
- chatbotContext.tables = { ...chatbotContext?.tables, [table_name]: selectedList };
5869
- dispatch(setChatbotContext(chatbotContext));
5870
+ dispatch(setChatbotContext({
5871
+ ...chatbotContext,
5872
+ tables: { ...chatbotContext?.tables, [table_name]: selectedList },
5873
+ }));
5870
5874
  }
5871
5875
  catch (error) {
5872
5876
  console.error("Error in onSelectionChanged", error);
@@ -6709,12 +6713,14 @@ const SliderContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
6709
6713
  const handleChange = (value) => {
6710
6714
  try {
6711
6715
  setSliderValue(value?.target?.value);
6712
- chatbotContext[bodyText?.paramName] = {
6713
- ...chatbotContext?.[bodyText?.paramName],
6714
- [bodyText?.paramName]: value?.target?.value,
6715
- updated: true
6716
- };
6717
- dispatch(setChatbotContext(chatbotContext));
6716
+ dispatch(setChatbotContext({
6717
+ ...chatbotContext,
6718
+ [bodyText?.paramName]: {
6719
+ ...chatbotContext?.[bodyText?.paramName],
6720
+ [bodyText?.paramName]: value?.target?.value,
6721
+ updated: true,
6722
+ },
6723
+ }));
6718
6724
  dispatch(setPersistedFormValues({ [formKey]: value?.target?.value }));
6719
6725
  }
6720
6726
  catch (error) {
@@ -6761,17 +6767,20 @@ const SelectContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
6761
6767
  else {
6762
6768
  value = selectedOptions.value;
6763
6769
  }
6764
- chatbotContext[bodyText?.paramName] = {
6765
- ...chatbotContext?.[bodyText?.paramName],
6766
- [bodyText?.paramName]: value,
6767
- updated: true,
6770
+ const updatedContext = {
6771
+ ...chatbotContext,
6772
+ [bodyText?.paramName]: {
6773
+ ...chatbotContext?.[bodyText?.paramName],
6774
+ [bodyText?.paramName]: value,
6775
+ updated: true,
6776
+ },
6768
6777
  };
6769
6778
  // chatbotContext.select = {
6770
6779
  // ...chatbotContext?.select,
6771
6780
  // [bodyText?.paramName]: selectedOptions,
6772
6781
  // updated: true
6773
6782
  // };
6774
- dispatch(setChatbotContext(chatbotContext));
6783
+ dispatch(setChatbotContext(updatedContext));
6775
6784
  dispatch(setPersistedFormValues({ [formKey]: Array.isArray(selectedOptions) ? selectedOptions : [selectedOptions] }));
6776
6785
  // Notify cross-filter context if cascading is active
6777
6786
  if (isCascading) {
@@ -6811,12 +6820,14 @@ const SelectContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
6811
6820
  setCurrentSelectedOptions([]);
6812
6821
  setIsAllSelected(false);
6813
6822
  // Also clear from chatbotContext and persistedFormValues
6814
- chatbotContext[bodyText?.paramName] = {
6815
- ...chatbotContext?.[bodyText?.paramName],
6816
- [bodyText?.paramName]: [],
6817
- updated: true,
6818
- };
6819
- dispatch(setChatbotContext(chatbotContext));
6823
+ dispatch(setChatbotContext({
6824
+ ...chatbotContext,
6825
+ [bodyText?.paramName]: {
6826
+ ...chatbotContext?.[bodyText?.paramName],
6827
+ [bodyText?.paramName]: [],
6828
+ updated: true,
6829
+ },
6830
+ }));
6820
6831
  dispatch(setPersistedFormValues({ [formKey]: [] }));
6821
6832
  }
6822
6833
  }
@@ -6836,12 +6847,14 @@ const SelectContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
6836
6847
  isRequired: isRequired, isDisabled: isDisabled || isFormDisabled, isClearable: !(isDisabled || isFormDisabled), onClearAll: () => {
6837
6848
  setCurrentSelectedOptions([]);
6838
6849
  setIsAllSelected(false);
6839
- chatbotContext[bodyText?.paramName] = {
6840
- ...chatbotContext?.[bodyText?.paramName],
6841
- [bodyText?.paramName]: [],
6842
- updated: true,
6843
- };
6844
- dispatch(setChatbotContext(chatbotContext));
6850
+ dispatch(setChatbotContext({
6851
+ ...chatbotContext,
6852
+ [bodyText?.paramName]: {
6853
+ ...chatbotContext?.[bodyText?.paramName],
6854
+ [bodyText?.paramName]: [],
6855
+ updated: true,
6856
+ },
6857
+ }));
6845
6858
  dispatch(setPersistedFormValues({ [formKey]: [] }));
6846
6859
  // Notify cross-filter context to clear downstream filters
6847
6860
  if (isCascading) {
@@ -6892,12 +6905,14 @@ const SelectContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
6892
6905
  setCurrentSelectedOptions([...currentOptions]);
6893
6906
  setIsAllSelected(true);
6894
6907
  const allValues = allOptionsRef.current.map((opt) => opt.value);
6895
- chatbotContext[bodyText?.paramName] = {
6896
- ...chatbotContext?.[bodyText?.paramName],
6897
- [bodyText?.paramName]: allValues,
6898
- updated: true,
6899
- };
6900
- dispatch(setChatbotContext(chatbotContext));
6908
+ dispatch(setChatbotContext({
6909
+ ...chatbotContext,
6910
+ [bodyText?.paramName]: {
6911
+ ...chatbotContext?.[bodyText?.paramName],
6912
+ [bodyText?.paramName]: allValues,
6913
+ updated: true,
6914
+ },
6915
+ }));
6901
6916
  dispatch(setPersistedFormValues({ [formKey]: currentOptions }));
6902
6917
  // Notify cross-filter context if cascading is active
6903
6918
  if (isCascading) {
@@ -6929,12 +6944,14 @@ const DatePickerContent = ({ bodyText, isFormDisabled = false, messageIndex }) =
6929
6944
  const handleDateChange = (date) => {
6930
6945
  try {
6931
6946
  setSelectedDate(date);
6932
- chatbotContext[bodyText?.paramName] = {
6933
- ...chatbotContext?.[bodyText?.paramName],
6934
- [bodyText?.paramName]: moment(date).format(displayFormat),
6935
- updated: true
6936
- };
6937
- dispatch(setChatbotContext(chatbotContext));
6947
+ dispatch(setChatbotContext({
6948
+ ...chatbotContext,
6949
+ [bodyText?.paramName]: {
6950
+ ...chatbotContext?.[bodyText?.paramName],
6951
+ [bodyText?.paramName]: moment(date).format(displayFormat),
6952
+ updated: true,
6953
+ },
6954
+ }));
6938
6955
  dispatch(setPersistedFormValues({ [formKey]: date }));
6939
6956
  }
6940
6957
  catch (error) {
@@ -6968,15 +6985,17 @@ const DateRangePickerContent = ({ bodyText, isFormDisabled = false, messageIndex
6968
6985
  try {
6969
6986
  setStartDate(start);
6970
6987
  setEndDate(end);
6971
- chatbotContext[bodyText?.paramName] = {
6972
- ...chatbotContext?.[bodyText?.paramName],
6988
+ dispatch(setChatbotContext({
6989
+ ...chatbotContext,
6973
6990
  [bodyText?.paramName]: {
6974
- startDate: start ? moment(start).format(displayFormat) : null,
6975
- endDate: end ? moment(end).format(displayFormat) : null,
6991
+ ...chatbotContext?.[bodyText?.paramName],
6992
+ [bodyText?.paramName]: {
6993
+ startDate: start ? moment(start).format(displayFormat) : null,
6994
+ endDate: end ? moment(end).format(displayFormat) : null,
6995
+ },
6996
+ updated: true,
6976
6997
  },
6977
- updated: true,
6978
- };
6979
- dispatch(setChatbotContext(chatbotContext));
6998
+ }));
6980
6999
  dispatch(setPersistedFormValues({ [formKey]: { startDate: start, endDate: end } }));
6981
7000
  }
6982
7001
  catch (error) {
@@ -7017,12 +7036,14 @@ const CheckboxContent = ({ bodyText, isFormDisabled = false, messageIndex }) =>
7017
7036
  // [bodyText?.paramName]: isChecked?.currentTarget?.checked,
7018
7037
  // updated: true
7019
7038
  // };
7020
- chatbotContext[bodyText?.paramName] = {
7021
- ...chatbotContext?.[bodyText?.paramName],
7022
- [bodyText?.paramName]: isChecked?.currentTarget?.checked,
7023
- updated: true
7024
- };
7025
- dispatch(setChatbotContext(chatbotContext));
7039
+ dispatch(setChatbotContext({
7040
+ ...chatbotContext,
7041
+ [bodyText?.paramName]: {
7042
+ ...chatbotContext?.[bodyText?.paramName],
7043
+ [bodyText?.paramName]: isChecked?.currentTarget?.checked,
7044
+ updated: true,
7045
+ },
7046
+ }));
7026
7047
  dispatch(setPersistedFormValues({ [formKey]: isChecked?.currentTarget?.checked }));
7027
7048
  }
7028
7049
  catch (error) {
@@ -7051,12 +7072,14 @@ const RadioContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
7051
7072
  // [bodyText?.paramName]: value,
7052
7073
  // updated: true,
7053
7074
  // };
7054
- chatbotContext[bodyText?.paramName] = {
7055
- ...chatbotContext?.[bodyText?.paramName],
7056
- [bodyText?.paramName]: value,
7057
- updated: true
7058
- };
7059
- dispatch(setChatbotContext(chatbotContext));
7075
+ dispatch(setChatbotContext({
7076
+ ...chatbotContext,
7077
+ [bodyText?.paramName]: {
7078
+ ...chatbotContext?.[bodyText?.paramName],
7079
+ [bodyText?.paramName]: value,
7080
+ updated: true,
7081
+ },
7082
+ }));
7060
7083
  dispatch(setPersistedFormValues({ [formKey]: value }));
7061
7084
  }
7062
7085
  catch (error) {
@@ -7079,13 +7102,15 @@ const InputContent = ({ bodyText, isFormDisabled = false, messageIndex }) => {
7079
7102
  try {
7080
7103
  const newValue = event?.target?.value || event?.currentTarget?.value || "";
7081
7104
  setValue(newValue);
7082
- chatbotContext[bodyText?.paramName] = {
7083
- ...chatbotContext?.[bodyText?.paramName],
7084
- [bodyText?.paramName]: replaceSpecialCharToCharCode(newValue),
7085
- updated: true,
7086
- type: inputType,
7087
- };
7088
- dispatch(setChatbotContext(chatbotContext));
7105
+ dispatch(setChatbotContext({
7106
+ ...chatbotContext,
7107
+ [bodyText?.paramName]: {
7108
+ ...chatbotContext?.[bodyText?.paramName],
7109
+ [bodyText?.paramName]: replaceSpecialCharToCharCode(newValue),
7110
+ updated: true,
7111
+ type: inputType,
7112
+ },
7113
+ }));
7089
7114
  dispatch(setPersistedFormValues({ [formKey]: newValue }));
7090
7115
  }
7091
7116
  catch (error) {
@@ -7109,6 +7134,8 @@ const ImageContent = ({ bodyText }) => {
7109
7134
  } })), caption && (jsx("div", { children: jsx(TextRenderer, { text: caption }) }))] }));
7110
7135
  };
7111
7136
 
7137
+ // Key used to persist timeout state in sessionStorage (survives component remounts from tab switches)
7138
+ const STEP_FORM_TIMEOUT_KEY = "__stepFormTimedOut";
7112
7139
  /**
7113
7140
  * Renders form widget data inline within a step.
7114
7141
  * Reuses the same rendering logic as CombinedContent but designed
@@ -7127,8 +7154,9 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7127
7154
  const chatbotFilterOptions = useSelector((state) => state.smartBotReducer.chatbotFilterOptions);
7128
7155
  const dimensionHierarchies = useSelector((state) => state.userRoleManagementService?.dimensionHierarchies);
7129
7156
  const [isFormSubmitted, setIsFormSubmitted] = useState(false);
7130
- const [isTimedOut, setIsTimedOut] = useState(false);
7157
+ const [isTimedOut, setIsTimedOut] = useState(() => sessionStorage.getItem(STEP_FORM_TIMEOUT_KEY) === "true");
7131
7158
  const timeoutRef = useRef(null);
7159
+ const prevIsFormDisabledRef = useRef(isFormDisabled);
7132
7160
  // 30-minute inactivity timeout: disable form and switch to agent_response tab
7133
7161
  const FORM_TIMEOUT_MS = 30 * 60 * 1000;
7134
7162
  useEffect(() => {
@@ -7137,6 +7165,7 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7137
7165
  const startTime = Date.now();
7138
7166
  timeoutRef.current = setTimeout(() => {
7139
7167
  setIsTimedOut(true);
7168
+ sessionStorage.setItem(STEP_FORM_TIMEOUT_KEY, "true");
7140
7169
  const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
7141
7170
  window.dispatchEvent(new CustomEvent("stepFormTimeout", { detail: { elapsedSeconds } }));
7142
7171
  }, FORM_TIMEOUT_MS);
@@ -7160,11 +7189,14 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7160
7189
  }
7161
7190
  }, [stepFormStreamData]);
7162
7191
  // Reset isFormSubmitted and isTimedOut when parent signals the form should be enabled (new step_form from restream)
7192
+ // Only reset on a true→false TRANSITION (not on initial mount)
7163
7193
  useEffect(() => {
7164
- if (!isFormDisabled) {
7194
+ if (prevIsFormDisabledRef.current && !isFormDisabled) {
7165
7195
  setIsFormSubmitted(false);
7166
7196
  setIsTimedOut(false);
7197
+ sessionStorage.removeItem(STEP_FORM_TIMEOUT_KEY);
7167
7198
  }
7199
+ prevIsFormDisabledRef.current = isFormDisabled;
7168
7200
  }, [isFormDisabled]);
7169
7201
  const [isFilterSetOpen, setIsFilterSetOpen] = useState(false);
7170
7202
  const [selectedFilterSet, setSelectedFilterSet] = useState(() => {
@@ -7239,11 +7271,49 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7239
7271
  const requiredFieldsFilled = useMemo(() => {
7240
7272
  if (!formData || !Array.isArray(formData))
7241
7273
  return false;
7274
+ // Only validate fields that are both isRequired AND of a type that visually
7275
+ // shows the mandatory indicator (*) to the user (currently only "select" fields).
7242
7276
  const requiredParams = formData
7243
- .filter((item) => item?.data?.isRequired)
7277
+ .filter((item) => item?.data?.isRequired && item?.data?.is_mandatory)
7244
7278
  .map((item) => item.data.param_name);
7245
- if (requiredParams.length === 0)
7246
- return true;
7279
+ if (requiredParams.length === 0) {
7280
+ // Fallback: if no field has is_mandatory, check select-type fields with isRequired
7281
+ const selectRequiredParams = formData
7282
+ .filter((item) => item?.type === "select" && item?.data?.isRequired)
7283
+ .map((item) => item.data.param_name);
7284
+ if (selectRequiredParams.length === 0) {
7285
+ // No mandatory fields at all — require at least one field to be filled
7286
+ const allParams = formData
7287
+ .filter((item) => item?.data?.param_name && item?.type !== "button")
7288
+ .map((item) => item.data.param_name);
7289
+ return allParams.some((param) => {
7290
+ const ctx = chatbotContext?.[param];
7291
+ if (ctx && ctx.updated) {
7292
+ const val = ctx[param];
7293
+ if (val && (Array.isArray(val) ? val.length > 0 : !!val))
7294
+ return true;
7295
+ }
7296
+ const persistedKey = `${messageIndex}_${param}`;
7297
+ const persistedVal = persistedFormValues?.[persistedKey];
7298
+ if (persistedVal && (Array.isArray(persistedVal) ? persistedVal.length > 0 : !!persistedVal))
7299
+ return true;
7300
+ return false;
7301
+ });
7302
+ }
7303
+ return selectRequiredParams.every((param) => {
7304
+ const ctx = chatbotContext?.[param];
7305
+ if (ctx && ctx.updated) {
7306
+ const val = ctx[param];
7307
+ if (val && (Array.isArray(val) ? val.length > 0 : !!val))
7308
+ return true;
7309
+ }
7310
+ const persistedKey = `${messageIndex}_${param}`;
7311
+ const persistedVal = persistedFormValues?.[persistedKey];
7312
+ if (persistedVal && (Array.isArray(persistedVal) ? persistedVal.length > 0 : !!persistedVal))
7313
+ return true;
7314
+ return false;
7315
+ });
7316
+ }
7247
7317
  return requiredParams.every((param) => {
7248
7318
  // Check chatbotContext (populated by saved filters)
7249
7319
  const ctx = chatbotContext?.[param];
@@ -7358,7 +7428,7 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7358
7428
  case "radio":
7359
7429
  return jsx(RadioContent, { bodyText: parsedData.bodyText, isFormDisabled: formFieldsDisabled, messageIndex: messageIndex }, key);
7360
7430
  case "button":
7361
- return jsx(ButtonContent, { bodyText: parsedData.bodyText, isFormDisabled: isFormDisabled || isFormSubmitted, isStepFormSubmit: true, isFormValid: requiredFieldsFilled }, key);
7431
+ return jsx(ButtonContent, { bodyText: parsedData.bodyText, isFormDisabled: isFormDisabled || isFormSubmitted || isTimedOut, isStepFormSubmit: true, isFormValid: requiredFieldsFilled }, key);
7362
7432
  case "input":
7363
7433
  return jsx(InputContent, { bodyText: parsedData.bodyText, isFormDisabled: formFieldsDisabled, messageIndex: messageIndex }, key);
7364
7434
  case "image":
@@ -7394,6 +7464,10 @@ const StepFormContent = ({ formData, messageIndex = 0, isFormDisabled = false, s
7394
7464
  ...(isFilterSelected && !isFormDisabled ? { pointerEvents: "none", opacity: 0.5 } : {}),
7395
7465
  }, children: crossFilterConfigs.length > 1 ? (jsx(CrossFilterProvider, { filters: crossFilterConfigs, fetchOptionsFn: fetchCrossFilterOptions, initialSelections: crossFilterInitialSelections, fetchOnMount: false, children: formFields })) : (formFields) }), buttonItems] }));
7396
7466
  };
7467
+ /** Reset the timeout flag (call when a new conversation/message starts) */
7468
+ const resetStepFormTimeoutFlag = () => {
7469
+ sessionStorage.removeItem(STEP_FORM_TIMEOUT_KEY);
7470
+ };
7397
7471
 
7398
7472
  const useStyles$4 = makeStyles$1((theme) => ({
7399
7473
  "@global": {
@@ -7832,10 +7906,12 @@ const StepsResponseTab = (props) => {
7832
7906
  }, [thinkingContext?.streamStartTime]);
7833
7907
  const [tabValue, setTabValue] = useState("steps");
7834
7908
  const [timeoutMessage, setTimeoutMessage] = useState("");
7909
+ const [isTimedOut, setIsTimedOut] = useState(false);
7835
7910
  // Switch to agent_response tab on form inactivity timeout (30 min)
7836
7911
  useEffect(() => {
7837
7912
  const handleStepFormTimeout = () => {
7838
7913
  setTimeoutMessage("This session timed out due to inactivity. Please start a new message to continue.");
7914
+ setIsTimedOut(true);
7839
7915
  setTabValue("agent_response");
7840
7916
  dispatch(setMinimizedStreamData(null));
7841
7917
  const elapsed = streamStartTimeRef.current
@@ -7884,7 +7960,7 @@ const StepsResponseTab = (props) => {
7884
7960
  icon: jsx(PsychologyOutlinedIcon, { fontSize: "large" }),
7885
7961
  },
7886
7962
  ], tabPanels: [
7887
- 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 }),
7963
+ 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 || isTimedOut }),
7888
7964
  jsxs(Fragment, { children: [jsx(AgentResponse$1, { content: content, isStreaming: isStreaming, streamingWidgetData: streamingWidgetData }), timeoutMessage && (jsx("div", { style: { marginTop: "8px", padding: "0 8px" }, children: jsx(TextRenderer, { text: timeoutMessage, thinking: "" }) }))] }),
7889
7965
  ], value: tabValue }) }));
7890
7966
  };
@@ -8329,6 +8405,8 @@ const StreamedContent = ({ botData }) => {
8329
8405
  ? botData?.utilityObject?.method
8330
8406
  : "PUT";
8331
8407
  delete botData.inputBody.chat_input;
8408
+ // Clear any stale timeout flag from a previous session
8409
+ resetStepFormTimeoutFlag();
8332
8410
  // Start the timer immediately when the API is called
8333
8411
  if (!streamStartTimeRef.current) {
8334
8412
  streamStartTimeRef.current = Date.now();
@@ -8790,7 +8868,7 @@ const StreamedContent = ({ botData }) => {
8790
8868
  // Append the error message at the bottom of any existing content.
8791
8869
  // If widgets already exist in appendedData, append as the last widget
8792
8870
  // so it renders AFTER the already-received content (not at the top).
8793
- const finalMessage = "The service is temporarily unavailable because of an unusual load. Please wait a moment and try again.";
8871
+ const finalMessage = "Please reach out to IA for this, as this didn't work even after retry";
8794
8872
  const hasExistingWidgetsOnErr = messageToStoreRef.current.appendedData &&
8795
8873
  (isArray(messageToStoreRef.current.appendedData)
8796
8874
  ? messageToStoreRef.current.appendedData.length > 0
@@ -9637,6 +9715,7 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
9637
9715
  const [activeFormIntent, setActiveFormIntent] = useState(null);
9638
9716
  const [retryCountdown, setRetryCountdown] = useState(0);
9639
9717
  const [timeoutMessage, setTimeoutMessage] = useState("");
9718
+ const [isTimedOut, setIsTimedOut] = useState(false);
9640
9719
  // Stable unique instance ID for this TabularContent mount
9641
9720
  const instanceIdRef = useRef(null);
9642
9721
  if (instanceIdRef.current === null) {
@@ -9666,6 +9745,7 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
9666
9745
  const handleStepFormTimeout = () => {
9667
9746
  setTimeoutMessage("This session timed out due to inactivity. Please start a new message to continue.");
9668
9747
  setStepFormSubmitted(true);
9748
+ setIsTimedOut(true);
9669
9749
  setTabValue("agent_response");
9670
9750
  dispatch(setMinimizedStreamData(null));
9671
9751
  const elapsed = streamStartTimeRef.current
@@ -10025,7 +10105,7 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
10025
10105
  icon: jsx(PsychologyOutlinedIcon, { fontSize: "large" }),
10026
10106
  },
10027
10107
  ], tabPanels: [
10028
- jsx(Steps, { steps: stepsState, questions: questionsState, questionsStepsMap: questionsStepsMapState, stepFormDataMap: stepFormDataMapState, isFormDisabled: (isFormDisabled && !isRestreaming) || stepFormSubmitted, activeFormIntent: hasNewStepFormFromRestream ? activeFormIntent : null, isRestreaming: isRestreaming }),
10108
+ jsx(Steps, { steps: stepsState, questions: questionsState, questionsStepsMap: questionsStepsMapState, stepFormDataMap: stepFormDataMapState, isFormDisabled: (isFormDisabled && !isRestreaming) || stepFormSubmitted || isTimedOut, activeFormIntent: hasNewStepFormFromRestream ? activeFormIntent : null, isRestreaming: isRestreaming }),
10029
10109
  jsxs(AgentResponse, { children: [children, renderedWidgets.length > 0 && (jsx("div", { className: "restream-widget-content", children: renderedWidgets })), retryCountdown > 0 && (jsx("div", { style: { marginTop: "8px" }, children: jsx(TextRenderer, { text: `Auto re-trying in ${retryCountdown}s`, thinking: "" }) })), timeoutMessage && (jsx("div", { style: { marginTop: "8px" }, children: jsx(TextRenderer, { text: timeoutMessage, thinking: "" }) }))] }),
10030
10110
  ], value: tabValue }) }));
10031
10111
  };