Skip to content

refactor: send raw typed payloads over chat WebSockets#24148

Draft
DanielleMaywood wants to merge 2 commits intomainfrom
dm/chat-ws-raw-payloads
Draft

refactor: send raw typed payloads over chat WebSockets#24148
DanielleMaywood wants to merge 2 commits intomainfrom
dm/chat-ws-raw-payloads

Conversation

@DanielleMaywood
Copy link
Copy Markdown
Contributor

🤖 This PR was written by Coder Agent on behalf of Danielle Maywood 🤖

watchChats and streamChat inherited the ServerSentEvent envelope from the pre-WebSocket SSE era. The newer WebSocket endpoints (watchAgentContainers, watchInboxNotifications, agent logs) already send raw typed payloads — these two were the last holdouts.

Backend: replace OneWayWebSocketEventSender with websocket.Accept + json.NewEncoder for both endpoints. Move ChatWatchEvent to codersdk so it gets codegen'd. Frontend consumers receive typed data directly instead of unwrapping an unknown envelope.

This removes isChatListSSEEvent, isChatStreamEvent, isChatStreamEventArray, toChatStreamEvents, and the asString/asNumber wrappers in normalizeChatDetailError/normalizeRetryState — all of which existed solely because the SSE envelope erased type information.

Decision log
  • Scoped to watchChats and streamChat only — watchWorkspace and watchAgentMetadata still use the SSE envelope (different consumers, separate cleanup)
  • ChatWatchEvent moved from coderd/pubsub to codersdk for codegen; pubsub aliases removed, all consumers reference codersdk directly
  • streamChat subscribes before websocket.Accept so failures return proper HTTP errors instead of WebSocket error frames
  • ChatEvent channel helper and HandleChatEvent remain in coderd/pubsub (server-internal plumbing)

Replace the legacy ServerSentEvent envelope with direct JSON encoding
for watchChats and streamChat. These endpoints inherited the SSE
envelope format from the pre-WebSocket era but never needed it — the
newer WebSocket endpoints (containers, notifications, logs) already
send raw typed payloads.

Backend: switch from OneWayWebSocketEventSender to websocket.Accept +
json.NewEncoder (matching watchAgentContainers). Move ChatWatchEvent
type to codersdk so it gets codegen'd to TypeScript.

Frontend: watchChat returns ChatStreamEvent[], watchChats returns
ChatWatchEvent. Remove isChatListSSEEvent, isChatStreamEvent,
toChatStreamEvents type guards and asString/asNumber defensive
wrappers from useChatStore — the typed stream data makes them
redundant.
@github-actions github-actions bot added the community Pull Requests and issues created by the community. label Apr 8, 2026
The streamChat WebSocket now sends raw ChatStreamEvent[] payloads
instead of SSE-wrapped envelopes. Update story mocks to match by
replacing wrapSSE({event}) with JSON.stringify([event]) and deleting
the now-unused wrapSSE helper.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Pull Requests and issues created by the community.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant