App._agentsTab = 'roster';
App._availableModelsCache = [];
App._availableModelsProvidersReport = {};
App._availableModelsProxyRuntime = {};
App._availableModelsFetchedAt = 0;
App._availableModelsInFlight = null;
App._loadAvailableModels = function(opts) {
      opts = opts || {};
      var self = this;
      var now = Date.now();
      var cacheTtlMs = opts.cacheTtlMs != null ? opts.cacheTtlMs : 300000;
      var timeoutMs = opts.timeoutMs != null ? opts.timeoutMs : 1200;
      var skipFetch = !!opts.skipFetch;
      var validationLevel = (opts.validationLevel || 'zero').toString().toLowerCase();
      var cached = Array.isArray(self._availableModelsCache) ? self._availableModelsCache : [];
      var cacheFresh = self._availableModelsFetchedAt && ((now - self._availableModelsFetchedAt) < cacheTtlMs);

      if (cacheFresh && !opts.forceRefresh) return Promise.resolve(cached);
      if (skipFetch) return Promise.resolve(cached);

      if (!self._availableModelsInFlight) {
        var modelsPath = '/api/models/available?validation_level=' + encodeURIComponent(validationLevel);
        self._availableModelsInFlight = api(modelsPath)
          .then(function(payload) {
            var models = (payload && payload.models) || [];
            self._availableModelsCache = Array.isArray(models) ? models : [];
            self._availableModelsProvidersReport = (payload && payload.providers) || {};
            self._availableModelsProxyRuntime = (payload && payload.proxy) || {};
            self._availableModelsFetchedAt = Date.now();
            return self._availableModelsCache;
          })
          .catch(function() {
            return cached;
          })
          .finally(function() {
            self._availableModelsInFlight = null;
          });
      }

      // For UI paths, prefer responsiveness over waiting on slow provider scans.
      if (opts.nonBlocking) return Promise.resolve(cached);

      return Promise.race([
        self._availableModelsInFlight,
        new Promise(function(resolve) { setTimeout(function() { resolve(cached); }, timeoutMs); })
      ]);
};
App.renderAgents = function() {
      var self = this;
      var tab = self._agentsTab || 'roster';
      var tabs = '<div class="tabs" style="margin-bottom:1rem">'
        + '<button class="' + (tab === 'roster' ? 'active' : '') + '" data-agents-tab="roster">Roster</button>'
        + '<button class="' + (tab === 'list' ? 'active' : '') + '" data-agents-tab="list">List</button>'
        + '</div>';
      var render = tab === 'list' ? self._renderListTab() : self._renderRosterTab();
      return render.then(function(body) { return tabs + body; });
};
App._renderRosterTab = function() {
      return api('/api/roster').then(function(data) {
        var roster = data.roster || [];
        if (roster.length === 0) return '<p style="color:var(--muted)">No taskable agents found.</p>';

        var grid = roster.map(function(agent) {
          var isCmd = agent.role === 'orchestrator';
          var borderColor = agent.color || 'var(--accent)';
          var stateColor = agent.state === 'Running' ? '#22c55e' : (agent.state === 'Error' ? '#ef4444' : (agent.state === 'Disabled' ? '#9baad6' : '#eab308'));
          var stateDot = '<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:' + stateColor + ';margin-right:6px"></span>';
          var displayName = agent.display_name || agent.name;
          var model = agent.model || '—';
          var modelShort = model.length > 28 ? model.substring(model.lastIndexOf('/') + 1) : model;
          var sessionCount = agent.session_count != null ? agent.session_count : '\u2014';
          var lastUsedLabel = formatTimestampLabel(agent.last_used_at);

          var roleLabel = isCmd ? 'ORCHESTRATOR' : 'SUBAGENT';
          var roleBg = isCmd ? 'rgba(234,179,8,0.15)' : 'rgba(193,128,255,0.15)';
          var roleColor = isCmd ? '#eab308' : borderColor;

          var card = '<div class="card roster-card" data-roster-id="' + esc(agent.name || agent.id) + '" style="cursor:pointer;border-left:3px solid ' + borderColor + ';padding:1rem;transition:transform 0.15s,box-shadow 0.15s' + (!agent.enabled ? ';opacity:0.5' : '') + '">'
            + '<div style="display:flex;align-items:flex-start;justify-content:space-between;gap:0.75rem;margin-bottom:0.5rem">'
            + '<div style="display:flex;align-items:flex-start;gap:0.5rem;flex:1;min-width:0">'
            + stateDot
            + '<span style="font-weight:700;font-size:1rem;line-height:1.2;color:var(--text);display:block;min-width:0;overflow-wrap:anywhere;word-break:break-word">' + esc(displayName) + '</span>'
            + '</div>'
            + '<span style="font-size:0.65rem;font-weight:600;letter-spacing:0.05em;padding:2px 8px;border-radius:3px;background:' + roleBg + ';color:' + roleColor + ';flex:0 0 auto;white-space:nowrap;align-self:flex-start">' + roleLabel + '</span>'
            + '</div>'
            + '<div style="font-size:0.75rem;color:var(--muted);margin-bottom:0.4rem;font-family:var(--mono)">' + esc(modelShort) + '</div>'
            + '<div style="display:flex;gap:1rem;font-size:0.75rem;color:var(--muted);flex-wrap:wrap">'
            + (function() {
                var sk = agent.skills || [];
                if (sk.length === 0) return '<span>0 skills</span>';
                var maxShow = 3;
                var shown = sk.slice(0, maxShow).map(function(s) {
                  var name = typeof s === 'string' ? s : (s.name || String(s));
                  return '<span class="badge muted" style="font-size:0.6rem">' + esc(name) + '</span>';
                }).join(' ');
                var overflow = sk.length > maxShow ? ' <span style="font-size:0.6rem;color:var(--muted)">+' + (sk.length - maxShow) + '</span>' : '';
                return shown + overflow;
              })()
            + '<span>' + sessionCount + ' sessions</span>'
            + '<span>last used ' + esc(lastUsedLabel) + '</span>'
            + '</div>'
            + '</div>';
          return card;
        }).join('');

        var cmdCount = roster.filter(function(a) { return a.role === 'orchestrator'; }).length;
        var specCount = roster.filter(function(a) { return a.role === 'subagent'; }).length;
        var header = '<div style="display:flex;align-items:baseline;gap:1rem;margin-bottom:1rem;flex-wrap:wrap">'
          + '<span style="font-size:0.8125rem;color:var(--muted)">' + roster.length + ' taskable agents</span>'
          + '<span class="badge">' + cmdCount + ' orchestrator</span>'
          + '<span class="badge">' + specCount + ' subagents</span>'
          + '</div>';

        return header
          + '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0.75rem">' + grid + '</div>'
          + '<div id="roster-modal" style="display:none;position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);padding:2rem;overflow-y:auto"></div>';
      });
};
App._rosterCache = null;
App._renderListTab = function() {
      var self = this;
      return Promise.all([
        api('/api/subagents'),
        self._loadAvailableModels({ nonBlocking: true, skipFetch: true }),
        fetchWithFallback('/api/skills', { skills: [] }, 'skills')
      ]).then(function(arr) {
        var data = arr[0] || {};
        var discoveredModels = arr[1] || [];
        var skillsData = (arr[2] && arr[2].data) ? arr[2].data : { skills: [] };
        var agents = data.agents || [];
        var skillRecords = (skillsData.skills || []).filter(function(s) { return s && s.name; });
        var skillNameSet = {};
        var allSkillNames = [];
        skillRecords.forEach(function(s) {
          var key = String(s.name).toLowerCase();
          if (!skillNameSet[key]) {
            skillNameSet[key] = true;
            allSkillNames.push(String(s.name));
          }
        });
        allSkillNames.sort();
        var enabledSkillNames = skillRecords
          .filter(function(s) { return !!s.enabled; })
          .map(function(s) { return String(s.name); });
        var enabledSkillCount = enabledSkillNames.length;
        var enabledSkillHint = enabledSkillNames.length
          ? enabledSkillNames.slice(0, 10).join(', ') + (enabledSkillNames.length > 10 ? ' ...' : '')
          : 'No enabled skills found. Enable skills from the Skills page first.';
        var skillOptions = allSkillNames
          .map(function(name) { return '<option value="' + esc(name) + '"></option>'; })
          .join('');
        var specialists = agents.filter(function(a) { return a.role === 'subagent' || a.role === 'specialist'; });
        var proxies = agents.filter(function(a) { return a.role === 'model-proxy'; });
        var enabledCount = specialists.filter(function(a) { return a.enabled; }).length;
        var modelOptions = self._renderModelOptionsHtml({
          discoveredModels: discoveredModels,
          roster: specialists,
          config: _cachedConfig,
          includeControlModes: true
        });

        var html = '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem"><div>';
        html += '<span style="font-size:1.5rem;font-weight:700;color:var(--text)">' + specialists.length + ' Sub-Agents</span>';
        html += '<span style="margin-left:0.75rem;font-size:0.8125rem;color:var(--muted)">' + enabledCount + ' enabled</span>';
        html += '<span style="margin-left:0.75rem;font-size:0.8125rem;color:var(--muted)">' + enabledSkillCount + ' shared runtime skills</span>';
        html += '</div>';
        html += '<button class="btn" id="sa-add-btn" style="font-size:0.75rem;padding:0.4rem 1rem">+ Add Agent</button>';
        html += '</div>';
        if (proxies.length > 0) {
          html += '<div class="card" style="margin-bottom:0.75rem;padding:0.75rem 1rem;font-size:0.75rem;color:var(--muted)">'
            + proxies.length + ' model prox' + (proxies.length === 1 ? 'y is' : 'ies are')
            + ' hidden from this taskable sub-agent list.'
            + '</div>';
        }

        function agentCard(a) {
          var c = '';
          var skills = a.skills || [];
          var fixedSkillCount = skills.length;
          var lastUsedLabel = formatTimestampLabel(a.last_used_at);
          var statusBadge = a.enabled
            ? '<span class="badge success">enabled</span>'
            : '<span class="badge" style="background:var(--surface);color:var(--muted)">disabled</span>';
          var roleBadge = '<span class="badge" style="background:rgba(193,128,255,0.15);color:#818cf8;margin-left:0.25rem">' + esc(a.role) + '</span>';
          c += '<div class="card" style="margin-bottom:0.75rem;opacity:' + (a.enabled ? '1' : '0.6') + '">';
          c += '<div style="display:flex;align-items:center;justify-content:space-between">';
          c += '<div style="display:flex;align-items:center;gap:0.5rem">';
          c += '<span style="font-size:1.25rem">\uD83E\uDD16</span>';
          c += '<div>';
          c += '<div style="font-weight:600;color:var(--text)">' + esc(a.display_name || a.name) + '</div>';
          c += '<div style="font-size:0.6875rem;color:var(--muted);font-family:var(--font-mono)">' + esc(a.name) + '</div>';
          c += '</div>';
          c += '</div>';
          c += '<div style="display:flex;align-items:center;gap:0.5rem">' + statusBadge + roleBadge + '</div>';
          c += '</div>';

          c += '<div style="display:flex;gap:1rem;margin-top:0.75rem;font-size:0.75rem;color:var(--muted)">';
          if (a.model) c += '<div><span style="color:var(--text-dim)">Model:</span> ' + esc(a.model) + '</div>';
          if (a.fallback_models && a.fallback_models.length) c += '<div><span style="color:var(--text-dim)">Fallbacks:</span> ' + esc(a.fallback_models.join(', ')) + '</div>';
          if (a.model_mode && a.model_mode !== 'fixed') c += '<div><span style="color:var(--text-dim)">Mode:</span> ' + esc(a.model_mode) + '</div>';
          if (a.resolved_model) c += '<div><span style="color:var(--text-dim)">Resolved:</span> ' + esc(a.resolved_model) + '</div>';
          c += '<div><span style="color:var(--text-dim)">Fixed skills:</span> '
            + '<button class="sa-edit-skills"'
            + ' data-name="' + esc(a.name) + '"'
            + ' data-display="' + esc(a.display_name || '') + '"'
            + ' data-model="' + esc(a.model || '') + '"'
            + ' data-fallbacks="' + esc((a.fallback_models || []).join(",")) + '"'
            + ' data-role="' + esc(a.role) + '"'
            + ' data-skills="' + esc((a.skills || []).join(",")) + '"'
            + ' data-desc="' + esc(a.description || '') + '"'
            + ' style="margin-left:0.25rem;background:transparent;border:1px solid var(--border);border-radius:4px;padding:0.05rem 0.35rem;color:var(--text);cursor:pointer;font-size:0.7rem">'
            + fixedSkillCount
            + '</button></div>';
          if (skills.length > 0) {
            c += '<div style="display:flex;flex-wrap:wrap;gap:3px;margin-top:4px">';
            skills.forEach(function(s) {
              var name = typeof s === 'string' ? s : (s.name || String(s));
              c += '<span class="badge muted" style="font-size:0.6rem">' + esc(name) + '</span>';
            });
            c += '</div>';
          }
          c += '<div><span style="color:var(--text-dim)">Shared skills:</span> ' + enabledSkillCount + '</div>';
          c += '<div><span style="color:var(--text-dim)">Sessions:</span> ' + (a.session_count != null ? a.session_count : '\u2014') + '</div>';
          c += '<div><span style="color:var(--text-dim)">Last used:</span> ' + esc(lastUsedLabel) + '</div>';
          if (a.description) c += '<div style="flex:1">' + esc(a.description) + '</div>';
          c += '</div>';

          c += '<div style="display:flex;gap:0.5rem;margin-top:0.75rem;border-top:1px solid var(--border);padding-top:0.6rem">';
          c += '<button class="btn secondary sa-toggle" data-name="' + esc(a.name) + '" style="font-size:0.6875rem;padding:0.25rem 0.6rem">' + (a.enabled ? 'Disable' : 'Enable') + '</button>';
          c += '<button class="btn secondary sa-edit" data-name="' + esc(a.name) + '" data-display="' + esc(a.display_name || '') + '" data-model="' + esc(a.model || '') + '" data-fallbacks="' + esc((a.fallback_models || []).join(",")) + '" data-role="' + esc(a.role) + '" data-skills="' + esc((a.skills || []).join(",")) + '" data-desc="' + esc(a.description || '') + '" style="font-size:0.6875rem;padding:0.25rem 0.6rem">Edit</button>';
          c += '<button class="btn secondary sa-delete" data-name="' + esc(a.name) + '" style="font-size:0.6875rem;padding:0.25rem 0.6rem;color:var(--error)">Delete</button>';
          c += '</div>';
          c += '</div>';
          return c;
        }

        if (specialists.length > 0) {
          html += '<div style="font-size:0.8125rem;font-weight:600;color:var(--text);margin-bottom:0.5rem;text-transform:uppercase;letter-spacing:0.05em">Subagents</div>';
          specialists.forEach(function(a) { html += agentCard(a); });
        }

        if (specialists.length === 0) {
          html += '<div class="card" style="text-align:center;padding:3rem"><div style="font-size:2rem;margin-bottom:0.5rem">\uD83E\uDD16</div>';
          html += '<div style="color:var(--muted)">No taskable sub-agents configured</div>';
          html += '<div style="font-size:0.75rem;color:var(--muted);margin-top:0.5rem">Import a prior agent export with <code style="background:var(--surface);padding:0.1rem 0.4rem;border-radius:4px">roboticus migrate import &lt;export-root&gt; --areas agents</code> or add one below</div>';
          html += '</div>';
        }

        html += '<div id="sa-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:100;display:none;align-items:center;justify-content:center">';
        html += '<div style="background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.5rem;width:min(440px,90vw)">';
        html += '<div style="font-weight:600;font-size:1rem;margin-bottom:1rem" id="sa-modal-title">Add Sub-Agent</div>';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Name (kebab-case)</label>';
        html += '<input class="settings-input" id="sa-m-name" placeholder="e.g. data-analyst" style="margin-bottom:0.75rem;font-family:var(--font-mono)">';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Display Name</label>';
        html += '<input class="settings-input" id="sa-m-display" placeholder="e.g. Data Analyst" style="margin-bottom:0.75rem">';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Model</label>';
        html += '<input class="settings-input" id="sa-m-model" list="sa-model-options" placeholder="e.g. ollama/qwen3:8b | auto | orchestrator" style="margin-bottom:0.75rem;font-family:var(--font-mono)">';
        html += '<datalist id="sa-model-options">' + modelOptions + '</datalist>';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Fallback Models (comma-separated)</label>';
        html += '<input class="settings-input" id="sa-m-fallbacks" list="sa-model-options" placeholder="e.g. openrouter/openai/gpt-4o, moonshot/kimi-k2-turbo-preview" style="margin-bottom:0.75rem;font-family:var(--font-mono)">';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Role</label>';
        html += '<select class="settings-input" id="sa-m-role" style="margin-bottom:0.75rem"><option value="subagent">subagent</option><option value="model-proxy">model-proxy</option></select>';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Fixed Skills (comma-separated)</label>';
        html += '<input class="settings-input" id="sa-m-skills" list="sa-skill-options" placeholder="e.g. research,summarization" style="margin-bottom:0.35rem">';
        html += '<datalist id="sa-skill-options">' + skillOptions + '</datalist>';
        html += '<div id="sa-m-skills-help" style="font-size:0.6875rem;color:var(--muted);margin-bottom:0.75rem">Available: ' + esc(enabledSkillHint) + '</div>';
        html += '<label style="font-size:0.75rem;color:var(--muted);display:block;margin-bottom:0.25rem">Description</label>';
        html += '<textarea class="settings-input" id="sa-m-desc" rows="2" placeholder="What does this agent do?" style="margin-bottom:1rem;resize:vertical"></textarea>';
        html += '<div style="display:flex;gap:0.5rem;justify-content:flex-end">';
        html += '<button class="btn secondary" id="sa-m-cancel" style="font-size:0.75rem;padding:0.35rem 1rem">Cancel</button>';
        html += '<button class="btn" id="sa-m-save" style="font-size:0.75rem;padding:0.35rem 1rem">Save</button>';
        html += '</div></div></div>';

        setTimeout(function() {
          var modal = document.getElementById('sa-modal');
          var editingName = null;
          var skillsHelpDefault = 'Available: ' + enabledSkillHint;

          function syncRoleSkillsState() {
            var role = ((document.getElementById('sa-m-role') || {}).value || 'subagent').toLowerCase();
            var skillsInput = document.getElementById('sa-m-skills');
            var help = document.getElementById('sa-m-skills-help');
            if (!skillsInput || !help) return;
            if (role === 'model-proxy') {
              skillsInput.disabled = true;
              skillsInput.value = '';
              help.textContent = 'Model proxies cannot own fixed skills. Set role to subagent to assign skills.';
            } else {
              skillsInput.disabled = false;
              help.textContent = skillsHelpDefault;
            }
          }

          function openModal(title, vals) {
            if (!modal) return;
            modal.style.display = 'flex';
            var t = document.getElementById('sa-modal-title'); if (t) t.textContent = title;
            var nameInp = document.getElementById('sa-m-name');
            if (nameInp) { nameInp.value = vals.name || ''; nameInp.disabled = !!vals.editing; }
            var d = document.getElementById('sa-m-display'); if (d) d.value = vals.display || '';
            var m = document.getElementById('sa-m-model'); if (m) m.value = vals.model || '';
            var fb = document.getElementById('sa-m-fallbacks'); if (fb) fb.value = vals.fallbacks || '';
            var r = document.getElementById('sa-m-role'); if (r) r.value = vals.role || 'subagent';
            var sk = document.getElementById('sa-m-skills'); if (sk) sk.value = vals.skills || '';
            var desc = document.getElementById('sa-m-desc'); if (desc) desc.value = vals.desc || '';
            editingName = vals.editing || null;
            syncRoleSkillsState();
          }

          function closeModal() { if (modal) modal.style.display = 'none'; editingName = null; }

          var addBtn = document.getElementById('sa-add-btn');
          if (addBtn) addBtn.onclick = function() { openModal('Add Sub-Agent', {}); };

          var cancelBtn = document.getElementById('sa-m-cancel');
          if (cancelBtn) cancelBtn.onclick = closeModal;

          if (modal) modal.onclick = function(e) { if (e.target === modal) closeModal(); };
          var roleSelect = document.getElementById('sa-m-role');
          if (roleSelect) roleSelect.onchange = syncRoleSkillsState;

          var saveBtn = document.getElementById('sa-m-save');
          if (saveBtn) saveBtn.onclick = function() {
            var nameVal = (document.getElementById('sa-m-name') || {}).value || '';
            var displayVal = (document.getElementById('sa-m-display') || {}).value || '';
            var modelVal = (document.getElementById('sa-m-model') || {}).value || '';
            var fallbackVals = (document.getElementById('sa-m-fallbacks') || {}).value || '';
            var roleVal = (document.getElementById('sa-m-role') || {}).value || 'subagent';
            var skillsVal = (document.getElementById('sa-m-skills') || {}).value || '';
            var skills = skillsVal.split(',').map(function(s) { return s.trim(); }).filter(Boolean);
            var fallbacks = fallbackVals.split(',').map(function(s) { return s.trim(); }).filter(Boolean);
            var descVal = (document.getElementById('sa-m-desc') || {}).value || '';
            if (!nameVal && !editingName) { toast('Name is required'); return; }

            if (editingName) {
              api('/api/subagents/' + encodeURIComponent(editingName), {
                method: 'PUT', headers: authHeaders({ 'Content-Type': 'application/json', 'Accept': 'application/json' }),
                body: JSON.stringify({ display_name: displayVal || null, model: modelVal || null, fallback_models: fallbacks, role: roleVal, skills: skills, description: descVal || null })
              }).then(function() { toast('Agent updated'); closeModal(); self.navigate('agents'); });
            } else {
              api('/api/subagents', {
                method: 'POST', headers: authHeaders({ 'Content-Type': 'application/json', 'Accept': 'application/json' }),
                body: JSON.stringify({ name: nameVal, display_name: displayVal || null, model: modelVal, fallback_models: fallbacks, role: roleVal, skills: skills, description: descVal || null })
              }).then(function() { toast('Agent created'); closeModal(); self.navigate('agents'); });
            }
          };

          document.querySelectorAll('.sa-toggle').forEach(function(btn) {
            btn.onclick = function() {
              var n = this.getAttribute('data-name');
              api('/api/subagents/' + encodeURIComponent(n) + '/toggle', {
                method: 'PUT', headers: authHeaders({ 'Accept': 'application/json' })
              }).then(function() { toast('Agent toggled'); self.navigate('agents'); });
            };
          });

          document.querySelectorAll('.sa-edit').forEach(function(btn) {
            btn.onclick = function() {
              var n = this.getAttribute('data-name');
              openModal('Edit: ' + n, {
                name: n, editing: n,
                display: this.getAttribute('data-display'),
                model: this.getAttribute('data-model'),
                fallbacks: this.getAttribute('data-fallbacks'),
                role: this.getAttribute('data-role'),
                skills: this.getAttribute('data-skills'),
                desc: this.getAttribute('data-desc')
              });
            };
          });

          document.querySelectorAll('.sa-edit-skills').forEach(function(btn) {
            btn.onclick = function() {
              var n = this.getAttribute('data-name');
              openModal('Edit skills: ' + n, {
                name: n, editing: n,
                display: this.getAttribute('data-display'),
                model: this.getAttribute('data-model'),
                fallbacks: this.getAttribute('data-fallbacks'),
                role: this.getAttribute('data-role'),
                skills: this.getAttribute('data-skills'),
                desc: this.getAttribute('data-desc')
              });
              var input = document.getElementById('sa-m-skills');
              if (input && !input.disabled) input.focus();
            };
          });

          document.querySelectorAll('.sa-delete').forEach(function(btn) {
            btn.onclick = function() {
              var n = this.getAttribute('data-name');
              if (!confirm('Delete sub-agent "' + n + '"? This cannot be undone.')) return;
              api('/api/subagents/' + encodeURIComponent(n), {
                method: 'DELETE', headers: authHeaders({ 'Accept': 'application/json' })
              }).then(function() { toast('Agent deleted'); self.navigate('agents'); });
            };
          });
          if (self._pendingSubagentEdit) {
            var pending = self._pendingSubagentEdit;
            self._pendingSubagentEdit = null;
            openModal('Edit: ' + pending.name, pending);
          }
        }, 0);

        return html;
      });
};
