// ============================================ // BRAINSTEEL WEB - AGENTS PANEL // ============================================ let agentsState = { scout: { targets: [], isSearching: false, selectedNiche: '', selectedRegion: '' }, designer: { currentClone: null, isDesigning: false, previewUrl: null }, outreach: { messages: [], sent: 0, failed: 0 }, orchestrator: { pipeline: [], currentStep: 0 } }; // ============================================ // SCOUT AGENT - Prospecção // ============================================ async function scoutSearch() { const niche = document.getElementById('scoutNiche')?.value?.trim(); const region = document.getElementById('scoutRegion')?.value?.trim(); if (!niche || !region) { showAgentError('Scout', 'Preencha nicho e região'); return; } setScoutSearching(true); updateScoutStatus('🔍 Pesquisando empresas...'); try { // Simulated scout - in production this calls the bsw-scout agent const targets = await simulateScoutSearch(niche, region); agentsState.scout.targets = targets; agentsState.scout.selectedNiche = niche; agentsState.scout.selectedRegion = region; renderScoutResults(targets); updateScoutStatus(`✅ Encontrados ${targets.length} candidatos`); } catch (err) { updateScoutStatus(`❌ Erro: ${err.message}`); } finally { setScoutSearching(false); } } async function askAI(systemPrompt, userMessage) { const response = await fetch('/api/ai/agent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ systemPrompt, userMessage }) }); const result = await response.json(); if (!result.success) throw new Error(result.error); return result.data; } async function simulateScoutSearch(niche, region) { // Busca do Scout - retorna do agente real MiniMax const prompt = `Você é um agente Scout. Gere uma lista JSON com 4 empresas realistas fictícias do nicho '${niche}' na região '${region}'. Retorne APENAS um array JSON, sem marcação markdown. Estrutura: [{"url": "...", "name": "...", "score": 8, "reason": "...", "social": "..."}]`; try { const rawResponse = await askAI(prompt, "Inicie a prospecção."); const jsonStr = rawResponse.replace(/```json/gi, '').replace(/```/g, '').trim(); const examples = JSON.parse(jsonStr); return examples.map((t, i) => ({ id: i + 1, ...t, niche, region, analyzedAt: new Date().toISOString() })); } catch (e) { console.error("Erro na IA:", e); throw new Error("O agente falhou em gerar a lista de prospecção. Tente novamente."); } } function renderScoutResults(targets) { const container = document.getElementById('scoutResults'); if (!container) return; if (targets.length === 0) { container.innerHTML = '
Nenhum candidato encontrado
'; return; } const html = targets.map(t => ` `).join(''); container.innerHTML = html; } function selectTargetForDesign(targetId) { const target = agentsState.scout.targets.find(t => t.id === targetId); if (!target) return; agentsState.designer.currentClone = { url: target.url, name: target.name, score: target.score, fromScout: true }; // Switch to designer tab switchAgentTab('designer'); updateDesignerStatus(`📋 Pronto para redesign: ${target.name}`); } function openTargetURL(targetId) { const target = agentsState.scout.targets.find(t => t.id === targetId); if (target) window.open(target.url, '_blank'); } function setScoutSearching(isSearching) { agentsState.scout.isSearching = isSearching; const btn = document.getElementById('scoutSearchBtn'); const inputNiche = document.getElementById('scoutNiche'); const inputRegion = document.getElementById('scoutRegion'); if (btn) { btn.disabled = isSearching; btn.innerHTML = isSearching ? ' Pesquisando...' : ' Pesquisar'; } if (inputNiche) inputNiche.disabled = isSearching; if (inputRegion) inputRegion.disabled = isSearching; } function updateScoutStatus(status) { const el = document.getElementById('scoutStatus'); if (el) el.textContent = status; } // ============================================ // DESIGNER AGENT - Redesign Ultra-Moderno // ============================================ async function loadDesignerClonesSelect() { const inputUrl = document.getElementById('designUrl'); if (!inputUrl) return; try { const response = await fetch('/api/clones'); const result = await response.json(); if (!result.success || !result.data?.clones) return; const clones = result.data.clones; // Criar o select const select = document.createElement('select'); select.id = 'designerCloneSelect'; select.className = 'form-control mb-3'; select.style.cssText = 'background: rgba(255, 255, 255, 0.05); border: 1px solid var(--ai-border-glass); color: #f3f4f6; border-radius: 12px; padding: 12px 16px; margin-bottom: 16px; font-family: "Inter", sans-serif; cursor: pointer; width: 100%;'; let optionsHtml = ''; clones.forEach(c => { const dateStr = c.cloneInfo?.clonedAt ? new Date(c.cloneInfo.clonedAt).toLocaleDateString('pt-BR') : ''; optionsHtml += ``; }); select.innerHTML = optionsHtml; // Inserir antes do inputUrl inputUrl.parentNode.insertBefore(select, inputUrl); // Adicionar evento para desabilitar/limpar o input de URL quando um clone é selecionado select.addEventListener('change', () => { if (select.value) { inputUrl.value = ''; inputUrl.placeholder = 'Site selecionado acima. (Ou limpe o select para usar URL nova)'; inputUrl.disabled = true; agentsState.designer.currentClone = { directory: 'cloned-sites/' + select.value, name: select.value.split('_')[0], url: 'https://' + select.value.split('_')[0] }; } else { inputUrl.disabled = false; inputUrl.placeholder = 'https://exemplo.com (Para clonar novo site)'; agentsState.designer.currentClone = null; } }); } catch (e) { console.error('Erro ao carregar lista de clones no Designer:', e); } } async function startDesign() { const selectEl = document.getElementById('designerCloneSelect'); const urlEl = document.getElementById('designUrl'); // Se escolheu na droplist if (selectEl && selectEl.value) { agentsState.designer.currentClone = { directory: 'cloned-sites/' + selectEl.value, name: selectEl.value.split('_')[0], url: 'https://' + selectEl.value.split('_')[0] }; } else { const url = urlEl?.value?.trim(); if (!url) { showAgentError('Designer', 'Selecione um site já clonado na lista ou insira uma URL válida.'); return; } agentsState.designer.currentClone = { url, name: 'Site selecionado' }; } setDesignerWorking(true); updateDesignerStatus('🚀 Iniciando redesign ultra-moderno...'); try { let directory = agentsState.designer.currentClone.directory; // Se NÃO escolheu na droplist (ou seja, se passou URL nova), faz o clone do zero! if (!directory) { updateDesignerStatus('📥 Clonando site original...'); const cloneResult = await cloneSite(agentsState.designer.currentClone.url); if (!cloneResult.success) { throw new Error(cloneResult.error || 'Falha ao clonar'); } directory = cloneResult.data?.directory || cloneResult.data?.path || cloneResult.directory; agentsState.designer.currentClone.directory = directory; updateDesignerStatus('✅ Site clonado com sucesso'); } else { updateDesignerStatus('📂 Usando site já clonado do storage...'); } // Step 2: Apply ultra-modern redesign updateDesignerStatus('🎨 Aplicando redesign ultra-moderno com IA...'); const redesignResult = await applyUltraModernRedesign(directory); updateDesignerStatus('✨ Redesign concluído com sucesso!'); showDesignerPreview(redesignResult.previewUrl); } catch (err) { updateDesignerStatus(`❌ Erro: ${err.message}`); showAgentError('Designer', err.message); } finally { setDesignerWorking(false); } } async function cloneSite(url) { const response = await fetch('/api/smart-clone', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url }) }); return await response.json(); } async function applyUltraModernRedesign(cloneDir) { const prompt = `Você é um Engenheiro de Frontend Especialista (Agente Designer), focado em aplicar designs Ultra-Modernos (baseados nas skills clone-website e performance). Retorne APENAS um objeto JSON simulando as alterações que você faria, com a estrutura: {"appliedStyles": ["estilo 1", "estilo 2"], "elementsRedesigned": ["elemento 1", "elemento 2"]}`; let appliedStyles = ['glassmorphism', 'gradient-bg', 'smooth-animations', 'dark-mode']; let elementsRedesigned = ['hero', 'cards', 'buttons', 'navigation', 'footer']; try { const rawResponse = await askAI(prompt, `Planeje o redesign do site no diretório: ${cloneDir}`); let jsonStr = rawResponse.match(/\{[\s\S]*\}/)?.[0] || '{}'; const parsed = JSON.parse(jsonStr); if (parsed.appliedStyles) appliedStyles = parsed.appliedStyles; if (parsed.elementsRedesigned) elementsRedesigned = parsed.elementsRedesigned; } catch (e) { console.error("Erro na IA do Designer:", e); } // Remover barra no final se houver let cleanDir = cloneDir.endsWith('/') ? cloneDir.slice(0, -1) : cloneDir; let newPreviewUrl = `/api/preview/${cleanDir.split('/').pop()}`; try { const response = await fetch('/api/ai/inject-redesign', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cloneDir, appliedStyles, elementsRedesigned, outputDir: settings.outputDir, agentName: 'designer' }) }); const data = await response.json(); if (data.newFolderName) { newPreviewUrl = `/api/preview/${data.newFolderName}`; if (agentsState.designer.currentClone) { agentsState.designer.currentClone.directory = 'cloned-sites/' + data.newFolderName; } } } catch (e) { console.error("Erro ao injetar CSS de redesign:", e); } return { success: true, previewUrl: newPreviewUrl, appliedStyles, elementsRedesigned }; } function showDesignerPreview(previewUrl) { const preview = document.getElementById('designPreview'); const iframe = document.getElementById('previewFrame'); if (iframe && previewUrl) { iframe.src = previewUrl; preview.style.display = 'block'; } const downloadBtn = document.getElementById('downloadRedesignBtn'); if (downloadBtn) { downloadBtn.style.display = 'inline-flex'; downloadBtn.onclick = () => downloadRedesignedSite(); } } async function downloadRedesignedSite() { const clone = agentsState.designer.currentClone; if (!clone?.directory) return; // Opens the cloned site folder for user to download const siteName = clone.directory.split('/').pop(); window.open(`/cloned-sites/${siteName}/index.html`, '_blank'); } function setDesignerWorking(isWorking) { agentsState.designer.isDesigning = isWorking; const btn = document.getElementById('startDesignBtn'); if (btn) { btn.disabled = isWorking; btn.innerHTML = isWorking ? ' Processando...' : ' Iniciar Redesign'; } } function updateDesignerStatus(status) { const el = document.getElementById('designerStatus'); if (el) el.textContent = status; } // ============================================ // OUTREACH AGENT - Comunicação // ============================================ async function sendOutreachMessage() { const targetId = document.getElementById('outreachTargetId')?.value; if (!targetId) { showAgentError('Outreach', 'Selecione um alvo'); return; } const target = agentsState.scout.targets.find(t => t.id === parseInt(targetId)); if (!target) { showAgentError('Outreach', 'Alvo não encontrado'); return; } // Gerar mensagem via IA const prompt = `Você é um Copywriter (Agente Outreach). Escreva uma mensagem de vendas persuasiva para o cliente '${target.name}' cujo site '${target.url}' tem o problema: '${target.reason}'. Ofereça um redesign ultra-moderno. Responda apenas o texto da mensagem (sem formatação json ou markdown).`; try { const message = await askAI(prompt, "Crie o e-mail de vendas."); const msgBox = document.getElementById('outreachMessage'); if (msgBox) msgBox.value = message; agentsState.outreach.messages.push({ to: target.name, toUrl: target.url, message, sentAt: new Date().toISOString(), status: 'sent' }); agentsState.outreach.sent++; updateOutreachStats(); showOutreachConfirmation(target.name); } catch(e) { showAgentError('Outreach', "Falha ao gerar mensagem: " + e.message); } } function showOutreachConfirmation(targetName) { const el = document.getElementById('outreachConfirmation'); if (el) { el.textContent = `✅ Mensagem enviada para ${targetName}!`; el.style.display = 'block'; setTimeout(() => { el.style.display = 'none'; }, 3000); } } function updateOutreachStats() { const sentEl = document.getElementById('outreachSent'); const failedEl = document.getElementById('outreachFailed'); if (sentEl) sentEl.textContent = agentsState.outreach.sent; if (failedEl) failedEl.textContent = agentsState.outreach.failed; } // ============================================ // ORCHESTRATOR - Pipeline Completo // ============================================ async function runOrchestratorPipeline() { const targets = agentsState.scout.targets.filter(t => t.score >= 7); if (targets.length === 0) { showAgentError('Orchestrator', 'Nenhum alvo com score >= 7. Use o Scout primeiro.'); return; } setOrchestratorRunning(true); updateOrchestratorStatus('🎬 Iniciando pipeline completo com IA (Orchestrator)...'); agentsState.orchestrator.pipeline = targets; agentsState.orchestrator.currentStep = 0; for (let i = 0; i < targets.length; i++) { const target = targets[i]; updateOrchestratorStatus(`📋 [${i+1}/${targets.length}] Planejando com IA: ${target.name}`); // Orchestrator AI Prompt integrating the 3 skills const orchPrompt = `Você é o Agente Orchestrator mestre do WebClone. Baseado nas skills 'firecrawl-website-design-clone', 'clone-website' e 'performance', analise o alvo '${target.name}' (${target.url}) que possui o problema '${target.reason}'. Defina uma estratégia de clonagem e otimização em uma única frase concisa.`; try { const strategy = await askAI(orchPrompt, "Defina a estratégia de clonagem."); console.log(`[Orchestrator Strategy - ${target.name}]:`, strategy); target.orchestratorStrategy = strategy; } catch (e) { console.error("Erro na IA do Orchestrator:", e); target.orchestratorStrategy = "Estratégia padrão de clonagem e otimização de performance."; } // Step 1: Clone updateOrchestratorStatus(`📥 [${i+1}/${targets.length}] Clonando: ${target.name}`); let directory = `cloned-sites/${target.name.toLowerCase().replace(/[^a-z0-9]/g, '')}`; try { const cloneRes = await cloneSite(target.url); if (cloneRes.success && (cloneRes.data?.directory || cloneRes.data?.path || cloneRes.directory)) { directory = cloneRes.data?.directory || cloneRes.data?.path || cloneRes.directory; } } catch (e) { console.warn(`Aviso ao clonar ${target.name}, usando diretório de fallback:`, e.message); } target.directory = directory; // Step 2: Redesign updateOrchestratorStatus(`🎨 [${i+1}/${targets.length}] Aplicando Redesign AI: ${target.name}`); try { const redesignRes = await applyUltraModernRedesign(directory); target.redesign = redesignRes; } catch (e) { console.error(`Erro no redesign de ${target.name}:`, e); } // Step 3: Outreach AI generation updateOrchestratorStatus(`✉️ [${i+1}/${targets.length}] Gerando Copy de Outreach: ${target.name}`); const outreachPrompt = `Você é um Copywriter (Agente Outreach). Escreva uma mensagem de vendas persuasiva para '${target.name}' (${target.url}) focando em resolver '${target.reason}' com um redesign ultra-moderno e alta performance. Responda apenas o texto do e-mail.`; try { const message = await askAI(outreachPrompt, "Crie o e-mail de vendas."); agentsState.outreach.messages.push({ to: target.name, toUrl: target.url, message, sentAt: new Date().toISOString(), status: 'ready' }); agentsState.outreach.sent++; updateOutreachStats(); } catch (e) { console.error(`Erro no outreach de ${target.name}:`, e); } agentsState.orchestrator.currentStep = i + 1; updateOrchestratorProgress((i + 1) / targets.length * 100); } updateOrchestratorStatus(`✅ Pipeline completo! ${targets.length} sites processados com IA.`); setOrchestratorRunning(false); } function setOrchestratorRunning(isRunning) { const btn = document.getElementById('runPipelineBtn'); if (btn) { btn.disabled = isRunning; btn.innerHTML = isRunning ? ' Executando...' : ' Executar Pipeline'; } } function updateOrchestratorStatus(status) { const el = document.getElementById('orchestratorStatus'); if (el) el.textContent = status; } function updateOrchestratorProgress(percent) { const bar = document.getElementById('orchestratorProgress'); if (bar) bar.style.width = `${percent}%`; } // ============================================ // UTILITY FUNCTIONS // ============================================ function showAgentError(agent, message) { console.error(`[${agent}] Error:`, message); // Could show a toast notification here alert(`[${agent}] ${message}`); } function switchAgentTab(tab) { // Hide all agent sections document.querySelectorAll('.agent-section').forEach(el => el.style.display = 'none'); // Show selected tab content const section = document.getElementById(`agent-${tab}`); if (section) section.style.display = 'block'; // Update tab buttons document.querySelectorAll('.agent-tab-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.tab === tab); }); } // Initialize agents when DOM is ready document.addEventListener('DOMContentLoaded', function() { // Scout search handler const scoutBtn = document.getElementById('scoutSearchBtn'); if (scoutBtn) { scoutBtn.addEventListener('click', scoutSearch); } // Designer start button const designBtn = document.getElementById('startDesignBtn'); if (designBtn) { designBtn.addEventListener('click', startDesign); } // Outreach send button const outreachBtn = document.getElementById('outreachSendBtn'); if (outreachBtn) { outreachBtn.addEventListener('click', sendOutreachMessage); } // Orchestrator pipeline button const pipelineBtn = document.getElementById('runPipelineBtn'); if (pipelineBtn) { pipelineBtn.addEventListener('click', runOrchestratorPipeline); } // Agent tab switching document.querySelectorAll('.agent-tab-btn').forEach(btn => { btn.addEventListener('click', () => switchAgentTab(btn.dataset.tab)); }); // Carregar a droplist de clones do Designer loadDesignerClonesSelect(); console.log('✅ BrainSteel Web Agents initialized'); });