import { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import SharedAgentCard from '../agents/SharedAgentCard'; import MessageInput from '../components/MessageInput'; import { useMediaQuery } from '../hooks'; import { selectConversationId, selectSelectedAgent, selectToken, } from '../preferences/preferenceSlice'; import { AppDispatch } from '../store'; import { handleSendFeedback } from './conversationHandlers'; import ConversationMessages from './ConversationMessages'; import { FEEDBACK, Query } from './conversationModels'; import { addQuery, fetchAnswer, resendQuery, selectQueries, selectStatus, setConversation, updateConversationId, updateQuery, } from './conversationSlice'; import { selectCompletedAttachments, clearAttachments, } from '../upload/uploadSlice'; export default function Conversation() { const { t } = useTranslation(); const { isMobile } = useMediaQuery(); const dispatch = useDispatch(); const token = useSelector(selectToken); const queries = useSelector(selectQueries); const status = useSelector(selectStatus); const conversationId = useSelector(selectConversationId); const selectedAgent = useSelector(selectSelectedAgent); const completedAttachments = useSelector(selectCompletedAttachments); const [lastQueryReturnedErr, setLastQueryReturnedErr] = useState(false); const [isShareModalOpen, setShareModalState] = useState(false); const fetchStream = useRef(null); const handleFetchAnswer = useCallback( ({ question, index }: { question: string; index?: number }) => { fetchStream.current = dispatch(fetchAnswer({ question, indx: index })); }, [dispatch, selectedAgent], ); const handleQuestion = useCallback( ({ question, isRetry = false, index = undefined, }: { question: string; isRetry?: boolean; index?: number; }) => { const trimmedQuestion = question.trim(); if (trimmedQuestion === '') return; const filesAttached = completedAttachments .filter((a) => a.id) .map((a) => ({ id: a.id as string, fileName: a.fileName })); if (index !== undefined) { if (!isRetry) dispatch(resendQuery({ index, prompt: trimmedQuestion })); handleFetchAnswer({ question: trimmedQuestion, index }); } else { if (!isRetry) dispatch( addQuery({ prompt: trimmedQuestion, attachments: filesAttached, }), ); handleFetchAnswer({ question: trimmedQuestion, index }); } }, [dispatch, handleFetchAnswer, completedAttachments], ); const handleFeedback = (query: Query, feedback: FEEDBACK, index: number) => { const prevFeedback = query.feedback; dispatch(updateQuery({ index, query: { feedback } })); handleSendFeedback( query.prompt, query.response!, feedback, conversationId as string, index, token, ).catch(() => handleSendFeedback( query.prompt, query.response!, feedback, conversationId as string, index, token, ).catch(() => dispatch(updateQuery({ index, query: { feedback: prevFeedback } })), ), ); }; const handleQuestionSubmission = ( question?: string, updated?: boolean, indx?: number, ) => { if (updated === true) { handleQuestion({ question: question as string, index: indx }); } else if (question && status !== 'loading') { if (lastQueryReturnedErr) { dispatch( updateQuery({ index: queries.length - 1, query: { prompt: question, }, }), ); handleQuestion({ question: question, isRetry: true, }); } else { handleQuestion({ question, }); } } }; const resetConversation = () => { dispatch(setConversation([])); dispatch( updateConversationId({ query: { conversationId: null }, }), ); dispatch(clearAttachments()); }; useEffect(() => { if (queries.length) { queries[queries.length - 1].error && setLastQueryReturnedErr(true); queries[queries.length - 1].response && setLastQueryReturnedErr(false); } }, [queries[queries.length - 1]]); return (
) : undefined } />
{ handleQuestionSubmission(text); }} loading={status === 'loading'} showSourceButton={selectedAgent ? false : true} showToolButton={selectedAgent ? false : true} />

{t('tagline')}

); }