fix(frank-tts): answer a voice-less request with the declared default

The omp speech device forwards a voice only when the call passes voice_id - there is no setting that feeds one (speech.voice is the TUI speak-aloud Kokoro enum, tts.localVoice belongs to the local backend) - so every harness voiceover arrives with no voice key and the shim answered 400 "unknown voice None". Measured on the deployed endpoint 2026-10-18, from a restarted session with the speech role pointed here.

DEFAULT_VOICE makes the absent case a spoken operator choice instead of a code surprise: the pack named there answers a voice-less request and the journal line is marked (default), so an unrequested voice never reads later like a requested one. An UNKNOWN name still 400s with the list that exists - the no-silent-fallback law that this endpoint was built on is untouched, and the strict shape stays the code default (empty DEFAULT_VOICE), which the second new seam test pins. Ships narrator1 in scripts/frank-tts.env.
This commit is contained in:
Frank committed 2026-10-18 19:21:28 -07:00
1 parent d2ce6693da
commit b91873578b
3 files changed
+58 -6

No files matched your search

+31
View File
@@ -183,6 +183,37 @@ assert 'voice_id' not in body, body
PY
}
@test "a voice-less request speaks the declared default and marks the log" {
# The omp harness has no setting that feeds a voice to its speech device, so
# a voice-less call is its NORMAL shape rather than a client bug. With the
# operator's default armed the call must produce that pack's audio, and the
# journal line must say (default) — otherwise an unrequested voice reads,
# weeks later, exactly like one somebody asked for.
arm_omni
export DEFAULT_VOICE=narrator1
start_app
speech '{"model":"tts-1","input":"hello"}'
[ "$output" = "200" ] || { cat "$TEST_TMP/app.log"; false; }
cmp "$TEST_TMP/out.bin" "$TEST_TMP/upstream.wav"
python3 - "$TEST_TMP/capture.json" <<'PY'
import json, sys
body = json.load(open(sys.argv[1]))
assert body['voice'] == 'narrator1', 'the declared default never reached the engine'
PY
grep -q 'speech voice=narrator1 (default) format=wav' "$TEST_TMP/app.log" \
|| { cat "$TEST_TMP/app.log"; false; }
}
@test "with no default declared a voice-less request stays a 400" {
# Strictness is still the code default: an endpoint that invents a voice
# nobody configured is exactly how a wrong-voice deployment stays wrong.
arm_omni
start_app
speech '{"model":"tts-1","input":"hello"}'
[ "$output" = "400" ] || { cat "$TEST_TMP/app.log"; false; }
grep -q 'narrator1' "$TEST_TMP/out.bin"
}
@test "an unknown voice is a 400 naming the voices that exist" {
arm_omni
start_app