Skip to content

fix(feishu): deliver MEDIA attachments inside topic threads - #76677

Closed
tidytorch wants to merge 3 commits into
NousResearch:mainfrom
tidytorch:fix/feishu-topic-media-reply-anchor
Closed

tidytorch wants to merge 3 commits into
NousResearch:mainfrom
tidytorch:fix/feishu-topic-media-reply-anchor

Conversation

@tidytorch

Copy link
Copy Markdown

What does this PR do?

Fixes outbound Feishu/Lark MEDIA: attachments in topic groups. Text replies already use ReplyMessage, but media/file sends reached the adapter without a reply anchor and fell through to CreateMessage with receive_id_type="thread_id". Feishu rejects that value with 99992402, so users receive the text but not the attachment or its failure notice.

This is an up-to-date replacement for #55067. Its two commits were cherry-picked so @qioer0762 remains the author; I resolved the conflicts against current main and re-ran the focused tests. The original PR is currently merge-conflicted and has no CI checks.

Related Issue

Fixes #39526

Related: #55067, #35576

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • gateway/platforms/base.py: include the triggering Feishu message ID in thread metadata so native media uses ReplyMessage with reply_in_thread=True.
  • plugins/platforms/feishu/adapter.py: never emit the unsupported receive_id_type="thread_id"; without an anchor, degrade to the valid chat target instead of silently dropping the message.
  • Replace the test that froze the invalid create-message behavior and add invariants for anchored topic replies and safe no-anchor fallback.

How to Test

  1. In a Feishu/Lark topic group, send a user message that makes the assistant return a valid MEDIA:/absolute/path/report.txt directive.

  2. Verify the text and native file attachment both appear inside the same topic.

  3. Run:

    scripts/run_tests.sh tests/gateway/test_stream_consumer_thread_routing.py tests/gateway/test_telegram_thread_fallback.py

Focused result on current main: 27 passed, 0 failed.

Checklist

Code

  • I've read the Contributing Guide.
  • My commit messages follow Conventional Commits.
  • I searched existing issues and PRs; this rebases and preserves authorship from the merge-conflicted fix(feishu): media/file sends in topic groups fail with 99992402 (invalid receive_id_type=thread_id) #55067.
  • My PR contains only changes related to this bug.
  • I've run the entire test suite locally; focused affected tests pass and CI is expected to run the broader matrix.
  • I've added regression tests.
  • Tested the failing user-visible behavior on Hermes v2026.7.30 / 0.19.1 with Lark on Windows 11 + WSL2; validated the updated code on Linux.

Documentation & Housekeeping

  • Documentation update: N/A; this restores the documented existing behavior.
  • cli-config.yaml.example: N/A; no config change.
  • CONTRIBUTING.md / AGENTS.md: N/A; no architecture or workflow change.
  • Cross-platform impact considered; the change is platform-scoped to Feishu metadata and SDK routing.
  • Tool descriptions/schemas: N/A.

Screenshots / Logs

The live reproduction is content-neutral: text was delivered in the correct Lark topic, while the requested .txt attachment was absent. A source-level harness also confirmed that current code selects CreateMessage for media with thread-only metadata and ReplyMessage once the message anchor is present.

…2402)

Feishu CreateMessage only accepts receive_id_type of
open_id/user_id/union_id/email/chat_id. The adapter's no-reply-anchor
branch sent receive_id_type="thread_id", which the API rejects with
[99992402] field validation failed — silently dropping media/file
attachments in topic groups (and stale-thread auto-resume sends).

Two changes that fix the whole class, not just .md files:

- gateway/platforms/base.py: _thread_metadata_for_source now carries a
  reply_to_message_id anchor for Feishu threads, so media/file sends
  (which otherwise reach the adapter with no reply target) can use the
  supported ReplyMessage + reply_in_thread path and land inside the
  topic. Telegram/other-platform metadata is untouched.
- plugins/platforms/feishu/adapter.py: when no reply anchor is
  available, _send_raw_message degrades to chat_id delivery instead of
  emitting the invalid thread_id receive_id_type, so the message still
  reaches the conversation rather than being dropped.

Relates to #39526, #35576.
- Replace the change-detector assertion that froze the buggy
  receive_id_type="thread_id" behavior with invariants: no-anchor sends
  degrade to chat_id, and anchored sends use ReplyMessage with
  reply_in_thread=True so media lands in the topic.
- Add base.py regression tests that Feishu thread metadata carries a
  reply_to_message_id anchor (and falls back to the source message id)
  without leaking telegram-only keys.

Relates to #39526.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for preserving the original investigation and removing the invalid receive_id_type="thread_id" branch. The bug remains present on current origin/main at plugins/platforms/feishu/adapter.py:4800, but this replacement still needs two routing fixes.

Problems

  • The new fallback creates against chat_id when a topic has no anchor. That avoids 99992402, but can deliver topic-scoped media into the parent chat rather than the triggering topic. The linked maintainer review on #55067 identified this same failure mode.
  • The patch does not update GatewayRunner's separate metadata builder. Post-stream media obtains metadata at gateway/run.py:18451; GatewayRunner._thread_metadata_for_target() returns only thread_id at gateway/run.py:19748-19769, and the attachment sends retain that metadata at gateway/run.py:18477-18502. Those sends still lack the Feishu reply anchor added to the base helper.

Suggested changes

  • Fail closed for a topic send with no valid reply anchor instead of creating a parent-chat message.
  • Propagate Feishu reply_to_message_id through the GatewayRunner post-stream path and cover it with an end-to-end routing test.

Automated hermes-sweeper review.

# failed (observed for media/file sends in topic groups, and for stale
# thread anchors on auto-resume). Degrade to chat_id delivery so the
# message still reaches the conversation instead of being dropped.
receive_id = chat_id

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a topic send this fallback creates in the parent chat, so it can expose an attachment outside the triggering topic. Please fail the topic delivery when no valid reply anchor exists rather than degrading a threaded message to chat_id.

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins platform/feishu Feishu / Lark adapter P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Aug 2, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Duplicate of #55067: both implement the same Feishu reply-anchor propagation and replace invalid receive_id_type=thread_id creation with chat delivery fallback for topic media.

@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Aug 2, 2026
@tidytorch

Copy link
Copy Markdown
Author

Addressed both review findings in 4a82a0d: topic-scoped sends now fail closed when no reply anchor exists, and GatewayRunner post-stream media metadata now carries the triggering Feishu message anchor. Added focused regressions for both paths; 30 related tests pass locally.

@tidytorch

Copy link
Copy Markdown
Author

FlyingShuttle has changed its pre-v3.0.0 policy to consume official Hermes releases without carrying or proposing upstream patch work. Closing this project-driven PR; topic-thread attachment support remains a documented limitation until an official Hermes release addresses it.

@tidytorch tidytorch closed this Aug 5, 2026
@tidytorch
tidytorch deleted the fix/feishu-topic-media-reply-anchor branch August 5, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/feishu Feishu / Lark adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feishu: MEDIA attachments sent via topic/thread reply land in main conversation instead of thread

4 participants