Whole-session resource timeline for the Resources drawer - #2185
simple-agent-manager[bot] merged 22 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: raphaeltm/simple-agent-manager/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
1 similar comment
|
@coderabbitai review |
|
@coderabbitai review |
Replace the chunk-at-a-time resource sparkline with a whole-session timeline prototype: - uPlot panels (CPU cores, memory used vs cache, disk, tool-call lane) sharing one x axis and crosshair, with reservation lines and OOM marks - level-of-detail data layer: the index draws the whole session, 5 s chunks load only when zoomed past the overview and are cached forever (chunks are immutable), so chunks never appear in the UI - sleeps between wake cycles compressed into labelled breaks (active-time axis) with a clock-time toggle - touch scrub with a fixed readout, pinch zoom, navigator strip with draggable window, range presets and a busiest-moments list - dev-only /prototype/resource-timeline route with synthetic sessions modelled on production ones and a proposed-vs-current backend switch Prototype branch: not for merge as-is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- uPlot hover only drives the cursor while a mouse is over the chart, so redraws and touch taps can no longer overwrite a pinned instant - sleeps compress logarithmically (a night reads longer than a pause); the navigator labels sleeps of an hour or more - finer tick steps, no clipped labels at the right edge, crowded ticks across a break dropped - compact per-panel values that fit beside the legend on a phone; MCP tool names shown as 'tool (server)', sub-second calls in ms - active time in view computed from runs, not sample coverage - navigator draws loaded detail where available - charts become one keyboard slider over time (arrows move, +/- zoom) - mock sessions: coordinator vs builder workloads; current-backend mode trims runs to returned chunks like the real adapter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Unit tests for the pure modules behind the prototype timeline: time-axis compression, round-trips and tick placement; level-of-detail bucketing (spike preservation, time-weighted means, gaps, disk rates, OOM counted once); summaries and peaks; the adapter over today's API (cores from CPU-ms, truncation detection, tool labels); view intents across axis modes; and readout wording at each zoom level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- the session tool-rail audit now opens Resources from the real rail button against today's /resource-history contract and asserts the whole-session readout, the OOM call-out, no chunk controls, and a keyboard-driven cursor reading - mock samples carry the collector's 5 s interval, and every chunk the view needs returns detail - adapter: when the server thinned a chunk, each kept sample stands for the time since the previous one (never across a sampler gap) and is no longer reported as an exact 5 s measurement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…llups Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…SQL engine Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pe route The drawer now reads /resource-timeline (every chunk, per-minute rollups, per-run reservations, collection state) and fetches 5 s chunks on zoom from /resource-timeline/chunks/:id. The prototype page and its mock data are gone; the stress scenarios live on as a Playwright fixture that serves real API shapes to the real chat rail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sion timeline Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ailure isolation Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imeline query - Pan, pinch, wheel and navigator drags apply at most one view change per animation frame; rapid wheel events build on the pending range. - The timeline index orders by started_at alone so the session index serves ORDER BY + LIMIT without sorting the session's whole history, and selects only the columns it returns. - The chunk route checks project access before validating the chunk id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…real timeline Touch runs through CDP touch events so pointer capture and pointerType behave as on a phone. The pinch test was verified to fail with pinch handling disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The prototype's lockfile update bumped @better-auth/utils to 0.5.0, which duplicated better-auth's core types and broke the api build (TS2742 in auth.ts). Regenerated from main's lockfile so uplot is the only change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment uPlot reports its cursor on redraws too, so with a mouse left over the chart (full-screen mobile drawer, or a desktop user reaching for the keyboard) the next data load reset the moment chosen with the arrow keys. Hover now drives the cursor only after the mouse moves again. Reproduced 4/6 on the 390px project in CI and locally; 8/8 after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7c1f706 to
af65f2f
Compare
|



