--- title: Token Cost --- ```js import {API} from "./components/config.js"; import {refCell} from "./components/ref-cell.js"; const POLL = 60_000; ``` ```js // Fetch token events, by-repo summary, workstreams, and tasks in parallel const tokenState = (async function*() { while (true) { let byRepo = [], events = [], wsMap = {}, taskMap = {}, ok = false; try { const [r1, r2, r3, r4] = await Promise.all([ fetch(`${API}/token-events/by-repo/`), fetch(`${API}/token-events/?limit=1000`), fetch(`${API}/workstreams/`), fetch(`${API}/tasks/`), ]); ok = r1.ok && r2.ok; if (ok) { byRepo = await r1.json(); events = await r2.json(); } if (r3.ok) { const wsList = await r3.json(); for (const w of wsList) wsMap[w.id] = w; } if (r4.ok) { const taskList = await r4.json(); for (const t of taskList) taskMap[t.id] = t; } } catch {} yield {byRepo, events, wsMap, taskMap, ok, ts: new Date()}; await new Promise(res => setTimeout(res, POLL)); } })(); ``` ```js // Resolve an event's repo_id via the 3-level chain: direct → workstream → task→workstream function resolveRepoId(e, wsMap, taskMap) { if (e.repo_id) return e.repo_id; const wsId = e.workstream_id ?? taskMap[e.task_id]?.workstream_id; return wsId ? (wsMap[wsId]?.repo_id ?? null) : null; } function buildSummary(events) { const byWs = {}, byModel = {}, byTask = {}; for (const e of events) { const tot = (e.tokens_in || 0) + (e.tokens_out || 0); if (e.workstream_id) { byWs[e.workstream_id] = byWs[e.workstream_id] || {scope_id: e.workstream_id, tokens_in: 0, tokens_out: 0, event_count: 0}; byWs[e.workstream_id].tokens_in += e.tokens_in || 0; byWs[e.workstream_id].tokens_out += e.tokens_out || 0; byWs[e.workstream_id].event_count++; } const model = e.model || "unknown"; byModel[model] = (byModel[model] || 0) + tot; if (e.task_id) { byTask[e.task_id] = byTask[e.task_id] || {task_id: e.task_id, tokens_in: 0, tokens_out: 0, event_count: 0}; byTask[e.task_id].tokens_in += e.tokens_in || 0; byTask[e.task_id].tokens_out += e.tokens_out || 0; byTask[e.task_id].event_count++; } } const toRows = obj => Object.values(obj) .map(v => ({...v, tokens_total: (v.tokens_in || 0) + (v.tokens_out || 0)})) .sort((a, b) => b.tokens_total - a.tokens_total); return { by_workstream: toRows(byWs), by_model: Object.entries(byModel) .map(([model, tokens_total]) => ({model, tokens_total})) .sort((a, b) => b.tokens_total - a.tokens_total), top_tasks: toRows(byTask), total_events: events.length, }; } function nameCell(name, fullName) { const s = String(name ?? fullName ?? "—"); const full = String(fullName ?? name ?? "—"); const el = document.createElement("span"); el.title = full; el.textContent = s.length > 80 ? s.slice(0, 80) + "…" : s; return el; } function sortRows(rows, sortField) { if (sortField === "Tokens Total") return rows; // already sorted by buildSummary / by-repo API const s = [...rows]; if (sortField === "Tokens In") s.sort((a, b) => (b.tokens_in || 0) - (a.tokens_in || 0)); else if (sortField === "Tokens Out") s.sort((a, b) => (b.tokens_out || 0) - (a.tokens_out || 0)); else if (sortField === "Event Count") s.sort((a, b) => (b.event_count || 0) - (a.event_count || 0)); else if (sortField === "Most Recent") s.sort((a, b) => (b._lastAt || 0) - (a._lastAt || 0)); return s; } ``` ```js const byRepo = tokenState.byRepo ?? []; const events = tokenState.events ?? []; const wsMap = tokenState.wsMap ?? {}; const taskMap = tokenState.taskMap ?? {}; const _ok = tokenState.ok ?? false; const _ts = tokenState.ts; ``` # Token Cost ```js display(html`
● ${_ok ? `Live · ${_ts?.toLocaleTimeString()} · ${events.length} events` : "API offline"}
`); ``` ```js const repoSel = Inputs.select( ["All repos", ...byRepo.map(r => r.repo_slug)], {label: "Filter by repo"} ); const sortSel = Inputs.select( ["Tokens Total", "Tokens In", "Tokens Out", "Event Count", "Most Recent"], {label: "Sort by"} ); const maxSel = Inputs.select( [10, 20, 50, 100, 500], {value: 20, label: "Show"} ); display(html`
${repoSel}${sortSel}${maxSel}
`); const repoFilter = view(repoSel); const sortOrder = view(sortSel); const maxResults = view(maxSel); ``` ```js // Build filtered and last-event-annotated row sets const selectedRepoId = repoFilter === "All repos" ? null : (byRepo.find(r => r.repo_slug === repoFilter)?.repo_id ?? null); const filteredEvents = selectedRepoId ? events.filter(e => resolveRepoId(e, wsMap, taskMap) === selectedRepoId) : events; const lastAtByRepo = {}, lastAtByWs = {}, lastAtByTask = {}; for (const e of filteredEvents) { const t = e.created_at ? new Date(e.created_at).getTime() : 0; const rid = resolveRepoId(e, wsMap, taskMap); if (rid) lastAtByRepo[rid] = Math.max(lastAtByRepo[rid] || 0, t); if (e.workstream_id) lastAtByWs[e.workstream_id] = Math.max(lastAtByWs[e.workstream_id] || 0, t); if (e.task_id) lastAtByTask[e.task_id] = Math.max(lastAtByTask[e.task_id] || 0, t); } const filteredByRepo = (selectedRepoId ? byRepo.filter(r => r.repo_id === selectedRepoId) : byRepo ).map(r => ({...r, _lastAt: lastAtByRepo[r.repo_id] || 0})); const summary = buildSummary(filteredEvents); const wsRowsFull = summary.by_workstream.map(r => ({...r, _lastAt: lastAtByWs[r.scope_id] || 0})); const taskRowsFull = summary.top_tasks.map(r => ({...r, _lastAt: lastAtByTask[r.task_id] || 0})); ``` ## By Repo ```js { const sorted = sortRows(filteredByRepo, sortOrder); const total = sorted.length; const rows = sorted.slice(0, maxResults); if (rows.length === 0) { display(html`

