voice.enabled OFFMaster switch. While OFF the entire voice subsystem stays inactive; the secondary toggles are hidden.
Toggles obrigatórios em Settings (`voice.enabled`, `voice.talkMode`, `voice.hotWord`, `voice.backend`, `voice.bargeIn`, `voice.debugRecord`), defaults seguros (tudo OFF na instalação fresca exceto `bargeIn` que é ON quando `talkMode` ativo), e contrato de privacidade — ring buffer pré-wake de 2 s **nunca** sai do dispositivo, post-wake só vai pro `services/ai/voice` configurado, nada é logado/persistido a menos que `debugRecord = true`. Surface compartilhada: `KodeVoiceSettingsTile` em `engines/sdk/koder_kit`.
The six knobs every Koder app with a microphone surfaces under Settings → Voice. Defaults are paranoid: nothing captures audio until the user opts in.
voice.enabled OFFMaster switch. While OFF the entire voice subsystem stays inactive; the secondary toggles are hidden.
voice.talkMode OFFContinuous-conversation mode. Mic stays open while in talk mode; idle timeout returns to standby.
voice.hotWord OFFWake-word detection ("Hey Koder"). Pre-wake ring buffer is strictly local — never leaves the device.
voice.backend openWakeWordopenWakeWord by default; falls back to Porcupine when openWakeWord is unavailable.
voice.bargeIn ON when talkModeAllows the user to interrupt mid-response. ON automatically when talkMode flips ON.
voice.debugRecord OFF (dev only)Captures raw audio to a local file for debugging. Dev builds only; ignored in non-dev builds.
Wake-word fires only when the configured backend matches the hot phrase. Pre-wake samples that do not match are dropped instantly.
Voice subsystem errors carry the canonical PRODUCT-CAT-CODE-SEQ shape. <APP> stands in for the calling product (KALL, KORE, …).
<APP>-VOICE-001-* Microphone permission denied by the OS or revoked in Settings.<APP>-VOICE-002-* Configured wake-word backend (openWakeWord / Porcupine) failed to load.<APP>-VOICE-003-* Wake-word detection collapsed mid-session; toggles flip OFF defensively.<APP>-VOICE-004-* Voice toggle ON but Settings consent never granted; aborting capture.Normative spec derived from
services/ai/voice/docs/rfcs/RFC-001-wake-word-talk-mode.md. Implementação obrigatória viaKodeVoiceSettingsTileemengines/sdk/koder_kit(Flutter) — nunca rolar UI de voz local.
Aplica-se a todo app Koder com microfone, em qualquer plataforma: Flutter mobile (Android + iOS), Flutter desktop (Linux + macOS + Windows), e qualquer surface futura que capture áudio do usuário (TV em casos específicos, web PWA com getUserMedia). CLI/TUI sem mic não implementam wake-word; recebem texto via stdin como hoje.
Todo app Koder com mic capability deve ter um agrupamento "Voz"
(Voice em en-US) na tela de Settings, contendo, na ordem:
voice.enabled)voice.talkMode) — mostrado apenas quando
voice.enabled = truevoice.hotWord) — input com sugestõesvoice.backend) — dropdownvoice.bargeIn) — visível apenas em Talk Modevoice.debugRecord) — visível
apenas em builds dev/debugA implementação é via drop-in KodeVoiceSettingsTile do koder_kit.
Nunca desenhar a tile localmente — todo app importa o componente
e o renderiza onde quiser na tela de Settings.
Em uma instalação nova (ou após Reset Settings) os valores armazenados devem corresponder à tabela abaixo. Absência da chave = mesmo valor que default, ou seja, configuração mínima é silently OFF.
| Chave | Default | Notas |
|---|---|---|
voice.enabled |
OFF | Privacy-by-default; sem opt-in nenhuma feature de voz roda |
voice.talkMode |
OFF | Exige voice.enabled = true; UI deve desabilitar (greyed-out) quando enabled é false |
voice.hotWord |
"hey kode" |
Lower-case ASCII; pode ser sobrescrito por hot-words alternativos (PT-BR: "oi kode") |
voice.backend |
autoselect | Plugin escolhe (preferindo openWakeWord); usuário pode forçar "openwakeword" ou "porcupine" |
voice.bargeIn |
ON (em Talk Mode) | Cancela TTS quando o usuário começa a falar — relevante apenas com talkMode ativo |
voice.debugRecord |
OFF | Disponível apenas em builds dev/debug; em release builds o toggle não aparece sequer |
Quando voice.enabled for toggled OFF em runtime, o app deve parar
imediatamente o capture de mic (interromper qualquer detector ativo) +
limpar o ring buffer (ver §4).
voice.hotWord aceita qualquer string que tenha um modelo carregável
no detector configurado. O KodeVoiceSettingsTile deve:
hey kode, oi kode, etc.)voice.ErrModelMissing e exibir a mensagem padronizada
per specs/errors/user-facing-messages.kmdO detector mantém um ring buffer rolante de 2 segundos de áudio PCM 16-bit mono 16 kHz. Esse buffer é uma estrutura de memória local e nunca sai do dispositivo. Especificamente:
services/ai/voice antes da wake-event detectionvoice.debugRecord = true — o pré-wake permanece
efêmero)Quando o detector dispara (wake event), o conteúdo do buffer + o
áudio capturado a partir desse instante é encaminhado ao endpoint
configurado em services/ai/voice para STT. O encaminhamento dessa
amostra deve documentar via KoderApp.config():
debugRecord só em dev buildsvoice.debugRecord = true faz com que toda a captura post-wake
seja salva localmente em ~/.kode/voice/debug/<utc-timestamp>.wav.
Esse caminho é local-only, mas é uma feature trapdoor — em release
builds o toggle não pode aparecer.
KoderApp.isDebugBuild no koder_kit.debugRecord (mesmo em dev), o app deve
exibir um warning visível ("Debug recording está ON — áudio sendo
gravado em disco") e logar a ativação no console.voice.bargeIn = true (default em Talk Mode) significa: quando o TTS
está reproduzindo a resposta do agente E o VAD detecta fala do
usuário, o TTS deve ser cancelado imediatamente (fade-out ≤ 100 ms
para evitar pop) e o detector volta para escuta.
voice.bargeIn = false é o modo half-duplex tradicional: o usuário
espera o TTS terminar antes de falar. Útil em ambientes ruidosos
onde o falso-positivo de VAD seria mais incômodo que esperar.
Erros de voz que cheguem ao usuário devem seguir
specs/errors/user-facing-messages.kmd: texto humanizado em
pt-BR/en-US, botão "Ver detalhes" expandindo o erro técnico, ID único
no formato <APP>-VOICE-<CODE>-<SEQ>. Mapping mínimo:
| Cenário | ID | Texto pt-BR |
|---|---|---|
| Permissão de mic negada | <APP>-VOICE-MIC-001 |
"Permita o acesso ao microfone para usar comandos de voz." |
| Modelo de hot-word não encontrado | <APP>-VOICE-MODEL-001 |
"A palavra '$hot' não tem modelo no detector $backend." |
| Endpoint de voz indisponível | <APP>-VOICE-NET-001 |
"Servidor de voz indisponível. Tente novamente." |
| Detector backend falhou na inicialização | <APP>-VOICE-INIT-001 |
"Não foi possível ativar o detector $backend." |
KodeApp.metrics() deve emitir três counters bumping em wake-event:
voice.wake.detected, voice.wake.false_positive (registrado quando
o usuário cancela explicitamente o pipeline pós-wake), voice.wake.error.voice.wake.detect_ms, voice.stt.first_token_ms, voice.tts.first_audio_ms.Quando um app Koder ganha mic capability, os pull requests devem incluir:
KodeVoiceSettingsTile do koder_kit na tela de SettingsdebugRecord toggle não aparece em release buildsCI gate: koder-relay status-style probe não cobre voice; falar com
/k-test <module> quando o tile + adoption sweep landar (KSTACK-89).
services/ai/voice/docs/rfcs/RFC-001-wake-word-talk-mode.mdengines/sdk/koder_kit/lib/src/voice/
(a criar — esta surface ainda não existe; landa em KSTACK-89 junto com
a adoção apps-side)