feat(panel): open agent transcripts newest first
PR 2b of the performance rollout. The desktop now opens an agent's transcript on its newest page, so the end shows after one request, and the log no longer scrolls itself while older pages load.
Host
-
followTranscriptreadsmessagesNewestbeside the seal rather than after it, and tells that page as{ ...page, newest: true, before?, caughtUp: false }. Once the subscription's first rows land, it readsmessagesNowfrom the newest page's cursor, so nothing written between the two reads is missed. A full page reads on at once. A short page counts as caught up, so it no longer makes an extra round trip just to get an empty page. -
sealedOfnow retries onSchedule.spaced(1s), up to 30 times. If the seal still fails after that, the follow tells the windowunanswered, which shows Try again, and invalidates itsRcMapentry so the next follow seals from scratch. A reseal after a broken subscription fails the same way (LiveStateunsealed). Before, it retried every second forever without saying anything. -
Pushed pages are a new view schema,
CodingAgentTranscriptPage, which addsnewest,before, and a requiredcaughtUp. -
Older pages: there's a new act
codingAgents.transcriptOlder(ACT_KIND, contract procedure, act-port procedure). It goes through the gateway methodcodingAgents.transcriptOldertomessagesBefore. -
Since #4392 is on main now, the newest and older reads ask for tool output cut (
cut: true), the same as the forward follow. -
A newest page the service keeps not answering is retried the same bounded number of times as the seal; after that the follow ends on the failure it told.
Panel
useAgentTranscriptholds the newest page first and exposeshasOlder,loadingOlder, andloadOlder. An older page goes in front of the held messages, but only while those messages still start where it was asked for. A newest page that doesn't overlap what's held (e.g. a tab shown again after more than a page was written) replaces it, so no gap is left in between.ConversationtakesonNearTop, which fires when the reader scrolls up within one screen of the top or the lines don't fill the box. When lines are put before the first one, the layout effect measures and moves the first line back to where the reader left it. It does this itself because the browser's scroll anchoring doesn't anchor anything at scrollTop 0. The log still pins to the bottom only while it is following its newest line.- The Stopped/Failed end row waits until a page has landed.
- Message links look for their message on older pages before they report it as gone. If an older read fails, the link stops reading on its own and waits for the reader to scroll up.
- PR 1's timing hooks still work:
transcript.first_paintends at the newest page's commit, andtranscript.caught_upends at the first short forward page.
Not in this PR
- Choosing the agent tab from the task row before the agent list returns. The brief's
NoAgentPanedoesn't exist on main, andAgentTabneeds a fullCodingAgentSummary, which the task row'sTaskAgentLines don't carry. The orchestrator decided to leave this for its own follow-up PR.
Tests
- Host: the follow asks for the newest page once and never from the start, follows on from its cursor without missing a message written between the reads, treats a short page as caught up with no further read, and reads on at once after a full page. A failing seal doesn't stop the first page, is retried a bounded number of times, then reports the failure, and following again seals anew. The older-page gateway method and act are covered too.
- Panel: older pages load one at a time and go in front; a failed older read can be retried; a newest page joins what's held or replaces it; a prepend leaves the line the reader was on in place; a following log stays at the bottom.
vitestoverpackages/hostand the panel'stasks,desktop, andai-elements(2355 tests) passes.
Made with Luke