--- title: Progress --- ```js import {POLL_HEAVY, apiFetch, pollDelay, waitForVisible} from "./components/config.js"; ``` ```js const progState = (async function*() { let failures = 0; while (true) { let data = [], tokenEvents = [], ok = false; try { const [r1, r2] = await Promise.all([ apiFetch("/progress/?limit=500"), apiFetch("/token-events/?limit=1000"), ]); ok = r1.ok; data = ok ? await r1.json() : []; tokenEvents = r2.ok ? await r2.json() : []; } catch {} failures = ok ? 0 : failures + 1; yield {data, tokenEvents, ok, ts: new Date()}; await waitForVisible(pollDelay({ok, base: POLL_HEAVY, failures})); } })(); ``` ```js const data = progState.data ?? []; const tokenEvents = progState.tokenEvents ?? []; const _ok = progState.ok ?? false; const _ts = progState.ts; ``` # Progress Log ```js import {injectTocTop} from "./components/toc-sidebar.js"; import {withDocHelp} from "./components/doc-overlay.js"; const _liveEl = html`
make api`}
No events in the last 30 days.
` : Plot.plot({ title: "Progress events & tokens per day (30-day window)", x: {label: "Date", tickRotate: -30}, y: {label: "← Events", grid: true}, marginBottom: 60, marginRight: tokensByDay.length > 0 ? 70 : 20, width: 750, marks: [ Plot.areaY(byDay, {x: "day", y: "count", fill: "steelblue", fillOpacity: 0.25}), Plot.lineY(byDay, {x: "day", y: "count", stroke: "steelblue", strokeWidth: 1.5}), Plot.tip(byDay, Plot.pointerX({x: "day", y: "count", title: d => `${d.day}\n${d.count} event${d.count === 1 ? "" : "s"}`})), ...(tokensByDay.length > 0 ? [ Plot.areaY(tokensByDay, {x: "day", y: d => d.tokens / ratio, fill: "#f28e2b", fillOpacity: 0.2}), Plot.lineY(tokensByDay, {x: "day", y: d => d.tokens / ratio, stroke: "#f28e2b", strokeWidth: 1.5}), Plot.tip(tokensByDay, Plot.pointerX({x: "day", y: d => d.tokens / ratio, title: d => `${d.day}\n${d.tokens.toLocaleString()} tokens`})), Plot.axisY({anchor: "right", label: "Tokens →", tickFormat: fmtTokens}), ] : []), Plot.ruleY([0]), ], }) ); if (byDay.length > 0) display(html`${filtered.length} events shown (append-only, no deletions).
`); display(Inputs.table(filtered.map(e => ({ Time: new Date(e.created_at).toLocaleString(), Type: e.event_type, Author: e.author ?? "—", Summary: e.summary, })), {rows: 50})); ```