Repository navigation
fix(gateway): voice turns drop the /voice join message id and name uncached speakers - #133598
Merged
unsupportedpastels merged 2 commits intoOct 6, 2026
Conversation
A typed `/voice join` binds that message's source, message_id included, and `_voice_input_source` rebuilt every voice turn from it. The join message is not the voice turn's trigger: run.py exports source.message_id as HERMES_SESSION_MESSAGE_ID (reply anchoring), and on main it also set the presence bit in the prompt-pin key, so the note-gating cache miss this PR fixes only surfaced for native slash-command joins. Clear it on the way out. Review-fix for NousResearch#127944. [adapted onto main: NousResearch#133463 resolves the speaker name inline in _voice_input_source, so the clear lands in main's block; the test moved to test_discord_turn_prompt_parity.py, a typed `/voice join` id on the bound source] (cherry picked from commit fe70c11)
guild.get_member() is cache-only, so a speaker who had never typed in the guild (no member intent, or joined voice straight away) rendered as the bare user id while their text turns render a display name: the session-context prompt differed again on every switch. Fall back to the cached global user (global name / username) before giving up; a guild nick still wins when the member is cached. Suggested in the first review, reproduced independently (F3 on the thread). [adapted onto main: NousResearch#133463 resolves the speaker name inline in _voice_input_source, not through DiscordAdapter.voice_member_display_name, so the fallback is a small helper there. It runs after the /voice join invoker's bound name, which is the nickname their typed turns carry; a cached global name would differ from it. Tests moved to test_discord_turn_prompt_parity.py] (cherry picked from commit 295a01f)
9 of 10 tasks
unsupportedpastels
deleted the
fix/voice-turn-trigger-and-uncached-name
branch
October 6, 2026 02:53
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.
What does this PR do?
Voice-channel turns rebuild their
SessionSourcefrom the copy bound at/voice join. #133463 made that rebuilt source carry the speaker's display name and the channel's current labels, so typing and talking now render the same pinned prompt. Two problems from #127944 were not part of that fix, and this PR carries teknium's commits for both from that PR onto currentmain:/voice joinmessage id. A typed/voice joinbinds that message's source,message_idincluded, and every later voice turn kept it.run.pyexportssource.message_idasHERMES_SESSION_MESSAGE_ID, the turn's triggering message. On Discord, the background-process tool stores it aswatcher_message_id, the reply anchor for completion notices, so a process started from a voice turn recorded the old/voice joinmessage as its trigger. The cron and Kanban tools read it only for Slack and Telegram, so they aren't affected here. Voice turns now clear it. This no longer affects the prompt cache, because fix(discord): slash, /thread and voice turns carry a message turn's prompt inputs #133463 made the triggering-message note static.guild.get_member()is cache-only. A speaker it misses who isn't the/voice joininvoker rendered as**User:** "<id>", so their turns still re-rendered the pinned prompt. The rebuilt source now falls back to the cached user's display name (global name or username) before the id.main/voice joininvoker, member not cached/voice joinmessage_idmessage_idAdapted onto
main. #127944 looked the name up through a newDiscordAdapter.voice_member_display_name. Onmain, #133463 resolves it inline in_voice_input_source, so both commits are rebuilt there, with conflict notes in the commit messages:_cached_user_display_namehelper.tests/gateway/test_discord_turn_prompt_parity.py.test_voice_session_prompt.pyisn't onmain.Known gap (out of scope). A speaker who has a server nickname, but is in neither the member cache nor the join binding, now gets their global name. That beats an id, but still differs from the nickname their typed messages carry. Matching it exactly would need a member fetch over the API on the voice path.
Related Issue
No issue. These are the remaining parts of #127944, whose name and triggering-note fixes landed in #133463.
Credit: both commits are @teknium1's review fixes on #127944, cherry-picked with
-xand authorship kept. The underlying work and diagnosis are @matttmcfarland's #127944, and @andrexibiza independently reproduced the uncached-speaker fallback (F3 on that PR).Type of Change
Changes Made
gateway/run_voice.py:_voice_input_sourceclears the boundmessage_id, and both its branches fall back to_cached_user_display_name(new) before the bare id.tests/gateway/test_discord_turn_prompt_parity.py: the voice parity test binds a typed/voice joinid and asserts that the voice turn doesn't carry it. The uncached case covers another speaker cached only as a user, one cached nowhere, and no binding at all. The joiner keeps their bound nickname over their cached global name.How to Test
pytest tests/gateway/test_discord_turn_prompt_parity.py -q: 12 passed.main'srun_voice.py, 4 of them fail: the message-id assertion in every voice case. With only the first commit'srun_voice.py, 1 fails: the uncached-speaker case.ruffpasses, andtyreports the same 34 diagnostics on the two files as onmain.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass: I ran the 113 related files above, not the full suitepython scripts/checkpasses (the blocking lint and code-health checks CI runs)Documentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AInfographic