<!-- SAGA-SOLID · part 101 -->
"font-size:15px;font-weight:600;margin-bottom:4px;">' + escapeHtml(a.name) + '</div>' +
            '<div style="font-size:12px;color:#888;margin-bottom:8px;">' + a.capabilities.join(', ') + '</div>' +
            '<button data-agent="' + a.agentId + '" class="ai-connect-btn" style="padding:10px 16px;border-radius:8px;' +
            'border:1px solid #c8a860;background:rgba(200,168,96,0.12);color:#c8a860;font-size:14px;cursor:pointer;">' +
            'Connect</button></div>';
        });
        if(listEl) listEl.innerHTML = html;
        // Wire connect buttons
        var btns = listEl.querySelectorAll('.ai-connect-btn');
        btns.forEach(function(b){
          b.onclick = function(){ aiConnectAgent(b.getAttribute('data-agent')); };
        });
      })
      .catch(function(e){
        if(listEl) listEl.innerHTML = '<div style="color:#888;font-size:13px;">Error: ' + e.message + '</div>';
      });
  }

  function escapeHtml(s){
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  }

  // Register new agent
  document.getElementById('cockpit-aiconnect').onclick = function(){
    var name = document.getElementById('ai-name').value.trim();
    var endpoint = document.getElementById('ai-endpoint').value.trim();
    var authType = document.getElementById('ai-authtype').value;
    var credential = document.getElementById('ai-credential').value;
    var caps = [];
    if(document.getElementById('ai-perm-walk').checked) caps.push('walk');

    if(!name){ alert('Please enter an AI name.'); return; }

    fetch('/api/agent-drive/agents', {
      method: 'POST',
      headers: {'Content-Type': 'application/json', 'x-csrf-token': aiGetCsrf()},
      body: JSON.stringify({name: name, endpoint: endpoint, authType: authType, credential: credential, capabilities: caps}),
      credentials: 'same-origin'
    }).then(function(r){ return r.json(); })
      .then(function(j){
        if(j.ok){
          // Clear credential field immediately
          document.getElementById('ai-credential').value = '';
          aiLoadAgents();
        } else {
          alert('Failed: ' + (j.error || 'unknown'));
        }
      })
      .catch(function(e){ alert('Error: ' + e.message); });
  };

  // Connect agent → create agent-scoped session + token → connect bridge
  // SEMANTIC: This authorizes intent acceptance. It does NOT create movement.
  function aiConnectAgent(agentId){
    var agent = AI.agents.find(function(a){ return a.agentId === agentId; });
    if(!agent) return;
    fetch('/api/agent-drive/session-token', {
      method: 'POST',
      headers: {'Content-Type': 'application/json', 'x-csrf-token': aiGetCsrf()},
      body: JSON.stringify({agentId: agentId}),
      credentials: 'same-origin'
    }).then(function(r){ return r.json(); })
      .then(function(j){
        if(j.ok && j.epoch && j.agentToken){
          AI.activeAgent = agent;
          var SD = window.SOLID_DRIVE;
          if(SD){
            SD.connect(j.epoch);
            SD._sessionEpoch = j.epoch;
            SD._agentName = j.agentName;
          }
          // Display token ONCE — player gives it to their AI out-of-band
          aiShowToken(j.agentName, j.agentToken);
          refreshCockpit();
        } else {
          alert('Failed: ' + (j.error || 'unknown'));
        }
      })
      .catch(function(e){ alert('Error: ' + e.message); });
  }

  // Show token once with copy button. Never stored in browser beyond display.
  function aiShowToken(agentName, token){
    var existing = document.getElementById('ai-token-display');
    if(existing) existing.remove();
    var d = document.createElement('div');
    d.id = 'ai-token-display';
    d.style.cssText = 'position:fixed;top:50%;left:20px;right:20px;transform:translateY(-50%);' +
      'z-index:99999;background:rgba(8,8,12,0.98);border:2px solid #c8a860;border-radius:16px;' +
      'padding:24px;font-family:-apple-system,system-ui,sans-serif;color:#f0e8d8;text-align:center;';
    d.innerHTML =
      '<div style="font-size:16px;font-weight:700;margin-bottom:8px;color:#c8a860;">AGENT TOKEN</div>' +
      '<div style="font-size:13px;color:#8a8578;margin-bottom:12px;">Give this to ' + escapeHtml(agentName) + '. Shown once.</div>' +
      '<div style="font-family:monospace;font-size:13px;word-break:break-all;background:rgba(255,255,255,0.06);' +
      'padding:12px;border-radius:8px;margin-bottom:12px;color:#4ad0e0;">' + escapeHtml(token) + '</div>' +
      '<div style="font-size:12px;color:#8b1a1a;margin-bottom:16px;">This authorizes intent acceptance only. ' +
      'It does not move your avatar.</div>' +
      '<button id="ai-token-copy" style="padding:12px 24px;border-radius:8px;border:1px solid #c8a860;' +
      'background:rgba(200,168,96,0.12);color:#c8a860;font-size:15px;cursor:pointer;margin-right:8px;">Copy</button>' +
      '<button id="ai-token-done" style="padding:12px 24px;border-radius:8px;borde