Continuação de conversa no terminal, histórico de agendamentos, webhooks e melhorias gerais

- Terminal com input de chat: após execução, permite continuar conversa com o agente
  via --resume do CLI, mantendo contexto da sessão (sessionId persistido)
- Nova rota POST /api/agents/:id/continue para retomar sessões
- Executor com função resume() para spawnar claude com --resume <sessionId>
- Histórico de agendamentos agora busca do executionsStore (persistente) com dados
  completos: agente, tarefa, status, duração, custo e link para detalhes no modal
- Execuções de agendamento tagueadas com source:'schedule' e scheduleId
- Correção da expressão cron duplicada na UI de agendamentos
- cronToHuman trata expressões com minuto específico (ex: 37 3 * * * → Todo dia às 03:37)
- Botão "Copiar cURL" nos cards de webhook com payload de exemplo contextual
- Webhooks component (webhooks.js) adicionado ao repositório
This commit is contained in:
Frederico Castro
2026-02-26 04:01:12 -03:00
parent 22a3ce9262
commit 93d9027e2c
18 changed files with 1609 additions and 75 deletions

View File

@@ -53,6 +53,12 @@
<span>Pipelines</span>
</a>
</li>
<li class="sidebar-nav-item">
<a href="#" class="sidebar-nav-link" data-section="webhooks">
<i data-lucide="webhook"></i>
<span>Webhooks</span>
</a>
</li>
<li class="sidebar-nav-item">
<a href="#" class="sidebar-nav-link" data-section="terminal">
<i data-lucide="terminal"></i>
@@ -148,6 +154,24 @@
<span class="metric-card-value" id="metric-schedules">0</span>
</div>
</article>
<article class="metric-card">
<div class="metric-card-icon metric-card-icon--yellow">
<i data-lucide="dollar-sign"></i>
</div>
<div class="metric-card-body">
<span class="metric-card-label">Custo Hoje</span>
<span class="metric-card-value metric-card-value--sm" id="metric-cost-today">$0.0000</span>
</div>
</article>
<article class="metric-card">
<div class="metric-card-icon metric-card-icon--cyan">
<i data-lucide="webhook"></i>
</div>
<div class="metric-card-body">
<span class="metric-card-label">Webhooks Ativos</span>
<span class="metric-card-value" id="metric-webhooks">0</span>
</div>
</article>
</div>
<div class="dashboard-grid">
@@ -361,6 +385,22 @@
</div>
</section>
<section id="webhooks" class="section" aria-label="Webhooks" hidden>
<div class="section-toolbar">
<div class="search-field">
<i data-lucide="search"></i>
<input type="search" placeholder="Buscar webhooks..." id="webhooks-search" aria-label="Buscar webhooks" />
</div>
<div class="section-toolbar-actions">
<button class="btn btn--primary btn--icon-text" type="button" id="webhooks-new-btn">
<i data-lucide="plus"></i>
<span>Novo Webhook</span>
</button>
</div>
</div>
<div id="webhooks-list"></div>
</section>
<section id="terminal" class="section" aria-label="Terminal" hidden>
<div class="terminal-wrapper">
<div class="terminal-toolbar">
@@ -384,12 +424,30 @@
</button>
</div>
</div>
<div class="approval-notification" id="approval-notification" hidden></div>
<div class="terminal-output" id="terminal-output" role="log" aria-live="polite" aria-label="Saída do terminal">
<div class="terminal-welcome">
<span class="terminal-prompt">$</span>
<span class="terminal-text">Aguardando execução de agente...</span>
</div>
</div>
<div class="terminal-input-bar" id="terminal-input-bar" hidden>
<div class="terminal-input-context" id="terminal-input-context"></div>
<div class="terminal-input-row">
<span class="terminal-input-prompt"></span>
<input
type="text"
class="terminal-input"
id="terminal-input"
placeholder="Continuar conversa com o agente..."
aria-label="Enviar mensagem ao agente"
autocomplete="off"
/>
<button class="btn btn--primary btn--sm" id="terminal-send-btn" type="button" aria-label="Enviar">
<i data-lucide="send"></i>
</button>
</div>
</div>
</div>
</section>
@@ -890,6 +948,17 @@
</div>
<div class="modal-body">
<input type="hidden" id="pipeline-execute-id">
<div class="form-group">
<label class="form-label" for="pipeline-execute-workdir">Diretório de Trabalho</label>
<input
type="text"
class="input"
id="pipeline-execute-workdir"
placeholder="/home/fred/projetos/meu-projeto"
autocomplete="off"
/>
<p class="form-hint">Todos os agentes da pipeline vão trabalhar neste diretório. Se vazio, cada agente usa seu próprio.</p>
</div>
<div class="form-group">
<label class="form-label" for="pipeline-execute-input">
Input Inicial
@@ -998,6 +1067,53 @@
</div>
</div>
<div class="modal-overlay" id="webhook-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="webhook-modal-title" hidden>
<div class="modal modal--md">
<div class="modal-header">
<h2 class="modal-title" id="webhook-modal-title">Novo Webhook</h2>
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="webhook-modal-overlay">
<i data-lucide="x"></i>
</button>
</div>
<div class="modal-body">
<form class="modal-form" id="webhook-form" novalidate>
<div class="form-group">
<label class="form-label" for="webhook-name">
Nome
<span class="form-required" aria-hidden="true">*</span>
</label>
<input type="text" class="input" id="webhook-name" placeholder="Ex: Deploy Trigger" required autocomplete="off" />
</div>
<div class="form-group">
<label class="form-label" for="webhook-target-type">Tipo de Destino</label>
<select class="select" id="webhook-target-type">
<option value="agent">Agente</option>
<option value="pipeline">Pipeline</option>
</select>
</div>
<div class="form-group">
<label class="form-label" for="webhook-target-id">
Destino
<span class="form-required" aria-hidden="true">*</span>
</label>
<select class="select" id="webhook-target-id" required>
<option value="">Selecionar...</option>
</select>
</div>
<div class="form-hint-block">
<p>Após criar, você receberá uma URL única para disparar este webhook via POST.</p>
<p><strong>Payload aceito:</strong></p>
<pre class="form-hint-code">{ "task": "descrição", "instructions": "..." }</pre>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn--ghost" type="button" data-modal-close="webhook-modal-overlay">Cancelar</button>
<button class="btn btn--primary" type="button" id="webhook-form-submit">Criar Webhook</button>
</div>
</div>
</div>
<div class="toast-container" id="toast-container" aria-live="assertive" aria-atomic="false" role="region" aria-label="Notificações"></div>
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
@@ -1012,6 +1128,7 @@
<script src="js/components/pipelines.js"></script>
<script src="js/components/settings.js"></script>
<script src="js/components/history.js"></script>
<script src="js/components/webhooks.js"></script>
<script src="js/app.js"></script>
<script>
lucide.createIcons();