#20244: resolution in DM with replyToMode=all
channel: slack
size: XS
Cluster:
Block Streaming Enhancements
Slack: thread replies with replyToMode "all" when streaming is on
With streaming enabled, agent replies and message-tool sends were posted as top-level messages in Slack DMs instead of under the incoming message, so replyToMode: "all" was ignored.
Use the same thread target for starting the stream as for the streaming decision: when starting a stream, set streamThreadTs = replyPlan.nextThreadTs() ?? streamThreadHint so we always have a thread (e.g. messageTs in DMs) when streaming was enabled.
When falling back to normal delivery due to no thread target, pass streamThreadHint into deliverNormally so the first message still threads.
Add a test that resolveSlackStreamingThreadHint returns messageTs for replyToMode "all" and a top-level message (e.g. DM).
Fixes the regression where DMs with replyToMode: "all" and streaming produced unthreaded replies.
#19930
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes a regression where Slack DMs with `replyToMode: "all"` and streaming enabled produced unthreaded replies. The stream-start path now falls back to `streamThreadHint` (the same thread target used to decide whether streaming is viable), ensuring the first streamed message is always posted as a thread reply in DMs.
- In `deliverWithStreaming`, the stream thread target is now `replyPlan.nextThreadTs() ?? streamThreadHint`, so the thread hint computed for the streaming decision is reused when the reply plan returns `undefined`.
- The `deliverNormally` fallback (when no thread target is found) now also receives `streamThreadHint` to preserve threading even in the non-streaming fallback path.
- Adds a test confirming `resolveSlackStreamingThreadHint` returns `messageTs` for `replyToMode=all` on a top-level message (the DM case).
- Import reordering groups type imports at the top of `dispatch.ts` (cosmetic).
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it's a small, well-targeted fix with correct logic and a covering test.
- The change is minimal (two lines of logic + one test). The fallback `?? streamThreadHint` is logically sound: `streamThreadHint` is guaranteed to be defined whenever we're inside the streaming path (since `shouldUseStreaming` requires it). The `deliverNormally` fallback change is defensive but correct. The new test directly validates the previously-broken scenario. No regressions are introduced — the `replyPlan.nextThreadTs()` is still tried first, so existing behavior for non-DM and non-`all` modes is unchanged.
- No files require special attention.
<sub>Last reviewed commit: 921f16d</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20623: fix(slack): duplicate replies and missing streaming recipient params
by rahulsub-be · 2026-02-19
82.7%
#20406: fix(slack): respect replyToMode when computing statusThreadTs in DMs
by QuinnYates · 2026-02-18
79.5%
#20274: fix: add fallback delivery when stopSlackStream fails
by nova-openclaw-cgk · 2026-02-18
79.1%
#21754: slack: pass inbound team_id into stream routing and startStream
by AIflow-Labs · 2026-02-20
79.0%
#22096: fix(slack): traverse .original for Slack SDK errors; pass recipient...
by maiclaw · 2026-02-20
78.7%
#12244: fix(slack): preserve thread context for DM thread replies
by junhoyeo · 2026-02-09
78.1%
#21218: fix(slack): pass recipient_team_id and recipient_user_id to chat stre…
by apham0001 · 2026-02-19
78.1%
#20248: fix(slack): flush draft stream before final reply to preserve messa...
by Utkarshbhimte · 2026-02-18
77.4%
#19083: Slack: preserve per-thread context and consistent thread replies
by jkimbo · 2026-02-17
77.2%
#19673: fix(telegram): avoid starting streaming replies with only 1-2 words
by emanuelst · 2026-02-18
77.1%