impact-chatbot 2.3.48 → 2.3.50

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.
@@ -506,6 +506,122 @@
506
506
  opacity: 0.7;
507
507
  }
508
508
 
509
+ .answer-mode-wrapper {
510
+ position: relative;
511
+ display: flex;
512
+ align-items: center;
513
+ flex-shrink: 0;
514
+ }
515
+
516
+ .answer-mode-trigger {
517
+ display: inline-flex;
518
+ align-items: center;
519
+ gap: 4px;
520
+ padding: 4px 10px;
521
+ border: 1px solid #d9dde7;
522
+ border-radius: 8px;
523
+ background: #f7f8fa;
524
+ cursor: pointer;
525
+ font-family: "Manrope", sans-serif;
526
+ font-size: 13px;
527
+ font-weight: 600;
528
+ color: #1f2b4d;
529
+ transition: all 0.15s ease;
530
+ line-height: 20px;
531
+ }
532
+ .answer-mode-trigger:hover {
533
+ background: #eef0f4;
534
+ border-color: #b3bdf8;
535
+ }
536
+
537
+ .answer-mode-trigger-label {
538
+ white-space: nowrap;
539
+ }
540
+
541
+ .answer-mode-trigger-chevron {
542
+ transition: transform 0.2s ease;
543
+ color: #6b7280;
544
+ }
545
+ .answer-mode-trigger-chevron.open {
546
+ transform: rotate(180deg);
547
+ }
548
+
549
+ .answer-mode-dropdown {
550
+ position: absolute;
551
+ bottom: calc(100% + 6px);
552
+ right: 0;
553
+ min-width: 220px;
554
+ background: #ffffff;
555
+ border: 1px solid #e5e7eb;
556
+ border-radius: 10px;
557
+ box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.12);
558
+ z-index: 10000;
559
+ padding: 4px;
560
+ animation: answerModeSlideUp 0.15s ease-out;
561
+ }
562
+
563
+ @keyframes answerModeSlideUp {
564
+ from {
565
+ opacity: 0;
566
+ transform: translateY(4px);
567
+ }
568
+ to {
569
+ opacity: 1;
570
+ transform: translateY(0);
571
+ }
572
+ }
573
+ .answer-mode-option {
574
+ display: flex;
575
+ align-items: center;
576
+ gap: 8px;
577
+ width: 100%;
578
+ padding: 8px 10px;
579
+ border: none;
580
+ background: transparent;
581
+ border-radius: 8px;
582
+ cursor: pointer;
583
+ transition: background 0.12s ease;
584
+ text-align: left;
585
+ }
586
+ .answer-mode-option:hover {
587
+ background: #f3f4f6;
588
+ }
589
+ .answer-mode-option.selected {
590
+ background: #eef2ff;
591
+ }
592
+
593
+ .answer-mode-option-check {
594
+ display: flex;
595
+ align-items: center;
596
+ justify-content: center;
597
+ width: 16px;
598
+ height: 16px;
599
+ flex-shrink: 0;
600
+ }
601
+
602
+ .answer-mode-option-content {
603
+ display: flex;
604
+ flex-direction: column;
605
+ gap: 1px;
606
+ min-width: 0;
607
+ }
608
+
609
+ .answer-mode-option-label {
610
+ font-family: "Manrope", sans-serif;
611
+ font-size: 13px;
612
+ font-weight: 600;
613
+ color: #1f2b4d;
614
+ line-height: 18px;
615
+ }
616
+
617
+ .answer-mode-option-desc {
618
+ font-family: "Manrope", sans-serif;
619
+ font-size: 11px;
620
+ font-weight: 400;
621
+ color: #6b7280;
622
+ line-height: 16px;
623
+ }
624
+
509
625
  .mention-tooltip {
510
626
  position: fixed;
511
627
  background-color: #1f2b4d;
package/dist/index.cjs.js CHANGED
@@ -789,6 +789,55 @@ const generateConversationObject = (conversationId) => {
789
789
  };
790
790
  }
791
791
  };
