Overlay de Voz
Ciclo de vida del overlay de voz cuando palabra de activación y push-to-talk se superponen
Audiencia: contribuidores de app macOS. Objetivo: mantener el overlay de voz predecible cuando palabra de activación y push-to-talk se superponen.
#
Intención actual
- Si el overlay ya está visible por palabra de activación y el usuario presiona hotkey, la sesión de hotkey _adopta_ el texto existente en lugar de resetearlo. El overlay permanece mientras se mantiene la hotkey. Cuando el usuario suelta: enviar si hay texto recortado, de lo contrario descartar.
- Palabra de activación sola aún auto-envía en silencio; push-to-talk envía inmediatamente al soltar.
#
Implementado (9 Dic, 2025)
- Las sesiones de overlay ahora llevan un token por captura (palabra de activación o push-to-talk). Las actualizaciones partial/final/send/dismiss/level se descartan cuando el token no coincide, evitando callbacks obsoletos.
- Push-to-talk adopta cualquier texto de overlay visible como prefijo (así presionar hotkey mientras el overlay de wake está arriba mantiene el texto y añade nuevo habla). Espera hasta 1.5s por una transcripción final antes de retroceder al texto actual.
- El logging de chime/overlay se emite a nivel ''info'' en categorías ''voicewake.overlay'', ''voicewake.ptt'', y ''voicewake.chime'' (inicio de sesión, parcial, final, envío, descarte, razón de chime).
#
Próximos pasos
1. VoiceSessionCoordinator (actor)
- Posee exactamente una ''VoiceSession'' a la vez.
- API (basada en token): ''beginWakeCapture'', ''beginPushToTalk'', ''updatePartial'', ''endCapture'', ''cancel'', ''applyCooldown''.
- Descarta callbacks que llevan tokens obsoletos (previene que reconocedores antiguos reabran el overlay).
2. VoiceSession (modelo)
- Campos: ''token'', ''source'' (wakeWord|pushToTalk), texto committed/volatile, flags de chime, temporizadores (auto-envío, idle), ''overlayMode'' (display|editing|sending), deadline de cooldown.
3. Binding de Overlay
- ''VoiceSessionPublisher'' (''ObservableObject'') refleja la sesión activa en SwiftUI.
- ''VoiceWakeOverlayView'' renderiza solo vía publisher; nunca muta singletons globales directamente.
- Acciones de usuario de overlay (''sendNow'', ''dismiss'', ''edit'') llaman de vuelta al coordinator con token de sesión.
4. Ruta de envío unificada
- En ''endCapture'': si texto recortado está vacío → descartar; sino ''performSend(session:)'' (reproduce chime de envío una vez, reenvía, descarta).
- Push-to-talk: sin delay; palabra de activación: delay opcional para auto-envío.
- Aplicar un cooldown corto al runtime de wake después de que push-to-talk termina para que palabra de activación no redispare inmediatamente.
5. Logging
- Coordinator emite logs ''.info'' en subsistema ''bot.molt'', categorías ''voicewake.overlay'' y ''voicewake.chime''.
- Eventos clave: ''session_started'', ''adopted_by_push_to_talk'', ''partial'', ''finalized'', ''send'', ''dismiss'', ''cancel'', ''cooldown''.
#
Lista de verificación de depuración
- Transmite logs mientras reproduces un overlay pegajoso:
''''`bash", "p3": "sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact", "p4": "''''`
sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact
''''`
- Verifica solo un token de sesión activo; callbacks obsoletos deben ser descartados por coordinator.
- Asegura que soltar push-to-talk siempre llame ''endCapture'' con token activo; si texto está vacío, espera ''dismiss'' sin chime ni envío.
#
Pasos de migración (sugeridos)
1. Añadir ''VoiceSessionCoordinator'', ''VoiceSession'', y ''VoiceSessionPublisher''.
2. Refactorizar ''VoiceWakeRuntime'' para crear/actualizar/terminar sesiones en lugar de tocar ''VoiceWakeOverlayController'' directamente.
3. Refactorizar ''VoicePushToTalk'' para adoptar sesiones existentes y llamar ''endCapture'' al soltar; aplicar cooldown de runtime.
4. Conectar ''VoiceWakeOverlayController'' al publisher; remover llamadas directas desde runtime/PTT.
5. Añadir tests de integración para adopción de sesión, cooldown, y descarte de texto vacío.