const PipelinesUI = { pipelines: [], agents: [], _editingId: null, _steps: [], _pendingApprovals: new Map(), async load() { try { const [pipelines, agents] = await Promise.all([ API.pipelines.list(), API.agents.list(), ]); PipelinesUI.pipelines = Array.isArray(pipelines) ? pipelines : []; PipelinesUI.agents = Array.isArray(agents) ? agents : []; PipelinesUI.render(); } catch (err) { Toast.error(`Erro ao carregar pipelines: ${err.message}`); } }, filter(searchText) { const search = (searchText || '').toLowerCase(); const filtered = PipelinesUI.pipelines.filter((p) => { const name = (p.name || '').toLowerCase(); const desc = (p.description || '').toLowerCase(); return !search || name.includes(search) || desc.includes(search); }); PipelinesUI.render(filtered); }, render(filteredPipelines) { const grid = document.getElementById('pipelines-grid'); if (!grid) return; const pipelines = filteredPipelines || PipelinesUI.pipelines; const existingCards = grid.querySelectorAll('.pipeline-card'); existingCards.forEach((c) => c.remove()); const emptyState = grid.querySelector('.empty-state'); if (pipelines.length === 0) { if (!emptyState) { grid.insertAdjacentHTML('beforeend', PipelinesUI.renderEmpty()); } if (window.lucide) lucide.createIcons({ nodes: [grid] }); return; } if (emptyState) emptyState.remove(); const fragment = document.createDocumentFragment(); pipelines.forEach((pipeline) => { const wrapper = document.createElement('div'); wrapper.innerHTML = PipelinesUI.renderCard(pipeline); fragment.appendChild(wrapper.firstElementChild); }); grid.appendChild(fragment); if (window.lucide) lucide.createIcons({ nodes: [grid] }); }, renderEmpty() { return `

Nenhum pipeline cadastrado

Crie seu primeiro pipeline para encadear agentes em fluxos automatizados.

`; }, renderCard(pipeline) { const steps = Array.isArray(pipeline.steps) ? pipeline.steps : []; const stepCount = steps.length; const flowHtml = steps.map((step, index) => { const agentName = step.agentName || step.agentId || 'Agente'; const isLast = index === steps.length - 1; const approvalIcon = step.requiresApproval && index > 0 ? ' ' : ''; return ` ${index + 1} ${approvalIcon}${agentName} ${!isLast ? '' : ''} `; }).join(''); return `

${pipeline.name || 'Sem nome'}

${stepCount} ${stepCount === 1 ? 'passo' : 'passos'}
${pipeline.description ? `

${pipeline.description}

` : ''}
${flowHtml || 'Nenhum passo configurado'}
`; }, openCreateModal() { PipelinesUI._editingId = null; PipelinesUI._steps = [ { agentId: '', inputTemplate: '', requiresApproval: false }, { agentId: '', inputTemplate: '', requiresApproval: false }, ]; const titleEl = document.getElementById('pipeline-modal-title'); if (titleEl) titleEl.textContent = 'Novo Pipeline'; const idEl = document.getElementById('pipeline-form-id'); if (idEl) idEl.value = ''; const nameEl = document.getElementById('pipeline-name'); if (nameEl) nameEl.value = ''; const descEl = document.getElementById('pipeline-description'); if (descEl) descEl.value = ''; PipelinesUI.renderSteps(); Modal.open('pipeline-modal-overlay'); }, async openEditModal(pipelineId) { try { const pipeline = await API.pipelines.get(pipelineId); PipelinesUI._editingId = pipelineId; PipelinesUI._steps = Array.isArray(pipeline.steps) ? pipeline.steps.map((s) => ({ agentId: s.agentId || '', inputTemplate: s.inputTemplate || '', requiresApproval: !!s.requiresApproval })) : []; const titleEl = document.getElementById('pipeline-modal-title'); if (titleEl) titleEl.textContent = 'Editar Pipeline'; const idEl = document.getElementById('pipeline-form-id'); if (idEl) idEl.value = pipeline.id; const nameEl = document.getElementById('pipeline-name'); if (nameEl) nameEl.value = pipeline.name || ''; const descEl = document.getElementById('pipeline-description'); if (descEl) descEl.value = pipeline.description || ''; PipelinesUI.renderSteps(); Modal.open('pipeline-modal-overlay'); } catch (err) { Toast.error(`Erro ao carregar pipeline: ${err.message}`); } }, renderSteps() { const container = document.getElementById('pipeline-steps-container'); if (!container) return; if (PipelinesUI._steps.length === 0) { container.innerHTML = ''; return; } const agentOptions = PipelinesUI.agents .map((a) => ``) .join(''); container.innerHTML = PipelinesUI._steps.map((step, index) => { const isFirst = index === 0; const isLast = index === PipelinesUI._steps.length - 1; const connectorHtml = !isLast ? '
' : ''; const approvalChecked = step.requiresApproval ? 'checked' : ''; const approvalHtml = index > 0 ? `` : ''; return `
${index + 1}
${approvalHtml}
${connectorHtml} `; }).join(''); container.querySelectorAll('select[data-step-field="agentId"]').forEach((select) => { const index = parseInt(select.dataset.stepIndex, 10); select.value = PipelinesUI._steps[index].agentId || ''; }); if (window.lucide) lucide.createIcons({ nodes: [container] }); }, _syncStepsFromDOM() { const container = document.getElementById('pipeline-steps-container'); if (!container) return; container.querySelectorAll('[data-step-field]').forEach((el) => { const index = parseInt(el.dataset.stepIndex, 10); const field = el.dataset.stepField; if (PipelinesUI._steps[index] !== undefined) { if (el.type === 'checkbox') { PipelinesUI._steps[index][field] = el.checked; } else { PipelinesUI._steps[index][field] = el.value; } } }); }, addStep() { PipelinesUI._syncStepsFromDOM(); PipelinesUI._steps.push({ agentId: '', inputTemplate: '', requiresApproval: false }); PipelinesUI.renderSteps(); }, removeStep(index) { PipelinesUI._syncStepsFromDOM(); PipelinesUI._steps.splice(index, 1); PipelinesUI.renderSteps(); }, moveStep(index, direction) { PipelinesUI._syncStepsFromDOM(); const targetIndex = index + direction; if (targetIndex < 0 || targetIndex >= PipelinesUI._steps.length) return; const temp = PipelinesUI._steps[index]; PipelinesUI._steps[index] = PipelinesUI._steps[targetIndex]; PipelinesUI._steps[targetIndex] = temp; PipelinesUI.renderSteps(); }, async save() { PipelinesUI._syncStepsFromDOM(); const name = document.getElementById('pipeline-name')?.value.trim(); if (!name) { Toast.warning('Nome do pipeline é obrigatório'); return; } if (PipelinesUI._steps.length < 2) { Toast.warning('O pipeline precisa de pelo menos 2 passos'); return; } const invalidStep = PipelinesUI._steps.find((s) => !s.agentId); if (invalidStep) { Toast.warning('Todos os passos devem ter um agente selecionado'); return; } const data = { name, description: document.getElementById('pipeline-description')?.value.trim() || '', steps: PipelinesUI._steps.map((s) => ({ agentId: s.agentId, inputTemplate: s.inputTemplate || '', requiresApproval: !!s.requiresApproval, })), }; try { if (PipelinesUI._editingId) { await API.pipelines.update(PipelinesUI._editingId, data); Toast.success('Pipeline atualizado com sucesso'); } else { await API.pipelines.create(data); Toast.success('Pipeline criado com sucesso'); } Modal.close('pipeline-modal-overlay'); await PipelinesUI.load(); } catch (err) { Toast.error(`Erro ao salvar pipeline: ${err.message}`); } }, async delete(pipelineId) { const confirmed = await Modal.confirm( 'Excluir pipeline', 'Tem certeza que deseja excluir este pipeline? Esta ação não pode ser desfeita.' ); if (!confirmed) return; try { await API.pipelines.delete(pipelineId); Toast.success('Pipeline excluído com sucesso'); await PipelinesUI.load(); } catch (err) { Toast.error(`Erro ao excluir pipeline: ${err.message}`); } }, execute(pipelineId) { const pipeline = PipelinesUI.pipelines.find((p) => p.id === pipelineId); const titleEl = document.getElementById('pipeline-execute-title'); if (titleEl) titleEl.textContent = `Executar: ${pipeline ? pipeline.name : 'Pipeline'}`; const idEl = document.getElementById('pipeline-execute-id'); if (idEl) idEl.value = pipelineId; const inputEl = document.getElementById('pipeline-execute-input'); if (inputEl) inputEl.value = ''; const workdirEl = document.getElementById('pipeline-execute-workdir'); if (workdirEl) workdirEl.value = ''; Modal.open('pipeline-execute-modal-overlay'); }, async _executeFromModal() { const pipelineId = document.getElementById('pipeline-execute-id')?.value; const input = document.getElementById('pipeline-execute-input')?.value.trim(); const workingDirectory = document.getElementById('pipeline-execute-workdir')?.value.trim() || ''; if (!input) { Toast.warning('O input inicial é obrigatório'); return; } try { await API.pipelines.execute(pipelineId, input, workingDirectory); Modal.close('pipeline-execute-modal-overlay'); App.navigateTo('terminal'); Toast.info('Pipeline iniciado'); } catch (err) { Toast.error(`Erro ao executar pipeline: ${err.message}`); } }, }; window.PipelinesUI = PipelinesUI;