Summary
The session Resources drawer showed one 15-minute storage chunk at a time and gave no information on hover or tap. Users could not tell they were looking at a thin slice of a session (Raphaël: "I was actually feeling a bit misled"). Older history past the newest 24 chunks was unreachable, and the stat cards described only the last wake.
This replaces it with a whole-session timeline that has no chunk UI:
workspace_resource_chunks.rollup_json, additive migration0177), computed on upload from the payload the upload path already decodes. A rollup failure never fails an upload.GET /api/projects/:id/sessions/:sessionId/resource-timelinereturns:runsper workspace, each with that workspace's reservation;omittedChunkCountpastWORKSPACE_RESOURCE_TIMELINE_MAX_CHUNKS, default 1000);collection, which says why an empty timeline is empty:unsupported(Instant),expired(samples past retention, summary remains) orpending.GET …/resource-timeline/chunks/:chunkIdreturns one chunk's 5-second samples, scoped to the project and session in the path (a foreign chunk returns 404).apps/web/src/components/chat/resource-timeline/)/prototype/resource-timelineroute, page and mock data are deleted. The seeded stress generator is now a Playwright fixture (apps/web/tests/playwright/resource-timeline-scenarios.ts) that serves real API shapes to the real chat rail.memoryWorkingSetBytes/memoryWorkingSetMeanBytes/memoryWorkingSetPeakBytes, the names on the still-open working-set branch, so that data appears once it lands.Idea
01M3P13H0W6EG1FS47PCG0N2EG. Task:tasks/active/2026-09-29-whole-session-resource-timeline.md.I/O budget (rule 60)
started_atalone soidx_workspace_resource_chunks_project_sessionserves ORDER BY + LIMIT without sorting the session's history (EXPLAIN QUERY PLANverified).Validation
pnpm lint: api and web clean. Web has 3 warnings, all in files this PR does not touch.pnpm typecheck: api and web, 0 errors.pnpm test:success: true(JSON reporter);Staging Verification (REQUIRED for all code changes — merge-blocking)
app.sammy.partyStaging Verification Evidence
0177_workspace_resource_chunk_rollups.sqlapplied 2026-09-29 10:18:17, androllup_jsonis present (D1 query).01KWHD8XS7MQ7R6KWXJYRHDVH4, sessioncbb7fed4…):200./resource-timeline*response was200.GET /api/workspaces/<deleted id>. They occur without opening Resources (verified separately) and are unrelated; filed astasks/backlog/2026-09-29-chat-page-404s-on-deleted-session-workspace.md.01M3PBHQCGR0RMTK5GQ6YQG197ran two CPU-busy loops on a VM workspace. Its chunk uploaded at 10:55Z through the deployed branch withrollup_jsonpresent (1,596 bytes, 181 samples).200).01M3PC194W66H7TDAXEMK5C1WCand node01M3PBHXT859K212KK8CBRCSM5were deleted; both rows are gone from D1.UI Compliance Checklist (Required for UI changes)
aria-valuetextreadouts, has arrow/+/-/0/Esc keys, and has labelled controls@simple-agent-manager/uiButton/Spinner and design tokens; charts are uPlot canvases themed from tokensassertNoOverflow).UI Screenshot Evidence
All screenshots were taken with Playwright (Chromium). Local ones drive the real chat rail against the scenario fixture; staging ones are the live app at
app.sammy.party.Surface: Session Resources drawer — whole-session timeline
Surface: Session Resources drawer — long history and older agents
acp_tool_callspans.Surface: Session Resources drawer — tool names in the readout
fetch <img src=x onerror=alert(1)> & "quotes" 🔥; an MCP tool name over 250 characters.assertNoClippedOverflow), so labels are now capped at 48 characters with an ellipsis. The hostile name renders as literal text and no<img>element is created.Surface: Session Resources drawer — empty states
cf-container) session, a VM session with nothing uploaded yet, and a session whose samples have passed retention.End-to-End Verification (Required for multi-component changes)
Data Flow Trace
POST /api/projects/:id/workspace-resource-history→storeWorkspaceResourceChunk(services/workspace-resource-history.ts) decodes and validates the gzip payload (validateWorkspaceResourceChunkBytes).buildStoredRollupJson→computeWorkspaceResourceRollup(services/workspace-resource-rollup.ts) →workspace_resource_chunks.rollup_json.SessionResourceHistoryDrawerlazy-loadsResourceTimeline→useResourceTimelineIndex→getSessionResourceTimeline(lib/api/resource-timeline.ts).GET …/resource-timeline→requireProjectAccess→getSessionResourceTimeline(services/workspace-resource-timeline.ts): chunk query,loadRunWorkspaces(reservations), andloadSessionRuntime/hasSessionSummaryfor empty states.indexFromApi(resource-source.ts) →rollupOverview/summaryOverview→buildSeries→ uPlot panels.useResourceTimelineDataselects the visible chunks →getSessionResourceTimelineChunk→GET …/resource-timeline/chunks/:id→getSessionResourceTimelineChunk→readChunkPayload(R2, checksum-verified) →chunkDetailFromApi→ 5-second series.Capability test:
apps/api/tests/unit/workspace-resource-timeline.test.tsuploads through the realstoreWorkspaceResourceChunkand reads through the real index on a real SQL engine. The Playwright suite drives the real chat rail against those API shapes.Untested Gaps
Post-Mortem (Required for bug fix PRs)
N/A: not a bug fix. It is a UX redesign; the misleading one-chunk view is replaced rather than patched.
Specialist Review Evidence (Required for agent-authored PRs)
needs-human-reviewlabel added and merge deferred to human (N/A: all completed)idtie-break forced a sort over the session's whole history → removed and the plan verified; the index query now selects only the columns it returns (935506b). LOW: migration numbering gap and covering-index DISTINCT subquery accepted.panels.tsat 501 lines accepted.CodeRabbit Review Evidence (Required for agent-authored PRs)
CodeRabbit Notes
The
coderabbit-reviewlabel was applied. Trusted workflow runs36567298551and36574196615passed and posted human-scoped review commands; the latter targeted head7c1f70619. CodeRabbit produced no review or inline comments after more than an hour, and its status reported Review skipped: bot user not eligible for review. The rebased head does not materially rework the feature, so the review was not requested again. Per.claude/rules/25-review-merge-gate.md, this outcome is recorded and does not block merge.Exceptions (If any)
Agent Preflight (Required)
Classification
External References
EXPLAIN QUERY PLAN.Codebase Impact Analysis
apps/api: migration 0177, schema,services/workspace-resource-rollup.ts(new),services/workspace-resource-timeline.ts(new), upload hook inservices/workspace-resource-history.ts, routes inroutes/projects/workspace-resource-history.ts, env knobs.apps/web:components/chat/resource-timeline/*,SessionResourceHistoryDrawer.tsx,lib/api/resource-timeline.ts(new; the unusedgetSessionResourceHistoryclient was removed), uPlot dependency.…/resource-historyroutes and theget_resource_historyMCP tool are unchanged.Documentation & Specs
apps/www/src/content/docs/docs/guides/session-resources.mdrewritten, with new screenshotsapps/www/src/content/docs/docs/reference/api.md(session timeline endpoints)apps/www/src/content/docs/docs/reference/configuration.md(three new vars)apps/api/.env.example,.claude/skills/api-reference,.claude/skills/env-referenceConstitution & Risk Check
DEFAULT_*: the timeline chunk cap, rollup bucket width and max buckets. No hardcoded URLs.ADD COLUMN); existing rows stay NULL and render from their summary.🤖 Generated with Claude Code