- Contador de tempo (mm:ss ou hh:mm:ss) que inicia ao processar e persiste entre reloads via sessionStorage - Espaçamento maior entre elementos da toolbar principal e action bar - Timer para ao completar execução/pipeline ou ao limpar terminal
1460 lines
65 KiB
HTML
1460 lines
65 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="pt-BR">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Agents Orchestrator</title>
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
|
||
<link rel="stylesheet" href="css/styles.css" />
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||
</head>
|
||
<body>
|
||
|
||
<div class="layout">
|
||
|
||
<aside class="sidebar">
|
||
<div class="sidebar-logo">
|
||
<div class="sidebar-logo-icon">
|
||
<i data-lucide="bot"></i>
|
||
</div>
|
||
<span class="sidebar-logo-text">Agents Orchestrator</span>
|
||
</div>
|
||
|
||
<nav class="sidebar-nav">
|
||
<ul class="sidebar-nav-list">
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="dashboard">
|
||
<i data-lucide="layout-dashboard"></i>
|
||
<span>Dashboard</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="agents">
|
||
<i data-lucide="cpu"></i>
|
||
<span>Agentes</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="tasks">
|
||
<i data-lucide="list-checks"></i>
|
||
<span>Tarefas</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="schedules">
|
||
<i data-lucide="clock"></i>
|
||
<span>Agendamentos</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item" data-section="pipelines">
|
||
<a class="sidebar-nav-link" href="#" data-section="pipelines">
|
||
<i data-lucide="git-merge" class="nav-icon"></i>
|
||
<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>
|
||
<span>Terminal</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="history">
|
||
<i data-lucide="history"></i>
|
||
<span>Histórico</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="import">
|
||
<i data-lucide="upload-cloud"></i>
|
||
<span>Importar</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="files">
|
||
<i data-lucide="folder-open"></i>
|
||
<span>Projetos</span>
|
||
</a>
|
||
</li>
|
||
<li class="sidebar-nav-item">
|
||
<a href="#" class="sidebar-nav-link" data-section="settings">
|
||
<i data-lucide="settings"></i>
|
||
<span>Configurações</span>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
|
||
<div class="sidebar-footer">
|
||
<div class="ws-status" id="ws-status">
|
||
<span class="ws-indicator ws-indicator--disconnected" id="ws-indicator"></span>
|
||
<span class="ws-label" id="ws-label">Desconectado</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<div class="main-wrapper">
|
||
<header class="main-header">
|
||
<div class="header-breadcrumb">
|
||
<h1 class="header-title" id="header-title">Dashboard</h1>
|
||
</div>
|
||
<div class="header-actions">
|
||
<div class="header-badge" id="active-executions-badge" aria-label="Execuções ativas">
|
||
<i data-lucide="activity"></i>
|
||
<span id="active-executions-count">0</span>
|
||
<span class="header-badge-label">ativas</span>
|
||
</div>
|
||
<button class="btn btn--ghost btn--icon-text" id="system-status-btn" type="button" aria-label="Status do sistema">
|
||
<i data-lucide="server"></i>
|
||
<span>Sistema</span>
|
||
</button>
|
||
<button class="btn btn--ghost btn--icon-text" id="import-agent-btn" type="button">
|
||
<i data-lucide="file-down"></i>
|
||
<span>Importar</span>
|
||
</button>
|
||
<button class="btn btn--primary btn--icon-text" id="new-agent-btn" type="button">
|
||
<i data-lucide="plus"></i>
|
||
<span>Novo Agente</span>
|
||
</button>
|
||
<button id="theme-toggle" class="btn btn--icon" title="Alternar tema">
|
||
<i data-lucide="sun" class="theme-icon-light"></i>
|
||
<i data-lucide="moon" class="theme-icon-dark"></i>
|
||
</button>
|
||
<div class="notification-wrapper">
|
||
<button id="notification-bell" class="btn btn--icon" title="Notificações">
|
||
<i data-lucide="bell"></i>
|
||
<span id="notification-badge" class="notification-badge hidden">0</span>
|
||
</button>
|
||
<div id="notification-panel" class="notification-panel hidden">
|
||
<div class="notification-panel-header">
|
||
<h3>Notificações</h3>
|
||
<div class="notification-panel-actions">
|
||
<button id="mark-all-read" class="btn btn--ghost btn--sm">Marcar lidas</button>
|
||
<button id="clear-notifications" class="btn btn--ghost btn--sm">Limpar</button>
|
||
</div>
|
||
</div>
|
||
<div id="notification-list" class="notification-list">
|
||
<div class="notification-empty">Nenhuma notificação</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="main-content">
|
||
|
||
<section id="dashboard" class="section active" aria-label="Dashboard">
|
||
<div class="metrics-grid">
|
||
<article class="metric-card">
|
||
<div class="metric-card-icon metric-card-icon--indigo">
|
||
<i data-lucide="cpu"></i>
|
||
</div>
|
||
<div class="metric-card-body">
|
||
<span class="metric-card-label">Total de Agentes</span>
|
||
<span class="metric-card-value" id="metric-total-agents">0</span>
|
||
</div>
|
||
</article>
|
||
<article class="metric-card">
|
||
<div class="metric-card-icon metric-card-icon--green">
|
||
<i data-lucide="zap"></i>
|
||
</div>
|
||
<div class="metric-card-body">
|
||
<span class="metric-card-label">Agentes Ativos</span>
|
||
<span class="metric-card-value" id="metric-active-agents">0</span>
|
||
</div>
|
||
</article>
|
||
<article class="metric-card">
|
||
<div class="metric-card-icon metric-card-icon--purple">
|
||
<i data-lucide="circle-play"></i>
|
||
</div>
|
||
<div class="metric-card-body">
|
||
<span class="metric-card-label">Execuções Hoje</span>
|
||
<span class="metric-card-value" id="metric-executions-today">0</span>
|
||
</div>
|
||
</article>
|
||
<article class="metric-card">
|
||
<div class="metric-card-icon metric-card-icon--orange">
|
||
<i data-lucide="clock"></i>
|
||
</div>
|
||
<div class="metric-card-body">
|
||
<span class="metric-card-label">Agendamentos</span>
|
||
<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="charts-row">
|
||
<div class="chart-container">
|
||
<div class="chart-header">
|
||
<h3>Execuções</h3>
|
||
<select id="chart-period" class="select-sm">
|
||
<option value="7">7 dias</option>
|
||
<option value="14">14 dias</option>
|
||
<option value="30">30 dias</option>
|
||
</select>
|
||
</div>
|
||
<canvas id="executions-chart"></canvas>
|
||
</div>
|
||
<div class="chart-container">
|
||
<div class="chart-header">
|
||
<h3>Custo (USD)</h3>
|
||
</div>
|
||
<canvas id="cost-chart"></canvas>
|
||
</div>
|
||
</div>
|
||
<div class="charts-row charts-row--triple">
|
||
<div class="chart-container">
|
||
<div class="chart-header">
|
||
<h3>Status</h3>
|
||
</div>
|
||
<canvas id="status-chart"></canvas>
|
||
</div>
|
||
<div class="chart-container">
|
||
<div class="chart-header">
|
||
<h3>Top Agentes</h3>
|
||
</div>
|
||
<canvas id="agents-chart"></canvas>
|
||
</div>
|
||
<div class="chart-container">
|
||
<div class="chart-header">
|
||
<h3>Taxa de Sucesso</h3>
|
||
</div>
|
||
<canvas id="success-rate-chart"></canvas>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dashboard-grid">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Atividade Recente</h2>
|
||
<button class="btn btn--ghost btn--sm" type="button" id="refresh-activity-btn">
|
||
<i data-lucide="refresh-cw"></i>
|
||
</button>
|
||
</div>
|
||
<div class="card-body">
|
||
<ul class="activity-list" id="activity-list">
|
||
<li class="activity-empty">
|
||
<i data-lucide="inbox"></i>
|
||
<span>Nenhuma execução recente</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Status do Sistema</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<ul class="system-status-list" id="system-status-list">
|
||
<li class="system-status-item">
|
||
<div class="system-status-info">
|
||
<i data-lucide="server"></i>
|
||
<span>Servidor HTTP</span>
|
||
</div>
|
||
<span class="badge badge--green">Online</span>
|
||
</li>
|
||
<li class="system-status-item">
|
||
<div class="system-status-info">
|
||
<i data-lucide="radio"></i>
|
||
<span>WebSocket</span>
|
||
</div>
|
||
<span class="badge badge--red" id="system-ws-status-badge">Desconectado</span>
|
||
</li>
|
||
<li class="system-status-item">
|
||
<div class="system-status-info">
|
||
<i data-lucide="database"></i>
|
||
<span>Armazenamento</span>
|
||
</div>
|
||
<span class="badge badge--green">OK</span>
|
||
</li>
|
||
<li class="system-status-item">
|
||
<div class="system-status-info">
|
||
<i data-lucide="terminal"></i>
|
||
<span>Claude CLI</span>
|
||
</div>
|
||
<span class="badge badge--gray" id="system-claude-status-badge">Verificando...</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="agents" class="section" aria-label="Agentes" hidden>
|
||
<div class="section-toolbar">
|
||
<div class="search-field">
|
||
<i data-lucide="search"></i>
|
||
<input type="search" placeholder="Buscar agentes..." id="agents-search" aria-label="Buscar agentes" />
|
||
</div>
|
||
<div class="section-toolbar-actions">
|
||
<select class="select" id="agents-filter-status" aria-label="Filtrar por status">
|
||
<option value="">Todos os status</option>
|
||
<option value="active">Ativo</option>
|
||
<option value="inactive">Inativo</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="agents-grid" id="agents-grid">
|
||
<div class="empty-state" id="agents-empty-state">
|
||
<div class="empty-state-icon">
|
||
<i data-lucide="bot"></i>
|
||
</div>
|
||
<h3 class="empty-state-title">Nenhum agente cadastrado</h3>
|
||
<p class="empty-state-desc">Crie seu primeiro agente para começar a orquestrar tarefas com Claude.</p>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="agents-empty-new-btn">
|
||
<i data-lucide="plus"></i>
|
||
<span>Criar Agente</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="tasks" class="section" aria-label="Tarefas" hidden>
|
||
<div class="section-toolbar">
|
||
<div class="search-field">
|
||
<i data-lucide="search"></i>
|
||
<input type="search" placeholder="Buscar tarefas..." id="tasks-search" aria-label="Buscar tarefas" />
|
||
</div>
|
||
<div class="section-toolbar-actions">
|
||
<select class="select" id="tasks-filter-category" aria-label="Filtrar por categoria">
|
||
<option value="">Todas as categorias</option>
|
||
<option value="code-review">Code Review</option>
|
||
<option value="security">Segurança</option>
|
||
<option value="refactor">Refatoração</option>
|
||
<option value="tests">Testes</option>
|
||
<option value="docs">Documentação</option>
|
||
<option value="performance">Performance</option>
|
||
</select>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="tasks-new-btn">
|
||
<i data-lucide="plus"></i>
|
||
<span>Nova Tarefa</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tasks-grid" id="tasks-grid">
|
||
<div class="empty-state" id="tasks-empty-state">
|
||
<div class="empty-state-icon">
|
||
<i data-lucide="list-checks"></i>
|
||
</div>
|
||
<h3 class="empty-state-title">Nenhuma tarefa cadastrada</h3>
|
||
<p class="empty-state-desc">Crie templates de tarefas para reutilizar em diferentes agentes.</p>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="tasks-empty-new-btn">
|
||
<i data-lucide="plus"></i>
|
||
<span>Criar Tarefa</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="schedules" class="section" aria-label="Agendamentos" hidden>
|
||
<div class="section-toolbar">
|
||
<div class="search-field">
|
||
<i data-lucide="search"></i>
|
||
<input type="search" placeholder="Buscar agendamentos..." id="schedules-search" aria-label="Buscar agendamentos" />
|
||
</div>
|
||
<div class="section-toolbar-actions">
|
||
<select class="select" id="schedules-filter-status" aria-label="Filtrar por status">
|
||
<option value="">Todos</option>
|
||
<option value="active">Ativo</option>
|
||
<option value="paused">Pausado</option>
|
||
</select>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="schedules-new-btn">
|
||
<i data-lucide="plus"></i>
|
||
<span>Novo Agendamento</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="table-wrapper">
|
||
<table class="table" id="schedules-table">
|
||
<colgroup>
|
||
<col style="width: 15%">
|
||
<col style="width: 30%">
|
||
<col style="width: 18%">
|
||
<col style="width: 17%">
|
||
<col style="width: 8%">
|
||
<col style="width: 12%">
|
||
</colgroup>
|
||
<thead>
|
||
<tr>
|
||
<th scope="col">Agente</th>
|
||
<th scope="col">Tarefa</th>
|
||
<th scope="col">Expressão Cron</th>
|
||
<th scope="col">Próxima Execução</th>
|
||
<th scope="col">Status</th>
|
||
<th scope="col" aria-label="Ações"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="schedules-tbody">
|
||
<tr class="table-empty-row">
|
||
<td colspan="6">
|
||
<div class="empty-state empty-state--inline">
|
||
<i data-lucide="clock"></i>
|
||
<span>Nenhum agendamento configurado</span>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card" style="margin-top: 1rem;">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Histórico de Disparos</h2>
|
||
</div>
|
||
<div class="card-body" id="schedules-history">
|
||
<p class="empty-state-desc">Nenhum disparo registrado</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="pipelines" class="section" aria-label="Pipelines" hidden>
|
||
<div class="page-title">Pipelines</div>
|
||
<div class="page-subtitle">Encadeie agentes para fluxos de trabalho automatizados</div>
|
||
|
||
<div class="section-toolbar">
|
||
<div class="search-field">
|
||
<i data-lucide="search" class="search-icon" style="width:16px;height:16px"></i>
|
||
<input type="text" placeholder="Buscar pipelines..." id="pipelines-search">
|
||
</div>
|
||
<div class="section-toolbar-actions">
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="pipelines-new-btn">
|
||
<i data-lucide="plus"></i>
|
||
<span>Novo Pipeline</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="pipelines-grid" class="agents-grid">
|
||
</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">
|
||
<div class="terminal-toolbar-left">
|
||
<div class="terminal-dot terminal-dot--red"></div>
|
||
<div class="terminal-dot terminal-dot--yellow"></div>
|
||
<div class="terminal-dot terminal-dot--green"></div>
|
||
<span class="terminal-title">Output de Execução</span>
|
||
</div>
|
||
<div class="terminal-toolbar-right">
|
||
<div class="terminal-timer" id="terminal-timer" hidden>
|
||
<i data-lucide="clock" style="width:14px;height:14px"></i>
|
||
<span id="terminal-timer-value">00:00</span>
|
||
</div>
|
||
<select class="select select--sm" id="terminal-execution-select" aria-label="Selecionar execução">
|
||
<option value="">Selecionar execução...</option>
|
||
</select>
|
||
<div class="terminal-ws-indicator" id="terminal-ws-indicator">
|
||
<span class="ws-indicator ws-indicator--disconnected" id="terminal-ws-dot"></span>
|
||
<span id="terminal-ws-label">Desconectado</span>
|
||
</div>
|
||
<button class="btn btn--danger btn--sm btn--icon-text" type="button" id="terminal-stop-btn" aria-label="Interromper execução" hidden>
|
||
<i data-lucide="square"></i>
|
||
<span>Interromper</span>
|
||
</button>
|
||
<button class="btn btn--ghost btn--sm btn--icon-text" type="button" id="terminal-clear-btn" aria-label="Limpar terminal">
|
||
<i data-lucide="trash-2"></i>
|
||
<span>Limpar</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="terminal-action-toolbar">
|
||
<div class="terminal-toolbar-left">
|
||
<button id="terminal-search-toggle" class="btn btn--ghost btn--sm" title="Buscar (Ctrl+F)">
|
||
<i data-lucide="search" style="width:14px;height:14px"></i>
|
||
</button>
|
||
<button id="terminal-download" class="btn btn--ghost btn--sm" title="Baixar saída">
|
||
<i data-lucide="download" style="width:14px;height:14px"></i>
|
||
</button>
|
||
<button id="terminal-copy" class="btn btn--ghost btn--sm" title="Copiar saída">
|
||
<i data-lucide="copy" style="width:14px;height:14px"></i>
|
||
</button>
|
||
</div>
|
||
<div class="terminal-toolbar-right">
|
||
<label class="terminal-toggle-label">
|
||
<input type="checkbox" id="terminal-autoscroll" checked>
|
||
<span>Auto-scroll</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div id="terminal-search-bar" class="terminal-search-bar hidden">
|
||
<input type="text" id="terminal-search-input" placeholder="Buscar no terminal..." class="input input--sm">
|
||
<span id="terminal-search-count" class="terminal-search-count">0/0</span>
|
||
<button id="terminal-search-prev" class="btn btn--ghost btn--sm">▲</button>
|
||
<button id="terminal-search-next" class="btn btn--ghost btn--sm">▼</button>
|
||
<button id="terminal-search-close" class="btn btn--ghost btn--sm">✕</button>
|
||
</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>
|
||
|
||
<section id="history" class="section" aria-label="Histórico de Execuções" hidden>
|
||
<div class="section-toolbar">
|
||
<div class="toolbar-filters">
|
||
<div class="search-field">
|
||
<i data-lucide="search"></i>
|
||
<input type="text" placeholder="Buscar..." id="history-search" aria-label="Buscar no histórico" />
|
||
</div>
|
||
<select class="select" id="history-filter-type" aria-label="Filtrar por tipo">
|
||
<option value="">Todos os tipos</option>
|
||
<option value="agent">Agentes</option>
|
||
<option value="pipeline">Pipelines</option>
|
||
</select>
|
||
<select class="select" id="history-filter-status" aria-label="Filtrar por status">
|
||
<option value="">Todos os status</option>
|
||
<option value="completed">Concluído</option>
|
||
<option value="error">Erro</option>
|
||
<option value="running">Em execução</option>
|
||
</select>
|
||
</div>
|
||
<div class="toolbar-actions">
|
||
<button id="history-export-csv" class="btn btn--ghost btn--sm" title="Exportar CSV">
|
||
<i data-lucide="file-spreadsheet" style="width:14px;height:14px"></i>
|
||
Exportar
|
||
</button>
|
||
<button class="btn btn-ghost btn-sm btn-danger" id="history-clear-btn" type="button">
|
||
<i data-lucide="trash-2"></i>
|
||
Limpar Histórico
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="history-list"></div>
|
||
<div id="history-pagination"></div>
|
||
</section>
|
||
|
||
<section id="import" class="section" aria-label="Importar Projeto" hidden>
|
||
<div id="import-container"></div>
|
||
</section>
|
||
|
||
<section id="files" class="section" aria-label="Projetos" hidden>
|
||
<div id="files-container"></div>
|
||
</section>
|
||
|
||
<section id="settings" class="section" aria-label="Configurações" hidden>
|
||
<div class="settings-grid">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Configurações Gerais</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<form class="settings-form" id="settings-form" novalidate>
|
||
<div class="form-group">
|
||
<label class="form-label" for="settings-default-model">Modelo Padrão</label>
|
||
<select class="select" id="settings-default-model" name="defaultModel">
|
||
<option value="claude-sonnet-4-6">claude-sonnet-4-6</option>
|
||
<option value="claude-opus-4-6">claude-opus-4-6</option>
|
||
<option value="claude-haiku-4-5-20251001">claude-haiku-4-5-20251001</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="settings-default-workdir">Diretório de Trabalho Padrão</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="settings-default-workdir"
|
||
name="defaultWorkdir"
|
||
placeholder="/home/fred/projetos"
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="settings-max-concurrent">Execuções Simultâneas Máximas</label>
|
||
<input
|
||
type="number"
|
||
class="input"
|
||
id="settings-max-concurrent"
|
||
name="maxConcurrent"
|
||
min="1"
|
||
max="20"
|
||
placeholder="5"
|
||
/>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn--primary">Salvar Configurações</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Informações do Sistema</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<ul class="system-info-list" id="system-info-list">
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Versão do Servidor</span>
|
||
<span class="system-info-value" id="info-server-version">1.0.0</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Versão do Node.js</span>
|
||
<span class="system-info-value font-mono" id="info-node-version">Carregando...</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Versão do Claude CLI</span>
|
||
<span class="system-info-value font-mono" id="info-claude-version">Carregando...</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Plataforma</span>
|
||
<span class="system-info-value font-mono" id="info-platform">Carregando...</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Tempo Online</span>
|
||
<span class="system-info-value font-mono" id="info-uptime">Carregando...</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Tema Atual</span>
|
||
<span class="system-info-value" id="info-current-theme">Escuro</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">Atalhos do Teclado</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<ul class="system-info-list">
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Fechar modal</span>
|
||
<span class="system-info-value font-mono">Esc</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Novo agente (em Agentes)</span>
|
||
<span class="system-info-value font-mono">N</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Dashboard</span>
|
||
<span class="system-info-value font-mono">1</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Agentes</span>
|
||
<span class="system-info-value font-mono">2</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Tarefas</span>
|
||
<span class="system-info-value font-mono">3</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Agendamentos</span>
|
||
<span class="system-info-value font-mono">4</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Pipelines</span>
|
||
<span class="system-info-value font-mono">5</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Terminal</span>
|
||
<span class="system-info-value font-mono">6</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Histórico</span>
|
||
<span class="system-info-value font-mono">7</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Webhooks</span>
|
||
<span class="system-info-value font-mono">8</span>
|
||
</li>
|
||
<li class="system-info-item">
|
||
<span class="system-info-label">Configurações</span>
|
||
<span class="system-info-value font-mono">9</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="agent-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="agent-modal-title" hidden>
|
||
<div class="modal modal--lg">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="agent-modal-title">Novo Agente</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="agent-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="modal-form" id="agent-form" novalidate>
|
||
<input type="hidden" id="agent-form-id" name="id" />
|
||
<div class="form-row">
|
||
<div class="form-group form-group--grow">
|
||
<label class="form-label" for="agent-name">
|
||
Nome do Agente
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="agent-name"
|
||
name="name"
|
||
placeholder="Ex: Revisor de Código"
|
||
required
|
||
autocomplete="off"
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-status-toggle">Status</label>
|
||
<div class="toggle-wrapper">
|
||
<input type="checkbox" class="toggle-input" id="agent-status-toggle" name="active" role="switch" />
|
||
<label class="toggle-label" for="agent-status-toggle">
|
||
<span class="toggle-thumb"></span>
|
||
<span class="toggle-text-on">Ativo</span>
|
||
<span class="toggle-text-off">Inativo</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-description">Descrição</label>
|
||
<textarea
|
||
class="textarea"
|
||
id="agent-description"
|
||
name="description"
|
||
rows="2"
|
||
placeholder="Descreva brevemente o propósito deste agente"
|
||
></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-system-prompt">
|
||
System Prompt
|
||
</label>
|
||
<textarea
|
||
class="textarea textarea--code"
|
||
id="agent-system-prompt"
|
||
name="systemPrompt"
|
||
rows="6"
|
||
placeholder="Você é um especialista em... Seu objetivo é... Sempre responda em português..."
|
||
></textarea>
|
||
<p class="form-hint">Instruções base que definem o comportamento, personalidade e restrições do agente.</p>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group form-group--grow">
|
||
<label class="form-label" for="agent-model">Modelo</label>
|
||
<select class="select" id="agent-model" name="model">
|
||
<option value="claude-sonnet-4-6">claude-sonnet-4-6</option>
|
||
<option value="claude-opus-4-6">claude-opus-4-6</option>
|
||
<option value="claude-haiku-4-5-20251001">claude-haiku-4-5-20251001</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group form-group--grow">
|
||
<label class="form-label" for="agent-workdir">Diretório de Trabalho</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="agent-workdir"
|
||
name="workdir"
|
||
value="/home/projetos/"
|
||
autocomplete="off"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group form-group--grow">
|
||
<label class="form-label" for="agent-allowed-tools">Ferramentas Permitidas</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="agent-allowed-tools"
|
||
name="allowedTools"
|
||
placeholder="Bash,Read,Write,Glob,Grep"
|
||
autocomplete="off"
|
||
/>
|
||
<p class="form-hint">Lista separada por vírgula. Vazio = todas permitidas.</p>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-max-turns">Max Turns</label>
|
||
<input
|
||
type="number"
|
||
class="input"
|
||
id="agent-max-turns"
|
||
name="maxTurns"
|
||
min="0"
|
||
max="100"
|
||
value="0"
|
||
/>
|
||
<p class="form-hint">Limite de turnos agênticos. 0 = sem limite.</p>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-permission-mode">Permission Mode</label>
|
||
<select class="select" id="agent-permission-mode" name="permissionMode">
|
||
<option value="">Padrão</option>
|
||
<option value="default">default</option>
|
||
<option value="plan">plan</option>
|
||
<option value="acceptEdits">acceptEdits</option>
|
||
<option value="bypassPermissions">bypassPermissions</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-delegate-to">Delegar para (auto)</label>
|
||
<select class="select" id="agent-delegate-to" name="delegateTo">
|
||
<option value="">Nenhum</option>
|
||
</select>
|
||
<p class="form-hint">Ao concluir, delega automaticamente o resultado para este agente.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label class="form-label">Retry em caso de falha</label>
|
||
<div class="toggle-wrapper">
|
||
<input type="checkbox" class="toggle-input" id="agent-retry-toggle" name="retryOnFailure" role="switch" />
|
||
<label class="toggle-label" for="agent-retry-toggle">
|
||
<span class="toggle-thumb"></span>
|
||
<span class="toggle-text-on">Sim</span>
|
||
<span class="toggle-text-off">Não</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group" id="agent-retry-max-group" style="display:none;">
|
||
<label class="form-label" for="agent-retry-max">Máximo de tentativas</label>
|
||
<select class="select" id="agent-retry-max" name="maxRetries">
|
||
<option value="1">1</option>
|
||
<option value="2">2</option>
|
||
<option value="3" selected>3</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="agent-tags-input">Tags</label>
|
||
<div class="tags-input-wrapper" id="agent-tags-wrapper">
|
||
<div class="tags-chips" id="agent-tags-chips"></div>
|
||
<input
|
||
type="text"
|
||
class="tags-input"
|
||
id="agent-tags-input"
|
||
placeholder="Digite e pressione Enter para adicionar"
|
||
autocomplete="off"
|
||
/>
|
||
</div>
|
||
<input type="hidden" id="agent-tags" name="tags" value="[]" />
|
||
</div>
|
||
|
||
<div class="form-divider"></div>
|
||
<div class="form-section" id="agent-secrets-section" hidden>
|
||
<h3 class="form-section-title">
|
||
<i data-lucide="key-round"></i>
|
||
Variáveis de Ambiente (Secrets)
|
||
</h3>
|
||
<p class="form-hint mb-12">Secrets são injetados como variáveis de ambiente na execução. Valores nunca são exibidos após salvos.</p>
|
||
<div id="agent-secrets-list" class="secrets-list"></div>
|
||
<div class="secrets-add-form">
|
||
<input type="text" class="input" id="agent-secret-name" placeholder="NOME_DA_VARIAVEL" autocomplete="off" />
|
||
<input type="password" class="input" id="agent-secret-value" placeholder="valor secreto" autocomplete="new-password" />
|
||
<button type="button" class="btn btn--primary btn--sm" id="agent-secret-add-btn">
|
||
<i data-lucide="plus"></i>
|
||
Adicionar
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="agent-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary" type="submit" form="agent-form" id="agent-form-submit">Salvar</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="agent-versions-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="agent-versions-title" hidden>
|
||
<div class="modal modal--lg">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="agent-versions-title">Histórico de Versões</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="agent-versions-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body" id="agent-versions-content">
|
||
<div class="empty-state">
|
||
<i data-lucide="history"></i>
|
||
<p>Carregando versões...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="execute-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="execute-modal-title" hidden>
|
||
<div class="modal modal--md">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="execute-modal-title">Executar Tarefa</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="execute-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="modal-form" id="execute-form" novalidate>
|
||
<input type="hidden" id="execute-agent-id" name="agentId" />
|
||
|
||
<div class="form-group" id="execute-agent-select-group">
|
||
<label class="form-label" for="execute-agent-select">
|
||
Agente
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<select class="select" id="execute-agent-select" name="agentSelect" required>
|
||
<option value="">Selecionar agente...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="execute-saved-task">Tarefa Salva</label>
|
||
<select class="select" id="execute-saved-task" name="savedTask">
|
||
<option value="">Digitar manualmente...</option>
|
||
</select>
|
||
<p class="form-hint">Selecione uma tarefa salva ou digite manualmente abaixo</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="execute-task-desc">
|
||
Descrição da Tarefa
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<textarea
|
||
class="textarea"
|
||
id="execute-task-desc"
|
||
name="task"
|
||
rows="3"
|
||
placeholder="Descreva o que o agente deve fazer..."
|
||
required
|
||
></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="execute-instructions">Instruções Adicionais</label>
|
||
<textarea
|
||
class="textarea textarea--code"
|
||
id="execute-instructions"
|
||
name="instructions"
|
||
rows="3"
|
||
placeholder="Contexto adicional, restrições ou preferências..."
|
||
></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="execute-repo">Repositório Git</label>
|
||
<div class="repo-selector">
|
||
<select class="select" id="execute-repo">
|
||
<option value="">Nenhum (usar diretório manual)</option>
|
||
</select>
|
||
<select class="select" id="execute-repo-branch" style="display:none">
|
||
<option value="">Branch padrão</option>
|
||
</select>
|
||
</div>
|
||
<p class="form-hint">Se selecionado, o agente trabalha no repositório e faz commit/push automático ao finalizar.</p>
|
||
</div>
|
||
|
||
<div class="form-group" id="execute-workdir-group">
|
||
<label class="form-label" for="execute-workdir">Diretório de Trabalho</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="execute-workdir"
|
||
value="/home/projetos/"
|
||
autocomplete="off"
|
||
/>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">Arquivos de Contexto</label>
|
||
<div class="dropzone" id="execute-dropzone">
|
||
<input type="file" id="execute-files" multiple hidden />
|
||
<div class="dropzone-content">
|
||
<i data-lucide="upload-cloud"></i>
|
||
<p>Arraste arquivos aqui ou <button type="button" class="dropzone-browse">selecione</button></p>
|
||
<span class="dropzone-hint">Até 20 arquivos, 10MB cada</span>
|
||
</div>
|
||
<ul class="dropzone-list" id="execute-file-list"></ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="quick-templates">
|
||
<p class="quick-templates-label">Templates rápidos</p>
|
||
<div class="quick-templates-grid">
|
||
<button class="template-btn" type="button" data-template="Analisar código e detectar bugs, vulnerabilidades e problemas de qualidade. Forneça um relatório detalhado com sugestões de correção.">
|
||
<i data-lucide="bug"></i>
|
||
<span>Detectar Bugs</span>
|
||
</button>
|
||
<button class="template-btn" type="button" data-template="Realizar revisão de segurança seguindo as diretrizes OWASP Top 10. Identificar vulnerabilidades, inputs não validados e problemas de autenticação/autorização.">
|
||
<i data-lucide="shield"></i>
|
||
<span>Revisão OWASP</span>
|
||
</button>
|
||
<button class="template-btn" type="button" data-template="Refatorar o código para melhorar legibilidade, manutenibilidade e aderência às boas práticas. Manter comportamento funcional intacto.">
|
||
<i data-lucide="wand"></i>
|
||
<span>Refatorar Código</span>
|
||
</button>
|
||
<button class="template-btn" type="button" data-template="Escrever testes unitários e de integração abrangentes. Garantir cobertura dos casos de sucesso, erro e edge cases.">
|
||
<i data-lucide="test-tube"></i>
|
||
<span>Escrever Testes</span>
|
||
</button>
|
||
<button class="template-btn" type="button" data-template="Documentar o código com JSDoc/docstrings, README atualizado, exemplos de uso e descrição de APIs públicas.">
|
||
<i data-lucide="book-open"></i>
|
||
<span>Documentar Código</span>
|
||
</button>
|
||
<button class="template-btn" type="button" data-template="Analisar e otimizar a performance do código. Identificar gargalos, reduzir complexidade algorítmica e melhorar uso de memória.">
|
||
<i data-lucide="gauge"></i>
|
||
<span>Otimizar Performance</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="execute-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary btn--icon-text" type="submit" form="execute-form" id="execute-form-submit">
|
||
<i data-lucide="play"></i>
|
||
<span>Executar</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="schedule-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="schedule-modal-title" hidden>
|
||
<div class="modal modal--md">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="schedule-modal-title">Novo Agendamento</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="schedule-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="modal-form" id="schedule-form" novalidate>
|
||
<input type="hidden" id="schedule-form-id" name="id" />
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="schedule-agent">
|
||
Agente
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<select class="select" id="schedule-agent" name="agentId" required>
|
||
<option value="">Selecionar agente...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="schedule-task">
|
||
Descrição da Tarefa
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<textarea
|
||
class="textarea"
|
||
id="schedule-task"
|
||
name="task"
|
||
rows="3"
|
||
placeholder="Descreva a tarefa que será executada automaticamente..."
|
||
required
|
||
></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="schedule-cron">
|
||
Expressão Cron
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<input
|
||
type="text"
|
||
class="input input--mono"
|
||
id="schedule-cron"
|
||
name="cron"
|
||
placeholder="0 * * * *"
|
||
required
|
||
autocomplete="off"
|
||
aria-describedby="schedule-cron-hint"
|
||
/>
|
||
<p class="form-hint" id="schedule-cron-hint">Formato: minuto hora dia-mês mês dia-semana</p>
|
||
</div>
|
||
|
||
<div class="cron-presets">
|
||
<p class="cron-presets-label">Presets</p>
|
||
<div class="cron-presets-list">
|
||
<button class="cron-preset-btn" type="button" data-cron="0 * * * *">
|
||
<span class="cron-preset-name">A cada hora</span>
|
||
<span class="cron-preset-expr">0 * * * *</span>
|
||
</button>
|
||
<button class="cron-preset-btn" type="button" data-cron="0 9 * * *">
|
||
<span class="cron-preset-name">Diário (09:00)</span>
|
||
<span class="cron-preset-expr">0 9 * * *</span>
|
||
</button>
|
||
<button class="cron-preset-btn" type="button" data-cron="0 9 * * 1">
|
||
<span class="cron-preset-name">Semanal (seg 09:00)</span>
|
||
<span class="cron-preset-expr">0 9 * * 1</span>
|
||
</button>
|
||
<button class="cron-preset-btn" type="button" data-cron="0 0 1 * *">
|
||
<span class="cron-preset-name">Mensal (dia 1)</span>
|
||
<span class="cron-preset-expr">0 0 1 * *</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="schedule-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary btn--icon-text" type="submit" form="schedule-form" id="schedule-form-submit">
|
||
<i data-lucide="clock"></i>
|
||
<span>Agendar</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="pipeline-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="pipeline-modal-title" hidden>
|
||
<div class="modal modal--lg">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="pipeline-modal-title">Novo Pipeline</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="pipeline-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form class="modal-form" id="pipeline-form" novalidate>
|
||
<input type="hidden" id="pipeline-form-id">
|
||
<div class="form-group">
|
||
<label class="form-label" for="pipeline-name">
|
||
Nome
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<input class="input" type="text" id="pipeline-name" placeholder="Ex: Análise e Correção de Bugs" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="pipeline-description">Descrição</label>
|
||
<textarea class="textarea" id="pipeline-description" rows="2" placeholder="Descreva o objetivo do pipeline..."></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="pipeline-workdir">
|
||
<i data-lucide="folder" style="width:14px;height:14px"></i>
|
||
Diretório do Projeto
|
||
</label>
|
||
<input class="input" type="text" id="pipeline-workdir" autocomplete="off">
|
||
<p class="form-hint">Caminho onde o projeto será criado/trabalhado. Todos os passos usarão este diretório.</p>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">
|
||
Passos do Pipeline
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<p class="form-hint mb-8">Cada passo usa um agente. O output de um passo vira o input do próximo.</p>
|
||
<div id="pipeline-steps-container"></div>
|
||
<button class="btn btn--ghost btn--sm mt-8" type="button" id="pipeline-add-step-btn">
|
||
<i data-lucide="plus" style="width:14px;height:14px"></i>
|
||
Adicionar Passo
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="pipeline-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary" type="button" id="pipeline-form-submit">Salvar Pipeline</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="pipeline-execute-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="pipeline-execute-title" hidden>
|
||
<div class="modal modal--md">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="pipeline-execute-title">Executar Pipeline</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="pipeline-execute-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<input type="hidden" id="pipeline-execute-id">
|
||
<div class="form-group">
|
||
<label class="form-label" for="pipeline-execute-input">
|
||
Input Inicial
|
||
<span class="form-required" aria-hidden="true">*</span>
|
||
</label>
|
||
<textarea class="textarea" id="pipeline-execute-input" rows="4" placeholder="Descreva a tarefa inicial para o pipeline..." autofocus></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">Arquivos de Contexto</label>
|
||
<div class="dropzone" id="pipeline-execute-dropzone">
|
||
<input type="file" id="pipeline-execute-files" multiple hidden />
|
||
<div class="dropzone-content">
|
||
<i data-lucide="upload-cloud"></i>
|
||
<p>Arraste arquivos aqui ou <button type="button" class="dropzone-browse">selecione</button></p>
|
||
<span class="dropzone-hint">Até 20 arquivos, 10MB cada</span>
|
||
</div>
|
||
<ul class="dropzone-list" id="pipeline-execute-file-list"></ul>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="pipeline-execute-repo">Repositório Git</label>
|
||
<div class="repo-selector">
|
||
<select class="select" id="pipeline-execute-repo">
|
||
<option value="">Nenhum (usar diretório manual)</option>
|
||
</select>
|
||
<select class="select" id="pipeline-execute-repo-branch" style="display:none">
|
||
<option value="">Branch padrão</option>
|
||
</select>
|
||
</div>
|
||
<p class="form-hint">Se selecionado, todos os agentes trabalham no repositório e o commit/push é automático ao final.</p>
|
||
</div>
|
||
|
||
<div class="form-group" id="pipeline-execute-workdir-group">
|
||
<label class="form-label" for="pipeline-execute-workdir">Diretório de Trabalho (opcional)</label>
|
||
<input
|
||
type="text"
|
||
class="input"
|
||
id="pipeline-execute-workdir"
|
||
placeholder="/home/projetos/meu-projeto"
|
||
autocomplete="off"
|
||
/>
|
||
<p class="form-hint">Se vazio, cada agente usa seu próprio diretório configurado.</p>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="pipeline-execute-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="pipeline-execute-submit">
|
||
<i data-lucide="play" style="width:14px;height:14px"></i>
|
||
<span>Executar</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="execution-detail-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="execution-detail-title" hidden>
|
||
<div class="modal modal-lg">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="execution-detail-title">Detalhe da Execução</h2>
|
||
<button class="modal-close" data-modal-close="execution-detail-modal-overlay" aria-label="Fechar" type="button">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body" id="execution-detail-content">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="confirm-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="confirm-modal-title" hidden>
|
||
<div class="modal modal--sm">
|
||
<div class="modal-header">
|
||
<div class="confirm-modal-icon" id="confirm-modal-icon">
|
||
<i data-lucide="triangle-alert"></i>
|
||
</div>
|
||
<h2 class="modal-title" id="confirm-modal-title">Confirmar Ação</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="confirm-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="confirm-modal-message" id="confirm-modal-message"></p>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="confirm-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--danger" type="button" id="confirm-modal-confirm-btn">Confirmar</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="export-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="export-modal-title" hidden>
|
||
<div class="modal modal--md">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="export-modal-title">Exportar Agente</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="export-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="export-code-wrapper">
|
||
<div class="export-code-toolbar">
|
||
<span class="export-code-label">JSON</span>
|
||
<button class="btn btn--ghost btn--sm btn--icon-text" type="button" id="export-copy-btn" aria-label="Copiar JSON">
|
||
<i data-lucide="copy"></i>
|
||
<span>Copiar</span>
|
||
</button>
|
||
</div>
|
||
<pre class="export-code" id="export-code-content" tabindex="0" aria-label="Dados do agente em formato JSON"></pre>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="export-modal-overlay">Fechar</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-overlay" id="import-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="import-modal-title" hidden>
|
||
<div class="modal modal--md">
|
||
<div class="modal-header">
|
||
<h2 class="modal-title" id="import-modal-title">Importar Agente</h2>
|
||
<button class="modal-close" type="button" aria-label="Fechar modal" data-modal-close="import-modal-overlay">
|
||
<i data-lucide="x"></i>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="form-group">
|
||
<label class="form-label" for="import-json-content">JSON do Agente</label>
|
||
<textarea
|
||
class="textarea textarea--code"
|
||
id="import-json-content"
|
||
rows="10"
|
||
placeholder="Cole aqui o JSON exportado do agente..."
|
||
></textarea>
|
||
<p class="form-hint">Cole o JSON gerado pela função de exportar agente.</p>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn--ghost" type="button" data-modal-close="import-modal-overlay">Cancelar</button>
|
||
<button class="btn btn--primary btn--icon-text" type="button" id="import-confirm-btn">
|
||
<i data-lucide="file-down"></i>
|
||
<span>Importar</span>
|
||
</button>
|
||
</div>
|
||
</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="js/lucide.js"></script>
|
||
<script src="js/api.js"></script>
|
||
<script src="js/utils.js"></script>
|
||
<script src="js/components/toast.js"></script>
|
||
<script src="js/components/modal.js"></script>
|
||
<script src="js/components/terminal.js"></script>
|
||
<script src="js/components/agents.js"></script>
|
||
<script src="js/components/dashboard.js"></script>
|
||
<script src="js/components/tasks.js"></script>
|
||
<script src="js/components/schedules.js"></script>
|
||
<script src="js/components/pipelines.js"></script>
|
||
<script src="js/components/flow-editor.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/components/notifications.js"></script>
|
||
<script src="js/components/files.js"></script>
|
||
<script src="js/components/import.js"></script>
|
||
<script src="js/app.js"></script>
|
||
<script>
|
||
Utils.refreshIcons();
|
||
App.init();
|
||
</script>
|
||
</body>
|
||
</html>
|