FE-873: Web-as-driver streaming chat transport (topology A)#225
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
PR SummaryMedium Risk Overview Sidecar RPC is split via
Reviewed by Cursor Bugbot for commit 1c702f1. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
Implements the Topology A observer relay seam to forward in-process Pi AgentSession events over the existing TUI sidecar /rpc WebSocket as brunch.sessionEvent JSON-RPC notifications, multiplexed alongside existing brunch.updated domain invalidations.
Changes:
- Add
SessionEventRelay(brunch.sessionEventframes with{seq, event}) plus unit tests. - Wire the relay through the TUI boot path into the web sidecar WebSocket transport, and add an end-to-end dev test that proves relay↔transcript reduction and multiplexing.
- Update RPC docs + SPEC/PLAN to record the validated/built slice and decision D84-L.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/rpc/websocket.ts | Subscribes to session-event relay and forwards frames over the /rpc WebSocket transport. |
| src/rpc/web-host.ts | Threads optional SessionEventRelay into the web host transport wiring. |
| src/rpc/session-event-relay.ts | Introduces the process-local relay that envelopes Pi events as brunch.sessionEvent notifications with monotonic seq. |
| src/rpc/session-event-relay.test.ts | Unit coverage for envelope shape, no replay, and explicit unsubscription. |
| src/rpc/README.md | Documents brunch.sessionEvent as an observer-only, non-canonical notification. |
| src/dev/tests/web-driver-streaming.relay.test.ts | End-to-end proof: real runBrunchTui host relays live events over ws, multiplexed with brunch.updated, and streamed text appears in JSONL. |
| src/app/brunch-tui.ts | Creates the relay, threads it into the sidecar, and attaches the live AgentSession after creation. |
| memory/SPEC.md | Records A28-L as validated and adds D84-L decision for the relay seam. |
| memory/PLAN.md | Updates FE-873 status/certainty and topology materialization notes to reflect the built observer relay slice. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const unsubscribeSessionEvents = options.sessionEvents?.subscribe((frame) => { | ||
| publishNotification(JSON.stringify(frame)); | ||
| }); |
…uash merge The FE-870 squash merge (#217, e4a63fd) reintroduced the exhausted renderer-golden-coverage--graph-render-migration.md scope card in its stale pre-build form (Cards 0-3 shown blocked/not-done), though Cards 0-3 shipped and PLAN records the scope card as retired. Re-delete it so HEAD matches bkp/ln/fe-870-renderer-golden-context-tools and PLAN's "scope card retired" state. No other canonical-doc drift from the restack.
…pology A) SessionEventRelay forwards the in-process AgentSession event stream over the existing TUI sidecar /rpc WebSocket as brunch.sessionEvent frames, multiplexed with brunch.updated. Ephemeral/process-local; no second canonical store (D19-L, D84-L). Battery claims 1-4 production-wired; claims 5-7 are follow-on slices. Signed-off-by: Lu Nelson <ln@hash.ai>
ec02a3d to
e50a407
Compare
291c5d9 to
1c702f1
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1c702f1. Configure here.
| if (ctx.hasUI && typeof ctx.ui.editor === 'function') { | ||
| answer = await ctx.ui.editor(params.prompt); | ||
| } else if (answerBroker) { | ||
| answer = await answerBroker.awaitAnswer({ exchangeId: params.exchangeId }); |
There was a problem hiding this comment.
Broker bypassed when TUI UI
High Severity
In the default runBrunchTui host, request_answer checks ctx.hasUI before the live-exchange broker, so mid-turn exchanges block on the terminal editor even though LiveExchangeBroker and session.answerExchange are wired. Web-side session.answerExchange then resolves an unused broker while the tool never awaits it, so live web answering fails in topology A.
Reviewed by Cursor Bugbot for commit 1c702f1. Configure here.
| return createJsonRpcFailure(requestId, -32010, NO_LIVE_AGENT_SESSION_DRIVER_MESSAGE); | ||
| } | ||
| return createJsonRpcSuccess(requestId, { status: 'completed' }); | ||
| }, |
There was a problem hiding this comment.
Sidecar allows observer driveTurn
Medium Severity
Every WebSocket client on the TUI sidecar shares the same handler registry, so session.driveTurn is callable from any connection. The fan-out acceptance model treats extra clients as read-only observers, but this method is not restricted to a single driver role and there is no rejection path for observer sockets.
Reviewed by Cursor Bugbot for commit 1c702f1. Configure here.



Summary
SessionEventRelayso the TUI-started sidecar can stream the live in-processAgentSessionevent feed over the existing/rpcWebSocket asbrunch.sessionEvent, multiplexed withbrunch.updatedand without a second canonical store.session.driveTurnfor plain prompts andsession.answerExchangeviaLiveExchangeBrokerfor liverequest_answerexchanges.Verification
npm run check