feat(host): a workspace's chat is followed over Neon Realtime and streamed to the panels that draw it

Merged
CH
8d ago
+745-8

Part of making workspace chat live over Neon Realtime. Stacked on #3916. One change: the host follows a workspace's chat and streams it to the panels that draw it.

What changes

Act port

  • New codingAgents.chatFollow procedure that returns a stream (oRPC eventIterator), following #4175's transcript pattern.
  • A panel follows a chat by keeping that stream open:
    • the host starts following the chat when the first stream opens
    • every change goes to every open stream of that chat
    • the host stops following when the last stream closes
  • A window and a web tab use the same procedure, so the web tab needs no code of its own. The chat isn't app state, so it isn't pushed through push.stream.

Host

  • chat-follow.ts:
    • joins the chat once (#3906)
    • seals live.workspaceChat for the account the follow started for (?userId=)
    • follows its parts with liveRows: over Realtime where LUKE_REALTIME=on, and otherwise by the held poll (#4272), which answers once the rows move
    • tells each change whole as chat.changed, and never sends a sealed statement
  • Failures:
    • a join or seal that goes unanswered is reported as unanswered and retried after 5 s
    • a chat that isn't found is reported as such, and the follow ends
    • signed out ends the follow
    • signing out lets every follow go
  • New gateway methods codingAgents.chatFollow and codingAgents.chatUnfollow, and a new chat.changed event.

Nothing in the window moves onto this yet. That's #3928.

Tests

  • compose-coding-agents.test.ts:
    • joins, then seals for the signed-in account, then subscribes every part
    • each change goes out whole, in the held read's order, with no sealed statement
    • unanswered is reported and retried, not found ends the follow
    • unfollow, sign-out, and the closed gate end it too
  • agent-inbox-procedures.test.ts:
    • two panel streams share one follow, and each hears only its own chat
    • the follow is let go when the last stream closes
    • the voice window is refused
  • New goldens for codingAgentChatFollowParamsSchema and codingAgentChatChangedSchema.
  • Checks run one at a time on the stack's top: tsc for each touched package, biome, oxlint, knip, discarded-effect, the repository checks, and the affected vitest suites.