'use client' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism' import { Copy, Check, User, Bot, Code2, Bug, Zap, Brain, Plug, Rocket, Workflow, Terminal, Palette } from 'lucide-react' import { useState } from 'react' import type { Message, AgentName } from '@/hooks/useAgentStore' import { formatDistanceToNow } from 'date-fns' const AGENT_META: Record = { chat: { icon: Bot, color: '#22d3ee', label: 'Chat' }, planner: { icon: Zap, color: '#a78bfa', label: 'Planner' }, coding: { icon: Code2, color: '#34d399', label: 'Coding' }, debug: { icon: Bug, color: '#f87171', label: 'Debug' }, memory: { icon: Brain, color: '#fbbf24', label: 'Memory' }, connector: { icon: Plug, color: '#60a5fa', label: 'Connector' }, deploy: { icon: Rocket, color: '#f472b6', label: 'Deploy' }, workflow: { icon: Workflow, color: '#fb923c', label: 'Workflow' }, sandbox: { icon: Terminal, color: '#4ade80', label: 'Sandbox' }, ui: { icon: Palette, color: '#e879f9', label: 'UI' }, } function CopyButton({ text }: { text: string }) { const [copied, setCopied] = useState(false) return ( ) } export default function MessageBubble({ message }: { message: Message }) { const isUser = message.role === 'user' const agentMeta = message.agent ? AGENT_META[message.agent] : AGENT_META['chat'] const AgentIcon = agentMeta?.icon || Bot return (
{/* Avatar */}
{isUser ? (
) : (
)}
{/* Content */}
{/* Header */} {!isUser && (
{message.agent && ( {agentMeta.label}Agent )} {formatDistanceToNow(message.timestamp, { addSuffix: true })}
)} {/* Bubble */}
{isUser ? (

{message.content}

) : (
{message.streaming && !message.content ? (
{[0, 1, 2].map(i => (
))}
) : (
{match[1]}
{code}
) } return ( {children} ) }, }} > {message.content} )} {message.streaming && message.content && ( )}
)}
{/* Metadata badges */} {message.metadata?.task_id && (
{message.metadata.task_id}
)}
) }