/* Matrix Context — control plane (admin UI). Zero-dependency SPA wired to /v1.
* Views: Overview, Inspector, Builder, Memory, Experts, Routing, Benchmarks,
* Standard, Settings. Enterprise basics: top-bar scope selector (tenant
* isolation), auth token, graceful offline state. (Cloud omitted — pre-launch.)
*/
(function () {
"use strict";
const MC = window.MC;
const $ = (s, r) => (r || document).querySelector(s);
const el = (h) => { const t = document.createElement("template"); t.innerHTML = h.trim(); return t.content.firstChild; };
const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
const state = { tab: "overview", scope: "/", online: false, version: null, health: null, experts: [], scopes: [], items: [] };
const BENCH = {
note: "sentence-transformers/all-MiniLM-L6-v2 · test split · K=8",
rows: [
{ m: "bm25_rag", kw: 100, pa: 81, adv: 64, hd: 72 },
{ m: "dense_rag", kw: 83, pa: 79, adv: 74, hd: 103 },
{ m: "hybrid_rag", kw: 96, pa: 88, adv: 71, hd: 91 },
{ m: "moc_rag_e2", kw: 96, pa: 86, adv: 78, hd: 48 },
{ m: "moc_rag_e3", kw: 96, pa: 89, adv: 79, hd: 62 },
],
};
const ENDPOINTS = ["GET /v1/health", "GET /v1/version", "GET /v1/experts", "GET /v1/scopes",
"GET /v1/items", "GET /v1/items/{id}", "POST /v1/remember", "POST /v1/recall",
"POST /v1/pack", "POST /v1/inspect", "POST /v1/router/explain", "POST /v1/forget"];
const NAV = [
["Workspace", [["overview", "Overview", "◎"], ["inspector", "Inspector", "⌕"], ["builder", "Ingest", "↥"], ["memory", "Memory", "▤"]]],
["Develop", [["integrate", "Integrate", "⌁"]]],
["Engine", [["experts", "Experts", "❖"], ["routing", "Routing", "⇄"], ["benchmarks", "Benchmarks", "▦"]]],
["Platform", [["standard", "MoC Contract", "§"], ["settings", "Settings", "⚙"]]],
];
// ---- ingest classifier (Compatible Mode) ----
const SAMPLE = `# Project notes
## Decision: default backend
Use SQLite as the default storage backend; vectors accelerate, SQL is the source of truth.
## Policy: secrets
The agent must never store API keys, tokens, or PII in durable memory.
## Preference
The user prefers local-first tools over cloud services.
## Roadmap
Defer Milvus to v2; pgvector lands in v1.`;
const EXPERT_FOR_TYPE = { decision: "semantic", fact: "semantic", rule: "policy", preference: "profile", event: "episodic", document: "document" };
function classify(text) {
if (!text || !text.trim()) return [];
const blocks = text.split(/\n(?=#)|\n\s*\n/).map((b) => b.replace(/^#+\s*/, "").replace(/\s+/g, " ").trim()).filter((b) => b.length > 12);
return blocks.slice(0, 20).map((b, i) => {
const low = b.toLowerCase();
let type = "fact";
if (/\b(decide|decision|chose|default|will use|roadmap|defer|v1|v2|phase)\b/.test(low)) type = "decision";
else if (/\b(policy|must|never|forbidden|require)\b/.test(low)) type = "rule";
else if (/\b(prefer|preference|like)\b/.test(low)) type = "preference";
const has = (id) => state.experts.some((e) => e.id === id);
let expert = EXPERT_FOR_TYPE[type] || "semantic";
if (!has(expert)) expert = (state.experts[0] && state.experts[0].id) || "semantic";
const importance = Math.round(Math.min(0.98, 0.55 + (type === "rule" ? 0.4 : type === "decision" ? 0.32 : 0.18)) * 100) / 100;
const tags = Array.from(new Set((low.match(/\b(mcp|sdk|api|sqlite|milvus|pgvector|policy|secrets|local-first|memory|scope|roadmap)\b/g) || []))).slice(0, 4);
return { id: "c" + i, content: b.slice(0, 280), type, expert, importance, confidence: Math.round((0.75 + Math.random() * 0.2) * 100) / 100, tags: tags.length ? tags : ["context"], approved: true };
});
}
// ---- boot / chrome ----
async function boot() {
try { state.health = await MC.health(); state.version = await MC.version(); state.online = true; }
catch (e) { state.online = false; }
if (state.online) {
try { state.experts = await MC.experts(); } catch (e) {}
try { state.scopes = await MC.scopes(); } catch (e) {}
try { state.items = (await MC.items()).items; } catch (e) {}
}
chrome(); render();
}
async function refreshStore() { try { state.items = (await MC.items()).items; state.health = await MC.health(); chrome(); } catch (e) {} }
function chrome() {
const p = $("#health"); if (p) { p.className = "pill " + (state.online ? "ok" : "bad"); p.textContent = state.online ? "● online" : "● offline"; }
const ver = $("#ver"); if (ver) ver.textContent = state.version ? ("contract " + state.version.contract) : "—";
const b = $("#banner"); if (b) b.classList.toggle("show", !state.online);
const sel = $("#scopesel");
if (sel) {
sel.innerHTML = `All scopes ` + state.scopes.map((s) => `${esc(s.label)} `).join("");
sel.value = state.scope;
}
}
function counts(field) { const m = {}; state.items.forEach((it) => { m[it[field]] = (m[it[field]] || 0) + 1; }); return m; }
const scopeLabel = () => (state.scope === "/" ? "all scopes" : state.scope);
function offline(v) { v.appendChild(el(`
Disconnected The backend is not reachable. Start it (python frontend/server.py ) or check Settings, then reload.
`)); }
function render() {
document.querySelectorAll(".tab").forEach((t) => t.classList.toggle("active", t.dataset.tab === state.tab));
const v = $("#view"); v.innerHTML = "";
const views = { overview: vOverview, inspector: vInspector, builder: vBuilder, memory: vMemory, integrate: vIntegrate, experts: vExperts, routing: vRouting, benchmarks: vBench, standard: vStandard, settings: vSettings };
if (!state.online && ["overview", "inspector", "builder", "memory", "experts", "routing"].indexOf(state.tab) >= 0) {
v.appendChild(el(`
${esc(state.tab[0].toUpperCase() + state.tab.slice(1))} `)); offline(v); return;
}
(views[state.tab] || vOverview)(v);
}
// ---- Overview ----
function vOverview(v) {
const ec = counts("expert"), sc = counts("scope");
v.appendChild(el(`
Control plane
Inspectable, typed memory for AI agents — routed retrieval, budgeted packs, every choice explained. Backed by MoC Contract v1.
Memory items
${state.health ? state.health.items : "—"}
Context experts
${state.experts.length}
Scopes
${state.scopes.length}
Route, don't dump Each query goes to the few typed experts it needs — not one flat index.
Budgeted packs Relevance · importance · recency − redundancy, under a token budget.
Always inspectable See selected/dropped experts, scores, and reasons for every item.
Experts ${state.experts.map((e) => `
${esc(e.name)} ${ec[e.id] || 0}
`).join("") || '
none
'}
Scopes ${state.scopes.map((s) => `
${esc(s.label)} ${sc[s.id] || 0}
`).join("") || '
none
'}
Get started
pip install matrix-context · matrix-context serve --transport rest
Conformance ${state.online ? "MoC API v1 Compatible" : "—"}
`));
}
// ---- Inspector ----
function vInspector(v) {
v.appendChild(el(`
Inspector
Ask a question; see exactly why each item was routed, kept, or dropped. scope: ${esc(scopeLabel())}
`));
const run = async () => {
$("#pack").innerHTML = 'running…
'; $("#route").innerHTML = "";
let r; try { r = await MC.inspect($("#q").value, { scope: state.scope, max_tokens: +$("#mt").value, top_experts: +$("#te").value }); }
catch (e) { $("#pack").innerHTML = `${esc(e.message)}
`; return; }
const max = Math.max.apply(null, r.routing.scores.map((s) => s.score).concat([0.0001]));
$("#routeCard").querySelector("h2").innerHTML = `Router — ${esc(r.routing.reason)} `;
$("#route").innerHTML = `${r.routing.selected.map((e) => `${esc(e)} `).join("")}${r.routing.unselected.map((e) => `${esc(e)} `).join("")}
` +
`${r.routing.scores.map((s) => { const on = r.routing.selected.indexOf(s.expert) >= 0; return `${on ? "● " : ""}${esc(s.expert)} ${s.score.toFixed(3)}
`; }).join("")}
`;
$("#packCard").querySelector("h2").innerHTML = `Context pack ${r.pack.tokens}/${r.pack.maxTokens} tok `;
$("#pack").innerHTML = `Expert Content Score ${r.pack.items.map((p) => `${esc(p.expert)} ${esc(p.content)}rel ${p.breakdown.relevance} · imp ${p.breakdown.importance} · rec ${p.breakdown.recency} · −red ${p.breakdown.redundancy}
${p.final_score} `).join("")} ${r.pack.dropped.length ? `${r.pack.dropped.map((d) => `${esc(d.expert)} ${esc(d.id)} dropped `).join("")} ` : ""}
Prompt-ready pack ${esc(r.pack.prompt)} `;
};
$("#run", v).onclick = run; run();
}
// ---- Builder ----
let cands = [];
function vBuilder(v) {
const defScope = state.scope !== "/" ? state.scope : ((state.scopes[0] && state.scopes[0].id) || "project:demo");
v.appendChild(el(`
Ingest
Never ingest blindly — paste, review typed candidates, approve, commit, then prove recall. Compatible Mode: client-side chunk → POST /v1/remember
`));
$("#sample", v).onclick = () => { $("#src").value = SAMPLE; };
$("#analyze", v).onclick = () => { cands = classify($("#src").value); paint(); };
function paint() {
const host = $("#cands"); host.innerHTML = ""; if (!cands.length) return;
const ap = cands.filter((c) => c.approved).length;
host.appendChild(el(`Review — ${ap}/${cands.length} approved
Commit ${ap} → POST /v1/remember type/confidence/source saved as tags
`));
host.querySelectorAll("input[type=checkbox]").forEach((cb) => cb.onchange = () => { cands[+cb.dataset.i].approved = cb.checked; paint(); });
host.querySelectorAll("select[data-e]").forEach((sl) => sl.onchange = () => { cands[+sl.dataset.e].expert = sl.value; });
$("#go", host).onclick = commit;
}
async function commit() {
const scope = $("#bscope").value || "/"; const ap = cands.filter((c) => c.approved);
const w = $("#commit"); w.innerHTML = ``;
const log = $("#log", w), line = (h) => { log.appendChild(el(`${h}
`)); log.scrollTop = log.scrollHeight; };
line(`remember.batch --scope ${esc(scope)} --count ${ap.length} `);
for (const c of ap) {
try { const it = await MC.remember({ content: c.content, expert: c.expert, scope, importance: c.importance, tags: c.tags.concat([`type:${c.type}`, `confidence:${c.confidence}`, "source:console"]) });
line(`POST /v1/remember expert=${esc(c.expert)} 201 ${esc(it.id)} `); }
catch (e) { line(`FAILED ${esc(e.message)} `); }
}
line(`done · ${ap.length} written `); await refreshStore();
$("#ti", w).onclick = () => { state.tab = "inspector"; render(); };
}
}
// ---- Memory ----
function vMemory(v) {
v.appendChild(el(`Memory Browse, filter, and forget stored items.
Expert All experts ${state.experts.map((e) => `${esc(e.name)} `).join("")}
Scope All scopes ${state.scopes.map((s) => `${esc(s.label)} `).join("")}
Refresh
`));
async function load() {
let items = []; try { items = (await MC.items({ expert: $("#fe").value, scope: $("#fs").value })).items; } catch (e) {}
const h = $("#rows"); h.innerHTML = `${items.length} item${items.length === 1 ? "" : "s"} ` + (items.length ? `Expert Content Scope Tags ${items.map((it) => `${esc(it.expert)} ${esc(it.content)} ${esc(it.scope)} ${(it.tags || []).map((t) => `${esc(t)} `).join(" ")} Forget `).join("")}
` : 'no items
');
h.querySelectorAll("button[data-d]").forEach((b) => b.onclick = async () => { await MC.forget(b.dataset.d); await refreshStore(); load(); });
}
$("#rf", v).onclick = load; $("#fe", v).onchange = load; $("#fs", v).onchange = load; load();
}
// ---- Experts ----
function vExperts(v) {
const c = counts("expert");
v.appendChild(el(`Context experts The typed partitions the router selects between.
${state.experts.map((e) => `
${esc(e.name)} ${c[e.id] || 0} items
${esc(e.desc)}
`).join("")}
`));
}
// ---- Routing ----
function vRouting(v) {
v.appendChild(el(`Routing The router debugger — per-expert scores and the decision reason.
`));
$("#run", v).onclick = async () => {
const o = $("#out"); o.innerHTML = '…
';
let r; try { r = await MC.routerExplain($("#q").value, { scope: state.scope }); } catch (e) { o.innerHTML = `${esc(e.message)}
`; return; }
const max = Math.max.apply(null, r.scores.map((s) => s.score).concat([0.0001]));
o.innerHTML = `Decision — ${esc(r.reason)} ${r.selected.map((e) => `${esc(e)} `).join("")}${r.unselected.map((e) => `${esc(e)} `).join("")}
${r.scores.map((s) => { const on = r.selected.indexOf(s.expert) >= 0; return `${on ? "● " : ""}${esc(s.expert)} ${s.score.toFixed(3)}
`; }).join("")}
`;
};
}
// ---- Benchmarks ----
function vBench(v) {
const bar = (val, color) => `
${val}% `;
v.appendChild(el(`Benchmarks Robustness on the public MoC-RAG Benchmark. ${esc(BENCH.note)}. BM25 is strong on keyword queries; MoC-RAG is more robust under paraphrase/adversarial.
Recall@8 by query type Method keyword paraphrased adversarial hard distractors ↓ ${BENCH.rows.map((r) => { const moc = r.m.indexOf("moc") === 0; return `${moc ? '' + esc(r.m) + " " : esc(r.m)} ${bar(r.kw)} ${bar(r.pa)} ${bar(r.adv, moc ? "var(--acc)" : "var(--amber)")} ${r.hd} `; }).join("")}
Honest claim: MoC-RAG improves robustness and context efficiency under typed, adversarial conditions — it does not universally beat all RAG.
`));
}
// ---- Standard ----
function vStandard(v) {
v.appendChild(el(`MoC Contract A frozen, versioned, inspectable wire contract — implement it and claim compatibility.
Contract
${state.version ? esc(state.version.contract) : "—"}
Implementation
${state.version ? esc(state.version.implementation + " " + state.version.build) : "—"}
Conformance
${state.online ? "MoC API v1 ✓" : "—"}
Endpoints ${ENDPOINTS.map((e) => `${esc(e)} `).join("")}
python -m moc_contract.conformance --url ${esc(location.origin)}
`));
}
// ---- Integrate (simple usage for agents) ----
function snippet(title, code) {
const id = "sn" + Math.random().toString(36).slice(2, 8);
return `
${esc(title)} Copy ${esc(code)} `;
}
function vIntegrate(v) {
const origin = location.origin;
const py = `from matrix_context import ContextManager
ctx = ContextManager.create("my-agent", path="agent.db")
def chat(user_msg, scope="/"):
# BEFORE the model call: routed, budgeted, inspectable context
pack = ctx.build_pack(user_msg, scope=scope, max_tokens=400)
answer = your_llm(pack.to_prompt() + "\\nUser: " + user_msg)
# AFTER the turn: remember it so the agent accumulates memory
ctx.remember(user_msg, expert="episodic", scope=scope)
ctx.remember(answer, expert="semantic", scope=scope)
return answer`;
const rest = `# BEFORE: a prompt-ready, routed pack
curl -s ${origin}/v1/pack -H 'content-type: application/json' \\
-d '{"query":"what did we decide?","max_tokens":400}'
# AFTER: remember the turn
curl -s ${origin}/v1/remember -H 'content-type: application/json' \\
-d '{"content":"...","expert":"episodic"}'`;
const mcp = `# Agent-native binding (MoC Contract v1 over MCP)
matrix-context serve --transport stdio`;
v.appendChild(el(`
Integrate an agent
Give any agent typed, inspectable memory in two calls per turn — build_pack before the model call, remember after. This server's live API base is ${esc(origin)}/v1 .
pip install matrix-context
${snippet("Python — the agent loop", py)}
${snippet("REST — any language", rest)}
${snippet("MCP — agent-native (binding pending)", mcp)}
Full guide: tutorials/build-your-first-chatbot.md · this endpoint passes MoC API v1 .
`));
v.querySelectorAll("button[data-copy]").forEach((b) => b.onclick = async () => {
try { await navigator.clipboard.writeText($("#" + b.dataset.copy).textContent); b.textContent = "Copied ✓"; setTimeout(() => { b.textContent = "Copy"; }, 1200); }
catch (e) { b.textContent = "Select & copy"; }
});
}
// ---- Settings ----
function vSettings(v) {
v.appendChild(el(`Settings Connection, tenancy, and display. This console is served same-origin against the live backend.
Connection
API base ${esc(MC.base)}
Status ${state.online ? "online" : "offline"}
Bearer token (optional — for protected servers)
Default scope (tenant isolation)
All scopes ${state.scopes.map((s) => `${esc(s.label)} `).join("")}
Drives the Inspector, Ingest, Memory, and Routing defaults. Also selectable from the top bar.
Display ${window.__rainOff ? "Enable" : "Disable"} matrix rain
`));
$("#savetok", v).onclick = () => { const t = $("#tok").value; if (t && t !== "********") { MC.setToken(t); boot(); } };
$("#defscope", v).onchange = (e) => { state.scope = e.target.value; chrome(); };
$("#rain", v).onclick = () => { window.__rainOff = !window.__rainOff; render(); };
}
// ---- mount (single innerHTML root — all sections render) ----
function mount() {
const root = $("#app");
root.innerHTML = `
Matrix Context
Console
—
scope
All scopes
● connecting…
Backend offline — start it (python frontend/server.py ) or check Settings, then reload.
${NAV.map(([g, items]) => `${g}
${items.map(([id, label, ic]) => `
${ic} ${label}
`).join("")}
`).join("")}
`;
root.querySelectorAll(".tab").forEach((t) => t.onclick = () => { state.tab = t.dataset.tab; render(); });
$("#scopesel").onchange = (e) => { state.scope = e.target.value; render(); };
boot();
}
document.addEventListener("DOMContentLoaded", mount);
})();