Skip to content

fix(voice): rebuild inactive recorder streams - #75541

Open
andyst-dev wants to merge 1 commit into
NousResearch:mainfrom
andyst-dev:fix/voice-recorder-stream-liveness
Open

fix(voice): rebuild inactive recorder streams#75541
andyst-dev wants to merge 1 commit into
NousResearch:mainfrom
andyst-dev:fix/voice-recorder-stream-liveness

Conversation

@andyst-dev

Copy link
Copy Markdown
Contributor

Summary

  • reuse the recorder's cached InputStream only while its active liveness signal remains true
  • close and rebuild inactive or unprobeable streams before the next recording, using the existing timeout-bounded shutdown path
  • still attempt close() when stop() rejects an already-inactive stream
  • add behavioral regression coverage for active reuse, inactive replacement, and failed liveness probes

This addresses the dead cached recorder mechanism isolated in #75417. It is intentionally complementary to #74152, which covers the separate manual push-to-talk wake-listener handoff and does not touch tools/voice_mode.py.

Refs #75417

Validation

  • scripts/run_tests.sh tests/tools/test_voice_mode.py -q -k 'ensure_stream' — 3 passed
  • related voice/wake/STT suites — 118 passed
  • four unrelated platform-specific failures were excluded from that related-suite run after reproducing each on clean upstream/main (two WSL playback mocks, the macOS beep gate, and the missing local TFLite runtime case)
  • uv run ruff check tools/voice_mode.py tests/tools/test_voice_mode.py
  • python -m py_compile tools/voice_mode.py tests/tools/test_voice_mode.py
  • git diff upstream/main...HEAD --check

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard tool/tts Text-to-speech and transcription area/streaming Streaming responses: gateway delivery, provider wire labels Jul 31, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused regression fix. The premise is confirmed on current main: tools/voice_mode.py:896-897 reuses every non-null cached stream without checking whether it remains active, and tools/voice_mode.py:1096-1101 skips close() if stop() raises. The PR's liveness gate and independent close attempt directly cover both paths, with behavioral tests in tests/tools/test_voice_mode.py:427-480.

The only production caller of _ensure_stream() remains AudioRecorder.start() at tools/voice_mode.py:1082; no sibling recorder lifecycle path was found. The checked-out main is an ancestor of the PR base, so no surrounding-code rework is indicated.

This is an automated hermes-sweeper review.

@teknium1 teknium1 added the sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users label Jul 31, 2026
@andrexibiza

Copy link
Copy Markdown
Contributor

Vox Lockin lane 09 cross-reference receipt (desktop lane; this PR touches the CLI recorder in tools/voice_mode.py, outside the desktop hook lane):

  • Merge-clean against current main (70db671).
  • Reviewed: AudioRecorder._ensure_stream rebuilds an inactive/broken sounddevice stream (reuse active, close+rebuild inactive, tolerate broken liveness probes) — the CLI voice-loop analogue of the desktop's mic re-arm class. Note transcribe_recording in the same file serves the desktop /api/audio/transcribe endpoint, but the recorder-stream change does not affect the desktop transcription path (desktop recordings come from the browser's MediaRecorder, not AudioRecorder).
  • Tests on PR head: 3 new TestAudioRecorder cases cover reuse/rebuild/probe-failure; consistent with the existing mock harness.

No desktop-class gap; recommend merge. (Lane 01/03 may want to run the full tests/tools/test_voice_mode.py suite for the CLI loop.)

@andyst-dev
andyst-dev force-pushed the fix/voice-recorder-stream-liveness branch from 0004a79 to ed399e3 Compare August 6, 2026 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/streaming Streaming responses: gateway delivery, provider wire comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users tool/tts Text-to-speech and transcription type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants