fix(feishu): send blocks as independent messages when blockStreaming is enabled#94250
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
|
Codex review: needs maintainer review before merge. Reviewed June 30, 2026, 12:08 PM ET / 16:08 UTC. Summary PR surface: Source +37, Tests +273. Total +310 across 2 files. Reproducibility: yes. Current main and v2026.6.10 are source-reproducible because the Feishu dispatcher returns from the non-card block path without sending, and the PR body supplies live after-fix Feishu logs/screenshots. Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this narrow Feishu dispatcher repair after required checks pass, and keep broader segment-streaming product/config work separate unless maintainers choose that direction. Do we have a high-confidence way to reproduce the issue? Yes. Current main and v2026.6.10 are source-reproducible because the Feishu dispatcher returns from the non-card block path without sending, and the PR body supplies live after-fix Feishu logs/screenshots. Is this the best way to solve the issue? Yes. The dispatcher is the right owner boundary for this existing channel option, and the latest head reuses established chunked text delivery instead of adding a new config mode; the broader segment-mode PR is not the narrowest fix for this bug. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 6cb82eaab865. Label changesLabel justifications:
Evidence reviewedPR surface: Source +37, Tests +273. Total +310 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
I have a real Feishu tenant setup and would be happy to help test this PR. I'm running OpenClaw 2026.6.8 with feishu plugin 2026.6.8, and the character-by-character streaming issue (#55027) affects my daily usage. If someone can point me to how to apply this patch on my instance, I can provide redacted screenshots of the block streaming behavior. Happy to help unblock this. |
|
Hi @bxy3045134656, thanks for offering to help test! Really appreciate it. The PR contains a single commit (6412454) modifying only 2 files in Option 1: gh pr checkout (easiest, if you have
|
Route the independent block-send path through sendChunkedTextReply instead of calling sendMessageFeishu directly, so the configured Feishu textChunkLimit is honored for completed blocks. Preserve mention targets only on the first emitted block chunk and keep sentBlockText based on the original block text for duplicate-final suppression. Add regression test with a small textChunkLimit that verifies a long block is split into chunked messages and mentions only appear on the first chunk.
|
Merged via squash.
|
…is enabled (openclaw#94250) * fix(feishu): send blocks as independent messages when blockStreaming is enabled * fix(feishu): preserve mention targets on first independently sent block * fix(feishu): route independent block sends through chunked text delivery Route the independent block-send path through sendChunkedTextReply instead of calling sendMessageFeishu directly, so the configured Feishu textChunkLimit is honored for completed blocks. Preserve mention targets only on the first emitted block chunk and keep sentBlockText based on the original block text for duplicate-final suppression. Add regression test with a small textChunkLimit that verifies a long block is split into chunked messages and mentions only appear on the first chunk. * fix(feishu): preserve block delivery target --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…is enabled (openclaw#94250) * fix(feishu): send blocks as independent messages when blockStreaming is enabled * fix(feishu): preserve mention targets on first independently sent block * fix(feishu): route independent block sends through chunked text delivery Route the independent block-send path through sendChunkedTextReply instead of calling sendMessageFeishu directly, so the configured Feishu textChunkLimit is honored for completed blocks. Preserve mention targets only on the first emitted block chunk and keep sentBlockText based on the original block text for duplicate-final suppression. Add regression test with a small textChunkLimit that verifies a long block is split into chunked messages and mentions only appear on the first chunk. * fix(feishu): preserve block delivery target --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…is enabled (openclaw#94250) * fix(feishu): send blocks as independent messages when blockStreaming is enabled * fix(feishu): preserve mention targets on first independently sent block * fix(feishu): route independent block sends through chunked text delivery Route the independent block-send path through sendChunkedTextReply instead of calling sendMessageFeishu directly, so the configured Feishu textChunkLimit is honored for completed blocks. Preserve mention targets only on the first emitted block chunk and keep sentBlockText based on the original block text for duplicate-final suppression. Add regression test with a small textChunkLimit that verifies a long block is split into chunked messages and mentions only appear on the first chunk. * fix(feishu): preserve block delivery target --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Root Cause
In
extensions/feishu/src/reply-dispatcher.ts, the block delivery path has only two behaviors:streaming: true(card mode) — blocks are consumed by a streaming card with character-by-character playback animation.streaming: false— blocks are silently dropped (returnwithout sending).There is no path for true progressive/block delivery without card-side animation playback. The
blockStreamingconfig option exists but was not wired to send blocks as independent Feishu messages.Summary
blockStreaming: trueand the streaming card path is not active, blocks are sent as independent Feishu messages immediately. Mention targets are preserved on the first block so @mentioned users receive a notification. AsentBlockTextaccumulator tracks what was sent to avoid duplicate final messages.Verification
pnpm test extensions/feishu/src/reply-dispatcher.test.ts— 83 passed (78 existing + 5 new block-streaming tests)pnpm build— OKReal behavior proof
Behavior addressed: Feishu channel blocks delivered as independent messages when
blockStreaming: trueand streaming card is inactive (streaming: false).Real environment tested: Linux 4.19.112, Node 24.13.1, commit
428b4754, branchfix/issue-55027-feishu-block-streaming, real Feishu bot credentials, live gateway with WebSocket connection.Methodology: Temporary
console.error("[PROOF]")probes were added at key decision points inreply-dispatcher.ts(dispatch init, block arrival, block send, sentBlockText accumulation) to surface the internal dispatch routing in gateway logs. These probes are for evidence collection only and are not included in the committed code.Exact steps or command run after this patch:
Evidence after fix:
Test 1 — Card mode (streaming=true): blocks go to streaming card (no regression)
Screenshots:

[Card mode — block consumed by streaming card]
Test 2 — Independent message mode (streaming=false): blocks sent as independent Feishu messages (new path)
Screenshots:

[Independent message — block sent as standalone Feishu message]
Observed result after fix:
sendMessageFeishu. Message received by the real Feishu user. ThesentBlockTextaccumulator correctly tracks sent content (38 chars). Gateway logdispatch complete (queuedFinal=false, replies=0)confirms the block was delivered without a duplicate final.What was not tested:
Revision 1 (2026-06-30)
Per ClawSweeper review:
sendChunkedTextReplyinstead of callingsendMessageFeishudirectly, so the configured FeishutextChunkLimitis honored for completed blocks (matching the established final/static fallback path).sentBlockTextbased on the original block text for duplicate-final suppression.textChunkLimit=4verifying a long block is split into chunked messages and mentions only appear on the first chunk.Updated verification:
pnpm test extensions/feishu/src/reply-dispatcher.test.ts— 84 passed (78 existing + 6 new block-streaming tests)pnpm check:test-types— OKpnpm build— OKa609e187f1