import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; import { MessageType } from '@/constants/chat'; import { useSetModalState } from '@/hooks/common-hooks'; import { IReferenceChunk, IReferenceObject } from '@/interfaces/database/chat'; import classNames from 'classnames'; import { PropsWithChildren, memo, useCallback, useContext, useEffect, useMemo, useState, } from 'react'; import { IRegenerateMessage, IRemoveMessageById } from '@/hooks/logic-hooks'; import { INodeEvent, MessageEventType } from '@/hooks/use-send-message'; import { cn } from '@/lib/utils'; import { AgentChatContext } from '@/pages/agent/context'; import { WorkFlowTimeline } from '@/pages/agent/log-sheet/workflow-timeline'; import { IMessage } from '@/pages/chat/interface'; import { isEmpty } from 'lodash'; import { Atom, ChevronDown, ChevronUp } from 'lucide-react'; import IndentedTreeModal from '../indented-tree/modal'; import MarkdownContent from '../next-markdown-content'; import { RAGFlowAvatar } from '../ragflow-avatar'; import { useTheme } from '../theme-provider'; import { Button } from '../ui/button'; import { AssistantGroupButton, UserGroupButton } from './group-button'; import styles from './index.less'; import { ReferenceDocumentList } from './reference-document-list'; import { UploadedMessageFiles } from './uploaded-message-files'; interface IProps extends Partial, IRegenerateMessage, PropsWithChildren { item: IMessage; conversationId?: string; currentEventListWithoutMessageById?: (messageId: string) => INodeEvent[]; setCurrentMessageId?: (messageId: string) => void; reference?: IReferenceObject; loading?: boolean; sendLoading?: boolean; visibleAvatar?: boolean; nickname?: string; avatar?: string; avatarDialog?: string | null; agentName?: string; clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void; index: number; showLikeButton?: boolean; showLoudspeaker?: boolean; showLog?: boolean; isShare?: boolean; } function MessageItem({ item, conversationId, currentEventListWithoutMessageById, setCurrentMessageId, reference, loading = false, avatar, avatarDialog, agentName, sendLoading = false, clickDocumentButton, removeMessageById, regenerateMessage, showLikeButton = true, showLoudspeaker = true, visibleAvatar = true, children, showLog, isShare, }: IProps) { const { theme } = useTheme(); const isAssistant = item.role === MessageType.Assistant; const isUser = item.role === MessageType.User; const { visible, hideModal } = useSetModalState(); const [clickedDocumentId] = useState(''); const [showThinking, setShowThinking] = useState(false); const { setLastSendLoadingFunc } = useContext(AgentChatContext); useEffect(() => { if (typeof setLastSendLoadingFunc === 'function') { setLastSendLoadingFunc(loading, item.id); } }, [loading, setLastSendLoadingFunc, item.id]); const referenceDocuments = useMemo(() => { const docs = reference?.doc_aggs ?? {}; return Object.values(docs); }, [reference?.doc_aggs]); const handleRegenerateMessage = useCallback(() => { regenerateMessage?.(item); }, [regenerateMessage, item]); useEffect(() => { if (typeof setCurrentMessageId === 'function') { setCurrentMessageId(item.id); } }, [item.id, setCurrentMessageId]); const startedNodeList = useCallback( (item: IMessage) => { const finish = currentEventListWithoutMessageById?.(item.id)?.some( (item) => item.event === MessageEventType.WorkflowFinished, ); return !finish && loading; }, [currentEventListWithoutMessageById, loading], ); return (
{visibleAvatar && (item.role === MessageType.User ? ( ) : avatarDialog || agentName ? ( ) : ( ))}
{isShare && isAssistant && ( )}
{isAssistant ? ( <> {isShare && !sendLoading && !isEmpty(item.content) && ( )} {!isShare && ( )} ) : ( )} {/* {isAssistant ? '' : nickname} */}
{isAssistant && currentEventListWithoutMessageById && showThinking && (
)}
{item.data ? ( children ) : sendLoading && isEmpty(item.content) ? ( <>{!isShare && 'running...'} ) : ( )}
{isAssistant && referenceDocuments.length > 0 && ( )} {isUser && ( )}
{visible && ( )}
); } export default memo(MessageItem);