Skip to content

fix(gateway): prevent silent message loss when extract pipeline strip… - #29499

Closed
LifeJiggy wants to merge 1 commit into
NousResearch:mainfrom
LifeJiggy:fix/discord-response-dropped
Closed

fix(gateway): prevent silent message loss when extract pipeline strip…#29499
LifeJiggy wants to merge 1 commit into
NousResearch:mainfrom
LifeJiggy:fix/discord-response-dropped

Conversation

@LifeJiggy

Copy link
Copy Markdown
Contributor

Title: fix(gateway): prevent silent message loss when extract pipeline strips tool-using responses

Summary

When a response with api_calls >= 2 goes through the extract pipeline
(extract_media → extract_images → extract_local_files), text_content
can be reduced to an empty string. The if text_content: send guard on
line 3236 then silently drops the response — no error, no warning, just
a missing Sending response log line.

Log a WARNING when this happens and fall back to the raw response so
the message is delivered instead of silently lost.

Changes

File Change
gateway/platforms/base.py:3201-3210 Added warning + fallback when text_content is empty after extract pipeline

Fixes #29346

@alt-glitch alt-glitch added P1 High — major feature broken, no workaround type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery labels May 20, 2026
…s tool-using responses

When a response with api_calls>=2 goes through the extract pipeline
(extract_media, extract_images, extract_local_files), the text_content
can be reduced to empty. Log a warning and fall back to the raw response
to prevent silent message drops.

Fixes NousResearch#29346
@LifeJiggy
LifeJiggy force-pushed the fix/discord-response-dropped branch from 8404f61 to f7bfae3 Compare May 21, 2026 02:21
banditburai added a commit to banditburai/hermes-agent that referenced this pull request Jun 1, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
teknium1 pushed a commit that referenced this pull request Jun 2, 2026
#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only #33842 and the unsafe
  raw-fallback #29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the #33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
@LifeJiggy

Copy link
Copy Markdown
Contributor Author

@teknium1 PTAl

changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only #33842 and the unsafe
  raw-fallback #29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the #33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
kossteg pushed a commit to kossteg/hermes-agent that referenced this pull request Jun 16, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
@teknium1

Copy link
Copy Markdown
Contributor

This looks implemented on current main by a broader follow-up fix. Automated hermes-sweeper review.

Evidence:

  • gateway/platforms/base.py:4232 snapshots the pre-extract response before the extract pipeline named in this PR.
  • gateway/platforms/base.py:4260 recovers when extraction leaves no text or attachments, logs response_delivery_recovered at warning level, and restores text_content so the send guard delivers the message.
  • gateway/platforms/base.py:4469 also logs response_delivery_dropped at error level if a non-empty response still produces nothing deliverable, so the failure mode is no longer silent.
  • tests/gateway/test_tool_response_drop_recovery.py:1 covers the Discord: tool-using responses (api_calls≥2) silently dropped — no Sending response log after response ready #29346 silent-drop regression across Discord and Telegram, including recovery, no duplicate attachment fallback, and loud unrecoverable drops.
  • Commit a1f76ba7e99629b2450bc72df4aff1d4da5cf41c (fix(gateway): recover extract-stripped tool responses on all platforms (#29346)) explicitly notes that it supersedes the raw-fallback approach from fix(gateway): prevent silent message loss when extract pipeline strip… #29499.
  • The fix is contained in tag v2026.6.5.

@teknium1 teknium1 closed this Jun 20, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jun 20, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
NousResearch#29346)

The extract pipeline (extract_media/extract_images/extract_local_files +
directive strips) can reduce a non-empty tool-using response to empty
text_content with no deliverable attachment. The 'if text_content' send
guard then silently skips delivery: a 'response ready' log with no
'Sending response', no error, and the answer never reaches the user.

- A2: snapshot the pre-extract response; when extraction yields empty text
  and no image/local/media attachment, deliver the recovered original from
  the post-extract_media body (so a spaced MEDIA path can't leak). Applies
  on ALL platforms (supersedes the Discord-only NousResearch#33842 and the unsafe
  raw-fallback NousResearch#29499).
- A3: loud delivery invariant - a non-empty response that produces nothing
  deliverable logs response_delivery_dropped at ERROR; every recovery logs
  response_delivery_recovered. No silent drop survives.
- Factor a _strip_media_directives helper for the [[...]] strips; MEDIA
  stripping stays owned by extract_media, whose grammar handles spaced and
  quoted paths.
- Salvaged + de-scoped the NousResearch#33842 test harness to all platforms; added
  unrecoverable-drop and no-leak regression tests.
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 P1 High — major feature broken, no workaround sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord: tool-using responses (api_calls≥2) silently dropped — no Sending response log after response ready

3 participants