Skip to content

fix(feishu): download attachments from replied-to messages - #26097

Closed
waynehuu wants to merge 1 commit into
NousResearch:mainfrom
waynehuu:fix/feishu-reply-attachment-download
Closed

fix(feishu): download attachments from replied-to messages#26097
waynehuu wants to merge 1 commit into
NousResearch:mainfrom
waynehuu:fix/feishu-reply-attachment-download

Conversation

@waynehuu

Copy link
Copy Markdown

Problem

When a user replies to a Feishu message that contains a file attachment and asks the agent to act on it (e.g. "deploy this webpage"), the gateway only fetched the text of the parent message via _fetch_message_text(). The attachment itself was never downloaded or cached.

The agent then had to fall back to lark-cli to re-download the file, which:

  • Requires a valid user OAuth token (fails silently when the token has expired)
  • Adds unnecessary round-trips and latency
  • Produces confusing errors like need_user_authorization (user: )

Solution

Introduce _fetch_reply_context() which, in addition to extracting the parent message text, also downloads any file/image/audio attachments from the replied-to message using the existing _download_feishu_message_resource() and _download_feishu_image() helpers.

The cached paths are merged into the current MessageEvent.media_urls so the agent receives them transparently — no lark-cli required.

_fetch_message_text() is preserved as a thin wrapper around _fetch_reply_context() for backward compatibility with any callers that only need the text.

Changes

  • gateway/platforms/feishu.py: add _fetch_reply_context(), refactor _fetch_message_text() as a wrapper, merge reply attachments into MessageEvent.media_urls
  • tests/gateway/test_feishu.py: update mock target from _fetch_message_text to _fetch_reply_context

Testing

All 397 existing Feishu gateway tests pass.

When a user replies to a message that contains a file attachment and
asks the agent to act on it (e.g. "deploy this"), the gateway only
fetched the text of the parent message, leaving the attachment
uncached. The agent then had to fall back to lark-cli to re-download
the file, which requires a valid user token and adds unnecessary
round-trips.

This change introduces _fetch_reply_context() which, in addition to
extracting the parent message text, also downloads any file/image/audio
attachments from the replied-to message and caches them via the
existing cache_document_from_bytes / cache_image_from_bytes helpers.
The cached paths are merged into the current MessageEvent's media_urls
so the agent receives them transparently, without needing lark-cli.

_fetch_message_text() is preserved as a thin wrapper around
_fetch_reply_context() for backward compatibility.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/feishu Feishu / Lark adapter comp/gateway Gateway runner, session dispatch, delivery labels May 15, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #13115 (and sibling of #24285 which is also a duplicate of #13115). There are now 4 competing PRs for Feishu reply-attachment propagation: #13115, #24285, #26063, and this one. See also #26037 (the bug report) and #14371 (related group-chat media).

@waynehuu waynehuu closed this May 15, 2026
@waynehuu
waynehuu deleted the fix/feishu-reply-attachment-download branch May 15, 2026 10:43
steveonjava pushed a commit to steveonjava/hermes-agent that referenced this pull request Aug 13, 2026
…d shim

The respawn guard (check_respawn_guard) blocked re-spawn whenever ANY
GitHub PR URL appeared in a recent task comment, regardless of the PR's
state. This deadlocked pipeline cards whose work is to *extend* an
existing draft PR: a human unblocks the card, but every dispatcher tick
re-emits respawn_guarded{active_pr} and never spawns — until the 24h
window lapses, at which point it could spawn a worker that opens a
DUPLICATE PR.

Policy: extending a *draft* PR is allowed; un-drafting, merging, or
modifying a *published* PR is a human action. Encode that at two layers:

1. Dispatcher (hermes_cli/kanban_db.py): _pr_is_draft() resolves PR draft
   state LIVE via gh at guard time (short TTL cache, hard timeout, fail
   safe to block on any uncertainty) — current ground truth, not a stale
   cached flag, so a draft->published transition takes effect immediately.
   check_respawn_guard now allows respawn when every referenced PR is a
   confirmed draft, and still blocks on published/undeterminable.

2. Tool boundary (scripts/gh-draft-guard.sh): restore the reverted shim
   and extend it — 'gh pr edit' on a published (or undeterminable) PR is
   refused unless GH_ALLOW_EDIT_PUBLISHED=1, alongside the existing
   create-->draft / ready / merge guards. Re-wire the installer into
   hermes-fork-update.sh so it self-heals across fork updates.

Tests: draft-aware cases (draft allows, published blocks, undeterminable
fails safe, any-non-draft-blocks) made hermetic by mocking _pr_is_draft;
existing active_pr tests updated to mock published state.

Unblocks the LiteLLM NousResearch#26097 consolidation card without risking a
duplicate upstream PR.
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 P2 Medium — degraded but workaround exists platform/feishu Feishu / Lark adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants