/* Matrix Context — live API adapter (same-origin /v1, MoC Contract v1). * Maps backend shapes for the UI: remember->item, inspect->routing/.pack, * version->contract_version/implementation_version, scopes->plain strings. */ (function () { const BASE = location.origin + "/v1"; let TOKEN = (window.localStorage && localStorage.getItem("mc_token")) || ""; function setToken(t) { TOKEN = t || ""; if (window.localStorage) localStorage.setItem("mc_token", TOKEN); } async function call(method, path, body) { const headers = { "Content-Type": "application/json" }; if (TOKEN) headers["Authorization"] = "Bearer " + TOKEN; const opt = { method, headers }; if (body !== undefined) opt.body = JSON.stringify(body); let resp; try { resp = await fetch(BASE + path, opt); } catch (e) { throw { status: 0, message: "network error — is the backend running?" }; } let data = {}; try { data = await resp.json(); } catch (e) {} if (!resp.ok) throw { status: resp.status, message: (data && data.error) || ("HTTP " + resp.status) }; return data; } window.MC = { base: BASE, setToken, hasToken: () => !!TOKEN, async health() { return await call("GET", "/health"); }, async version() { const v = await call("GET", "/version"); return { contract: v.contract_version, implementation: v.implementation, build: v.implementation_version, name: v.name }; }, async experts() { const r = await call("GET", "/experts"); return (r.experts || []).map((e) => ({ id: e.name, name: e.name, desc: e.description || "" })); }, async scopes() { const r = await call("GET", "/scopes"); return (r.scopes || []).map((s) => ({ id: s, label: s })); }, async items(f) { f = f || {}; const q = []; if (f.scope) q.push("scope=" + encodeURIComponent(f.scope)); if (f.expert) q.push("expert=" + encodeURIComponent(f.expert)); const r = await call("GET", "/items" + (q.length ? "?" + q.join("&") : "")); return { items: r.items || [], count: r.count || 0 }; }, async remember(item) { const r = await call("POST", "/remember", { content: item.content, expert: item.expert, scope: item.scope, importance: item.importance, tags: item.tags || [], ttl: item.ttl != null ? item.ttl : null, }); return r.item; }, async forget(id) { return !!(await call("POST", "/forget", { id })).deleted; }, async inspect(query, opts) { opts = opts || {}; const r = await call("POST", "/inspect", { query, scope: opts.scope || "/", max_tokens: opts.max_tokens || 256, top_experts: opts.top_experts || 3, pin_experts: opts.pin_experts || [], }); const scores = Object.entries((r.routing && r.routing.scores) || {}) .map(([expert, score]) => ({ expert, score })).sort((a, b) => b.score - a.score); return { query: r.query, routing: { selected: (r.routing && r.routing.selected_experts) || [], unselected: (r.routing && r.routing.unselected_experts) || [], scores, widened: !!(r.routing && r.routing.widened), reason: (r.routing && r.routing.reason) || "", }, pack: { tokens: r.pack && r.pack.tokens, maxTokens: r.pack && r.pack.max_tokens, items: (r.pack && r.pack.items) || [], dropped: (r.pack && r.pack.dropped) || [], citations: (r.pack && r.pack.citations) || [], prompt: (r.pack && r.pack.prompt) || "", }, }; }, async routerExplain(query, opts) { opts = opts || {}; const r = await call("POST", "/router/explain", { query, scope: opts.scope || "/", top_experts: opts.top_experts || 3 }); return { selected: r.selected_experts || [], unselected: r.unselected_experts || [], scores: r.scores || [], reason: r.reason || "", widened: !!r.widened }; }, }; })();