fix(voice): prevent restart race when continuous mode stops after 3 no-speech cycles

When voice continuous mode detects 3 consecutive no-speech cycles it sets
_voice_continuous = False and previously did an immediate 
eturn. The
restart guard if self._voice_continuous and not submitted and not
self._voice_recording came *after* the early return, so the thread could
never restart. However a timing window existed: if _voice_start_recording was
already queued from a prior iteration, the 
eturn bypassed the guard while
the thread was already in flight.

Replace the bare 
eturn with a stop_continuous_restart boolean evaluated
in the same if that guards _restart_recording. This ensures both branches
read a consistent no-restart signal and no recording thread is spawned after
the user's session has been intentionally halted.
This commit is contained in:
brunopirz 2026-06-24 13:15:04 -03:00 committed by Teknium
parent 268b98253d
commit ee5f20bdf2

10
cli.py
View file

@ -11913,13 +11913,14 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
pass
# Track consecutive no-speech cycles to avoid infinite restart loops.
stop_continuous_restart = False
if not submitted:
self._no_speech_count = getattr(self, '_no_speech_count', 0) + 1
if self._no_speech_count >= 3:
self._voice_continuous = False
self._no_speech_count = 0
_cprint(f"{_DIM}No speech detected 3 times, continuous mode stopped.{_RST}")
return
stop_continuous_restart = True
else:
self._no_speech_count = 0
@ -11927,7 +11928,12 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
# restart recording so the user can keep talking.
# (When transcript IS submitted, process_loop handles restart
# after chat() completes.)
if self._voice_continuous and not submitted and not self._voice_recording:
if (
self._voice_continuous
and not submitted
and not self._voice_recording
and not stop_continuous_restart
):
self._voice_restart_recording_async()
def _voice_speak_response_async(self, text: str) -> None: