import { memo } from "react"; import { User, Sparkles, AlertTriangle } from "lucide-react"; import { cn } from "@/lib/utils"; import { Reasoning, ReasoningTrigger, ReasoningContent, } from "@/components/ai-elements/reasoning"; import { MarkdownRenderer } from "@/components/MarkdownRenderer"; import { MentionRenderer } from "@/lib/ir/mention-renderer"; import { getProviderIcon } from "./provider-icon"; import { isVisibleToolCall } from "./tool-utils"; import { ToolCallList } from "./tool-call-list"; import { useCodePreview } from "./code-preview-context"; import type { Message } from "./types"; interface MessageBubbleProps { msg: Message; modelProvider?: string; } export const MessageBubble = memo(function MessageBubble({ msg, modelProvider, }: MessageBubbleProps) { const isUser = msg.role === "user"; const { openCodePreview } = useCodePreview(); const hasToolCalls = !isUser && msg.tool_calls && msg.tool_calls.some((tc) => isVisibleToolCall(tc.name)); const isError = !isUser && /^Error:|I encountered an error/i.test(msg.content); return (
{!isUser && }
{/* Reasoning content */} {msg.reasoning_content && ( {msg.reasoning_content} )} {/* Tool calls */} {hasToolCalls && } {/* Message content */}
{isUser ? (
) : isError ? (

Something went wrong

openCodePreview({ ...payload, id: crypto.randomUUID() }) } />
) : ( openCodePreview({ ...payload, id: crypto.randomUUID() }) } /> )}
{isUser && }
); }); function AIAvatar({ providerName }: { providerName?: string }) { const Icon = providerName ? getProviderIcon(providerName) : null; if (Icon) { return ( ); } return ( ); } function UserAvatar() { return ( ); }