Activación por voz y push-to-talk

Modos

  • Modo activación por voz (predeterminado): reconocedor de voz siempre activo que espera tokens de activación (swabbleTriggerWords). Al coincidir, inicia la captura, muestra el overlay con texto parcial y auto-envía tras silencio.
  • Push-to-talk (mantén Option derecho): mantén la tecla Option derecha para capturar inmediatamente — sin necesidad de activación. El overlay aparece mientras se mantiene presionado; soltar finaliza y reenvía tras un breve retraso para que puedas ajustar el texto.

Comportamiento del runtime (activación por voz)

  • El reconocedor de voz vive en VoiceWakeRuntime.
  • La activación solo se dispara cuando hay una pausa significativa entre la palabra de activación y la siguiente palabra (~0.55s de brecha). El overlay/chime puede empezar en la pausa incluso antes de que comience el comando.
  • Ventanas de silencio: 2.0s cuando el habla fluye, 5.0s si solo se escuchó la activación.
  • Parada forzada: 120s para prevenir sesiones desbocadas.
  • Debounce entre sesiones: 350ms.
  • El overlay se controla vía VoiceWakeOverlayController con coloreo committed/volatile.
  • Después de enviar, el reconocedor se reinicia limpiamente para escuchar la siguiente activación.

Invariantes del ciclo de vida

  • Si la activación por voz está habilitada y los permisos están concedidos, el reconocedor de activación debería estar escuchando (excepto durante una captura explícita de push-to-talk).
  • La visibilidad del overlay (incluyendo el cierre manual vía el botón X) nunca debe impedir que el reconocedor se reanude.

Modo de fallo de overlay atascado (anterior)

Anteriormente, si el overlay se quedaba atascado visible y lo cerrabas manualmente, la activación por voz podía parecer “muerta” porque el intento de reinicio del runtime podía ser bloqueado por la visibilidad del overlay y no se programaba ningún reinicio posterior.

Endurecimiento:

  • El reinicio del runtime de activación ya no es bloqueado por la visibilidad del overlay.
  • La finalización del cierre del overlay dispara un VoiceWakeRuntime.refresh(...) vía VoiceSessionCoordinator, así que cerrar manualmente con X siempre reanuda la escucha.

Detalles de push-to-talk

  • La detección del hotkey usa un monitor global .flagsChanged para Option derecho (keyCode 61 + .option). Solo observamos eventos (sin tragárselos).
  • El pipeline de captura vive en VoicePushToTalk: inicia Speech inmediatamente, transmite parciales al overlay y llama a VoiceWakeForwarder al soltar.
  • Cuando push-to-talk comienza, pausamos el runtime de activación para evitar taps de audio en conflicto; se reinicia automáticamente después de soltar.
  • Permisos: requiere Micrófono + Speech; ver eventos necesita aprobación de Accesibilidad/Input Monitoring.
  • Teclados externos: algunos pueden no exponer Option derecho como se espera — ofrece un atajo alternativo si los usuarios reportan fallos.

Ajustes visibles al usuario

  • Toggle de Voice Wake: habilita el runtime de activación.
  • Mantén Cmd+Fn para hablar: habilita el monitor push-to-talk. Deshabilitado en macOS < 26.
  • Selectores de idioma y micrófono, medidor de nivel en vivo, tabla de palabras de activación, tester (solo local; no reenvía).
  • El selector de micrófono preserva la última selección si un dispositivo se desconecta, muestra una indicación de desconectado y recurre temporalmente al predeterminado del sistema hasta que vuelva.
  • Sonidos: chimes en la detección de activación y al enviar; por defecto el sonido del sistema “Glass” de macOS. Puedes elegir cualquier archivo cargable por NSSound (p. ej. MP3/WAV/AIFF) para cada evento o elegir No Sound.

Comportamiento de reenvío

  • Cuando la activación por voz está habilitada, las transcripciones se reenvían al Gateway/agente activo (el mismo modo local vs remoto usado por el resto de la app de Mac).
  • Las respuestas se entregan al último proveedor principal usado (WhatsApp/Telegram/Discord/WebChat). Si la entrega falla, el error se registra y la ejecución sigue visible vía WebChat/logs de sesión.

Payload de reenvío

  • VoiceWakeForwarder.prefixedTranscript(_:) antepone la indicación de máquina antes de enviar. Compartido entre las rutas de activación por voz y push-to-talk.

Verificación rápida

  • Activa push-to-talk, mantén Cmd+Fn, habla, suelta: el overlay debería mostrar parciales y luego enviar.
  • Mientras mantienes, las orejas de la barra de menú deberían permanecer agrandadas (usa triggerVoiceEars(ttl:nil)); bajan después de soltar.