Problem
Voice dictation (#5755) biases the ASR toward domain terms using a hardcoded list of ~31 generic developer keyterms (Qwen, MCP, TypeScript, worktree, …) in packages/cli/src/ui/voice/voice-keyterms.ts. There is no way for a user to extend this list, so project- or domain-specific proper nouns — product names, internal services, non-English terms — are frequently mis-transcribed and there is no supported workaround.
The underlying Qwen ASR API already accepts a vocabulary-biasing hint (corpus_text for the realtime transport, a leading system message for the batch transport), and the CLI already plumbs the keyterm list into both. The only missing piece is a user-facing way to contribute terms.
Proposed solution
Let users supply their own keyterms via a file, merged with the existing global list:
- New optional setting
general.voice.keytermsFile — a path to a keyterms file (absolute, or relative to the workspace root).
- Zero-config default: auto-load
.qwen/voice-keyterms.txt when present and no explicit path is set.
- File format: one term per line; blank lines and
# comments ignored.
- The merged list is deduped case-insensitively (global terms keep their canonical casing) and capped by term count and total length so a large file degrades gracefully instead of bloating every request or feeding the existing keyterm-echo guard.
- Reading the file never throws — on any error the static globals are used alone, so a bad path can never break dictation.
Scope
- Applies to the Qwen ASR transports only (
qwen3-asr-flash-realtime realtime + qwen3-asr-flash batch), which is where keyterm biasing is already wired.
- Out of scope: the DashScope
fun-asr / paraformer realtime transport. Those models support hotwords through a different, stateful mechanism (pre-register a vocabulary via the VocabularyService, then pass a vocabulary_id), not an inline string. Wiring that is a separate, larger change and is intentionally not included here.
Test plan
- Unit tests for
buildVoiceKeyterms: auto-discovery, explicit absolute/relative paths, comment/blank-line handling, case-insensitive dedupe, missing-file fallback, and the size cap.
- Typecheck, lint, and existing voice transcriber / settings-schema suites stay green.
Problem
Voice dictation (#5755) biases the ASR toward domain terms using a hardcoded list of ~31 generic developer keyterms (
Qwen,MCP,TypeScript,worktree, …) inpackages/cli/src/ui/voice/voice-keyterms.ts. There is no way for a user to extend this list, so project- or domain-specific proper nouns — product names, internal services, non-English terms — are frequently mis-transcribed and there is no supported workaround.The underlying Qwen ASR API already accepts a vocabulary-biasing hint (
corpus_textfor the realtime transport, a leading system message for the batch transport), and the CLI already plumbs the keyterm list into both. The only missing piece is a user-facing way to contribute terms.Proposed solution
Let users supply their own keyterms via a file, merged with the existing global list:
general.voice.keytermsFile— a path to a keyterms file (absolute, or relative to the workspace root)..qwen/voice-keyterms.txtwhen present and no explicit path is set.#comments ignored.Scope
qwen3-asr-flash-realtimerealtime +qwen3-asr-flashbatch), which is where keyterm biasing is already wired.fun-asr/paraformerrealtime transport. Those models support hotwords through a different, stateful mechanism (pre-register a vocabulary via the VocabularyService, then pass avocabulary_id), not an inline string. Wiring that is a separate, larger change and is intentionally not included here.Test plan
buildVoiceKeyterms: auto-discovery, explicit absolute/relative paths, comment/blank-line handling, case-insensitive dedupe, missing-file fallback, and the size cap.