// Public, completed rollouts across all saved runners. Filters live in the URL.
import { $, $$, api, esc, money, ago, rewardBadge, DOMAIN_NAME, sk, emptyState, fmt } from "./util.js";
import { icon } from "./icons.js";
let current = null;
export function unmount() {
if (current) { current.controller?.abort(); current.events.abort(); clearTimeout(current.timer); }
current = null;
}
const REWARD = [["", "Any reward"], ["full", "Reward ≥ 0.999"], ["partial", "0 < reward < 0.999"], ["zero", "Reward ≤ 0"]];
const SORT = [["new", "Newest"], ["reward_desc", "Highest reward"], ["reward_asc", "Lowest reward"], ["cost_asc", "Cheapest"], ["cost_desc", "Most expensive"]];
const THINK = { default: "model default", none: "off", low: "low", medium: "medium", high: "high" };
const RUNNER = { harbor: "Harbor", mimo: "MiMo", "nemo-gym": "NeMo Gym", openenv: "OpenEnv", verifiers: "Verifiers", verl: "verl", skyrl: "SkyRL", mcp: "MCP", ors: "ORS" };
const runnerName = (value) => RUNNER[value] || value || "Harbor";
const short = (value) => (value || "").split("/").at(-1) || "Unknown model";
const num = (value) => value == null ? "–" : new Intl.NumberFormat("en-US", { maximumFractionDigits: 4 }).format(value);
const KEYS = ["dataset", "runner", "group", "model", "served", "judge", "reward", "thinking", "q"];
const LABEL = { model: short, served: (v) => "served by " + v, judge: (v) => "judge " + short(v), thinking: (v) => "thinking " + (THINK[v] || v),
reward: (v) => (REWARD.find(([k]) => k === v) || [v, v])[1], q: (v) => `“${v}”`, group: (v) => v, dataset: (v) => v, runner: runnerName };
function row(r) {
const title = r.title || r.path || r.task_id || "Rollout";
const details = [r.dataset, runnerName(r.runner), r.domain && DOMAIN_NAME[r.domain],
r.harness && !["mimo", "nemo-gym"].includes(r.runner) ? r.harness : null,
r.endpoint ? "own endpoint" : r.provider, r.judge ? `judge ${short(r.judge)}` : null].filter(Boolean).join(" · ");
return `
${rewardBadge(r.reward, r.status)}${esc(title)}
${esc(details)}
${r.shot ? `
` : ""}
${esc(short(r.model))}${money(r.cost?.total)}
${ago(r.created_at)}${icon("chevronRight", 14)}`;
}
function modelResults(results) {
return `
| Model | Environment | Runner | Metric | Runs | Mean reward |
|---|---|---|---|---|---|
| ${esc(r.served)} | ${esc([DOMAIN_NAME[r.domain] || r.domain, r.revision ? `revision ${r.revision.slice(0, 8)}` : ""].filter(Boolean).join(" · "))} | ${esc(runnerName(r.runner))} | ${esc(r.metric)}${r.judge ? `judge ${esc(short(r.judge))}` : ""} | ${fmt.format(r.runs)} | ${num(r.mean)} |
Public, graded rollouts across Harbor, MiMo, NeMo Gym and other supported runners. Explore their traces and compare results within an environment. Your public and private runs are in My rollouts.
Reward scales differ by environment. Values below use each rollout’s recorded scoring metric.
Observed results can use different tasks, revisions and judges; they are not a controlled model ranking.
Public rollouts hide account identities and may later be released as an open dataset for research.
Couldn't load rollouts: ${esc(e.message)}
`; } } finally { if (current === page && sequence === page.sequence) { page.pending = false; $("#cm-more button", el).disabled = false; $("#cm-rows", el).setAttribute("aria-busy", "false"); } } }; const reload = () => { clearTimeout(page.timer); sync(); load(); }; el.addEventListener("error", e => { if (e.target.classList?.contains("cm-shot")) e.target.remove(); }, {capture:true, signal:page.events.signal}); el.addEventListener("click", e => { const unset = e.target.closest("[data-unset]"), model = e.target.closest("[data-pick-model]"), dataset = e.target.closest("[data-pick-dataset]"), retry = e.target.closest("[data-retry]"); if (unset) { f[unset.dataset.unset] = ""; reload(); } else if (model) { f.model = model.dataset.pickModel; reload(); } else if (dataset) { f.dataset = dataset.dataset.pickDataset; reload(); } else if (retry) load(retry.dataset.retry === 'more'); else if (e.target.closest("#cm-clear")) { for (const key of KEYS) f[key] = ""; reload(); } else if (e.target.closest("#cm-more button")) load(true); }, {signal:page.events.signal}); // Tie every listener to this mount, even when the router reuses the main node. const change = e => { const select = e.target.closest("[data-f]"); if (select) { f[select.dataset.f] = select.value; reload(); } }; const input = e => { if (e.target.id !== "cm-q") return; f.q = e.target.value.trim(); page.controller?.abort(); ++page.sequence; clearTimeout(page.timer); page.timer = setTimeout(reload, 250); }; el.addEventListener("change", change, {signal:page.events.signal}); el.addEventListener("input", input, {signal:page.events.signal}); sync(); load(); }