| name | maintain-live |
| description | Maintain Live's pinned-session voice lifecycle, VAD turn detection, meter/countdown UI, barge-in/mute behavior, typed event correlation, and spoken replies. Use when changing Live start/stop, turn state, native audio events, or Live accessibility. |
Maintain Live
Role and boundary
Keep Live as the hands-free state machine for one snapshotted conversation and one native session. Keep UI guards and transcript projection in TypeScript while native audio, VAD, cancellation, and playback ownership remain in Rust; do not retarget a running session from the sidebar.
Source map
src/live.ts: LiveUiState, typed LiveEvent, wireLive, LiveReplySpeechTarget, meter/countdown helpers, pinned conversationSessionId, start/stop/mute, event guards, and whenIdle.
src/main.ts: Live markup, thinking control, initializeVoiceFeatures, navigation and voice-shortcut wiring; src/voice-shortcuts.ts: O/X keyboard contract.
src/chat-store.ts, src/assistant-coordinator.ts, src/settings.ts, src/tts.ts: pinned transcript, correlated generation, Live snapshot, and spoken reply target.
src-tauri/src/live/mod.rs: LiveStartConfig, LiveState, preparation, detector worker, reply registration/speech commands, stop, and native events; src-tauri/src/live/playback.rs: the 48 kHz SpeechPlayback implementation, resampling, horizon, fences, played-back drain, metrics, and cancellation.
src-tauri/src/live/vad.rs, audio_macos.rs, audio_stub.rs: Silero/VAD thresholds, silence/minimum-utterance gates, and full-duplex audio graph; tests in src-tauri/src/live/playback.rs, tests/live.test.ts, tests/live-meter.test.ts, tests/voice-shortcuts.test.ts, and tests/assistant-activity.test.ts.
Cover
- Reserve and snapshot provider, model, thinking, voice input/output, sensitivity, end-of-turn pause, minimum utterance, and barge-in before native start; bind every event to the active
sessionId, utterance, requestId, and speechSessionId.
- Preserve
inactive → preparing → listening/user-speaking/transcribing/thinking/assistant-speaking/muted → stopping/error guards, immediate cancellation on barge-in only when enabled, mute cancellation, and idempotent stop/idle settlement.
- Keep Live transcript appends and voice provenance pinned to the start-time conversation. Spoken microphone turns receive the Live speech target; typed Live turns use the same pinned conversation but deliberately receive no speech target and remain silent. No turn may append or generate after stopping begins.
- Render the meter only from native
listeningLevel samples and the countdown only from native ticks with stale-event grace; never synthesize audio motion on a timer.
- Preserve native bounded queues, AVAudioEngine timeline/horizon, stale-event rejection, and local-first audio/transcription boundaries. Inspect current source before changing state or event names.
Validate and accept
- Run
bun test tests/live.test.ts tests/live-meter.test.ts tests/voice-shortcuts.test.ts tests/assistant-activity.test.ts.
- Run
git diff --check against the actual files changed; run just check when the change crosses TypeScript/Rust/build boundaries. Exercise start/stop, mute, barge-in on/off, minimum utterance, stale events, pinned session, meter, countdown, and O/X/Escape paths in the packaged app via $test-voice-layer-app.
- Treat real microphone permission, AVAudioEngine routing, audible speech, and human interruption quality as device-owned acceptance; native events and tests are not audible proof.
Relationships
Coordinate with $maintain-navigation, $maintain-sessions, $maintain-assistant-orchestration, $maintain-voice-input, $maintain-voice-output, and $maintain-assistant-providers. Use $live-end-of-turn-pause and $voice-meter for their focused specialist workflows.