const $ = (id) => document.getElementById(id);
const charts = {};
const pending = new Map();
let requestId = 0;
let toastTimer = null;
let lastResult = null;
let lastArenaRows = [];
let lastCapacityTrace = [];
let lastTopologyRows = [];
let lastDesignRows = [];
let lastPairedStudy = null;
let lastRobustStudy = null;
let lastAgentRun = null;
let lastAgentCompare = null;
let lastAgentTtl = null;
let lastAgentMemory = null;
let lastAgentBudget = null;
let lastAgentAffinity = null;
let lastPredictiveStudy = null;
let lastPredictiveAlpha = null;
let lastExecutionRun = null;
let lastExecutionCompare = null;
let lastExecutionThreshold = null;
let lastExecutionDecay = null;
let lastExecutionPlanning = null;
let lastExecutionHorizon = null;
let lastExecutionBudget = null;
let lastConsolidation = null;
let lastMeasurementImport = null;
let lastCalibration = null;
let measurementFileContent = "";
let traceRequests = [];
const COLORS = {
blue: "#78a1db",
blue2: "#5f86bf",
steel: "#91a0b2",
green: "#69c39a",
amber: "#d2b36a",
red: "#d97f89",
purple: "#9288c7",
gray: "#687585",
grid: "rgba(140,155,175,.14)",
};
const runtimePill = $("runtimePill");
const runtimeText = $("runtimeText");
const worker = new Worker("./worker.mjs", { type: "module" });
worker.addEventListener("message", (event) => {
const data = event.data || {};
if (data.type === "ready") {
runtimePill.classList.add("ready");
runtimeText.textContent = "Python runtime ready";
["runBtn", "arenaBtn", "capacityBtn", "topologyBtn", "designBtn", "pairedStudyBtn", "robustStudyBtn", "agentRunBtn", "agentCompareBtn", "agentTtlBtn", "agentMemoryCompareBtn", "agentBudgetBtn", "agentAffinityBtn", "predictiveCompareBtn", "predictiveAlphaBtn", "execRunBtn", "execCompareBtn", "execThresholdBtn", "execDecayBtn", "execPlanningBtn", "execHorizonBtn", "execBudgetBtn", "consRunBtn"].forEach((id) => { $(id).disabled = false; });
if (measurementFileContent) $("measurementCalibrateBtn").disabled = false;
syncConditionalControls();
window.setTimeout(() => document.body.classList.add("runtime-ready"), 650);
return;
}
if (data.type === "fatal") {
runtimePill.classList.add("error");
runtimeText.textContent = "Runtime failed";
console.error(data.error);
return;
}
if (!pending.has(data.id)) return;
const { resolve, reject } = pending.get(data.id);
pending.delete(data.id);
data.error ? reject(new Error(data.error)) : resolve(data.result);
});
function callPython(action, payload) {
const id = ++requestId;
return new Promise((resolve, reject) => {
pending.set(id, { resolve, reject });
worker.postMessage({ id, action, payload });
});
}
function num(id) { return Number($(id).value); }
function boolSelect(id) { return $(id).value === "on"; }
function configFromUI(overrides = {}) {
return {
model: $("model").value,
accelerator: $("accelerator").value,
prefill_accelerator: $("prefillAccelerator").value,
decode_accelerator: $("decodeAccelerator").value,
prefill_workers: num("prefillWorkers"),
decode_workers: num("decodeWorkers"),
interconnect_gbps: num("interconnect"),
transfer_base_ms: num("transferBase"),
topology: $("topology").value,
scheduler: $("scheduler").value,
quantization: $("quantization").value,
prefix_cache_enabled: boolSelect("prefixCache"),
shared_prefix_tokens: num("sharedPrefix"),
prefix_reuse_fraction: num("prefixReuse"),
arrival_process: $("arrival").value,
request_rate_rps: num("rate"),
duration_s: num("duration"),
prompt_tokens_mean: num("promptMean"),
prompt_tokens_cv: num("promptCv"),
output_tokens_mean: num("outputMean"),
output_tokens_cv: num("outputCv"),
max_batch_size: num("maxBatch"),
max_batch_tokens: num("maxBatchTokens"),
chunk_size: num("chunkSize"),
kv_block_tokens: num("kvBlock"),
burst_multiplier: num("burstMultiplier"),
burst_period_s: num("burstPeriod"),
seed: num("seed"),
slo_ttft_ms: num("sloTtft"),
slo_e2e_ms: num("sloE2e"),
slo_attainment_target: 0.99,
trace_requests: $("arrival").value === "trace" ? traceRequests : [],
...overrides,
};
}
function fmt(value, digits = 1) {
if (!Number.isFinite(value)) return "N/A";
return value.toLocaleString(undefined, { maximumFractionDigits: digits });
}
function pct(value, digits = 1) { return `${fmt(value * 100, digits)}%`; }
function escapeHtml(value) {
return String(value).replace(/[&<>'"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """ })[c]);
}
function slug(value) {
return String(value).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
}
function stamp() {
const d = new Date();
const pad = (v) => String(v).padStart(2, "0");
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
}
function showToast(message, kind = "info", timeoutMs = 2200) {
const toast = $("toast");
toast.textContent = message;
toast.classList.toggle("error", kind === "error");
toast.classList.add("show");
if (toastTimer) clearTimeout(toastTimer);
toastTimer = setTimeout(() => {
toast.classList.remove("show", "error");
}, timeoutMs);
}
function reportError(context, error) {
console.error(context, error);
showToast(`${context}: ${error.message}`, "error", 5200);
}
async function copyText(text, message) {
try {
await navigator.clipboard.writeText(text);
showToast(message);
} catch {
const area = document.createElement("textarea");
area.value = text;
area.style.position = "fixed";
area.style.opacity = "0";
document.body.appendChild(area);
area.select();
document.execCommand("copy");
area.remove();
showToast(message);
}
}
function csvCell(value) {
const text = String(value ?? "");
return /[",\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
}
function tableText(headers, rows, separator = "\t") {
return [headers, ...rows].map((row) => row.join(separator)).join("\n");
}
function downloadCsv(filename, headers, rows) {
const csv = [headers, ...rows].map((row) => row.map(csvCell).join(",")).join("\n");
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
function downloadJson(result) {
const cfg = result.config || configFromUI();
const topology = cfg.topology === "disaggregated_pd" ? `pd-${cfg.prefill_workers}p-${cfg.decode_workers}d` : `colocated-${cfg.accelerator}`;
const name = `inferscale-run_${slug(cfg.model)}_${slug(topology)}_${slug(cfg.scheduler)}_${stamp()}.json`;
const blob = new Blob([JSON.stringify(result, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = name;
a.click();
URL.revokeObjectURL(url);
}
function downloadNamedJson(prefix, result) {
const blob = new Blob([JSON.stringify(result, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${prefix}_${stamp()}.json`;
a.click();
URL.revokeObjectURL(url);
}
function downloadTextFile(filename, content, mime = "text/plain;charset=utf-8") {
const blob = new Blob([content], { type: mime });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
Chart.defaults.color = "#929dab";
Chart.defaults.borderColor = COLORS.grid;
Chart.defaults.font.family = getComputedStyle(document.body).fontFamily;
Chart.defaults.font.size = 13;
Chart.defaults.animation.duration = 0;
function commonChartOptions() {
return { responsive: true, maintainAspectRatio: false };
}
function lineLegend() {
return {
labels: {
usePointStyle: true,
pointStyle: "line",
pointStyleWidth: 26,
boxWidth: 26,
boxHeight: 2,
padding: 14,
},
};
}
function pointLegend() {
return {
labels: {
usePointStyle: true,
boxWidth: 8,
boxHeight: 8,
padding: 14,
},
};
}
function destroyChart(name) {
if (charts[name]) {
charts[name].destroy();
delete charts[name];
}
}
function chartFileName(card) {
const chartName = card.dataset.chartName || "figure";
if (chartName.startsWith("agent-")) {
const cfg = agentConfigFromUI();
return `inferscale_${slug(chartName)}_${slug(cfg.model)}_${slug(cfg.accelerator)}_${slug(cfg.retention_policy)}_${slug(cfg.routing_policy)}_${stamp()}.png`;
}
const cfg = configFromUI();
const topology = cfg.topology === "disaggregated_pd"
? `pd-${cfg.prefill_workers}p-${cfg.decode_workers}d-${cfg.prefill_accelerator}-${cfg.decode_accelerator}`
: `colocated-${cfg.accelerator}`;
return `inferscale_${slug(chartName)}_${slug(cfg.model)}_${slug(topology)}_${slug(cfg.scheduler)}_${stamp()}.png`;
}
function downloadChart(card) {
const canvas = card.querySelector("canvas");
const chart = Chart.getChart(canvas);
if (!chart) return;
const exportCanvas = document.createElement("canvas");
exportCanvas.width = canvas.width;
exportCanvas.height = canvas.height;
const ctx = exportCanvas.getContext("2d");
ctx.fillStyle = "#0a0f15";
ctx.fillRect(0, 0, exportCanvas.width, exportCanvas.height);
ctx.drawImage(canvas, 0, 0);
exportCanvas.toBlob((blob) => {
if (!blob) return;
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = chartFileName(card);
a.click();
URL.revokeObjectURL(url);
showToast("Chart PNG downloaded");
}, "image/png");
}
function renderSimulation(result) {
lastResult = result;
$("emptyState").classList.add("hidden");
$("resultContent").classList.remove("hidden");
$("exportBtn").disabled = false;
$("copyResultBtn").disabled = false;
const s = result.summary;
const l = result.latency;
const r = result.resource;
const d = result.diagnostics || {};
$("mTtft").textContent = `${fmt(l.ttft_ms.p95)} ms`;
$("mE2e").textContent = `${fmt(l.e2e_ms.p95)} ms`;
$("mGoodput").textContent = `${fmt(s.goodput_rps, 2)} req/s`;
$("mSlo").textContent = pct(s.slo_attainment);
$("mReq").textContent = `${fmt(s.request_throughput_rps, 2)} req/s`;
$("mKv").textContent = `${fmt(r.peak_kv_gb, 2)} GB`;
const tag = $("runState");
tag.textContent = `${s.requests_completed}/${s.requests_generated} completed`;
tag.className = `tag ${s.slo_attainment >= .99 && s.requests_unfinished === 0 ? "good" : "bad"}`;
$("mBottleneck").textContent = d.label || "N/A";
$("mDiagnosis").textContent = d.explanation || "No simulator diagnosis available.";
$("mRecommendation").textContent = d.recommendation ? `Next check: ${d.recommendation}` : "";
const e = d.evidence || {};
const evidence = [
`topology ${r.topology || result.config.topology || "colocated"}`,
`busy ${pct(e.busy_fraction ?? s.busy_fraction)}`,
`KV ${pct(e.peak_kv_utilization ?? r.peak_kv_utilization)}`,
`TTFT pass ${pct(e.ttft_slo_attainment ?? s.ttft_slo_attainment)}`,
`E2E pass ${pct(e.e2e_slo_attainment ?? s.e2e_slo_attainment)}`,
`queue p95 ${fmt(e.queue_p95_ms ?? l.queue_ms.p95)} ms`,
];
if ((r.prefix_cache_hit_rate ?? 0) > 0) evidence.push(`cache hit ${pct(r.prefix_cache_hit_rate)}`, `prefill saved ${fmt(r.prefill_tokens_saved, 0)} tok`);
if (r.topology === "disaggregated_pd") evidence.push(
`prefill busy ${pct(r.prefill_busy_fraction)}`,
`decode busy ${pct(r.decode_busy_fraction)}`,
`link busy ${pct(r.transfer_busy_fraction)}`,
`transfer p95 ${fmt(r.p95_transfer_ms, 2)} ms`,
);
$("mEvidence").innerHTML = evidence.map((x) => `${escapeHtml(x)}`).join("");
destroyChart("latency");
charts.latency = new Chart($("latencyChart"), {
type: "bar",
data: {
labels: ["TTFT p50", "TTFT p95", "E2E p50", "E2E p95", "Queue p95"],
datasets: [{
label: "Milliseconds",
data: [l.ttft_ms.p50, l.ttft_ms.p95, l.e2e_ms.p50, l.e2e_ms.p95, l.queue_ms.p95],
backgroundColor: [COLORS.steel, COLORS.blue, "#8196b1", COLORS.blue2, COLORS.amber],
}],
},
options: { ...commonChartOptions(), plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true } } },
});
const timeline = result.timeline || [];
const lineDatasets = [
{ label: r.topology === "disaggregated_pd" ? "Prefill queue" : "Waiting", data: timeline.map((x) => ({ x: x.time_s, y: x.waiting })), borderColor: COLORS.amber, pointRadius: 0, tension: .08, yAxisID: "y" },
{ label: "Decoding", data: timeline.map((x) => ({ x: x.time_s, y: x.decoding })), borderColor: COLORS.blue, pointRadius: 0, tension: .08, yAxisID: "y" },
{ label: "KV GB", data: timeline.map((x) => ({ x: x.time_s, y: x.kv_used_gb })), borderColor: COLORS.green, pointRadius: 0, tension: .08, yAxisID: "y1" },
];
if (r.topology === "disaggregated_pd") {
lineDatasets.splice(1, 0, { label: "Decode queue", data: timeline.map((x) => ({ x: x.time_s, y: x.decode_ready || 0 })), borderColor: COLORS.steel, borderDash: [4, 3], pointRadius: 0, tension: .08, yAxisID: "y" });
}
destroyChart("timeline");
charts.timeline = new Chart($("timelineChart"), {
type: "line",
data: { datasets: lineDatasets },
options: {
...commonChartOptions(),
parsing: false,
interaction: { mode: "nearest", intersect: false },
plugins: { legend: lineLegend() },
scales: {
x: { type: "linear", title: { display: true, text: "Virtual time (s)" } },
y: { beginAtZero: true, title: { display: true, text: "Requests" } },
y1: { beginAtZero: true, position: "right", grid: { drawOnChartArea: false }, title: { display: true, text: "KV GB" } },
},
},
});
const sample = result.requests || [];
destroyChart("scatter");
charts.scatter = new Chart($("scatterChart"), {
type: "scatter",
data: { datasets: [{ label: "Requests", data: sample.map((x) => ({ x: x.prompt_tokens, y: x.ttft_ms })), backgroundColor: "rgba(121,167,255,.55)", pointRadius: 2.2 }] },
options: { ...commonChartOptions(), plugins: { legend: { display: false } }, scales: { x: { title: { display: true, text: "Prompt tokens" } }, y: { title: { display: true, text: "TTFT (ms)" }, beginAtZero: true } } },
});
const warnings = $("warnings");
const allWarnings = [...(result.warnings || [])];
if (result.provenance?.profile_warning) allWarnings.unshift(result.provenance.profile_warning);
if (allWarnings.length) {
warnings.innerHTML = allWarnings.map((w) => `
${escapeHtml(w)}
`).join("");
warnings.classList.remove("hidden");
} else {
warnings.classList.add("hidden");
}
}
$("runBtn").addEventListener("click", async () => {
if ($("arrival").value === "trace" && traceRequests.length === 0) { showToast("Load a trace file first"); return; }
const button = $("runBtn");
const state = $("runState");
button.disabled = true;
button.textContent = "Running simulation...";
state.textContent = "Simulating...";
state.className = "tag neutral";
try {
renderSimulation(await callPython("simulate", configFromUI()));
} catch (error) {
state.textContent = "Error";
state.className = "tag bad";
reportError("Simulation failed", error);
} finally {
button.textContent = "Run simulation";
button.disabled = false;
}
});
$("copyResultBtn").addEventListener("click", () => { if (lastResult) copyText(JSON.stringify(lastResult, null, 2), "Result JSON copied"); });
$("exportBtn").addEventListener("click", () => { if (lastResult) downloadJson(lastResult); });
function schedulerLabel(value) {
return ({
static_fcfs: "Static FCFS",
continuous_fcfs: "Continuous FCFS",
continuous_sjf: "Continuous SJF",
continuous_slo: "Continuous SLO",
chunked_slo: "Chunked SLO",
})[value] || value;
}
function arenaTableRows(rows) {
return rows.map((r) => [schedulerLabel(r.scheduler), `${fmt(r.goodput_rps, 2)} req/s`, pct(r.slo_attainment), `${fmt(r.p95_ttft_ms)} ms`, `${fmt(r.p95_e2e_ms)} ms`, pct(r.peak_kv_utilization), fmt(r.unfinished, 0), r.bottleneck || "N/A"]);
}
function renderArena(rows) {
lastArenaRows = rows;
$("arenaEmpty").classList.add("hidden");
$("arenaContent").classList.remove("hidden");
$("arenaCopyBtn").disabled = false;
$("arenaCsvBtn").disabled = false;
$("arenaRows").innerHTML = rows.map((r, index) => `| ${escapeHtml(schedulerLabel(r.scheduler))}${index === 0 ? 'Best' : ""} | ${fmt(r.goodput_rps, 2)} req/s | ${pct(r.slo_attainment)} | ${fmt(r.p95_ttft_ms)} ms | ${fmt(r.p95_e2e_ms)} ms | ${pct(r.peak_kv_utilization)} | ${fmt(r.unfinished, 0)} | ${escapeHtml(r.bottleneck || "N/A")} |
`).join("");
destroyChart("arena");
charts.arena = new Chart($("arenaChart"), {
type: "bar",
data: { labels: rows.map((r) => schedulerLabel(r.scheduler)), datasets: [{ label: "Goodput (req/s)", data: rows.map((r) => r.goodput_rps), backgroundColor: COLORS.blue }, { label: "Raw throughput (req/s)", data: rows.map((r) => r.request_throughput_rps), backgroundColor: "#53677f" }] },
options: { ...commonChartOptions(), scales: { y: { beginAtZero: true } } },
});
}
$("arenaBtn").addEventListener("click", async () => {
const button = $("arenaBtn");
button.disabled = true;
button.textContent = "Comparing...";
try { renderArena((await callPython("compare", { config: configFromUI() })).rows); }
catch (error) { reportError("Scheduler comparison failed", error); }
finally { button.disabled = false; button.textContent = "Compare schedulers"; }
});
const arenaHeaders = ["Scheduler", "Goodput", "SLO attainment", "p95 TTFT", "p95 E2E", "KV peak", "Unfinished", "Diagnosis"];
$("arenaCopyBtn").addEventListener("click", () => copyText(tableText(arenaHeaders, arenaTableRows(lastArenaRows)), "Scheduler table copied"));
$("arenaCsvBtn").addEventListener("click", () => downloadCsv(`inferscale_scheduler-arena_${stamp()}.csv`, arenaHeaders, arenaTableRows(lastArenaRows)));
function capacityTableRows(trace) {
return trace.map((r) => [
`${fmt(r.rate_rps, 2)} req/s`,
r.passed ? "PASS" : "FAIL",
pct(r.slo_attainment),
pct(r.slo_attainment_min),
pct(r.target ?? num("targetSlo")),
`${pct(r.slo_attainment_min)} - ${pct(r.slo_attainment_max)}`,
`${fmt(r.goodput_rps, 2)} req/s`,
`${fmt(r.p95_ttft_ms)} ms`,
`${fmt(r.p95_e2e_ms)} ms`,
]);
}
function renderCapacity(result) {
lastCapacityTrace = result.trace || [];
$("plannerEmpty").classList.add("hidden");
$("plannerContent").classList.remove("hidden");
$("capacityCopyBtn").disabled = false;
$("capacityCsvBtn").disabled = false;
$("pCapacity").textContent = `${fmt(result.capacity_rps, 2)} req/s`;
$("pRecommended").textContent = `${fmt(result.recommended_rps, 2)} req/s`;
$("pHeadroom").textContent = pct(result.headroom ?? num("headroom"));
$("pStatus").textContent = result.status.replaceAll("_", " ");
const state = $("plannerState");
state.textContent = result.status === "ok" ? "Search complete" : result.status.replaceAll("_", " ");
state.className = `tag ${result.capacity_rps > 0 ? "good" : "bad"}`;
$("capacityRows").innerHTML = lastCapacityTrace.map((r) => `| ${fmt(r.rate_rps, 2)} req/s | ${r.passed ? "PASS" : "FAIL"} | ${pct(r.slo_attainment)} | ${pct(r.slo_attainment_min)} | ${pct(r.target ?? num("targetSlo"))} | ${pct(r.slo_attainment_min)} - ${pct(r.slo_attainment_max)} | ${fmt(r.goodput_rps, 2)} req/s | ${fmt(r.p95_ttft_ms)} ms | ${fmt(r.p95_e2e_ms)} ms |
`).join("");
if (!lastCapacityTrace.length) return;
const target = num("targetSlo");
const mean = lastCapacityTrace.map((r) => ({ x: r.rate_rps, y: r.slo_attainment }));
const worst = lastCapacityTrace.map((r) => ({ x: r.rate_rps, y: r.slo_attainment_min }));
const xs = lastCapacityTrace.map((r) => r.rate_rps);
const minX = Math.min(...xs);
const maxX = Math.max(...xs);
destroyChart("capacity");
charts.capacity = new Chart($("capacityChart"), {
type: "line",
data: { datasets: [
{ label: "Mean SLO attainment", data: mean, borderColor: COLORS.blue, backgroundColor: COLORS.blue, fill: false, tension: .06, pointRadius: 3 },
{ label: "Worst repetition", data: worst, borderColor: COLORS.amber, backgroundColor: COLORS.amber, borderDash: [5, 4], fill: false, pointRadius: 2, tension: .06 },
{ label: "Target", data: [{ x: minX, y: target }, { x: maxX, y: target }], borderColor: COLORS.green, backgroundColor: COLORS.green, borderDash: [6, 5], fill: false, pointRadius: 0 },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", title: { display: true, text: "Offered load (req/s)" }, ticks: { maxTicksLimit: 8 } }, y: { min: 0, max: 1, ticks: { callback: (v) => `${Math.round(v * 100)}%` } } } },
});
}
$("capacityBtn").addEventListener("click", async () => {
if ($("arrival").value === "trace") { showToast("Capacity search requires a rate-driven workload"); return; }
const button = $("capacityBtn");
const state = $("plannerState");
button.disabled = true;
button.textContent = "Searching...";
state.textContent = "Running simulations...";
state.className = "tag neutral";
try {
renderCapacity(await callPython("capacity", {
config: configFromUI({ slo_attainment_target: num("targetSlo") }),
min_rate: num("minRate"),
max_rate: num("maxRate"),
iterations: num("searchIter"),
repetitions: num("repetitions"),
headroom: num("headroom"),
}));
} catch (error) {
state.textContent = "Error";
state.className = "tag bad";
reportError("Capacity search failed", error);
} finally {
button.disabled = false;
button.textContent = "Find sustainable capacity";
}
});
const capacityHeaders = ["Rate", "Pass", "Mean SLO", "Worst repetition", "Target", "SLO range", "Goodput", "p95 TTFT", "p95 E2E"];
$("capacityCopyBtn").addEventListener("click", () => copyText(tableText(capacityHeaders, capacityTableRows(lastCapacityTrace)), "Capacity table copied"));
$("capacityCsvBtn").addEventListener("click", () => downloadCsv(`inferscale_capacity-trace_${stamp()}.csv`, capacityHeaders, capacityTableRows(lastCapacityTrace)));
function scenarioLabel(value) {
return ({
colocated: "Colocated",
colocated_cache: "Colocated + prefix cache",
disaggregated_pd: "P/D disaggregated",
disaggregated_pd_cache: "P/D + prefix cache",
})[value] || value;
}
function topologyTableRows(rows) {
return rows.map((r) => [
scenarioLabel(r.scenario),
fmt(r.accelerator_instances, 0),
`${fmt(r.goodput_rps, 2)} req/s`,
`${fmt(r.goodput_per_accelerator, 2)} req/s/GPU`,
pct(r.slo_attainment),
`${fmt(r.p95_ttft_ms)} ms`,
`${fmt(r.p95_e2e_ms)} ms`,
`${fmt(r.p95_transfer_ms, 2)} ms`,
pct(r.prefix_hit_rate),
`${fmt(r.prefill_tokens_saved, 0)} tok`,
r.bottleneck || "N/A",
]);
}
function renderTopology(rows) {
lastTopologyRows = rows;
$("topologyEmpty").classList.add("hidden");
$("topologyContent").classList.remove("hidden");
$("topologyCopyBtn").disabled = false;
$("topologyCsvBtn").disabled = false;
$("topologyRows").innerHTML = rows.map((r, index) => `| ${escapeHtml(scenarioLabel(r.scenario))}${index === 0 ? 'Best' : ""} | ${fmt(r.accelerator_instances, 0)} | ${fmt(r.goodput_rps, 2)} req/s | ${pct(r.slo_attainment)} | ${fmt(r.p95_ttft_ms)} ms | ${fmt(r.p95_e2e_ms)} ms | ${fmt(r.p95_transfer_ms, 2)} ms | ${pct(r.prefix_hit_rate)} | ${fmt(r.prefill_tokens_saved, 0)} tok | ${escapeHtml(r.bottleneck || "N/A")} |
`).join("");
const palette = [COLORS.blue, COLORS.green, COLORS.amber, COLORS.red];
destroyChart("topology");
charts.topology = new Chart($("topologyChart"), {
type: "scatter",
data: { datasets: rows.map((r, i) => ({ label: scenarioLabel(r.scenario), data: [{ x: r.p95_ttft_ms, y: r.goodput_rps }], backgroundColor: palette[i % palette.length], borderColor: palette[i % palette.length], pointRadius: 6, pointHoverRadius: 8 })) },
options: { ...commonChartOptions(), plugins: { legend: pointLegend() }, scales: { x: { title: { display: true, text: "p95 TTFT (ms)" }, beginAtZero: true }, y: { title: { display: true, text: "Goodput (req/s)" }, beginAtZero: true } } },
});
}
$("topologyBtn").addEventListener("click", async () => {
const button = $("topologyBtn");
button.disabled = true;
button.textContent = "Comparing...";
try { renderTopology((await callPython("topology_compare", { config: configFromUI() })).rows); }
catch (error) { reportError("Topology comparison failed", error); }
finally { button.disabled = false; button.textContent = "Compare 4 scenarios"; }
});
const topologyHeaders = ["Scenario", "GPU instances", "Goodput", "Goodput / GPU", "SLO attainment", "p95 TTFT", "p95 E2E", "p95 KV transfer", "Cache hit", "Prefill saved", "Diagnosis"];
$("topologyCopyBtn").addEventListener("click", () => copyText(tableText(topologyHeaders, topologyTableRows(lastTopologyRows)), "Topology table copied"));
$("topologyCsvBtn").addEventListener("click", () => downloadCsv(`inferscale_topology-cache-study_${stamp()}.csv`, topologyHeaders, topologyTableRows(lastTopologyRows)));
function designTableRows(rows) {
return rows.map((r) => [
r.label,
r.pareto ? "YES" : "NO",
r.efficiency_pareto ? "YES" : "NO",
r.slo_pass ? "PASS" : "FAIL",
fmt(r.accelerator_instances, 0),
`${fmt(r.goodput_rps, 2)} req/s`,
`${fmt(r.goodput_per_accelerator, 2)} req/s/GPU`,
`${fmt(r.p95_ttft_ms)} ms`,
`${fmt(r.p95_e2e_ms)} ms`,
pct(r.peak_kv_utilization),
r.bottleneck || "N/A",
]);
}
function renderDesign(result) {
lastDesignRows = result.rows || [];
$("designEmpty").classList.add("hidden");
$("designContent").classList.remove("hidden");
$("designCopyBtn").disabled = false;
$("designCsvBtn").disabled = false;
$("dCandidates").textContent = fmt(result.candidate_count, 0);
$("dPareto").textContent = fmt(result.pareto_count, 0);
$("dEfficiencyPareto").textContent = fmt(result.efficiency_pareto_count, 0);
$("designRows").innerHTML = lastDesignRows.map((r) => `| ${escapeHtml(r.label)}${r.pareto ? 'Perf' : ""}${r.efficiency_pareto ? 'Eff' : ""} | ${r.pareto ? "YES" : "NO"} | ${r.efficiency_pareto ? "YES" : "NO"} | ${r.slo_pass ? "PASS" : "FAIL"} | ${fmt(r.accelerator_instances, 0)} | ${fmt(r.goodput_rps, 2)} req/s | ${fmt(r.goodput_per_accelerator, 2)} req/s/GPU | ${fmt(r.p95_ttft_ms)} ms | ${fmt(r.p95_e2e_ms)} ms | ${pct(r.peak_kv_utilization)} | ${escapeHtml(r.bottleneck || "N/A")} |
`).join("");
const passPoints = lastDesignRows.filter((r) => r.slo_pass).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_rps }));
const failPoints = lastDesignRows.filter((r) => !r.slo_pass).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_rps }));
const frontier = lastDesignRows.filter((r) => r.pareto).sort((a, b) => a.p95_ttft_ms - b.p95_ttft_ms).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_rps }));
destroyChart("design");
charts.design = new Chart($("designChart"), {
type: "scatter",
data: { datasets: [
{ label: "SLO pass", data: passPoints, backgroundColor: COLORS.green, borderColor: COLORS.green, pointRadius: 4 },
{ label: "SLO fail", data: failPoints, backgroundColor: COLORS.gray, borderColor: COLORS.gray, pointRadius: 4 },
{ type: "line", label: "Performance frontier", pointStyle: "line", data: frontier, borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointBackgroundColor: COLORS.blue, pointRadius: 5, fill: false, tension: 0 },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: pointLegend() }, scales: { x: { title: { display: true, text: "p95 TTFT (ms)" }, beginAtZero: true }, y: { title: { display: true, text: "Goodput (req/s)" }, beginAtZero: true } } },
});
const efficiencyPass = lastDesignRows.filter((r) => r.slo_pass).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_per_accelerator }));
const efficiencyFail = lastDesignRows.filter((r) => !r.slo_pass).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_per_accelerator }));
const efficiencyFrontier = lastDesignRows.filter((r) => r.efficiency_pareto).sort((a, b) => a.p95_ttft_ms - b.p95_ttft_ms).map((r) => ({ x: r.p95_ttft_ms, y: r.goodput_per_accelerator }));
destroyChart("designEfficiency");
charts.designEfficiency = new Chart($("designEfficiencyChart"), {
type: "scatter",
data: { datasets: [
{ label: "SLO pass", data: efficiencyPass, backgroundColor: COLORS.green, borderColor: COLORS.green, pointRadius: 4 },
{ label: "SLO fail", data: efficiencyFail, backgroundColor: COLORS.gray, borderColor: COLORS.gray, pointRadius: 4 },
{ type: "line", label: "Efficiency frontier", pointStyle: "line", data: efficiencyFrontier, borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointBackgroundColor: COLORS.amber, pointRadius: 5, fill: false, tension: 0 },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: pointLegend() }, scales: { x: { title: { display: true, text: "p95 TTFT (ms)" }, beginAtZero: true }, y: { title: { display: true, text: "Goodput / accelerator (req/s/GPU)" }, beginAtZero: true } } },
});
}
$("designBtn").addEventListener("click", async () => {
const button = $("designBtn");
button.disabled = true;
button.textContent = "Exploring...";
try { renderDesign(await callPython("design_space", { config: configFromUI(), include_disaggregated: $("includePd").checked })); }
catch (error) { reportError("Design-space sweep failed", error); }
finally { button.disabled = false; button.textContent = "Explore design space"; }
});
const designHeaders = ["Candidate", "Perf Pareto", "Efficiency Pareto", "SLO pass", "GPU instances", "Goodput", "Goodput / GPU", "p95 TTFT", "p95 E2E", "KV peak", "Diagnosis"];
$("designCopyBtn").addEventListener("click", () => copyText(tableText(designHeaders, designTableRows(lastDesignRows)), "Design table copied"));
$("designCsvBtn").addEventListener("click", () => downloadCsv(`inferscale_design-space_${stamp()}.csv`, designHeaders, designTableRows(lastDesignRows)));
function studyValue(metric, value) {
if (metric === "slo_attainment") return pct(value);
if (metric === "goodput_rps") return `${fmt(value, 3)} req/s`;
return `${fmt(value, 2)} ms`;
}
function studyDelta(metric, value) {
if (metric === "slo_attainment") return `${value >= 0 ? "+" : ""}${fmt(value * 100, 2)} pp`;
if (metric === "goodput_rps") return `${value >= 0 ? "+" : ""}${fmt(value, 3)} req/s`;
return `${value >= 0 ? "+" : ""}${fmt(value, 2)} ms`;
}
function pairedTableRows(result) {
return (result?.metrics || []).map((m) => [
m.label,
studyValue(m.metric, m.baseline_mean),
studyValue(m.metric, m.treatment_mean),
studyDelta(m.metric, m.delta_mean),
`${studyDelta(m.metric, m.delta_ci95_low)} to ${studyDelta(m.metric, m.delta_ci95_high)}`,
`${m.relative_change_pct >= 0 ? "+" : ""}${fmt(m.relative_change_pct, 2)}%`,
pct(m.treatment_win_rate),
m.ci_excludes_zero ? "YES" : "NO",
]);
}
function renderPairedStudy(result) {
lastPairedStudy = result;
$("pairedEmpty").classList.add("hidden");
$("pairedContent").classList.remove("hidden");
["pairedCopyBtn", "pairedCsvBtn", "pairedJsonBtn"].forEach((id) => { $(id).disabled = false; });
const state = $("pairedState");
state.textContent = `${result.repetitions} paired runs`;
state.className = "tag good";
let improvements = 0;
let regressions = 0;
for (const m of result.metrics) {
if (!m.ci_excludes_zero) continue;
const favorable = m.preferred_direction === "higher" ? m.delta_ci95_low > 0 : m.delta_ci95_high < 0;
favorable ? improvements++ : regressions++;
}
const conclusion = improvements && !regressions
? `${improvements} metric${improvements === 1 ? "" : "s"} show a directional treatment improvement with a 95% bootstrap interval excluding zero.`
: regressions && !improvements
? `${regressions} metric${regressions === 1 ? "" : "s"} show a directional treatment regression with a 95% bootstrap interval excluding zero.`
: improvements || regressions
? "The treatment shows mixed statistically separated effects across metrics; inspect the latency/throughput trade-off rather than declaring one winner."
: "None of the paired metric intervals excludes zero; this workload does not support a stable directional conclusion at the chosen repetition count.";
$("pairedSummary").innerHTML = `${escapeHtml(result.baseline_label)} vs ${escapeHtml(result.treatment_label)}. ${result.repetitions} common-seed repetitions with ${result.bootstrap_samples} bootstrap resamples. ${escapeHtml(conclusion)}`;
$("pairedRows").innerHTML = result.metrics.map((m) => {
const favorable = m.preferred_direction === "higher" ? m.delta_ci95_low > 0 : m.delta_ci95_high < 0;
const separated = m.ci_excludes_zero;
return `| ${escapeHtml(m.label)} | ${studyValue(m.metric, m.baseline_mean)} | ${studyValue(m.metric, m.treatment_mean)} | ${studyDelta(m.metric, m.delta_mean)} | ${studyDelta(m.metric, m.delta_ci95_low)} to ${studyDelta(m.metric, m.delta_ci95_high)} | ${m.relative_change_pct >= 0 ? "+" : ""}${fmt(m.relative_change_pct, 2)}% | ${pct(m.treatment_win_rate)} | ${separated ? "YES" : "NO"} |
`;
}).join("");
const effects = result.metrics.map((m) => m.relative_change_pct * (m.preferred_direction === "higher" ? 1 : -1));
destroyChart("paired");
charts.paired = new Chart($("pairedChart"), {
type: "bar",
data: { labels: result.metrics.map((m) => m.label), datasets: [{ label: "Relative improvement (%)", data: effects, backgroundColor: effects.map((v) => v >= 0 ? COLORS.green : COLORS.red) }] },
options: { ...commonChartOptions(), plugins: { legend: { display: false }, tooltip: { callbacks: { label: (ctx) => `${fmt(ctx.raw, 2)}% (positive = treatment better)` } } }, scales: { y: { title: { display: true, text: "Relative improvement (%)" } } } },
});
}
const pairedHeaders = ["Metric", "Baseline mean", "Treatment mean", "Mean delta", "95% bootstrap CI", "Relative change", "Treatment win rate", "CI excludes zero"];
$("pairedStudyBtn").addEventListener("click", async () => {
const button = $("pairedStudyBtn");
button.disabled = true;
button.textContent = "Running paired study...";
$("pairedState").textContent = "Running...";
$("pairedState").className = "tag neutral";
try {
renderPairedStudy(await callPython("paired_study", {
config: configFromUI(), study: $("studyPreset").value,
repetitions: num("studyReps"), bootstrap_samples: num("studyBootstrap"),
}));
} catch (error) {
$("pairedState").textContent = "Error";
$("pairedState").className = "tag bad";
reportError("Paired study failed", error);
} finally {
button.disabled = false;
button.textContent = "Run paired study";
}
});
$("pairedCopyBtn").addEventListener("click", () => { if (lastPairedStudy) copyText(tableText(pairedHeaders, pairedTableRows(lastPairedStudy)), "Paired study copied"); });
$("pairedCsvBtn").addEventListener("click", () => { if (lastPairedStudy) downloadCsv(`inferscale_paired-study_${slug(lastPairedStudy.study)}_${stamp()}.csv`, pairedHeaders, pairedTableRows(lastPairedStudy)); });
$("pairedJsonBtn").addEventListener("click", () => { if (lastPairedStudy) downloadNamedJson(`inferscale_paired-study_${slug(lastPairedStudy.study)}`, lastPairedStudy); });
function robustTableRows(result) {
return (result?.rows || []).map((r) => [
r.sample,
fmt(r.prefill_scale, 3), fmt(r.decode_scale, 3), fmt(r.transfer_scale, 3),
pct(r.baseline.slo_attainment), pct(r.treatment.slo_attainment),
studyDelta("goodput_rps", r.treatment.goodput_rps - r.baseline.goodput_rps),
studyDelta("p95_ttft_ms", r.treatment.p95_ttft_ms - r.baseline.p95_ttft_ms),
studyDelta("p95_e2e_ms", r.treatment.p95_e2e_ms - r.baseline.p95_e2e_ms),
]);
}
function renderRobustStudy(result) {
lastRobustStudy = result;
$("robustEmpty").classList.add("hidden");
$("robustContent").classList.remove("hidden");
["robustCopyBtn", "robustCsvBtn", "robustJsonBtn"].forEach((id) => { $(id).disabled = false; });
const s = result.summary;
$("rTtftWins").textContent = pct(s.treatment_ttft_win_fraction);
$("rGoodputWins").textContent = pct(s.treatment_goodput_win_fraction);
$("rTreatmentPass").textContent = pct(s.treatment_slo_pass_fraction);
$("rBaselinePass").textContent = pct(s.baseline_slo_pass_fraction);
$("robustState").textContent = `${result.samples} perturbations`;
$("robustState").className = "tag good";
const ttftStable = s.treatment_ttft_win_fraction >= .8 || s.treatment_ttft_win_fraction <= .2;
const goodputStable = s.treatment_goodput_win_fraction >= .8 || s.treatment_goodput_win_fraction <= .2;
const stability = ttftStable && goodputStable ? "The directional conclusion is comparatively stable across the tested perturbations." : "At least one conclusion changes frequently under profile perturbation; treat the apparent winner as calibration-sensitive.";
$("robustSummary").innerHTML = `${escapeHtml(result.baseline_label)} vs ${escapeHtml(result.treatment_label)}. ${result.samples} shared perturbations within +/-${fmt(result.uncertainty * 100, 0)}% of the analytical prefill/decode/transfer timing proxies. ${escapeHtml(stability)} This is sensitivity analysis, not a confidence interval over real GPUs.`;
$("robustRows").innerHTML = result.rows.map((r) => `| ${r.sample} | ${fmt(r.prefill_scale, 3)} | ${fmt(r.decode_scale, 3)} | ${fmt(r.transfer_scale, 3)} | ${pct(r.baseline.slo_attainment)} | ${pct(r.treatment.slo_attainment)} | ${studyDelta("goodput_rps", r.treatment.goodput_rps - r.baseline.goodput_rps)} | ${studyDelta("p95_ttft_ms", r.treatment.p95_ttft_ms - r.baseline.p95_ttft_ms)} | ${studyDelta("p95_e2e_ms", r.treatment.p95_e2e_ms - r.baseline.p95_e2e_ms)} |
`).join("");
}
const robustHeaders = ["Sample", "Prefill scale", "Decode scale", "Transfer scale", "Baseline SLO", "Treatment SLO", "Goodput delta", "TTFT delta", "E2E delta"];
$("robustStudyBtn").addEventListener("click", async () => {
const button = $("robustStudyBtn");
button.disabled = true;
button.textContent = "Stress-testing...";
$("robustState").textContent = "Running...";
$("robustState").className = "tag neutral";
try {
renderRobustStudy(await callPython("robustness_study", {
config: configFromUI(), study: $("studyPreset").value,
samples: num("robustSamples"), uncertainty: num("robustUncertainty"),
}));
} catch (error) {
$("robustState").textContent = "Error";
$("robustState").className = "tag bad";
reportError("Sensitivity study failed", error);
} finally {
button.disabled = false;
button.textContent = "Stress-test selected hypothesis";
}
});
$("robustCopyBtn").addEventListener("click", () => { if (lastRobustStudy) copyText(tableText(robustHeaders, robustTableRows(lastRobustStudy)), "Robustness table copied"); });
$("robustCsvBtn").addEventListener("click", () => { if (lastRobustStudy) downloadCsv(`inferscale_robustness_${slug(lastRobustStudy.study)}_${stamp()}.csv`, robustHeaders, robustTableRows(lastRobustStudy)); });
$("robustJsonBtn").addEventListener("click", () => { if (lastRobustStudy) downloadNamedJson(`inferscale_robustness_${slug(lastRobustStudy.study)}`, lastRobustStudy); });
function agentConfigFromUI(overrides = {}) {
return {
model: $("agentModel").value,
accelerator: $("agentAccelerator").value,
quantization: $("agentQuantization").value,
replicas: num("agentReplicas"),
session_rate_rps: num("agentRate"),
duration_s: num("agentDuration"),
turns_mean: num("agentTurns"),
turns_cv: num("agentTurnsCv"),
initial_prompt_tokens_mean: num("agentInitialPrompt"),
append_tokens_mean: num("agentAppend"),
output_tokens_mean: num("agentOutput"),
token_cv: num("agentTokenCv"),
output_tokens_cv: num("agentTokenCv"),
tool_gap_mean_s: num("agentToolGap"),
tool_gap_cv: num("agentToolGapCv"),
seed: num("agentSeed"),
retention_policy: $("agentRetention").value,
routing_policy: $("agentRouting").value,
kv_ttl_s: num("agentTtl"),
kv_memory_fraction: num("agentKvFraction"),
affinity_slack_ms: num("agentAffinitySlack"),
gap_aware_threshold_s: num("agentGapThreshold"),
host_memory_gb: num("agentHostMemory"),
host_bandwidth_gbps: num("agentHostBandwidth"),
host_transfer_base_ms: num("agentHostBase"),
adaptive_predictor_scope: $("agentPredictorScope").value,
adaptive_alpha: num("agentPredictorAlpha"),
adaptive_min_observations: num("agentPredictorMin"),
slo_turn_ttft_ms: num("agentTtftSlo"),
slo_session_e2e_ms: num("agentSessionSlo"),
...overrides,
};
}
function renderAgentRun(result) {
lastAgentRun = result;
$("agentRunEmpty").classList.add("hidden");
$("agentRunContent").classList.remove("hidden");
["agentRunCopyJson", "agentRunJson"].forEach((id) => { $(id).disabled = false; });
const l = result.latency;
const r = result.resource;
const sm = result.summary;
$("agentTtft").textContent = `${fmt(l.turn_ttft_ms.p95)} ms`;
$("agentSessionE2e").textContent = `${fmt(l.session_e2e_ms.p95)} ms`;
$("agentSessionSloValue").textContent = pct(sm.session_slo_attainment);
$("agentCacheHit").textContent = pct(r.cross_turn_cache_hit_rate);
$("agentRecompute").textContent = `${fmt(r.recomputed_history_tokens, 0)} tok`;
$("agentPeakKv").textContent = `${fmt(r.peak_kv_gb, 3)} GB`;
$("agentHostMeanKv").textContent = `${fmt(r.mean_host_kv_gb, 3)} GB`;
$("agentHostTransfer").textContent = `${fmt(r.p95_host_transfer_ms)} ms`;
const state = $("agentRunState");
state.textContent = `${sm.sessions_completed}/${sm.sessions_generated} sessions`;
state.className = `tag ${sm.sessions_completed === sm.sessions_generated && sm.turns_failed === 0 ? "good" : "bad"}`;
$("agentRunSummary").innerHTML = `${escapeHtml(result.config.retention_policy)} retention + ${escapeHtml(result.config.routing_policy.replaceAll("_", " "))} routing. ${sm.turns_completed} turns completed across ${sm.sessions_completed} sessions. Reuse hit ${pct(r.cross_turn_cache_hit_rate)} of eligible turns; ${pct(r.host_cache_hit_rate)} came from the host tier. ${fmt(r.recomputed_history_tokens, 0)} history tokens were recomputed. HBM and host residency are simulator-side memory-time accounting metrics.`;
const timeline = result.timeline || [];
destroyChart("agentTimeline");
charts.agentTimeline = new Chart($("agentTimelineChart"), {
type: "line",
data: {
datasets: [
{ label: "HBM KV GB", data: timeline.map((x) => ({ x: x.time_s, y: x.kv_used_gb })), borderColor: COLORS.green, backgroundColor: COLORS.green, pointRadius: 0, tension: .08, yAxisID: "yKv" },
{ label: "Host KV GB", data: timeline.map((x) => ({ x: x.time_s, y: x.host_kv_gb || 0 })), borderColor: COLORS.steel, backgroundColor: COLORS.steel, pointRadius: 0, borderDash: [6, 4], tension: .08, yAxisID: "yKv" },
{ label: "Busy replicas", data: timeline.map((x) => ({ x: x.time_s, y: x.busy_replicas })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 0, tension: .08, yAxisID: "yCount" },
{ label: "Queued turns", data: timeline.map((x) => ({ x: x.time_s, y: x.queued_turns })), borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 0, tension: .08, yAxisID: "yCount" },
],
},
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", title: { display: true, text: "Virtual time (s)" } }, yCount: { position: "left", beginAtZero: true, title: { display: true, text: "Replicas / queued turns" } }, yKv: { position: "right", beginAtZero: true, grid: { drawOnChartArea: false }, title: { display: true, text: "KV GB" } } } },
});
destroyChart("agentTurn");
charts.agentTurn = new Chart($("agentTurnChart"), {
type: "scatter",
data: { datasets: [{ label: "Turn", data: (result.turns || []).map((x) => ({ x: x.turn_index, y: x.ttft_ms })), backgroundColor: COLORS.blue, pointRadius: 3, pointHoverRadius: 5 }] },
options: { ...commonChartOptions(), plugins: { legend: { display: false } }, scales: { x: { type: "linear", ticks: { precision: 0 }, title: { display: true, text: "Turn index" } }, y: { beginAtZero: true, title: { display: true, text: "TTFT (ms)" } } } },
});
}
$("agentRunBtn").addEventListener("click", async () => {
const button = $("agentRunBtn");
button.disabled = true;
button.textContent = "Running stateful simulation...";
$("agentRunState").textContent = "Running...";
$("agentRunState").className = "tag neutral";
try { renderAgentRun(await callPython("agent_simulate", { config: agentConfigFromUI() })); }
catch (error) { $("agentRunState").textContent = "Error"; $("agentRunState").className = "tag bad"; reportError("Agent session simulation failed", error); }
finally { button.disabled = false; button.textContent = "Run stateful session simulation"; }
});
$("agentRunCopyJson").addEventListener("click", () => { if (lastAgentRun) copyText(JSON.stringify(lastAgentRun, null, 2), "Agent-session JSON copied"); });
$("agentRunJson").addEventListener("click", () => { if (lastAgentRun) downloadNamedJson("inferscale_agent-session", lastAgentRun); });
const agentCompareHeaders = ["Policy", "p95 turn TTFT", "p95 session E2E", "Cache hit", "Route locality", "Recomputed history", "Mean KV", "Peak KV", "HBM GB-s", "Evictions"];
function agentCompareTableRows(result) {
return result.rows.map((r) => [r.label, `${fmt(r.p95_turn_ttft_ms)} ms`, `${fmt(r.p95_session_e2e_ms)} ms`, pct(r.cache_hit_rate), pct(r.routing_locality_rate), `${fmt(r.recomputed_history_tokens, 0)} tok`, `${fmt(r.mean_kv_gb, 3)} GB`, `${fmt(r.peak_kv_gb, 3)} GB`, fmt(r.hbm_gb_seconds, 3), r.pressure_evictions + r.ttl_evictions]);
}
function renderAgentCompare(result) {
lastAgentCompare = result;
$("agentCompareEmpty").classList.add("hidden");
$("agentCompareContent").classList.remove("hidden");
["agentCompareCopy", "agentCompareCsv"].forEach((id) => { $(id).disabled = false; });
$("agentCompareRows").innerHTML = result.rows.map((r) => `| ${escapeHtml(r.label)} | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.cache_hit_rate)} | ${pct(r.routing_locality_rate)} | ${fmt(r.recomputed_history_tokens, 0)} tok | ${fmt(r.mean_kv_gb, 3)} GB | ${fmt(r.peak_kv_gb, 3)} GB | ${fmt(r.hbm_gb_seconds, 3)} | ${r.pressure_evictions + r.ttl_evictions} |
`).join("");
destroyChart("agentCompare");
charts.agentCompare = new Chart($("agentCompareChart"), {
type: "scatter",
data: { datasets: result.rows.map((r, i) => ({ label: r.label, data: [{ x: r.mean_kv_gb, y: r.p95_turn_ttft_ms }], backgroundColor: [COLORS.gray, COLORS.amber, COLORS.green, COLORS.blue][i], borderColor: [COLORS.gray, COLORS.amber, COLORS.green, COLORS.blue][i], pointRadius: 7, pointHoverRadius: 9 })) },
options: { ...commonChartOptions(), plugins: { legend: pointLegend() }, scales: { x: { beginAtZero: true, title: { display: true, text: "Mean resident KV (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 turn TTFT (ms)" } } } },
});
}
$("agentCompareBtn").addEventListener("click", async () => {
const button = $("agentCompareBtn"); button.disabled = true; button.textContent = "Comparing...";
try { renderAgentCompare(await callPython("agent_compare", { config: agentConfigFromUI() })); }
catch (error) { reportError("Agent policy comparison failed", error); }
finally { button.disabled = false; button.textContent = "Compare 4 policies"; }
});
$("agentCompareCopy").addEventListener("click", () => { if (lastAgentCompare) copyText(tableText(agentCompareHeaders, agentCompareTableRows(lastAgentCompare)), "Agent policy table copied"); });
$("agentCompareCsv").addEventListener("click", () => { if (lastAgentCompare) downloadCsv(`inferscale_agent-policy-comparison_${stamp()}.csv`, agentCompareHeaders, agentCompareTableRows(lastAgentCompare)); });
const agentTtlHeaders = ["TTL", "Pareto", "p95 turn TTFT", "p95 session E2E", "Cache hit", "Recomputed history", "Mean KV", "HBM GB-s", "TTL evictions", "Pressure evictions"];
function agentTtlTableRows(result) {
return result.rows.map((r) => [`${fmt(r.ttl_s, 2)} s`, r.pareto ? "YES" : "NO", `${fmt(r.p95_turn_ttft_ms)} ms`, `${fmt(r.p95_session_e2e_ms)} ms`, pct(r.cache_hit_rate), `${fmt(r.recomputed_history_tokens, 0)} tok`, `${fmt(r.mean_kv_gb, 3)} GB`, fmt(r.hbm_gb_seconds, 3), r.ttl_evictions, r.pressure_evictions]);
}
function renderAgentTtl(result) {
lastAgentTtl = result;
$("agentTtlEmpty").classList.add("hidden");
$("agentTtlContent").classList.remove("hidden");
["agentTtlCopy", "agentTtlCsv"].forEach((id) => { $(id).disabled = false; });
$("agentTtlRows").innerHTML = result.rows.map((r) => `| ${fmt(r.ttl_s, 2)} s | ${r.pareto ? "YES" : "NO"} | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.cache_hit_rate)} | ${fmt(r.recomputed_history_tokens, 0)} tok | ${fmt(r.mean_kv_gb, 3)} GB | ${fmt(r.hbm_gb_seconds, 3)} | ${r.ttl_evictions} | ${r.pressure_evictions} |
`).join("");
const pareto = result.rows.filter((r) => r.pareto).sort((a, b) => a.mean_kv_gb - b.mean_kv_gb);
destroyChart("agentTtl");
charts.agentTtl = new Chart($("agentTtlChart"), {
type: "scatter",
data: { datasets: [
{ label: "TTL candidates", data: result.rows.map((r) => ({ x: r.mean_kv_gb, y: r.p95_turn_ttft_ms, ttl: r.ttl_s })), backgroundColor: COLORS.blue, pointRadius: 5, pointHoverRadius: 7 },
{ type: "line", label: "Retention frontier", data: pareto.map((r) => ({ x: r.mean_kv_gb, y: r.p95_turn_ttft_ms })), borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 5, tension: 0, fill: false },
] },
options: { ...commonChartOptions(), plugins: { legend: lineLegend(), tooltip: { callbacks: { afterLabel: (ctx) => ctx.datasetIndex === 0 ? `TTL ${fmt(ctx.raw.ttl, 2)} s` : "" } } }, scales: { x: { beginAtZero: true, title: { display: true, text: "Mean resident KV (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 turn TTFT (ms)" } } } },
});
}
$("agentTtlBtn").addEventListener("click", async () => {
const button = $("agentTtlBtn"); button.disabled = true; button.textContent = "Sweeping TTL...";
try { renderAgentTtl(await callPython("agent_ttl_sweep", { config: agentConfigFromUI() })); }
catch (error) { reportError("TTL sweep failed", error); }
finally { button.disabled = false; button.textContent = "Run TTL sweep"; }
});
$("agentTtlCopy").addEventListener("click", () => { if (lastAgentTtl) copyText(tableText(agentTtlHeaders, agentTtlTableRows(lastAgentTtl)), "TTL sweep copied"); });
$("agentTtlCsv").addEventListener("click", () => { if (lastAgentTtl) downloadCsv(`inferscale_agent-ttl-frontier_${stamp()}.csv`, agentTtlHeaders, agentTtlTableRows(lastAgentTtl)); });
const agentMemoryHeaders = ["Policy", "p95 turn TTFT", "p95 session E2E", "Session SLO", "Reuse", "HBM hit", "Host hit", "Mean HBM", "Mean host", "Transfer p95", "Recomputed"];
function agentMemoryTableRows(result) {
return result.rows.map((r) => [r.label, `${fmt(r.p95_turn_ttft_ms)} ms`, `${fmt(r.p95_session_e2e_ms)} ms`, pct(r.session_slo_attainment), pct(r.cache_hit_rate), pct(r.hbm_hit_rate), pct(r.host_hit_rate), `${fmt(r.mean_hbm_gb, 3)} GB`, `${fmt(r.mean_host_gb, 3)} GB`, `${fmt(r.p95_host_transfer_ms)} ms`, `${fmt(r.recomputed_history_tokens, 0)} tok`]);
}
function renderAgentMemory(result) {
lastAgentMemory = result;
$("agentMemoryEmpty").classList.add("hidden");
$("agentMemoryContent").classList.remove("hidden");
$("agentMemoryCompareBlock").classList.remove("hidden");
["agentMemoryCopy", "agentMemoryCsv"].forEach((id) => { $(id).disabled = false; });
$("agentMemoryRows").innerHTML = result.rows.map((r) => `| ${escapeHtml(r.label)} | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.session_slo_attainment)} | ${pct(r.cache_hit_rate)} | ${pct(r.hbm_hit_rate)} | ${pct(r.host_hit_rate)} | ${fmt(r.mean_hbm_gb, 3)} GB | ${fmt(r.mean_host_gb, 3)} GB | ${fmt(r.p95_host_transfer_ms)} ms | ${fmt(r.recomputed_history_tokens, 0)} tok |
`).join("");
const palette = [COLORS.gray, COLORS.amber, COLORS.green, COLORS.blue, COLORS.purple];
destroyChart("agentMemory");
charts.agentMemory = new Chart($("agentMemoryChart"), {
type: "scatter",
data: { datasets: result.rows.map((r, i) => ({ label: r.label, data: [{ x: r.mean_hbm_gb, y: r.p95_turn_ttft_ms }], backgroundColor: palette[i], borderColor: palette[i], pointRadius: 7, pointHoverRadius: 9 })) },
options: { ...commonChartOptions(), plugins: { legend: pointLegend() }, scales: { x: { beginAtZero: true, title: { display: true, text: "Mean HBM KV (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 turn TTFT (ms)" } } } },
});
}
$("agentMemoryCompareBtn").addEventListener("click", async () => {
const button = $("agentMemoryCompareBtn"); button.disabled = true; button.textContent = "Comparing policies...";
try { renderAgentMemory(await callPython("agent_memory_compare", { config: agentConfigFromUI() })); }
catch (error) { reportError("Memory policy comparison failed", error); }
finally { button.disabled = false; button.textContent = "Compare memory policies"; }
});
$("agentMemoryCopy").addEventListener("click", () => { if (lastAgentMemory) copyText(tableText(agentMemoryHeaders, agentMemoryTableRows(lastAgentMemory)), "Memory-policy table copied"); });
$("agentMemoryCsv").addEventListener("click", () => { if (lastAgentMemory) downloadCsv(`inferscale_agent-memory-policies_${stamp()}.csv`, agentMemoryHeaders, agentMemoryTableRows(lastAgentMemory)); });
const agentBudgetHeaders = ["Policy", "Budget / replica", "Reference x", "p95 TTFT", "Session SLO", "Reuse", "Mean HBM", "Mean host", "Pressure evictions", "Failed turns"];
function agentBudgetTableRows(result) {
return result.rows.map((r) => [r.policy, `${fmt(r.budget_gb_per_replica, 4)} GB`, `${fmt(r.budget_multiplier, 2)}x`, `${fmt(r.p95_turn_ttft_ms)} ms`, pct(r.session_slo_attainment), pct(r.cache_hit_rate), `${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.mean_host_gb, 4)} GB`, r.pressure_evictions, r.turns_failed]);
}
function renderAgentBudget(result) {
lastAgentBudget = result;
$("agentMemoryEmpty").classList.add("hidden");
$("agentMemoryContent").classList.remove("hidden");
$("agentBudgetBlock").classList.remove("hidden");
["agentBudgetCopy", "agentBudgetCsv"].forEach((id) => { $(id).disabled = false; });
$("agentBudgetCaption").textContent = `HBM budget sweep (reference peak ${fmt(result.reference_peak_replica_kv_gb, 4)} GB / replica)`;
$("agentBudgetRows").innerHTML = result.rows.map((r) => `| ${escapeHtml(r.policy)} | ${fmt(r.budget_gb_per_replica, 4)} GB | ${fmt(r.budget_multiplier, 2)}x | ${fmt(r.p95_turn_ttft_ms)} ms | ${pct(r.session_slo_attainment)} | ${pct(r.cache_hit_rate)} | ${fmt(r.mean_hbm_gb, 4)} GB | ${fmt(r.mean_host_gb, 4)} GB | ${r.pressure_evictions} | ${r.turns_failed} |
`).join("");
const policies = [...new Set(result.rows.map((r) => r.policy))];
const palette = [COLORS.green, COLORS.blue, COLORS.purple];
destroyChart("agentBudget");
charts.agentBudget = new Chart($("agentBudgetChart"), {
type: "line",
data: { datasets: policies.map((policy, i) => ({ label: policy, data: result.rows.filter((r) => r.policy === policy).sort((a, b) => a.budget_gb_per_replica - b.budget_gb_per_replica).map((r) => ({ x: r.budget_gb_per_replica, y: r.p95_turn_ttft_ms })), borderColor: palette[i], backgroundColor: palette[i], pointRadius: 4, tension: .12, fill: false })) },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", beginAtZero: true, title: { display: true, text: "HBM KV budget per replica (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 turn TTFT (ms)" } } } },
});
}
$("agentBudgetBtn").addEventListener("click", async () => {
const button = $("agentBudgetBtn"); button.disabled = true; button.textContent = "Stressing HBM budget...";
try { renderAgentBudget(await callPython("agent_memory_sweep", { config: agentConfigFromUI() })); }
catch (error) { reportError("HBM budget study failed", error); }
finally { button.disabled = false; button.textContent = "Stress HBM budget"; }
});
$("agentBudgetCopy").addEventListener("click", () => { if (lastAgentBudget) copyText(tableText(agentBudgetHeaders, agentBudgetTableRows(lastAgentBudget)), "HBM budget table copied"); });
$("agentBudgetCsv").addEventListener("click", () => { if (lastAgentBudget) downloadCsv(`inferscale_agent-hbm-budget_${stamp()}.csv`, agentBudgetHeaders, agentBudgetTableRows(lastAgentBudget)); });
const agentAffinityHeaders = ["Affinity slack", "p95 turn TTFT", "p95 session E2E", "Route locality", "Cache hit", "Recomputed", "Session SLO", "Pressure evictions"];
function agentAffinityTableRows(result) {
return result.rows.map((r) => [`${fmt(r.affinity_slack_ms, 0)} ms`, `${fmt(r.p95_turn_ttft_ms)} ms`, `${fmt(r.p95_session_e2e_ms)} ms`, pct(r.routing_locality_rate), pct(r.cache_hit_rate), `${fmt(r.recomputed_history_tokens, 0)} tok`, pct(r.session_slo_attainment), r.pressure_evictions]);
}
function renderAgentAffinity(result) {
lastAgentAffinity = result;
$("agentAffinityEmpty").classList.add("hidden");
$("agentAffinityContent").classList.remove("hidden");
["agentAffinityCopy", "agentAffinityCsv"].forEach((id) => { $(id).disabled = false; });
$("agentAffinityRows").innerHTML = result.rows.map((r) => `| ${fmt(r.affinity_slack_ms, 0)} ms | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.routing_locality_rate)} | ${pct(r.cache_hit_rate)} | ${fmt(r.recomputed_history_tokens, 0)} tok | ${pct(r.session_slo_attainment)} | ${r.pressure_evictions} |
`).join("");
destroyChart("agentAffinity");
charts.agentAffinity = new Chart($("agentAffinityChart"), {
type: "line",
data: { datasets: [
{ label: "p95 session E2E", data: result.rows.map((r) => ({ x: r.affinity_slack_ms, y: r.p95_session_e2e_ms })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 4, tension: .12, yAxisID: "yLatency", fill: false },
{ label: "Routing locality", data: result.rows.map((r) => ({ x: r.affinity_slack_ms, y: r.routing_locality_rate * 100 })), borderColor: COLORS.green, backgroundColor: COLORS.green, pointRadius: 4, tension: .12, yAxisID: "yLocality", fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", beginAtZero: true, title: { display: true, text: "Affinity slack (ms)" } }, yLatency: { position: "left", beginAtZero: true, title: { display: true, text: "p95 session E2E (ms)" } }, yLocality: { position: "right", min: 0, max: 100, grid: { drawOnChartArea: false }, title: { display: true, text: "Routing locality (%)" } } } },
});
}
$("agentAffinityBtn").addEventListener("click", async () => {
const button = $("agentAffinityBtn"); button.disabled = true; button.textContent = "Sweeping affinity...";
try { renderAgentAffinity(await callPython("agent_affinity_sweep", { config: agentConfigFromUI() })); }
catch (error) { reportError("Affinity sweep failed", error); }
finally { button.disabled = false; button.textContent = "Run affinity sweep"; }
});
$("agentAffinityCopy").addEventListener("click", () => { if (lastAgentAffinity) copyText(tableText(agentAffinityHeaders, agentAffinityTableRows(lastAgentAffinity)), "Affinity sweep copied"); });
$("agentAffinityCsv").addEventListener("click", () => { if (lastAgentAffinity) downloadCsv(`inferscale_agent-affinity-frontier_${stamp()}.csv`, agentAffinityHeaders, agentAffinityTableRows(lastAgentAffinity)); });
const predictiveHeaders = ["Policy", "p95 turn TTFT", "p95 session E2E", "Session SLO", "Reuse", "Mean HBM", "Mean host", "Prediction MAE", "Oracle agreement", "Post-shift MAE", "Recomputed"];
function predictiveTableRows(result) {
return result.rows.map((r) => [
r.label,
`${fmt(r.p95_turn_ttft_ms)} ms`,
`${fmt(r.p95_session_e2e_ms)} ms`,
pct(r.session_slo_attainment),
pct(r.cache_hit_rate),
`${fmt(r.mean_hbm_gb, 4)} GB`,
`${fmt(r.mean_host_gb, 4)} GB`,
r.prediction_count ? `${fmt(r.prediction_mae_s, 3)} s` : "N/A",
r.prediction_count ? pct(r.oracle_action_agreement) : "N/A",
r.prediction_count ? `${fmt(r.post_shift_mae_s, 3)} s` : "N/A",
`${fmt(r.recomputed_history_tokens, 0)} tok`,
]);
}
function renderPredictiveStudy(result) {
lastPredictiveStudy = result;
$("predictiveEmpty").classList.add("hidden");
$("predictiveContent").classList.remove("hidden");
$("predictiveCompareBlock").classList.remove("hidden");
["predictiveCopy", "predictiveCsv", "predictiveJson"].forEach((id) => { $(id).disabled = false; });
const nonOracle = result.rows.filter((r) => r.retention !== "gap_aware");
const best = [...nonOracle].sort((a, b) => a.p95_turn_ttft_ms - b.p95_turn_ttft_ms)[0];
const tool = result.rows.find((r) => r.label === "Adaptive per-tool EWMA");
$("predictiveBestTtft").textContent = best ? `${fmt(best.p95_turn_ttft_ms)} ms` : "N/A";
$("predictiveAgreement").textContent = tool ? pct(tool.oracle_action_agreement) : "N/A";
$("predictivePostMae").textContent = tool ? `${fmt(tool.post_shift_mae_s, 3)} s` : "N/A";
$("predictiveShiftValue").textContent = `${fmt(result.shift_fraction * 100, 0)}% / ${fmt(result.shift_multiplier, 2)}x`;
$("predictiveRows").innerHTML = result.rows.map((r) => `| ${escapeHtml(r.label)} | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.session_slo_attainment)} | ${pct(r.cache_hit_rate)} | ${fmt(r.mean_hbm_gb, 4)} GB | ${fmt(r.mean_host_gb, 4)} GB | ${r.prediction_count ? `${fmt(r.prediction_mae_s, 3)} s` : "N/A"} | ${r.prediction_count ? pct(r.oracle_action_agreement) : "N/A"} | ${r.prediction_count ? `${fmt(r.post_shift_mae_s, 3)} s` : "N/A"} | ${fmt(r.recomputed_history_tokens, 0)} tok |
`).join("");
const palette = [COLORS.amber, COLORS.steel, COLORS.purple, COLORS.blue, COLORS.green];
destroyChart("predictivePolicy");
charts.predictivePolicy = new Chart($("predictivePolicyChart"), {
type: "scatter",
data: { datasets: result.rows.map((r, i) => ({ label: r.label, data: [{ x: r.mean_hbm_gb, y: r.p95_turn_ttft_ms }], backgroundColor: palette[i], borderColor: palette[i], pointRadius: 7, pointHoverRadius: 9 })) },
options: { ...commonChartOptions(), parsing: false, scales: { x: { type: "linear", beginAtZero: true, title: { display: true, text: "Mean HBM KV (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 turn TTFT (ms)" } } } },
});
const globalCurve = result.learning_curves.global || [];
const toolCurve = result.learning_curves.per_tool || [];
const maxMae = Math.max(0.1, ...globalCurve.map((r) => r.rolling_mae_s), ...toolCurve.map((r) => r.rolling_mae_s));
const shiftX = result.shift_observation || 0;
const learningDatasets = [
{ label: "Global EWMA rolling MAE", data: globalCurve.map((r) => ({ x: r.observation, y: r.rolling_mae_s })), borderColor: COLORS.steel, backgroundColor: COLORS.steel, pointRadius: 0, tension: .16, fill: false },
{ label: "Per-tool EWMA rolling MAE", data: toolCurve.map((r) => ({ x: r.observation, y: r.rolling_mae_s })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 0, tension: .16, fill: false },
];
if (shiftX > 0) learningDatasets.push({ label: "Regime shift", data: [{ x: shiftX, y: 0 }, { x: shiftX, y: maxMae }], borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 0, borderDash: [6, 5], fill: false });
destroyChart("predictiveLearning");
charts.predictiveLearning = new Chart($("predictiveLearningChart"), {
type: "line",
data: { datasets: learningDatasets },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", beginAtZero: true, title: { display: true, text: "Completed tool observations" } }, y: { beginAtZero: true, title: { display: true, text: "Rolling absolute error (s)" } } } },
});
}
function predictivePayload() {
return {
config: agentConfigFromUI({ routing_policy: "bounded_affinity" }),
horizon_s: num("predictiveHorizon"),
shift_fraction: num("predictiveShift"),
shift_multiplier: num("predictiveMultiplier"),
alpha: num("predictiveAlpha"),
};
}
$("predictiveCompareBtn").addEventListener("click", async () => {
const button = $("predictiveCompareBtn"); button.disabled = true; button.textContent = "Running predictive study...";
try { renderPredictiveStudy(await callPython("agent_predictive_tiering", predictivePayload())); }
catch (error) { reportError("Predictive tiering study failed", error); }
finally { button.disabled = false; button.textContent = "Compare predictive policies"; }
});
$("predictiveCopy").addEventListener("click", () => { if (lastPredictiveStudy) copyText(tableText(predictiveHeaders, predictiveTableRows(lastPredictiveStudy)), "Predictive-tiering table copied"); });
$("predictiveCsv").addEventListener("click", () => { if (lastPredictiveStudy) downloadCsv(`inferscale_predictive-tiering_${stamp()}.csv`, predictiveHeaders, predictiveTableRows(lastPredictiveStudy)); });
$("predictiveJson").addEventListener("click", () => { if (lastPredictiveStudy) downloadNamedJson("inferscale_predictive-tiering", lastPredictiveStudy); });
const predictiveAlphaHeaders = ["Alpha", "Pre-shift MAE", "Post-shift MAE", "Oracle agreement", "p95 TTFT", "p95 session E2E", "Session SLO", "Mean HBM", "Mean host"];
function predictiveAlphaTableRows(result) {
return result.rows.map((r) => [fmt(r.alpha, 2), `${fmt(r.pre_shift_mae_s, 3)} s`, `${fmt(r.post_shift_mae_s, 3)} s`, pct(r.oracle_action_agreement), `${fmt(r.p95_turn_ttft_ms)} ms`, `${fmt(r.p95_session_e2e_ms)} ms`, pct(r.session_slo_attainment), `${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.mean_host_gb, 4)} GB`]);
}
function renderPredictiveAlpha(result) {
lastPredictiveAlpha = result;
$("predictiveEmpty").classList.add("hidden");
$("predictiveContent").classList.remove("hidden");
$("predictiveAlphaBlock").classList.remove("hidden");
["predictiveAlphaCopy", "predictiveAlphaCsv", "predictiveAlphaJson"].forEach((id) => { $(id).disabled = false; });
$("predictiveAlphaCaption").textContent = `Adaptation-rate sweep (best post-shift alpha ${fmt(result.best_post_shift_alpha, 2)})`;
$("predictiveAlphaRows").innerHTML = result.rows.map((r) => `| ${fmt(r.alpha, 2)} | ${fmt(r.pre_shift_mae_s, 3)} s | ${fmt(r.post_shift_mae_s, 3)} s | ${pct(r.oracle_action_agreement)} | ${fmt(r.p95_turn_ttft_ms)} ms | ${fmt(r.p95_session_e2e_ms)} ms | ${pct(r.session_slo_attainment)} | ${fmt(r.mean_hbm_gb, 4)} GB | ${fmt(r.mean_host_gb, 4)} GB |
`).join("");
destroyChart("predictiveAlpha");
charts.predictiveAlpha = new Chart($("predictiveAlphaChart"), {
type: "line",
data: { datasets: [
{ label: "Pre-shift MAE", data: result.rows.map((r) => ({ x: r.alpha, y: r.pre_shift_mae_s })), borderColor: COLORS.steel, backgroundColor: COLORS.steel, pointRadius: 4, tension: .12, fill: false },
{ label: "Post-shift MAE", data: result.rows.map((r) => ({ x: r.alpha, y: r.post_shift_mae_s })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 4, tension: .12, fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: 0, max: 1, title: { display: true, text: "EWMA alpha" } }, y: { beginAtZero: true, title: { display: true, text: "Mean absolute error (s)" } } } },
});
}
$("predictiveAlphaBtn").addEventListener("click", async () => {
const button = $("predictiveAlphaBtn"); button.disabled = true; button.textContent = "Sweeping adaptation rate...";
const payload = predictivePayload();
try { renderPredictiveAlpha(await callPython("agent_adaptive_alpha_sweep", payload)); }
catch (error) { reportError("Adaptation-rate sweep failed", error); }
finally { button.disabled = false; button.textContent = "Sweep adaptation rate"; }
});
$("predictiveAlphaCopy").addEventListener("click", () => { if (lastPredictiveAlpha) copyText(tableText(predictiveAlphaHeaders, predictiveAlphaTableRows(lastPredictiveAlpha)), "Adaptation-rate table copied"); });
$("predictiveAlphaCsv").addEventListener("click", () => { if (lastPredictiveAlpha) downloadCsv(`inferscale_adaptation-rate-sweep_${stamp()}.csv`, predictiveAlphaHeaders, predictiveAlphaTableRows(lastPredictiveAlpha)); });
$("predictiveAlphaJson").addEventListener("click", () => { if (lastPredictiveAlpha) downloadNamedJson("inferscale_adaptation-rate-sweep", lastPredictiveAlpha); });
function executionConfigFromUI(overrides = {}) {
return {
model: $("execModel").value,
accelerator: $("execAccelerator").value,
quantization: $("execQuantization").value,
seed: num("execSeed"),
duration_s: num("execDuration"),
workflow_rate_rps: num("execRate"),
max_steps: num("execMaxSteps"),
shift_fraction: num("execShift"),
dynamic_prompt_tokens_mean: num("execPrompt"),
output_tokens_mean: num("execOutput"),
tool_gap_mean_s: num("execGap"),
prefix_cache_budget_fraction: num("execCacheBudget"),
prefetch_policy: $("execPolicy").value,
transition_decay: num("execDecay"),
confidence_threshold: num("execThreshold"),
host_bandwidth_gbps: num("execBandwidth"),
forecast_horizon: num("execHorizon"),
prefetch_top_k: num("execTopK"),
forecast_discount: num("execDiscount"),
forecast_min_score: num("execMinScore"),
utility_threshold_ms: num("execUtility"),
...overrides,
};
}
function rollingBinaryAccuracy(rows, windowSize = 16) {
const width = Math.max(4, windowSize);
return (rows || []).map((row, idx) => {
const chunk = rows.slice(Math.max(0, idx - width + 1), idx + 1);
const correct = chunk.filter((item) => item.prediction_correct).length;
return { x: idx + 1, y: chunk.length ? (correct / chunk.length) * 100 : 0, postShift: Boolean(row.post_shift) };
});
}
function renderExecutionRun(result) {
lastExecutionRun = result;
$("execRunEmpty").classList.add("hidden");
$("execRunContent").classList.remove("hidden");
["execRunCopyJson", "execRunJson"].forEach((id) => { $(id).disabled = false; });
const l = result.latency;
const r = result.resource;
const p = result.prediction;
const s = result.summary;
$("execTtft").textContent = `${fmt(l.step_ttft_ms.p95)} ms`;
$("execE2e").textContent = `${fmt(l.workflow_e2e_ms.p95)} ms`;
$("execAccuracy").textContent = pct(p.top1_accuracy);
$("execPostAccuracy").textContent = pct(p.post_shift_accuracy);
$("execPrefixHit").textContent = pct(r.prefix_hit_rate);
$("execPrecision").textContent = r.prefetch_attempts ? pct(r.prefetch_precision) : "N/A";
$("execCoverage").textContent = pct(r.prefetch_coverage);
$("execWaste").textContent = `${fmt(r.wrong_step_prefetch_gb, 4)} GB`;
$("execEce").textContent = pct(p.calibration?.ece || 0);
$("execForecastRecall").textContent = pct(r.forecast_recall || 0);
$("execUtilization").textContent = r.prefetch_attempts ? pct(r.prefetch_utilization || 0) : "N/A";
$("execUnused").textContent = `${fmt(r.unused_prefetch_gb || 0, 4)} GB`;
$("execRunState").textContent = `${s.workflows_completed}/${s.workflows_generated} workflows`;
$("execRunState").className = `tag ${s.workflow_completion_rate === 1 ? "good" : "bad"}`;
const lookahead = result.provenance.lookahead === "oracle-upper-bound" ? "oracle upper bound" : "online/no-lookahead";
$("execRunSummary").innerHTML = `${escapeHtml(result.config.prefetch_policy.replaceAll("_", " "))} policy. ${p.count} observed transitions; top-1 accuracy ${pct(p.top1_accuracy)} overall and ${pct(p.post_shift_accuracy)} after the workflow shift. Calibration ECE is ${pct(p.calibration?.ece || 0)}. Forecast-set recall is ${pct(r.forecast_recall || 0)}; ${r.prefetch_attempts || 0} prefetch attempts achieved ${pct(r.prefetch_utilization || 0)} eventual utilization and left ${fmt(r.unused_prefetch_gb || 0, 4)} GB unused before eviction/end. Provenance: ${escapeHtml(lookahead)}.`;
const timeline = result.timeline || [];
destroyChart("execTimeline");
charts.execTimeline = new Chart($("execTimelineChart"), {
type: "line",
data: { datasets: [
{ label: "Prefix HBM GB", data: timeline.map((x) => ({ x: x.time_s, y: x.prefix_hbm_gb })), borderColor: COLORS.green, backgroundColor: COLORS.green, pointRadius: 0, tension: .08, yAxisID: "yKv" },
{ label: "Queued steps", data: timeline.map((x) => ({ x: x.time_s, y: x.queued_steps })), borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 0, tension: .08, yAxisID: "yCount" },
{ label: "Transfer busy", data: timeline.map((x) => ({ x: x.time_s, y: x.transfer_busy })), borderColor: COLORS.steel, backgroundColor: COLORS.steel, pointRadius: 0, borderDash: [6, 4], tension: 0, yAxisID: "yCount" },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", title: { display: true, text: "Virtual time (s)" } }, yCount: { position: "left", beginAtZero: true, title: { display: true, text: "Queued steps / transfer busy" } }, yKv: { position: "right", beginAtZero: true, grid: { drawOnChartArea: false }, title: { display: true, text: "Prefix HBM (GB)" } } } },
});
const curve = rollingBinaryAccuracy(p.rows || []);
const shiftPoint = curve.find((point) => point.postShift)?.x || 0;
const datasets = [
{ label: "Rolling top-1 accuracy", data: curve.map((point) => ({ x: point.x, y: point.y })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 0, tension: .15, fill: false },
];
if (shiftPoint > 0) datasets.push({ label: "Workflow shift", data: [{ x: shiftPoint, y: 0 }, { x: shiftPoint, y: 100 }], borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 0, borderDash: [6, 5], fill: false });
destroyChart("execLearning");
charts.execLearning = new Chart($("execLearningChart"), {
type: "line",
data: { datasets },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", beginAtZero: true, title: { display: true, text: "Observed transitions" } }, y: { min: 0, max: 100, title: { display: true, text: "Rolling top-1 accuracy (%)" } } } },
});
const calibrationBins = p.calibration?.bins || [];
destroyChart("execCalibration");
charts.execCalibration = new Chart($("execCalibrationChart"), {
type: "line",
data: { datasets: [
{ label: "Observed accuracy", data: calibrationBins.map((b) => ({ x: b.mean_confidence * 100, y: b.accuracy * 100 })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 5, tension: .08, fill: false },
{ label: "Perfect calibration", data: [{ x: 0, y: 0 }, { x: 100, y: 100 }], borderColor: COLORS.steel, backgroundColor: COLORS.steel, borderDash: [6, 5], pointRadius: 0, fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: 0, max: 100, title: { display: true, text: "Mean predicted confidence (%)" } }, y: { min: 0, max: 100, title: { display: true, text: "Observed top-1 accuracy (%)" } } } },
});
}
$("execRunBtn").addEventListener("click", async () => {
const button = $("execRunBtn");
button.disabled = true; button.textContent = "Running execution model...";
$("execRunState").textContent = "Running..."; $("execRunState").className = "tag neutral";
try { renderExecutionRun(await callPython("execution_learning_run", { config: executionConfigFromUI() })); }
catch (error) { $("execRunState").textContent = "Error"; $("execRunState").className = "tag bad"; reportError("Execution-learning run failed", error); }
finally { button.disabled = false; button.textContent = "Run execution-learning simulation"; }
});
$("execRunCopyJson").addEventListener("click", () => { if (lastExecutionRun) copyText(JSON.stringify(lastExecutionRun, null, 2), "Execution-learning JSON copied"); });
$("execRunJson").addEventListener("click", () => { if (lastExecutionRun) downloadNamedJson("inferscale_execution-learning-run", lastExecutionRun); });
const execCompareHeaders = ["Policy", "p95 TTFT", "p95 workflow E2E", "Post-shift top-1", "Prefix hit", "Prefetch precision", "Coverage", "Mean HBM", "Wrong prefetch", "Saved prefill"];
function execCompareTableRows(result) {
return result.rows.map((r) => [r.label, `${fmt(r.p95_step_ttft_ms)} ms`, `${fmt(r.p95_workflow_e2e_ms)} ms`, pct(r.post_shift_accuracy), pct(r.prefix_hit_rate), r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A", pct(r.prefetch_coverage), `${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.wrong_step_prefetch_gb, 4)} GB`, `${fmt(r.prefill_tokens_saved, 0)} tok`]);
}
function renderExecutionCompare(result) {
lastExecutionCompare = result;
$("execCompareEmpty").classList.add("hidden"); $("execCompareContent").classList.remove("hidden");
["execCompareCopy", "execCompareCsv", "execCompareJson"].forEach((id) => { $(id).disabled = false; });
$("execCompareRows").innerHTML = result.rows.map((r) => `| ${escapeHtml(r.label)} | ${fmt(r.p95_step_ttft_ms)} ms | ${fmt(r.p95_workflow_e2e_ms)} ms | ${pct(r.post_shift_accuracy)} | ${pct(r.prefix_hit_rate)} | ${r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A"} | ${pct(r.prefetch_coverage)} | ${fmt(r.mean_hbm_gb, 4)} GB | ${fmt(r.wrong_step_prefetch_gb, 4)} GB | ${fmt(r.prefill_tokens_saved, 0)} tok |
`).join("");
const palette = [COLORS.gray, COLORS.amber, COLORS.blue, COLORS.green];
destroyChart("execCompare");
charts.execCompare = new Chart($("execCompareChart"), {
type: "scatter",
data: { datasets: result.rows.map((r, i) => ({ label: r.label, data: [{ x: r.post_shift_accuracy * 100, y: r.p95_step_ttft_ms }], backgroundColor: palette[i], borderColor: palette[i], pointRadius: 7, pointHoverRadius: 9 })) },
options: { ...commonChartOptions(), plugins: { legend: pointLegend() }, scales: { x: { min: 0, max: 100, title: { display: true, text: "Post-shift next-role top-1 accuracy (%)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 step TTFT (ms)" } } } },
});
}
$("execCompareBtn").addEventListener("click", async () => {
const button = $("execCompareBtn"); button.disabled = true; button.textContent = "Comparing policies...";
try { renderExecutionCompare(await callPython("execution_prefetch_study", { config: executionConfigFromUI() })); }
catch (error) { reportError("Execution prefetch study failed", error); }
finally { button.disabled = false; button.textContent = "Compare 4 policies"; }
});
$("execCompareCopy").addEventListener("click", () => { if (lastExecutionCompare) copyText(tableText(execCompareHeaders, execCompareTableRows(lastExecutionCompare)), "Execution policy table copied"); });
$("execCompareCsv").addEventListener("click", () => { if (lastExecutionCompare) downloadCsv(`inferscale_execution-prefetch-study_${stamp()}.csv`, execCompareHeaders, execCompareTableRows(lastExecutionCompare)); });
$("execCompareJson").addEventListener("click", () => { if (lastExecutionCompare) downloadNamedJson("inferscale_execution-prefetch-study", lastExecutionCompare); });
const execThresholdHeaders = ["Threshold", "p95 TTFT", "Post-shift top-1", "Precision", "Coverage", "Prefix hit", "Wrong prefetch", "Mean HBM"];
function execThresholdTableRows(result) {
return result.rows.map((r) => [fmt(r.threshold, 2), `${fmt(r.p95_step_ttft_ms)} ms`, pct(r.post_shift_accuracy), r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A", pct(r.prefetch_coverage), pct(r.prefix_hit_rate), `${fmt(r.wrong_step_prefetch_gb, 4)} GB`, `${fmt(r.mean_hbm_gb, 4)} GB`]);
}
function renderExecutionThreshold(result) {
lastExecutionThreshold = result;
$("execThresholdEmpty").classList.add("hidden"); $("execThresholdContent").classList.remove("hidden");
["execThresholdCopy", "execThresholdCsv", "execThresholdJson"].forEach((id) => { $(id).disabled = false; });
$("execCoverageCorr").textContent = fmt(result.association.coverage_vs_ttft_r, 3);
$("execPrecisionCorr").textContent = fmt(result.association.precision_vs_wrong_prefetch_r, 3);
const bestTtft = result.rows.reduce((a, b) => a.p95_step_ttft_ms <= b.p95_step_ttft_ms ? a : b);
const bestWaste = result.rows.reduce((a, b) => a.wrong_step_prefetch_gb <= b.wrong_step_prefetch_gb ? a : b);
$("execThresholdBestTtft").textContent = `${fmt(bestTtft.threshold, 2)} / ${fmt(bestTtft.p95_step_ttft_ms)} ms`;
$("execThresholdBestWaste").textContent = `${fmt(bestWaste.threshold, 2)} / ${fmt(bestWaste.wrong_step_prefetch_gb, 4)} GB`;
$("execThresholdRows").innerHTML = result.rows.map((r) => `| ${fmt(r.threshold, 2)} | ${fmt(r.p95_step_ttft_ms)} ms | ${pct(r.post_shift_accuracy)} | ${r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A"} | ${pct(r.prefetch_coverage)} | ${pct(r.prefix_hit_rate)} | ${fmt(r.wrong_step_prefetch_gb, 4)} GB | ${fmt(r.mean_hbm_gb, 4)} GB |
`).join("");
destroyChart("execThreshold");
charts.execThreshold = new Chart($("execThresholdChart"), {
type: "line",
data: { datasets: [
{ label: "p95 step TTFT", data: result.rows.map((r) => ({ x: r.threshold, y: r.p95_step_ttft_ms })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 4, tension: .1, yAxisID: "yLatency", fill: false },
{ label: "Wrong-step prefetch GB", data: result.rows.map((r) => ({ x: r.threshold, y: r.wrong_step_prefetch_gb })), borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 4, tension: .1, yAxisID: "yWaste", fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: 0, max: 1, title: { display: true, text: "Prefetch confidence threshold" } }, yLatency: { position: "left", beginAtZero: true, title: { display: true, text: "p95 TTFT (ms)" } }, yWaste: { position: "right", beginAtZero: true, grid: { drawOnChartArea: false }, title: { display: true, text: "Wrong-step prefetch (GB)" } } } },
});
}
$("execThresholdBtn").addEventListener("click", async () => {
const button = $("execThresholdBtn"); button.disabled = true; button.textContent = "Sweeping threshold...";
try { renderExecutionThreshold(await callPython("execution_threshold_sweep", { config: executionConfigFromUI() })); }
catch (error) { reportError("Execution threshold sweep failed", error); }
finally { button.disabled = false; button.textContent = "Sweep confidence threshold"; }
});
$("execThresholdCopy").addEventListener("click", () => { if (lastExecutionThreshold) copyText(tableText(execThresholdHeaders, execThresholdTableRows(lastExecutionThreshold)), "Execution threshold table copied"); });
$("execThresholdCsv").addEventListener("click", () => { if (lastExecutionThreshold) downloadCsv(`inferscale_execution-threshold-sweep_${stamp()}.csv`, execThresholdHeaders, execThresholdTableRows(lastExecutionThreshold)); });
$("execThresholdJson").addEventListener("click", () => { if (lastExecutionThreshold) downloadNamedJson("inferscale_execution-threshold-sweep", lastExecutionThreshold); });
const execDecayHeaders = ["Decay", "Pre-shift top-1", "Post-shift top-1", "p95 TTFT", "Prefix hit", "Precision", "Coverage", "Wrong prefetch"];
function execDecayTableRows(result) {
return result.rows.map((r) => [fmt(r.decay, 2), pct(r.pre_shift_accuracy), pct(r.post_shift_accuracy), `${fmt(r.p95_step_ttft_ms)} ms`, pct(r.prefix_hit_rate), r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A", pct(r.prefetch_coverage), `${fmt(r.wrong_step_prefetch_gb, 4)} GB`]);
}
function renderExecutionDecay(result) {
lastExecutionDecay = result;
$("execDecayEmpty").classList.add("hidden"); $("execDecayContent").classList.remove("hidden");
["execDecayCopy", "execDecayCsv", "execDecayJson"].forEach((id) => { $(id).disabled = false; });
$("execBestAccuracyDecay").textContent = fmt(result.best_post_shift_accuracy_decay, 2);
$("execBestTtftDecay").textContent = fmt(result.best_ttft_decay, 2);
$("execAccuracyTtftCorr").textContent = fmt(result.association.post_shift_accuracy_vs_ttft_r, 3);
$("execAccuracyHitCorr").textContent = fmt(result.association.post_shift_accuracy_vs_prefix_hit_r, 3);
$("execDecayRows").innerHTML = result.rows.map((r) => `| ${fmt(r.decay, 2)} | ${pct(r.pre_shift_accuracy)} | ${pct(r.post_shift_accuracy)} | ${fmt(r.p95_step_ttft_ms)} ms | ${pct(r.prefix_hit_rate)} | ${r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A"} | ${pct(r.prefetch_coverage)} | ${fmt(r.wrong_step_prefetch_gb, 4)} GB |
`).join("");
destroyChart("execDecay");
charts.execDecay = new Chart($("execDecayChart"), {
type: "line",
data: { datasets: [
{ label: "Post-shift top-1 accuracy", data: result.rows.map((r) => ({ x: r.decay, y: r.post_shift_accuracy * 100 })), borderColor: COLORS.green, backgroundColor: COLORS.green, pointRadius: 4, tension: .1, yAxisID: "yAccuracy", fill: false },
{ label: "p95 step TTFT", data: result.rows.map((r) => ({ x: r.decay, y: r.p95_step_ttft_ms })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 4, tension: .1, yAxisID: "yLatency", fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: .2, max: 1, title: { display: true, text: "Transition retention / decay" } }, yAccuracy: { position: "left", min: 0, max: 100, title: { display: true, text: "Post-shift top-1 accuracy (%)" } }, yLatency: { position: "right", beginAtZero: true, grid: { drawOnChartArea: false }, title: { display: true, text: "p95 TTFT (ms)" } } } },
});
}
$("execDecayBtn").addEventListener("click", async () => {
const button = $("execDecayBtn"); button.disabled = true; button.textContent = "Sweeping decay...";
try { renderExecutionDecay(await callPython("execution_decay_sweep", { config: executionConfigFromUI() })); }
catch (error) { reportError("Execution decay sweep failed", error); }
finally { button.disabled = false; button.textContent = "Sweep transition decay"; }
});
$("execDecayCopy").addEventListener("click", () => { if (lastExecutionDecay) copyText(tableText(execDecayHeaders, execDecayTableRows(lastExecutionDecay)), "Execution decay table copied"); });
$("execDecayCsv").addEventListener("click", () => { if (lastExecutionDecay) downloadCsv(`inferscale_execution-decay-sweep_${stamp()}.csv`, execDecayHeaders, execDecayTableRows(lastExecutionDecay)); });
$("execDecayJson").addEventListener("click", () => { if (lastExecutionDecay) downloadNamedJson("inferscale_execution-decay-sweep", lastExecutionDecay); });
const execPlanningHeaders = ["Policy", "p95 TTFT", "Future-role recall@K", "Prefix hit", "Utilization", "Next-step precision", "Mean HBM", "Unused prefetch", "Saved prefill", "ECE"];
function execPlanningTableRows(result) {
return result.rows.map((r) => [
r.label, `${fmt(r.p95_step_ttft_ms)} ms`, pct(r.forecast_recall), pct(r.prefix_hit_rate),
r.prefetch_coverage ? pct(r.prefetch_utilization) : "N/A", r.prefetch_coverage ? pct(r.prefetch_precision) : "N/A",
`${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.unused_prefetch_gb, 4)} GB`, `${fmt(r.prefill_tokens_saved, 0)} tok`, pct(r.ece),
]);
}
function renderExecutionPlanning(result) {
lastExecutionPlanning = result;
$("execPlanningEmpty").classList.add("hidden"); $("execPlanningContent").classList.remove("hidden");
["execPlanningCopy", "execPlanningCsv", "execPlanningJson"].forEach((id) => { $(id).disabled = false; });
$("execPlanningBestTtft").textContent = result.best_ttft_policy || "N/A";
$("execPlanningBestEfficiency").textContent = result.best_prefill_per_hbm_policy || "N/A";
$("execPlanningHorizon").textContent = `${num("execHorizon")} steps`;
$("execPlanningTopK").textContent = `${num("execTopK")} roles`;
$("execPlanningRows").innerHTML = execPlanningTableRows(result).map((row) => `${row.map((cell) => `| ${escapeHtml(String(cell))} | `).join("")}
`).join("");
const palette = [COLORS.steel, COLORS.blue, COLORS.green, COLORS.amber];
destroyChart("execPlanning");
charts.execPlanning = new Chart($("execPlanningChart"), {
type: "scatter",
data: { datasets: result.rows.map((r, i) => ({ label: r.label, data: [{ x: r.mean_hbm_gb, y: r.p95_step_ttft_ms }], backgroundColor: palette[i], borderColor: palette[i], pointRadius: 7, pointHoverRadius: 9 })) },
options: { ...commonChartOptions(), plugins: { legend: pointLegend() }, scales: { x: { beginAtZero: true, title: { display: true, text: "Mean prefix HBM (GB)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 step TTFT (ms)" } } } },
});
}
$("execPlanningBtn").addEventListener("click", async () => {
const button = $("execPlanningBtn"); button.disabled = true; button.textContent = "Comparing planners...";
try { renderExecutionPlanning(await callPython("execution_planning_study", { config: executionConfigFromUI() })); }
catch (error) { reportError("Execution planning study failed", error); }
finally { button.disabled = false; button.textContent = "Compare planning policies"; }
});
$("execPlanningCopy").addEventListener("click", () => { if (lastExecutionPlanning) copyText(tableText(execPlanningHeaders, execPlanningTableRows(lastExecutionPlanning)), "Planning table copied"); });
$("execPlanningCsv").addEventListener("click", () => { if (lastExecutionPlanning) downloadCsv(`inferscale_execution-planning-study_${stamp()}.csv`, execPlanningHeaders, execPlanningTableRows(lastExecutionPlanning)); });
$("execPlanningJson").addEventListener("click", () => { if (lastExecutionPlanning) downloadNamedJson("inferscale_execution-planning-study", lastExecutionPlanning); });
const execHorizonHeaders = ["Horizon", "p95 TTFT", "Future-role recall@K", "Prefix hit", "Utilization", "Unused prefetch", "Mean HBM", "Saved prefill"];
function execHorizonTableRows(result) {
return result.rows.map((r) => [r.horizon, `${fmt(r.p95_step_ttft_ms)} ms`, pct(r.forecast_recall), pct(r.prefix_hit_rate), r.prefetch_coverage ? pct(r.prefetch_utilization) : "N/A", `${fmt(r.unused_prefetch_gb, 4)} GB`, `${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.prefill_tokens_saved, 0)} tok`]);
}
function renderExecutionHorizon(result) {
lastExecutionHorizon = result;
$("execHorizonEmpty").classList.add("hidden"); $("execHorizonContent").classList.remove("hidden");
["execHorizonCopy", "execHorizonCsv", "execHorizonJson"].forEach((id) => { $(id).disabled = false; });
$("execHorizonBestTtft").textContent = `${result.best_ttft_horizon ?? "N/A"} steps`;
$("execHorizonBestUtil").textContent = `${result.best_utilization_horizon ?? "N/A"} steps`;
$("execHorizonTopK").textContent = `${num("execTopK")} roles`;
$("execHorizonBudget").textContent = `${fmt(num("execCacheBudget"), 2)}x`;
$("execHorizonRows").innerHTML = execHorizonTableRows(result).map((row) => `${row.map((cell) => `| ${escapeHtml(String(cell))} | `).join("")}
`).join("");
destroyChart("execHorizon");
charts.execHorizon = new Chart($("execHorizonChart"), {
type: "line",
data: { datasets: [
{ label: "p95 step TTFT", data: result.rows.map((r) => ({ x: r.horizon, y: r.p95_step_ttft_ms })), borderColor: COLORS.blue, backgroundColor: COLORS.blue, pointRadius: 4, yAxisID: "yLatency", fill: false },
{ label: "Prefetch utilization", data: result.rows.map((r) => ({ x: r.horizon, y: r.prefetch_utilization * 100 })), borderColor: COLORS.green, backgroundColor: COLORS.green, pointRadius: 4, yAxisID: "yPct", fill: false },
{ label: "Future-role recall@K", data: result.rows.map((r) => ({ x: r.horizon, y: r.forecast_recall * 100 })), borderColor: COLORS.amber, backgroundColor: COLORS.amber, pointRadius: 4, borderDash: [6, 4], yAxisID: "yPct", fill: false },
] },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: 1, max: 5, ticks: { stepSize: 1 }, title: { display: true, text: "Forecast horizon (steps)" } }, yLatency: { position: "left", beginAtZero: true, title: { display: true, text: "p95 TTFT (ms)" } }, yPct: { position: "right", min: 0, max: 100, grid: { drawOnChartArea: false }, title: { display: true, text: "Recall / utilization (%)" } } } },
});
}
$("execHorizonBtn").addEventListener("click", async () => {
const button = $("execHorizonBtn"); button.disabled = true; button.textContent = "Sweeping horizons...";
try { renderExecutionHorizon(await callPython("execution_horizon_sweep", { config: executionConfigFromUI() })); }
catch (error) { reportError("Forecast horizon sweep failed", error); }
finally { button.disabled = false; button.textContent = "Sweep forecast horizon"; }
});
$("execHorizonCopy").addEventListener("click", () => { if (lastExecutionHorizon) copyText(tableText(execHorizonHeaders, execHorizonTableRows(lastExecutionHorizon)), "Horizon table copied"); });
$("execHorizonCsv").addEventListener("click", () => { if (lastExecutionHorizon) downloadCsv(`inferscale_execution-horizon-sweep_${stamp()}.csv`, execHorizonHeaders, execHorizonTableRows(lastExecutionHorizon)); });
$("execHorizonJson").addEventListener("click", () => { if (lastExecutionHorizon) downloadNamedJson("inferscale_execution-horizon-sweep", lastExecutionHorizon); });
const execBudgetHeaders = ["Budget", "Policy", "p95 TTFT", "Future-role recall@K", "Prefix hit", "Utilization", "Mean HBM", "Unused prefetch", "Pressure evictions"];
function execBudgetTableRows(result) {
return result.rows.map((r) => [`${fmt(r.budget, 2)}x`, r.policy_label, `${fmt(r.p95_step_ttft_ms)} ms`, pct(r.forecast_recall), pct(r.prefix_hit_rate), r.prefetch_coverage ? pct(r.prefetch_utilization) : "N/A", `${fmt(r.mean_hbm_gb, 4)} GB`, `${fmt(r.unused_prefetch_gb, 4)} GB`, fmt(r.pressure_evictions, 0)]);
}
function renderExecutionBudget(result) {
lastExecutionBudget = result;
$("execBudgetEmpty").classList.add("hidden"); $("execBudgetContent").classList.remove("hidden");
["execBudgetCopy", "execBudgetCsv", "execBudgetJson"].forEach((id) => { $(id).disabled = false; });
$("execBudgetRows").innerHTML = execBudgetTableRows(result).map((row) => `${row.map((cell) => `| ${escapeHtml(String(cell))} | `).join("")}
`).join("");
const policyColors = { "Top-1": COLORS.steel, "Multi-step": COLORS.blue, "Utility-aware": COLORS.green };
const policies = ["Top-1", "Multi-step", "Utility-aware"];
destroyChart("execBudget");
charts.execBudget = new Chart($("execBudgetChart"), {
type: "line",
data: { datasets: policies.map((policy) => ({ label: policy, data: result.rows.filter((r) => r.policy_label === policy).map((r) => ({ x: r.budget, y: r.p95_step_ttft_ms })), borderColor: policyColors[policy], backgroundColor: policyColors[policy], pointRadius: 4, tension: .08, fill: false })) },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: lineLegend() }, scales: { x: { type: "linear", min: .25, max: 1.05, title: { display: true, text: "Prefix-cache budget (working-set x)" } }, y: { beginAtZero: true, title: { display: true, text: "p95 step TTFT (ms)" } } } },
});
}
$("execBudgetBtn").addEventListener("click", async () => {
const button = $("execBudgetBtn"); button.disabled = true; button.textContent = "Sweeping cache budget...";
try { renderExecutionBudget(await callPython("execution_budget_sweep", { config: executionConfigFromUI() })); }
catch (error) { reportError("Cache budget study failed", error); }
finally { button.disabled = false; button.textContent = "Sweep cache budget"; }
});
$("execBudgetCopy").addEventListener("click", () => { if (lastExecutionBudget) copyText(tableText(execBudgetHeaders, execBudgetTableRows(lastExecutionBudget)), "Cache budget table copied"); });
$("execBudgetCsv").addEventListener("click", () => { if (lastExecutionBudget) downloadCsv(`inferscale_execution-cache-budget-sweep_${stamp()}.csv`, execBudgetHeaders, execBudgetTableRows(lastExecutionBudget)); });
$("execBudgetJson").addEventListener("click", () => { if (lastExecutionBudget) downloadNamedJson("inferscale_execution-cache-budget-sweep", lastExecutionBudget); });
const consHeaders = ["Rank", "Policy", "Median TTFT", "95% CI of mean", "TTFT wins", "Pareto stable", "Oracle regret", "Worst seed", "Unused prefetch", "Mean HBM"];
function consTableRows(result) {
return [...result.policies].sort((a, b) => a.robust_rank - b.robust_rank).map((r) => [
r.robust_rank, r.label, `${fmt(r.median_ttft_ms)} ms`, `${fmt(r.ttft_ci95_low_ms)}-${fmt(r.ttft_ci95_high_ms)} ms`,
pct(r.ttft_win_rate), pct(r.pareto_stability), `${fmt(r.median_oracle_regret_ms)} ms`, `${fmt(r.worst_seed_ttft_ms)} ms`,
`${fmt(r.mean_unused_prefetch_gb, 4)} GB`, `${fmt(r.mean_hbm_gb, 4)} GB`,
]);
}
function renderConsolidation(result) {
lastConsolidation = result;
$("consEmpty").classList.add("hidden"); $("consContent").classList.remove("hidden");
["consCopy", "consCsv", "consJson", "consReportBtn"].forEach((id) => { $(id).disabled = false; });
$("consState").textContent = `${result.repetitions} matched seeds`;
$("consState").className = "tag good";
$("consWinner").textContent = result.robust_winner || "N/A";
$("consNominal").textContent = result.nominal_winner_first_seed || "N/A";
$("consSeedCount").textContent = fmt(result.repetitions, 0);
$("consOracle").textContent = `${fmt(result.oracle?.median_ttft_ms)} ms`;
const rows = consTableRows(result);
$("consRows").innerHTML = rows.map((row) => `${row.map((cell, idx) => `| ${escapeHtml(String(cell))} | `).join("")}
`).join("");
$("consNote").textContent = result.note || "";
destroyChart("consolidation");
const ordered = [...result.policies].sort((a, b) => a.robust_rank - b.robust_rank);
charts.consolidation = new Chart($("consChart"), {
type: "scatter",
data: { datasets: ordered.map((r, idx) => ({
label: r.label,
data: [{ x: r.median_oracle_regret_ms, y: r.pareto_stability * 100 }],
backgroundColor: [COLORS.blue, COLORS.green, COLORS.amber, COLORS.steel][idx % 4],
borderColor: [COLORS.blue, COLORS.green, COLORS.amber, COLORS.steel][idx % 4],
pointRadius: 7,
})) },
options: { ...commonChartOptions(), parsing: false, plugins: { legend: pointLegend() }, scales: {
x: { beginAtZero: true, title: { display: true, text: "Median regret to bounded offline oracle (ms)" } },
y: { min: 0, max: 100, title: { display: true, text: "Pareto stability across matched seeds (%)" } },
} },
});
}
$("consRunBtn").addEventListener("click", async () => {
const button = $("consRunBtn"); button.disabled = true; button.textContent = "Running matched seeds...";
$("consState").textContent = "Running"; $("consState").className = "tag";
try {
renderConsolidation(await callPython("consolidation_study", {
config: executionConfigFromUI(), repetitions: num("consSeeds"), bootstrap_samples: num("consBootstrap"),
}));
} catch (error) { reportError("Robust policy study failed", error); }
finally { button.disabled = false; button.textContent = "Run robust policy study"; }
});
$("consCopy").addEventListener("click", () => { if (lastConsolidation) copyText(tableText(consHeaders, consTableRows(lastConsolidation)), "Robust policy table copied"); });
$("consCsv").addEventListener("click", () => { if (lastConsolidation) downloadCsv(`inferscale_robust-policy-study_${stamp()}.csv`, consHeaders, consTableRows(lastConsolidation)); });
$("consJson").addEventListener("click", () => { if (lastConsolidation) downloadNamedJson("inferscale_robust-policy-study", lastConsolidation); });
$("measurementFile").addEventListener("change", async (event) => {
const file = event.target.files?.[0];
if (!file) { measurementFileContent = ""; $("measurementCalibrateBtn").disabled = true; $("measurementStatus").textContent = "No measurement file loaded"; return; }
try {
measurementFileContent = await file.text();
$("measurementStatus").textContent = `${file.name} loaded (${measurementFileContent.length.toLocaleString()} characters)`;
$("measurementCalibrateBtn").disabled = !runtimePill.classList.contains("ready");
} catch (error) {
measurementFileContent = ""; $("measurementCalibrateBtn").disabled = true;
$("measurementStatus").textContent = "File read failed"; reportError("Measurement file failed", error);
}
});
const measurementHeaders = ["Case", "Metric", "Measured", "Baseline pred.", "Calibrated pred.", "Baseline APE", "Calibrated APE"];
function measurementTableRows(calibration) {
const baselineRows = calibration.baseline?.rows || [];
const calibratedRows = calibration.calibrated?.rows || [];
const byKey = new Map(calibratedRows.map((row) => [`${row.case}|${row.metric}`, row]));
return baselineRows.map((base) => {
const calibrated = byKey.get(`${base.case}|${base.metric}`) || {};
const unit = base.metric.includes("_ms") ? " ms" : base.metric.includes("rps") ? " req/s" : "";
return [base.case, base.metric, `${fmt(base.measured, 2)}${unit}`, `${fmt(base.predicted, 2)}${unit}`, `${fmt(calibrated.predicted, 2)}${unit}`, `${fmt(base.absolute_percentage_error, 2)}%`, `${fmt(calibrated.absolute_percentage_error, 2)}%`];
});
}
function renderCalibration(imported, calibration) {
lastMeasurementImport = imported; lastCalibration = calibration;
$("measurementEmpty").classList.add("hidden"); $("measurementContent").classList.remove("hidden");
["measurementCopy", "measurementCsv", "measurementJson"].forEach((id) => { $(id).disabled = false; });
if (lastConsolidation) $("consReportBtn").disabled = false;
$("measurementState").textContent = calibration.validation_mode === "held-out" ? "Held-out" : "Resubstitution";
$("measurementState").className = `tag ${calibration.validation_mode === "held-out" ? "good" : ""}`;
$("measurementCases").textContent = fmt(imported.case_count, 0);
$("measurementPrefill").textContent = `${fmt(calibration.fitted_scales.prefill_time_scale, 3)}x`;
$("measurementDecode").textContent = `${fmt(calibration.fitted_scales.decode_time_scale, 3)}x`;
$("measurementMape").textContent = `${fmt(calibration.calibrated.mape_pct, 2)}%`;
$("measurementCaption").textContent = `${calibration.train_count} train / ${calibration.holdout_count} validation cases`;
const rows = measurementTableRows(calibration);
$("measurementRows").innerHTML = rows.map((row) => `${row.map((cell) => `| ${escapeHtml(String(cell))} | `).join("")}
`).join("");
$("measurementNote").textContent = `${calibration.note} Baseline MAPE ${fmt(calibration.baseline.mape_pct, 2)}%; calibrated MAPE ${fmt(calibration.calibrated.mape_pct, 2)}%.`;
}
$("measurementCalibrateBtn").addEventListener("click", async () => {
if (!measurementFileContent) return;
const button = $("measurementCalibrateBtn"); button.disabled = true; button.textContent = "Importing measurements...";
try {
const imported = await callPython("measurement_import", {
content: measurementFileContent, source: $("measurementSource").value, base_config: configFromUI(),
});
button.textContent = "Calibrating + validating...";
const calibrated = await callPython("measurement_calibrate", {
cases: imported.cases, holdout_fraction: num("measurementHoldout"), seed: num("seed"),
});
renderCalibration(imported, calibrated);
} catch (error) { reportError("Measurement calibration failed", error); }
finally { button.disabled = false; button.textContent = "Import and calibrate"; }
});
$("measurementCopy").addEventListener("click", () => { if (lastCalibration) copyText(tableText(measurementHeaders, measurementTableRows(lastCalibration)), "Validation table copied"); });
$("measurementCsv").addEventListener("click", () => { if (lastCalibration) downloadCsv(`inferscale_heldout-validation_${stamp()}.csv`, measurementHeaders, measurementTableRows(lastCalibration)); });
$("measurementJson").addEventListener("click", () => { if (lastCalibration) downloadNamedJson("inferscale_measurement-calibration", { imported: lastMeasurementImport, calibration: lastCalibration }); });
$("consReportBtn").addEventListener("click", async () => {
if (!lastConsolidation) return;
const button = $("consReportBtn"); button.disabled = true; button.textContent = "Generating report...";
try {
const result = await callPython("research_report", { robust: lastConsolidation, calibration: lastCalibration });
downloadTextFile(`inferscale_research-consolidation_${stamp()}.md`, result.markdown, "text/markdown;charset=utf-8");
} catch (error) { reportError("Report generation failed", error); }
finally { button.disabled = false; button.textContent = "Download Markdown report"; }
});
function syncAgentControls() {
const retention = $("agentRetention").value;
const routing = $("agentRouting").value;
const adaptive = retention === "adaptive";
const ttl = retention === "ttl" || adaptive;
const hostTier = retention === "offload" || retention === "gap_aware" || adaptive;
const gapAware = retention === "gap_aware" || adaptive;
const bounded = routing === "bounded_affinity";
$("agentTtl").disabled = !ttl;
$("agentTtlLabel").classList.toggle("field-disabled", !ttl);
$("agentAffinitySlack").disabled = !bounded;
$("agentAffinitySlackLabel").classList.toggle("field-disabled", !bounded);
$("agentGapThreshold").disabled = !gapAware;
$("agentGapThresholdLabel").classList.toggle("field-disabled", !gapAware);
["agentHostMemory", "agentHostBandwidth", "agentHostBase"].forEach((id) => { $(id).disabled = !hostTier; });
["agentHostMemoryLabel", "agentHostBandwidthLabel", "agentHostBaseLabel"].forEach((id) => { $(id).classList.toggle("field-disabled", !hostTier); });
["agentPredictorScope", "agentPredictorAlpha", "agentPredictorMin"].forEach((id) => { $(id).disabled = !adaptive; });
["agentPredictorScopeLabel", "agentPredictorAlphaLabel", "agentPredictorMinLabel"].forEach((id) => { $(id).classList.toggle("field-disabled", !adaptive); });
}
$("agentRetention").addEventListener("change", syncAgentControls);
$("agentRouting").addEventListener("change", syncAgentControls);
syncAgentControls();
function normalizeTraceRows(rows) {
if (!Array.isArray(rows)) throw new Error("Trace JSON must be an array or contain a requests array");
if (rows.length > 10000) throw new Error("Trace replay is limited to 10,000 requests in the browser");
return rows.map((row, index) => {
const arrival = Number(row.arrival_time);
const prompt = Number(row.prompt_tokens);
const output = Number(row.output_tokens);
if (!Number.isFinite(arrival) || arrival < 0 || !Number.isFinite(prompt) || prompt < 1 || !Number.isFinite(output) || output < 1) {
throw new Error(`Invalid trace row ${index + 1}`);
}
return { arrival_time: arrival, prompt_tokens: Math.round(prompt), output_tokens: Math.round(output) };
});
}
function parseTraceCsv(text) {
const lines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
if (lines.length < 2) throw new Error("CSV trace needs a header and at least one request");
const headers = lines[0].split(",").map((x) => x.trim());
const required = ["arrival_time", "prompt_tokens", "output_tokens"];
const idx = Object.fromEntries(required.map((name) => [name, headers.indexOf(name)]));
if (required.some((name) => idx[name] < 0)) throw new Error("CSV header must contain arrival_time,prompt_tokens,output_tokens");
return normalizeTraceRows(lines.slice(1).map((line) => {
const cells = line.split(",").map((x) => x.trim());
return { arrival_time: cells[idx.arrival_time], prompt_tokens: cells[idx.prompt_tokens], output_tokens: cells[idx.output_tokens] };
}));
}
async function loadTraceFile(file) {
const text = await file.text();
let rows;
if (file.name.toLowerCase().endsWith(".json")) {
const parsed = JSON.parse(text);
rows = normalizeTraceRows(Array.isArray(parsed) ? parsed : parsed.requests);
} else {
rows = parseTraceCsv(text);
}
rows.sort((a, b) => a.arrival_time - b.arrival_time);
traceRequests = rows;
const span = rows.length ? rows[rows.length - 1].arrival_time - rows[0].arrival_time : 0;
$("traceStatus").textContent = `${rows.length.toLocaleString()} requests loaded (${fmt(span, 2)} s span)`;
showToast("Trace loaded");
}
$("traceFile").addEventListener("change", async (event) => {
const file = event.target.files?.[0];
if (!file) return;
try { await loadTraceFile(file); }
catch (error) { traceRequests = []; $("traceStatus").textContent = "Trace rejected"; reportError("Trace load failed", error); }
});
$("traceClearBtn").addEventListener("click", () => {
traceRequests = [];
$("traceFile").value = "";
$("traceStatus").textContent = "No trace loaded";
});
function syncConditionalControls() {
const pd = $("topology").value === "disaggregated_pd";
$("pdControls").classList.toggle("hidden", !pd);
$("colocatedAcceleratorLabel").classList.toggle("hidden", pd);
if (pd && $("scheduler").value === "static_fcfs") {
$("scheduler").value = "continuous_fcfs";
showToast("Static FCFS switched to Continuous FCFS for P/D topology");
}
$("prefixControls").classList.toggle("hidden", !boolSelect("prefixCache"));
const trace = $("arrival").value === "trace";
$("burstControls").classList.toggle("hidden", $("arrival").value !== "bursty");
$("traceControls").classList.toggle("hidden", !trace);
["rate", "duration", "promptMean", "promptCv", "outputMean", "outputCv"].forEach((id) => { $(id).disabled = trace; });
$("capacityBtn").disabled = trace || !runtimePill.classList.contains("ready");
$("capacityBtn").title = trace ? "Capacity search is undefined for a fixed arrival trace" : "";
}
$("topology").addEventListener("change", syncConditionalControls);
$("prefixCache").addEventListener("change", syncConditionalControls);
$("arrival").addEventListener("change", syncConditionalControls);
syncConditionalControls();
const tabButtons = [...document.querySelectorAll(".tab")];
function activateTab(tab) {
for (const item of tabButtons) {
const active = item === tab;
item.classList.toggle("active", active);
item.setAttribute("aria-selected", active ? "true" : "false");
item.tabIndex = active ? 0 : -1;
}
document.querySelectorAll(".tab-panel").forEach((panel) => {
panel.classList.remove("active");
panel.setAttribute("aria-hidden", "true");
});
const targetPanel = $(tab.dataset.tab);
targetPanel.classList.add("active");
targetPanel.setAttribute("aria-hidden", "false");
setTimeout(() => Object.values(charts).forEach((chart) => chart.resize()), 20);
}
for (const tab of tabButtons) {
tab.addEventListener("click", () => activateTab(tab));
tab.addEventListener("keydown", (event) => {
if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return;
event.preventDefault();
const current = tabButtons.indexOf(tab);
let next = current;
if (event.key === "ArrowLeft") next = (current - 1 + tabButtons.length) % tabButtons.length;
if (event.key === "ArrowRight") next = (current + 1) % tabButtons.length;
if (event.key === "Home") next = 0;
if (event.key === "End") next = tabButtons.length - 1;
tabButtons[next].focus();
activateTab(tabButtons[next]);
});
}
function closeExpandedChart() {
const card = document.querySelector(".chart-card.chart-expanded");
if (!card) return;
card.classList.remove("chart-expanded");
const button = card.querySelector(".chart-expand");
if (button) button.textContent = "Expand";
document.body.classList.remove("chart-open");
setTimeout(() => Chart.getChart(card.querySelector("canvas"))?.resize(), 20);
}
for (const button of document.querySelectorAll(".chart-expand")) {
button.addEventListener("click", () => {
const card = button.closest(".chart-card");
const wasExpanded = card.classList.contains("chart-expanded");
closeExpandedChart();
if (!wasExpanded) {
card.classList.add("chart-expanded");
button.textContent = "Close";
document.body.classList.add("chart-open");
setTimeout(() => Chart.getChart(card.querySelector("canvas"))?.resize(), 20);
}
});
}
for (const button of document.querySelectorAll(".chart-download")) {
button.addEventListener("click", () => downloadChart(button.closest(".chart-card")));
}
document.addEventListener("keydown", (event) => { if (event.key === "Escape") closeExpandedChart(); });