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.esm.js CHANGED
@@ -767,6 +767,55 @@ const generateConversationObject = (conversationId) => {
767
767
  };
768
768
  }
769
769
  };
770
+ /**
771
+ * Extracts userExplicitInput and textWithColumnNames from a saved filter set.
772
+ * @param {object} selectedFilterSet - The selected saved filter set object
773
+ * @param {string} userText - The user's input text (used to build textWithColumnNames)
774
+ * @param {object} existingExplicitInput - Optional existing userExplicitInput to merge with (e.g. from @ mentions)
775
+ * @returns {{ userExplicitInput: object, textWithColumnNames: string }}
776
+ */
777
+ const extractSavedFilterData = (selectedFilterSet, userText = "", existingExplicitInput = {}) => {
778
+ let userExplicitInput = { ...existingExplicitInput };
779
+ let textWithColumnNames = "";
780
+ if (!selectedFilterSet?.saved_filter_preference) {
781
+ return { userExplicitInput: existingExplicitInput, textWithColumnNames };
782
+ }
783
+ selectedFilterSet.saved_filter_preference.forEach((filter) => {
784
+ const attrName = filter.attribute_name;
785
+ if (!attrName)
786
+ return;
787
+ let filterValues = [];
788
+ if (Array.isArray(filter.values)) {
789
+ filter.values.forEach((v) => {
790
+ if (v && Array.isArray(v.values)) {
791
+ filterValues.push(...v.values.map(String));
792
+ }
793
+ else if (typeof v === "string" || typeof v === "number") {
794
+ filterValues.push(String(v));
795
+ }
796
+ });
797
+ }
798
+ if (filterValues.length > 0) {
799
+ if (userExplicitInput[attrName]) {
800
+ userExplicitInput[attrName] = [
801
+ ...new Set([...userExplicitInput[attrName], ...filterValues]),
802
+ ];
803
+ }
804
+ else {
805
+ userExplicitInput[attrName] = [...new Set(filterValues)];
806
+ }
807
+ const filterText = `${attrName}: ${filterValues.join(", ")}`;
808
+ textWithColumnNames = textWithColumnNames
809
+ ? `${filterText} ${textWithColumnNames}`
810
+ : `${filterText} ${userText}`;
811
+ }
812
+ });
813
+ // Ensure textWithColumnNames ends with the user's text
814
+ if (textWithColumnNames && !textWithColumnNames.includes(userText) && userText.trim()) {
815
+ textWithColumnNames = `${textWithColumnNames} ${userText}`.trim();
816
+ }
817
+ return { userExplicitInput, textWithColumnNames };
818
+ };
770
819
 
771
820
  // Special character mapping for text replacement
