'use client'; import { useState } from 'react'; import { Copy, ThumbsUp, ThumbsDown, RefreshCw, ChevronDown, ChevronUp, Brain, Loader2, AlertCircle, Check } from 'lucide-react'; import { Avatar } from '@/components/ui/Avatar'; import { AILogo } from '@/components/ui/AILogo'; import { MarkdownRenderer } from '@/components/markdown/MarkdownRenderer'; import { CodeExecutionResult, PyodideLoading } from '@/components/features/CodeExecutionResult'; import { cn } from '@/lib/utils'; import type { Message, User, ToolResult } from '@/types'; interface MessageBubbleProps { message: Message; user?: User; thinkingContent?: string; isStreaming?: boolean; error?: string; /** 代码执行产生的图片(Base64) */ images?: string[]; /** Pyodide 加载状态 */ pyodideStatus?: { stage: 'loading' | 'ready' | 'error'; message: string; progress?: number; }; } export function MessageBubble({ message, user, thinkingContent, isStreaming, error, images, pyodideStatus }: MessageBubbleProps) { const isUser = message.role === 'user'; const [thinkingExpanded, setThinkingExpanded] = useState(false); const [copied, setCopied] = useState(false); // 复制消息内容 const handleCopy = async () => { try { await navigator.clipboard.writeText(message.content); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (error) { console.error('Failed to copy:', error); } }; if (isUser) { return (
{thinkingContent}