import { useCallback, useEffect, useRef, useState } from 'react'; import { useDropzone } from 'react-dropzone'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import SharedAgentCard from '../agents/SharedAgentCard'; import DragFileUpload from '../assets/DragFileUpload.svg'; import MessageInput from '../components/MessageInput'; import { useMediaQuery } from '../hooks'; import { ActiveState } from '../models/misc'; import { selectConversationId, selectSelectedAgent, selectToken, } from '../preferences/preferenceSlice'; import { AppDispatch } from '../store'; import Upload from '../upload/Upload'; 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 [uploadModalState, setUploadModalState] = useState('INACTIVE'); const [files, setFiles] = useState([]); const [lastQueryReturnedErr, setLastQueryReturnedErr] = useState(false); const [isShareModalOpen, setShareModalState] = useState(false); const [handleDragActive, setHandleDragActive] = useState(false); const fetchStream = useRef(null); const onDrop = useCallback((acceptedFiles: File[]) => { setUploadModalState('ACTIVE'); setFiles(acceptedFiles); setHandleDragActive(false); }, []); const { getRootProps, getInputProps } = useDropzone({ onDrop, noClick: true, multiple: true, onDragEnter: () => { setHandleDragActive(true); }, onDragLeave: () => { setHandleDragActive(false); }, maxSize: 25000000, accept: { 'application/pdf': ['.pdf'], 'text/plain': ['.txt'], 'text/x-rst': ['.rst'], 'text/x-markdown': ['.md'], 'application/zip': ['.zip'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'], 'application/json': ['.json'], 'text/csv': ['.csv'], 'text/html': ['.html'], 'application/epub+zip': ['.epub'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': [ '.xlsx', ], 'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'], }, }); 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: queries[queries.length - 1].prompt, 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')}

{handleDragActive && (
{t('modals.uploadDoc.drag.title')} {t('modals.uploadDoc.drag.description')}
)} {uploadModalState === 'ACTIVE' && ( setUploadModalState('INACTIVE')} > )} ); }