Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions gateway/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -18239,11 +18239,9 @@ def _should_send_voice_reply(
(voice_mode == "all")
or (voice_mode == "voice_only" and is_voice_input)
# ``voice.auto_tts`` is synced into the adapter on gateway startup.
# Treat it as "voice accompanies text replies" unless a chat was
# explicitly turned off. The base adapter's own auto-TTS path only
# covers voice-input replies, so final text replies need the runner
# path here.
or (voice_mode != "off" and adapter_auto_tts)
# It is the fallback only when the chat has no explicit mode;
# otherwise the chat-level all/voice_only/off choice takes precedence.
or (voice_mode is None and adapter_auto_tts)
)
if not should:
logger.debug(
Expand Down
19 changes: 19 additions & 0 deletions tests/gateway/test_auto_voice_reply_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ def test_should_send_voice_reply_streamed_global_auto_tts_fires(self):
voice_event, "hello", [], already_sent=True
) is True

def test_should_send_voice_reply_voice_only_still_requires_voice_input(self):
"""Explicit voice_only must not widen to text input (#73508 regression).

Persisted voice_only mode is synced into the adapter as an explicit
auto-TTS opt-in, so adapter_auto_tts is True for this chat. The
chat-level mode stays authoritative: text input gets no voice reply,
voice input still does.
"""
runner = _make_runner()
runner._voice_mode["telegram:123"] = "voice_only"
adapter = _make_adapter(Platform.TELEGRAM)
adapter._should_auto_tts_for_chat = MagicMock(return_value=True)
runner.adapters[Platform.TELEGRAM] = adapter
event = _make_event(Platform.TELEGRAM, chat_id="123")

assert runner._should_send_voice_reply(event, "hello", []) is False

voice_event = _make_event(Platform.TELEGRAM, chat_id="123", message_type=MessageType.VOICE)
assert runner._should_send_voice_reply(voice_event, "hello", [], already_sent=True) is True

def _make_runner() -> GatewayRunner:
with patch("gateway.run.GatewayRunner._load_voice_modes", return_value={}):
Expand Down
Loading