fix(feishu): add searchable streaming fallback#74808
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 12, 2026, 11:10 AM ET / 15:10 UTC. Summary PR surface: Source +32, Tests +35, Docs +4. Total +71 across 5 files. Reproducibility: no. not at high confidence end to end. Current source and the linked report establish that streamed replies use interactive cards, while the harness proves the proposed outbound Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the default-off fallback only after a real Feishu tenant proves that the exact emitted Do we have a high-confidence way to reproduce the issue? No, not at high confidence end to end. Current source and the linked report establish that streamed replies use interactive cards, while the harness proves the proposed outbound Is this the best way to solve the issue? Unclear. Reusing the existing post sender behind a default-off setting is a narrow implementation, but it is only the best solution if Feishu owners accept the extra visible message and live tenant proof confirms that the post is actually searchable. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e728957989f6. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +32, Tests +35, Docs +4. Total +71 across 5 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
|
17d2087 to
3572c0f
Compare
f42b457 to
3c24702
Compare
3c24702 to
27816ac
Compare
d5dc8ef to
963b9bb
Compare
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
0a49d2b to
6d78d0e
Compare
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
6d78d0e to
3ee9dc1
Compare
|
ClawSweeper PR egg 🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat. Where did the egg go?
|
|
No Feishu/Lark tenant access on my side to capture the live search-result proof ClawSweeper is asking for. Requesting a maintainer with Feishu tenant credentials to either pick up live proof capture or apply a proof override. Code review status from ClawSweeper (latest 2026-05-24 02:19 UTC): patch quality 🐚 platinum hermit, default-off opt-in setting ( |
deba93b to
29c2ce5
Compare
|
@clawsweeper re-review Rebased onto current |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
The code is unchanged and was rated clean in the last verdict (platinum hermit, no findings). The only remaining blocker is live Feishu/Lark tenant proof showing a streamed reply surfacing in tenant search after enabling I do not have access to a Feishu/Lark tenant to capture that, and I will not submit fabricated screenshots/logs. Requesting one of:
Real behavior proof: |
|
Heads up: this PR needs to be updated against current |
|
Status update to tee this up for maintainer review. Code / surface is ready:
Remaining blocker is the proof gap, which needs maintainer/tenant access: Per the two maintainer options ClawSweeper laid out, this needs one of:
Happy to adjust the implementation if maintainers prefer a different delivery shape for the fallback. |
c85ab81 to
0e7733b
Compare
0e7733b to
855c22b
Compare
|
@clawsweeper re-review Rebased onto current The real-behavior proof in the body now drives the actual production
Full captured output is in the PR body Evidence field. The only remaining gap is a live Feishu tenant conversation-search hit, which needs tenant credentials I do not have. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
855c22b to
9cc80a0
Compare
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Requesting a maintainer proof override ( Current ClawSweeper verdict on head What is proven (PR body Evidence, captured through the real production
What cannot be shown from the contributor side: a redacted live Feishu/Lark tenant conversation-search hit, which requires Feishu app credentials and a configured tenant I do not have. I will not submit fabricated tenant screenshots/logs. This is a safe override candidate: the setting is default-off (no change for existing deployments on upgrade), it reuses the existing Per ClawSweeper's maintainer options, requesting one of:
Happy to adjust the fallback's delivery shape if maintainers prefer a different approach. |
|
Verification update The Real behavior proof in the description is backed by a runnable harness that drives the production Re-ran at this PR head: Captured outbound sequence (real call order):
The harness asserts these (BEFORE sends == Not covered: the core typing-dispatcher wrapper and the live Feishu socket are simulated. Whether Feishu's index ultimately surfaces the post is governed by Feishu's documented @clawsweeper re-run |
|
Closing this for now. The change itself is sound and proven at the code/network layer: the searchable What is blocking it from landing is not code, it is verification and product sign-off that need a live tenant and an owner decision:
Rather than leave it open indefinitely waiting on both, closing. Happy to reopen if someone can supply a Feishu test tenant for the live search-hit screenshot and a maintainer signs off on the duplicate-message/quota tradeoff. The branch and proof harness are kept locally. |
Summary
channels.feishu.streamingSearchFallbacksettingFixes #74767
Tests
pnpm test extensions/feishu/src/reply-dispatcher.test.ts extensions/feishu/src/streaming-card.test.tspnpm test extensions/feishu/src/tools-config.test.ts extensions/feishu/src/policy.test.ts extensions/feishu/src/accounts.test.tspnpm exec oxfmt --check --threads=1 extensions/feishu/src/reply-dispatcher.ts extensions/feishu/src/streaming-card.ts extensions/feishu/src/reply-dispatcher.test.ts docs/channels/feishu.md extensions/feishu/src/config-schema.ts extensions/feishu/openclaw.plugin.jsonReal behavior proof
Behavior addressed: Feishu users searching their conversation history for content from streamed assistant replies could not find any matches (#74767), because OpenClaw's Feishu streaming path closes the final text into a CardKit interactive message (
msg_type: "interactive"), and Feishu's conversation-search index does not cover interactive card content; onlytextandpostmessages are indexed, per https://open.feishu.cn/document/server-docs/im-v1/message/create.Real environment tested: Linux, real OpenClaw checkout at this PR head, Node 22.19. The repro drives the actual production
createFeishuReplyDispatcher(the function this PR changes) through a complete streamed final turn withchannels.feishu.streamingSearchFallbackfirst false, then true. The streaming card session,send.ts, the Lark client request construction, and the dispatcher gating are all unmodified production code; the only thing replaced is the literal network socket: the Lark SDK HTTP transport and the SSRF-guarded fetch the streaming card uses are swapped for an in-memory capturer that records every outbound Feishu API request and returns canned success bodies. No live Feishu credentials are exercised.Exact steps or command run after this patch:
The repro registers the in-memory capturer, builds a config for each setting value, drives one full streamed final reply through
createFeishuReplyDispatcher(deliver final, then idle/close), and records every outbound Feishu API request with itsmsg_type.Evidence after fix: copied live output (full before/after capture, no redaction needed) from this PR head:
Observed result after fix: with the flag off (current main), the streamed final turn produces only the interactive streaming card (
msg_type: "interactive"), so no search-indexable message is emitted; this is the symptom in #74767. Withchannels.feishu.streamingSearchFallback: true, the dispatcher additionally invokessendSearchableStreamingFallbackafter the card closes, and the captured outbound request is anim.message.replywithmsg_type: "post"whose content carries the full final reply text verbatim, which Feishu's conversation-search index covers. The duplicate visible message is the documented tradeoff and the setting stays default-off, so existing Feishu deployments are unaffected.What was not tested: a live Feishu Open Platform round-trip against a real tenant, which requires Feishu app credentials and a configured chat. The capture above is the actual outbound JSON the production dispatcher produces; whether Feishu's search index ultimately surfaces the post is governed by Feishu's documented
msg_typeindexing rules cited above. A maintainer with a Feishu test tenant can confirm the end-to-end search hit if desired.