diff --git a/cli.py b/cli.py index 17d33cf46..f809f797b 100644 --- a/cli.py +++ b/cli.py @@ -10107,9 +10107,11 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin): target=self._reload_mcp, daemon=True ) _reload_thread.start() - _reload_thread.join(timeout=30) - if _reload_thread.is_alive(): - print(" ⚠️ MCP reload timed out (30s). Some servers may not have reconnected.") + # Do NOT join here — process_loop calls this from its idle branch, so a + # blocking join would freeze input consumption for up to 30s (and a hung + # MCP server could block far longer). The reload runs purely in the + # background daemon thread, which reports its own progress/completion + # status via print() inside _reload_mcp(). # Inline-skip tokens that bypass the destructive-slash confirmation modal. # A general escape hatch for non-interactive use (scripting/automation) and @@ -10737,8 +10739,16 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin): except Exception: pass + # Recorder creation can fail (no input device, PortAudio init error). + # Reset the flag on failure or _voice_recording stays True forever and + # every future voice start is silently skipped by the guard above. if self._voice_recorder is None: - self._voice_recorder = create_audio_recorder() + try: + self._voice_recorder = create_audio_recorder() + except Exception: + with self._voice_lock: + self._voice_recording = False + raise # Apply config-driven silence params (numeric-guarded so YAML # scalar corruption doesn't break recording start-up).