From d5b305b250066a629d1a9d37620992814c272d36 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 8 Mar 2026 13:57:58 +0000 Subject: [PATCH] fix: follow up #39321 and #38445 landings --- .secrets.baseline | 4 ++-- CHANGELOG.md | 2 ++ apps/macos/Sources/OpenClaw/TalkModeRuntime.swift | 12 ++++++++---- .../LowCoverageViewSmokeTests.swift | 9 +++++++++ .../TalkModeRuntimeSpeechTests.swift | 14 ++++++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 apps/macos/Tests/OpenClawIPCTests/TalkModeRuntimeSpeechTests.swift diff --git a/.secrets.baseline b/.secrets.baseline index 15df9508431..2964cc29bda 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -11481,7 +11481,7 @@ "filename": "src/agents/models-config.e2e-harness.ts", "hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d", "is_verified": false, - "line_number": 130 + "line_number": 131 } ], "src/agents/models-config.fills-missing-provider-apikey-from-env-var.e2e.test.ts": [ @@ -13034,5 +13034,5 @@ } ] }, - "generated_at": "2026-03-08T05:05:36Z" + "generated_at": "2026-03-08T13:52:40Z" } diff --git a/CHANGELOG.md b/CHANGELOG.md index eb7c0d4f82c..b331327d2c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Docs: https://docs.openclaw.ai - Mattermost replies: keep `root_id` pinned to the existing thread root when an agent replies inside a thread, while still using reply-target threading for top-level posts. (#27744) thanks @hnykda. - Agents/failover: detect Amazon Bedrock `Too many tokens per day` quota errors as rate limits across fallback, cron retry, and memory embeddings while keeping context-window `too many tokens per request` errors out of the rate-limit lane. (#39377) Thanks @gambletan. - Android/Play distribution: remove self-update, background location, `screen.record`, and background mic capture from the Android app, narrow the foreground service to `dataSync` only, and clean up the legacy `location.enabledMode=always` preference migration. (#39660) Thanks @obviyus. +- macOS overlays: fix VoiceWake, Talk, and Notify overlay exclusivity crashes by removing shared `inout` visibility mutation from `OverlayPanelFactory.present`, and add a repeated Talk overlay smoke test. (#39275, #39321) Thanks @fellanH. +- macOS Talk Mode: set the speech recognition request `taskHint` to `.dictation` for mic capture, and add regression coverage for the request defaults. (#38445) Thanks @dmiv. ## 2026.3.7 diff --git a/apps/macos/Sources/OpenClaw/TalkModeRuntime.swift b/apps/macos/Sources/OpenClaw/TalkModeRuntime.swift index 56d44ed3ee6..77fffcd811b 100644 --- a/apps/macos/Sources/OpenClaw/TalkModeRuntime.swift +++ b/apps/macos/Sources/OpenClaw/TalkModeRuntime.swift @@ -70,6 +70,11 @@ actor TalkModeRuntime { private let minSpeechRMS: Double = 1e-3 private let speechBoostFactor: Double = 6.0 + static func configureRecognitionRequest(_ request: SFSpeechAudioBufferRecognitionRequest) { + request.shouldReportPartialResults = true + request.taskHint = .dictation + } + // MARK: - Lifecycle func setEnabled(_ enabled: Bool) async { @@ -176,10 +181,9 @@ actor TalkModeRuntime { return } - self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest() - self.recognitionRequest?.shouldReportPartialResults = true - self.recognitionRequest?.taskHint = .dictation - guard let request = self.recognitionRequest else { return } + let request = SFSpeechAudioBufferRecognitionRequest() + Self.configureRecognitionRequest(request) + self.recognitionRequest = request if self.audioEngine == nil { self.audioEngine = AVAudioEngine() diff --git a/apps/macos/Tests/OpenClawIPCTests/LowCoverageViewSmokeTests.swift b/apps/macos/Tests/OpenClawIPCTests/LowCoverageViewSmokeTests.swift index 0526e287b02..4d8e5839d51 100644 --- a/apps/macos/Tests/OpenClawIPCTests/LowCoverageViewSmokeTests.swift +++ b/apps/macos/Tests/OpenClawIPCTests/LowCoverageViewSmokeTests.swift @@ -66,6 +66,15 @@ struct LowCoverageViewSmokeTests { try? await Task.sleep(nanoseconds: 250_000_000) } + @Test func `talk overlay presents twice and dismisses`() async { + let controller = TalkOverlayController() + controller.present() + controller.updateLevel(0.4) + controller.present() + controller.dismiss() + try? await Task.sleep(nanoseconds: 250_000_000) + } + @Test func `visual effect view hosts in NS hosting view`() { let hosting = NSHostingView(rootView: VisualEffectView(material: .sidebar)) _ = hosting.fittingSize diff --git a/apps/macos/Tests/OpenClawIPCTests/TalkModeRuntimeSpeechTests.swift b/apps/macos/Tests/OpenClawIPCTests/TalkModeRuntimeSpeechTests.swift new file mode 100644 index 00000000000..c72749daba4 --- /dev/null +++ b/apps/macos/Tests/OpenClawIPCTests/TalkModeRuntimeSpeechTests.swift @@ -0,0 +1,14 @@ +import Speech +import Testing +@testable import OpenClaw + +struct TalkModeRuntimeSpeechTests { + @Test func `speech request uses dictation defaults`() { + let request = SFSpeechAudioBufferRecognitionRequest() + + TalkModeRuntime.configureRecognitionRequest(request) + + #expect(request.shouldReportPartialResults) + #expect(request.taskHint == .dictation) + } +}