772
821
  const SPECIAL_CHARACTER_MAPPING = {
@@ -1858,6 +1907,7 @@ const useAgentFlow = (dateFormat, chatDataRef, currentMode, setShowChatPlacehold
1858
1907
  chat_input: data?.chatInput,
1859
1908
  delay: 0.3,
1860
1909
  chat_id: utilityObjectData?.uniqueChatId ? utilityObjectData?.uniqueChatId : utilityObjectData?.currentAgentChatId,
1910
+ answer_mode: data?.answerMode || "auto",
1861
1911
  ...(!isEmpty(utilityObjectData?.additionalArgs) ? utilityObjectData.additionalArgs : {}),
1862
1912
  };
1863
1913
  // Handle @ filter mentions - user_explicit_input contains filter values
@@ -4623,7 +4673,7 @@ const Rectangle = ({ type, icon, title, description, onClick, hoverable }) => {
4623
4673
  return (jsx("div", { className: `${classes.rectangle} ${classes[type]} ${hoverable ? classes.rectangleHoverable : ''}`, onClick: onClick, title: isTruncated ? title : null, children: jsxs("div", { className: classes.textContainer, children: [jsx(Typography, { className: classes.title, ref: titleRef, children: title }), jsx(Typography, { className: classes.description, children: description })] }) }));
4624
4674
  };
4625
4675
  const ChatPlaceholder = (props) => {
4626
- 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;
4676
+ 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;
4627
4677
  const classes = useStyles$6();
4628
4678
  globalStyles();
4629
4679
  const [cardList, setCardList] = useState([]);
@@ -4707,7 +4757,17 @@ const ChatPlaceholder = (props) => {
4707
4757
  user_input: title,
4708
4758
  init: true,
4709
4759
  delay: 0.3,
4760
+ answer_mode: answerMode || "auto",
4710
4761
  };
4762
+ // If a saved filter set is selected, merge its filters into the payload
4763
+ if (selectedFilterSet?.saved_filter_preference) {
4764
+ const { userExplicitInput, textWithColumnNames } = extractSavedFilterData(selectedFilterSet, title);
4765
+ if (!isEmpty$1(userExplicitInput)) {
4766
+ initiateAgentPayload.user_explicit_input = userExplicitInput;
4767
+ initiateAgentPayload.chat_input = title;
4768
+ initiateAgentPayload.user_input = textWithColumnNames || title;
4769
+ }
4770
+ }
4711
4771
  setAgentFlow(initiateAgentPayload, "", baseUrl);
4712
4772
  }
4713
4773
  // setAgentFlow(initiateAgentPayload, "", baseUrl);
@@ -5414,6 +5474,15 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5414
5474
  try {
5415
5475
  const data = JSON.parse(event.data);
5416
5476
  console.log("[ButtonContent] SSE chunk:", data);
5477
+ // Always keep stepFormStreamControl.sessionId in sync with the latest chunk's session_id
5478
+ if (data?.session_id) {
5479
+ stepFormStreamControl.sessionId = data.session_id;
5480
+ sessionStorage.setItem("stepForm_sessionId", data.session_id);
5481
+ }
5482
+ if (data?.chat_id) {
5483
+ stepFormStreamControl.chatId = data.chat_id;
5484
+ sessionStorage.setItem("stepForm_chatId", data.chat_id);
5485
+ }
5417
5486
  if (data?.status === "step" || data?.status === "step_form" || data?.status === "questions" || data?.status === "thinking" || data?.status === "widget") {
5418
5487
  chunksRef.push(data);
5419
5488
  // Dispatch widget chunks immediately for real-time rendering
@@ -5438,6 +5507,8 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
5438
5507
  stepFormStreamControl.initValue = true;
5439
5508
  stepFormStreamControl.sessionId = "";
5440
5509
  stepFormStreamControl.uniqueChatId = data?.chat_id ? data.chat_id : "";
5510
+ // Clear sessionStorage so stale session_id isn't picked up by future non-init calls
5511
+ sessionStorage.setItem("stepForm_sessionId", "");
5441
5512
  }
5442
5513
  // Stream ended — dispatch all collected chunks at once
5443
5514
  stepFormStreamControl.isStreaming = false;
@@ -6736,6 +6807,165 @@ const StepsResponseTab = (props) => {
6736
6807
  ], value: tabValue }) }));
6737
6808
  };
6738
6809
 