792
+ /**
793
+ * Extracts userExplicitInput and textWithColumnNames from a saved filter set.
794
+ * @param {object} selectedFilterSet - The selected saved filter set object
795
+ * @param {string} userText - The user's input text (used to build textWithColumnNames)
796
+ * @param {object} existingExplicitInput - Optional existing userExplicitInput to merge with (e.g. from @ mentions)
797
+ * @returns {{ userExplicitInput: object, textWithColumnNames: string }}
798
+ */
799
+ const extractSavedFilterData = (selectedFilterSet, userText = "", existingExplicitInput = {}) => {
800
+ let userExplicitInput = { ...existingExplicitInput };
801
+ let textWithColumnNames = "";
802
+ if (!selectedFilterSet?.saved_filter_preference) {
803
+ return { userExplicitInput: existingExplicitInput, textWithColumnNames };
804
+ }
805
+ selectedFilterSet.saved_filter_preference.forEach((filter) => {
806
+ const attrName = filter.attribute_name;
807
+ if (!attrName)
808
+ return;
809
+ let filterValues = [];
810
+ if (Array.isArray(filter.values)) {
811
+ filter.values.forEach((v) => {
812
+ if (v && Array.isArray(v.values)) {
813
+ filterValues.push(...v.values.map(String));
814
+ }
815
+ else if (typeof v === "string" || typeof v === "number") {
816
+ filterValues.push(String(v));
817
+ }
818
+ });
819
+ }
820
+ if (filterValues.length > 0) {
821
+ if (userExplicitInput[attrName]) {
822
+ userExplicitInput[attrName] = [
823
+ ...new Set([...userExplicitInput[attrName], ...filterValues]),
824
+ ];
825
+ }
826
+ else {
827
+ userExplicitInput[attrName] = [...new Set(filterValues)];
828
+ }
829
+ const filterText = `${attrName}: ${filterValues.join(", ")}`;
830
+ textWithColumnNames = textWithColumnNames
831
+ ? `${filterText} ${textWithColumnNames}`
832
+ : `${filterText} ${userText}`;
833
+ }
834
+ });
835
+ // Ensure textWithColumnNames ends with the user's text
836
+ if (textWithColumnNames && !textWithColumnNames.includes(userText) && userText.trim()) {
837
+ textWithColumnNames = `${textWithColumnNames} ${userText}`.trim();
838
+ }
839
+ return { userExplicitInput, textWithColumnNames };
840
+ };
792
841
 
793
842
  // Special character mapping for text replacement
