Repository navigation
fix(gateway): hold back half-streamed MEDIA:/[[…]] directives - #138551
santa-sketch wants to merge 1 commit into
Conversation
Interim stream edits could show a delivery directive before it was complete: the display cleaner only strips full deliverable tags, so `MEDIA:/home/…` without its extension, or `[[audio_`, went out as text. For a voice-only reply the cleaned final is empty, so finalize never edits the bubble and the partial path stays visible above the voice note on Telegram. Defer interim edits while the open line may still become a directive, the same way partial silence markers are deferred. The final flush is unchanged, so undeliverable tags stay visible (NousResearch#34517). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Seen in production use, and this PR fixes it. Details from the Fish Audio plugin side: Live report (Hermes v0.21.7, Telegram, Why the bubble stays. At finish the cleaned final is empty. Probe. I drove
Possible follow-up, not needed for this PR: the empty-final branch could also delete an existing preview. That would cover other cases where a preview was sent and the final cleans to empty. On the plugin side we're asking the model for one line of text next to the tag (fish-audio-hermes 1.7.4), but this PR is the real fix. |
…teway tests (#44) Report a problem: only an explicit yes to publishing, given after the user has seen the final text, approves filing (shared kit v2). fish_speak asks the agent for a short text line next to the audio tag, so a streamed Telegram reply no longer leaves a frozen "MEDIA" message (core fix: NousResearch/hermes-agent#138551). Desktop gateway tests use a temporary Hermes home for the dashboard's own profile.
What does this PR do?
With streaming on (Telegram,
transport: edit), a reply that is only a voice note(
MEDIA:/…/cache/audio/tts_….ogg) leaves a visible text bubble with a partial path(
MEDIA:/home/…) above the voice note. Same for[[audio_as_voice]]while it is being typed.Cause: interim edits fire per chunk, and
_clean_for_displayonly strips completedeliverable tags (by design, #34517). A tag streamed without its extension yet is shown.
At finish the cleaned final is empty, so
_adopt_final_textadopts nothing and the bubbleis never edited again: the partial path stays.
Fix:
_should_editnow also defers interim edits while the open (last) line of the cleanedbuffer may still become a directive: an unstripped
MEDIA:on that line, a word-startprefix of
MEDIA, or a prefix of[[audio_as_voice]]/[[as_document]]. This mirrors theexisting
_is_partial_silence_markerhold-back. The final (non-interim) flush is unchanged,so undeliverable tags still show up as before.
Related Issue
No existing issue found (searched "MEDIA stream", "streaming media tag", "audio_as_voice").
#73537 fixes the same split-tag class for the API server's SSE endpoints; this is the gateway
stream consumer path.
Type of Change
Changes Made
gateway/stream_consumer.py:_has_pending_media_directive()+ use it in_should_edit().tests/gateway/test_stream_consumer_pending_media.py: voice-only reply streamed in chunks,a split
[[audio_as_voice]], and prose mentioning "MEDIA" (still streams).How to Test
scripts/run_tests.sh tests/gateway/test_stream_consumer_pending_media.py— 2 of the 3 tests fail onmain, all pass with the fix.scripts/run_tests.shovertests/gateway/test_{stream,media,telegram,…voice,…tts,…silence}*(120 files): 1165 passed, 0 failed.Checklist
Code
python scripts/checkpasses🤖 Generated with Claude Code