Skip to content

fix(feishu): fall back media replies#98320

Merged
steipete merged 3 commits into
openclaw:mainfrom
TUARAN:fix/feishu-media-reply-fallback
Jul 21, 2026
Merged

fix(feishu): fall back media replies#98320
steipete merged 3 commits into
openclaw:mainfrom
TUARAN:fix/feishu-media-reply-fallback

Conversation

@TUARAN

@TUARAN TUARAN commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes Feishu image and file delivery when the quoted reply target has been withdrawn or deleted.

  • route image and file replies through the existing sendReplyOrFallbackDirect contract
  • preserve the native-thread safety gate through allowTopLevelReplyFallback
  • forward that safety flag from the reply dispatcher into media sends
  • cover returned and thrown unavailable-target errors for image and file replies

Closes #98311.

Verification

  • node scripts/run-vitest.mjs extensions/feishu/src/media.test.ts extensions/feishu/src/reply-dispatcher.test.ts (126 tests passed)
  • node_modules/oxfmt/bin/oxfmt --check extensions/feishu/src/media.test.ts extensions/feishu/src/media.ts extensions/feishu/src/reply-dispatcher.ts extensions/feishu/src/send.ts
  • git diff --check upstream/main...HEAD
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/main --codex-bin /Applications/ChatGPT.app/Contents/Resources/codex --stream-engine-output (clean; no accepted/actionable findings, correctness 0.9)
  • node_modules/.bin/tsx /private/tmp/feishu-98320-live-proof-20260716.mts (real image and file recovery passed; proof messages cleaned up)
  • refreshed from current upstream/main 9c6c8446a7d; exact tested head 951c75ff096ddd35d3a0ae99c7de47134fb864d5

Real behavior proof

Behavior addressed: Feishu image and file replies no longer disappear when their quoted reply target was withdrawn; the existing guarded fallback delivers them as top-level messages when that fallback is allowed.

Real environment tested: Exact head 951c75ff096ddd35d3a0ae99c7de47134fb864d5 on macOS arm64, using the configured real Feishu Open Platform app and a paired Feishu recipient. The run used the current branch's real sendMessageFeishu, sendMediaFeishu, upload, reply-fallback, direct-create, and message-readback paths.

Exact steps or command run after this patch: node_modules/.bin/tsx /private/tmp/feishu-98320-live-proof-20260716.mts. For both image and file cases, the harness created a real Feishu message, withdrew it through the real API, called sendMediaFeishu with that withdrawn message as replyToMessageId and allowTopLevelReplyFallback: true, read the recovered message back from Feishu, verified its type and receipt, then deleted the proof message.

Evidence after fix:

{
  "head": "951c75ff096",
  "environment": "real Feishu Open Platform app + paired recipient",
  "results": [
    {
      "kind": "image",
      "withdrawnCode": 230011,
      "recoveredTopLevel": true,
      "readbackType": "image",
      "receiptMatchesReadback": true
    },
    {
      "kind": "file",
      "withdrawnCode": 230011,
      "recoveredTopLevel": true,
      "readbackType": "file",
      "receiptMatchesReadback": true
    }
  ],
  "cleanupCompleted": true
}

Observed result after fix: Both real reply attempts returned Feishu code 230011 (The message was withdrawn.). The current OpenClaw path recovered both uploads through top-level creation; Feishu readback reported image and file, both returned message IDs matched the OpenClaw receipts, and all proof messages were removed afterward.

What was not tested: Feishu code 231003 (message not found) was covered by focused regression tests but not induced in the live tenant. Native topic-thread fallback was not exercised live because it would require creating a user-visible topic scenario; its allow/deny boundary is covered by the focused tests. The live run used one configured Feishu tenant and one paired recipient.

@openclaw-barnacle openclaw-barnacle Bot added channel: feishu Channel integration: feishu size: S labels Jul 1, 2026
@clawsweeper

clawsweeper Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 15, 2026, 10:33 PM ET / July 16, 2026, 02:33 UTC.

Summary
Routes Feishu image and file replies through the established unavailable-target fallback, forwards the dispatcher’s top-level fallback safety flag, and adds regression coverage for returned and thrown failures.

PR surface: Source +24, Tests +93. Total +117 across 4 files.

Reproducibility: yes. at source level. Current main’s media reply path lacks the established unavailable-target fallback, and the focused tests model both returned and thrown Feishu error shapes; the submitted live run additionally proves the repaired allowed-fallback path.

