Add live transcription preview#571
Conversation
50bd008 to
7f452c1
Compare
Greptile SummaryThis PR adds rolling live transcription previews for Wyoming ASR: the Python side periodically re-transcribes a sliding audio window and writes JSONL events to a log file (and/or the terminal), while the macOS app's new
Confidence Score: 5/5Safe to merge; the feature is well-scoped to Wyoming ASR live recording, the cancel-race ordering is correct, and the previously reported Rich live-status suppression for non-Wyoming providers is now fixed. The Python cancel-ordering (request_stop before task.cancel + await) correctly prevents stale partials from landing after the final event, confirmed by the dedicated race-condition test. The live_preview_console_active gate now includes both the Wyoming provider check and the file-transcription check, fixing the issue raised in an earlier review pass. The two P2 observations are both benign given current usage patterns. No files require special attention; the incremental FileHandle-based reading in LiveTranscriptionPreview.swift and the cancel-safe run loop in asr.py are the most complex new paths and both have direct test coverage. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant RecordingIndicatorController
participant LiveTranscriptionPreview
participant VoiceLevelOverlayController
participant CLI as agent-cli process
participant LivePreviewStreamer
participant WyomingASR
User->>RecordingIndicatorController: begin(for: toggleTranscription)
RecordingIndicatorController->>LiveTranscriptionPreview: start(logURL)
Note over LiveTranscriptionPreview: Truncates JSONL, starts 250ms timer
RecordingIndicatorController->>VoiceLevelOverlayController: show(showsPreviewSpace: true)
RecordingIndicatorController->>CLI: spawn with --live-preview-log --live-preview-interval 1 --live-preview-window 10
loop Every interval_seconds (1s)
CLI->>LivePreviewStreamer: emit_partial()
LivePreviewStreamer->>WyomingASR: _transcribe_recorded_audio_wyoming(rolling window)
WyomingASR-->>LivePreviewStreamer: partial text
LivePreviewStreamer->>LivePreviewStreamer: "_publish_event(type=partial)"
LivePreviewStreamer-->>CLI: append to JSONL log
end
loop Every 250ms (Swift timer)
LiveTranscriptionPreview->>LiveTranscriptionPreview: readNewContents(offset-tracked)
LiveTranscriptionPreview->>LiveTranscriptionPreview: parse last valid JSON event
LiveTranscriptionPreview-->>VoiceLevelOverlayController: "@Published text update"
end
User->>RecordingIndicatorController: end(for: toggleTranscription)
CLI->>LivePreviewStreamer: finally: request_stop() then cancel task then stop(final_text)
LivePreviewStreamer-->>CLI: append final event to JSONL
RecordingIndicatorController->>VoiceLevelOverlayController: hide()
RecordingIndicatorController->>LiveTranscriptionPreview: stop()
Note over LiveTranscriptionPreview: Invalidates timer, clears state
Reviews (6): Last reviewed commit: "Signal live preview stop before cancella..." | Re-trigger Greptile |
64faa0f to
d6745a9
Compare
for more information, see https://pre-commit.ci
a39c536 to
5b2893b
Compare
Summary
Test Plan
uv run ruff check agent_cli/agents/transcribe.py agent_cli/services/asr.py agent_cli/opts.py tests/test_asr.py tests/agents/test_transcribe.py tests/agents/test_transcribe_recovery.pyuv run pytest tests/test_asr.py tests/agents/test_transcribe.py tests/agents/test_transcribe_recovery.py tests/test_docs_gen.py -qswift buildinmacos/AgentCLIswift run AgentCLI --agentcli-live-preview-self-testinmacos/AgentCLIuv run agent-cli transcribe --live-preview-stdout