From bfb015dbc55fc2444707657faa87f6d9699ddd76 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 15 Jul 2026 01:49:23 -0700 Subject: [PATCH] fix(macos): silence Xcode 27 source warnings (#108081) * fix(macos): silence Xcode 27 warnings * fix(macos): silence remaining Swift 6.4 warnings --- .../Sources/OpenClaw/DashboardLinkBrowserTabBar.swift | 10 ++++++++-- apps/macos/Sources/OpenClaw/DockIconManager.swift | 2 +- .../Sources/OpenClawChatUI/ChatSpeechController.swift | 10 +++++++++- .../Sources/OpenClawKit/CameraAuthorization.swift | 8 ++++++++ .../Sources/OpenClawKit/DeviceIdentity.swift | 11 +++++++++++ .../Sources/OpenClawKit/GatewayNodeSession.swift | 2 +- .../Sources/OpenClawKit/TalkBufferedAudioPlayer.swift | 10 +++++++++- 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/apps/macos/Sources/OpenClaw/DashboardLinkBrowserTabBar.swift b/apps/macos/Sources/OpenClaw/DashboardLinkBrowserTabBar.swift index 350283614667..376d9edb48c4 100644 --- a/apps/macos/Sources/OpenClaw/DashboardLinkBrowserTabBar.swift +++ b/apps/macos/Sources/OpenClaw/DashboardLinkBrowserTabBar.swift @@ -182,11 +182,17 @@ private final class DashboardLinkBrowserTabItemView: NSView { override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) + // SDK 27 restores AppKit's "Color" suffix; older Swift importers expose + // the same API as quinaryLabel. + #if compiler(>=6.4) + let hoverColor = NSColor.quinaryLabelColor + #else + let hoverColor = NSColor.quinaryLabel + #endif let color: NSColor? = if self.isActive { .quaternaryLabelColor } else if self.isHovered { - // macOS 14+ spells this without the "Color" suffix; quinaryLabelColor does not exist. - .quinaryLabel + hoverColor } else { nil } diff --git a/apps/macos/Sources/OpenClaw/DockIconManager.swift b/apps/macos/Sources/OpenClaw/DockIconManager.swift index 946b4b3a31e9..7006464472b6 100644 --- a/apps/macos/Sources/OpenClaw/DockIconManager.swift +++ b/apps/macos/Sources/OpenClaw/DockIconManager.swift @@ -58,7 +58,7 @@ final class DockIconManager: NSObject, @unchecked Sendable { } private func setupObservers() { - Task { @MainActor in + Task { @MainActor [self] in guard let app = NSApp else { self.logger.warning("NSApp not ready, delaying Dock observers") try? await Task.sleep(for: .milliseconds(200)) diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSpeechController.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSpeechController.swift index 5936d243c315..1e6f3af2b854 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSpeechController.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSpeechController.swift @@ -227,7 +227,7 @@ public final class OpenClawChatSpeechController { /// Whole-clip playback for gateway-rendered container audio. File metadata /// helps AVAudioPlayer parse clips whose type is not obvious from the bytes. @MainActor -final class ChatSpeechClipPlayer: NSObject, ChatSpeechClipPlaying, @preconcurrency AVAudioPlayerDelegate { +final class ChatSpeechClipPlayer: NSObject, ChatSpeechClipPlaying { private var player: AVAudioPlayer? private var continuation: CheckedContinuation? @@ -276,6 +276,14 @@ final class ChatSpeechClipPlayer: NSObject, ChatSpeechClipPlaying, @preconcurren } } +// SDK 27 imports AVAudioPlayerDelegate with compatible isolation. Older SDKs +// still need the preconcurrency bridge for this main-actor implementation. +#if compiler(>=6.4) +extension ChatSpeechClipPlayer: AVAudioPlayerDelegate {} +#else +extension ChatSpeechClipPlayer: @preconcurrency AVAudioPlayerDelegate {} +#endif + /// On-device fallback voice via AVSpeechSynthesizer. @MainActor final class ChatSpeechLocalSpeaker: NSObject, ChatSpeechLocalSpeaking, diff --git a/apps/shared/OpenClawKit/Sources/OpenClawKit/CameraAuthorization.swift b/apps/shared/OpenClawKit/Sources/OpenClawKit/CameraAuthorization.swift index cfb1bca6b471..faae12d66f0e 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawKit/CameraAuthorization.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawKit/CameraAuthorization.swift @@ -8,11 +8,19 @@ public enum CameraAuthorization { case .authorized: return true case .notDetermined: + #if compiler(>=6.4) + return await withCheckedContinuation { cont in + AVCaptureDevice.requestAccess(for: mediaType) { granted in + cont.resume(returning: granted) + } + } + #else return await withCheckedContinuation(isolation: nil) { cont in AVCaptureDevice.requestAccess(for: mediaType) { granted in cont.resume(returning: granted) } } + #endif case .denied, .restricted: return false @unknown default: diff --git a/apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceIdentity.swift b/apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceIdentity.swift index ebd16bb39184..1e21592b047b 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceIdentity.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceIdentity.swift @@ -196,6 +196,16 @@ public enum DeviceIdentityStore { self.loadOrCreate(profile: .primary) } + #if compiler(>=6.4) + static func withStateDirectory( + _ url: URL, + operation: nonisolated(nonsending) () async throws -> T) async rethrows -> T + { + try await DeviceIdentityPaths.$scopedStateDirURL.withValue( + url, + operation: operation) + } + #else static func withStateDirectory( _ url: URL, operation: () async throws -> T, @@ -206,6 +216,7 @@ public enum DeviceIdentityStore { operation: operation, isolation: isolation) } + #endif public static func loadOrCreate(profile: GatewayDeviceIdentityProfile) -> DeviceIdentity { self.loadOrCreate( diff --git a/apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayNodeSession.swift b/apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayNodeSession.swift index e0c5696bf5df..4ac76471d446 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayNodeSession.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayNodeSession.swift @@ -1316,7 +1316,7 @@ extension GatewayNodeSession { } let receiptID = UUID() - let task = Task { + let task = Task { [self] in await Self.invokeWithTimeout( request: request, timeoutMs: timeoutMs, diff --git a/apps/shared/OpenClawKit/Sources/OpenClawKit/TalkBufferedAudioPlayer.swift b/apps/shared/OpenClawKit/Sources/OpenClawKit/TalkBufferedAudioPlayer.swift index 8f906a5bff26..96e3b1ced398 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawKit/TalkBufferedAudioPlayer.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawKit/TalkBufferedAudioPlayer.swift @@ -10,7 +10,7 @@ import OSLog /// silently failing playback can never hang the talk loop. Shared by the iOS /// and macOS talk runtimes. @MainActor -public final class TalkBufferedAudioPlayer: NSObject, @preconcurrency AVAudioPlayerDelegate { +public final class TalkBufferedAudioPlayer: NSObject { public static let shared = TalkBufferedAudioPlayer() override public init() { @@ -168,4 +168,12 @@ public final class TalkBufferedAudioPlayer: NSObject, @preconcurrency AVAudioPla }) } } + +// SDK 27 imports AVAudioPlayerDelegate with compatible isolation. Older SDKs +// still need the preconcurrency bridge for this main-actor implementation. +#if compiler(>=6.4) +extension TalkBufferedAudioPlayer: AVAudioPlayerDelegate {} +#else +extension TalkBufferedAudioPlayer: @preconcurrency AVAudioPlayerDelegate {} +#endif #endif