Skip to content

Fix Slack native stream rollover#672

Draft
tdietert wants to merge 1 commit into
vercel:mainfrom
tdietert:fix/slack-stream-rollover
Draft

Fix Slack native stream rollover#672
tdietert wants to merge 1 commit into
vercel:mainfrom
tdietert:fix/slack-stream-rollover

Conversation

@tdietert

@tdietert tdietert commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #671

What problems was I solving

Slack native streamed messages can stop accepting chat.appendStream / chat.stopStream calls while a long-running agent turn is still producing output. Slack reports that state as message_not_in_streaming_state; previously the adapter rejected and dropped later output.

This PR makes the Slack adapter treat that documented error as the recovery boundary: when the current native streamed message is no longer streamable, the adapter continues the turn in a fresh streamed message in the same thread and retries only the pending chunk.

What user-facing changes did I ship

  • packages/adapter-slack/src/index.ts — Slack native streams now recover reactively from message_not_in_streaming_state by starting a fresh stream and retrying only the pending markdown delta.
  • packages/adapter-slack/src/index.ts — The adapter now calls chat.startStream, chat.appendStream, and chat.stopStream directly instead of going through ChatStreamer, so it owns stream lifecycle and confirmed-offset bookkeeping explicitly.
  • packages/adapter-slack/src/index.ts — Latest structured task/plan chunks are re-seeded on rollover; fallback updates only the current message segment to avoid duplicating text already emitted in earlier rolled messages.
  • packages/adapter-slack/package.json — Keeps the Slack Web API floor at ^7.17.0 for the native stream chunk API surface used by the adapter.

How I implemented it

  • Removed the ChatStreamer/buffer_size: 1 path and the open-code-fence-prefix workaround from the PR.
  • Added direct native stream state tracking:
    • active Slack stream ts
    • last known message ts
    • current message start offset
    • last confirmed markdown offset
    • latest structured chunk snapshots
    • bounded rollover count
  • On append expiry, the adapter starts a new stream in the same thread, optionally re-seeds latest structured chunks, and retries exactly the pending delta.
  • On stop expiry, the adapter treats an already-flushed stream as complete; if final blocks or unconfirmed tail need recovery, it uses chat.update on the latest stream segment rather than duplicating the full cumulative answer.
  • Updated adapter and integration tests to mock/assert direct Web API streaming methods instead of chatStream().
  • Added a patch changeset for @chat-adapter/slack.

How to verify it

Manual testing

  • Start a Slack native stream, let Slack report message_not_in_streaming_state, and confirm later deltas continue in a fresh streamed message.
  • Confirm task/plan progress chunks still appear after a rollover.
  • Confirm stop-time expiry does not truncate an already-flushed response.

Automated tests

pnpm --filter @chat-adapter/slack... build
pnpm --filter @chat-adapter/slack... typecheck
pnpm --filter @chat-adapter/slack test
pnpm check
pnpm validate

All of the above passed locally after the refactor.

Changelog

@chat-adapter/slack now recovers expired Slack native streams by reactively rolling long-running replies onto fresh streamed messages without dropping pending text.

@tdietert tdietert requested a review from a team as a code owner July 2, 2026 22:35
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@tdietert is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@socket-security

socket-security Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​slack/​web-api@​7.18.010010010099100

View full report

@tdietert tdietert force-pushed the fix/slack-stream-rollover branch 2 times, most recently from b18c2ad to e1ebd3d Compare July 3, 2026 01:45
@tdietert tdietert marked this pull request as draft July 3, 2026 01:55
@tdietert tdietert force-pushed the fix/slack-stream-rollover branch from e1ebd3d to 9d97505 Compare July 3, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack: auto-roll a native stream onto a fresh message when Slack expires it mid-stream (long-running, out-of-process producers)

1 participant