// 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 `
${results.map((r) => ``).join("")}
ModelEnvironmentRunnerMetricRunsMean 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)}
`; } export async function mount(el, { qs }) { unmount(); const page = current = { controller: null, events: new AbortController(), timer: null, sequence: 0, pending: false }; const p = qs || new URLSearchParams(); const f = Object.fromEntries(KEYS.map((k) => [k, p.get(k) || ""])); f.dataset ||= p.get("d") || ""; f.group ||= DOMAIN_NAME[p.get("domain")] || ""; f.sort = SORT.some(([k]) => k === p.get("sort")) ? p.get("sort") : "new"; // Legacy Tasks URLs become rollout filters; no implicit MiMo dataset selection. const sync = () => { const q = new URLSearchParams(Object.entries(f).filter(([k, v]) => v && !(k === "sort" && v === "new"))); history.replaceState(null, "", "/community" + (q.size ? `?${q}` : "")); }; el.innerHTML = `

Community

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.

${sk.line(60, 22)}

Reward scales differ by environment. Values below use each rollout’s recorded scoring metric.

Rollouts

${sk.lines(95, 90, 92, 88)}

Public rollouts hide account identities and may later be released as an open dataset for research.

`; let offset = 0; const seen = new Set(); const option = (key, label, entries = [], labelOf = (v) => v) => { const list = entries.slice(); if (f[key] && !list.some(([v]) => v === f[key])) list.push([f[key], 0]); return ``; }; const renderHead = (d) => { const s = d.stats, fc = d.facets; const fig = (v, label) => `
${fmt.format(v)}${label}
`; $("#cm-figs", el).innerHTML = fig(d.total, "public rollouts") + fig(s.datasets, "environments") + fig(s.runners, "runners") + fig(s.models, "models"); $("#cm-result-panel", el).hidden = !s.results.length; $("#cm-board", el).innerHTML = s.results.length ? modelResults(s.results) : ""; const focus = document.activeElement, focusedQuery = focus?.id === "cm-q", focusedFilter = focus?.dataset?.f; const selection = focusedQuery ? [focus.selectionStart, focus.selectionEnd] : null; const moreOpen = $(".cm-more", el)?.open; $("#cm-filters", el).innerHTML = ` ${option("runner", "Any runner", fc.runner, runnerName)}${option("dataset", "Any environment", fc.dataset)}${option("model", "Any model", fc.model, short)}
${icon("filter", 14)}More
${option("group", "Any group", fc.group)}${option("served", "Any provider", fc.served)}${option("judge", "Any judge", fc.judge, short)}${option("thinking", "Any thinking", fc.thinking, v => THINK[v] || v)}
`; if (focusedQuery) { const input = $("#cm-q", el); input.focus({preventScroll:true}); input.setSelectionRange(...selection); } else if (focusedFilter) $$('[data-f]', el).find(x => x.dataset.f === focusedFilter)?.focus({preventScroll:true}); const active = KEYS.filter(k => f[k]); $("#cm-active", el).innerHTML = active.length ? 'Filtered by' + active.map(k => ``).join("") + '' : ""; }; const load = async (append = false) => { if (append && page.pending) return; page.controller?.abort(); const controller = page.controller = new AbortController(), sequence = ++page.sequence; page.pending = true; $("#cm-more button", el).disabled = true; $("#cm-rows", el).setAttribute("aria-busy", "true"); $("#cm-error", el).innerHTML = ""; const q = new URLSearchParams({limit:"40",offset:String(append ? offset : 0)}); for (const [key, value] of Object.entries(f)) if (value) q.set(key, value); try { const d = await api(`/api/community?${q}`, {signal:controller.signal}); if (current !== page || sequence !== page.sequence) return; if (!append) { renderHead(d); seen.clear(); offset = 0; $("#cm-rows", el).innerHTML = ""; } const next = d.runs.filter(r => { if (seen.has(r.id)) return false; seen.add(r.id); return true; }); $("#cm-rows", el).insertAdjacentHTML("beforeend", next.map(row).join("")); offset += d.runs.length; $("#cm-count", el).textContent = d.total ? `${fmt.format(seen.size)} of ${fmt.format(d.total)}` : ""; $("#cm-more", el).hidden = offset >= d.total || !d.runs.length; $("#cm-more span", el).textContent = `Showing ${fmt.format(seen.size)} of ${fmt.format(d.total)}`; if (!d.total) $("#cm-rows", el).innerHTML = emptyState("globe", KEYS.some(k => f[k]) ? "No rollouts match" : "No public rollouts yet", KEYS.some(k => f[k]) ? "Clear a filter to see more public rollouts." : "Completed, graded runs appear here when shared publicly. Private runs remain in My rollouts.", 'My rolloutsExplore environments'); } catch (e) { if (current === page && sequence === page.sequence && e.name !== "AbortError") { if (!append) $("#cm-rows", el).innerHTML = ""; $("#cm-error", el).innerHTML = `

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(); }