Cykl życia nakładki głosowej (macOS)
Odbiorcy: współtwórcy aplikacji macOS. Cel: utrzymać przewidywalne działanie nakładki głosowej, gdy wake-word i push-to-talk nachodzą na siebie.Obecna intencja
- Jeśli nakładka jest już widoczna z powodu wake-word, a użytkownik naciśnie hotkey, sesja hotkey przejmuje istniejący tekst zamiast go resetować. Nakładka pozostaje widoczna tak długo, jak długo hotkey jest przytrzymany. Gdy użytkownik puści klawisz: wyślij, jeśli istnieje tekst po
trim, w przeciwnym razie zamknij. - Sam wake-word nadal automatycznie wysyła po ciszy; push-to-talk wysyła natychmiast po puszczeniu.
Zaimplementowane (9 grudnia 2025)
- Sesje nakładki mają teraz token per przechwycenie (wake-word albo push-to-talk). Aktualizacje partial/final/send/dismiss/level są odrzucane, gdy token nie pasuje, co zapobiega nieaktualnym callbackom.
- Push-to-talk przejmuje dowolny widoczny tekst nakładki jako prefiks (więc naciśnięcie hotkey, gdy nakładka wake jest widoczna, zachowuje tekst i dopisuje nową mowę). Czeka do 1,5 s na końcową transkrypcję, po czym wraca do bieżącego tekstu.
- Logowanie chime/nakładki jest emitowane na poziomie
infow kategoriachvoicewake.overlay,voicewake.pttivoicewake.chime(start sesji, partial, final, send, dismiss, powód chime).
Kolejne kroki
- VoiceSessionCoordinator (actor)
- Zarządza dokładnie jedną
VoiceSessionnaraz. - API (oparte na tokenach):
beginWakeCapture,beginPushToTalk,updatePartial,endCapture,cancel,applyCooldown. - Odrzuca callbacki niosące nieaktualne tokeny (zapobiega ponownemu otwieraniu nakładki przez stare rozpoznawacze).
- Zarządza dokładnie jedną
- VoiceSession (model)
- Pola:
token,source(wakeWord|pushToTalk), tekst committed/volatile, flagi chime, timery (auto-send, idle),overlayMode(display|editing|sending), termin cooldownu.
- Pola:
- Powiązanie nakładki
VoiceSessionPublisher(ObservableObject) odwzorowuje aktywną sesję do SwiftUI.VoiceWakeOverlayViewrenderuje wyłącznie przez publisher; nigdy nie mutuje bezpośrednio globalnych singletonów.- Akcje użytkownika w nakładce (
sendNow,dismiss,edit) wywołują callback do coordinatora z tokenem sesji.
- Ujednolicona ścieżka wysyłki
- Przy
endCapture: jeśli tekst po trim jest pusty → zamknij; w przeciwnym razieperformSend(session:)(odtwarza send chime raz, przekazuje dalej, zamyka). - Push-to-talk: bez opóźnienia; wake-word: opcjonalne opóźnienie dla auto-send.
- Zastosuj krótki cooldown do runtime wake po zakończeniu push-to-talk, aby wake-word nie wyzwolił się od razu ponownie.
- Przy
- Logowanie
- Coordinator emituje logi
.infow subsystemieai.openclaw, w kategoriachvoicewake.overlayivoicewake.chime. - Kluczowe zdarzenia:
session_started,adopted_by_push_to_talk,partial,finalized,send,dismiss,cancel,cooldown.
- Coordinator emituje logi
Lista kontrolna debugowania
-
Strumieniuj logi podczas odtwarzania problemu z „lepka” nakładką:
- Zweryfikuj, że aktywny jest tylko jeden token sesji; nieaktualne callbacki powinny być odrzucane przez coordinator.
-
Upewnij się, że puszczenie push-to-talk zawsze wywołuje
endCapturez aktywnym tokenem; jeśli tekst jest pusty, oczekujdismissbez chime ani wysyłki.
Kroki migracji (sugerowane)
- Dodaj
VoiceSessionCoordinator,VoiceSessioniVoiceSessionPublisher. - Zrefaktoryzuj
VoiceWakeRuntime, aby tworzył/aktualizował/kończył sesje zamiast bezpośrednio dotykaćVoiceWakeOverlayController. - Zrefaktoryzuj
VoicePushToTalk, aby przejmował istniejące sesje i wywoływałendCaptureprzy puszczeniu; zastosuj runtime cooldown. - Podłącz
VoiceWakeOverlayControllerdo publishera; usuń bezpośrednie wywołania z runtime/PTT. - Dodaj testy integracyjne dla przejmowania sesji, cooldownu i zamykania przy pustym tekście.