/* ============================================================ Elysium API client — talks to FastAPI routes on gr.Server. - Sends multipart/form-data with optional attachments - Hard-caps at 2 files (server also enforces) - Surfaces friendly errors so boot.js can toast them ============================================================ */ window.ElysiumAPI = { async turn(text, files) { const fd = new FormData(); fd.append('user_text', text || ''); (files || []).slice(0, 2).forEach(f => fd.append('attachments', f, f.name)); const r = await fetch('/api/turn', { method: 'POST', body: fd }); if (!r.ok) { let detail = ''; try { detail = (await r.text()).slice(0, 200); } catch {} throw new Error(`HTTP ${r.status}${detail ? ': ' + detail : ''}`); } return r.json(); }, async health() { try { const r = await fetch('/api/health'); if (!r.ok) return { status: 'error' }; return r.json(); } catch { return { status: 'offline' }; } }, async hypergraph() { try { const r = await fetch('/api/hypergraph'); if (!r.ok) return { nodes: [], edges: [], node_count: 0, edge_count: 0 }; return r.json(); } catch { return { nodes: [], edges: [], node_count: 0, edge_count: 0 }; } }, async nodeDetail(id) { try { const r = await fetch('/api/node/' + encodeURIComponent(id)); if (!r.ok) return null; return r.json(); } catch { return null; } }, async reset() { try { const r = await fetch('/api/reset', { method: 'POST' }); return r.ok ? r.json() : { status: 'error' }; } catch { return { status: 'offline' }; } }, };