MCPcopy Create free account
hub / github.com/microsoft/data-formulator / DataLoadingChat

Function DataLoadingChat

src/views/DataLoadingChat.tsx:609–1096  ·  view source on GitHub ↗
({
    initialPrompt,
    initialImages,
    autoSendInitialPrompt,
})

Source from the content-addressed store, hash-verified

607}
608
609export const DataLoadingChat: React.FC<DataLoadingChatProps> = ({
610 initialPrompt,
611 initialImages,
612 autoSendInitialPrompt,
613}) => {
614 const theme = useTheme();
615 const { t } = useTranslation();
616 const dispatch = useDispatch<AppDispatch>();
617
618 const chatMessages = useSelector((state: DataFormulatorState) => state.dataLoadingChatMessages);
619 const chatInProgress = useSelector((state: DataFormulatorState) => state.dataLoadingChatInProgress);
620 // External reset signal — bumped by `clearChatMessages` (manual reset
621 // button, new menu-level query, full session reset). When it changes
622 // we abort any in-flight stream, drop partial UI state, and re-seed
623 // from props if the parent provided a new prompt/images. Without
624 // this, an in-flight stream's eventual dispatches would leak into
625 // the freshly-cleared thread.
626 const chatResetCounter = useSelector((state: DataFormulatorState) => state.dataLoadingChatResetCounter ?? 0);
627 const existingTables = useSelector((state: DataFormulatorState) => state.tables);
628 const activeModel = useSelector(dfSelectors.getActiveModel);
629 const frontendRowLimit = useSelector((state: DataFormulatorState) => state.config?.frontendRowLimit ?? 2_000_000);
630 const existingNames = new Set(existingTables.map(tbl => tbl.id));
631
632 const [prompt, setPrompt] = useState('');
633 const [userImages, setUserImages] = useState<string[]>([]);
634 const [userAttachments, setUserAttachments] = useState<string[]>([]);
635 const [streamingContent, setStreamingContent] = useState('');
636 const [streamingToolSteps, setStreamingToolSteps] = useState<ToolStep[]>([]);
637 const [debugEvents, setDebugEvents] = useState<any[]>([]);
638 const [showDebugPanel] = useState(false);
639 const abortControllerRef = useRef<AbortController | null>(null);
640 // Monotonic session token. Bumped on every external reset; the
641 // currently-running `sendMessage` captures the value at the time
642 // it started and discards any state/dispatch updates if the token
643 // has moved on (i.e. the user reset / restarted the chat mid-stream).
644 const sessionRef = useRef(0);
645 const lastResetRef = useRef(chatResetCounter);
646 const messagesEndRef = useRef<HTMLDivElement>(null);
647 const inputRef = useRef<HTMLTextAreaElement>(null);
648
649 // Auto-scroll to bottom
650 useEffect(() => {
651 messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
652 }, [chatMessages, streamingContent]);
653
654 // Auto-focus input
655 useEffect(() => { inputRef.current?.focus(); }, []);
656
657 // ---- External initial prompt handling -------------------------------
658 // Pre-fill the input (and optionally auto-send) when `initialPrompt`
659 // is provided. Used by external surfaces (e.g. landing-page quick chat
660 // box) to hand off text to the agent. Auto-send only fires for a
661 // fresh conversation — we never auto-resend on remount mid-chat.
662 const hasExistingMessages = chatMessages.length > 0;
663 const [pendingAutoSend, setPendingAutoSend] = useState(false);
664 useEffect(() => {
665 // Detect external reset: abort, invalidate in-flight session,
666 // and clear all local UI state before re-seeding. Including

Callers

nothing calls this directly

Calls 8

streamRequestFunction · 0.90
getUrlsFunction · 0.90
apiRequestFunction · 0.90
isCurrentFunction · 0.85
processActionsFunction · 0.85
filterMethod · 0.80
logMethod · 0.45

Tested by

no test coverage detected