diff --git a/services/ai_voice_runtime_service/app.py b/services/ai_voice_runtime_service/app.py index edfc7f3..49f37ca 100644 --- a/services/ai_voice_runtime_service/app.py +++ b/services/ai_voice_runtime_service/app.py @@ -823,7 +823,11 @@ def _media_registration_from_row(row: VoiceAISessionRow, *, queue_code: str | No voice_v2_duplex=bool(voice_v2_for_session and _voice_v2_duplex_enabled()), voice_v2_streaming_asr_backend=streaming_backend, voice_v2_prebaked_ack=bool(voice_v2_for_session and _voice_v2_prebaked_ack_enabled()), - voice_v2_emotive_ack=bool(voice_v2_for_session and _voice_v2_emotive_ack_enabled()), + # Deliberately NOT gated on voice_v2_for_session: phrase-variant rotation only + # needs a text pool + live TTS, not the v2 duplex/partial-ASR pipeline, so calls + # outside the v2 queue allowlist still get varied fillers instead of always the + # single fixed "Секунду." fallback string. + voice_v2_emotive_ack=bool(_voice_v2_emotive_ack_enabled()), voice_v2_emotive_ack_ru_only=bool(_voice_v2_emotive_ack_ru_only()), ) diff --git a/tests/test_ai_voice_runtime_service.py b/tests/test_ai_voice_runtime_service.py index d42f65b..638f2d7 100644 --- a/tests/test_ai_voice_runtime_service.py +++ b/tests/test_ai_voice_runtime_service.py @@ -855,3 +855,27 @@ def test_push_voice_ai_telephony_event_call_ended_returns_detached_safe_payload( } assert closed == [("avs_runtime_call_ended", "call_ended")] assert orchestrator_calls == [("POST", "/ai/voice/sessions/avs_runtime_call_ended/close")] + + +def test_media_registration_emotive_ack_rotation_is_not_gated_on_v2_queue_eligibility(monkeypatch): + # AI_VOICE_V2_QUEUE_CODES defaults to "voice_lab_ai" only, so a queue outside + # that allowlist runs the plain v1 ack path. Emotive-ack rotation must still + # apply there — otherwise every filler collapses to the single fixed + # "Секунду." fallback string instead of rotating through phrase variants. + monkeypatch.delenv("AI_VOICE_V2_QUEUE_CODES", raising=False) + monkeypatch.delenv("AI_VOICE_V2_EMOTIVE_ACK_ENABLED", raising=False) + row = VoiceAISessionRow( + session_id="avs_runtime_emotive_ack_v1", + call_id="call_runtime_emotive_ack_v1", + interaction_id="int_runtime_emotive_ack_v1", + ai_session_id="ais_runtime_emotive_ack_v1", + language="ru", + media_uuid="media-emotive-ack-v1", + queue_id="que_not_v2_eligible", + agent_profile="voice_support", + ) + + registration = runtime_module._media_registration_from_row(row, queue_code="queue_outside_v2_allowlist") + + assert registration.voice_v2_enabled is False + assert registration.voice_v2_emotive_ack is True