import { memo, Suspense, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { DelayedRender } from '@librechat/client'; import type { TMessage } from 'librechat-data-provider'; import type { TMessageContentProps, TDisplayProps } from '~/common'; import Error from '~/components/Messages/Content/Error'; import { useMessageContext } from '~/Providers'; import MarkdownLite from './MarkdownLite'; import EditMessage from './EditMessage'; import Thinking from './Parts/Thinking'; import { useLocalize } from '~/hooks'; import Container from './Container'; import Markdown from './Markdown'; import { cn } from '~/utils'; import store from '~/store'; const ERROR_CONNECTION_TEXT = 'Error connecting to server, try refreshing the page.'; const DELAYED_ERROR_TIMEOUT = 5500; const UNFINISHED_DELAY = 250; const parseThinkingContent = (text: string) => { const thinkingMatch = text.match(/:::thinking([\s\S]*?):::/); return { thinkingContent: thinkingMatch ? thinkingMatch[1].trim() : '', regularContent: thinkingMatch ? text.replace(/:::thinking[\s\S]*?:::/, '').trim() : text, }; }; const LoadingFallback = () => (

); const ErrorBox = ({ children, className = '', }: { children: React.ReactNode; className?: string; }) => (
{children}
); const ConnectionError = ({ message }: { message?: TMessage }) => { const localize = useLocalize(); return ( }>
{localize('com_ui_error_connection')}
); }; export const ErrorMessage = ({ text, message, className = '', }: Pick & { message?: TMessage }) => { if (text === ERROR_CONNECTION_TEXT) { return ; } return ( ); }; const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplayProps) => { const { isSubmitting = false, isLatestMessage = false } = useMessageContext(); const enableUserMsgMarkdown = useRecoilValue(store.enableUserMsgMarkdown); const showCursorState = useMemo( () => showCursor === true && isSubmitting, [showCursor, isSubmitting], ); const content = useMemo(() => { if (!isCreatedByUser) { return ; } if (enableUserMsgMarkdown) { return ; } return <>{text}; }, [isCreatedByUser, enableUserMsgMarkdown, text, isLatestMessage]); return (
0 && 'result-streaming', isCreatedByUser && !enableUserMsgMarkdown && 'whitespace-pre-wrap', isCreatedByUser ? 'dark:text-gray-20' : 'dark:text-gray-100', )} > {content}
); }; export const UnfinishedMessage = ({ message }: { message: TMessage }) => ( ); const MessageContent = ({ text, edit, error, unfinished, isSubmitting, isLast, ...props }: TMessageContentProps) => { const { message } = props; const { messageId } = message; const { thinkingContent, regularContent } = useMemo(() => parseThinkingContent(text), [text]); const showRegularCursor = useMemo(() => isLast && isSubmitting, [isLast, isSubmitting]); const unfinishedMessage = useMemo( () => !isSubmitting && unfinished ? ( ) : null, [isSubmitting, unfinished, message], ); if (error) { return ; } if (edit) { return ; } return ( <> {thinkingContent.length > 0 && ( {thinkingContent} )} {unfinishedMessage} ); }; export default memo(MessageContent);