fix(discord): keep live voice transcription bounded - #42611
Conversation
|
Runtime note: this PR is now deployed on Joey's ssh-linux Hermes gateway via isolated worktree /home/j/.hermes/hermes-agent/.claude/worktrees/runtime-discord-voice-pr42611 at 5bb0eb6. Branch protection still prevents joelneleber from merging or enabling auto-merge; maintainer merge still needed upstream. |
|
✅ Verified — Discord voice transcription bounded with opt-in agent dispatch Reviewed the diff across all 7 files.
The behavioral change from always-dispatch to opt-in is well-documented in |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the voice-buffer and per-transcript agent-turn costs. The current implementation still waits for silence before completing an utterance (plugins/platforms/discord/adapter.py:664) and sends completed transcripts through the normal agent pipeline (gateway/run.py:13070-13081), so the core issue remains worth salvaging.
Problems
.env.exampleaddsHERMES_DISCORD_VOICE_TRANSCRIPT_AGENT_TURNSas a user-facing behavior setting. This conflicts with the repository policy inAGENTS.md:102-107: behavioral configuration belongs inconfig.yaml, not a newHERMES_*/.envsetting.- The added clearing test exercises the existing silence path, not the new duration cap. It should prove a fresh active speaker is emitted at
MAX_UTTERANCE_DURATION. - Current Discord YAML handling is plugin-owned by
plugins/platforms/discord/adapter.py:_apply_yaml_config(:8229-8352); salvage should validate the config path there as well asgateway/config.py.
Suggested changes
- Retain a config.yaml-only setting and remove the public environment-variable path.
- Add the active-monologue duration-cap regression test and document the config setting in
website/docs/user-guide/messaging/discord.md.
Automated hermes-sweeper review.
| # should also become an agent turn. | ||
| # HERMES_DISCORD_VOICE_TRANSCRIPT_AGENT_TURNS=false | ||
|
|
||
| # ============================================================================= |
There was a problem hiding this comment.
This makes a new non-secret HERMES_* variable the user-facing behavior switch. Repository policy requires behavioral settings to be configured through config.yaml; please remove this .env mechanism and keep the supported configuration path YAML-only.
|
|
||
| SILENCE_THRESHOLD = 1.5 # seconds of silence → end of utterance | ||
| MIN_SPEECH_DURATION = 0.5 # minimum seconds to process (skip noise) | ||
| MAX_UTTERANCE_DURATION = 30.0 # bound hot-path audio buffers during long monologues |
There was a problem hiding this comment.
Please add a regression test where last_packet_time is fresh but the PCM buffer reaches MAX_UTTERANCE_DURATION; the current added test only covers the pre-existing silence-triggered clearing path.
…vocabulary Rename discord.voice_transcripts_to_agent to voice_transcript_agent_turns to match the key name used by the reviewed implementation in NousResearch#42611, easing future reconciliation (default here stays true, preserving existing behavior; NousResearch#42611 proposes flipping it). Also document the three new keys in cli-config.yaml.example. Co-Authored-By: Claude Fable 5 <[email protected]>
Brain-Context: none present in Hermes checkout; read AGENTS.md.
Root cause summary
Discord live voice capture already cleared
VoiceReceiverbuffers aftercheck_silence()emitted a completed utterance, so the receiver was not intentionally retranscribing the same in-memory audio forever. The expensive slowdown came from the runtime feeding every completed transcript snippet throughadapter.handle_message(), which creates a full agent turn by default. Long meetings also had an inactivity timer risk: the Discord voice timeout was reset on join/playback, but not on inbound audio/transcript activity, so an active listening session could still age toward disconnect.What changed
HERMES_DISCORD_VOICE_TRANSCRIPT_AGENT_TURNSanddiscord.voice_transcript_agent_turnsopt-in behavior for deployments that do want every transcript snippet to invoke the agent.VoiceReceiverto bound per-speaker PCM buffers during long monologues..env.exampleandcli-config.yaml.example.Are we trimming/resetting audio after transcription, or retranscribing everything every time?
We are trimming/resetting.
VoiceReceiver.check_silence()returns a completed(user_id, pcm_bytes)utterance and then clears that SSRC buffer plus its last-packet timestamp. The new regression test asserts the completed utterance is returned once and a secondcheck_silence()does not re-emit the same audio. This PR also bounds long utterances so hot-path audio buffers do not grow for an entire meeting.Tests run
scripts/run_tests.sh tests/gateway/test_voice_command.py tests/gateway/test_stt_config.py tests/gateway/test_discord_voice_mixer.py -- -q/Users/j/.hermes/hermes-agent/venv/bin/python -m py_compile gateway/run.py gateway/config.py plugins/platforms/discord/adapter.py