fix: initialize CLI voice state for single-query mode

- initialize voice and interrupt runtime state in HermesCLI.__init__
- prevent chat -q from crashing before run() has executed
- add regression coverage for single-query state initialization
This commit is contained in:
teknium1
2026-03-14 06:31:32 -07:00
parent 7b10881b9e
commit 9633ddd8d8
2 changed files with 41 additions and 0 deletions

30
cli.py
View File

@@ -1289,11 +1289,41 @@ class HermesCLI:
self._history_file = _hermes_home / ".hermes_history"
self._last_invalidate: float = 0.0 # throttle UI repaints
self._app = None
# State shared by interactive run() and single-query chat mode.
# These must exist before any direct chat() call because single-query
# mode does not go through run().
self._agent_running = False
self._pending_input = queue.Queue()
self._interrupt_queue = queue.Queue()
self._should_exit = False
self._last_ctrl_c_time = 0
self._clarify_state = None
self._clarify_freetext = False
self._clarify_deadline = 0
self._sudo_state = None
self._sudo_deadline = 0
self._approval_state = None
self._approval_deadline = 0
self._approval_lock = threading.Lock()
self._secret_state = None
self._secret_deadline = 0
self._spinner_text: str = "" # thinking spinner text for TUI
self._command_running = False
self._command_status = ""
self._attached_images: list[Path] = []
self._image_counter = 0
# Voice mode state (also reinitialized inside run() for interactive TUI).
self._voice_lock = threading.Lock()
self._voice_mode = False
self._voice_tts = False
self._voice_recorder = None
self._voice_recording = False
self._voice_processing = False
self._voice_continuous = False
self._voice_tts_done = threading.Event()
self._voice_tts_done.set()
# Background task tracking: {task_id: threading.Thread}
self._background_tasks: Dict[str, threading.Thread] = {}

View File

@@ -95,6 +95,17 @@ class TestVerboseAndToolProgress:
assert cli.tool_progress_mode in ("off", "new", "all", "verbose")
class TestSingleQueryState:
def test_voice_and_interrupt_state_initialized_before_run(self):
"""Single-query mode calls chat() without going through run()."""
cli = _make_cli()
assert cli._voice_tts is False
assert cli._voice_mode is False
assert cli._voice_tts_done.is_set()
assert hasattr(cli, "_interrupt_queue")
assert hasattr(cli, "_pending_input")
class TestHistoryDisplay:
def test_history_numbers_only_visible_messages_and_summarizes_tools(self, capsys):
cli = _make_cli()