From 1bbb4243220f44174f2ca2b193e5c5f034b20048 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 9 Dec 2025 05:02:03 +0100 Subject: [PATCH] Overlay: block new sessions while sending; delay runtime restart --- apps/macos/Sources/Clawdis/VoiceWakeOverlay.swift | 5 +++++ apps/macos/Sources/Clawdis/VoiceWakeRuntime.swift | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/macos/Sources/Clawdis/VoiceWakeOverlay.swift b/apps/macos/Sources/Clawdis/VoiceWakeOverlay.swift index 41571bdda..9a1fbc0c1 100644 --- a/apps/macos/Sources/Clawdis/VoiceWakeOverlay.swift +++ b/apps/macos/Sources/Clawdis/VoiceWakeOverlay.swift @@ -13,6 +13,7 @@ final class VoiceWakeOverlayController: ObservableObject { enum Source: String { case wakeWord, pushToTalk } @Published private(set) var model = Model() + var isVisible: Bool { self.model.isVisible } struct Model { var text: String = "" @@ -51,6 +52,10 @@ final class VoiceWakeOverlayController: ObservableObject { forwardEnabled: Bool = false, isFinal: Bool = false) -> UUID { + if self.model.isSending { + self.logger.log(level: .info, "overlay drop session_start while sending") + return self.activeToken ?? UUID() + } let token = UUID() let message = """ overlay session_start source=\(source.rawValue) \ diff --git a/apps/macos/Sources/Clawdis/VoiceWakeRuntime.swift b/apps/macos/Sources/Clawdis/VoiceWakeRuntime.swift index 6e97a57d5..7bac07069 100644 --- a/apps/macos/Sources/Clawdis/VoiceWakeRuntime.swift +++ b/apps/macos/Sources/Clawdis/VoiceWakeRuntime.swift @@ -359,7 +359,7 @@ actor VoiceWakeRuntime { self.overlayToken = nil self.cooldownUntil = Date().addingTimeInterval(self.debounceAfterSend) - self.restartRecognizer() + self.scheduleRestartRecognizer() } // MARK: - Audio level handling @@ -406,6 +406,18 @@ actor VoiceWakeRuntime { } } + private func scheduleRestartRecognizer(delay: TimeInterval = 0.7) { + Task { [weak self] in + let nanos = UInt64(max(0, delay) * 1_000_000_000) + try? await Task.sleep(nanoseconds: nanos) + guard let self else { return } + if self.isCapturing { return } + let overlayVisible = await MainActor.run { VoiceWakeOverlayController.shared.isVisible } + if overlayVisible { return } + self.restartRecognizer() + } + } + func applyPushToTalkCooldown() { self.cooldownUntil = Date().addingTimeInterval(self.debounceAfterSend) }