fix(gateway): preserve voice_only semantics for text input - #73938
Conversation
Independent reproduction and local runtime verificationI reproduced this regression on a live Telegram gateway and applied this PR's production fix as a temporary local patch. ReproductionThe chat had an explicit persisted mode of: {
"telegram:<redacted>": "voice_only"
}Global On unpatched current Hermes, sending typed text still produced both the normal text reply and an unwanted TTS voice reply. The adapter reports auto-TTS enabled for the chat after the persisted or (voice_mode != "off" and adapter_auto_tts)Local fix appliedI applied the gate from this PR to the current or (voice_mode is None and adapter_auto_tts)I also carried the focused regression test, adapted only to its current location in VerificationAfter applying the patch and restarting the gateway:
Focused suites run: This confirms the PR fixes the reported regression in a real Telegram runtime, not only in an isolated unit test. Current GitHub stateThe PR workflow did not fail its tests. The CI run is currently recorded as https://github.com/NousResearch/hermes-agent/actions/runs/30428499647 The PR has since become conflicting with current Runtime media evidenceThe repaired proof clip below shows the full regression sequence on Telegram: voice mode is enabled, typed text is sent, and Hermes responds with both a voice attachment and a text reply. Open the 22-second MP4 proof clip The clip is silent and trimmed to the relevant interaction. The original recording was retained separately. |
55f5f7a to
01b3727
Compare

Summary
all,voice_only,off) authoritative over the adapter/global auto-TTS fallback.voice_onlychats from speaking normal text-input replies after the mode is synced into the adapter as an auto-TTS opt-in.voice.auto_ttsbehavior for chats with no explicit voice mode.Root cause
The runner gate added in #73508 used
voice_mode != "off" and adapter_auto_ttsas a broad fallback./voice onstoresvoice_onlyand also enables auto-TTS for that chat in the adapter, soadapter_auto_ttsisTruefor both text and voice input. That widenedvoice_onlyinto the equivalent ofall.The fallback should apply only when no explicit chat mode exists. An explicit
voice_onlymode should continue to require voice input.Regression test
The existing
voice_onlygate test now includes the real adapter state produced by mode synchronization (_should_auto_tts_for_chat(...) == True). It fails on currentmainfor text input and passes with this fix, while still confirming streamed voice input is spoken.Validation
Focused suites:
tests/gateway/test_auto_voice_reply_format.pytests/gateway/test_voice_command.pytests/gateway/test_base_auto_tts_output_format.pytests/gateway/test_telegram_voice_v0_regressions.py