`;
}
export async function mount(el, { id }) {
alive = true;
el.innerHTML = skeleton();
const st = { id, run: null, traj: [], follow: true, shown: 0 };
let first;
try { first = await api(`/api/runs/${encodeURIComponent(id)}`); } catch (e) {
if (!alive) return;
el.innerHTML = `
${emptyState("search", "Rollout not found", e.status === 404 ? "It may be private, or the link is wrong." : esc(e.message),
`${icon("arrowLeft")}Your rollouts`)}
`;
return;
}
if (!alive) return;
if (["mimo", "nemo-gym"].includes(first.run.runner)) {
other = await import("./run-mimo.js");
if (alive) other.mount(el, id, first);
return;
}
el.innerHTML = `
What the agent did
`;
$("#rp-follow", el).addEventListener("change", (e) => (st.follow = e.target.checked));
$("#rp-expand", el).addEventListener("click", (e) => {
const open = e.target.textContent === "Expand all";
el.querySelectorAll("#rp-tl details").forEach((d) => (d.open = open));
e.target.textContent = open ? "Collapse all" : "Expand all";
});
el.addEventListener("click", async (e) => {
if (e.target.closest("#rp-stop")) {
e.target.closest("#rp-stop").disabled = true;
try { await api(`/api/runs/${encodeURIComponent(id)}/cancel`, { method: "POST" }); toast("Stopping: the sandbox is shut down"); } catch (err) { toast(err.message); }
}
const v = e.target.closest("[data-vis]");
if (v) {
try {
const r = await api(`/api/runs/${encodeURIComponent(id)}/visibility`, { method: "POST", body: { visibility: v.dataset.vis } });
st.run = r.run; renderHead(el, st);
if (v.dataset.vis === "public") { const b = v.getBoundingClientRect(); confetti(b.left + b.width / 2, b.top); toast("Public: thank you for sharing"); }
else toast("Private: only you can see this rollout");
} catch (err) { toast(err.message); }
}
});
apply(el, st, first);
const poll = async () => {
if (!alive) return;
try { apply(el, st, await api(`/api/runs/${encodeURIComponent(id)}`)); } catch { /* next tick */ }
if (alive && isLive(st.run)) timer = setTimeout(poll, 2000);
else refreshActive();
};
if (isLive(st.run)) timer = setTimeout(poll, 2000);
}
function apply(el, st, d) {
st.run = d.run;
const grew = d.trajectory.length !== st.traj.length || JSON.stringify(d.trajectory.at(-1)) !== JSON.stringify(st.traj.at(-1));
st.traj = d.trajectory;
renderHead(el, st);
renderPhases(el, st);
if (grew) renderTimeline(el, st);
renderTail(el, st);
renderGrade(el, st);
renderCost(el, st);
renderMeta(el, st);
}
function renderHead(el, st) {
const r = st.run, owner = r.is_owner;
const end = r.finished_at || Date.now() / 1000, start = r.started_at || r.created_at;
const vis = owner && !r.restricted ? `${["public", "private"].map((v) => ``).join("")}`
: visibilityBadge(r.visibility);
const model = r.endpoint ? r.model : (r.model || "").split("/")[1] || r.model;
$("#rp-head", el).innerHTML = `
`;
const summary = (inner) => `${icon("chevronRight", 13, "chev")}${inner}`;
const textOf = (c) => (typeof c === "string" ? c : Array.isArray(c) ? c.map((p) => (typeof p === "string" ? p : p?.text || "")).join("\n") : c == null ? "" : JSON.stringify(c));
function parseArgs(a) { if (typeof a !== "string") return a || {}; try { return JSON.parse(a); } catch { return { arguments: a }; } }
function rows(messages) {
const results = {};
messages.forEach((m) => { if (m.role === "tool" && m.tool_call_id) results[m.tool_call_id] = m; });
let users = 0, steps = 0;
const out = [];
for (const m of messages) {
const text = textOf(m.content);
if (m.role === "system") {
out.push(row("ev-prompt", "doc", `${summary(`System prompt${text.length.toLocaleString()} characters, from the agent`)}
${esc(text)}
`));
} else if (m.role === "user") {
users++;
out.push(row("ev-prompt", "doc", `${summary(`${users === 1 ? "Instructions to the model" : "Message to the model"}${text.length.toLocaleString()} characters`)}
${isLive(r) ? `Appears here once the agent finishes and the task's ${r.judge ? `grader has run (it asks ${esc(r.judge)}, through a relay that only this rollout's grading can use)` : "tests have run"}.` : "This rollout was not graded."}
${r.endpoint ? "Tokens are billed by your endpoint; the sandbox by Hugging Face." : `Billed to ${r.is_owner ? "your" : "the runner's"} Hugging Face account: the sandbox by the hour, tokens at the provider's price.`}
`;
}
function renderMeta(el, st) {
const r = st.run, p = r.params || {};
const row2 = (k, v) => (v == null || v === "" ? "" : `