6810
+ /**
6811
+ * Tab Notification Utility
6812
+ * Shows a red badge on the browser tab favicon and updates the document title
6813
+ * when new step_form chunks arrive while the user is on a different tab.
6814
+ * Similar to Facebook's unread message count badge.
6815
+ */
6816
+ const ORIGINAL_TITLE = " Impact Smart ";
6817
+ const FAVICON_SELECTOR = 'link[rel="icon"]';
6818
+ let notificationCount = 0;
6819
+ let originalFaviconHref = null;
6820
+ let faviconCanvas = null;
6821
+ let faviconCtx = null;
6822
+ let faviconImg = null;
6823
+ let isInitialized = false;
6824
+ let visibilityListenerAttached = false;
6825
+ let titleBlinkInterval = null;
6826
+ /**
6827
+ * Initialize the canvas and load the original favicon image.
6828
+ * Called lazily on first notification.
6829
+ */
6830
+ function init() {
6831
+ if (isInitialized)
6832
+ return;
6833
+ isInitialized = true;
6834
+ const faviconEl = document.querySelector(FAVICON_SELECTOR);
6835
+ originalFaviconHref = faviconEl ? faviconEl.href : "/assets/IA.svg";
6836
+ faviconCanvas = document.createElement("canvas");
6837
+ faviconCanvas.width = 64;
6838
+ faviconCanvas.height = 64;
6839
+ faviconCtx = faviconCanvas.getContext("2d");
6840
+ faviconImg = new Image();
6841
+ faviconImg.crossOrigin = "anonymous";
6842
+ faviconImg.src = originalFaviconHref;
6843
+ if (!visibilityListenerAttached) {
6844
+ visibilityListenerAttached = true;
6845
+ document.addEventListener("visibilitychange", handleVisibilityChange);
6846
+ }
6847
+ }
6848
+ /**
6849
+ * When the user returns to the tab, clear all notifications.
6850
+ */
6851
+ function handleVisibilityChange() {
6852
+ if (!document.hidden && notificationCount > 0) {
6853
+ clearTabNotification();
6854
+ }
6855
+ }
6856
+ /**
6857
+ * Draw the favicon with a red notification badge showing the count.
6858
+ */
6859
+ function drawBadge(count) {
6860
+ if (!faviconCtx || !faviconCanvas)
6861
+ return;
6862
+ const size = faviconCanvas.width;
6863
+ faviconCtx.clearRect(0, 0, size, size);
6864
+ // Draw original favicon
6865
+ if (faviconImg && faviconImg.complete && faviconImg.naturalWidth > 0) {
6866
+ faviconCtx.drawImage(faviconImg, 0, 0, size, size);
6867
+ }
6868
+ if (count <= 0)
6869
+ return;
6870
+ const text = count > 99 ? "99+" : String(count);
6871
+ // Badge dimensions
6872
+ const badgeRadius = 14;
6873
+ const badgeX = size - badgeRadius - 1;
6874
+ const badgeY = badgeRadius + 1;
6875
+ // Draw red circle
6876
+ faviconCtx.beginPath();
6877
+ faviconCtx.arc(badgeX, badgeY, badgeRadius, 0, 2 * Math.PI);
6878
+ faviconCtx.fillStyle = "#e53e3e";
6879
+ faviconCtx.fill();
6880
+ // White border
6881
+ faviconCtx.lineWidth = 2;
6882
+ faviconCtx.strokeStyle = "#ffffff";
6883
+ faviconCtx.stroke();
6884
+ // Draw count text
6885
+ faviconCtx.fillStyle = "#ffffff";
6886
+ faviconCtx.font = `bold ${count > 9 ? 14 : 18}px sans-serif`;
6887
+ faviconCtx.textAlign = "center";
6888
+ faviconCtx.textBaseline = "middle";
6889
+ faviconCtx.fillText(text, badgeX, badgeY + 1);
6890
+ }
6891
+ /**
6892
+ * Update the favicon element in the DOM.
6893
+ */
6894
+ function applyFavicon(dataUrl) {
6895
+ let faviconEl = document.querySelector(FAVICON_SELECTOR);
6896
+ if (!faviconEl) {
6897
+ faviconEl = document.createElement("link");
6898
+ faviconEl.rel = "icon";
6899
+ document.head.appendChild(faviconEl);
6900
+ }
6901
+ faviconEl.href = dataUrl;
6902
+ }
6903
+ /**
6904
+ * Increment the tab notification count.
6905
+ * Only shows badge when the tab is not visible (user is on another tab).
6906
+ */
6907
+ function showTabNotification() {
6908
+ // Only notify when user is NOT looking at this tab
6909
+ if (!document.hidden)
6910
+ return;
6911
+ init();
6912
+ notificationCount += 1;
6913
+ // Start blinking title to grab attention
6914
+ startTitleBlink();
6915
+ // Draw and apply badge favicon
6916
+ const renderBadge = () => {
6917
+ drawBadge(notificationCount);
6918
+ applyFavicon(faviconCanvas.toDataURL("image/png"));
6919
+ };
6920
+ if (faviconImg && faviconImg.complete) {
6921
+ renderBadge();
6922
+ }
6923
+ else if (faviconImg) {
6924
+ faviconImg.onload = renderBadge;
6925
+ }
6926
+ }
6927
+ /**
6928
+ * Alternates the document title between notification message and a blank/attention string
6929
+ * to create a blinking effect that catches the user's eye (like WhatsApp Web / Facebook).
6930
+ */
6931
+ function startTitleBlink() {
6932
+ if (titleBlinkInterval)
6933
+ clearInterval(titleBlinkInterval);
6934
+ let showNotification = true;
6935
+ const notificationTitle = `(${notificationCount}) New form awaiting input`;
6936
+ // Set immediately
6937
+ document.title = notificationTitle;
6938
+ titleBlinkInterval = setInterval(() => {
6939
+ if (showNotification) {
6940
+ document.title = ORIGINAL_TITLE.trim();
6941
+ }
6942
+ else {
6943
+ document.title = `(${notificationCount}) New form awaiting input`;
6944
+ }
6945
+ showNotification = !showNotification;
6946
+ }, 1000);
6947
+ }
6948
+ /**
6949
+ * Stop the title blink interval.
6950
+ */
6951
+ function stopTitleBlink() {
6952
+ if (titleBlinkInterval) {
6953
+ clearInterval(titleBlinkInterval);
6954
+ titleBlinkInterval = null;
6955
+ }
6956
+ }
6957
+ /**
6958
+ * Clear all tab notifications — restore original title and favicon.
6959
+ */
6960
+ function clearTabNotification() {
6961
+ notificationCount = 0;
6962
+ stopTitleBlink();
6963
+ document.title = ORIGINAL_TITLE;
6964
+ if (originalFaviconHref) {
6965
+ applyFavicon(originalFaviconHref);
6966
+ }
6967
+ }
6968
+
6739
6969
  /**
6740
6970
  * Module-level Map to persist streaming state across component remounts (tab switches).
6741
6971
  * Keyed by a stable identifier derived from input payload + mode + conversation ID.
@@ -6827,6 +7057,7 @@ const StreamedContent = ({ botData }) => {
6827
7057
  const thinkingDoneRef = useRef(false);
6828
7058
  const setThinkingContentRef = useRef(setThinkingContent); // Store current setThinkingContent function
6829
7059
  const streamTimeoutRef = useRef(null); // Ref for stream timeout
7060
+ const streamingDoneProcessedRef = useRef(false); // Guard to prevent isStreamingDone effect running twice
6830
7061
  // Stable key for the module-level streamStateMap (survives cloneDeep of botData)
6831
7062
  const streamKey = useRef(`${currentMode}_${activeConversationId}_${JSON.stringify(botData.inputBody)}`).current;
6832
7063
  // Look up existing stream state from the Map (persists across tab-switch remounts)
@@ -7065,6 +7296,7 @@ const StreamedContent = ({ botData }) => {
7065
7296
  setStepChange((prev) => !prev);
7066
7297
  }
7067
7298
  else if (data.status === "step_form") {
7299
+ showTabNotification();
7068
7300
  const formWidgetData = isArray(data.widget_data)
7069
7301
  ? data.widget_data
7070
7302
  : [data.widget_data];
@@ -7258,7 +7490,8 @@ const StreamedContent = ({ botData }) => {
7258
7490
  * Parses the accumulated response and updates the chat history
7259
7491
  */
