feat(host): a window follows an agent's transcript as a stream of pushed pages
Merged
CH
5d ago+1271+1271+0123456789012345678901234567890123456789-11-11-01234567890123456789
The host half of making the agent transcript live on main. It's stacked on #3298 (luke/live-transcript-clock-edges) and replaces #3909, which was built on the old stack. The window moves over in the next PR.
What changed
- Act port: a new event-iterator procedure,
codingAgents.transcript, takes a transcript key and yields its pages for as long as the window keeps the stream open.- The key is an agent's own transcript, one of its workers' (
callId), or a task's planning worker's. - Opening a stream asks the host to follow from the start, so a window that arrives late gets the whole transcript.
- Closing the last stream of a transcript lets the host's follow go.
- Each page of an agent's own transcript notes its title and status, as the read did.
- web-host serves the same procedures, so a web tab follows transcripts exactly as a window does, with no extra wiring.
- The key is an agent's own transcript, one of its workers' (
- Gateway:
codingAgents.transcriptFollow/Unfollow:followTranscriptreads on the transcript's existing Realtime subscription (transcriptFollows) and tells each page astranscript.changed. It reads the first page from the start, the next one right away after a page with messages, and otherwise again only when the statements move or the service'swakeInedge passes.tasks.workerTranscriptFollow/Unfollow: a planning worker is followed on the service's heldtasks.messagesread until #3311 gives it live statements of its own. The follow stops once the worker has ended and its page is empty.
- Wire:
codingAgentTranscriptKeySchemaandcodingAgentTranscriptChangedSchema, recorded inhosted-wire-schemas.test.tswith goldens generated underLUKE_UPDATE_FIXTURES=1. - The sealed statements stay in the host.
Tests
compose-coding-agents.test.ts: a followed agent transcript is told page by page; a transcript the account can't reach is told not found once; behind a closed gate it's told unanswered; sign-out lets it go.compose-tasks.test.ts: a planning worker is told page by page on the held read, and the follow ends with the worker.agents-procedures.test.ts: two streams of one transcript each hear its pages and nothing of another's; the host lets it go only when the last stream closes.
Checks run locally
pnpm check:affected gets OOM-killed in the sandbox, so I ran its pieces one at a time:
repository-checks.sh,biome check .,oxlint,knipdiscarded-effect(with a larger heap)tscfor host, desktop, web and panel- vitest for the whole host suite (451 tests)
What to check by hand
Nothing visible changes yet: no window opens the stream until the next PR.
Made with Luke