fix(feishu): download attachments from replied-to messages - #26097
Closed
waynehuu wants to merge 1 commit into
Closed
fix(feishu): download attachments from replied-to messages#26097waynehuu wants to merge 1 commit into
waynehuu wants to merge 1 commit into
Conversation
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.
Collaborator
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-clito re-download the file, which: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_urlsso 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 intoMessageEvent.media_urlstests/gateway/test_feishu.py: update mock target from_fetch_message_textto_fetch_reply_contextTesting
All 397 existing Feishu gateway tests pass.