import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { useState, useMemo } from 'react'; import { cn } from "@/lib/utils"; import { Message } from "@/hooks/use-chat"; import { Bot, User } from "lucide-react"; import { markdownRenderers } from "./markdown-renderers"; import { MessageActions } from "./message-actions"; import { MessageBackground } from "./message-background"; import { MessageStepThinking } from "./message-step-thinking"; import type { ThinkingMessageMetadata } from "@/hooks/use-chat"; interface ChatMessageProps { message: Message; isStreaming?: boolean; } export function ChatMessage({ message, isStreaming = false }: ChatMessageProps) { // Verificar se é mensagem de processo de pensamento const isThinkingMessage = message.metadata && typeof message.metadata === 'object' && 'type' in message.metadata && message.metadata.type === 'thinking'; if (isThinkingMessage) { return ; } const isUser = message.role === 'user'; const [selected, setSelected] = useState(false); const isEmpty = !message.content || message.content.trim() === ''; // Memoizar processamento de conteúdo const processedContent = useMemo(() => { let content = message.content || ''; // Remove metadata tags content = content.replace(/[\s\S]*?<\/metadata>/gi, '').trim(); // Also remove common prefixes const prefixes = [ 'Bloco oculto de metadados:', 'Metadata:', 'Metadados:', 'Hidden metadata block:', 'JSON metadata:', '---' ]; for (const prefix of prefixes) { const regex = new RegExp(`${prefix}\\s*$`, 'i'); if (regex.test(content)) { content = content.replace(regex, '').trim(); } } return content || message.content; }, [message.content]); return ( setSelected((v) => !v)} tabIndex={0} >
{isUser ? : }
{isUser ? ( // Estilo específico para mensagem do usuário (mais destaque, fonte maior)
{processedContent}
) : ( // Estilo Assistant isEmpty && isStreaming ? (
Gerando resposta...
) : (
{processedContent} {isStreaming && !isEmpty && ( )}
) )}
{!isUser && !isStreaming && (
)} ); }