No token events with repo association yet.

`); } else { display(Plot.plot({ title: "Token consumption by repo", marginLeft: 160, width: Math.min(900, width), x: {label: "Tokens", tickFormat: "~s"}, y: {label: null}, color: {legend: true, domain: ["tokens_in", "tokens_out"], range: ["#4e79a7","#f28e2b"]}, marks: [ Plot.barX( rows.flatMap(r => [ {repo: r.repo_slug, type: "tokens_in", value: r.tokens_in}, {repo: r.repo_slug, type: "tokens_out", value: r.tokens_out}, ]), {x: "value", y: "repo", fill: "type", tip: true} ), ], })); display(Inputs.table(rows.map((r, i) => ({...r, _ref: i})), { columns: ["_ref", "repo_slug", "tokens_in", "tokens_out", "tokens_total", "event_count"], header: { _ref: "REF", repo_slug: "Repo", tokens_in: "Tokens In", tokens_out: "Tokens Out", tokens_total: "Total", event_count: "Events", }, format: { _ref: (_, i) => refCell(i + 1, "repos", rows[i].repo_slug), repo_slug: d => nameCell(d, d), tokens_in: d => d.toLocaleString(), tokens_out: d => d.toLocaleString(), tokens_total: d => d.toLocaleString(), }, width: {_ref: 50, repo_slug: 160, tokens_in: 110, tokens_out: 110, tokens_total: 110, event_count: 80}, })); if (total > maxResults) display(html`

Showing ${maxResults} of ${total} repos

`); } } ``` ## By Workplan ```js { const sorted = sortRows(wsRowsFull, sortOrder); const total = sorted.length; const rows = sorted.slice(0, maxResults); if (rows.length === 0) { display(html`

No workstream data yet.

`); } else { display(Inputs.table(rows.map((r, i) => ({...r, _ref: i})), { columns: ["_ref", "scope_id", "tokens_in", "tokens_out", "tokens_total", "event_count"], header: { _ref: "REF", scope_id: "Workstream", tokens_in: "Tokens In", tokens_out: "Tokens Out", tokens_total: "Total", event_count: "Events", }, format: { _ref: (_, i) => refCell(i + 1, "workstreams", rows[i].scope_id), scope_id: d => { const ws = wsMap[d]; return nameCell(ws?.title ?? ws?.slug, d); }, tokens_in: d => d.toLocaleString(), tokens_out: d => d.toLocaleString(), tokens_total: d => d.toLocaleString(), }, width: {_ref: 50, scope_id: 200, tokens_in: 110, tokens_out: 110, tokens_total: 110, event_count: 80}, })); if (total > maxResults) display(html`

Showing ${maxResults} of ${total} workstreams

`); } } ``` ## By Model ```js if (summary.by_model.length === 0) { display(html`

No model data yet.

`); } else { display(Plot.plot({ title: "Token consumption by model", marginLeft: 200, width: Math.min(700, width), x: {label: "Total tokens", tickFormat: "~s"}, marks: [ Plot.barX(summary.by_model, {x: "tokens_total", y: "model", fill: "#4e79a7", tip: true}), ], })); } ``` ## Top Tasks by Tokens ```js { const sorted = sortRows(taskRowsFull, sortOrder); const total = sorted.length; const rows = sorted.slice(0, maxResults); if (rows.length === 0) { display(html`

No task-level data yet.

`); } else { display(Inputs.table(rows.map((r, i) => ({...r, _ref: i})), { columns: ["_ref", "task_id", "tokens_in", "tokens_out", "tokens_total"], header: {_ref: "REF", task_id: "Task", tokens_in: "In", tokens_out: "Out", tokens_total: "Total"}, format: { _ref: (_, i) => refCell(i + 1, "tasks", rows[i].task_id), task_id: d => { const task = taskMap[d]; return nameCell(task?.title, d); }, tokens_in: d => d.toLocaleString(), tokens_out: d => d.toLocaleString(), tokens_total: d => d.toLocaleString(), }, width: {_ref: 50, task_id: 240}, })); if (total > maxResults) display(html`

Showing ${maxResults} of ${total} tasks

`); } } ```