66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
"""Release contracts for localized, interruptible thinking voice cues."""
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
VOICE = ROOT / "dockerfiles/hermes-webui-atlas-voice.js"
|
|
|
|
|
|
def _source() -> str:
|
|
return VOICE.read_text(encoding="utf-8")
|
|
|
|
|
|
def test_fast_answers_suppress_cues_and_long_waits_are_bounded():
|
|
source = _source()
|
|
|
|
assert "const THINKING_CUE_FIRST_MS=1900" in source
|
|
assert "const THINKING_CUE_INTERVAL_MS=6500" in source
|
|
assert "cue.issued>=cue.pool.length" in source
|
|
assert "scheduleNextThinkingCue(cue,THINKING_CUE_FIRST_MS)" in source
|
|
assert "scheduleNextThinkingCue(cue,THINKING_CUE_INTERVAL_MS)" in source
|
|
assert "cancelThinkingCues();\n const turn=ensureSpeechTurn(token)" in source
|
|
|
|
|
|
def test_cues_are_localized_deterministic_and_non_repeating():
|
|
source = _source()
|
|
|
|
assert "{id:'thinking',text:\"I'm thinking.\"}" in source
|
|
assert "{id:'let_me_think',text:'Дайте подумать.'}" in source
|
|
assert "{id:'still_working',text:'Sigo pensando en eso.'}" in source
|
|
assert "offset:cuePoolOffset(turnId,pool.length)" in source
|
|
assert "cue.pool[(cue.offset+cue.issued)%cue.pool.length]" in source
|
|
assert "cue.issued+=1" in source
|
|
assert "const localized=normalizeSttLanguage(language)||'en'" in source
|
|
|
|
|
|
def test_cues_are_turn_owned_audio_only_and_abortable():
|
|
source = _source()
|
|
cue_region = source.split("async function issueThinkingCue(cue){", 1)[1].split(
|
|
"function scheduleThinkingCues", 1
|
|
)[0]
|
|
|
|
assert "cue.token===generation" in source
|
|
assert "state==='thinking'" in source
|
|
assert "cue.turnId+':thinking-cue:'" in cue_region
|
|
assert "request.cue_id=entry.id" in cue_region
|
|
assert "fetch(TTS_STREAM_URL" in cue_region
|
|
assert "fetch('/api/tts'" not in cue_region
|
|
assert "atlas-pcm-playback" in cue_region
|
|
assert "signal:controller.signal" in cue_region
|
|
assert "cue.controller.abort()" in source
|
|
assert "cancelThinkingCues();\n cancelSpeechTurn();" in source
|
|
assert "composer.value" not in cue_region
|
|
assert "window.send" not in cue_region
|
|
|
|
|
|
def test_thinking_barge_in_arms_quickly_but_guards_playback_echo():
|
|
source = _source()
|
|
|
|
assert "let speechArmAt=Date.now()+100" in source
|
|
assert "speechArmAt=now+(state==='thinking'?150:450)" in source
|
|
assert "playbackActive&&!playbackWasActive" in source
|
|
assert "const BARGE_TRIGGER_FRAMES=4" in source
|
|
assert "},50);" in source
|
|
assert "lookback:monitor.lookback" in source
|