fix(slack): add streaming keepalive to prevent session timeout#240
Open
gakonst wants to merge 1 commit intovercel:mainfrom
Open
fix(slack): add streaming keepalive to prevent session timeout#240gakonst wants to merge 1 commit intovercel:mainfrom
gakonst wants to merge 1 commit intovercel:mainfrom
Conversation
Slack's streaming API expires after ~5 min of inactivity. When the textStream iterable pauses during long-running agent work (tool calls, reasoning, etc.), the session expires and subsequent append/stop calls fail with message_not_in_streaming_state. Race each chunk against a 2-minute keepalive timer. If no chunk arrives in time, append a zero-width space to keep the session alive. The same pending iterator promise is re-raced after each keepalive, so no chunks are ever dropped.
Contributor
|
Someone is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Slack's streaming API expires the session after ~5 minutes of inactivity. When the
textStreamiterable pauses for extended periods — which is common during long-running agent tool calls, multi-step reasoning, or external API waits — the session expires silently. All subsequentstreamer.append()orstreamer.stop()calls then fail with:This is fatal: the SDK's
sendStructuredChunkcatch handler disables structured chunks for the rest of the stream, and if text streaming also fails, the entire response is lost. The user sees only an error message.Currently the SDK has no keepalive or heartbeat mechanism — the
for awaitloop instream()simply blocks waiting for the next chunk with no timeout awareness.Fix
Replace the
for awaitloop with aPromise.racepattern that races eachiter.next()against a 2-minute keepalive timer (well under Slack's ~5-minute TTL). If no chunk arrives within 2 minutes, a zero-width space (\u200B) is appended via the existingflushMarkdownDeltahelper to keep the session alive.The same pending iterator promise is re-raced after each keepalive, so no chunks are ever dropped or duplicated.
Before
After
Testing
pnpm --filter @chat-adapter/slack build✅pnpm --filter @chat-adapter/slack typecheck✅pnpm --filter @chat-adapter/slack test— 296/297 pass (1 pre-existing network-dependent failure unrelated to this change)