tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_voice_on tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_voice_off tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_voice_tts tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_voice_status_off tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_voice_status_on tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_toggle_off_to_on tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_toggle_on_to_off tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_persistence_saved tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_persistence_loaded tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_persistence_saved_for_off tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_sync_voice_mode_state_to_adapter_restores_off_chats tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_sync_populates_enabled_chats_from_voice_modes tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_sync_pushes_config_default_onto_adapter tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_restart_restores_voice_off_state tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_per_chat_isolation tests/gateway/test_voice_command.py::TestHandleVoiceCommand::test_platform_isolation tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_voice_input_voice_only_skipped tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_voice_input_all_mode_skipped tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_text_input_all_mode_runner_fires tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_text_input_voice_only_no_reply tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_off_mode_voice tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_off_mode_text tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_discord_vc_voice_input_base_handles tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_discord_vc_voice_only_base_handles tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_error_response_skipped tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_empty_response_skipped tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_dedup_skips_when_agent_called_tts tests/gateway/test_voice_command.py::TestAutoVoiceReply::test_no_dedup_for_other_tools tests/gateway/test_voice_command.py::TestSendVoiceReply::test_calls_tts_and_send_voice tests/gateway/test_voice_command.py::TestSendVoiceReply::test_non_telegram_auto_voice_reply_uses_mp3 tests/gateway/test_voice_command.py::TestSendVoiceReply::test_auto_voice_reply_uses_thread_metadata_helper tests/gateway/test_voice_command.py::TestSendVoiceReply::test_empty_text_after_strip_skips tests/gateway/test_voice_command.py::TestSendVoiceReply::test_tts_failure_no_crash tests/gateway/test_voice_command.py::TestSendVoiceReply::test_exception_caught tests/gateway/test_voice_command.py::TestDiscordPlayTtsSkip::test_play_tts_plays_in_vc_when_connected tests/gateway/test_voice_command.py::TestDiscordPlayTtsSkip::test_play_tts_not_skipped_when_not_in_vc tests/gateway/test_voice_command.py::TestDiscordPlayTtsSkip::test_play_tts_not_skipped_for_different_channel tests/gateway/test_voice_command.py::TestVoiceInHelp::test_voice_in_help_output tests/gateway/test_voice_command.py::TestVoiceInHelp::test_voice_is_known_command tests/gateway/test_voice_command.py::TestVoiceReceiver::test_initial_state tests/gateway/test_voice_command.py::TestVoiceReceiver::test_start_sets_running tests/gateway/test_voice_command.py::TestVoiceReceiver::test_stop_clears_state tests/gateway/test_voice_command.py::TestVoiceReceiver::test_map_ssrc tests/gateway/test_voice_command.py::TestVoiceReceiver::test_map_ssrc_overwrites tests/gateway/test_voice_command.py::TestVoiceReceiver::test_pause_resume tests/gateway/test_voice_command.py::TestVoiceReceiver::test_check_silence_empty tests/gateway/test_voice_command.py::TestVoiceReceiver::test_check_silence_returns_completed_utterance tests/gateway/test_voice_command.py::TestVoiceReceiver::test_check_silence_ignores_short_buffer tests/gateway/test_voice_command.py::TestVoiceReceiver::test_check_silence_ignores_recent_audio tests/gateway/test_voice_command.py::TestVoiceReceiver::test_check_silence_unknown_user_discarded tests/gateway/test_voice_command.py::TestVoiceReceiver::test_stale_buffer_discarded tests/gateway/test_voice_command.py::TestVoiceReceiver::test_on_packet_skips_when_not_running tests/gateway/test_voice_command.py::TestVoiceReceiver::test_on_packet_skips_when_paused tests/gateway/test_voice_command.py::TestVoiceReceiver::test_on_packet_skips_short_data tests/gateway/test_voice_command.py::TestVoiceReceiver::test_on_packet_skips_non_rtp tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_unsupported_platform tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_no_guild_id tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_user_not_in_vc tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_success tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_failure tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_exception tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_join_missing_voice_dependencies tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_leave_not_in_vc tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_leave_no_guild tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_leave_success tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_no_adapter tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_no_text_channel tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_creates_event_and_dispatches tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_reuses_bound_source_metadata tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_posts_transcript_in_text_channel tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_suppresses_duplicate_transcript tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_input_suppresses_near_duplicate_transcript tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_get_guild_id_from_guild tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_get_guild_id_from_interaction tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_get_guild_id_none tests/gateway/test_voice_command.py::TestVoiceChannelCommands::test_get_guild_id_dm tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_in_voice_channel_true tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_in_voice_channel_false_no_client tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_in_voice_channel_false_disconnected tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_leave_voice_channel_cleans_up tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_leave_voice_channel_no_connection tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_get_user_voice_channel_no_client tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_get_user_voice_channel_no_guild tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_get_user_voice_channel_user_not_in_vc tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_get_user_voice_channel_success tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_play_in_voice_channel_not_connected tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_allowed_user_empty_list tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_allowed_user_in_list tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_is_allowed_user_not_in_list tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_process_voice_input_success tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_process_voice_input_hallucination_filtered tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_process_voice_input_stt_failure tests/gateway/test_voice_command.py::TestDiscordVoiceChannelMethods::test_process_voice_input_exception_caught tests/gateway/test_voice_command.py::TestVoiceReceiverThreadSafety::test_check_silence_holds_lock tests/gateway/test_voice_command.py::TestVoiceReceiverThreadSafety::test_on_packet_buffer_write_holds_lock tests/gateway/test_voice_command.py::TestVoiceReceiverThreadSafety::test_concurrent_buffer_access_safe tests/gateway/test_voice_command.py::TestCallbackWiringOrder::test_callback_set_before_join tests/gateway/test_voice_command.py::TestCallbackWiringOrder::test_join_failure_clears_callback tests/gateway/test_voice_command.py::TestCallbackWiringOrder::test_join_returns_false_clears_callback tests/gateway/test_voice_command.py::TestLeaveExceptionHandling::test_leave_exception_still_cleans_state tests/gateway/test_voice_command.py::TestLeaveExceptionHandling::test_leave_clears_callback tests/gateway/test_voice_command.py::TestAutoTtsEmptyTextGuard::test_empty_after_strip_skips_tts tests/gateway/test_voice_command.py::TestAutoTtsEmptyTextGuard::test_code_block_response_skips_tts tests/gateway/test_voice_command.py::TestAutoTtsEmptyTextGuard::test_base_empty_check_in_source tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_none_sentinel_flushes_buffer tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_stop_event_aborts_early tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_done_event_set_on_exception tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_think_blocks_stripped tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_sentence_splitting tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_markdown_stripped_in_speech tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_duplicate_sentences_deduped tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_no_api_key_display_only tests/gateway/test_voice_command.py::TestStreamTtsToSpeaker::test_long_buffer_flushed_on_timeout tests/gateway/test_voice_command.py::TestStopAcquiresLock::test_stop_clears_under_lock tests/gateway/test_voice_command.py::TestStopAcquiresLock::test_stop_does_not_deadlock_with_on_packet tests/gateway/test_voice_command.py::TestPacketDebugCounterIsInstanceLevel::test_counter_is_per_instance tests/gateway/test_voice_command.py::TestPacketDebugCounterIsInstanceLevel::test_counter_initialized_in_init tests/gateway/test_voice_command.py::TestPlayInVoiceChannelUsesRunningLoop::test_source_uses_get_running_loop tests/gateway/test_voice_command.py::TestSendVoiceReplyFilename::test_filename_uses_uuid tests/gateway/test_voice_command.py::TestSendVoiceReplyFilename::test_filenames_are_unique tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_adapter_has_on_voice_disconnect_attr tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_timeout_calls_disconnect_callback tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_runner_cleanup_method_removes_voice_mode tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_timeout_without_callback_does_not_crash tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_timeout_skips_disconnect_when_voice_mode_off tests/gateway/test_voice_command.py::TestVoiceTimeoutCleansRunnerState::test_timeout_still_disconnects_when_voice_mode_active tests/gateway/test_voice_command.py::TestPlaybackTimeout::test_source_has_wait_for_timeout tests/gateway/test_voice_command.py::TestPlaybackTimeout::test_playback_timeout_constant_exists tests/gateway/test_voice_command.py::TestPlaybackTimeout::test_playback_timeout_fires tests/gateway/test_voice_command.py::TestPlaybackTimeout::test_is_playing_wait_has_timeout tests/gateway/test_voice_command.py::TestSendVoiceReplyCleanup::test_cleanup_in_finally tests/gateway/test_voice_command.py::TestSendVoiceReplyCleanup::test_files_cleaned_on_send_exception tests/gateway/test_voice_command.py::TestAutoTtsTempFileCleanup::test_source_has_finally_remove tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_returns_none_when_not_connected tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_returns_none_when_vc_disconnected tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_returns_info_with_members tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_speaking_detection tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_context_string_format tests/gateway/test_voice_command.py::TestVoiceChannelAwareness::test_context_empty_when_not_connected tests/gateway/test_voice_command.py::TestDisconnectVoiceCleanup::test_disconnect_clears_voice_state tests/gateway/test_voice_command.py::TestVoiceReception::test_known_ssrc_returns_completed tests/gateway/test_voice_command.py::TestVoiceReception::test_known_ssrc_short_buffer_ignored tests/gateway/test_voice_command.py::TestVoiceReception::test_known_ssrc_recent_audio_waits tests/gateway/test_voice_command.py::TestVoiceReception::test_unknown_ssrc_no_automap_no_completed tests/gateway/test_voice_command.py::TestVoiceReception::test_unknown_ssrc_late_speaking_event tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_single_allowed_user tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_multiple_allowed_users_no_map tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_no_allowlist_single_member tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_unallowed_user_rejected tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_only_bot_in_channel tests/gateway/test_voice_command.py::TestVoiceReception::test_automap_persists_across_calls tests/gateway/test_voice_command.py::TestVoiceReception::test_stale_unknown_buffer_discarded tests/gateway/test_voice_command.py::TestVoiceReception::test_paused_receiver_ignores_packets tests/gateway/test_voice_command.py::TestVoiceReception::test_resumed_receiver_accepts_packets tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_dave_known_user_decrypt_ok tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_dave_unknown_ssrc_passthrough tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_dave_unencrypted_error_passthrough tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_dave_other_error_drops tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_no_dave_direct_decode tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_bot_own_ssrc_ignored tests/gateway/test_voice_command.py::TestVoiceReception::test_on_packet_multiple_ssrcs_separate_buffers tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_play_tts_plays_in_vc tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_play_tts_fallback_when_not_in_vc tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_play_tts_wrong_channel_no_match tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_voice_input_runner_skips tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_text_input_voice_all_runner_fires tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_text_input_voice_off_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_text_input_voice_only_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_error_response_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_empty_response_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_agent_tts_tool_dedup tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_streaming_on_voice_input_runner_fires tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_streaming_on_text_input_runner_fires tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_streaming_on_voice_off_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_streaming_on_empty_response_no_tts tests/gateway/test_voice_command.py::TestVoiceTTSPlayback::test_streaming_on_agent_tts_dedup tests/gateway/test_voice_command.py::TestUDPKeepalive::test_keepalive_interval_is_reasonable tests/gateway/test_voice_command.py::TestUDPKeepalive::test_keepalive_sends_silence_frame tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_default_false_no_override_suppresses tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_default_true_no_override_fires tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_explicit_enable_overrides_false_default tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_explicit_disable_overrides_true_default tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_enabled_wins_over_disabled tests/gateway/test_voice_command.py::TestShouldAutoTtsForChat::test_per_chat_isolation