Voice: add speech-recognition language selection (Wispr Flow) (QUALITY-1066) - #13720
Voice: add speech-recognition language selection (Wispr Flow) (QUALITY-1066)#13720warp-agent-staging[bot] wants to merge 3 commits into
Conversation
Add the approved-pending spec for the Voice language selection option (Wispr Flow): a Speech Recognition Language dropdown in Settings -> AI -> Voice, an enum-backed VoiceInputLanguage setting (Auto-detect default), client->server language passthrough via the Transcriber trait, and server forwarding of language into the Wispr Flow request body. Cross-repo change; matching spec PR in warpdotdev/warp-server. Co-Authored-By: Warp <agent@warp.dev>
Add a "Speech Recognition Language" dropdown to Settings -> AI -> Voice so users can pin the language Wispr Flow transcribes in. Introduces a VoiceInputLanguage enum setting (AutoDetect default, cloud-synced globally), renders the dropdown below the toggle-key dropdown (gated on Voice Input being enabled), and extends the Transcriber::transcribe trait to carry an optional language forwarded via TranscribeRequest. AutoDetect sends no language, preserving today's behavior. Wired at both transcribe call sites (editor voice input and the CLI agent footer). Adds unit tests for the enum default/code() and TranscribeRequest language serialization. Part of QUALITY-1066. Co-Authored-By: Warp <agent@warp.dev>
There was a problem hiding this comment.
Overview
Client half of QUALITY-1066 (voice language selection). Adds a VoiceInputLanguage enum setting (AutoDetect default, cloud-synced globally), a "Speech Recognition Language" dropdown in Settings → AI → Voice (gated on Voice Input enabled), and extends Transcriber::transcribe with language: Option<String> wired at both call sites (editor/view/voice.rs and the CLI agent_input_footer). The code is a faithful, correct mirror of the existing VoiceInputToggleKey pattern.
What I verified (the code is sound)
VoiceInputLanguagemirrorsVoiceInputToggleKeyexactly: same derive list, same#[schemars(... rename_all = "snake_case")], sameimplement_setting_for_enum!shape (differing only inSyncToCloud::GloballyvsNever, the toml path, and the description — all per spec). ISO 639-1code()values are correct (en,es, …th).- The
AISettingsChangedEvent::VoiceInputLanguagevariant is macro-generated bydefine_settings_group!from the newvoice_input_languagefield onAISettings(confirmed incrates/settings/src/macros.rs) — so no explicit enum edit was needed. - The dropdown creation,
SetVoiceInputLanguagehandler, render call, and event subscription all mirror the toggle-key equivalents, including theis_voice_input_enabledgate. Sensible additions:set_menu_max_heightfor the longer 22-item list, and correctly omitting theexplicitly_interacted_with_voiceone-time flag (per spec).LocalOnlyIconState::for_settingcorrectly shows no local-only icon for this globally-synced setting. - Both transcribe call sites read
voice_input_language.code().map(...)and passOption<String>;AutoDetect→None→languageomitted end-to-end. Unit tests cover default/code()/TranscribeRequestserialization (omits for AutoDetect, includes"nl"for Dutch).
Concern
- Missing visual evidence (blocking). This is a user-facing UI change (a new dropdown). The attached screenshot shows the Voice section with the Voice Input toggle disabled (AI requires a signed-in account) — it does not show the "Speech Recognition Language" dropdown rendered, the "Auto-detect" default, the option list, or the hide-when-Voice-Input-off behavior. Per this repo's
review-pr-localguidance, author environment limitations (logged-out OSS sandbox) do not exempt user-facing changes from visual evidence. Please attach a screenshot or short recording captured in a signed-in, AI-enabled Warp environment showing: (1) the dropdown rendered below the key dropdown with "Auto-detect" selected by default; (2) a different language selected with the label updated; (3) the dropdown hidden when Voice Input is toggled off. The OSS sandbox can't sign in (this review sandbox has the same limitation), so capture it from a local desktop or a computer-use-enabled credentialed environment (see Warp's computer use docs). This corresponds to spec validation criteria #4 and #5, which are currently unmet.
Note
The matching server PR (#12740) has a separate review comment on the Wispr language field shape (the documented API expects a list ["en"], but the server sends a bare string). Resolving that is also required for the feature to work end-to-end.
Minor (non-blocking)
The new tests in ai_tests.rs embed use crate::ai::voice::transcribe::TranscribeRequest; inside two test functions; the file's convention is top-level imports (5 top-level use statements, 0 embedded elsewhere). Consider hoisting it to the top with the other imports.
Verdict
Found: 0 critical, 1 important, 0 suggestions
Request changes — the code is correct, but a user-facing dropdown change requires visual evidence of the rendered dropdown (Auto-detect default + option list + hide-when-off) captured in a signed-in, AI-enabled environment before merge.
The two new voice-language transcribe tests embedded a `use crate::ai::voice::transcribe::TranscribeRequest;` inside the test functions; the file's convention is top-level imports. Hoist it to the top with the other `use crate::...` statements and drop the two embedded copies. No behavior change. Addresses review nit on #13720 (QUALITY-1066). Co-Authored-By: Warp <agent@warp.dev>
|
Rework (review cycle 1) — changes requested addressed. Visual proof (the blocking concern): Captured from a signed-in, AI-enabled build. The Warp GUI was built from this branch ( Full set + the expanded list are in the PR description. (Images are hosted on a throwaway draft release Nit (non-blocking): Also hoisted the Note on the matching server PR (#12740): the Wispr |
There was a problem hiding this comment.
Re-review (rework cycle 1) — verdict: Approve
Blocker resolution verified
The blocking finding from the prior review (missing visual evidence for a user-facing change) is resolved. The PR body now embeds 5 screenshots captured from a signed-in dogfood build of this branch (--features voice_input, staging auth). This review downloaded and inspected the assets directly and validated them against the spec's acceptance criteria:
- Invariants #1/#2: the "Speech Recognition Language" dropdown renders in Settings → AI → Voice immediately below "Key for Activating Voice Input", with Auto-detect selected by default. ✔
- Full list: the expanded dropdown shows all 21 options (Auto-detect + 20 languages with native names). ✔
- Invariant #3: selecting a language updates the closed dropdown's label (shown with "Indonesian (Bahasa Indonesia)"). ✔
- Hide gate / criterion #5: with Voice Input toggled off, both dropdowns are hidden (not greyed out). ✔
The prior nit (test-only import hoisted to the top of ai_tests.rs) was addressed in commit 786d5e1 with no behavior change.
Rubric
Correctness, naming, comments, tests, and security all look good. The setting mirrors the existing VoiceInputToggleKey pattern; cloud sync choice (Globally(RespectUserSyncSetting::Yes)) matches the spec's rationale; the Transcriber trait change is wired at both transcribe call sites (editor + CLI agent footer) — a correct superset of the spec. The 4 unit tests cover default, code() mapping, and TranscribeRequest serialization for both Auto-detect and selected-language cases.
Notes for the human merger (not blocking)
- CI coverage: the Rust CI jobs (Formatting + Clippy, tests, release compilation) are skipped on this draft PR — they run when the PR is marked ready / enters the merge queue. Locally the author validated
./script/format --check,cargo check --tests -p warp, andcargo clippy -p warp --all-targets --tests -- -D warnings(both feature sets); the full test binary OOMs in the 15 GB sandbox. Confirm the full suite is green once marked ready. - The throwaway draft release hosting the screenshots (
voice-language-proof-QUALITY-1066) can be deleted after merge.
Verdict
Found: 0 critical, 0 important, 0 suggestions
Approve




Summary
Client half of QUALITY-1066 (voice language selection). Adds a "Speech Recognition Language" dropdown to Settings → AI → Voice so a user can pin the language Wispr Flow transcribes in. The selection flows from the client → the warp-server transcribe API → the Wispr Flow request body. "Auto-detect" (the default) sends no language, preserving today's behavior.
This is the client half; the server half (which forwards the language to Wispr) lives in the matching PR below. Both must ship for the feature to work end to end.
Changes
app/src/settings/ai.rs: newVoiceInputLanguageenum setting —AutoDetectdefault, cloud-synced globally (SyncToCloud::Globally(RespectUserSyncSetting::Yes)),toml_pathagents.voice.voice_input_language; pluscode()(ISO 639-1) anddisplay_name()helpers. Field added toAISettings.app/src/settings_view/ai_page.rs: renders the "Speech Recognition Language" dropdown immediately below the "Key for Activating Voice Input" dropdown, inside the sameis_voice_input_enabledgate; adds theSetVoiceInputLanguageaction + handler, theAISettingsChangedEvent::VoiceInputLanguagesubscription, and enable/disable wiring.app/src/voice/transcriber.rs,app/src/server/voice_transcriber.rs:Transcriber::transcribegainslanguage: Option<String>, forwarded ontoTranscribeRequest.app/src/editor/view/voice.rsandapp/src/ai/blocklist/agent_view/agent_input_footer/mod.rs: read the setting and pass the language at both transcribe call sites.app/src/settings/ai_tests.rs: unit tests for the enum default/code()andTranscribeRequestlanguage serialization.Language list (v1, curated): Auto-detect +
en, es, fr, de, it, pt, nl, hi, ja, ko, zh, ar, ru, pl, sv, tr, uk, id, vi, th.Verification
voice_input_language_default_is_auto_detect,voice_input_language_code_returns_iso_639_1_code,transcribe_request_omits_language_for_auto_detect,transcribe_request_includes_selected_language../script/format --checkpasses;./script/check_no_inline_test_modulespasses.cargo check --tests -p warppasses (the test crate, includingai_tests.rs, type-checks cleanly). Building/running the full warp lib test binary OOMs in this 15 GB sandbox (the singlerustc --testprocess for the warp lib exceeds the memory limit); CI runs the full test suite.cargo clippy -p warp --all-targets --tests -- -D warningspasses with both default features and--features voice_input.Visual proof (user-facing change) — captured from a signed-in, AI-enabled build
The Warp GUI was built from this branch (
cargo build --bin warp --features voice_input, the internal/dogfood channel) and launched signed in viaWARP_API_KEYagainst staging. The "Speech Recognition Language" dropdown was exercised on screen:Screenshots are hosted on a throwaway draft release (
voice-language-proof-QUALITY-1066, no tag created) purely to attach the images to this PR; it can be deleted after this PR merges.Rework (review cycle 1)
use crate::ai::voice::transcribe::TranscribeRequest;import from inside the two new test functions to the top ofapp/src/settings/ai_tests.rs(the file's top-level-import convention). No behavior change (commit 786d5e1).Matching PR
Server half: https://github.com/warpdotdev/warp-server/pull/12740
Originating thread: https://warpdotdev.slack.com/archives/C0BDQDW8V5E/p1784060704730339
Spec:
agents/specs/QUALITY-1066: voice language selection.md(committed in this PR)This PR was generated with Oz.