Skip to content

Share one server-sent events helper across the four streams - #434

Merged
abhishekgahlot2 merged 1 commit into
useagenthq:mainfrom
coolestnick:fix/shared-sse-helper
Nov 10, 2026
Merged

abhishekgahlot2 merged 1 commit into
useagenthq:mainfrom
coolestnick:fix/shared-sse-helper

Conversation

@coolestnick

@coolestnick coolestnick commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Closes #325

The run, thread, chat and changes streams each built their own ReadableStream, opening comment, 25 s heartbeat, header block and abort cleanup. This moves all of that into one helper, sseResponse in backend/src/util/sse.ts, and the four routes now only write frames and hand back what to undo when the stream closes.

What changed:

  • backend/src/util/sse.ts owns the stream, the : open comment (with an optional retry:), the heartbeat, the four anti-buffering headers and the teardown. It gives the route send, sendEvent, close and a closed flag.
  • runs/routes.ts (run stream and thread stream), chat/routes.ts and runs/changes-route.ts go through it. The route logic itself is moved, not rewritten.
  • runs/routes.ts went from 1009 to 919 lines, so its ratchet baseline is lowered to 919.
  • backend/AGENTS.md has a new owner row so the next stream goes through the helper.

One behaviour change to be aware of: every stream now closes, and runs its teardown, when a write fails because the client left or when the response body is cancelled. Before, only the changes stream closed on a failed write and none of the routes handled a cancelled body; they waited for the request's abort signal. Headers, frames and their order are unchanged.

Tests (backend/src/util/sse.test.ts):

  • the exact headers and opening comment, with and without retry:
  • frame bytes for sendEvent and send
  • the heartbeat fires and its interval is cleared on close
  • abort, body cancel, and a route that throws while starting all tear down once
  • a request that is already aborted never starts the route
  • the 25_000 interval and the text/event-stream; charset=utf-8 header appear in only one non-test file under backend/src. This one fails on main, where four files hold them.

Checks:

  • bun run typecheck at the root -> ok
  • cd backend && bun run test on my own database -> 3586 pass, 3 skip, 0 fail, then the Slack suite 119 pass, 0 fail
  • bun test scripts/agent-docs.test.ts -> 5 pass

Before / after

I captured all four streams with curl -i against a local backend, first on main and then on this branch, and diffed the two captures. In the lines both captures share, the only differences were the Date header and the thread stream's per-connection epoch id. The capture on main was cut off before the chat model's first text frame, so the chat delta frame is only in the capture from this branch. Holding the changes stream open for 27 s on this branch showed the : ping heartbeat.

Changes stream, same on both:

HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform
Connection: keep-alive
X-Accel-Buffering: no

: open
retry: 1500

Chat stream, same on both up to the context frame, the delta frame is from this branch only:

: open

event: context
data: {"citations":[]}

event: delta
data: {"delta":"Hi!"}

@abhishekgahlot2
abhishekgahlot2 merged commit 4ef8fef into useagenthq:main Nov 10, 2026
20 checks passed
@abhishekgahlot2

Copy link
Copy Markdown
Contributor

Merged, thanks @coolestnick. One helper for all four streams means the next heartbeat or teardown fix lands everywhere at once, and closing the stream on a failed write or a cancelled body is a real improvement over what three of them did before.

@github-actions github-actions Bot locked and limited conversation to collaborators Nov 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Share one server-sent events helper across the four streams

2 participants