Review metrics: none identified.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] The branch is behind current main and its dependency/aggregate gate currently fails, so the exact three-way merge result has not completed required gating.
  • [P1] The live proof exercises the permitted top-level recovery path but not a native topic-thread denial; that critical no-cross-thread boundary is supported by focused tests rather than live tenant proof.

Maintainer options:

  1. Refresh and gate the exact head (recommended)
    Rebase or refresh onto current main, verify the dependency failure is resolved, and merge only after the focused delivery and thread-boundary checks pass on that head.
  2. Pause if integration drift appears
    Keep the PR open for a narrow reconciliation if current-main changes alter the shared fallback helper, dispatcher flag, or receipt behavior.

Next step before merge

  • No automated repair is indicated; maintainers should refresh the branch onto current main, clear the exact-head dependency gate, and perform normal merge review.

Security
Cleared: The patch adds no dependency, credential, persistence, workflow-permission, lifecycle-hook, or downloaded-code surface and reuses existing Feishu API paths.

Review details

Best possible solution:

Refresh this canonical branch onto current main, retain the shared fallback helper and explicit thread-safety flag, rerun the focused Feishu tests plus required gates on the exact mergeable head, then land it and close the linked issue and weaker duplicate PR.

Do we have a high-confidence way to reproduce the issue?

Yes at source level. Current main’s media reply path lacks the established unavailable-target fallback, and the focused tests model both returned and thrown Feishu error shapes; the submitted live run additionally proves the repaired allowed-fallback path.

Is this the best way to solve the issue?

Yes. Reusing the existing text/card fallback contract and forwarding its explicit safety flag is narrower and less drift-prone than implementing a second media-specific recovery path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 154d1277e12e.

Label changes

Label justifications:

  • P2: This fixes a bounded Feishu message-loss bug affecting image and file replies only when their quoted target becomes unavailable.
  • merge-risk: 🚨 message-delivery: An incorrect fallback or safety-flag integration could still drop media or deliver it at the wrong Feishu conversation level.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Exact-head live Feishu output demonstrates after-fix image and file recovery with withdrawn targets, server readback, receipt matching, and cleanup; private tenant details were not exposed.
  • proof: sufficient: Contributor real behavior proof is sufficient. Exact-head live Feishu output demonstrates after-fix image and file recovery with withdrawn targets, server readback, receipt matching, and cleanup; private tenant details were not exposed.
Evidence reviewed

PR surface:

Source +24, Tests +93. Total +117 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 3 57 33 +24
Tests 1 93 0 +93
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 150 33 +117

What I checked:

