import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useRef, useEffect } from 'react'; import { MdSend, MdRefresh } from 'react-icons/md'; import { FiCpu, FiInfo } from 'react-icons/fi'; import { v4 as uuidv4 } from 'uuid'; import { toast } from "react-toastify"; import classNames from "classnames"; import ChatMessageComponent from './ChatMessage'; import { defaultHTML } from "../../utils/consts"; const ChatInterface = ({ agentId, html, setHtml, isAiWorking, setisAiWorking, onNewPrompt, onScrollToBottom, geminiKey, chatgptKey, hfToken }) => { const [prompt, setPrompt] = useState(""); const [messages, setMessages] = useState([]); const chatEndRef = useRef(null); const [latestHtml, setLatestHtml] = useState(html); const [isTyping, setIsTyping] = useState(false); // Efeito para rolar para o final quando novas mensagens chegarem useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); // Função principal para enviar mensagem const send = async () => { if (!prompt.trim() || isAiWorking) return; setisAiWorking(true); onNewPrompt(prompt); // Adiciona mensagem do usuário ao histórico const userMessage = { id: uuidv4(), type: 'user', content: prompt, timestamp: new Date() }; setMessages(prev => [...prev, userMessage]); try { // Registra o contexto atual para o agente orquestrador (opcional) const context = { currentHtml: html !== defaultHTML ? html : "Sem HTML ainda", previousMessages: messages.slice(-5), // Últimas 5 mensagens agentId }; const resp = await fetch(`/api/agent/${agentId}/message`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ prompt, html: html === defaultHTML ? undefined : html, gemini_api_key: geminiKey, chatgpt_api_key: chatgptKey, hf_token: hfToken, provider: "auto", context: JSON.stringify(context) // Enviando contexto para o servidor }), }); const reader = resp.body?.getReader(); const dec = new TextDecoder("utf-8"); let partial = ""; let agentReply = { id: uuidv4(), type: 'agent', content: '', agentId, timestamp: new Date() }; // Adiciona a mensagem vazia inicial do agente setMessages(prev => [...prev, agentReply]); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = dec.decode(value); // Processa os logs separadamente const lines = chunk.split('\n'); for (const line of lines) { if (line.trim().startsWith('[LOG]')) { // Adiciona logs como mensagens de tipo log const logMessage = { id: uuidv4(), type: 'log', content: line.replace('[LOG] ', ''), timestamp: new Date() }; setMessages(prev => [...prev, logMessage]); } else if (line.trim().startsWith('❌')) { // Adiciona erros como mensagens de tipo error const errorMessage = { id: uuidv4(), type: 'error', content: line, timestamp: new Date() }; setMessages(prev => [...prev, errorMessage]); } else if (line.trim()) { // Atualiza o conteúdo da resposta do agente partial += line; setMessages(prev => prev.map(msg => msg.id === agentReply.id ? { ...msg, content: partial } : msg)); } } if (partial.length > 200) onScrollToBottom(); // Se é um HTML válido, atualiza o editor if (partial.includes("")) { setLatestHtml(partial); setHtml(partial); } } } catch (e) { toast.error(e.message); // Adiciona erro como mensagem const errorMessage = { id: uuidv4(), type: 'error', content: e.message, timestamp: new Date() }; setMessages(prev => [...prev, errorMessage]); } finally { setisAiWorking(false); setPrompt(""); } }; // Função para limpar o chat const clearChat = () => { if (window.confirm("Tem certeza que deseja limpar todas as mensagens?")) { setMessages([]); toast.info("Chat limpo com sucesso"); } }; return (_jsxs("div", { className: "flex flex-col h-full bg-gray-950", children: [_jsxs("div", { className: "bg-gray-900 px-4 py-2 flex justify-between items-center border-b border-gray-800 text-xs text-gray-400", children: [_jsxs("div", { className: "flex items-center", children: [_jsx("span", { className: `w-2 h-2 rounded-full mr-2 ${isAiWorking ? 'bg-green-500 animate-pulse' : 'bg-gray-500'}` }), isAiWorking ? 'Processando...' : 'Pronto'] }), _jsxs("div", { className: "flex space-x-2", children: [_jsx("button", { onClick: clearChat, className: "text-gray-400 hover:text-gray-200 transition-colors", title: "Limpar chat", children: _jsx(MdRefresh, { size: 16 }) }), _jsx("button", { className: "text-gray-400 hover:text-gray-200 transition-colors", title: "Sugest\u00F5es de prompt", children: _jsx(FiInfo, { size: 16 }) })] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [messages.length === 0 ? (_jsxs("div", { className: "h-full flex flex-col items-center justify-center text-gray-500", children: [_jsx(FiCpu, { size: 32, className: "mb-3" }), _jsxs("p", { className: "text-sm", children: ["Inicie uma conversa com o agente ", agentId] }), _jsxs("div", { className: "mt-4 grid grid-cols-2 gap-2", children: [_jsx(SuggestionButton, { onClick: () => setPrompt("Crie um componente de botão com hover effect"), text: "Criar bot\u00E3o com hover" }), _jsx(SuggestionButton, { onClick: () => setPrompt("Crie um formulário de contato responsivo"), text: "Formul\u00E1rio de contato" }), _jsx(SuggestionButton, { onClick: () => setPrompt("Adicione um cabeçalho com menu de navegação"), text: "Cabe\u00E7alho com menu" }), _jsx(SuggestionButton, { onClick: () => setPrompt("Implemente um dark mode toggle"), text: "Dark mode toggle" })] })] })) : (messages.map(message => (_jsx(ChatMessageComponent, { message: message }, message.id)))), _jsx("div", { ref: chatEndRef })] }), _jsxs("div", { className: "bg-gray-900 p-3 border-t border-gray-800", children: [_jsxs("div", { className: "relative", children: [_jsx("textarea", { className: classNames("w-full px-4 py-3 pr-10 bg-gray-800 border border-gray-700 rounded-md resize-none text-gray-200 placeholder-gray-500 focus:outline-none focus:border-indigo-500 transition-colors", { "opacity-70": isAiWorking, }), rows: 2, disabled: isAiWorking, value: prompt, placeholder: `Pergunte algo para ${agentId}...`, onChange: (e) => setPrompt(e.target.value), onKeyDown: (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } } }), _jsx("button", { disabled: isAiWorking || !prompt.trim(), onClick: send, className: classNames("absolute right-3 bottom-3 p-1.5 rounded-full text-white transition-colors", { "bg-indigo-600 hover:bg-indigo-700": prompt.trim() && !isAiWorking, "bg-gray-700 cursor-not-allowed": !prompt.trim() || isAiWorking }), children: _jsx(MdSend, { size: 18 }) })] }), _jsx("div", { className: "text-xs text-gray-500 mt-2 px-2", children: "Pressione Enter para enviar, Shift+Enter para nova linha" })] })] })); }; const SuggestionButton = ({ onClick, text }) => (_jsx("button", { onClick: onClick, className: "px-3 py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded-md text-sm text-left transition-colors", children: text })); export default ChatInterface;