794
843
  const SPECIAL_CHARACTER_MAPPING = {
@@ -1880,6 +1929,7 @@ const useAgentFlow = (dateFormat, chatDataRef, currentMode, setShowChatPlacehold
1880
1929
  chat_input: data?.chatInput,
1881
1930
  delay: 0.3,
1882
1931
  chat_id: utilityObjectData?.uniqueChatId ? utilityObjectData?.uniqueChatId : utilityObjectData?.currentAgentChatId,
1932
+ answer_mode: data?.answerMode || "auto",
1883
1933
  ...(!isEmpty(utilityObjectData?.additionalArgs) ? utilityObjectData.additionalArgs : {}),
1884
1934
  };
1885
1935
  // Handle @ filter mentions - user_explicit_input contains filter values
@@ -4645,7 +4695,7 @@ const Rectangle = ({ type, icon, title, description, onClick, hoverable }) => {
4645
4695
  return (jsxRuntime.jsx("div", { className: `${classes.rectangle} ${classes[type]} ${hoverable ? classes.rectangleHoverable : ''}`, onClick: onClick, title: isTruncated ? title : null, children: jsxRuntime.jsxs("div", { className: classes.textContainer, children: [jsxRuntime.jsx(material.Typography, { className: classes.title, ref: titleRef, children: title }), jsxRuntime.jsx(material.Typography, { className: classes.description, children: description })] }) }));
4646
4696
  };
4647
4697
  const ChatPlaceholder = (props) => {
4648
- const { dateFormat, chatDataRef, currentMode, setShowChatPlaceholder, setLoader, setCurrentAgentId, baseUrl, setBaseUrl, setCurrentSessionId, customChatConfig, chatDataInfoRef, setChatDataState, userInput, legacyAgentScreen, activeConversationId, chatBodyRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, setUniqueChatId, fieldNumber, setFieldNumber, setAdditionalArgs, questions, displayQuestions, setActiveConversationId } = props;
4698
+ const { dateFormat, chatDataRef, currentMode, setShowChatPlaceholder, setLoader, setCurrentAgentId, baseUrl, setBaseUrl, setCurrentSessionId, customChatConfig, chatDataInfoRef, setChatDataState, userInput, legacyAgentScreen, activeConversationId, chatBodyRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, setUniqueChatId, fieldNumber, setFieldNumber, setAdditionalArgs, questions, displayQuestions, setActiveConversationId, selectedFilterSet, answerMode, } = props;
4649
4699
  const classes = useStyles$6();
4650
4700
  globalStyles();
4651
4701
  const [cardList, setCardList] = React.useState([]);
@@ -4729,7 +4779,17 @@ const ChatPlaceholder = (props) => {
4729
4779
  user_input: title,
4730
4780
  init: true,
4731
4781
  delay: 0.3,
4782
+ answer_mode: answerMode || "auto",
4732
4783
  };
4784
+ // If a saved filter set is selected, merge its filters into the payload
4785
+ if (selectedFilterSet?.saved_filter_preference) {
4786
+ const { userExplicitInput, textWithColumnNames } = extractSavedFilterData(selectedFilterSet, title);
4787
+ if (!lodash.isEmpty(userExplicitInput)) {
4788
+ initiateAgentPayload.user_explicit_input = userExplicitInput;
4789
+ initiateAgentPayload.chat_input = title;
4790
+ initiateAgentPayload.user_input = textWithColumnNames || title;
4791
+ }
4792
+ }
4733
4793
  setAgentFlow(initiateAgentPayload, "", baseUrl);
4734
4794
  }
4735
4795
  // setAgentFlow(initiateAgentPayload, "", baseUrl);
@@ -5436,6 +5496,15 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5436
5496
  try {
5437
5497
  const data = JSON.parse(event.data);
5438
5498
  console.log("[ButtonContent] SSE chunk:", data);
5499
+ // Always keep stepFormStreamControl.sessionId in sync with the latest chunk's session_id
5500
+ if (data?.session_id) {
5501
+ stepFormStreamControl.sessionId = data.session_id;
5502
+ sessionStorage.setItem("stepForm_sessionId", data.session_id);
5503
+ }
5504
+ if (data?.chat_id) {
5505
+ stepFormStreamControl.chatId = data.chat_id;
5506
+ sessionStorage.setItem("stepForm_chatId", data.chat_id);
5507
+ }
5439
5508
  if (data?.status === "step" || data?.status === "step_form" || data?.status === "questions" || data?.status === "thinking" || data?.status === "widget") {
5440
5509
  chunksRef.push(data);
5441
5510
  // Dispatch widget chunks immediately for real-time rendering
@@ -5460,6 +5529,8 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5460
5529
  stepFormStreamControl.initValue = true;
5461
5530
  stepFormStreamControl.sessionId = "";
5462
5531
  stepFormStreamControl.uniqueChatId = data?.chat_id ? data.chat_id : "";
5532
+ // Clear sessionStorage so stale session_id isn't picked up by future non-init calls
5533
+ sessionStorage.setItem("stepForm_sessionId", "");
5463
5534
  }
5464
5535
  // Stream ended — dispatch all collected chunks at once
5465
5536
  stepFormStreamControl.isStreaming = false;
@@ -6758,6 +6829,165 @@ const StepsResponseTab = (props) => {
6758
6829
  ], value: tabValue }) }));
6759
6830
  };
6760
6831
 