Likely related people:

  • steipete: Authored the merged Feishu unavailable-target fallback that defines the contract extended by this PR and has substantial prior history in the send/thread paths. (role: introduced related behavior; confidence: high; commits: f9c0dc2d2b9e, 2a252a14cc9f, 6ea3a47dae5a; files: extensions/feishu/src/send.ts, extensions/feishu/src/reply-dispatcher.ts, extensions/feishu/src/bot.ts)
  • m1heng: The Feishu package README identifies this person as the plugin’s community owner, making them a relevant reviewer for delivery and thread-boundary behavior. (role: plugin community owner; confidence: medium; files: extensions/feishu/README.md, extensions/feishu/package.json)
  • Madoka: Prior merged work added broad Feishu reply routing, reply-target forwarding, and topic-aware behavior adjacent to this fallback boundary. (role: reply routing feature contributor; confidence: medium; commits: 63ce7c74bdc0; files: extensions/feishu/src/send.ts, extensions/feishu/src/reply-dispatcher.ts, extensions/feishu/src/bot.ts)
  • kcinzgg: Introduced the Feishu replyInThread configuration family whose safety boundary this patch preserves. (role: replyInThread feature contributor; confidence: medium; commits: 89669a33bd67; files: extensions/feishu/src/config-schema.ts, extensions/feishu/src/send.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-01T01:40:37.478Z sha f887f14 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-05T02:08:36.809Z sha d622350 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-08T09:18:44.907Z sha 5869fdc :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T03:05:12.164Z sha 5869fdc :: needs maintainer review before merge. :: none
  • reviewed 2026-07-16T01:48:56.252Z sha 951c75f :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 1, 2026
wangmiao0668000666 pushed a commit to wangmiao0668000666/openclaw that referenced this pull request Jul 1, 2026
Reverts the r2-vulnerable Layer 4 loopback test that mutated
node_modules/@larksuiteoapi/node-sdk at module load. ClawSweeper r2
flagged the node_modules patching as 'merge-risk: 🚨 automation'
P1, and dropped rating from 🦪 silver shellfish to 🧂 unranked krab.

Removing this test file drops the PR diff from +780/-77 to +392/-77
(50% reduction). Layer 1-3 proof remains: 10 mock-based media tests
in media.reply-fallback.test.ts + 3 dispatcher propagation tests
in reply-dispatcher.test.ts, all 112/112 passing.

The 'real Feishu Open Platform delivery proof' blocker remains in the
P1 'real behavior proof' category — same as PR openclaw#98320 (TUARAN)
and the other competing Feishu fix. That blocker is maintainer-decision
category per the skill §6.7 'Mechanical vs architectural blocker'.

PR body is being updated separately to add '## Evidence' top-level
heading per checklist openclaw#23 (real-behavior-proof-check.mjs policy).
@wangmiao0668000666

Copy link
Copy Markdown
Contributor

Hi @TUARAN — both of our PRs (#98320 and #98329) are open candidates for #98311 and both are blocked on the same "real Feishu setup proof" requirement.

The approaches are essentially the same: route media replies through the existing sendReplyOrFallbackDirect fallback helper. #98329 additionally fixes the r1 ClawSweeper P2 finding that the dispatcher did not forward allowTopLevelReplyFallback into sendMediaFeishu, and includes 13 regression tests with a revert-line gate for that forwarding.

Rather than having two competing PRs consume maintainer review bandwidth, would you be open to closing #98320 in favor of #98329? Happy to credit you in the PR body or co-author the commit if any of your approach was used. If you prefer to keep #98320 as the canonical branch, I'm also willing to close #98329 and port the dispatcher-forwarding fix + tests over to your branch.

Let me know what you think.

@wangmiao0668000666

Copy link
Copy Markdown
Contributor

I just closed my own attempt (#98329) after comparing the two branches. Both fix the same Feishu image/file withdrawn-reply-target fallback gap by reusing sendReplyOrFallbackDirect, but this branch is narrower (size S) and keeps the thread-boundary guard intact.

The remaining blocker for both PRs is real Feishu Open Platform proof. If there is anything I can do to help verify the fallback path — e.g., reviewing the mock-based regression tests or running a local branch variation — let me know.

@TUARAN

TUARAN commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for comparing the branches and consolidating on #98320.

I agree this is the better canonical branch to keep open. The dispatcher forwarding piece is already present here, and the remaining blocker is real Feishu proof rather than patch shape, so I’d rather keep the narrower diff instead of mixing in the larger branch.

I’ll keep pushing on the proof path from here. If maintainers later want extra dispatcher-only regression coverage, I can port that minimally instead of merging the broader history.

@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 2, 2026
@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. and removed status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 5, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 13, 2026
@TUARAN
TUARAN force-pushed the fix/feishu-media-reply-fallback branch from 5869fdc to 951c75f Compare July 16, 2026 01:43
@TUARAN

TUARAN commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Refreshed this PR from current main and reran all proof on exact head 951c75ff096ddd35d3a0ae99c7de47134fb864d5.

  • focused Feishu tests: 126/126 passed
  • oxfmt and git diff --check: passed
  • mandatory Codex autoreview: clean, no accepted/actionable findings
  • real Feishu image path: withdrawn reply returned 230011, recovered top-level, server readback image, receipt matched
  • real Feishu file path: withdrawn reply returned 230011, recovered top-level, server readback file, receipt matched
  • proof messages were deleted after readback

The PR body now contains the refreshed six-field proof and exact commands.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@steipete steipete self-assigned this Jul 21, 2026
@steipete
steipete force-pushed the fix/feishu-media-reply-fallback branch from 951c75f to dc9c348 Compare July 21, 2026 05:45
@clawsweeper

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(feishu): fall back media replies This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@steipete
steipete merged commit 37ac5d6 into openclaw:main Jul 21, 2026
94 of 96 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 21, 2026
* fix(feishu): fall back media replies

* test(feishu): polish media fallback coverage

* test(feishu): cover media fallback policy wiring

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feishu image/file replies lose media on withdrawn/recalled reply targets that text replies survive

3 participants