import { Button, Dropdown, Space, Tag, Tooltip, Avatar, Divider } from 'antd'; import { useMemo, useState } from 'react'; import { CopyOutlined, SyncOutlined } from '@ant-design/icons'; import dayjs from 'dayjs'; import type { BranchInfo, ChatMessage } from '../../../../api'; import type { Agent } from '../../../../api/agents'; import Markdown from '../../../../components/Markdown'; import { formatMessageContent } from '../../utils/format'; import type { CopyMode } from '../../utils/copy'; import { ReasoningView, RetrievedView, ToolCallView } from './MetaViews'; import './MessageItem.css'; export default function MessageItem(props: { message: ChatMessage; agentList: Agent[]; currentAgentId: string; highlighted?: boolean; branch?: BranchInfo; busy?: boolean; onRegenerate?: (id: string) => void; onSwitchBranch?: (userMsgId: string, branchId: string) => void; onCopy?: (text: string, mode: CopyMode) => void; isMobile?: boolean; }) { const { message, agentList, currentAgentId, highlighted, branch, busy, onRegenerate, onSwitchBranch, onCopy, isMobile } = props; const [reasoningExpanded, setReasoningExpanded] = useState(false); const formattedContent = useMemo(() => formatMessageContent(message.content), [message.content]); const speakerType = (message as any)?.speaker?.type as ('user' | 'agent' | undefined); const speakerId = (message as any)?.speaker?.id as string | undefined; const isUser = speakerType ? speakerType === 'user' : message.role === 'user'; const bubbleRole = isUser ? 'user' : 'assistant'; // 获取回答者 Agent 信息 const answerAgentId = !isUser ? (speakerType === 'agent' ? speakerId : undefined) || message.agent_id || currentAgentId : undefined; const answerAgent = answerAgentId ? agentList.find(a => a.id === answerAgentId) : undefined; const hasBranches = !!branch && branch.total > 1; const activeIdx = branch?.activeIndex ?? 0; const total = branch?.total ?? 1; const timeStr = useMemo(() => { if (!message.createdAt) return ''; return dayjs(message.createdAt * 1000).format('HH:mm'); }, [message.createdAt]); const goPrev = () => { if (!branch || !message.parentId) return; const i = Math.max(0, activeIdx - 1); onSwitchBranch?.(message.parentId, branch.ids[i]); }; const goNext = () => { if (!branch || !message.parentId) return; const i = Math.min(total - 1, activeIdx + 1); onSwitchBranch?.(message.parentId, branch.ids[i]); }; return (