// API client for OPRT Launch Board backend // Override window.OPRT_API_BASE and window.OPRT_TOKEN in settings panel (persisted to localStorage). const DEFAULT_BASE = "https://launch.quinn.chat"; function getConfig() { return { base: localStorage.getItem("oprt.apiBase") || DEFAULT_BASE, token: localStorage.getItem("oprt.apiToken") || "dev-token-please-change", }; } function setConfig({ base, token }) { if (base != null) localStorage.setItem("oprt.apiBase", base); if (token != null) localStorage.setItem("oprt.apiToken", token); } async function api(path, opts = {}) { const { base, token } = getConfig(); const res = await fetch(base + path, { ...opts, headers: { "content-type": "application/json", "Authorization": "Bearer " + token, ...(opts.headers || {}), }, }); if (!res.ok) { const body = await res.text().catch(() => ""); throw new Error(`${res.status} ${res.statusText}: ${body}`); } if (res.status === 204) return null; return res.json(); } const OprtAPI = { listInstances: () => api("/api/instances"), getInstance: (id) => api("/api/instances/" + id), createInstance: (body) => api("/api/instances", { method: "POST", body: JSON.stringify(body) }), getEvents: (id) => api("/api/instances/" + id + "/events"), pause: (id) => api("/api/instances/" + id + "/pause", { method: "POST" }), resume: (id) => api("/api/instances/" + id + "/resume", { method: "POST" }), archive: (id) => api("/api/instances/" + id, { method: "DELETE" }), listKeys: (id) => api("/api/instances/" + id + "/keys"), rotateKey: (id, keyId, newKey) => api(`/api/instances/${id}/keys/${keyId}/rotate`, { method: "POST", body: JSON.stringify({ newKey }) }), listSkills: () => api("/api/skills"), metricsOverview: (range="30d") => api("/api/metrics/overview?range=" + range), metricsTokens: (instanceId, range="30d") => api(`/api/metrics/tokens?range=${range}${instanceId ? "&instanceId=" + instanceId : ""}`), billingAccounts: () => api("/api/billing/accounts"), billingInvoices: () => api("/api/billing/invoices"), updateInstanceSkills: (id, skills) => api(`/api/instances/${id}/skills`, { method: "PUT", body: JSON.stringify({ skills }) }), listFiles: (id) => api(`/api/instances/${id}/files`), readFile: (id, path) => api(`/api/instances/${id}/files/${path}`), writeFile: (id, path, content) => api(`/api/instances/${id}/files/${path}`, { method: "PUT", body: JSON.stringify({ content }) }), health: async () => { const { base } = getConfig(); const r = await fetch(base + "/healthz"); return r.ok; }, }; window.OprtAPI = OprtAPI; window.OprtConfig = { get: getConfig, set: setConfig };