File size: 4,490 Bytes
20ec4ad 969b550 20ec4ad 8a0e39e 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 8a0e39e 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 969b550 20ec4ad 969b550 20ec4ad |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
import React from 'react';
import { FaRobot } from 'react-icons/fa';
import { FiUser, FiCpu, FiAlertTriangle, FiTerminal, FiInfo } from 'react-icons/fi';
import ReactMarkdown from 'react-markdown';
export type MessageType = 'user' | 'agent' | 'log' | 'error' | 'info';
export interface ChatMessage {
id: string;
type: MessageType;
content: string;
agentId?: string;
timestamp: Date;
}
interface ChatMessageProps {
message: ChatMessage;
}
// Componente para exibir uma única mensagem do chat
const ChatMessageComponent: React.FC<ChatMessageProps> = ({ message }) => {
// Renderiza logs de forma diferente
if (message.type === 'log') {
// Extrai informações do log no formato [Agent:agentId] message
const logMatch = message.content.match(/\[Agent:([^\]]+)\] (.*)/);
if (logMatch) {
const [_, agentId, logContent] = logMatch;
return (
<div className="text-xs text-gray-500 py-1 pl-8 border-l border-gray-700 my-1">
<span className="font-semibold text-gray-400">{agentId}:</span> {logContent}
</div>
);
}
return (
<div className="flex items-start space-x-2 text-xs text-gray-500 py-1">
<FiTerminal className="text-gray-500 mt-0.5 flex-shrink-0" size={12} />
<div>{message.content}</div>
</div>
);
}
// Renderiza erros de forma destacada
if (message.type === 'error') {
return (
<div className="flex items-start space-x-2 my-2 p-2 bg-red-900/20 border-l-2 border-red-500 text-red-400 rounded">
<FiAlertTriangle className="text-red-500 mt-1 flex-shrink-0" />
<div>
<p className="font-semibold text-red-400">Erro:</p>
<p className="text-gray-300">{message.content}</p>
</div>
</div>
);
}
// Renderiza mensagens informativas
if (message.type === 'info') {
return (
<div className="flex items-start space-x-2 my-2 p-2 bg-blue-900/20 border-l-2 border-blue-500 text-blue-400 rounded">
<FiInfo className="text-blue-500 mt-1 flex-shrink-0" />
<div>
<p className="font-semibold text-blue-400">Informação:</p>
<p className="text-gray-300 whitespace-pre-line">{message.content}</p>
</div>
</div>
);
}
// Renderiza mensagem do usuário
if (message.type === 'user') {
return (
<div className="flex items-start space-x-2 my-3">
<div className="bg-indigo-600 text-white p-2 rounded-full flex-shrink-0">
<FiUser />
</div>
<div className="bg-gray-800 p-3 rounded-lg rounded-tl-none max-w-[calc(100%-50px)] text-gray-200">
{message.content}
</div>
</div>
);
}
// Renderiza resposta do agente
const agentColor = getAgentColor(message.agentId || 'default');
return (
<div className="flex items-start space-x-2 my-3">
<div className={`${agentColor} text-white p-2 rounded-full flex-shrink-0`}>
<FiCpu />
</div>
<div className="bg-gray-900 p-3 rounded-lg rounded-tl-none max-w-[calc(100%-50px)] text-gray-200 border border-gray-800">
<MessageContent content={message.content} />
</div>
</div>
);
};
// Função auxiliar para definir cores diferentes para cada agente
const getAgentColor = (agentId: string): string => {
switch (agentId) {
case 'orchestrator':
return 'bg-purple-600';
case 'mike':
return 'bg-blue-600';
case 'alex':
return 'bg-green-600';
case 'david':
return 'bg-amber-600';
default:
return 'bg-indigo-600';
}
};
// Componente para exibir o conteúdo da mensagem com formatação markdown
const MessageContent: React.FC<{ content: string }> = ({ content }) => {
// Verifica se o conteúdo é HTML
if (content.includes('<html') || content.includes('<!DOCTYPE')) {
return (
<div>
<div className="bg-gray-800 p-2 rounded mb-2 text-xs text-green-400">
<FiInfo className="inline mr-1" /> HTML gerado
</div>
<div className="text-gray-300 max-h-80 overflow-y-auto">
{content}
</div>
</div>
);
}
// Tenta renderizar o conteúdo como markdown
try {
return (
<div className="prose prose-invert prose-sm max-w-none">
<ReactMarkdown>{content}</ReactMarkdown>
</div>
);
} catch {
// Se falhar, renderiza como texto normal
return <div className="whitespace-pre-wrap">{content}</div>;
}
};
export default ChatMessageComponent; |