7260
7492
  useEffect(() => {
7261
- if (isStreamingDone) {
7493
+ if (isStreamingDone && !streamingDoneProcessedRef.current) {
7494
+ streamingDoneProcessedRef.current = true;
7262
7495
  localStorage.setItem("isStreaming", "false");
7263
7496
  if (currentMode === "agent") {
7264
7497
  setIsStop(false);
@@ -9611,7 +9844,7 @@ const useMentionState = () => {
9611
9844
  };
9612
9845
 
9613
9846
  const ChatbotInput = (props) => {
9614
- const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, } = props;
9847
+ const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, answerMode, setAnswerMode, } = props;
9615
9848
  const editorRef = useRef(null);
9616
9849
  const selectRef = useRef(null);
9617
9850
  const filterSetSelectRef = useRef(null);
@@ -9621,6 +9854,8 @@ const ChatbotInput = (props) => {
9621
9854
  const chatInputContainerRef = useRef(null);
9622
9855
  const [isFixed, setIsFixed] = useState(false);
9623
9856
  const [height, setHeight] = useState("auto");
9857
+ const [showAnswerModeMenu, setShowAnswerModeMenu] = useState(false);
9858
+ const answerModeRef = useRef(null);
9624
9859
  const [hasMentionsInEditor, setHasMentionsInEditor] = useState(false);
9625
9860
  const isInsertingMentionRef = useRef(false);
9626
9861
  const isTransitioningStageRef = useRef(false);
@@ -10621,44 +10856,9 @@ const ChatbotInput = (props) => {
10621
10856
  // If a saved filter set is selected, merge its filters into userExplicitInput
10622
10857
  // and textWithColumnNames in the same format as @ mentions
10623
10858
  if (selectedFilterSet?.saved_filter_preference) {
10624
- selectedFilterSet.saved_filter_preference.forEach((filter) => {
10625
- const attrName = filter.attribute_name;
10626
- if (!attrName)
10627
- return;
10628
- // Extract all values from the filter's values array
10629
- let filterValues = [];
10630
- if (Array.isArray(filter.values)) {
10631
- filter.values.forEach((v) => {
10632
- if (v && Array.isArray(v.values)) {
10633
- filterValues.push(...v.values.map(String));
10634
- }
10635
- else if (typeof v === "string" || typeof v === "number") {
10636
- filterValues.push(String(v));
10637
- }
10638
- });
10639
- }
10640
- if (filterValues.length > 0) {
10641
- // Merge into userExplicitInput (combine with existing @ mention values if any)
10642
- if (userExplicitInput[attrName]) {
10643
- userExplicitInput[attrName] = [
10644
- ...new Set([...userExplicitInput[attrName], ...filterValues]),
10645
- ];
10646
- }
10647
- else {
10648
- userExplicitInput[attrName] = [...new Set(filterValues)];
10649
- }
10650
- // Build textWithColumnNames prefix from saved filter data
10651
- const filterText = `${attrName}: ${filterValues.join(", ")}`;
10652
- textWithColumnNames = textWithColumnNames
10653
- ? `${filterText} ${textWithColumnNames}`
10654
- : `${filterText} ${formattedText}`;
10655
- }
10656
- });
10657
- // If textWithColumnNames was not set by mentions but was set by saved filters,
10658
- // ensure it ends with the user's text
10659
- if (!textWithColumnNames.includes(formattedText) && formattedText.trim()) {
10660
- textWithColumnNames = `${textWithColumnNames} ${formattedText}`.trim();
10661
- }
10859
+ const filterData = extractSavedFilterData(selectedFilterSet, formattedText, userExplicitInput);
10860
+ Object.assign(userExplicitInput, filterData.userExplicitInput);
10861
+ textWithColumnNames = filterData.textWithColumnNames || textWithColumnNames;
10662
10862
  }
10663
10863
  setInputValue("");
10664
10864
  if (editorRef.current) {
@@ -10918,6 +11118,25 @@ const ChatbotInput = (props) => {
10918
11118
  document.removeEventListener("mousedown", handleClickOutside);
10919
11119
  };
10920
11120
  }, [showFilterSetMenu]);
11121
+ // Click outside handler for answer mode dropdown
11122
+ useEffect(() => {
11123
+ const handleClickOutside = (event) => {
11124
+ if (answerModeRef.current && !answerModeRef.current.contains(event.target)) {
11125
+ setShowAnswerModeMenu(false);
11126
+ }
11127
+ };
11128
+ if (showAnswerModeMenu) {
11129
+ document.addEventListener("mousedown", handleClickOutside);
11130
+ }
11131
+ return () => {
11132
+ document.removeEventListener("mousedown", handleClickOutside);
11133
+ };
11134
+ }, [showAnswerModeMenu]);
11135
+ const ANSWER_MODE_OPTIONS = [
11136
+ { value: "fast", label: "Fast", description: "Speed over depth" },
11137
+ { value: "auto", label: "Auto", description: "Adapts depth, detail, and visuals" },
11138
+ ];
11139
+ const selectedModeOption = ANSWER_MODE_OPTIONS.find((opt) => opt.value === answerMode) || ANSWER_MODE_OPTIONS[1];
10921
11140
  return (jsx("div", { className: "chat-input-container", ref: chatInputContainerRef, onClick: (e) => {
10922
11141
  // Focus editor when clicking anywhere in the input container
10923
11142
  // unless clicking on a button or interactive element
@@ -10928,7 +11147,8 @@ const ChatbotInput = (props) => {
10928
11147
  !target.closest(".chat-actions") &&
10929
11148
  !target.closest(".filter-set-trigger-wrapper") &&
10930
11149
  !target.closest(".filter-set-chip-clear") &&
10931
- !target.closest(".mention-select-wrapper")) {
11150
+ !target.closest(".mention-select-wrapper") &&
11151
+ !target.closest(".answer-mode-wrapper")) {
10932
11152
  editorRef.current.focus();
10933
11153
  }
10934
11154
  }, children: 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: [jsxs("div", { className: "chat-input-left-actions", children: [jsxs("div", { className: "filter-set-trigger-wrapper", ref: filterSetSelectRef, children: [jsx(Tooltip, { title: hasMentionsInEditor || showMentionSelect ? "Cannot use filter set while @ mentions are active" : "Add filter set", children: jsx("button", { type: "button", className: `filter-set-plus-btn${hasMentionsInEditor || showMentionSelect ? " disabled" : ""}`, onClick: () => {
@@ -10958,7 +11178,10 @@ const ChatbotInput = (props) => {
10958
11178
  handleSendMessage();
10959
11179
  }
10960
11180
  }
10961
- }, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsx(Button, { icon: jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsx(Button, { icon: jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsx(Tooltip, { title: "Save Chat", children: jsx(Button, { icon: jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsx(Button, { icon: !isStopIcon ? jsx(SvgChatBotSendIcon, {}) : jsx(SvgChatbotStopIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "primary", onClick: () => {
11181
+ }, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsx(Button, { icon: jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsx(Button, { icon: jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsx(Tooltip, { title: "Save Chat", children: jsx(Button, { icon: jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsxs("div", { className: "answer-mode-wrapper", ref: answerModeRef, children: [jsxs("button", { type: "button", className: "answer-mode-trigger", onClick: () => setShowAnswerModeMenu(!showAnswerModeMenu), children: [jsx("span", { className: "answer-mode-trigger-label", children: selectedModeOption.label }), jsx("svg", { className: `answer-mode-trigger-chevron ${showAnswerModeMenu ? "open" : ""}`, width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: jsx("path", { d: "M3 7.5L6 4.5L9 7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), showAnswerModeMenu && (jsx("div", { className: "answer-mode-dropdown", children: ANSWER_MODE_OPTIONS.map((option) => (jsxs("button", { type: "button", className: `answer-mode-option ${answerMode === option.value ? "selected" : ""}`, onClick: () => {
11182
+ setAnswerMode(option.value);
11183
+ setShowAnswerModeMenu(false);
11184
+ }, children: [jsx("div", { className: "answer-mode-option-check", children: answerMode === option.value && (jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: jsx("path", { d: "M2.5 7L5.5 10L11.5 4", stroke: "#5C6BC0", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })) }), jsxs("div", { className: "answer-mode-option-content", children: [jsx("span", { className: "answer-mode-option-label", children: option.label }), jsx("span", { className: "answer-mode-option-desc", children: option.description })] })] }, option.value))) }))] }), jsx(Button, { icon: !isStopIcon ? jsx(SvgChatBotSendIcon, {}) : jsx(SvgChatbotStopIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "primary", onClick: () => {
10962
11185
  !isStopIcon ? handleSendMessage() : onStopIconClick();
10963
11186
  }, id: "chat-input-send-button", className: isStopIcon ? "stop-icon-button" : "" })] }), showMentionSelect && (jsx("div", { className: "mention-select-wrapper", ref: selectRef, style: {
10964
11187
  position: "fixed",
@@ -11889,6 +12112,7 @@ const SmartBot = (props) => {
11889
12112
  const [filterOptions, setFilterOptions] = useState([]);
11890
12113
  const [savedFilterSets, setSavedFilterSets$1] = useState([]);
11891
12114
  const [selectedFilterSet, setSelectedFilterSet] = useState(null);
12115
+ const [answerMode, setAnswerMode] = useState("auto");
11892
12116
  const [chatBotWidth, setChatBotWidth] = useState(null);
11893
12117
  useRef(0);
11894
12118
  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);
@@ -12366,10 +12590,11 @@ const SmartBot = (props) => {
12366
12590
  let data = {
12367
12591
  agentId: currentAgentId,
12368
12592
  userInput: cloneDeep(userInput),
12369
- sessionId: currentSessionId,
12593
+ sessionId: isEmpty$1(userInput) ? currentSessionId : "",
12370
12594
  baseUrl: baseUrl,
12371
12595
  userExplicitInput: userExplicitInput,
12372
12596
  textWithColumnNames: textWithColumnNames,
12597
+ answerMode: answerMode,
12373
12598
  };
12374
12599
  // if(!isEmpty(userInput)) {
12375
12600
  dispatch(setThinkingContext({
@@ -12403,6 +12628,13 @@ const SmartBot = (props) => {
12403
12628
  // Reset step form stream state so old TabularContent instances don't process new data
12404
12629
  dispatch(setStepFormStreamData(null));
12405
12630
  resetActiveTabularInstance();
12631
+ // Reset stepFormStreamControl so stale session_id doesn't leak into new prompts
12632
+ stepFormStreamControl.sessionId = "";
12633
+ stepFormStreamControl.chatId = "";
12634
+ stepFormStreamControl.initValue = false;
12635
+ stepFormStreamControl.uniqueChatId = "";
12636
+ sessionStorage.removeItem("stepForm_sessionId");
12637
+ sessionStorage.removeItem("stepForm_chatId");
12406
12638
  // dispatch(setChatbotContext({}));
12407
12639
  setUserInput(params?.text);
12408
12640
  handleSendMessage(params?.text, params?.userExplicitInput, params?.textWithColumnNames);
@@ -12552,7 +12784,9 @@ const SmartBot = (props) => {
12552
12784
  }
12553
12785
  fetchConversations(null, "agent");
12554
12786
  }, [renameConversation, deleteConversation, fetchConversations]);
12555
- return (jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsx(ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (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 ? jsx(Fragment, {}) : null, isChatBotOpen: showModal || forceOpen, historyPanelData: historyPanelData, onHistorySearchChange: (params) => { console.log("History Search Change", params); }, onHistorySelectConversation: (params) => {
12787
+ return (jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsx(ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (jsx(ChatbotInput, { newChatScreen: newChatScreen, inputValue: userInput, setInputValue: setUserInput, isStopIcon: isStop, onSendIconClick: onSendIconClick, onStopIconClick: onStopIconClick, currentMode: currentMode, filterOptions: filterOptions,
12788
+ // onSaveClick={saveCurrentChat}
12789
+ savedFilterSets: savedFilterSets, selectedFilterSet: selectedFilterSet, onFilterSetSelect: (filterSet) => setSelectedFilterSet(filterSet), onClearFilterSet: () => setSelectedFilterSet(null), onTriggerRefresh: triggerRefreshAction, answerMode: answerMode, setAnswerMode: setAnswerMode })) : showSavedFilters ? jsx(Fragment, {}) : null, isChatBotOpen: showModal || forceOpen, historyPanelData: historyPanelData, onHistorySearchChange: (params) => { console.log("History Search Change", params); }, onHistorySelectConversation: (params) => {
12556
12790
  console.log("History Select Conversation", params);
12557
12791
  setNewChatScreen(false);
12558
12792
  setShowChatPlaceholder(false);
@@ -12761,7 +12995,7 @@ const SmartBot = (props) => {
12761
12995
  icon: jsx(SvgSaveFilterTab, {}),
12762
12996
  },
12763
12997
  ], utilityList: utilityList, isAssistantThinking: false, isCustomScreen: showChatPlaceholder ? showChatPlaceholder : showSavedFilters, customScreenJsx: showChatPlaceholder ?
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 })
12998
+ 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 })
12765
12999
  :
12766
13000
  jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose, chatBotWidth: chatBotWidth }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
12767
13001
  freeTextHeading: "Try adding more details :",