// API client with JWT auth injection. const TOKEN_KEY = 'st_token' export function getToken() { return localStorage.getItem(TOKEN_KEY) } export function setToken(t) { if (t) localStorage.setItem(TOKEN_KEY, t) else localStorage.removeItem(TOKEN_KEY) } async function request(method, url, body, isForm = false) { const headers = {} const token = getToken() if (token) headers['Authorization'] = `Bearer ${token}` let payload = body if (!isForm && body !== undefined && body !== null) { headers['Content-Type'] = 'application/json' payload = JSON.stringify(body) } const res = await fetch(url, { method, headers, body: payload }) let data = null try { data = await res.json() } catch (e) { /* ignore json parse errors */ } if (!res.ok) { const msg = (data && (data.error || data.message)) || `HTTP ${res.status}` throw new Error(msg) } return data } export const api = { login: (username, password) => request('POST', '/api/auth/login', { username, password }), me: () => request('GET', '/api/auth/me'), setup: (b) => request('POST', '/api/auth/setup', b), updateProfile: (b) => request('PATCH', '/api/auth/profile', b), adminCreateUser: (b) => request('POST', '/api/admin/users', b), adminListUsers: () => request('GET', '/api/admin/users'), adminUpdateUser: (username, b) => request('PUT', `/api/admin/users/${username}`, b), createGroup: (formData) => request('POST', '/api/groups', formData, true), listGroups: () => request('GET', '/api/groups'), getGroup: (id) => request('GET', `/api/groups/${id}`), deleteGroup: (id) => request('DELETE', `/api/groups/${id}`), analyzeGroup: (id, opts = {}) => request('POST', `/api/groups/${id}/analyze${opts.append ? '?append=true' : ''}`), listPersonas: (gid) => request('GET', `/api/groups/${gid}/personas`), getPersona: (gid, pid) => request('GET', `/api/groups/${gid}/personas/${pid}`), updatePersona: (gid, pid, b) => request('PUT', `/api/groups/${gid}/personas/${pid}`, b), chatStart: (gid, pid, scenario, locale) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/start`, { scenario, locale }), chatResume: (gid, pid) => request('GET', `/api/chat/${gid}/personas/${pid}/chat/resume`), chatSend: (gid, pid, text) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/send`, { text }), chatFinish: (gid, pid) => request('POST', `/api/chat/${gid}/personas/${pid}/chat/finish`), mySessions: () => request('GET', '/api/chat/sessions'), myBoard: () => request('GET', '/api/me/board'), weakAreas: () => request('GET', '/api/me/weak-areas'), myPersonas: () => request('GET', '/api/me/personas'), generatePersona: (b) => request('POST', '/api/me/personas/generate', b), analytics: (params = {}) => { const qs = new URLSearchParams() if (params.from) qs.set('from', params.from) if (params.to) qs.set('to', params.to) const q = qs.toString() return request('GET', `/api/analytics${q ? `?${q}` : ''}`) }, }