"""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