Files
Agents-Orchestrator/public/js/components/terminal.js
Frederico Castro 2f7a9d4c56 Implementação completa de funcionalidades pendentes
- Settings persistentes (modelo padrão, workdir, max concurrent)
- Import/export de agentes via JSON
- Agendamentos persistentes com restore no startup
- Edição de agendamentos e tarefas existentes
- Filtros e busca em todas as seções
- Isolamento de WebSocket por clientId
- Autenticação via AUTH_TOKEN e CORS configurável
- Graceful shutdown com cancelamento de execuções
- Correção: --max-tokens removido (flag inválida do CLI)
- Correção: pipeline agora verifica exit code e propaga erros
- Correção: streaming de output em pipelines via WebSocket
- Permission mode bypassPermissions como padrão
- Página de configurações do sistema
- Contagem diária de execuções no dashboard
- Histórico de execuções recentes
2026-02-26 01:24:51 -03:00

109 lines
3.1 KiB
JavaScript

const Terminal = {
lines: [],
maxLines: 1000,
autoScroll: true,
executionFilter: null,
_processingInterval: null,
addLine(content, type = 'default', executionId = null) {
const time = new Date();
const formatted = time.toTimeString().slice(0, 8);
Terminal.lines.push({ content, type, timestamp: formatted, executionId });
if (Terminal.lines.length > Terminal.maxLines) {
Terminal.lines.shift();
}
Terminal.render();
},
startProcessing(agentName) {
Terminal.stopProcessing();
Terminal.addLine(`Agente "${agentName}" processando tarefa...`, 'system');
let dots = 0;
Terminal._processingInterval = setInterval(() => {
dots = (dots + 1) % 4;
const indicator = document.getElementById('terminal-processing');
if (indicator) {
indicator.textContent = 'Processando' + '.'.repeat(dots + 1);
}
}, 500);
Terminal.render();
},
stopProcessing() {
if (Terminal._processingInterval) {
clearInterval(Terminal._processingInterval);
Terminal._processingInterval = null;
}
},
clear() {
Terminal.stopProcessing();
Terminal.lines = [];
Terminal.executionFilter = null;
Terminal.render();
},
setExecutionFilter(executionId) {
Terminal.executionFilter = executionId;
Terminal.render();
},
scrollToBottom() {
const output = document.getElementById('terminal-output');
if (output) output.scrollTop = output.scrollHeight;
},
render() {
const output = document.getElementById('terminal-output');
if (!output) return;
const lines = Terminal.executionFilter
? Terminal.lines.filter((l) => !l.executionId || l.executionId === Terminal.executionFilter)
: Terminal.lines;
if (lines.length === 0 && !Terminal._processingInterval) {
output.innerHTML = `
<div class="terminal-welcome">
<span class="terminal-prompt">$</span>
<span class="terminal-text">Aguardando execução de agente...</span>
</div>`;
return;
}
const html = lines.map((line) => {
const typeClass = line.type && line.type !== 'default' ? ' ' + line.type : '';
const escaped = Terminal._escapeHtml(line.content);
const formatted = escaped.replace(/\n/g, '<br>');
return `<div class="terminal-line${typeClass}">
<span class="timestamp">${line.timestamp}</span>
<span class="content">${formatted}</span>
</div>`;
}).join('');
const processing = Terminal._processingInterval
? '<div class="terminal-line system"><span class="terminal-processing-indicator"><span id="terminal-processing" class="processing-dots">Processando...</span><span class="terminal-spinner"></span></span></div>'
: '';
output.innerHTML = html + processing + '<span class="terminal-cursor blink">_</span>';
if (Terminal.autoScroll) Terminal.scrollToBottom();
},
_escapeHtml(text) {
return String(text)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
},
};
window.Terminal = Terminal;