function toast(msg) {
var c = document.getElementById('toasts'); if (!c) return;
var el = document.createElement('div'); el.className = 'toast'; el.textContent = msg;
c.appendChild(el); setTimeout(function() { el.remove(); }, 4000);
}
var AUTH_CHECKED = false;
var AUTH_REQUIRED = false;
var API_KEY = null;
function authHeaders(extra) {
var h = extra || { 'Accept': 'application/json' };
if (API_KEY) h['Authorization'] = 'Bearer ' + API_KEY;
return h;
}
function ensureAuth() {
if (AUTH_CHECKED) return Promise.resolve();
return fetch(BASE + '/api/health', { headers: { 'Accept': 'application/json' } })
.then(function() {
AUTH_CHECKED = true;
AUTH_REQUIRED = false;
return fetch(BASE + '/api/config', { headers: { 'Accept': 'application/json' } });
})
.then(function(r) {
if (r.status === 401) {
AUTH_REQUIRED = true;
API_KEY = prompt('Enter API key:');
if (API_KEY === '' || API_KEY === null) API_KEY = null;
}
AUTH_CHECKED = true;
})
.catch(function() { AUTH_CHECKED = true; });
}
function api(path, opts) {
opts = opts || {};
var url = BASE + path;
var defaultHeaders = { 'Accept': 'application/json' };
if (opts.body) defaultHeaders['Content-Type'] = 'application/json';
var headers = opts.headers ? authHeaders(opts.headers) : authHeaders(defaultHeaders);
return fetch(url, { headers: headers, method: opts.method || 'GET', body: opts.body }).then(function(r) {
if (!r.ok) return r.text().then(function(t) {
var msg = r.statusText; var pd = null;
try { pd = JSON.parse(t); msg = pd.detail || pd.title || pd.error || t; } catch(_) { msg = t || msg; }
var err = new Error(msg);
err.status = r.status;
err.problem = pd;
throw err;
});
var ct = r.headers.get('content-type');
if (ct && ct.indexOf('application/json') !== -1) return r.json();
return r.text();
});
}
function fetchWithFallback(url, fallback, label) {
return api(url)
.then(function(data) { return { ok: true, data: data, label: label }; })
.catch(function(err) {
return {
ok: false,
data: fallback,
label: label,
error: (err && err.message) ? err.message : String(err || 'unknown error')
};
});
}
function applySidebarIdentity(agentStatus, health) {
var agent = agentStatus || {};
var healthData = health || {};
if (agent.name) setAgentDisplayName(agent.name);
else if (healthData.agent) setAgentDisplayName(healthData.agent);
var state = String(agent.state || healthData.status || 'unknown').toLowerCase();
var dotEl = document.getElementById('agent-dot');
if (dotEl) {
dotEl.className = 'status-dot' + (state === 'running' ? '' : state === 'sleeping' ? ' warning' : ' error');
}
var stateEl = document.getElementById('agent-state');
if (stateEl) stateEl.textContent = state || 'unknown';
var ve = document.getElementById('version');
if (ve) ve.textContent = healthData.version || 'unknown';
}
function refreshSidebarIdentity() {
return Promise.all([
api('/api/agent/status').catch(function() { return {}; }),
api('/api/health').catch(function() { return {}; })
]).then(function(arr) {
applySidebarIdentity(arr[0], arr[1]);
}).catch(function() {});
}