6832
+ /**
6833
+ * Tab Notification Utility
6834
+ * Shows a red badge on the browser tab favicon and updates the document title
6835
+ * when new step_form chunks arrive while the user is on a different tab.
6836
+ * Similar to Facebook's unread message count badge.
6837
+ */
6838
+ const ORIGINAL_TITLE = " Impact Smart ";
6839
+ const FAVICON_SELECTOR = 'link[rel="icon"]';
6840
+ let notificationCount = 0;
6841
+ let originalFaviconHref = null;
6842
+ let faviconCanvas = null;
6843
+ let faviconCtx = null;
6844
+ let faviconImg = null;
6845
+ let isInitialized = false;
6846
+ let visibilityListenerAttached = false;
6847
+ let titleBlinkInterval = null;
6848
+ /**
6849
+ * Initialize the canvas and load the original favicon image.
6850
+ * Called lazily on first notification.
6851
+ */
6852
+ function init() {
6853
+ if (isInitialized)
6854
+ return;
6855
+ isInitialized = true;
6856
+ const faviconEl = document.querySelector(FAVICON_SELECTOR);
6857
+ originalFaviconHref = faviconEl ? faviconEl.href : "/assets/IA.svg";
6858
+ faviconCanvas = document.createElement("canvas");
6859
+ faviconCanvas.width = 64;
6860
+ faviconCanvas.height = 64;
6861
+ faviconCtx = faviconCanvas.getContext("2d");
6862
+ faviconImg = new Image();
6863
+ faviconImg.crossOrigin = "anonymous";
6864
+ faviconImg.src = originalFaviconHref;
6865
+ if (!visibilityListenerAttached) {
6866
+ visibilityListenerAttached = true;
6867
+ document.addEventListener("visibilitychange", handleVisibilityChange);
6868
+ }
6869
+ }
6870
+ /**
6871
+ * When the user returns to the tab, clear all notifications.
6872
+ */
6873
+ function handleVisibilityChange() {
6874
+ if (!document.hidden && notificationCount > 0) {
6875
+ clearTabNotification();
6876
+ }
6877
+ }
6878
+ /**
6879
+ * Draw the favicon with a red notification badge showing the count.
6880
+ */
6881
+ function drawBadge(count) {
6882
+ if (!faviconCtx || !faviconCanvas)
6883
+ return;
6884
+ const size = faviconCanvas.width;
6885
+ faviconCtx.clearRect(0, 0, size, size);
6886
+ // Draw original favicon
6887
+ if (faviconImg && faviconImg.complete && faviconImg.naturalWidth > 0) {
6888
+ faviconCtx.drawImage(faviconImg, 0, 0, size, size);
6889
+ }
6890
+ if (count <= 0)
6891
+ return;
6892
+ const text = count > 99 ? "99+" : String(count);
6893
+ // Badge dimensions
6894
+ const badgeRadius = 14;
6895
+ const badgeX = size - badgeRadius - 1;
6896
+ const badgeY = badgeRadius + 1;
6897
+ // Draw red circle
6898
+ faviconCtx.beginPath();
6899
+ faviconCtx.arc(badgeX, badgeY, badgeRadius, 0, 2 * Math.PI);
6900
+ faviconCtx.fillStyle = "#e53e3e";
6901
+ faviconCtx.fill();
6902
+ // White border
6903
+ faviconCtx.lineWidth = 2;
6904
+ faviconCtx.strokeStyle = "#ffffff";
6905
+ faviconCtx.stroke();
6906
+ // Draw count text
6907
+ faviconCtx.fillStyle = "#ffffff";
6908
+ faviconCtx.font = `bold ${count > 9 ? 14 : 18}px sans-serif`;
6909
+ faviconCtx.textAlign = "center";
6910
+ faviconCtx.textBaseline = "middle";
6911
+ faviconCtx.fillText(text, badgeX, badgeY + 1);
6912
+ }
6913
+ /**
6914
+ * Update the favicon element in the DOM.
6915
+ */
6916
+ function applyFavicon(dataUrl) {
6917
+ let faviconEl = document.querySelector(FAVICON_SELECTOR);
6918
+ if (!faviconEl) {
6919
+ faviconEl = document.createElement("link");
6920
+ faviconEl.rel = "icon";
6921
+ document.head.appendChild(faviconEl);
6922
+ }
6923
+ faviconEl.href = dataUrl;
6924
+ }
6925
+ /**
6926
+ * Increment the tab notification count.
6927
+ * Only shows badge when the tab is not visible (user is on another tab).
6928
+ */
6929
+ function showTabNotification() {
6930
+ // Only notify when user is NOT looking at this tab
6931
+ if (!document.hidden)
6932
+ return;
6933
+ init();
6934
+ notificationCount += 1;
6935
+ // Start blinking title to grab attention
6936
+ startTitleBlink();
6937
+ // Draw and apply badge favicon
6938
+ const renderBadge = () => {
6939
+ drawBadge(notificationCount);
6940
+ applyFavicon(faviconCanvas.toDataURL("image/png"));
6941
+ };
6942
+ if (faviconImg && faviconImg.complete) {
6943
+ renderBadge();
6944
+ }
6945
+ else if (faviconImg) {
6946
+ faviconImg.onload = renderBadge;
6947
+ }
6948
+ }
6949
+ /**
6950
+ * Alternates the document title between notification message and a blank/attention string
6951
+ * to create a blinking effect that catches the user's eye (like WhatsApp Web / Facebook).
6952
+ */
6953
+ function startTitleBlink() {
6954
+ if (titleBlinkInterval)
6955
+ clearInterval(titleBlinkInterval);
6956
+ let showNotification = true;
6957
+ const notificationTitle = `(${notificationCount}) New form awaiting input`;
6958
+ // Set immediately
6959
+ document.title = notificationTitle;
6960
+ titleBlinkInterval = setInterval(() => {
6961
+ if (showNotification) {
6962
+ document.title = ORIGINAL_TITLE.trim();
6963
+ }
6964
+ else {
6965
+ document.title = `(${notificationCount}) New form awaiting input`;
6966
+ }
6967
+ showNotification = !showNotification;
6968
+ }, 1000);
6969
+ }
6970
+ /**
6971
+ * Stop the title blink interval.
6972
+ */
6973
+ function stopTitleBlink() {
6974
+ if (titleBlinkInterval) {
6975
+ clearInterval(titleBlinkInterval);
6976
+ titleBlinkInterval = null;
6977
+ }
6978
+ }
6979
+ /**
6980
+ * Clear all tab notifications — restore original title and favicon.
6981
+ */
6982
+ function clearTabNotification() {
6983
+ notificationCount = 0;
6984
+ stopTitleBlink();
6985
+ document.title = ORIGINAL_TITLE;
6986
+ if (originalFaviconHref) {
6987
+ applyFavicon(originalFaviconHref);
6988
+ }
6989
+ }
6990
+
6761
6991
  /**
6762
6992
  * Module-level Map to persist streaming state across component remounts (tab switches).
6763
6993
  * Keyed by a stable identifier derived from input payload + mode + conversation ID.
@@ -6849,6 +7079,7 @@ const StreamedContent = ({ botData }) => {
6849
7079
  const thinkingDoneRef = React.useRef(false);
6850
7080
  const setThinkingContentRef = React.useRef(setThinkingContent); // Store current setThinkingContent function
6851
7081
  const streamTimeoutRef = React.useRef(null); // Ref for stream timeout
7082
+ const streamingDoneProcessedRef = React.useRef(false); // Guard to prevent isStreamingDone effect running twice
6852
7083
  // Stable key for the module-level streamStateMap (survives cloneDeep of botData)
6853
7084
  const streamKey = React.useRef(`${currentMode}_${activeConversationId}_${JSON.stringify(botData.inputBody)}`).current;
6854
7085
  // Look up existing stream state from the Map (persists across tab-switch remounts)
@@ -7087,6 +7318,7 @@ const StreamedContent = ({ botData }) => {
7087
7318
  setStepChange((prev) => !prev);
7088
7319
  }
7089
7320
  else if (data.status === "step_form") {
7321
+ showTabNotification();
7090
7322
  const formWidgetData = isArray(data.widget_data)
7091
7323
  ? data.widget_data
7092
7324
  : [data.widget_data];
@@ -7280,7 +7512,8 @@ const StreamedContent = ({ botData }) => {
7280
7512
  * Parses the accumulated response and updates the chat history
7281
7513
  */
