(function () {
const esc = (s) => String(s ?? '').replace(/&/g, '&').replace(//g, '>');
const SEV_COLS = [
{ key: 'critical', label: 'Crítico', cls: 'ao-board-col--critical' },
{ key: 'high', label: 'Alto', cls: 'ao-board-col--high' },
{ key: 'warn', label: 'Aviso', cls: 'ao-board-col--warn' },
{ key: 'info', label: 'Info / OK', cls: 'ao-board-col--ok' },
];
const AGENT_ACCENTS = {
A0: '#6366f1', A1: '#22c55e', A2: '#3b82f6', A3: '#06b6d4', A4: '#8b5cf6',
A5: '#ec4899', A6: '#a855f7', A7: '#ef4444', sentinel: '#f59e0b', curator: '#64748b',
};
let state = {
selectedAgent: 'A6',
selectedIncidentId: null,
threadId: null,
mobileTab: 'board',
pollTimer: null,
};
async function agentsApi(path, opts = {}) {
const deskApi = typeof globalThis.api === 'function' ? globalThis.api : null;
if (deskApi) return deskApi(`/v1/agents${path}`, opts);
const h = authHeaders({ ...(opts.headers || {}) });
if (!(opts.body instanceof FormData) && !h['Content-Type']) h['Content-Type'] = 'application/json';
const r = await fetchWithTimeout(`/api/v1/agents${path}`, { ...opts, headers: h }, 60000);
if (r.status === 401) {
logout();
throw new Error('sessão expirada — faça login novamente');
}
if (!r.ok) throw new Error(`${r.status} ${(await r.text()).slice(0, 200)}`);
return r.json();
}
function fmtAge(iso) {
if (!iso) return '—';
try {
const ms = Date.now() - new Date(iso).getTime();
const m = Math.floor(ms / 60000);
if (m < 1) return 'agora';
if (m < 60) return `há ${m} min`;
const h = Math.floor(m / 60);
if (h < 24) return `há ${h}h`;
return `há ${Math.floor(h / 24)}d`;
} catch {
return iso;
}
}
function incidentCard(inc) {
const active = state.selectedIncidentId === inc.id ? ' ao-incident-card--active' : '';
return `
Carregando…
'; const data = await agentsApi(`/threads/${threadId}/messages`); box.innerHTML = data.messages.map(threadBubble).join('') || 'Sem mensagens.
'; box.scrollTop = box.scrollHeight; } function bindShell(el) { el.querySelector('#ao-btn-refresh')?.addEventListener('click', () => renderAgenticOps()); el.querySelectorAll('[data-agent-id]').forEach((node) => { node.addEventListener('click', () => { state.selectedAgent = node.dataset.agentId; renderAgenticOps(); }); }); el.querySelectorAll('[data-incident-id], [data-open-incident]').forEach((node) => { node.addEventListener('click', async (ev) => { if (ev.target.closest('[data-ack-incident]')) return; const id = parseInt(node.dataset.incidentId || node.dataset.openIncident, 10); state.selectedIncidentId = id; const card = el.querySelector(`[data-incident-id="${id}"]`); const tid = parseInt(card?.dataset.threadId, 10); if (tid) await loadThread(el, tid); renderAgenticOps(); }); }); el.querySelectorAll('[data-ack-incident]').forEach((btn) => { btn.addEventListener('click', async (ev) => { ev.stopPropagation(); await agentsApi(`/incidents/${btn.dataset.ackIncident}/ack`, { method: 'POST' }); if (state.selectedIncidentId === parseInt(btn.dataset.ackIncident, 10)) { state.selectedIncidentId = null; state.threadId = null; } await renderAgenticOps(); }); }); el.querySelector('#ao-btn-reply')?.addEventListener('click', async () => { const input = el.querySelector('#ao-reply-input'); const tid = state.threadId; const body = (input?.value || '').trim(); if (!tid || !body) return; await agentsApi(`/threads/${tid}/reply`, { method: 'POST', body: JSON.stringify({ body, target_agent: state.selectedAgent }), }); input.value = ''; await loadThread(el, tid); }); el.querySelector('#ao-btn-chat')?.addEventListener('click', async () => { const input = el.querySelector('#ao-chat-input'); const out = el.querySelector('#ao-chat-answer'); const q = (input?.value || '').trim(); if (!q) return; out.hidden = false; out.innerHTML = 'A pensar…
'; try { const res = await agentsApi('/chat', { method: 'POST', body: JSON.stringify({ question: q, include_findings: true, target_agent: state.selectedAgent }), }); out.innerHTML = `${esc(state.selectedAgent)}
${esc(res.answer)}
`; if (res.thread_id) { state.threadId = res.thread_id; await loadThread(el, res.thread_id); } } catch (err) { out.innerHTML = `${esc(err.message)}
`; } }); el.querySelectorAll('.ao-mobile-tabs button').forEach((btn) => { btn.addEventListener('click', () => { state.mobileTab = btn.dataset.aoTab; el.querySelectorAll('.ao-mobile-tabs button').forEach((b) => b.classList.toggle('active', b === btn)); el.querySelectorAll('.ao-pane').forEach((p) => { p.classList.toggle('ao-pane--active', p.dataset.aoPane === state.mobileTab); }); }); }); } function schedulePoll() { if (state.pollTimer) clearInterval(state.pollTimer); state.pollTimer = setInterval(() => { if (document.hidden) return; const view = document.getElementById('view-agentic-ops'); if (view && !view.hidden) renderAgenticOps({ poll: true }); }, 30000); } async function renderAgenticOps(options = {}) { const el = document.getElementById('agentic-ops-content'); if (!el) return; if (!options.poll) { el.innerHTML = '' + 'Sessão não encontrada. Fazer login
'; return; } if (!options.poll && typeof ensureValidSession === 'function') { const ok = await ensureValidSession(); if (!ok) { el.innerHTML = 'Sessão expirada. Fazer login
'; return; } } try { const [overview, incidents, roster, timeline] = await Promise.all([ agentsApi('/overview'), agentsApi('/incidents?status=open&limit=50'), agentsApi('/roster'), agentsApi('/timeline?limit=12'), ]); const list = incidents.incidents || []; const openAgents = new Set(list.map((i) => i.primary_agent)); const filtered = state.selectedAgent && state.selectedAgent !== 'ALL' ? list.filter((i) => i.primary_agent === state.selectedAgent) : list; const bySev = { critical: [], high: [], warn: [], info: [] }; filtered.forEach((inc) => { const k = bySev[inc.severity] ? inc.severity : 'warn'; (bySev[k] || bySev.warn).push(inc); }); const sel = list.find((i) => i.id === state.selectedIncidentId); const ollamaPill = overview.ollama ? `Ollama · ${esc(overview.model)}` : 'Ollama offline'; const tier = overview.tier === 't1' ? 'T1 LLM' : 'T0'; const open = overview.incidents_open || {}; const boardCols = SEV_COLS.map((col) => { const cards = (bySev[col.key] || []).map(incidentCard).join('') || ''; return `✓ Ambiente saudável — nenhum incidente aberto.
Erro: ${esc(err.message)}
`; } } document.addEventListener('keydown', (ev) => { if (ev.key === 'r' && !ev.ctrlKey && !ev.metaKey && document.getElementById('view-agentic-ops') && !document.getElementById('view-agentic-ops').hidden) { const t = ev.target; if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA')) return; ev.preventDefault(); renderAgenticOps(); } if (ev.key === 'Escape') { state.selectedIncidentId = null; state.threadId = null; renderAgenticOps(); } }); window.renderAgenticOps = renderAgenticOps; })();