fix(tts): fail loud on unknown provider + CI guard preventing #797 regression#9
Merged
Merged
Conversation
…earch#797 regression Addresses the permanence gap revealed by toryx-private#797: commit 19098b0 reverted the Fish Audio implementation (_generate_fish_audio + elif provider == 'fish' branch), and the broken state went unnoticed for nearly a day because the dispatcher's final else: silently fell back to Edge TTS. Ray's responses were generated in a generic Microsoft voice instead of his cloned Fish voice, but no error ever surfaced. This PR closes the mechanism: 1. text_to_speech_tool dispatch: unknown provider now returns a loud JSON error listing the known providers, rather than silently routing to Edge. The 'edge' default is preserved via an explicit elif provider == 'edge' branch. 2. tests/tools/test_tts_providers.py: new CI test that parses tts_tool.py and asserts every documented provider has a generator function AND a dispatch branch. Fish Audio has a dedicated canary test. Deleting Fish (or any other provider) will now fail CI. Together these make the NousResearch#797-class regression impossible to re-ship without an explicit, visible deletion from REQUIRED_PROVIDERS — which a human reviewer has to approve. Related: closes lmsanch/toryx-private#797 (reopened)
lmsanch
added a commit
that referenced
this pull request
May 23, 2026
…earch#797 regression (#9) Addresses the permanence gap revealed by toryx-private#797: commit 19098b0 reverted the Fish Audio implementation (_generate_fish_audio + elif provider == 'fish' branch), and the broken state went unnoticed for nearly a day because the dispatcher's final else: silently fell back to Edge TTS. Ray's responses were generated in a generic Microsoft voice instead of his cloned Fish voice, but no error ever surfaced. This PR closes the mechanism: 1. text_to_speech_tool dispatch: unknown provider now returns a loud JSON error listing the known providers, rather than silently routing to Edge. The 'edge' default is preserved via an explicit elif provider == 'edge' branch. 2. tests/tools/test_tts_providers.py: new CI test that parses tts_tool.py and asserts every documented provider has a generator function AND a dispatch branch. Fish Audio has a dedicated canary test. Deleting Fish (or any other provider) will now fail CI. Together these make the NousResearch#797-class regression impossible to re-ship without an explicit, visible deletion from REQUIRED_PROVIDERS — which a human reviewer has to approve. Related: closes lmsanch/toryx-private#797 (reopened)
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.
Summary
Permanence layer for the Fish Audio regression (lmsanch/toryx-private#797 / hermes-agent#8). Closes the mechanism by which the regression could happen again, not just the specific reverted commit.
Changes
tools/tts_tool.py— split the old catch-allelse:into two paths:elif provider == "edge":— the original Edge TTS + NeuTTS fallback logic (unchanged behavior when edge is explicitly configured)else:— loud failure: returns{"success": false, "error": "TTS provider 'X' is not implemented. Known providers: edge, elevenlabs, ..."}. Logs at ERROR level.Before: any typo in
tts.provider("Fish"instead of"fish", or"fish"after a buggy revert) silently routed to Edge. You got audio back in a generic voice and no error surfaced. That's how NousResearch#797 went unnoticed for a day.After: the same typo surfaces immediately with an explicit error listing the known providers.
tests/tools/test_tts_providers.py— new CI guard (4 tests):REQUIRED_PROVIDERShas a_generate_*function intts_tool.pyprovider == "..."dispatch branch"not implemented"or"Known providers")_generate_fish_audiospecifically exists and has a dispatch branch (canary for the exact feat: add email gateway platform (IMAP/SMTP) NousResearch/hermes-agent#797 regression)If anyone deletes Fish (or any provider), CI fails with a message pointing at NousResearch#797 and explaining the pattern. They must also remove it from
REQUIRED_PROVIDERSwith a deliberate human-reviewed commit to merge.Test results (from the hermes-agent venv, locally)
What this does NOT do
provideris a known value — all existing Edge/Fish/OpenAI/etc. flows unchangedRelated