fix(chat-workflow): explicitly close the SSE writable so chat.status unsticks
Summary
Follow-up to PR #604 — closes the second half of the same bug. The DB clear from #604 was working correctly, but users were still seeing the stop button stuck for ~2 minutes after the stream ended.
Root cause: runAgentStep calls writer.releaseLock() which doesn't close the underlying writable. The writable stays open until Vercel Workflow's runtime garbage-collects the run (observed ~2 min), so the SSE response holds its HTTP connection open and the AI SDK chat hook stays in submitted waiting on a stream-end signal that never arrives promptly.
open-agents avoids this by explicitly calling writable.close() in a "use step" inside the workflow body — same pattern this PR mirrors.
Changes
- New
app/lib/workflows/closeChatStream.ts"use step" that callswritable.close()and defensively swallows errors. runAgentWorkflow'sfinallyblock now runs both cleanups in parallel viaPromise.all([clearChatActiveStream, closeChatStream])— same shape as open-agents'.- 3 new
closeChatStreamtests + 2 newrunAgentWorkflowtests (success and throw paths both close the writable).
Test plan
-
pnpm test— 3154 → 3159 passing (5 new) -
pnpm lint:check— clean for touched files - Manual: send message in open-agents UI, confirm send button reverts within ~1s of stream ending (was 2m+)
Linked
- Source of bug: #604 review tests showed DB clears correctly but UI stays stuck — this PR closes the UI-side half
- Tracking issue: #605
🤖 Generated with Claude Code
Summary by cubic
Explicitly closes the chat SSE writable at the end of runAgentWorkflow so the stream ends immediately and the UI unsticks (stop button/chat.status leaves submitted). Fixes the ~2‑minute hang seen after #604.
- Bug Fixes
- Added
closeChatStream"use step" to callwritable.close()and swallow errors. - Updated
runAgentWorkflowto runcloseChatStreamandclearChatActiveStreamin parallel viaPromise.all. - Added tests for
closeChatStreamand for closing on both success and error paths inrunAgentWorkflow; tests live under__tests__/.
- Added