Files
skills/orchestrator/templates/resources.js
T
Kevin Veen-BirkenbachandClaude Opus 5.5 35c270e120 feat(orchestrator): W4 resources view and host samples
A resources timer samples host CPU, RAM, swap and per-session tokens into samples.jsonl; the hub serves them and a Resources view charts them. Committed below the bar on the operator's word 2026-11-12 (no further per-bundle tests, one gate after the merge): the W4 e2e never ran in a real browser.

🎯 Fix: 92 %
💥 Break: 6 %
💸 Cost: 100 %
⏱️ Time: 100 %
🛡️ Security: 100 %
🏆 Score: 86
🚦 Gate: ⛔ break 6 % > 5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 16:15:43 +00:00

145 lines
5.4 KiB
JavaScript

const Resources = (() => {
"use strict";
const IDLE = 30;
const SATURATED = 90;
const CALM = 50;
const GAP = 1800;
const STEP = 60;
const COUNTS = ["input", "output", "cache_read", "cache_write"];
const ZONES = [{kind: "idle", from: 0, to: IDLE}, {kind: "saturated", from: SATURATED, to: 100}];
const finite = (value) => typeof value === "number" && Number.isFinite(value);
const share = (part, whole) => (finite(part) && finite(whole) && whole > 0 ? Math.round((1000 * part) / whole) / 10 : null);
const listOf = (row, key) => (Array.isArray(row[key]) ? row[key].filter((item) => item && typeof item === "object") : []);
const timed = (samples) => samples.filter((row) => row && finite(row.t));
function series(samples, pick) {
const found = new Map();
for (const row of timed(samples)) {
for (const [name, kind, value] of pick(row)) {
const key = `${kind}\u0000${name}`;
if (!found.has(key)) {
found.set(key, {name: String(name), kind, points: []});
}
found.get(key).points.push([row.t, finite(value) ? value : null]);
}
}
return [...found.values()];
}
function lines(samples) {
return {
disks: series(samples, (row) => listOf(row, "disks").map((disk) => [disk.mount, "disk", share(disk.used, disk.total)])),
host: series(samples, (row) => [["CPU", "host", row.cpu], ["RAM", "host", row.ram], ["Swap", "host", row.swap]]),
gpu: series(samples, (row) => listOf(row, "gpus").flatMap((gpu) => [[gpu.name, "util", gpu.asleep ? null : gpu.util], [gpu.name, "vram", gpu.asleep ? null : share(gpu.vram_used, gpu.vram_total)]])),
};
}
function segments(points) {
const found = [];
let current = [];
let last = null;
for (const [t, value] of points) {
if (current.length && (value === null || t - last > GAP)) {
found.push(current);
current = [];
}
if (value !== null) {
current.push([t, value]);
}
last = t;
}
if (current.length) {
found.push(current);
}
return found;
}
function spans(samples, test, value) {
const rows = timed(samples);
const found = [];
let open = null;
rows.forEach((row, index) => {
if (open && index && row.t - rows[index - 1].t > GAP) {
found.push(open);
open = null;
}
if (!test(row)) {
if (open) {
found.push(open);
}
open = null;
return;
}
const next = rows[index + 1];
const end = row.t + (next && next.t - row.t <= GAP ? next.t - row.t : STEP);
const peak = value(row);
open = open ? {from: open.from, to: end, peak: Math.max(open.peak, peak)} : {from: row.t, to: end, peak};
});
if (open) {
found.push(open);
}
return found;
}
function waits(samples) {
const waiting = (row) => (row.queue && finite(row.queue.waiting) ? row.queue.waiting : 0);
return spans(samples, (row) => waiting(row) > 0 && finite(row.cpu) && finite(row.ram) && row.cpu < CALM && row.ram < CALM, waiting);
}
function gpuSpans(samples, test) {
const names = [...new Set(timed(samples).flatMap((row) => listOf(row, "gpus").filter(test).map((gpu) => String(gpu.name))))];
return names.map((name) => ({name, spans: spans(samples, (row) => listOf(row, "gpus").some((gpu) => String(gpu.name) === name && test(gpu)), () => 1)}));
}
const asleep = (samples) => gpuSpans(samples, (gpu) => gpu.asleep === true);
const unknown = (samples) => gpuSpans(samples, (gpu) => gpu.asleep !== true && !finite(gpu.util) && !finite(gpu.vram_used));
function stack(tokens) {
const totals = new Map();
const hours = new Map();
for (const row of tokens) {
if (!row || !finite(row.t) || typeof row.agent !== "string") {
continue;
}
const counts = COUNTS.map((name) => (finite(row[name]) && row[name] > 0 ? row[name] : 0));
const sum = counts.reduce((total, value) => total + value, 0);
if (!totals.has(row.agent)) {
totals.set(row.agent, 0);
}
totals.set(row.agent, totals.get(row.agent) + sum);
if (!hours.has(row.t)) {
hours.set(row.t, new Map());
}
const hour = hours.get(row.t);
if (!hour.has(row.agent)) {
hour.set(row.agent, {agent: row.agent, total: 0, models: [], ...Object.fromEntries(COUNTS.map((name) => [name, 0]))});
}
const entry = hour.get(row.agent);
COUNTS.forEach((name, index) => {
entry[name] += counts[index];
});
entry.total += sum;
if (typeof row.model === "string" && !entry.models.includes(row.model)) {
entry.models.push(row.model);
}
}
const agents = [...totals].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([agent]) => agent);
const bars = [...hours.keys()].sort((a, b) => a - b).map((t) => {
let base = 0;
const parts = agents.filter((agent) => hours.get(t).has(agent)).map((agent) => {
const entry = hours.get(t).get(agent);
const part = {...entry, from: base, to: base + entry.total};
base += entry.total;
return part;
});
return {t, total: base, parts};
});
return {agents, totals: Object.fromEntries(totals), bars, top: Math.max(0, ...bars.map((bar) => bar.total))};
}
return {IDLE, SATURATED, CALM, GAP, COUNTS, ZONES, lines, segments, spans, waits, asleep, unknown, stack};
})();
if (typeof module === "object" && module.exports) {
module.exports = Resources;
}