mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-03 21:35:13 +00:00
5 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
dbd93fee51
|
app,dash: render pre-history days as no data, not a currency zero (#765)
* fix(app,dash): render pre-history days as no data, not a currency zero Days before the first recorded day in history.daily were painted as a real 0.00/0 calls in the daily activity heatmap and the daily spend charts. That zero is unknown, not measured, so those cells and bars now read "No data recorded" instead of a currency zero. Genuinely idle days within recorded history stay as real zeros. - app: heatmap cells, the daily spend bars, and the daily-by-model columns get a distinct no-data style plus a "No data recorded" hover for days before the first recorded day. - dash: the granular line chart drops buckets before the first recorded day so no flat zero line is drawn before any history exists. - data-start is derived in the UI layer from history.daily; payload shape is unchanged. Verified: app vitest 418 pass (7 new for the no-data behavior); app, dash, and root typecheck clean; dash and app renderer vite builds succeed. * no-data: cap guard, timezone-free dash trim, StackedBars aria Three hardening fixes from adversarial review of the no-data rendering: dataStartKey returns null at the payload's 365-entry history cap, where the oldest retained entry is no longer the true data start; classifying past it would label real aged-out history as no data on long custom ranges. Documented that the install-to-first-use gap reading as no data is literally accurate: nothing was recorded then either. The dash granular chart now trims leading zero-only buckets by value instead of comparing bucket timestamps against date keys, so producer and viewer timezone skew can never drop a real first-day bucket, and an all-zero series lands in the established empty state. StackedBars no-data columns expose their state via aria-label, not only a title on a non-focusable div. |
||
|
|
5d366fb03b
|
feat(dashboard): add granular session and model timelines (#673)
* feat(dashboard): add granular usage timelines * fix(dashboard): readable timeline legend and month-scale buckets Session legend labels now use the real projectPath's last two segments (app/web) instead of the sanitized project dir, which rendered as an unreadable -Users-name-... dump and truncated in the legend. Hourly buckets now cap at 8 days; longer ranges bucket daily. A 30-day window rendered 720 overlapping hourly spikes, unreadable as a chart. The browser no longer gives the backend session_other/model_other aggregate a top-N slot, which rendered two identical Other legend entries whenever the backend fold out-ranked a real series. --------- Co-authored-by: AgentSeal <hello@agentseal.org> |
||
|
|
9b20dfd7dc
|
feat(context): per-session context token tree across CLI, TUI, and dashboard (#592)
* feat(context): add experimental context command with per-session token tree Reconstructs context breakdown for a Claude Code session from its transcript: messages and tokens by role, block type, and tool, split into full-session history vs the live window since the last compaction (following preservedSegment.headUuid). Block tokens are chars/4 estimates, images estimated from sniffed PNG or JPEG dimensions, reasoning derived per message from output_tokens minus visible output since transcripts strip thinking text. The exact context size comes from the last assistant message's API usage, and the gap to the estimate is shown as derived system prompt and tool overhead. * feat(context): show session titles in context --list Reads the latest ai-title entry (summary entry as fallback for older sessions) from one tail and one head chunk of each transcript, so the list stays fast on 100MB files. * feat(dash): context explorer page with Claude Code and Codex session trees Adds a Context page to the web dashboard: a navbar toggle, a provider picker (Claude Code / Codex), the 15 most recent sessions with titles, and per-session expandable details showing the context token tree, the exact live context vs window, and a live/full-history scope toggle. Server side adds /api/context/sessions and /api/context/tree with an mtime-keyed tree cache, plus a Codex rollout builder: response items feed the tree, compacted entries (with replacement_history) split live window from full history, reasoning comes exact from cumulative token_count totals, and model_context_window gives the real window. * feat(context): interactive TUI for the context command codeburn context with no arguments now opens an ink TUI: arrow keys to move, enter to expand a session's token tree inline (with a spinner while the transcript reads), tab to switch between Claude Code and Codex, f to toggle live window vs full history, q to quit. Flag and id forms keep the plain output for scripts, and non-TTY runs fall back to the static list. Tree rows are shared with the static renderer via snapshotRows. * fix(context): review fixes across window detection, codex parsing, and surfaces Window sizes are no longer guessed from token counts alone: opus-4-8 and [1m] model ids map to the 1M window (a 190K opus-4-8 session used to render as 95% of a 200K window), and Codex omits the percentage instead of borrowing Anthropic constants when the rollout lacks model_context_window. Codex compaction accounting now reads the encrypted compaction item and developer messages from replacement_history, so post-compaction windows stop undercounting. Both builders stream with largeLineAsBuffer so one oversized line cannot silently truncate the walk. The tree API stops sending session.filePath, serves the flattened rows so the dash renders the same tree as the CLI and TUI, resolves ids directly instead of re-scanning every session file per request, and the tree cache evicts LRU. Session discovery honors CLAUDE_CONFIG_DIRS, CLAUDE_CONFIG_DIR, and CODEX_HOME, stats files in parallel, and id lookups stat only matching files. CLI gains --provider codex and machine-readable --list --json; --full now opens the TUI in full scope instead of bypassing it. The TUI shows build errors instead of a frozen spinner and drops the ref-plus-counter repaint for plain state. The dashboard scopes the usage error banner and device sidebar to the Usage page. |
||
|
|
1dba4e0aa4
|
feat(web): in-dashboard device discovery, share-from-browser, redesign + hardening (#534)
* feat(web): device discovery + pairing endpoints for the dashboard Add /api/identity, /api/devices/scan (mDNS browse with confirm code and paired status), and /api/devices/pair (approve-style pairing via linkRemote). Backs the Search local devices button so pairing can happen from the browser instead of the CLI. * feat(web): two-panel dashboard with eywa-inspired warm theme Redesign the dashboard into a left sidebar (device switcher + Search local devices) and a right content panel, restyled to a warm-paper, forest-green archival theme (serif display numbers, ink text, hairline borders) in place of the dark midnight theme. The Search local devices modal discovers nearby devices over mDNS and pairs in one click (approve on the other device), backed by /api/devices/scan and /api/devices/pair. * feat(web): use the CodeBurn flame logo in the dashboard header Replace the placeholder triangle with the flame mark (the repo's codeburn-symbolic vector), tinted the theme's forest green, and set the same flame as the favicon. * feat(web): color the All-devices chart by device, add task-level combined views In the All devices view the daily chart now stacks by device (one color per device) instead of by model, and the combined panels add a By task breakdown plus in/out token detail. Devices that cannot be reached are hidden entirely rather than shown as error rows. * feat(web): use the flame image as the dashboard logo and favicon Replace the inline vector flame with the brand flame PNG (public/codeburn-flame.png) in the header and as the favicon. * fix(web): trim flame logo padding and tighten brand spacing Crop the transparent border off the flame PNG (it was 184px of padding each side) and reduce the header gap so the mark sits close to the wordmark. * feat(web): cost/tokens toggle, cache read/write, full feature panels Add a Cost/Tokens unit toggle that switches the hero number and the chart between dollars and tokens. Surface cache write/read token totals as metric cards. Add per-device panels for subagents, skills, MCP servers, and a savings / retry-tax / routing-waste summary. The combined view gains cache totals and the unit toggle too. * feat(web): use CodeBurn website logos and add community links Use the website's navbar flame (logo.png) with the Code+Burn wordmark in the header, and the three-flame app icon (icon.png) as the favicon. Add Website, Discord, and X links to the sidebar footer. * fix(web): use the single-flame logo for the favicon too The three-flame icon was wrong for the tab; use the same single flame as the navbar everywhere and drop the unused three-flame asset. * chore(web): set dashboard title to CodeBurn - Local Dashboard * harden sharing + dashboard for public launch Security: - pairing: cap PIN attempts (close window after 5 wrong guesses) so a 6-digit PIN cannot be brute-forced within the TTL on a 0.0.0.0 listener. - web dashboard: reject non-loopback Host (defeats DNS rebinding that could read unsanitized local usage) and cross-origin requests (CSRF); require application/json on the pair endpoint. - store tokens with 0600 perms (was world-readable), 0700 dir. Robustness: - client: per-request timeout so a hung/asleep peer cannot hang a pull; pullDevices fetches remotes concurrently and isolates failures. - dashboard: normalize peer payloads at the boundary and add an error boundary so a peer on a different version cannot white-screen the SPA; finite-guard fmtNum/compactUsd. Tests: PIN attempt-cap test added (1269 pass). * feat(web): share this device from the dashboard, with browser approval Add a Share this device toggle to the dashboard sidebar. It runs the secure share server in-process (mTLS + mDNS advertise) so no terminal is needed, with a Keep sharing always option (persisted; otherwise it stops after idle). Incoming approve-style pairings are queued and surfaced in the browser as an Approve/Deny prompt with the matching code, instead of a terminal prompt. The shared payload is sanitized; start degrades gracefully if the port is already held by a CLI share. * fix(sharing): keep a paired device from dropping on a transient pull - client: 8s -> 15s timeout and a fresh socket per request (agent:false) so the pinned-fingerprint check always reads this connection's cert. - share server: wrap request handling so a getUsage error returns a fast 500 instead of hanging the caller (which times out and drops the device). - dashboard: re-pull paired devices every 20s so a brief drop self-heals instead of staying gone until you change tabs. * fix(sharing): re-sanitize remote payloads on receipt A peer might run an older build that does not strip its own project names/sessions. Sanitize every remote payload when we receive it too, so project names never cross into our dashboard regardless of the sender's version. Aggregate numbers (cost, tokens, models, tools, daily) are kept. * harden dashboard sharing: version-skew, lifecycle, server errors - normalize remote daily-history entries so a peer on an older build (daily rows missing topModels) can no longer crash the chart / brick the page. - ShareController: commit always/sharing state only after listen() binds, so a port-in-use start no longer reports sharing when it is not. - attach durable error/tlsClientError handlers to both HTTPS servers so a malformed peer connection cannot crash the process. - reset view/provider selection when the viewed device disappears or lacks the selected provider (no more empty/no-selection state on sleep-wake). - by-device chart: stable per-device color/key so bars do not reshuffle when a device drops or returns between polls. * polish: device identity, approval guard, queue cap, formatting - give each device a stable unique id (cert fingerprint for remotes, 'local' for this device); key the sidebar, selection, and by-device chart by id so two devices sharing a hostname no longer collide. - approval prompt: drop a request from the UI the moment it is answered so it cannot be double-clicked. - share controller: cap concurrent pending approvals and allow only one per device, so a LAN peer cannot flood the prompt. - usd(): render negatives as -$5.00, consistent with compactUsd. |
||
|
|
2d44aeaedb
|
feat(web): local React dashboard served by codeburn web (#531)
Add a Vite + React 19 + Tailwind v4 + Recharts SPA (dash/) and a 'web' command that serves the built UI plus a local /api/usage endpoint backed by the existing menubar aggregation. Midnight theme with CodeBurn's orange chart ramp: hero cost, a stacked-by-model daily bar chart with a custom tooltip and hover-dim, metric cards, by-tool and by-activity bar lists, and top-projects and tools tables. Period and provider filters, react-query with skeleton loading. Stays 100% local. build:dash builds the SPA into dist/dash (shipped via package files, served at runtime); a missing build falls back to a helpful message. |