Histórico persistente de execuções com visualização detalhada

- Novo executionsStore em db.js com cache in-memory e escrita debounced
- Camada de cache (src/cache/index.js) com TTL e suporte opcional a Redis
- Persistência de execuções de agentes e pipelines com metadados completos
- Pipeline grava cada etapa com prompt, resultado, timestamps e status
- 4 endpoints REST: listagem paginada com filtros, detalhe, exclusão individual e limpeza total
- Componente frontend (history.js) com cards, filtros, paginação e modal de detalhe
- Timeline visual para pipelines com prompts colapsáveis por etapa
- Correção do executor: --max-turns em vez de --max-tokens, --permission-mode bypassPermissions
- Refatoração do scheduler com persistência melhorada e graceful shutdown
This commit is contained in:
Frederico Castro
2026-02-26 01:36:28 -03:00
parent 2f7a9d4c56
commit 4b6c876f36
13 changed files with 1536 additions and 398 deletions

View File

@@ -7,6 +7,7 @@ import { v4 as uuidv4 } from 'uuid';
import apiRouter, { setWsBroadcast, setWsBroadcastTo } from './src/routes/api.js';
import * as manager from './src/agents/manager.js';
import { cancelAllExecutions } from './src/agents/executor.js';
import { flushAllStores } from './src/store/db.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
const PORT = process.env.PORT || 3000;
@@ -57,35 +58,23 @@ wss.on('connection', (ws, req) => {
ws.clientId = clientId;
connectedClients.set(clientId, ws);
ws.on('close', () => {
connectedClients.delete(clientId);
});
ws.on('error', () => {
connectedClients.delete(clientId);
});
ws.on('close', () => connectedClients.delete(clientId));
ws.on('error', () => connectedClients.delete(clientId));
ws.send(JSON.stringify({ type: 'connected', clientId }));
});
function broadcast(message) {
const payload = JSON.stringify(message);
for (const [, client] of connectedClients) {
if (client.readyState === 1) {
client.send(payload);
}
if (client.readyState === 1) client.send(payload);
}
}
function broadcastTo(clientId, message) {
const payload = JSON.stringify(message);
const client = connectedClients.get(clientId);
if (client && client.readyState === 1) {
client.send(payload);
} else {
broadcast(message);
}
if (client && client.readyState === 1) client.send(payload);
else broadcast(message);
}
setWsBroadcast(broadcast);
@@ -97,6 +86,9 @@ function gracefulShutdown(signal) {
cancelAllExecutions();
console.log('Execuções ativas canceladas.');
flushAllStores();
console.log('Dados persistidos.');
httpServer.close(() => {
console.log('Servidor HTTP encerrado.');
process.exit(0);