fix(chat): clear active_stream_id when chat workflow finishes

Merged
SW
5mo ago
+270-8

Summary

  • Adds clearChatActiveStreamWhenWorkflowFinishes() helper + 4 unit tests
  • Wires it into handleChatWorkflowStream via Next.js after() so the post-stream cleanup runs without blocking the SSE response
  • Uses CAS (expected = run.runId, next = null) so a newer run that already claimed the slot is never clobbered

Why

handleChatWorkflowStream sets chats.active_stream_id when it starts the workflow but never clears it afterward. The chat UI's recovery probe (GET /api/sessions/{sessionId}/chats) reports isStreaming based on active_stream_id !== null, so a stale non-null value tells the open-agents stream-recovery hook to call chat.resumeStream() forever — which keeps the AI SDK chat.status stuck in submitted / streaming. The send button never returns and the user can't submit a follow-up.

The bug only surfaced after the chat-cutover from open-agents to recoup-api (recoupable/open-agents#43) — before the cutover, open-agents' own workflow handler had similar cleanup logic.

Test plan

  • pnpm test -- --run lib/chat/__tests__/clearChatActiveStreamWhenWorkflowFinishes.test.ts — 4/4 pass (3148/3148 total)
  • pnpm lint:check — no new lint errors
  • tsc --noEmit — no new type errors
  • Manual: send a message in chat, confirm send button returns after the stream completes and a follow-up can be sent

🤖 Generated with Claude Code


Summary by cubic

Clears chats.active_stream_id when a chat workflow finishes to stop endless stream recovery. This fixes the stuck “submitted/streaming” status so the send button returns and follow-ups work.

  • Bug Fixes

    • Added clearChatActiveStream(chatId, runId) as a workflow "use step" that CAS-clears to null with 3 retries (50ms delay), preserving newer runs.
    • Calls it in runAgentWorkflow (via try/finally and getWorkflowMetadata().workflowRunId) so cleanup runs immediately on success, failure, or cancel; removed the handler after() approach.
    • New tests cover the step’s retry/race behavior and verify runAgentWorkflow triggers cleanup on both success and error paths.
  • Refactors

    • Extracted delay(ms) to lib/time/delay with unit tests; used by clearChatActiveStream’s retry loop.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved chat stream state cleanup with automatic retry mechanism (up to 3 attempts) to gracefully handle transient failures without disrupting user sessions.
    • Enhanced workflow execution error handling to ensure cleanup operations always complete, even when unexpected errors occur during workflow steps.

Review Change Stack