Yashp2003's picture
Update logbook: Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models
7b7aad4 verified
Raw
History Blame Contribute Delete
102 kB
(function () {
"use strict";
let MANIFEST = null;
const PAGE_CACHE = {};
const UNFURL_CACHE = {};
const DATA_CACHE = {};
const LIVE_RELOAD_MS = 1500;
const FIGURE_FRAME_WINDOWS = new Set();
let FIGURE_NAVIGATION_READY = false;
let CURRENT_VIEW = null;
let RENDER_SEQUENCE = 0;
function esc(s) {
return String(s)
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
function flattenTree(node, depth, acc) {
acc.push({ node: node, depth: depth });
(node.children || []).forEach((c) => flattenTree(c, depth + 1, acc));
return acc;
}
function findNode(node, slug) {
if (node.slug === slug) return node;
for (const c of node.children || []) {
const hit = findNode(c, slug);
if (hit) return hit;
}
return null;
}
/* -------------------- minimal markdown -------------------- */
function inline(text) {
let t = esc(text);
t = t.replace(/`([^`]+)`/g, (_, c) => `<code>${c}</code>`);
t = t.replace(/\*\*([^*]+)\*\*/g, (_, c) => `<strong>${c}</strong>`);
t = t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, txt, url) => {
const safe = esc(url);
const attrs = /^https?:/.test(url) ? ' target="_blank" rel="noopener"' : "";
const item = /^https?:/.test(url) ? classifyResource(url) : null;
const data = item
? ` class="res-link" data-res-url="${esc(item.url)}"`
: "";
return `<a href="${safe}"${attrs}${data}>${txt}</a>`;
});
t = t.replace(/(^|[\s(])(https?:\/\/[^\s<>)"'`]+)/g, (m, pre, url) => {
let rest = "";
const cut = url.search(/&quot;|&#39;|&lt;|&gt;/);
if (cut !== -1) {
rest = url.slice(cut);
url = url.slice(0, cut);
}
const trailing = (url.match(/[.,;:!?`]+$/) || [""])[0];
const clean = trailing ? url.slice(0, -trailing.length) : url;
if (!clean) return m;
const item = classifyResource(clean);
if (item) return `${pre}${resChipHtml(item)}${trailing}${rest}`;
return `${pre}<a href="${clean}" target="_blank" rel="noopener">${clean}</a>${trailing}${rest}`;
});
return t;
}
function resChipHtml(item) {
return (
`<a class="res-chip" href="${esc(item.url)}" target="_blank" ` +
`rel="noopener" data-res-url="${esc(item.url)}">` +
`<span class="res-chip-ico">${RESOURCE_ICONS[item.kind]}</span>` +
`${esc(item.id)}</a>`
);
}
const URL_ONLY = /^(https?:\/\/[^\s]+)$/;
const DETECTED_URL =
/(https?:\/\/[^\s<>)\]"'`]+|trackio-local-dashboard:\/\/[^\s<>)\]"'`]+|trackio-artifact:\/\/[^\s<>)\]"'`]+|trackio-local-path:\/\/[^\s<>)\]"'`]+)/g;
function renderMarkdown(md, container) {
const cellRe = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
const tokens = [];
let pos = 0;
let found = false;
let match;
while ((match = cellRe.exec(md))) {
found = true;
tokens.push({
kind: "md",
text: md.slice(pos, match.index + match[1].length),
});
tokens.push({
kind: "cell",
meta: parseCellMeta(match[2]),
body: match[3],
});
pos = match.index + match[0].length;
}
tokens.push({ kind: "md", text: found ? md.slice(pos) : md });
for (let i = 0; i < tokens.length; i++) {
const t = tokens[i];
if (t.kind === "md") {
renderMarkdownPlain(t.text, container);
continue;
}
if (t.consumed) continue;
if (t.meta.type === "code") {
const arts = [];
for (let j = i + 1; j < tokens.length; j++) {
const n = tokens[j];
if (n.kind === "md") {
if (n.text.trim() === "") continue;
break;
}
if (n.meta.type === "artifact") {
arts.push(n);
n.consumed = true;
continue;
}
break;
}
renderCell(t.meta, t.body, container, arts);
} else {
renderCell(t.meta, t.body, container);
}
}
}
function parseCellMeta(raw) {
try {
return JSON.parse(raw);
} catch (e) {
return { type: "markdown", title: "Note" };
}
}
function renderMarkdownPlain(md, container) {
const lines = md.replace(/<!--[\s\S]*?-->/g, "").split("\n");
let i = 0;
let para = [];
function flushPara() {
if (!para.length) return;
const joined = para.join(" ").trim();
para = [];
if (!joined) return;
if (/^trackio-artifact:\/\/\S+$/.test(joined)) return;
if (/^trackio-local-path:\/\/\S+$/.test(joined)) return;
if (joined.indexOf("📦 Artifact") !== -1) {
const div = document.createElement("div");
div.className = "artifact-chip";
div.innerHTML = ARTIFACT_ICON_IMG + inline(joined.replace(/📦\s*/, ""));
container.appendChild(div);
return;
}
if (URL_ONLY.test(joined) || IMG_PATH.test(joined)) {
const el = renderStandaloneUrl(joined);
if (el) container.appendChild(el);
return;
}
const p = document.createElement("p");
p.innerHTML = inline(joined);
container.appendChild(p);
}
while (i < lines.length) {
const line = lines[i];
const trimmed = line.trim();
if (trimmed === "") {
flushPara();
i++;
continue;
}
const fence = trimmed.match(/^(`{3,}|~{3,})(.*)$/);
if (fence) {
flushPara();
const marker = fence[1][0];
const closeRe = new RegExp("^" + marker + "{" + fence[1].length + ",}\\s*$");
const info = fence[2].trim();
const buf = [];
i++;
while (i < lines.length && !closeRe.test(lines[i].trim())) {
buf.push(lines[i]);
i++;
}
i++;
const lang = (info.split(/\s+/)[0] || "").toLowerCase();
const tm = info.match(/title=(\S+)/);
container.appendChild(
renderCode(buf.join("\n"), lang, tm ? tm[1] : null)
);
continue;
}
if (trimmed === "---") {
flushPara();
container.appendChild(document.createElement("hr"));
i++;
continue;
}
const h = trimmed.match(/^(#{1,4})\s+(.*)$/);
if (h) {
flushPara();
const el = document.createElement("h" + h[1].length);
el.innerHTML = inline(h[2]);
container.appendChild(el);
i++;
continue;
}
if (
trimmed.startsWith("|") &&
i + 1 < lines.length &&
/^\|?[\s:|-]*-{2,}[\s:|-]*\|?$/.test(lines[i + 1].trim())
) {
flushPara();
const rows = [];
while (i < lines.length && lines[i].trim().startsWith("|")) {
rows.push(parseRow(lines[i].trim()));
i++;
}
renderTable(rows, container);
continue;
}
if (trimmed.startsWith("> ")) {
flushPara();
const bq = document.createElement("blockquote");
bq.innerHTML = inline(trimmed.slice(2));
container.appendChild(bq);
i++;
continue;
}
if (/^`[^`]+`$/.test(trimmed)) {
flushPara();
const el = document.createElement("div");
el.className = "ts";
el.textContent = trimmed.replace(/`/g, "");
container.appendChild(el);
i++;
continue;
}
if (trimmed.startsWith("- ")) {
flushPara();
const items = [];
while (i < lines.length && lines[i].trim().startsWith("- ")) {
items.push(lines[i].trim().slice(2).trim());
i++;
}
renderList(items, container);
continue;
}
para.push(trimmed);
i++;
}
flushPara();
}
function renderCell(meta, body, container, artifacts) {
const cell = document.createElement("section");
cell.className = `cell ${meta.type || "markdown"}`;
if (meta.id) cell.dataset.cellId = meta.id;
if (isPinned(meta)) cell.classList.add("pinned-source");
const head = document.createElement("div");
head.className = "cell-head";
const rawTitle = (meta.title || "").trim();
const title = rawTitle && rawTitle.toLowerCase() !== "untitled" ? esc(rawTitle) : "";
const when = meta.created_at ? `<span>${esc(formatTime(meta.created_at))}</span>` : "";
head.innerHTML =
(title ? `<div class="cell-title">${title}</div>` : "") +
`<div class="cell-meta">${when}</div>`;
if (!title) head.classList.add("no-title");
cell.appendChild(head);
const bodyEl = document.createElement("div");
bodyEl.className = "cell-body";
if (meta.type === "code") {
renderCodeCell(body, bodyEl, artifacts);
} else if (meta.type === "figure") {
cell.dataset.resUrl = `trackio-figure://${(meta.title || "Figure").trim()}`;
renderFigureCell(body, bodyEl, head);
} else if (meta.type === "artifact") {
renderMarkdownPlain(body, bodyEl);
const chip = bodyEl.querySelector(".artifact-chip");
const uri = body.match(
/(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/
);
if (chip && uri) chip.dataset.resUrl = uri[1];
if (chip && meta.path) {
const ico = chip.querySelector(".art-ico");
if (ico) ico.outerHTML = FILE_ICON;
}
} else if (meta.type === "dashboard") {
const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
cell.dataset.resUrl = sp
? sp[0]
: `trackio-local-dashboard://${(meta.dashboard_project || "").trim()}`;
renderDashboardCell(meta, body, bodyEl, head);
} else {
const cleaned = stripDuplicateTitle(body, meta.title);
renderMarkdownPlain(cleaned, bodyEl);
renderDetectedEmbeds(cleaned, bodyEl);
}
cell.appendChild(bodyEl);
container.appendChild(cell);
return cell;
}
function isPinned(meta) {
return Boolean(meta && (meta.pinned === true || meta.pinned === "true"));
}
function stripDuplicateTitle(body, title) {
if (!title) return body;
const m = body.match(/^\s*#{1,6}\s+([^\n]+)\n?/);
if (!m) return body;
const norm = (s) =>
s
.toLowerCase()
.replace(/[*_`#]/g, "")
.replace(/\s+/g, " ")
.trim();
return norm(m[1]) === norm(title) ? body.slice(m[0].length) : body;
}
function formatTime(iso) {
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return iso;
return d.toLocaleString(undefined, {
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
});
}
function parseFences(text) {
const fenceRe = /(`{3,4}|~{3,4})([^\n]*)\n([\s\S]*?)\n\1/g;
const parts = [];
let pos = 0;
let match;
while ((match = fenceRe.exec(text))) {
if (match.index > pos) {
parts.push({ kind: "text", text: text.slice(pos, match.index) });
}
const info = match[2].trim();
const lang = (info.split(/\s+/)[0] || "").toLowerCase();
const titleMatch = info.match(/title=(\S+)/);
parts.push({
kind: lang === "result" || lang === "output" ? "output" : "code",
lang,
title: titleMatch ? titleMatch[1] : null,
text: match[3],
});
pos = match.index + match[0].length;
}
if (pos < text.length) parts.push({ kind: "text", text: text.slice(pos) });
return parts;
}
function fitFigureFrame(frame, wrap) {
let doc;
try {
doc = frame.contentDocument;
} catch (e) {
return;
}
if (!doc || !doc.body) return;
frame.style.transform = "none";
frame.style.width = "100%";
frame.style.height = "auto";
frame.style.position = "";
frame.style.left = "";
frame.style.top = "";
const avail = wrap.clientWidth;
const isFullscreen =
document.fullscreenElement === wrap ||
document.webkitFullscreenElement === wrap;
const availHeight = isFullscreen ? wrap.clientHeight : Infinity;
const cw = Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth, 1);
const ch = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, 1);
const scale = Math.min(avail / cw, availHeight / ch);
if (avail && scale < 1 - 1e-3) {
frame.style.width = `${cw}px`;
frame.style.height = `${ch}px`;
frame.style.transformOrigin = "top left";
frame.style.transform = `scale(${scale})`;
if (isFullscreen) {
frame.style.position = "absolute";
frame.style.left = `${Math.max(0, (avail - cw * scale) / 2)}px`;
frame.style.top = `${Math.max(0, (availHeight - ch * scale) / 2)}px`;
wrap.style.height = "100%";
} else {
wrap.style.height = `${Math.ceil(ch * scale)}px`;
}
} else {
frame.style.width = "100%";
frame.style.height = `${ch}px`;
wrap.style.height = isFullscreen ? "100%" : `${ch}px`;
}
}
function attachFigureFit(frame, wrap) {
const refit = () => fitFigureFrame(frame, wrap);
frame.addEventListener("load", refit);
if (window.ResizeObserver) {
const ro = new ResizeObserver(() => refit());
ro.observe(wrap);
}
}
function renderFigureCell(text, container, head) {
const parts = parseFences(text);
const htmlPart = parts.find((part) => part.lang === "html");
const rawPart = parts.find((part) => part.lang === "raw");
if (!htmlPart || !htmlPart.text.trim()) {
const empty = document.createElement("p");
empty.className = "muted";
empty.textContent = "No figure HTML.";
container.appendChild(empty);
return;
}
const frame = document.createElement("iframe");
frame.className = "figure-frame";
frame.sandbox = "allow-scripts allow-same-origin";
frame.loading = "lazy";
frame.srcdoc = htmlPart.text;
registerFigureNavigation(frame);
const figWrap = document.createElement("div");
figWrap.className = "figure-fit";
figWrap.appendChild(frame);
attachFigureFit(frame, figWrap);
if (head) {
const metaEl = head.querySelector(".cell-meta");
if (metaEl)
metaEl.insertBefore(buildFullscreenControl(figWrap, frame), metaEl.firstChild);
}
if (!rawPart || !rawPart.text.trim()) {
container.appendChild(figWrap);
return;
}
const sw = document.createElement("div");
sw.className = "fig-switch";
const thumb = document.createElement("span");
thumb.className = "fig-switch-thumb";
const figBtn = document.createElement("button");
figBtn.type = "button";
figBtn.className = "active";
figBtn.textContent = "Figure";
const rawBtn = document.createElement("button");
rawBtn.type = "button";
rawBtn.textContent = "Raw";
sw.appendChild(thumb);
sw.appendChild(figBtn);
sw.appendChild(rawBtn);
const rawView = document.createElement("div");
rawView.className = "figure-raw";
rawView.hidden = true;
const pre = document.createElement("pre");
const code = document.createElement("code");
code.textContent = rawPart.text;
pre.appendChild(code);
rawView.appendChild(pre);
rawView.appendChild(copySnippetBtn(rawPart.text));
const select = (showRaw) => {
sw.classList.toggle("raw", showRaw);
figBtn.classList.toggle("active", !showRaw);
rawBtn.classList.toggle("active", showRaw);
figWrap.hidden = showRaw;
rawView.hidden = !showRaw;
};
figBtn.addEventListener("click", () => select(false));
rawBtn.addEventListener("click", () => select(true));
if (head) {
head.insertBefore(sw, head.querySelector(".cell-meta"));
} else {
container.appendChild(sw);
}
container.appendChild(figWrap);
container.appendChild(rawView);
}
// Poster embeds can send `{ type: "trackio-logbook:navigate", target: "..." }`
// from their iframe. Only accept messages from figure frames we created, and
// only route to pages that are present in this logbook's manifest.
function registerFigureNavigation(frame) {
const registerFrameWindow = () => {
if (frame.contentWindow) FIGURE_FRAME_WINDOWS.add(frame.contentWindow);
};
// `srcdoc` replaces the initial about:blank document. Register after that
// navigation as well, so messages come from the live figure document.
frame.addEventListener("load", registerFrameWindow);
registerFrameWindow();
if (FIGURE_NAVIGATION_READY) return;
FIGURE_NAVIGATION_READY = true;
window.addEventListener("message", (event) => {
if (!FIGURE_FRAME_WINDOWS.has(event.source)) return;
const message = event.data;
if (!message || message.type !== "trackio-logbook:navigate") return;
const target = String(message.target || "").replace(/^#?\//, "");
if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return;
const hash = "#/view/code/" + target;
if (location.hash === hash) scrollToHash();
else location.hash = hash;
});
}
const FULLSCREEN_ICON =
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' +
'stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
'<path d="M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5"/>' +
'<path d="M3 8 8 3M16 3l5 5M21 16l-5 5M8 21l-5-5"/></svg>';
const PIN_ICON =
'<svg class="pin-ico" viewBox="0 0 24 24" aria-hidden="true">' +
'<path d="M16 9V4h1c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1h1v5c0 ' +
'1.66-1.34 3-3 3v2h5.97v7l1 1 1-1v-7H19v-2c-1.66 0-3-1.34-3-3z"/></svg>';
const FILE_ICON =
'<svg class="art-file-ico" viewBox="0 0 24 24" aria-hidden="true">' +
'<path d="M6 3.5h8l4 4V20H6zM14 3.5V8h4"/></svg>';
// Figures are rendered in same-origin iframes, so fullscreen the fitted
// wrapper rather than the iframe document. This uses the browser's native
// fullscreen UI and preserves the figure's existing responsive sizing.
function buildFullscreenControl(figWrap, frame) {
const wrap = document.createElement("span");
wrap.className = "cell-fullscreen";
const btn = document.createElement("button");
btn.type = "button";
btn.className = "cell-fullscreen-btn";
btn.setAttribute("aria-label", "Open figure in fullscreen");
btn.title = "Open figure in fullscreen";
btn.innerHTML = FULLSCREEN_ICON;
wrap.appendChild(btn);
btn.addEventListener("click", async () => {
const request = figWrap.requestFullscreen || figWrap.webkitRequestFullscreen;
if (!request) return;
try {
await request.call(figWrap);
} catch (_) {
// Fullscreen can be disabled by the embedding browser or policy.
}
});
document.addEventListener("fullscreenchange", () => {
if (document.fullscreenElement === figWrap) fitFigureFrame(frame, figWrap);
});
return wrap;
}
function extractUrls(text) {
const seen = new Set();
const urls = [];
let match;
while ((match = DETECTED_URL.exec(text))) {
const url = match[1].replace(/[.,;:!?'"`]+$/, "");
if (!seen.has(url)) {
seen.add(url);
urls.push(url);
}
}
DETECTED_URL.lastIndex = 0;
return urls;
}
const IMG_URL = /(\.(png|jpe?g|gif|svg|webp)(\?|$)|\/artifact_blob\/)/i;
function renderDetectedEmbeds(text, container) {
extractUrls(text).forEach((url) => {
if (url.startsWith("trackio-local-dashboard://")) {
const div = document.createElement("div");
div.className = "artifact-chip";
div.dataset.resUrl = url;
div.innerHTML =
"🎯 <strong>Local Trackio dashboard</strong> — publish the logbook to share it";
container.appendChild(div);
} else if (IMG_URL.test(url)) {
container.appendChild(renderImage(url));
} else if (/huggingface\.co\/spaces\//.test(url)) {
maybeEmbedTrackioSpace(url, container);
}
});
}
function renderStandaloneUrl(url) {
if (IMG_URL.test(url) || IMG_PATH.test(url)) return renderImage(url);
const item = classifyResource(url);
if (item) {
const marker = document.createElement("span");
marker.className = "resource-anchor";
marker.dataset.resUrl = item.url;
marker.setAttribute("aria-hidden", "true");
return marker;
}
const p = document.createElement("p");
p.innerHTML = inline(url);
return p;
}
function renderImage(url) {
const a = document.createElement("a");
a.className = "unfurl image";
a.href = url;
a.target = "_blank";
a.rel = "noopener";
const img = document.createElement("img");
img.loading = "lazy";
img.src = url;
img.alt = "artifact image";
a.appendChild(img);
return a;
}
function maybeEmbedTrackioSpace(url, container) {
const id = url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
const holder = document.createElement("div");
container.appendChild(holder);
getJSON(`https://huggingface.co/api/spaces/${id}`).then((d) => {
const tags = (d && d.tags) || [];
if (tags.some((t) => String(t).toLowerCase() === "trackio")) {
renderTrackioSpaceEmbed(holder, url, id);
} else {
holder.remove();
}
});
}
function jpGutter(label) {
const g = document.createElement("div");
g.className = "jp-gutter";
g.textContent = label;
return g;
}
function renderOutArtifact(info) {
const remote = !info.local && !!info.url;
const el = document.createElement(remote ? "a" : "div");
el.className = "out-artifact";
if (remote) {
el.href = info.url;
el.target = "_blank";
el.rel = "noopener";
}
el.dataset.resUrl = info.resUrl;
const parts = [info.type, info.size].filter(Boolean).map(esc);
const state = remote
? `<span class="out-artifact-state open">Open ↗</span>`
: `<span class="out-artifact-state">publish to share</span>`;
const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state;
const icon = info.isPathRef ? FILE_ICON : ARTIFACT_ICON_IMG;
el.innerHTML =
`<span class="out-artifact-ico">${icon}</span>` +
`<span class="out-artifact-name">${esc(info.name)}</span>` +
`<span class="out-artifact-meta">${meta}</span>`;
return el;
}
function isShellCommand(part) {
return (
part.kind === "code" &&
part.lang === "bash" &&
!part.title &&
/^\s*\$\s/.test(part.text)
);
}
function renderCommandLine(text) {
const command = text.trim().replace(/^\$\s*/, "");
const el = document.createElement("div");
el.className = "jp-cmd";
const prompt = document.createElement("span");
prompt.className = "jp-cmd-prompt";
prompt.textContent = "$";
const code = document.createElement("code");
code.textContent = command;
el.appendChild(prompt);
el.appendChild(code);
el.appendChild(copySnippetBtn(command));
return el;
}
function renderCodeCell(body, container, artifacts) {
const parts = parseFences(body);
const block = document.createElement("div");
block.className = "jp";
const input = document.createElement("div");
input.className = "jp-in";
const inputBody = document.createElement("div");
inputBody.className = "jp-in-body";
input.appendChild(jpGutter("In"));
input.appendChild(inputBody);
let metaEl = null;
let outputEl = null;
let outBody = null;
const ensureOut = () => {
if (outputEl) return;
outputEl = document.createElement("div");
outputEl.className = "jp-out";
outputEl.appendChild(jpGutter("Out"));
outBody = document.createElement("div");
outBody.className = "jp-out-body";
outputEl.appendChild(outBody);
};
const embedTexts = [];
parts.forEach((part) => {
if (part.kind === "text") {
const text = part.text.trim();
if (!text) return;
if (/^exit\s+\S+(\s|·)/.test(text)) {
metaEl = document.createElement("div");
metaEl.className = "jp-meta";
metaEl.textContent = text.replace(
/\s*·\s*[A-Z][a-z]{2} \d{1,2}, \d{4}.*$/,
""
);
} else {
renderMarkdownPlain(text, container);
embedTexts.push(text);
}
return;
}
if (part.kind === "output") {
ensureOut();
const pre = document.createElement("pre");
pre.className = "jp-out-pre";
const c = document.createElement("code");
c.textContent = part.text;
pre.appendChild(c);
outBody.appendChild(pre);
outputEl.appendChild(copySnippetBtn(part.text));
embedTexts.push(part.text);
return;
}
if (isShellCommand(part)) {
inputBody.appendChild(renderCommandLine(part.text));
} else {
inputBody.appendChild(
renderCode(part.text, part.lang, part.title, Boolean(part.title))
);
}
});
if (artifacts && artifacts.length) {
ensureOut();
const artWrap = document.createElement("div");
artWrap.className = "jp-artifacts";
artifacts.forEach((a) => {
artWrap.appendChild(
renderOutArtifact(artifactInfoFromCell(a.meta, a.body))
);
});
outBody.appendChild(artWrap);
}
if (inputBody.childNodes.length > 0) block.appendChild(input);
if (metaEl) block.appendChild(metaEl);
if (outputEl) block.appendChild(outputEl);
if (block.childNodes.length) container.appendChild(block);
embedTexts.forEach((text) => renderDetectedEmbeds(text, container));
}
function parseRow(line) {
let s = line.trim();
if (s.startsWith("|")) s = s.slice(1);
if (s.endsWith("|")) s = s.slice(0, -1);
return s.split(/(?<!\\)\|/).map((c) => c.replace(/\\\|/g, "|").trim());
}
const TRUTHY = ["x", "✓", "✔", "yes", "done", "true", "[x]"];
const CHIP_COLORS = [
["#e7f0ff", "#2158d0"],
["#fde8ec", "#c62a4b"],
["#e6f7ee", "#1a8a55"],
["#fdf0e0", "#b26a12"],
["#efe9ff", "#5b3bd6"],
["#e6f6f8", "#127b88"],
];
function chipColor(name) {
let h = 0;
for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
return CHIP_COLORS[h % CHIP_COLORS.length];
}
const STATUS_MAP = {
"": ["Planned", "gray"],
planned: ["Planned", "gray"],
todo: ["Planned", "gray"],
"to do": ["Planned", "gray"],
backlog: ["Planned", "gray"],
"in progress": ["In progress", "amber"],
"in-progress": ["In progress", "amber"],
wip: ["In progress", "amber"],
running: ["In progress", "amber"],
active: ["In progress", "amber"],
done: ["Done", "green"],
complete: ["Done", "green"],
completed: ["Done", "green"],
blocked: ["Blocked", "red"],
failed: ["Failed", "red"],
abandoned: ["Abandoned", "gray"],
};
function statusBadge(val) {
const [label, tone] = STATUS_MAP[val.toLowerCase()] || [val || "—", "gray"];
return `<span class="badge ${tone}">${esc(label)}</span>`;
}
function renderTable(rows, container) {
if (rows.length < 2) return;
const header = rows[0];
const body = rows.slice(2);
const roles = header.map((h) => {
const t = h.toLowerCase();
if (t.includes("status") || t.includes("state")) return "status";
if (t.includes("progress") || t.includes("complete") || t.includes("done"))
return "check";
if (t === "who" || t.includes("assign") || t.includes("owner")) return "who";
return "text";
});
const table = document.createElement("table");
table.className = "board";
const thead = document.createElement("thead");
const htr = document.createElement("tr");
header.forEach((h, c) => {
const th = document.createElement("th");
th.textContent = h;
if (roles[c] === "check") th.className = "col-check";
htr.appendChild(th);
});
thead.appendChild(htr);
table.appendChild(thead);
const tbody = document.createElement("tbody");
body.forEach((cells) => {
const nonEmpty = cells.filter((x) => x !== "").length;
if (header.length > 1 && nonEmpty === 1 && cells[0]) {
const tr = document.createElement("tr");
tr.className = "section-row";
const td = document.createElement("td");
td.colSpan = header.length;
td.innerHTML = inline(cells[0]);
tr.appendChild(td);
tbody.appendChild(tr);
return;
}
const tr = document.createElement("tr");
header.forEach((_, c) => {
const td = document.createElement("td");
const val = (cells[c] || "").trim();
if (roles[c] === "status") {
td.className = "col-status";
td.innerHTML = statusBadge(val);
} else if (roles[c] === "check") {
td.className = "col-check";
const on = TRUTHY.indexOf(val.toLowerCase()) !== -1;
td.innerHTML = `<span class="box ${on ? "on" : ""}">${on ? "✓" : ""}</span>`;
} else if (roles[c] === "who") {
if (!val || /^to assign$/i.test(val)) {
td.innerHTML = `<span class="who-chip muted">${esc(val || "—")}</span>`;
} else {
const [bg, fg] = chipColor(val);
td.innerHTML = `<span class="who-chip" style="background:${bg};color:${fg}">${esc(val)}</span>`;
}
} else {
td.innerHTML = inline(val);
}
tr.appendChild(td);
});
const link = tr.querySelector('a[href^="#/"]');
if (link) {
tr.classList.add("linked-row");
tr.addEventListener("click", (e) => {
if (e.target.tagName !== "A") location.hash = link.getAttribute("href");
});
}
tbody.appendChild(tr);
});
table.appendChild(tbody);
const wrap = document.createElement("div");
wrap.className = "board-wrap";
wrap.appendChild(table);
container.appendChild(wrap);
}
const HL_RULES = {
python: [
["comment", /#[^\n]*/],
["string", /'''[\s\S]*?'''|"""[\s\S]*?"""|'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
[
"keyword",
/\b(?:def|class|return|if|elif|else|for|while|import|from|as|with|try|except|finally|raise|in|not|and|or|is|None|True|False|lambda|yield|global|nonlocal|assert|pass|break|continue|async|await|print)\b/,
],
["number", /\b\d[\d_.eE+-]*\b/],
],
bash: [
["comment", /#[^\n]*/],
["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
["keyword", /\b(?:if|then|else|fi|for|in|do|done|while|case|esac|function|export|source|echo|cd|return|local)\b/],
["number", /(?<=\s)-{1,2}[a-zA-Z][\w-]*/],
],
json: [
["string", /"(?:\\.|[^"\\])*"/],
["keyword", /\b(?:true|false|null)\b/],
["number", /-?\b\d[\d.eE+-]*\b/],
],
yaml: [
["comment", /#[^\n]*/],
["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
["keyword", /\b(?:true|false|null|yes|no)\b/],
["number", /-?\b\d[\d.eE+-]*\b/],
],
};
HL_RULES.javascript = HL_RULES.python;
HL_RULES.typescript = HL_RULES.python;
HL_RULES.sql = [
["comment", /--[^\n]*/],
["string", /'(?:\\.|[^'\\])*'/],
[
"keyword",
/\b(?:SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|ON|GROUP|BY|ORDER|LIMIT|INSERT|INTO|VALUES|UPDATE|SET|DELETE|CREATE|TABLE|AS|AND|OR|NOT|NULL|COUNT|DISTINCT|IN)\b/i,
],
["number", /\b\d[\d.]*\b/],
];
function highlightCode(code, lang) {
const rules = HL_RULES[lang];
if (!rules) return esc(code);
const combined = new RegExp(rules.map((r) => "(" + r[1].source + ")").join("|"), "g");
let out = "";
let last = 0;
let m;
while ((m = combined.exec(code))) {
if (m[0] === "") {
combined.lastIndex++;
continue;
}
out += esc(code.slice(last, m.index));
let gi = 1;
while (gi < m.length && m[gi] === undefined) gi++;
out += `<span class="tok-${rules[gi - 1][0]}">${esc(m[0])}</span>`;
last = m.index + m[0].length;
}
out += esc(code.slice(last));
return out;
}
function copySnippetBtn(text) {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "copy-snippet";
btn.title = "Copy";
btn.textContent = "⧉";
btn.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
copyText(text, btn, "⧉");
});
return btn;
}
function renderCode(code, lang, title, open) {
const pre = document.createElement("pre");
pre.className = "hl";
const c = document.createElement("code");
c.innerHTML = highlightCode(code, lang);
pre.appendChild(c);
if (!title || open) {
const wrap = document.createElement("div");
wrap.className = "snippet";
wrap.appendChild(pre);
wrap.appendChild(copySnippetBtn(code));
return wrap;
}
const det = document.createElement("details");
det.className = "code-accordion";
det.dataset.resUrl = `trackio-script://${title}`;
const sum = document.createElement("summary");
sum.innerHTML =
`<span class="code-ico">&lt;/&gt;</span>` +
`<span class="code-name">${esc(title)}</span>`;
sum
.querySelector(".code-name")
.addEventListener("click", (e) => e.preventDefault());
det.appendChild(sum);
const wrap = document.createElement("div");
wrap.className = "snippet";
wrap.appendChild(pre);
wrap.appendChild(copySnippetBtn(code));
det.appendChild(wrap);
return det;
}
const IMG_PATH = /^[^\s]+\.(png|jpe?g|gif|svg|webp)$/i;
function renderList(items, container) {
let ul = null;
items.forEach((item) => {
if (URL_ONLY.test(item) || IMG_PATH.test(item)) {
const el = renderStandaloneUrl(item);
if (el) {
ul = null;
container.appendChild(el);
}
} else if (item.indexOf("📦 Artifact") !== -1) {
ul = null;
const div = document.createElement("div");
div.className = "artifact-chip";
div.innerHTML = inline(item.replace("📦", "🪣"));
container.appendChild(div);
} else if (item.indexOf("trackio-local-dashboard://") !== -1) {
ul = null;
const uri = item.match(/trackio-local-dashboard:\/\/\S+/)?.[0] || "";
const div = document.createElement("div");
div.className = "artifact-chip";
if (uri) div.dataset.resUrl = uri;
div.innerHTML =
"🎯 <strong>Local dashboard</strong> — publish the logbook to share it";
container.appendChild(div);
} else {
if (!ul) {
ul = document.createElement("ul");
container.appendChild(ul);
}
const li = document.createElement("li");
li.innerHTML = inline(item);
ul.appendChild(li);
}
});
}
/* -------------------- resource classification -------------------- */
function fmt(n) {
if (n == null) return null;
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
return String(n);
}
const RESOURCE_SECTIONS = [
["dashboard", "Dashboards", "🎯"],
["model", "Models", "🤗"],
["dataset", "Datasets", "📊"],
["space", "Spaces", "🚀"],
["artifact", "Artifacts", "🪣"],
["paper", "Papers", "📄"],
["repo", "Code", "🐙"],
["job", "Jobs", "⚙️"],
["bucket", "Buckets", "🪣"],
];
const RESOURCE_ICONS = Object.fromEntries(
RESOURCE_SECTIONS.map(([kind, , icon]) => [kind, icon])
);
const ARTIFACT_ICON_IMG = `<img class="art-ico" src="./bucket-icon.svg" alt="" />`;
const DASHBOARD_ICON_IMG = `<img class="art-ico" src="./trackio-logo-light.png" alt="" />`;
const HF_NON_MODEL_PREFIX =
/^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/;
function hfId(url, marker) {
return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
}
function validHfSegment(value) {
return Boolean(
value &&
value.length <= 96 &&
/^[A-Za-z0-9_.-]+$/.test(value) &&
!/^[.-]|[.-]$|--|\.\./.test(value)
);
}
function validHfRepoId(parts) {
return (
parts.length === 2 &&
parts.join("/").length <= 96 &&
parts.every(validHfSegment)
);
}
function classifyResource(url) {
if (IMG_URL.test(url)) {
return null;
}
let m;
if (url.startsWith("trackio-local-dashboard://")) {
return {
kind: "dashboard",
id: url.slice("trackio-local-dashboard://".length),
url,
local: true,
};
}
if (url.startsWith("trackio-artifact://")) {
return {
kind: "artifact",
id: url.slice("trackio-artifact://".length),
url,
local: true,
};
}
if (url.startsWith("trackio-local-path://")) {
return {
kind: "artifact",
id: url.slice("trackio-local-path://".length),
url,
local: true,
};
}
if ((m = url.match(/huggingface\.co\/buckets\/([^/#\s]+\/[^/#\s]+)#(.+)/))) {
if (!validHfRepoId(m[1].split("/"))) return null;
return { kind: "artifact", id: decodeURIComponent(m[2]), url };
}
if (/huggingface\.co\/datasets\//.test(url)) {
const parts = hfId(url, "/datasets/").split("/").slice(0, 2);
if (!validHfRepoId(parts)) return null;
return { kind: "dataset", id: parts.join("/"), url };
}
if (/huggingface\.co\/spaces\//.test(url)) {
const parts = hfId(url, "/spaces/").split("/").slice(0, 2);
if (!validHfRepoId(parts)) return null;
return { kind: "space", id: parts.join("/"), url };
}
if (/huggingface\.co\/jobs\//.test(url)) {
const parts = hfId(url, "/jobs/").split("/").slice(0, 2);
if (!validHfRepoId(parts)) return null;
const jid = parts[1];
return {
kind: "job",
id: parts[0] + ` · ${jid.slice(0, 12)}${jid.length > 12 ? "…" : ""}`,
url,
};
}
if (/huggingface\.co\/buckets\//.test(url)) {
const parts = hfId(url, "/buckets/").split("/").slice(0, 2);
if (!validHfRepoId(parts)) return null;
return { kind: "bucket", id: parts.join("/"), url };
}
if (/huggingface\.co\/papers\//.test(url)) {
const id = hfId(url, "/papers/").split("/")[0];
if (!validHfSegment(id)) return null;
return { kind: "paper", id: `Paper ${id}`, url };
}
if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) {
return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url };
}
if ((m = url.match(/github\.com\/([^/?#]+\/[^/?#]+)/))) {
return { kind: "repo", id: m[1], url };
}
if ((m = url.match(/huggingface\.co\/([^?#]+)/))) {
const rest = m[1].replace(/\/$/, "");
if (validHfRepoId(rest.split("/")) && !HF_NON_MODEL_PREFIX.test(rest)) {
return { kind: "model", id: rest, url };
}
}
return null;
}
function dashboardSubdomainFromUrl(url) {
return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-");
}
function dashboardOpenLink(head, url) {
if (!head || !url) return;
const meta = head.querySelector(".cell-meta");
if (!meta) return;
let link = meta.querySelector(".cell-open");
if (!link) {
link = document.createElement("a");
link.className = "cell-open";
link.target = "_blank";
link.rel = "noopener";
meta.insertBefore(link, meta.firstChild);
}
link.href = url;
link.textContent = "Open ↗";
}
function dashboardFrame(src) {
const iframe = document.createElement("iframe");
iframe.className = "dashboard-frame";
iframe.src = src;
iframe.loading = "lazy";
iframe.allow = "clipboard-read; clipboard-write; fullscreen";
return iframe;
}
function renderDashboardCell(meta, body, container, head) {
const project = meta.dashboard_project || "";
const holder = document.createElement("div");
holder.className = "dashboard-shell";
container.appendChild(holder);
const space = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
if (space) {
const url = space[0];
dashboardOpenLink(head, url);
holder.appendChild(
dashboardFrame(
`https://${dashboardSubdomainFromUrl(url)}.hf.space/?sidebar=hidden&hide_empty_tabs=true`
)
);
return;
}
if (!isLocalPreview()) {
holder.className = "artifact-chip";
holder.dataset.resUrl = `trackio-local-dashboard://${project}`;
holder.innerHTML =
"🎯 <strong>Local Trackio dashboard</strong> — publish the logbook to share it";
return;
}
const open = "/dashboard/?project=" + encodeURIComponent(project);
dashboardOpenLink(head, open);
holder.appendChild(
dashboardFrame(open + "&sidebar=hidden&hide_empty_tabs=true"),
);
}
const CACHE_PREFIX = "trackio-logbook:";
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
const CACHE_MISS_TTL_MS = 60 * 60 * 1000;
function cacheGet(url) {
try {
const raw = localStorage.getItem(CACHE_PREFIX + url);
if (!raw) return undefined;
const entry = JSON.parse(raw);
const ttl = entry.d === null ? CACHE_MISS_TTL_MS : CACHE_TTL_MS;
if (Date.now() - entry.t > ttl) {
localStorage.removeItem(CACHE_PREFIX + url);
return undefined;
}
return entry.d;
} catch (e) {
return undefined;
}
}
function cacheSet(url, data) {
try {
localStorage.setItem(
CACHE_PREFIX + url,
JSON.stringify({ t: Date.now(), d: data })
);
} catch (e) {}
}
async function getJSON(url) {
if (UNFURL_CACHE[url] !== undefined) return UNFURL_CACHE[url];
const cached = cacheGet(url);
if (cached !== undefined) {
UNFURL_CACHE[url] = cached;
return cached;
}
try {
const r = await fetch(url);
if (!r.ok) throw new Error(r.status);
const j = await r.json();
UNFURL_CACHE[url] = j;
cacheSet(url, j);
return j;
} catch (e) {
UNFURL_CACHE[url] = null;
cacheSet(url, null);
return null;
}
}
/* -------------------- routing / render -------------------- */
function buildTree() {
const tree = document.getElementById("tree");
tree.innerHTML = "";
const label = document.createElement("div");
label.className = "tree-label";
label.textContent = "Pages";
tree.appendChild(label);
const nodes = [];
(MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes));
nodes.forEach(({ node, depth }) => {
const a = document.createElement("a");
a.href = "#/view/code/" + node.slug;
a.className = "depth-" + depth;
a.dataset.slug = node.slug;
const mark = document.createElement("span");
mark.className = "tree-mark";
mark.textContent = "§";
a.appendChild(mark);
a.appendChild(document.createTextNode(" " + node.title));
tree.appendChild(a);
});
}
function highlightTraceSession(sessionId) {
document.querySelectorAll("#tree a").forEach((link) => {
link.classList.toggle("active", link.dataset.sessionId === sessionId);
});
}
function buildTraceTree(activeSessionId) {
const tree = document.getElementById("tree");
tree.innerHTML = "";
const sessions = MANIFEST.traces || [];
if (!sessions.length) return;
const label = document.createElement("div");
label.className = "tree-label";
label.textContent = "Sessions";
tree.appendChild(label);
sessions.forEach((session) => {
const link = document.createElement("a");
link.href = "#" + traceSessionAnchor(session.id);
link.dataset.sessionId = session.id;
link.textContent = session.title || session.id;
link.title = session.title || session.id;
tree.appendChild(link);
});
highlightTraceSession(activeSessionId || sessions[0].id);
}
function renderSidebar(route) {
if (route.view === "trace") {
highlight(null);
buildTraceTree(route.sessionId);
return;
}
if (route.view === "workspace") {
document.getElementById("tree").innerHTML = "";
highlight(null);
return;
}
buildTree();
highlight(route.slug);
}
function highlight(slug) {
document
.querySelectorAll("#tree a")
.forEach((a) => a.classList.toggle("active", a.dataset.slug === slug));
document
.getElementById("book-head")
.classList.toggle("active", slug === MANIFEST.root.slug);
}
function clearPageCache() {
Object.keys(PAGE_CACHE).forEach((key) => {
delete PAGE_CACHE[key];
});
Object.keys(DATA_CACHE).forEach((key) => {
delete DATA_CACHE[key];
});
}
function isLocalPreview() {
return ["localhost", "127.0.0.1", "::1"].includes(location.hostname);
}
async function fetchManifest() {
const suffix = isLocalPreview() ? `?t=${Date.now()}` : "";
return await (await fetch("./logbook.json" + suffix, { cache: "no-store" })).json();
}
async function fetchPage(node) {
if (PAGE_CACHE[node.file]) return PAGE_CACHE[node.file];
try {
const suffix = isLocalPreview()
? `?rev=${encodeURIComponent(MANIFEST.revision || "")}`
: "";
const r = await fetch("./" + node.file + suffix, { cache: "no-store" });
PAGE_CACHE[node.file] = await r.text();
} catch (e) {
PAGE_CACHE[node.file] = "# " + node.title + "\n\n_Could not load section._";
}
return PAGE_CACHE[node.file];
}
async function fetchData(file, cacheResult = true) {
if (cacheResult && DATA_CACHE[file]) return DATA_CACHE[file];
const suffix = isLocalPreview()
? `?rev=${encodeURIComponent(MANIFEST.revision || "")}`
: "";
const response = await fetch("./" + file + suffix, { cache: "no-store" });
if (!response.ok) throw new Error(`Could not load ${file}`);
const data = await response.json();
if (cacheResult) DATA_CACHE[file] = data;
return data;
}
function allNodes() {
const nodes = [];
flattenTree(MANIFEST.root, 0, nodes);
return nodes.map(({ node }) => node);
}
function collectPinnedCells(markdown, nodes) {
const cells = [];
markdown.forEach((text, index) => {
const cellRe = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
let match;
let cellIndex = 0;
while ((match = cellRe.exec(text))) {
const meta = parseCellMeta(match[2]);
if (isPinned(meta)) {
cells.push({
meta,
body: match[3],
node: nodes[index],
index: cells.length,
order: meta.pinned_at || meta.created_at || "",
cellIndex,
});
}
cellIndex++;
}
});
return cells.sort(
(a, b) =>
a.order.localeCompare(b.order) ||
a.index - b.index ||
a.cellIndex - b.cellIndex
);
}
function renderPinnedNotes(cells, container) {
if (!cells.length) return;
const deck = document.createElement("section");
deck.className = "pinned-notes";
const list = document.createElement("div");
list.className = "pinned-notes-list";
cells.forEach(({ meta, body }) => {
const cell = renderCell(meta, body, list);
cell.classList.add("pinned-copy");
const title = cell.querySelector(".cell-title");
if (title) title.insertAdjacentHTML("afterbegin", PIN_ICON);
});
deck.appendChild(list);
const anchor =
container.querySelector(".agent-hint") ||
Array.from(container.children).find((el) => el.tagName === "H1");
container.insertBefore(deck, anchor ? anchor.nextSibling : container.firstChild);
const owner = container.closest(".page-section");
if (owner) owner.classList.add("has-pinned-notes");
}
function isIndexPaperLink(el) {
if (!el || el.tagName !== "P") return false;
return Array.from(el.querySelectorAll("a[href]")).some((a) => {
const href = a.getAttribute("href") || "";
return (
/huggingface\.co\/papers\//.test(href) ||
/openreview\.net\//.test(href) ||
/arxiv\.org\//.test(href)
);
});
}
function removeIndexProse(body) {
const h1 = Array.from(body.children).find((el) => el.tagName === "H1");
if (!h1) return;
let current = h1.nextElementSibling;
while (current && current.tagName !== "H2") {
const next = current.nextElementSibling;
if (isIndexPaperLink(current)) {
current.classList.add("index-paper-link");
} else {
current.remove();
}
current = next;
}
}
function removePageDirectory(body) {
const heading = Array.from(body.children).find(
(el) => el.tagName === "H2" && el.textContent.trim().toLowerCase() === "pages"
);
if (!heading) return;
let current = heading;
while (current) {
const next = current.nextElementSibling;
current.remove();
if (next && ["H1", "H2"].includes(next.tagName)) break;
current = next;
}
}
async function renderLogbook(opts = {}) {
const scrollY = window.scrollY;
const page = document.getElementById("page");
page.innerHTML = "";
const nodes = allNodes();
const markdown = await Promise.all(nodes.map(fetchPage));
if (opts.renderId && opts.renderId !== RENDER_SEQUENCE) return;
const pinnedCells = collectPinnedCells(markdown, nodes);
let bookIntroBody = null;
nodes.forEach((node, index) => {
const section = document.createElement("section");
section.className = "page-section";
section.id = "/" + node.slug;
section.dataset.slug = node.slug;
const layout = document.createElement("div");
layout.className = "page-layout";
const body = document.createElement("div");
body.className = "page-body";
renderMarkdown(markdown[index], body);
if (node.slug === MANIFEST.root.slug) {
section.classList.add("book-intro");
removeIndexProse(body);
removePageDirectory(body);
const h1 = body.querySelector("h1");
if (h1 && h1.parentNode === body) h1.remove();
bookIntroBody = body;
}
layout.appendChild(body);
section.appendChild(layout);
page.appendChild(section);
});
const pinnedSlugs = Array.from(
new Set(pinnedCells.map((cell) => cell.node && cell.node.slug).filter(Boolean))
);
const pinnedTarget =
pinnedSlugs.length === 1
? Array.from(page.querySelectorAll(".page-section"))
.find((section) => section.dataset.slug === pinnedSlugs[0])
?.querySelector(".page-body")
: bookIntroBody;
if (pinnedTarget) renderPinnedNotes(pinnedCells, pinnedTarget);
// Pinned cells are promoted into one deck. Remove their source render so
// summaries, posters, and notes do not appear twice in the continuous view.
page
.querySelectorAll(".pinned-source:not(.pinned-copy)")
.forEach((cell) => cell.remove());
if (bookIntroBody) {
const section = bookIntroBody.closest(".book-intro");
const hasExtra = Array.from(bookIntroBody.children).some(
(el) =>
el.tagName !== "H1" &&
!el.classList.contains("agent-hint") &&
!el.classList.contains("index-paper-link") &&
!el.classList.contains("pinned-notes")
);
if (section && !section.classList.contains("has-pinned-notes") && !hasExtra) {
section.classList.add("book-intro-tight");
}
}
requestAnimationFrame(() => {
if (opts.preserveScroll) {
window.scrollTo(0, scrollY);
} else {
scrollToHash({ behavior: "auto" });
}
updateActiveSection();
});
}
function fmtBytes(n) {
if (n == null || isNaN(n)) return null;
if (n < 1000) return `${n} B`;
const units = ["kB", "MB", "GB", "TB"];
let v = n;
let i = -1;
do {
v /= 1000;
i++;
} while (v >= 1000 && i < units.length - 1);
return `${v.toFixed(v < 10 ? 1 : 0)} ${units[i]}`;
}
function spaceIdFromUrl(url) {
return url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
}
function artifactInfoFromCell(meta, body) {
const name = meta.artifact || meta.path || "";
let size = null;
const sm = body.match(/·\s*([\d.]+\s*[kMGT]?B)\b/);
if (sm) size = sm[1].trim();
if (!size && meta.size != null) size = fmtBytes(meta.size);
const bucket = body.match(/https:\/\/huggingface\.co\/buckets\/[^\s<>)"'`]+/);
const artUri = body.match(/trackio-artifact:\/\/\S+/);
const pathUri = body.match(/trackio-local-path:\/\/\S+/);
const url = bucket ? bucket[0] : "";
const local = !bucket;
const resUrl =
url || (artUri ? artUri[0] : pathUri ? pathUri[0] : `trackio-artifact://${name}`);
return {
name,
type: meta.artifact_type || "",
size,
local,
isPathRef: !!meta.path,
url,
resUrl,
};
}
const VIEW_ROUTE = { trace: "#/view/trace", workspace: "#/view/workspace" };
const VIEW_TOKENS = {
code: "agent_view_tokens",
trace: "trace_view_tokens",
workspace: "workspace_view_tokens",
};
function readTarget(view) {
const onSpaces =
/\.hf\.space$/.test(location.hostname) ||
/(^|\.)huggingface\.co$/.test(location.hostname);
let base = "";
if (onSpaces && MANIFEST.space_id) base = MANIFEST.space_id;
else if (/^https?:$/.test(location.protocol))
base = `${location.origin}${location.pathname}`;
if (!base) return "";
return base + (VIEW_ROUTE[view] || "");
}
function renderLogbookHeader(view) {
const title = document.getElementById("logbook-title");
if (title) title.textContent = MANIFEST.title;
const cli = document.getElementById("logbook-cli");
if (!cli) return;
cli.innerHTML = "";
cli.appendChild(buildAgentHint(view));
const destination = buildHubDestinationLink(view);
if (destination) cli.appendChild(destination);
}
function hubDestination(view) {
if (view === "trace" && MANIFEST.trace_dataset) {
return {
label: "View Hugging Face dataset:",
url: MANIFEST.trace_dataset,
fallback: "Agent Traces dataset",
};
}
if (view === "workspace") {
const bucketId = (MANIFEST.workspace || {}).bucket_id;
const url =
MANIFEST.workspace_bucket ||
(bucketId ? `https://huggingface.co/buckets/${bucketId}` : "");
if (url) {
return {
label: "View Hugging Face Bucket:",
url,
fallback: "Workspace Bucket",
};
}
}
return null;
}
function buildHubDestinationLink(view) {
const destination = hubDestination(view);
if (!destination || !destination.url.startsWith("https://huggingface.co/")) {
return null;
}
const row = document.createElement("div");
row.className = "hub-destination";
const label = document.createElement("span");
label.textContent = destination.label;
const link = document.createElement("a");
link.href = destination.url;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.textContent =
destination.url
.replace(/^https:\/\/huggingface\.co\/(?:datasets|buckets)\//, "")
.replace(/\/$/, "") || destination.fallback;
link.title = destination.url;
const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
icon.setAttribute("viewBox", "0 0 24 24");
icon.setAttribute("aria-hidden", "true");
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("d", "M14 5h5v5M19 5l-8 8M19 13v5a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5");
icon.appendChild(path);
link.appendChild(icon);
row.appendChild(label);
row.appendChild(link);
return row;
}
function buildAgentHint(view) {
const target = readTarget(view);
const command = `trackio logbook read${target ? ` ${target}` : ""}`;
const tokens = MANIFEST[VIEW_TOKENS[view] || VIEW_TOKENS.code];
const div = document.createElement("div");
div.className = "agent-hint";
const label = document.createElement("span");
label.className = "agent-hint-label";
label.textContent = "Read from the CLI:";
const code = document.createElement("code");
code.textContent = command;
const copy = document.createElement("button");
copy.className = "copy";
copy.type = "button";
copy.title = "Copy";
copy.textContent = "⧉";
copy.addEventListener("click", () => copyText(command, copy, "⧉"));
const note = document.createElement("span");
note.className = "agent-hint-note";
note.textContent =
"compact view for agents" + (tokens ? ` · ~${fmt(tokens)} tokens` : "");
div.appendChild(label);
div.appendChild(code);
div.appendChild(copy);
div.appendChild(note);
return div;
}
function routeState() {
const raw = (location.hash || "").replace(/^#\/?/, "");
if (!raw) return { view: "code", slug: MANIFEST.root.slug };
const parts = raw.split("/");
if (parts[0] !== "view") {
const slug = findNode(MANIFEST.root, raw) ? raw : MANIFEST.root.slug;
return { view: "code", slug };
}
if (parts[1] === "trace") {
return { view: "trace", sessionId: parts.slice(2).join("/") || null };
}
if (parts[1] === "workspace") return { view: "workspace" };
const candidate = parts.slice(2).join("/") || MANIFEST.root.slug;
return {
view: "code",
slug: findNode(MANIFEST.root, candidate) ? candidate : MANIFEST.root.slug,
};
}
function updateViewTabs(route = routeState()) {
document.querySelectorAll("#view-tabs a").forEach((tab) => {
const view = tab.dataset.view;
tab.classList.toggle("active", view === route.view);
tab.setAttribute("aria-current", view === route.view ? "page" : "false");
if (view === "code") {
const slug = route.view === "code" ? route.slug : MANIFEST.root.slug;
tab.href = `#/view/code/${slug}`;
} else if (view === "trace") {
tab.href = "#/view/trace";
}
});
}
function setActiveView(route) {
CURRENT_VIEW = route.view;
document.body.dataset.view = route.view;
updateViewTabs(route);
renderLogbookHeader(route.view);
renderSidebar(route);
}
function formatDuration(ms) {
if (ms == null || isNaN(ms)) return "—";
const total = Math.max(0, Math.floor(ms / 1000));
const hours = Math.floor(total / 3600);
const minutes = Math.floor((total % 3600) / 60);
const seconds = total % 60;
if (hours) return `${hours}h ${minutes}m ${seconds}s`;
if (minutes) return `${minutes}m ${seconds}s`;
return `${seconds}s`;
}
function formatDate(value) {
if (!value) return "—";
const date = new Date(value);
if (isNaN(date.getTime())) return value;
return date.toLocaleString([], {
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
second: "2-digit",
});
}
function emptyView(title, text, command) {
const empty = document.createElement("div");
empty.className = "view-empty";
const heading = document.createElement("h2");
heading.textContent = title;
const body = document.createElement("p");
body.textContent = text;
empty.appendChild(heading);
empty.appendChild(body);
if (command) {
const code = document.createElement("code");
code.textContent = command;
empty.appendChild(code);
}
return empty;
}
function traceEventLabel(event) {
if (event.kind === "reasoning") return "Thought";
if (event.kind === "tool_call") return event.tool_name || event.title || "Tool";
if (event.kind === "tool_result") return "Tool output";
return event.title || event.kind || "Event";
}
function appendTraceResult(entry, result) {
if (!entry || !result || !result.output) return;
const card = entry.querySelector(".trace-card");
if (!card) return;
const details = document.createElement("details");
details.className = "trace-output";
const summary = document.createElement("summary");
summary.textContent = result.status === "error" ? "Error output" : "Output";
const output = document.createElement("pre");
output.textContent = result.output;
details.appendChild(summary);
details.appendChild(output);
card.appendChild(details);
}
function traceEventCard(event, result) {
const entry = document.createElement("div");
entry.className = `trace-entry trace-${event.kind || "status"}`;
entry.style.setProperty("--trace-depth", Math.min(Number(event.depth) || 0, 4));
const rail = document.createElement("div");
rail.className = "trace-rail";
const number = document.createElement("span");
number.className = "trace-number";
number.textContent = `#${event.sequence || ""}`;
const dot = document.createElement("span");
dot.className = "trace-dot";
const elapsed = document.createElement("span");
elapsed.className = "trace-elapsed";
elapsed.textContent = formatDuration(event.elapsed_ms);
rail.appendChild(number);
rail.appendChild(dot);
rail.appendChild(elapsed);
const card = document.createElement("article");
card.className = "trace-card";
const head = document.createElement("header");
const kind = document.createElement("span");
kind.className = "trace-kind";
kind.textContent = traceEventLabel(event);
head.appendChild(kind);
if (event.turn) {
const turn = document.createElement("span");
turn.className = "trace-turn";
turn.textContent = `turn ${event.turn}`;
head.appendChild(turn);
}
card.appendChild(head);
const bodyText = event.text || event.input || event.output;
if (bodyText) {
const body = document.createElement(
event.kind === "tool_call" || event.kind === "tool_result" ? "pre" : "div"
);
body.className = "trace-body";
body.textContent = bodyText;
card.appendChild(body);
}
if (event.status) {
const status = document.createElement("span");
status.className = `trace-status-badge trace-status-badge-${event.status}`;
status.textContent = String(event.status).replace(/_/g, " ");
head.appendChild(status);
}
entry.appendChild(rail);
entry.appendChild(card);
appendTraceResult(entry, result);
return entry;
}
function traceSessionAnchor(id) {
return "/view/trace/" + id;
}
function buildTraceSession(session, index) {
const sec = document.createElement("section");
sec.className = "trace-session";
sec.id = traceSessionAnchor(session.id);
sec.dataset.sessionId = session.id;
const title = document.createElement("h2");
title.className = "trace-session-title";
title.textContent = session.title || session.id;
sec.appendChild(title);
const meta = document.createElement("div");
meta.className = "trace-meta";
[
["Started", formatDate(index.started_at)],
["Ended", formatDate(index.ended_at)],
["Duration", formatDuration(index.duration_ms)],
["Events", String(index.event_count || 0)],
].forEach(([label, value]) => {
const item = document.createElement("span");
const strong = document.createElement("strong");
strong.textContent = label;
item.appendChild(strong);
item.appendChild(document.createTextNode(` ${value}`));
meta.appendChild(item);
});
if (index.model) {
const model = document.createElement("span");
const strong = document.createElement("strong");
strong.textContent = "Model";
model.appendChild(strong);
model.appendChild(document.createTextNode(` ${index.model}`));
meta.appendChild(model);
}
if (index.source_available === false) {
const missing = document.createElement("span");
missing.className = "trace-source-missing";
missing.textContent = "Source file unavailable · showing last capture";
meta.appendChild(missing);
}
sec.appendChild(meta);
const timeline = document.createElement("section");
timeline.className = "trace-timeline";
sec.appendChild(timeline);
const chunks = index.chunks || [];
if (!chunks.length) {
timeline.appendChild(
emptyView("Empty trace", "No displayable events were found in this session.")
);
return sec;
}
const controls = document.createElement("div");
controls.className = "trace-load-controls";
const progress = document.createElement("span");
progress.className = "trace-load-progress";
const loadMore = document.createElement("button");
loadMore.type = "button";
loadMore.className = "trace-load-more";
controls.appendChild(progress);
controls.appendChild(loadMore);
sec.appendChild(controls);
let nextChunk = 0;
let loadedEvents = 0;
let loading = false;
const pendingCalls = new Map();
function updateLoadControls() {
const total = Number(index.event_count) || chunks.reduce(
(sum, chunk) => sum + (Number(chunk.count) || 0),
0
);
progress.textContent = `${Math.min(loadedEvents, total)} of ${total} events loaded`;
if (nextChunk >= chunks.length) {
loadMore.textContent = "All events loaded";
loadMore.disabled = true;
return;
}
const count = Number(chunks[nextChunk].count) || "next";
loadMore.textContent = `Load ${count} more events`;
loadMore.disabled = false;
}
async function loadNextTraceChunk() {
if (loading || nextChunk >= chunks.length) return;
loading = true;
loadMore.disabled = true;
loadMore.textContent = "Loading…";
const descriptor = chunks[nextChunk];
try {
// Event chunks can be large. Do not retain the parsed JSON in DATA_CACHE;
// the rendered DOM is the only long-lived copy.
const chunk = await fetchData(descriptor.file, false);
const events = chunk.events || [];
events.forEach((event) => {
if (
event.kind === "tool_result" &&
event.call_id &&
pendingCalls.has(event.call_id)
) {
appendTraceResult(pendingCalls.get(event.call_id), event);
pendingCalls.delete(event.call_id);
return;
}
const entry = traceEventCard(event);
timeline.appendChild(entry);
if (event.kind === "tool_call" && event.call_id) {
pendingCalls.set(event.call_id, entry);
}
});
loadedEvents += events.length;
nextChunk += 1;
sec.dataset.loadedChunks = String(nextChunk);
updateLoadControls();
} catch (error) {
progress.textContent = "Could not load the next trace segment.";
loadMore.textContent = "Retry";
loadMore.disabled = false;
} finally {
loading = false;
}
}
sec.dataset.loadedChunks = "0";
sec.loadNextTraceChunk = loadNextTraceChunk;
loadMore.addEventListener("click", loadNextTraceChunk);
updateLoadControls();
return sec;
}
function ensureTraceSessionLoaded(sessionId) {
const target = document.getElementById(traceSessionAnchor(sessionId));
if (
target &&
target.dataset.loadedChunks === "0" &&
typeof target.loadNextTraceChunk === "function"
) {
return target.loadNextTraceChunk();
}
return Promise.resolve();
}
function scrollToTraceSession(sessionId) {
if (!sessionId) {
window.scrollTo({ top: 0, behavior: "auto" });
return;
}
const target = document.getElementById(traceSessionAnchor(sessionId));
if (target) target.scrollIntoView({ behavior: "auto" });
else window.scrollTo({ top: 0, behavior: "auto" });
}
// A published static Space may store only a reference to a private (or
// public) repository instead of embedding trace/workspace content. These
// helpers render that reference: link-only for private/inaccessible repos,
// and a probe-then-render path for public ones.
function repoRefCard(ref, opts) {
const wrap = document.createElement("div");
wrap.className = "view-empty repo-ref-card";
const h = document.createElement("h2");
h.textContent = opts.title;
wrap.appendChild(h);
const p = document.createElement("p");
p.textContent = opts.message;
wrap.appendChild(p);
if (ref && ref.repo_url) {
const a = document.createElement("a");
a.className = "repo-ref-link";
a.href = ref.repo_url;
a.target = "_blank";
a.rel = "noopener noreferrer";
a.textContent = "Open on the Hub ↗";
wrap.appendChild(a);
}
return wrap;
}
async function probeRepoAccessible(ref) {
if (!ref || !ref.repo_id) return false;
let url = "";
if (ref.repo_type === "dataset") {
url = "https://huggingface.co/api/datasets/" + ref.repo_id;
} else if (ref.repo_type === "bucket") {
url = "https://huggingface.co/api/buckets/" + ref.repo_id;
}
if (!url) return ref.private === false;
try {
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) return false;
const metadata = await response.json();
return metadata.private !== true;
} catch (error) {
return false;
}
}
async function renderRepoReference(ref, kind, page, renderId) {
const isTraces = kind === "traces";
const noun = isTraces ? "agent traces" : "workspace files";
const linkOnly = () =>
repoRefCard(ref, {
title: isTraces ? "Agent traces" : "Workspace",
message:
`These ${noun} live in a private repository. ` +
"Open it on the Hub to view them.",
});
const accessible = await probeRepoAccessible(ref);
if (renderId !== RENDER_SEQUENCE) return;
if (!accessible) {
page.appendChild(linkOnly());
return;
}
page.appendChild(
repoRefCard(ref, {
title: isTraces ? "Agent traces" : "Workspace",
message:
`These ${noun} are published to a public repository on the Hub.`,
})
);
}
async function renderTrace(route, renderId) {
const page = document.getElementById("page");
page.innerHTML = "";
page.className = "trace-page";
const sessions = MANIFEST.traces || [];
if (!sessions.length) {
updateViewTabs({ view: "trace" });
if (MANIFEST.traces_ref && MANIFEST.traces_ref.repo_url) {
await renderRepoReference(MANIFEST.traces_ref, "traces", page, renderId);
return;
}
page.appendChild(
emptyView(
"No agent sessions attached yet",
"Attach the active session once and Trackio will keep its trace refreshed here while you work. The session stays local until you explicitly publish it.",
"trackio logbook attach trace <session.jsonl>"
)
);
return;
}
updateViewTabs({ view: "trace" });
const loading = document.createElement("div");
loading.className = "view-loading";
loading.textContent = "Loading traces…";
page.appendChild(loading);
let loaded;
try {
loaded = await Promise.all(
sessions.map(async (session) => {
const index = await fetchData(session.index_file);
return { session, index };
})
);
} catch (error) {
if (renderId !== RENDER_SEQUENCE) return;
page.innerHTML = "";
page.appendChild(
emptyView("Trace unavailable", "The normalized traces could not be loaded.")
);
return;
}
if (renderId !== RENDER_SEQUENCE) return;
page.innerHTML = "";
const shell = document.createElement("div");
shell.className = "trace-shell";
loaded.forEach(({ session, index }) => {
shell.appendChild(buildTraceSession(session, index));
});
page.appendChild(shell);
const activeSessionId = route.sessionId || sessions[0].id;
await ensureTraceSessionLoaded(activeSessionId);
if (renderId !== RENDER_SEQUENCE) return;
scrollToTraceSession(activeSessionId);
}
function svgIcon(kind) {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 24 24");
svg.setAttribute("aria-hidden", "true");
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute(
"d",
kind === "folder"
? "M3.5 6.5h6l2 2h9v9a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"
: kind === "download"
? "M12 3v12m0 0 4-4m-4 4-4-4M5 20h14"
: "M6 3.5h8l4 4V20H6zM14 3.5V8h4"
);
svg.appendChild(path);
return svg;
}
function workspaceTree(files) {
const root = { directories: new Map(), files: [] };
files.forEach((file) => {
const parts = file.path.split("/");
let cursor = root;
parts.slice(0, -1).forEach((name) => {
if (!cursor.directories.has(name)) {
cursor.directories.set(name, { directories: new Map(), files: [] });
}
cursor = cursor.directories.get(name);
});
cursor.files.push(file);
});
return root;
}
function workspaceFileRow(file) {
const row = document.createElement("div");
row.className = "workspace-file";
const name = document.createElement("div");
name.className = "workspace-file-name";
name.appendChild(svgIcon("file"));
const label = document.createElement("span");
label.textContent = file.name;
label.title = file.path;
name.appendChild(label);
const type = document.createElement("span");
type.className = "workspace-file-type";
type.textContent = file.type || "file";
const size = document.createElement("span");
size.className = "workspace-file-size";
size.textContent = fmtBytes(file.size) || "—";
const modified = document.createElement("time");
modified.className = "workspace-file-time";
modified.dateTime = file.modified_at || "";
modified.textContent = formatDate(file.modified_at);
row.appendChild(name);
row.appendChild(type);
row.appendChild(size);
row.appendChild(modified);
const url =
isLocalPreview() && file.local_url
? file.local_url
: file.download_url || file.bucket_url;
if (url) {
const download = document.createElement("a");
download.className = "workspace-download";
download.href = url;
download.title = "Download";
download.setAttribute("aria-label", `Download ${file.name}`);
if (isLocalPreview() && file.local_url) download.download = file.name;
download.appendChild(svgIcon("download"));
row.appendChild(download);
} else {
const pending = document.createElement("span");
pending.className = "workspace-unpublished";
pending.textContent = "Local";
row.appendChild(pending);
}
return row;
}
function renderWorkspaceNode(node, container) {
Array.from(node.directories.entries())
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([name, child]) => {
const details = document.createElement("details");
details.className = "workspace-folder";
details.open = true;
const summary = document.createElement("summary");
summary.appendChild(svgIcon("folder"));
const label = document.createElement("span");
label.textContent = name;
summary.appendChild(label);
details.appendChild(summary);
const children = document.createElement("div");
children.className = "workspace-folder-children";
renderWorkspaceNode(child, children);
details.appendChild(children);
container.appendChild(details);
});
node.files
.sort((a, b) => a.name.localeCompare(b.name))
.forEach((file) => container.appendChild(workspaceFileRow(file)));
}
const WORKSPACE_MODE_KEY = "trackio-logbook:workspace-mode";
function getWorkspaceMode() {
try {
return localStorage.getItem(WORKSPACE_MODE_KEY) === "type" ? "type" : "tree";
} catch (error) {
return "tree";
}
}
function setWorkspaceMode(mode) {
try {
localStorage.setItem(WORKSPACE_MODE_KEY, mode);
} catch (error) {
/* ignore storage failures (private mode, etc.) */
}
}
function fileGroupKey(file) {
if (file.type) return file.type;
const name = file.name || file.path || "";
const dot = name.lastIndexOf(".");
if (dot > 0 && dot < name.length - 1) return name.slice(dot + 1).toLowerCase();
return "other";
}
function renderWorkspaceByType(files, container) {
const groups = new Map();
files.forEach((file) => {
const key = fileGroupKey(file);
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push(file);
});
Array.from(groups.keys())
.sort((a, b) => a.localeCompare(b))
.forEach((key) => {
const items = groups
.get(key)
.sort((a, b) => a.name.localeCompare(b.name));
const section = document.createElement("div");
section.className = "workspace-group";
const heading = document.createElement("h3");
heading.className = "workspace-group-head";
const label = document.createElement("span");
label.textContent = key;
const count = document.createElement("span");
count.className = "workspace-group-count";
count.textContent = String(items.length);
heading.appendChild(label);
heading.appendChild(count);
section.appendChild(heading);
items.forEach((file) => section.appendChild(workspaceFileRow(file)));
container.appendChild(section);
});
}
function buildWorkspaceToggle(current, onChange) {
const toggle = document.createElement("div");
toggle.className = "workspace-toggle";
toggle.setAttribute("role", "group");
toggle.setAttribute("aria-label", "Workspace layout");
const buttons = [];
[
["tree", "Tree"],
["type", "By type"],
].forEach(([mode, text]) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "workspace-toggle-btn";
btn.textContent = text;
const setActive = (active) => {
btn.classList.toggle("is-active", active);
btn.setAttribute("aria-pressed", active ? "true" : "false");
};
setActive(mode === current);
btn.addEventListener("click", () => {
buttons.forEach((entry) => entry.setActive(entry.mode === mode));
onChange(mode);
});
buttons.push({ mode, setActive });
toggle.appendChild(btn);
});
return toggle;
}
const HF_LOGO_DATA_URI = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NSIgaGVpZ2h0PSI4OCIgZmlsbD0ibm9uZSI+Cgk8cGF0aCBmaWxsPSIjRkZEMjFFIiBkPSJNNDcuMjEgNzYuNWEzNC43NSAzNC43NSAwIDEgMCAwLTY5LjUgMzQuNzUgMzQuNzUgMCAwIDAgMCA2OS41WiIgLz4KCTxwYXRoCgkJZmlsbD0iI0ZGOUQwQiIKCQlkPSJNODEuOTYgNDEuNzVhMzQuNzUgMzQuNzUgMCAxIDAtNjkuNSAwIDM0Ljc1IDM0Ljc1IDAgMCAwIDY5LjUgMFptLTczLjUgMGEzOC43NSAzOC43NSAwIDEgMSA3Ny41IDAgMzguNzUgMzguNzUgMCAwIDEtNzcuNSAwWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiMzQTNCNDUiCgkJZD0iTTU4LjUgMzIuM2MxLjI4LjQ0IDEuNzggMy4wNiAzLjA3IDIuMzhhNSA1IDAgMSAwLTYuNzYtMi4wN2MuNjEgMS4xNSAyLjU1LS43MiAzLjctLjMyWk0zNC45NSAzMi4zYy0xLjI4LjQ0LTEuNzkgMy4wNi0zLjA3IDIuMzhhNSA1IDAgMSAxIDYuNzYtMi4wN2MtLjYxIDEuMTUtMi41Ni0uNzItMy43LS4zMloiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkYzMjNEIgoJCWQ9Ik00Ni45NiA1Ni4yOWM5LjgzIDAgMTMtOC43NiAxMy0xMy4yNiAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzYtMi4zMyAxLjE1LTUuNDYgMi43NC04LjkgMi43NC03LjE5IDAtMTMtNi44OC0xMy0yLjM4czMuMTYgMTMuMjYgMTMgMTMuMjZaIgoJLz4KCTxwYXRoCgkJZmlsbD0iIzNBM0I0NSIKCQlmaWxsLXJ1bGU9ImV2ZW5vZGQiCgkJZD0iTTM5LjQzIDU0YTguNyA4LjcgMCAwIDEgNS4zLTQuNDljLjQtLjEyLjgxLjU3IDEuMjQgMS4yOC40LjY4LjgyIDEuMzcgMS4yNCAxLjM3LjQ1IDAgLjktLjY4IDEuMzMtMS4zNS40NS0uNy44OS0xLjM4IDEuMzItMS4yNWE4LjYxIDguNjEgMCAwIDEgNSA0LjE3YzMuNzMtMi45NCA1LjEtNy43NCA1LjEtMTAuNyAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzZsLS4xNC4wN2MtMi4zMSAxLjE1LTUuMzkgMi42Ny04Ljc3IDIuNjdzLTYuNDUtMS41Mi04Ljc3LTIuNjdjLTIuNi0xLjI5LTQuMjMtMi4xLTQuMjMuMjkgMCAzLjA1IDEuNDYgOC4wNiA1LjQ3IDEwLjk3WiIKCQljbGlwLXJ1bGU9ImV2ZW5vZGQiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkY5RDBCIgoJCWQ9Ik03MC43MSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0yNC4yMSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0xNy41MiA0OGMtMS42MiAwLTMuMDYuNjYtNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMC0xLjMzIDMuNzYgNy4xIDcuMSAwIDAgMC0xLjk0LS4zYy0xLjU1IDAtMi45NS41OS0zLjk0IDEuNjZhNS44IDUuOCAwIDAgMC0uOCA3IDUuMyA1LjMgMCAwIDAtMS43OSAyLjgyYy0uMjQuOS0uNDggMi44LjggNC43NGE1LjIyIDUuMjIgMCAwIDAtLjM3IDUuMDJjMS4wMiAyLjMyIDMuNTcgNC4xNCA4LjUyIDYuMSAzLjA3IDEuMjIgNS44OSAyIDUuOTEgMi4wMWE0NC4zMyA0NC4zMyAwIDAgMCAxMC45MyAxLjZjNS44NiAwIDEwLjA1LTEuOCAxMi40Ni01LjM0IDMuODgtNS42OSAzLjMzLTEwLjktMS43LTE1LjkyLTIuNzctMi43OC00LjYyLTYuODctNS03Ljc3LS43OC0yLjY2LTIuODQtNS42Mi02LjI1LTUuNjJhNS43IDUuNyAwIDAgMC00LjYgMi40NmMtMS0xLjI2LTEuOTgtMi4yNS0yLjg2LTIuODJBNy40IDcuNCAwIDAgMCAxNy41MiA0OFptMCA0Yy41MSAwIDEuMTQuMjIgMS44Mi42NSAyLjE0IDEuMzYgNi4yNSA4LjQzIDcuNzYgMTEuMTguNS45MiAxLjM3IDEuMzEgMi4xNCAxLjMxIDEuNTUgMCAyLjc1LTEuNTMuMTUtMy40OC0zLjkyLTIuOTMtMi41NS03LjcyLS42OC04LjAxLjA4LS4wMi4xNy0uMDIuMjQtLjAyIDEuNyAwIDIuNDUgMi45MyAyLjQ1IDIuOTNzMi4yIDUuNTIgNS45OCA5LjNjMy43NyAzLjc3IDMuOTcgNi44IDEuMjIgMTAuODMtMS44OCAyLjc1LTUuNDcgMy41OC05LjE2IDMuNTgtMy44MSAwLTcuNzMtLjktOS45Mi0xLjQ2LS4xMS0uMDMtMTMuNDUtMy44LTExLjc2LTcgLjI4LS41NC43NS0uNzYgMS4zNC0uNzYgMi4zOCAwIDYuNyAzLjU0IDguNTcgMy41NC40MSAwIC43LS4xNy44My0uNi43OS0yLjg1LTEyLjA2LTQuMDUtMTAuOTgtOC4xNy4yLS43My43MS0xLjAyIDEuNDQtMS4wMiAzLjE0IDAgMTAuMiA1LjUzIDExLjY4IDUuNTMuMTEgMCAuMi0uMDMuMjQtLjEuNzQtMS4yLjMzLTIuMDQtNC45LTUuMi01LjIxLTMuMTYtOC44OC01LjA2LTYuOC03LjMzLjI0LS4yNi41OC0uMzggMS0uMzggMy4xNyAwIDEwLjY2IDYuODIgMTAuNjYgNi44MnMyLjAyIDIuMSAzLjI1IDIuMWMuMjggMCAuNTItLjEuNjgtLjM4Ljg2LTEuNDYtOC4wNi04LjIyLTguNTYtMTEuMDEtLjM0LTEuOS4yNC0yLjg1IDEuMzEtMi44NVoiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkZEMjFFIgoJCWQ9Ik0zOC42IDc2LjY5YzIuNzUtNC4wNCAyLjU1LTcuMDctMS4yMi0xMC44NC0zLjc4LTMuNzctNS45OC05LjMtNS45OC05LjNzLS44Mi0zLjItMi42OS0yLjljLTEuODcuMy0zLjI0IDUuMDguNjggOC4wMSAzLjkxIDIuOTMtLjc4IDQuOTItMi4yOSAyLjE3LTEuNS0yLjc1LTUuNjItOS44Mi03Ljc2LTExLjE4LTIuMTMtMS4zNS0zLjYzLS42LTMuMTMgMi4yLjUgMi43OSA5LjQzIDkuNTUgOC41NiAxMS0uODcgMS40Ny0zLjkzLTEuNzEtMy45My0xLjcxcy05LjU3LTguNzEtMTEuNjYtNi40NGMtMi4wOCAyLjI3IDEuNTkgNC4xNyA2LjggNy4zMyA1LjIzIDMuMTYgNS42NCA0IDQuOSA1LjItLjc1IDEuMi0xMi4yOC04LjUzLTEzLjM2LTQuNC0xLjA4IDQuMTEgMTEuNzcgNS4zIDEwLjk4IDguMTUtLjggMi44NS05LjA2LTUuMzgtMTAuNzQtMi4xOC0xLjcgMy4yMSAxMS42NSA2Ljk4IDExLjc2IDcuMDEgNC4zIDEuMTIgMTUuMjUgMy40OSAxOS4wOC0yLjEyWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiNGRjlEMEIiCgkJZD0iTTc3LjQgNDhjMS42MiAwIDMuMDcuNjYgNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMSAxLjMzIDMuNzYgNy4xIDcuMSAwIDAgMSAxLjk1LS4zYzEuNTUgMCAyLjk1LjU5IDMuOTQgMS42NmE1LjggNS44IDAgMCAxIC44IDcgNS4zIDUuMyAwIDAgMSAxLjc4IDIuODJjLjI0LjkuNDggMi44LS44IDQuNzRhNS4yMiA1LjIyIDAgMCAxIC4zNyA1LjAyYy0xLjAyIDIuMzItMy41NyA0LjE0LTguNTEgNi4xLTMuMDggMS4yMi01LjkgMi01LjkyIDIuMDFhNDQuMzMgNDQuMzMgMCAwIDEtMTAuOTMgMS42Yy01Ljg2IDAtMTAuMDUtMS44LTEyLjQ2LTUuMzQtMy44OC01LjY5LTMuMzMtMTAuOSAxLjctMTUuOTIgMi43OC0yLjc4IDQuNjMtNi44NyA1LjAxLTcuNzcuNzgtMi42NiAyLjgzLTUuNjIgNi4yNC01LjYyYTUuNyA1LjcgMCAwIDEgNC42IDIuNDZjMS0xLjI2IDEuOTgtMi4yNSAyLjg3LTIuODJBNy40IDcuNCAwIDAgMSA3Ny40IDQ4Wm0wIDRjLS41MSAwLTEuMTMuMjItMS44Mi42NS0yLjEzIDEuMzYtNi4yNSA4LjQzLTcuNzYgMTEuMThhMi40MyAyLjQzIDAgMCAxLTIuMTQgMS4zMWMtMS41NCAwLTIuNzUtMS41My0uMTQtMy40OCAzLjkxLTIuOTMgMi41NC03LjcyLjY3LTguMDFhMS41NCAxLjU0IDAgMCAwLS4yNC0uMDJjLTEuNyAwLTIuNDUgMi45My0yLjQ1IDIuOTNzLTIuMiA1LjUyLTUuOTcgOS4zYy0zLjc4IDMuNzctMy45OCA2LjgtMS4yMiAxMC44MyAxLjg3IDIuNzUgNS40NyAzLjU4IDkuMTUgMy41OCAzLjgyIDAgNy43My0uOSA5LjkzLTEuNDYuMS0uMDMgMTMuNDUtMy44IDExLjc2LTctLjI5LS41NC0uNzUtLjc2LTEuMzQtLjc2LTIuMzggMC02LjcxIDMuNTQtOC41NyAzLjU0LS40MiAwLS43MS0uMTctLjgzLS42LS44LTIuODUgMTIuMDUtNC4wNSAxMC45Ny04LjE3LS4xOS0uNzMtLjctMS4wMi0xLjQ0LTEuMDItMy4xNCAwLTEwLjIgNS41My0xMS42OCA1LjUzLS4xIDAtLjE5LS4wMy0uMjMtLjEtLjc0LTEuMi0uMzQtMi4wNCA0Ljg4LTUuMiA1LjIzLTMuMTYgOC45LTUuMDYgNi44LTcuMzMtLjIzLS4yNi0uNTctLjM4LS45OC0uMzgtMy4xOCAwLTEwLjY3IDYuODItMTAuNjcgNi44MnMtMi4wMiAyLjEtMy4yNCAyLjFhLjc0Ljc0IDAgMCAxLS42OC0uMzhjLS44Ny0xLjQ2IDguMDUtOC4yMiA4LjU1LTExLjAxLjM0LTEuOS0uMjQtMi44NS0xLjMxLTIuODVaIgoJLz4KCTxwYXRoCgkJZmlsbD0iI0ZGRDIxRSIKCQlkPSJNNTYuMzMgNzYuNjljLTIuNzUtNC4wNC0yLjU2LTcuMDcgMS4yMi0xMC44NCAzLjc3LTMuNzcgNS45Ny05LjMgNS45Ny05LjNzLjgyLTMuMiAyLjctMi45YzEuODYuMyAzLjIzIDUuMDgtLjY4IDguMDEtMy45MiAyLjkzLjc4IDQuOTIgMi4yOCAyLjE3IDEuNTEtMi43NSA1LjYzLTkuODIgNy43Ni0xMS4xOCAyLjEzLTEuMzUgMy42NC0uNiAzLjEzIDIuMi0uNSAyLjc5LTkuNDIgOS41NS04LjU1IDExIC44NiAxLjQ3IDMuOTItMS43MSAzLjkyLTEuNzFzOS41OC04LjcxIDExLjY2LTYuNDRjMi4wOCAyLjI3LTEuNTggNC4xNy02LjggNy4zMy01LjIzIDMuMTYtNS42MyA0LTQuOSA1LjIuNzUgMS4yIDEyLjI4LTguNTMgMTMuMzYtNC40IDEuMDggNC4xMS0xMS43NiA1LjMtMTAuOTcgOC4xNS44IDIuODUgOS4wNS01LjM4IDEwLjc0LTIuMTggMS42OSAzLjIxLTExLjY1IDYuOTgtMTEuNzYgNy4wMS00LjMxIDEuMTItMTUuMjYgMy40OS0xOS4wOC0yLjEyWiIKCS8+Cjwvc3ZnPgo=";
function hubGroupId(type) {
return "ws-hub-" + String(type).toLowerCase().replace(/[^a-z0-9]+/g, "-");
}
const HUB_REF_GROUP_ORDER = [
"Jobs",
"Datasets",
"Models",
"Spaces",
"Buckets",
"Collections",
"Papers",
];
function hubRefFromRepoRef(ref) {
if (!ref || !ref.repo_id || !ref.repo_url) return null;
if (ref.repo_type === "dataset") {
return { url: ref.repo_url, type: "Datasets", label: ref.repo_id };
}
if (ref.repo_type === "bucket") {
return { url: ref.repo_url, type: "Buckets", label: ref.repo_id };
}
return null;
}
async function publicAssociatedHubRefs() {
const refs = [MANIFEST.traces_ref, MANIFEST.workspace_ref].filter(Boolean);
const publicStates = await Promise.all(refs.map(probeRepoAccessible));
return refs
.filter((ref, index) => publicStates[index])
.map(hubRefFromRepoRef)
.filter(Boolean);
}
function mergeHubRefs(...groups) {
const merged = [];
const seen = new Set();
groups.flat().forEach((ref) => {
if (!validHubRef(ref)) return;
const key = `${ref.type || "Other"}:${ref.label || ref.url}`;
if (seen.has(key)) return;
seen.add(key);
merged.push(ref);
});
return merged;
}
function validHubRef(ref) {
if (!ref || !ref.url) return false;
if (classifyResource(ref.url)) return true;
const match = ref.url.match(/huggingface\.co\/collections\/([^/?#]+\/[^/?#]+)/);
return Boolean(match && validHfRepoId(match[1].split("/")));
}
function renderHubRefs(refs) {
const validRefs = Array.isArray(refs) ? refs.filter(validHubRef) : [];
if (!validRefs.length) return null;
const section = document.createElement("section");
section.className = "workspace-hub";
const heading = document.createElement("h2");
heading.className = "workspace-hub-title";
const hubLogo = document.createElement("img");
hubLogo.className = "workspace-hub-logo";
hubLogo.src = HF_LOGO_DATA_URI;
hubLogo.alt = "";
hubLogo.setAttribute("aria-hidden", "true");
heading.appendChild(hubLogo);
heading.appendChild(document.createTextNode("Hugging Face artifacts"));
section.appendChild(heading);
const byType = new Map();
validRefs.forEach((ref) => {
const type = ref.type || "Other";
if (!byType.has(type)) byType.set(type, []);
byType.get(type).push(ref);
});
const order = [
...HUB_REF_GROUP_ORDER,
...Array.from(byType.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
];
order.forEach((type) => {
const items = byType.get(type);
if (!items || !items.length) return;
const group = document.createElement("div");
group.className = "workspace-hub-group";
group.id = hubGroupId(type);
const gh = document.createElement("h3");
gh.className = "workspace-hub-group-head";
const label = document.createElement("span");
label.textContent = type;
const count = document.createElement("span");
count.className = "workspace-hub-count";
count.textContent = String(items.length);
gh.appendChild(label);
gh.appendChild(count);
group.appendChild(gh);
const list = document.createElement("div");
list.className = "workspace-hub-list";
items.forEach((ref) => {
const link = document.createElement("a");
link.className = "workspace-hub-link";
link.href = ref.url;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.textContent = ref.label || ref.url;
link.title = ref.url;
list.appendChild(link);
});
group.appendChild(list);
section.appendChild(group);
});
return section;
}
function workspaceSidebarEntries(files, hubRefs) {
const entries = [];
if (files && files.length) entries.push({ id: "ws-files", label: "Files" });
const counts = new Map();
(Array.isArray(hubRefs) ? hubRefs : []).filter(validHubRef).forEach((ref) => {
const type = ref.type || "Other";
counts.set(type, (counts.get(type) || 0) + 1);
});
const order = [
...HUB_REF_GROUP_ORDER,
...Array.from(counts.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
];
order.forEach((type) => {
if (counts.get(type)) entries.push({ id: hubGroupId(type), label: type });
});
return entries;
}
function buildWorkspaceSidebar(entries) {
const tree = document.getElementById("tree");
tree.innerHTML = "";
if (!entries || !entries.length) return;
const label = document.createElement("div");
label.className = "tree-label";
label.textContent = "Sections";
tree.appendChild(label);
entries.forEach((entry) => {
const a = document.createElement("a");
a.href = "#/view/workspace";
a.className = "depth-0";
a.dataset.section = entry.id;
const mark = document.createElement("span");
mark.className = "tree-mark";
mark.textContent = "§";
a.appendChild(mark);
a.appendChild(document.createTextNode(" " + entry.label));
a.addEventListener("click", (event) => {
event.preventDefault();
const target = document.getElementById(entry.id);
if (!target) return;
target.scrollIntoView({ behavior: "smooth", block: "start" });
tree
.querySelectorAll("a")
.forEach((link) => link.classList.toggle("active", link === a));
});
tree.appendChild(a);
});
}
async function renderWorkspace(renderId) {
const page = document.getElementById("page");
page.innerHTML = "";
page.className = "workspace-page";
const loading = document.createElement("div");
loading.className = "view-loading";
loading.textContent = "Loading workspace…";
page.appendChild(loading);
let workspace;
try {
workspace = await fetchData((MANIFEST.workspace || {}).file || "workspace.json");
} catch (error) {
if (renderId !== RENDER_SEQUENCE) return;
page.innerHTML = "";
page.appendChild(emptyView("Workspace unavailable", "The workspace inventory could not be loaded."));
return;
}
if (renderId !== RENDER_SEQUENCE) return;
page.innerHTML = "";
const associatedHubRefs = await publicAssociatedHubRefs();
if (renderId !== RENDER_SEQUENCE) return;
const hubRefs = mergeHubRefs(workspace.hub_refs || [], associatedHubRefs);
const shell = document.createElement("div");
shell.className = "workspace-shell";
const header = document.createElement("header");
header.className = "workspace-header";
const summary = document.createElement("p");
summary.textContent = `${workspace.file_count || 0} files · ${fmtBytes(workspace.total_size || 0)}`;
header.appendChild(summary);
const files = workspace.files || [];
if (files.length) {
const inventory = document.createElement("section");
inventory.className = "workspace-inventory";
inventory.id = "ws-files";
const renderInventory = (mode) => {
inventory.innerHTML = "";
if (mode === "type") renderWorkspaceByType(files, inventory);
else renderWorkspaceNode(workspaceTree(files), inventory);
};
const toggle = buildWorkspaceToggle(getWorkspaceMode(), (mode) => {
setWorkspaceMode(mode);
renderInventory(mode);
});
header.appendChild(toggle);
shell.appendChild(header);
shell.appendChild(inventory);
renderInventory(getWorkspaceMode());
} else if (MANIFEST.workspace_ref && MANIFEST.workspace_ref.repo_url) {
shell.appendChild(header);
await renderRepoReference(
MANIFEST.workspace_ref,
"workspace",
shell,
renderId
);
if (renderId !== RENDER_SEQUENCE) return;
} else {
shell.appendChild(header);
shell.appendChild(
emptyView(
"No workspace files captured yet",
"Supported model and data files appear here as they are created or changed after a trace is attached. Outputs captured by trackio logbook run appear when the run finishes; logged Trackio artifacts appear immediately in the Logbook tab. Files stay local until you choose to publish."
)
);
}
const hub = renderHubRefs(hubRefs);
if (hub) shell.appendChild(hub);
page.appendChild(shell);
buildWorkspaceSidebar(workspaceSidebarEntries(files, hubRefs));
window.scrollTo({ top: 0, behavior: "auto" });
}
async function renderCurrentView(opts = {}) {
const route = routeState();
const renderId = ++RENDER_SEQUENCE;
setActiveView(route);
if (route.view === "trace") {
await renderTrace(route, renderId);
} else if (route.view === "workspace") {
await renderWorkspace(renderId);
} else {
document.getElementById("page").className = "code-page";
await renderLogbook({ ...opts, renderId });
}
}
function handleRouteChange() {
const route = routeState();
if (
route.view === "code" &&
CURRENT_VIEW === "code" &&
document.querySelector("#page .page-section")
) {
updateViewTabs(route);
scrollToHash();
return;
}
if (
route.view === "trace" &&
CURRENT_VIEW === "trace" &&
document.querySelector("#page .trace-session")
) {
setActiveView(route);
const sessions = MANIFEST.traces || [];
const activeSessionId = route.sessionId || (sessions[0] || {}).id;
ensureTraceSessionLoaded(activeSessionId);
scrollToTraceSession(activeSessionId);
return;
}
renderCurrentView();
}
function currentSlug() {
const route = routeState();
return route.view === "code" ? route.slug : MANIFEST.root.slug;
}
function scrollToHash(opts = {}) {
if (routeState().view !== "code") return;
const slug = currentSlug();
if (!location.hash || slug === MANIFEST.root.slug) {
window.scrollTo({ top: 0, behavior: opts.behavior || "auto" });
highlight(slug);
return;
}
const section = document.getElementById("/" + slug);
if (section) section.scrollIntoView({ behavior: opts.behavior || "smooth" });
highlight(slug);
}
function navigateToLogbookSlug(target) {
const slug = String(target || "").replace(/^#?\//, "").trim();
if (!slug || !findNode(MANIFEST.root, slug)) return;
const hash = "#/view/code/" + slug;
if (location.hash === hash) {
scrollToHash({ behavior: "smooth" });
} else {
location.hash = hash;
}
}
function setupFigureNavigation() {
window.addEventListener("message", (event) => {
const data = event.data;
if (!data || data.type !== "trackio-logbook:navigate") return;
// Only accept messages from one of this logbook's sandboxed figure
// iframes, rather than from an arbitrary same-origin page.
const isFigureFrame = Array.from(
document.querySelectorAll("iframe.figure-frame")
).some((frame) => frame.contentWindow === event.source);
if (!isFigureFrame) return;
navigateToLogbookSlug(data.target);
});
}
let SCROLL_FRAME = 0;
function updateActiveSection() {
if (CURRENT_VIEW !== "code" && CURRENT_VIEW !== "trace") return;
cancelAnimationFrame(SCROLL_FRAME);
SCROLL_FRAME = requestAnimationFrame(() => {
const selector =
CURRENT_VIEW === "trace" ? ".trace-session" : ".page-section";
const sections = Array.from(document.querySelectorAll(selector));
if (!sections.length) return;
const marker = Math.min(window.innerHeight * 0.28, 180);
let active = sections[0];
sections.forEach((section) => {
if (section.getBoundingClientRect().top <= marker) active = section;
});
if (
window.innerHeight + window.scrollY >=
document.documentElement.scrollHeight - 2
) {
active = sections[sections.length - 1];
}
if (CURRENT_VIEW === "trace") {
highlightTraceSession(active.dataset.sessionId);
} else {
highlight(active.dataset.slug);
}
});
}
function startLiveReload() {
if (!isLocalPreview()) return;
setInterval(async () => {
try {
const next = await fetchManifest();
if (!next || next.revision === MANIFEST.revision) return;
MANIFEST = next;
clearPageCache();
document.title = MANIFEST.title + " · Trackio Logbook";
document.getElementById("book-title").textContent = MANIFEST.title;
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
buildTree();
renderCurrentView({ preserveScroll: true });
} catch (e) {}
}, LIVE_RELOAD_MS);
}
function setupConnect() {
const space = MANIFEST.space_id;
if (!space) return;
const steps = [
{ t: "Install Trackio, if you don't have it yet.", c: "uv tool install trackio" },
{ t: "Add the Trackio skill for your agent, then reload it.", c: "trackio skills add" },
{ t: "Connect to this logbook.", c: `trackio logbook open ${space}` },
];
const ol = document.getElementById("connect-steps");
steps.forEach((s, i) => {
const li = document.createElement("li");
const title = document.createElement("div");
title.className = "step-title";
title.textContent = `${i + 1}. ${s.t}`;
const block = document.createElement("div");
block.className = "codeblock";
const code = document.createElement("code");
code.textContent = s.c;
const copy = document.createElement("button");
copy.className = "copy";
copy.type = "button";
copy.title = "Copy";
copy.textContent = "⧉";
copy.addEventListener("click", () => copyText(s.c, copy, "⧉"));
block.appendChild(code);
block.appendChild(copy);
li.appendChild(title);
li.appendChild(block);
ol.appendChild(li);
});
const agentPrompt =
`Read and help maintain this Trackio experiment logbook ("${MANIFEST.title}").\n\n` +
"1. If you don't have Trackio, install it: uv tool install trackio\n" +
"2. Add the Trackio skill for your agent: trackio skills add (then reload)\n" +
`3. Connect to this logbook: trackio logbook open ${space}\n\n` +
"Start with `trackio logbook read`; use `trackio logbook read page \"...\"` " +
"for a page-level view, then fetch relevant details with " +
"`trackio logbook read cell cell_<id>`. If I've given you " +
'write access to the Space, add findings with `trackio logbook cell markdown "..." ' +
'--page "..."` and they will sync back automatically.';
const foot = document.getElementById("sidebar-foot");
foot.hidden = false;
const modal = document.getElementById("modal");
const open = () => (modal.hidden = false);
const close = () => (modal.hidden = true);
document.getElementById("connect-btn").addEventListener("click", open);
document.getElementById("modal-close").addEventListener("click", close);
modal.querySelector(".modal-backdrop").addEventListener("click", close);
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") close();
});
const agentBtn = document.getElementById("copy-agent");
agentBtn.addEventListener("click", () =>
copyText(agentPrompt, agentBtn, "Copy for agent")
);
}
function copyText(text, btn, restore) {
const done = () => {
const prev = btn.textContent;
btn.textContent = restore === "⧉" ? "✓" : "Copied!";
btn.classList.add("copied");
setTimeout(() => {
btn.textContent = restore;
btn.classList.remove("copied");
}, 1400);
void prev;
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(done, done);
} else {
const ta = document.createElement("textarea");
ta.value = text;
document.body.appendChild(ta);
ta.select();
try {
document.execCommand("copy");
} catch (e) {}
document.body.removeChild(ta);
done();
}
}
async function init() {
MANIFEST = await fetchManifest();
document.title = MANIFEST.title + " · Trackio Logbook";
document.getElementById("book-title").textContent = MANIFEST.title;
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
document.getElementById("book-head").addEventListener("click", () => {
const target = "#/view/code/" + MANIFEST.root.slug;
if (location.hash === target) scrollToHash();
else location.hash = target;
});
buildTree();
setupConnect();
setupFigureNavigation();
window.addEventListener("hashchange", handleRouteChange);
window.addEventListener("scroll", updateActiveSection, { passive: true });
await renderCurrentView();
startLiveReload();
}
init();
})();