From d15adb490b634dd22a65a1c8d7f4ec9fa74816b4 Mon Sep 17 00:00:00 2001 From: historia Date: Tue, 1 Sep 2026 03:38:50 -0400 Subject: fix: hide speech-to-speech only models from config wizard --- app/tests/test_backends_audiocpp.py | 25 +++++++++++++++++++++++++ app/tests/test_hub.py | 12 ++++++++---- app/tests/test_tts.py | 7 +++++-- 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'app/tests') diff --git a/app/tests/test_backends_audiocpp.py b/app/tests/test_backends_audiocpp.py index 8b1698b..7edb3c9 100644 --- a/app/tests/test_backends_audiocpp.py +++ b/app/tests/test_backends_audiocpp.py @@ -385,6 +385,31 @@ class LoadModelCatalogTests(unittest.TestCase): self.assertNotIn("empty_tts", [entry["family"] for entry in catalog]) + def test_skips_speech_to_speech_only_families(self): + # PersonaPlex-style specs: categorized "tts" but with a task list + # naming no text-synthesis capability — the family cannot narrate + # text and every request would fail, so it is never offered for + # install (the generic task check, no family names hardcoded). + _write_spec(self.checkout, "personaplex", tasks=("s2s",)) + catalog = make_server.catalog.load_model_catalog(self.checkout) + self.assertNotIn("personaplex", + [entry["family"] for entry in catalog]) + + def test_design_only_family_is_kept(self): + # Voice design is a text-synthesis task: a vdes-only spec stays + # installable. + _write_spec(self.checkout, "designer", tasks=("vdes",)) + catalog = make_server.catalog.load_model_catalog(self.checkout) + self.assertIn("designer", [entry["family"] for entry in catalog]) + + def test_taskless_tts_category_fallback_is_kept(self): + # A spec without a task list keeps the old category fallback, so + # a future/malformed "tts" spec is not silently dropped. + _write_spec(self.checkout, "mystery_tts", tasks=()) + catalog = make_server.catalog.load_model_catalog(self.checkout) + self.assertIn("mystery_tts", + [entry["family"] for entry in catalog]) + def test_families_sorted_alphabetically_by_display_name(self): catalog = make_server.catalog.load_model_catalog(self.checkout) names = [entry["display_name"].lower() for entry in catalog] diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py index 80a97d0..ddd6ec0 100644 --- a/app/tests/test_hub.py +++ b/app/tests/test_hub.py @@ -1238,7 +1238,9 @@ class ConvertFlowTests(unittest.TestCase): self.assertEqual(kwargs["model_ids"], ["alpha"]) self.assertEqual(kwargs["model_voices"], {"alpha": "narrator"}) self.assertEqual(kwargs["run_notice"], - "skipped non-TTS model(s): plex") + "skipped plex — speech-to-speech, not TTS: it " + "cannot turn text into audio. Consider deleting " + "the model") def test_all_pick_refuses_when_every_model_is_non_narrating(self): # With nothing left to generate with after the skip, the All pick @@ -1260,9 +1262,11 @@ class ConvertFlowTests(unittest.TestCase): self._field("model_id")["value"] = hub.AUDIOCPP_MODEL_ALL error = voice_field["validate"]("narrator") self.assertIsNotNone(error) - self.assertIn("plex-1", error) - self.assertIn("plex-2", error) - self.assertIn("synthesize text", error) + self.assertIn("plex-1, plex-2", error) + self.assertIn("speech-to-speech, not TTS", error) + self.assertIn("cannot turn text into audio", error) + self.assertIn("Consider deleting the models", error) + self.assertIn("nothing for an 'All' run", error) def test_all_voice_falls_back_per_capability(self): # A CustomVoice entry cannot clone: it synthesizes with a built-in diff --git a/app/tests/test_tts.py b/app/tests/test_tts.py index 8403913..6c245e5 100644 --- a/app/tests/test_tts.py +++ b/app/tests/test_tts.py @@ -1051,7 +1051,9 @@ class AudioCppFamilyDetectionTests(unittest.TestCase): {"id": "tts-1", "family": "qwen3_tts", "task": "tts"}]}) message = str(ctx.exception) self.assertIn("personaplex", message) - self.assertIn("speech-to-speech", message) + self.assertIn("speech-to-speech, not TTS", message) + self.assertIn("cannot synthesize narration", message) + self.assertIn("Consider deleting the model", message) self.assertIn(_AUDIOCPP_MODEL_ID, message) self.assertIn("tts-1", message) @@ -1385,7 +1387,8 @@ class AudioCppDeterministicErrorTests(unittest.TestCase): def test_speech_to_speech_only_family_is_not_retryable_with_a_hint(self): exc = self._error("PersonaPlex supports only speech-to-speech sessions") self.assertIsInstance(exc, NonRetryableTTSError) - self.assertIn("cannot generate audiobooks", str(exc)) + self.assertIn("speech-to-speech, not TTS", str(exc)) + self.assertIn("Consider deleting the model", str(exc)) def test_unresolvable_clone_voice_is_not_retryable_with_a_hint(self): exc = self._error("Vevo2 requires target_voice or voice speaker audio") -- cgit v1.2.3