7282
7514
  React.useEffect(() => {
7283
- if (isStreamingDone) {
7515
+ if (isStreamingDone && !streamingDoneProcessedRef.current) {
7516
+ streamingDoneProcessedRef.current = true;
7284
7517
  localStorage.setItem("isStreaming", "false");
7285
7518
  if (currentMode === "agent") {
7286
7519
  setIsStop(false);
@@ -9633,7 +9866,7 @@ const useMentionState = () => {
9633
9866
  };
9634
9867
 
9635
9868
  const ChatbotInput = (props) => {
9636
- const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, } = props;
9869
+ const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, answerMode, setAnswerMode, } = props;
9637
9870
  const editorRef = React.useRef(null);
9638
9871
  const selectRef = React.useRef(null);
9639
9872
  const filterSetSelectRef = React.useRef(null);
@@ -9643,6 +9876,8 @@ const ChatbotInput = (props) => {
9643
9876
  const chatInputContainerRef = React.useRef(null);
9644
9877
  const [isFixed, setIsFixed] = React.useState(false);
9645
9878
  const [height, setHeight] = React.useState("auto");
9879
+ const [showAnswerModeMenu, setShowAnswerModeMenu] = React.useState(false);
9880
+ const answerModeRef = React.useRef(null);
9646
9881
  const [hasMentionsInEditor, setHasMentionsInEditor] = React.useState(false);
9647
9882
  const isInsertingMentionRef = React.useRef(false);
9648
9883
  const isTransitioningStageRef = React.useRef(false);
@@ -10643,44 +10878,9 @@ const ChatbotInput = (props) => {
10643
10878
  // If a saved filter set is selected, merge its filters into userExplicitInput
10644
10879
  // and textWithColumnNames in the same format as @ mentions
10645
10880
  if (selectedFilterSet?.saved_filter_preference) {
10646
- selectedFilterSet.saved_filter_preference.forEach((filter) => {
10647
- const attrName = filter.attribute_name;
10648
- if (!attrName)
10649
- return;
10650
- // Extract all values from the filter's values array
10651
- let filterValues = [];
10652
- if (Array.isArray(filter.values)) {
10653
- filter.values.forEach((v) => {
10654
- if (v && Array.isArray(v.values)) {
10655
- filterValues.push(...v.values.map(String));
10656
- }
10657
- else if (typeof v === "string" || typeof v === "number") {
10658
- filterValues.push(String(v));
10659
- }
10660
- });
10661
- }
10662
- if (filterValues.length > 0) {
10663
- // Merge into userExplicitInput (combine with existing @ mention values if any)
10664
- if (userExplicitInput[attrName]) {
10665
- userExplicitInput[attrName] = [
10666
- ...new Set([...userExplicitInput[attrName], ...filterValues]),
10667
- ];
10668
- }
10669
- else {
10670
- userExplicitInput[attrName] = [...new Set(filterValues)];
10671
- }
10672
- // Build textWithColumnNames prefix from saved filter data
10673
- const filterText = `${attrName}: ${filterValues.join(", ")}`;
10674
- textWithColumnNames = textWithColumnNames
10675
- ? `${filterText} ${textWithColumnNames}`
10676
- : `${filterText} ${formattedText}`;
10677
- }
10678
- });
10679
- // If textWithColumnNames was not set by mentions but was set by saved filters,
10680
- // ensure it ends with the user's text
10681
- if (!textWithColumnNames.includes(formattedText) && formattedText.trim()) {
10682
- textWithColumnNames = `${textWithColumnNames} ${formattedText}`.trim();
10683
- }
10881
+ const filterData = extractSavedFilterData(selectedFilterSet, formattedText, userExplicitInput);
10882
+ Object.assign(userExplicitInput, filterData.userExplicitInput);
10883
+ textWithColumnNames = filterData.textWithColumnNames || textWithColumnNames;
10684
10884
  }
10685
10885
  setInputValue("");
10686
10886
  if (editorRef.current) {
@@ -10940,6 +11140,25 @@ const ChatbotInput = (props) => {
10940
11140
  document.removeEventListener("mousedown", handleClickOutside);
10941
11141
  };
10942
11142
  }, [showFilterSetMenu]);
11143
+ // Click outside handler for answer mode dropdown
11144
+ React.useEffect(() => {
11145
+ const handleClickOutside = (event) => {
11146
+ if (answerModeRef.current && !answerModeRef.current.contains(event.target)) {
11147
+ setShowAnswerModeMenu(false);
11148
+ }
11149
+ };
11150
+ if (showAnswerModeMenu) {
11151
+ document.addEventListener("mousedown", handleClickOutside);
11152
+ }
11153
+ return () => {
11154
+ document.removeEventListener("mousedown", handleClickOutside);
11155
+ };
11156
+ }, [showAnswerModeMenu]);
11157
+ const ANSWER_MODE_OPTIONS = [
11158
+ { value: "fast", label: "Fast", description: "Speed over depth" },
11159
+ { value: "auto", label: "Auto", description: "Adapts depth, detail, and visuals" },
11160
+ ];
11161
+ const selectedModeOption = ANSWER_MODE_OPTIONS.find((opt) => opt.value === answerMode) || ANSWER_MODE_OPTIONS[1];
10943
11162
  return (jsxRuntime.jsx("div", { className: "chat-input-container", ref: chatInputContainerRef, onClick: (e) => {
10944
11163
  // Focus editor when clicking anywhere in the input container
10945
11164
  // unless clicking on a button or interactive element
@@ -10950,7 +11169,8 @@ const ChatbotInput = (props) => {
10950
11169
  !target.closest(".chat-actions") &&
10951
11170
  !target.closest(".filter-set-trigger-wrapper") &&
10952
11171
  !target.closest(".filter-set-chip-clear") &&
10953
- !target.closest(".mention-select-wrapper")) {
11172
+ !target.closest(".mention-select-wrapper") &&
11173
+ !target.closest(".answer-mode-wrapper")) {
10954
11174
  editorRef.current.focus();
10955
11175
  }
10956
11176
  }, children: jsxRuntime.jsxs("div", { className: `chat-input-wrapper ${isFixed ? "stacked" : ""} ${selectedFilterSet ? "has-filter-selected" : ""} ${(!isFixed || inputValue === "") && !newChatScreen && !selectedFilterSet ? "empty" : ""} ${!newChatScreen && !isFixed && !selectedFilterSet ? "single-line-textarea" : ""}`, style: { height }, children: [jsxRuntime.jsxs("div", { className: "chat-input-left-actions", children: [jsxRuntime.jsxs("div", { className: "filter-set-trigger-wrapper", ref: filterSetSelectRef, children: [jsxRuntime.jsx(impactUiV3.Tooltip, { title: hasMentionsInEditor || showMentionSelect ? "Cannot use filter set while @ mentions are active" : "Add filter set", children: jsxRuntime.jsx("button", { type: "button", className: `filter-set-plus-btn${hasMentionsInEditor || showMentionSelect ? " disabled" : ""}`, onClick: () => {
@@ -10980,7 +11200,10 @@ const ChatbotInput = (props) => {
10980
11200
  handleSendMessage();
10981
11201
  }
10982
11202
  }
10983
- }, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxRuntime.jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsxRuntime.jsx(impactUiV3.Tooltip, { title: "Save Chat", children: jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsxRuntime.jsx(impactUiV3.Button, { icon: !isStopIcon ? jsxRuntime.jsx(SvgChatBotSendIcon, {}) : jsxRuntime.jsx(SvgChatbotStopIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "primary", onClick: () => {
11203
+ }, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxRuntime.jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsxRuntime.jsx(impactUiV3.Tooltip, { title: "Save Chat", children: jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsxRuntime.jsxs("div", { className: "answer-mode-wrapper", ref: answerModeRef, children: [jsxRuntime.jsxs("button", { type: "button", className: "answer-mode-trigger", onClick: () => setShowAnswerModeMenu(!showAnswerModeMenu), children: [jsxRuntime.jsx("span", { className: "answer-mode-trigger-label", children: selectedModeOption.label }), jsxRuntime.jsx("svg", { className: `answer-mode-trigger-chevron ${showAnswerModeMenu ? "open" : ""}`, width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: jsxRuntime.jsx("path", { d: "M3 7.5L6 4.5L9 7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), showAnswerModeMenu && (jsxRuntime.jsx("div", { className: "answer-mode-dropdown", children: ANSWER_MODE_OPTIONS.map((option) => (jsxRuntime.jsxs("button", { type: "button", className: `answer-mode-option ${answerMode === option.value ? "selected" : ""}`, onClick: () => {
11204
+ setAnswerMode(option.value);
11205
+ setShowAnswerModeMenu(false);
11206
+ }, children: [jsxRuntime.jsx("div", { className: "answer-mode-option-check", children: answerMode === option.value && (jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: jsxRuntime.jsx("path", { d: "M2.5 7L5.5 10L11.5 4", stroke: "#5C6BC0", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })) }), jsxRuntime.jsxs("div", { className: "answer-mode-option-content", children: [jsxRuntime.jsx("span", { className: "answer-mode-option-label", children: option.label }), jsxRuntime.jsx("span", { className: "answer-mode-option-desc", children: option.description })] })] }, option.value))) }))] }), jsxRuntime.jsx(impactUiV3.Button, { icon: !isStopIcon ? jsxRuntime.jsx(SvgChatBotSendIcon, {}) : jsxRuntime.jsx(SvgChatbotStopIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "primary", onClick: () => {
10984
11207
  !isStopIcon ? handleSendMessage() : onStopIconClick();
10985
11208
  }, id: "chat-input-send-button", className: isStopIcon ? "stop-icon-button" : "" })] }), showMentionSelect && (jsxRuntime.jsx("div", { className: "mention-select-wrapper", ref: selectRef, style: {
10986
11209
  position: "fixed",
@@ -11911,6 +12134,7 @@ const SmartBot = (props) => {
11911
12134
  const [filterOptions, setFilterOptions] = React.useState([]);
11912
12135
  const [savedFilterSets, setSavedFilterSets] = React.useState([]);
11913
12136
  const [selectedFilterSet, setSelectedFilterSet] = React.useState(null);
12137
+ const [answerMode, setAnswerMode] = React.useState("auto");
11914
12138
  const [chatBotWidth, setChatBotWidth] = React.useState(null);
11915
12139
  React.useRef(0);
11916
12140
  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);
@@ -12388,10 +12612,11 @@ const SmartBot = (props) => {
12388
12612
  let data = {
12389
12613
  agentId: currentAgentId,
12390
12614
  userInput: lodash.cloneDeep(userInput),
12391
- sessionId: currentSessionId,
12615
+ sessionId: lodash.isEmpty(userInput) ? currentSessionId : "",
12392
12616
  baseUrl: baseUrl,
12393
12617
  userExplicitInput: userExplicitInput,
12394
12618
  textWithColumnNames: textWithColumnNames,
12619
+ answerMode: answerMode,
12395
12620
  };
12396
12621
  // if(!isEmpty(userInput)) {
12397
12622
  dispatch(smartBotActions.setThinkingContext({
@@ -12425,6 +12650,13 @@ const SmartBot = (props) => {
12425
12650
  // Reset step form stream state so old TabularContent instances don't process new data
12426
12651
  dispatch(smartBotActions.setStepFormStreamData(null));
12427
12652
  resetActiveTabularInstance();
12653
+ // Reset stepFormStreamControl so stale session_id doesn't leak into new prompts
12654
+ stepFormStreamControl.sessionId = "";
12655
+ stepFormStreamControl.chatId = "";
12656
+ stepFormStreamControl.initValue = false;
12657
+ stepFormStreamControl.uniqueChatId = "";
12658
+ sessionStorage.removeItem("stepForm_sessionId");
12659
+ sessionStorage.removeItem("stepForm_chatId");
12428
12660
  // dispatch(setChatbotContext({}));
12429
12661
  setUserInput(params?.text);
12430
12662
  handleSendMessage(params?.text, params?.userExplicitInput, params?.textWithColumnNames);
@@ -12574,7 +12806,9 @@ const SmartBot = (props) => {
12574
12806
  }
12575
12807
  fetchConversations(null, "agent");
12576
12808
  }, [renameConversation, deleteConversation, fetchConversations]);
12577
- return (jsxRuntime.jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsxRuntime.jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(impactUiV3.ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (jsxRuntime.jsx(ChatbotInput, { newChatScreen: newChatScreen, inputValue: userInput, setInputValue: setUserInput, isStopIcon: isStop, onSendIconClick: onSendIconClick, onStopIconClick: onStopIconClick, currentMode: currentMode, filterOptions: filterOptions, onSaveClick: saveCurrentChat, savedFilterSets: savedFilterSets, selectedFilterSet: selectedFilterSet, onFilterSetSelect: (filterSet) => setSelectedFilterSet(filterSet), onClearFilterSet: () => setSelectedFilterSet(null), onTriggerRefresh: triggerRefreshAction })) : showSavedFilters ? jsxRuntime.jsx(jsxRuntime.Fragment, {}) : null, isChatBotOpen: showModal || forceOpen, historyPanelData: historyPanelData, onHistorySearchChange: (params) => { console.log("History Search Change", params); }, onHistorySelectConversation: (params) => {
12809
+ return (jsxRuntime.jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsxRuntime.jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(impactUiV3.ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (jsxRuntime.jsx(ChatbotInput, { newChatScreen: newChatScreen, inputValue: userInput, setInputValue: setUserInput, isStopIcon: isStop, onSendIconClick: onSendIconClick, onStopIconClick: onStopIconClick, currentMode: currentMode, filterOptions: filterOptions,
12810
+ // onSaveClick={saveCurrentChat}
12811
+ savedFilterSets: savedFilterSets, selectedFilterSet: selectedFilterSet, onFilterSetSelect: (filterSet) => setSelectedFilterSet(filterSet), onClearFilterSet: () => setSelectedFilterSet(null), onTriggerRefresh: triggerRefreshAction, answerMode: answerMode, setAnswerMode: setAnswerMode })) : showSavedFilters ? jsxRuntime.jsx(jsxRuntime.Fragment, {}) : null, isChatBotOpen: showModal || forceOpen, historyPanelData: historyPanelData, onHistorySearchChange: (params) => { console.log("History Search Change", params); }, onHistorySelectConversation: (params) => {
12578
12812
  console.log("History Select Conversation", params);
12579
12813
  setNewChatScreen(false);
12580
12814
  setShowChatPlaceholder(false);
@@ -12783,7 +13017,7 @@ const SmartBot = (props) => {
12783
13017
  icon: jsxRuntime.jsx(SvgSaveFilterTab, {}),
12784
13018
  },
12785
13019
  ], utilityList: utilityList, isAssistantThinking: false, isCustomScreen: showChatPlaceholder ? showChatPlaceholder : showSavedFilters, customScreenJsx: showChatPlaceholder ?
12786
- jsxRuntime.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 })
13020
+ jsxRuntime.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, selectedFilterSet: selectedFilterSet, answerMode: answerMode })
12787
13021
  :
12788
13022
  jsxRuntime.jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose, chatBotWidth: chatBotWidth }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
12789
13023
  freeTextHeading: "Try adding more details :",