<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent Monitor</title>
<style>
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  :root {
    --bg: var(--color-background-primary, #0f0f0f);
    --bg2: var(--color-background-secondary, #1a1a1a);
    --bg3: var(--color-background-tertiary, #242424);
    --text: var(--color-text-primary, #f5f5f5);
    --text2: var(--color-text-secondary, #a0a0a0);
    --border: var(--color-border-primary, #2e2e2e);
    --accent: var(--color-accent-primary, #6366f1);
    --danger: #ef4444; --success: #10b981; --warning: #f59e0b;
    --font: var(--font-sans, system-ui, -apple-system, sans-serif);
  }
  body { background: var(--bg); color: var(--text); font-family: var(--font); font-size: 13px; line-height: 1.5; padding: 12px; min-height: 100vh; }
  .header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; gap: 8px; }
  .title { font-size: 15px; font-weight: 600; flex: 1; }
  .badge { border-radius: 99px; padding: 2px 10px; font-size: 11px; font-weight: 600; white-space: nowrap; }
  .badge-active   { background: #065f46; color: #6ee7b7; }
  .badge-inactive { background: var(--bg3); color: var(--text2); }
  .badge-error    { background: #7f1d1d; color: #fca5a5; }
  .section-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text2); margin-bottom: 6px; }
  .info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
  .info-card { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
  .info-card-label { font-size: 10px; color: var(--text2); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 3px; }
  .info-card-value { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .info-card-value.mono { font-family: monospace; font-size: 12px; }
  .field { margin-bottom: 12px; }
  .field-label { font-size: 11px; color: var(--text2); margin-bottom: 4px; }
  .field-value { font-size: 12px; color: var(--text); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
  .stats-row { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
  .stat { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; flex: 1; min-width: 80px; }
  .stat-val { font-size: 18px; font-weight: 700; }
  .stat-lbl { font-size: 10px; color: var(--text2); text-transform: uppercase; }
  .budget-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
  .budget-bar-wrap { flex: 1; background: var(--bg3); border-radius: 99px; height: 6px; overflow: hidden; }
  .budget-bar-fill { height: 100%; border-radius: 99px; background: var(--accent); }
  .budget-bar-fill.warn { background: var(--warning); }
  .budget-bar-fill.danger { background: var(--danger); }
  .budget-text { font-size: 11px; color: var(--text2); white-space: nowrap; }
  .actions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
  .btn { border: none; border-radius: 6px; padding: 6px 12px; font-size: 12px; font-weight: 500; cursor: pointer; font-family: var(--font); transition: opacity 0.15s, filter 0.15s; }
  .btn:disabled { opacity: 0.4; cursor: not-allowed; }
  .btn:hover:not(:disabled) { filter: brightness(1.1); }
  .btn-primary { background: var(--accent); color: #fff; }
  .btn-danger  { background: var(--danger); color: #fff; }
  .btn-neutral { background: var(--bg3); color: var(--text); border: 1px solid var(--border); }
  .result-msg { margin-top: 8px; font-size: 12px; padding: 6px 10px; border-radius: 6px; }
  .result-msg.success { background: #064e3b; color: #6ee7b7; }
  .result-msg.error   { background: #450a0a; color: #fca5a5; }
  .spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: middle; margin-right: 4px; }
  @keyframes spin { to { transform: rotate(360deg); } }
  .loading { text-align: center; color: var(--text2); padding: 48px 0; }
  .empty-msg { color: var(--text2); font-size: 12px; padding: 24px 0; text-align: center; }
</style>
</head>
<body>
<div id="root"></div>
<script>
(function () {
  'use strict';

  var _id = 1, _pending = {}, _handlers = {};
  function mcpSend(method, params) { window.parent.postMessage({ jsonrpc: '2.0', method: method, params: params || {} }, '*'); }
  function mcpRequest(method, params) {
    return new Promise(function (resolve, reject) {
      var id = _id++;
      _pending[id] = { resolve: resolve, reject: reject };
      window.parent.postMessage({ jsonrpc: '2.0', id: id, method: method, params: params || {} }, '*');
      setTimeout(function () { if (_pending[id]) { delete _pending[id]; reject(new Error('Timeout')); } }, 30000);
    });
  }
  window.addEventListener('message', function (e) {
    var msg = e.data;
    if (!msg || msg.jsonrpc !== '2.0') return;
    if (msg.id && _pending[msg.id]) {
      var cb = _pending[msg.id]; delete _pending[msg.id];
      if (msg.error) cb.reject(new Error(msg.error.message || 'MCP error'));
      else cb.resolve(msg.result); return;
    }
    if (msg.method && _handlers[msg.method]) _handlers[msg.method](msg.params);
  });
  function callTool(name, args) { return mcpRequest('tools/call', { name: name, arguments: args || {} }); }

  var root = document.getElementById('root');
  var currentData = null;
  var initialDataReceived = false;

  function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text !== undefined) e.textContent = text; return e; }
  function clearEl(c) { while (c.firstChild) c.removeChild(c.firstChild); }
  function showLoading(msg) { clearEl(root); var d = el('div', 'loading'); var sp = el('span', 'spinner'); d.appendChild(sp); d.appendChild(document.createTextNode(' ' + (msg || 'Loading…'))); root.appendChild(d); }
  function showEmpty(msg) { clearEl(root); root.appendChild(el('div', 'empty-msg', msg)); }
  function fmtCredits(n) { return n !== null && n !== undefined ? Number(n).toFixed(2) + ' cr' : '—'; }
  function fmtNum(n) { return n !== null && n !== undefined ? Number(n).toLocaleString() : '—'; }

  function statusBadgeCls(status) {
    var s = (status || '').toLowerCase();
    if (s === 'active') return 'badge badge-active';
    if (s === 'error' || s === 'disabled') return 'badge badge-error';
    return 'badge badge-inactive';
  }

  function render(d) {
    currentData = d;
    clearEl(root);

    // Header
    var header = el('div', 'header');
    header.appendChild(el('div', 'title', d.name || 'Agent'));
    header.appendChild(el('span', statusBadgeCls(d.status), (d.status || 'unknown').replace(/_/g, ' ')));
    root.appendChild(header);

    // Info grid
    root.appendChild(el('div', 'section-label', 'Identity'));
    var grid = el('div', 'info-grid');
    function infoCard(label, value, mono) {
      var card = el('div', 'info-card');
      card.appendChild(el('div', 'info-card-label', label));
      card.appendChild(el('div', 'info-card-value' + (mono ? ' mono' : ''), value || '—'));
      return card;
    }
    grid.appendChild(infoCard('Provider', d.provider));
    grid.appendChild(infoCard('Model', d.model, true));
    grid.appendChild(infoCard('Scope', d.scope));
    grid.appendChild(infoCard('Budget', fmtCredits(d.budget_spent) + ' / ' + fmtCredits(d.budget_cap)));
    root.appendChild(grid);

    // Role / Goal / Backstory
    if (d.role) { var rf = el('div', 'field'); rf.appendChild(el('div', 'field-label', 'Role')); rf.appendChild(el('div', 'field-value', d.role)); root.appendChild(rf); }
    if (d.goal) { var gf = el('div', 'field'); gf.appendChild(el('div', 'field-label', 'Goal')); gf.appendChild(el('div', 'field-value', d.goal)); root.appendChild(gf); }

    // Budget bar
    var cap = Number(d.budget_cap) || 0;
    var spent = Number(d.budget_spent) || 0;
    var pct = cap > 0 ? Math.min(100, (spent / cap) * 100) : 0;
    root.appendChild(el('div', 'section-label', 'Budget'));
    var budgetRow = el('div', 'budget-row');
    var barWrap = el('div', 'budget-bar-wrap');
    var barFill = el('div', 'budget-bar-fill' + (pct >= 90 ? ' danger' : pct >= 70 ? ' warn' : ''));
    barFill.style.width = pct.toFixed(1) + '%';
    barWrap.appendChild(barFill); budgetRow.appendChild(barWrap);
    budgetRow.appendChild(el('span', 'budget-text', fmtCredits(spent) + ' / ' + fmtCredits(cap)));
    root.appendChild(budgetRow);

    // Runtime stats
    var rs = d.runtime_state;
    if (rs) {
      root.appendChild(el('div', 'section-label', 'Runtime'));
      var statsRow = el('div', 'stats-row');
      function stat(val, lbl) { var s = el('div', 'stat'); s.appendChild(el('div', 'stat-val', val)); s.appendChild(el('div', 'stat-lbl', lbl)); return s; }
      statsRow.appendChild(stat(fmtNum(rs.total_executions), 'Runs'));
      statsRow.appendChild(stat(fmtNum(rs.total_cost_credits), 'Credits'));
      statsRow.appendChild(stat(fmtNum(rs.total_input_tokens), 'In tokens'));
      statsRow.appendChild(stat(fmtNum(rs.total_output_tokens), 'Out tokens'));
      root.appendChild(statsRow);
      if (rs.last_error) { var ef = el('div', 'field'); ef.appendChild(el('div', 'field-label', 'Last Error')); ef.appendChild(el('div', 'field-value', rs.last_error)); root.appendChild(ef); }
    }

    // Actions
    root.appendChild(el('div', 'section-label', 'Actions'));
    var actionsWrap = el('div', 'actions');
    actionsWrap.id = 'agent-actions';

    var isActive = (d.status || '').toLowerCase() === 'active';
    var toggleBtn = el('button', 'btn ' + (isActive ? 'btn-danger' : 'btn-primary'), isActive ? 'Disable' : 'Enable');
    toggleBtn.addEventListener('click', function () {
      doAction(isActive ? 'disable' : 'enable', 'agent_toggle_status', { agent_id: d.id, status: isActive ? 'inactive' : 'active' });
    });
    actionsWrap.appendChild(toggleBtn);

    var healthBtn = el('button', 'btn btn-neutral', 'Health Check');
    healthBtn.addEventListener('click', function () { doAction('health check', 'agent_heartbeat_run_now', { agent_id: d.id }); });
    actionsWrap.appendChild(healthBtn);

    root.appendChild(actionsWrap);

    var msgEl = el('div');
    msgEl.id = 'agent-result';
    root.appendChild(msgEl);
  }

  function doAction(label, toolName, args) {
    var actEl = document.getElementById('agent-actions');
    var msgEl = document.getElementById('agent-result');
    if (actEl) Array.from(actEl.querySelectorAll('.btn')).forEach(function (b) { b.disabled = true; });
    if (msgEl) { msgEl.textContent = ''; msgEl.className = ''; }

    callTool(toolName, args)
      .then(function () {
        if (msgEl) { msgEl.textContent = '✓ ' + label.charAt(0).toUpperCase() + label.slice(1) + ' complete.'; msgEl.className = 'result-msg success'; }
        mcpSend('ui/update-model-context', { content: [{ type: 'text', text: 'Agent ' + ((currentData && currentData.id) ? currentData.id.slice(0, 8) : '') + ': ' + label + '.' }] });
        setTimeout(function () { if (currentData && currentData.id) loadAgent(currentData.id); }, 1200);
      })
      .catch(function (err) {
        if (msgEl) { msgEl.textContent = '✗ ' + err.message; msgEl.className = 'result-msg error'; }
        if (actEl) Array.from(actEl.querySelectorAll('.btn')).forEach(function (b) { b.disabled = false; });
      });
  }

  function loadAgent(id) {
    if (!id) { showEmpty('No agent ID. Call agent_get to load one.'); return; }
    showLoading('Loading agent…');
    callTool('agent_get', { agent_id: id })
      .then(function (result) {
        var text = result && result.content && result.content[0] && result.content[0].text;
        if (!text) throw new Error('Empty response');
        render(JSON.parse(text));
      })
      .catch(function (err) { showEmpty('Failed to load: ' + err.message); });
  }

  _handlers['ui/notifications/tool-result'] = function (params) {
    var text = params && params.content && params.content[0] && params.content[0].text;
    if (!text) return;
    try { var d = JSON.parse(text); if (d.id && d.status !== undefined && d.name !== undefined) { initialDataReceived = true; render(d); } } catch (_) {}
  };

  showLoading('Connecting…');
  mcpRequest('ui/initialize', { protocolVersion: '2026-01-26', clientInfo: { name: 'fleetq-agent-monitor', version: '1.0.0' }, appCapabilities: {} })
    .then(function () { mcpSend('ui/notifications/initialized', {}); })
    .catch(function () {})
    .finally(function () {
      setTimeout(function () { if (!initialDataReceived) showEmpty('No agent data received. Call agent_get first.'); }, 600);
    });

})();
</script>
</body>
</html>
