import { useState, useEffect, memo } from 'react'; import { CheckCircle, ChevronRight, ChevronDown, Clock, Loader, Loader2, XCircle, Copy, Check, Brain, Maximize2, Download, File, FileText, Image, Music, Video, X, } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import type { ChatMessage, Attachment, TaskToolResult } from '../../types/protocol'; import { ToolDetailModal } from './ToolDetailModal'; // 状态图标组件 function StatusIcon({ status, size = 14, }: { status: string; size?: number; }) { const iconClass = `transition-all duration-300`; switch (status) { case 'calling': case 'running': return ( ); case 'result': case 'success': case 'completed': return ( ); case 'failed': return ( ); case 'timeout': return ( ); case 'pending': case 'interrupted': case 'cancelled': return ( ); default: return null; } } interface MessageBubbleProps { message: ChatMessage; onNavigateToSubAgent?: (taskId: string, description: string, subagentType?: string) => void; showThinking?: boolean; /** 主代理当前生效模型(Task 卡片差异显示:子代理模型不同才展示模型徽章) */ effectiveModel?: { provider: string; model: string } | null; } function getAttachmentIcon(mediaType: string) { switch (mediaType) { case 'image': return ; case 'audio': return ; case 'video': return