diff --git a/src/components/features/MessageBubble.tsx b/src/components/features/MessageBubble.tsx index 9d922d5..56160cb 100644 --- a/src/components/features/MessageBubble.tsx +++ b/src/components/features/MessageBubble.tsx @@ -5,8 +5,9 @@ import { Copy, ThumbsUp, ThumbsDown, RefreshCw, ChevronDown, ChevronUp, Brain, L 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 } from '@/types'; +import type { Message, User, ToolResult } from '@/types'; interface MessageBubbleProps { message: Message; @@ -14,9 +15,17 @@ interface MessageBubbleProps { 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 }: MessageBubbleProps) { +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); @@ -96,6 +105,34 @@ export function MessageBubble({ message, user, thinkingContent, isStreaming, err ) : null} + {/* 工具调用结果 - 代码执行图片展示 */} + {message.toolResults && message.toolResults.length > 0 && ( +
+ {message.toolResults.map((result, index) => ( + + ))} +
+ )} + + {/* Pyodide 加载状态 */} + {pyodideStatus && ( +
+ +
+ )} + + {/* 代码执行图片(从 props 传入) */} + {images && images.length > 0 && ( + + )} + {/* 流式状态指示器 */} {isStreaming && message.content && (
@@ -149,3 +186,32 @@ function ActionButton({ icon: Icon, title, onClick }: ActionButtonProps) { ); } + +/** + * 工具调用结果显示组件 + * 专门处理代码执行结果和图片显示 + */ +interface ToolResultDisplayProps { + result: ToolResult; +} + +function ToolResultDisplay({ result }: ToolResultDisplayProps) { + // 只有代码执行工具才显示图片 + if (result.toolName !== 'code_execution') { + return null; + } + + // 如果没有图片,不显示 + if (!result.images || result.images.length === 0) { + return null; + } + + return ( + + ); +} diff --git a/src/components/markdown/MarkdownRenderer.tsx b/src/components/markdown/MarkdownRenderer.tsx index 6d12969..c5e24f7 100644 --- a/src/components/markdown/MarkdownRenderer.tsx +++ b/src/components/markdown/MarkdownRenderer.tsx @@ -196,11 +196,11 @@ const markdownComponents = { }, // 图片 - img({ src, alt }: { src?: string; alt?: string }) { + img(props: React.ImgHTMLAttributes) { return ( {alt );