feat(panel): keep huge sessions navigable — transcript windowing + delegated collapse - #317
Merged
Merged
Conversation
Get now accepts turn_limit, turn_offset and turn_tail so clients can read a bounded slice of a session's chronological turn stream instead of every row. The response carries total_turns and message_turns so a windowed client can place its slice and keep whole-session KPIs exact. A zero turn_limit preserves the previous return-everything behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The session side panel now renders only the last 200 turns (turnPageSize) and opens on the tail of the conversation. A 'load earlier turns (N more)' anchor at the top of the transcript swaps in the preceding 200-turn page via HTMX (GET /sessions/<id>/turns) until turn 0 is reached. The turns KPI uses the server-side message_turns count so it covers the whole session regardless of the window. Bubble collapse, tool/thinking group disclosure and 'Collapse all' are now plain classes + [hidden] flipped by delegated listeners in assets/transcript.js — a constant number of listeners per document instead of one Alpine component and one window listener per message, which froze the tab on sessions with tens of thousands of turns. The in-transcript search keeps working through the same window events it already dispatched. Bubble visuals are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
screens.md and components.md now describe the 200-turn window, the 'load earlier turns' anchor and the transcript.js delegated collapse mechanism; the panel skill and reviewer agent state that repeated per-turn elements never get Alpine components. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Opening a very large session in the panel (e.g. 1.9B tokens, hundreds of thousands of turns) froze the browser tab. Two compounding causes:
Sessions.Gethad no turn windowing (SELECT … FROM turnswith noLIMIT), so every turn landed in the DOM.x-dataand awindow-level listener; tool/thinking groups too. Thousands of turns meant thousands of reactive components initialized on load, and "Collapse all" / in-transcript search dispatched synchronous O(N) event storms.What changed
API (
Sessions.Get) — new optionalturn_limit/turn_offset/turn_tailrequest fields window the chronological turn stream server-side; the response now carriestotal_turnsandmessage_turns.turn_limit = 0keeps the old return-everything behavior, so existing callers are unaffected.Transcript paging (panel) — the side panel requests only the last 200 turns (
turnPageSize) and opens on the tail of the conversation. A "↑ load earlier turns (N more)" anchor at the top of the transcript HTMX-swaps in the preceding 200-turn page (GET /sessions/<id>/turns?before=N), stacking older pages above the ones on screen until turn 0. The "turns" KPI uses the server-sidemessage_turnscount, so it stays whole-session-accurate regardless of the window.Delegated collapse (panel) — per-bubble collapse, tool/thinking group disclosure and "Collapse all" are now plain classes +
[hidden]flipped by delegated listeners inassets/transcript.js: a constant number of listeners per document instead of one Alpine component + onewindowlistener per message. The in-transcript search keeps working through the samemessages-toggle-all/transcript-expand-groupsevents it already dispatched. Bubble visuals are unchanged.Validation
Exercised end-to-end against a disposable Postgres/MinIO stack with a synthetic 1,260-turn session (plus a small control session):
go test ./...,go vet,golangci-lintclean; screenshots compared against the current bubble design — pixel-identical.Docs (
docs/panel/screens.md,components.md, design brief, panel skill + reviewer agent) updated to describe the windowing and the no-Alpine-per-turn rule.Note: the in-transcript search only sees loaded turns; server-side transcript search is a natural follow-up if that bites in practice.
🤖 Generated with Claude Code