fix(slack): preserve buffered thread stream replies#78536
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: Do we have a high-confidence way to reproduce the issue? Yes at the source level: on current main, make Real behavior proof Next step before merge Security Review detailsBest possible solution: Merge the focused Slack extension fallback after maintainer readiness, targeted Slack validation, changed-gate proof, and preferably a live Socket Mode thread check; keep the linked user issue open until this PR lands. Do we have a high-confidence way to reproduce the issue? Do we have a high-confidence way to reproduce the issue? Yes at the source level: on current main, make Is this the best way to solve the issue? Is this the best way to solve the issue? Yes, the PR uses the existing Slack fallback delivery path and keeps the change limited to locally buffered stream finalization failures, without changing Slack config, routing, or native streaming defaults. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against d648673b3105. |
byungskers
left a comment
There was a problem hiding this comment.
Excellent bug fix with thorough documentation and test coverage. The Slack native streaming buffer contract is tricky, and losing short replies because stopStream failed before flush is a frustrating user experience.
A few constructive notes:
-
Fallback delivery duplication risk: The PR mentions that
pendingTextis cleared after acknowledged native flushes, which avoids replay. Could you add a test that explicitly verifies no duplicate delivery occurs if a partial flush succeeded before the final stop failure? -
Error classification: The change broadens the error allowlist for fallback delivery. Is there any error type where fallback delivery would be incorrect (e.g., rate limits or auth failures where retrying via
chat.postMessagewould also fail)? The current approach seems safe since it only posts already-generated text, but worth confirming. -
Testbox gap: You noted Testbox was unavailable for
pnpm check:changed. If this merges before you can run it, consider scheduling a follow-up Testbox run or asking a maintainer to trigger one — the Slack extension has enough surface area that changed-surface validation is valuable.
The real behavior proof section is particularly well done. The before/after flow diagram makes the change easy to understand. LGTM with minor test suggestions.
|
when will this be merged to main? |
Summary
chat.stopStreamfailures before that flush can drop the generated reply.stopSlackStream()now converts any finalize failure with pending buffered text into the existing fallback-delivery error, so the message is posted through normal threadedchat.postMessagedelivery.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Real behavior proof (required for external PRs)
pnpm test:serial extensions/slack/src/streaming.test.ts extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts extensions/slack/src/monitor/message-handler/dispatch.streaming.test.ts extensions/slack/src/monitor/message-handler/prepare.thread-session-key.test.ts extensions/slack/src/monitor/replies.test.tsdeliverReplieswith the original Slack thread timestamp when finalization fails before the SDK buffer flushes.pnpm check:changedcould not run becausetbx_01kqydekhtz0ktjtfh8mwfgfb6timed out/shut down before sync and replacementtbx_01kqyz9d18px8wjb8zz7mytd77shut down while queued.chat.postMessageto the same thread.Root Cause (if applicable)
ChatStreamerbuffers shortmarkdown_textlocally until finalization; OpenClaw only converted a small allowlist of finalize errors into fallback-deliverable pending text.Regression Test Plan (if applicable)
extensions/slack/src/streaming.test.ts;extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.tsUser-visible / Behavior Changes
Slack thread replies that previously disappeared when native streaming finalization failed should now post through normal threaded delivery.
Diagram (if applicable)
Security Impact (required)
Yes/No) NoYes/No) NoYes/No) No, fallback uses the existing Slack send path already used for normal replies.Yes/No) NoYes/No) NoYes, explain risk + mitigation: N/ARepro + Verification
Environment
Steps
Expected
Actual
deliverRepliesreceives the pending text and originalthreadTs.Evidence
Human Verification (required)
What you personally verified (not just CI), and how:
git diff --check origin/main...HEADpassed.pnpm check:changed, blocked by Testbox leases shutting down before execution.Review Conversations
Compatibility / Migration
Yes/No) YesYes/No) NoYes/No) NoRisks and Mitigations
session.pendingText, which is cleared after acknowledged native flushes, so it avoids replaying already-acknowledged chunks.