From 9218c881cd6a786f1c9f22e5c38960b8e02090ac Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 12 Nov 2026 19:53:34 -0800 Subject: [PATCH] fix(desktop): weak-link ScreenCaptureKit so the Computer Use helper loads on macOS 14 and 15 The helper targets macOS 14 but CI builds it with the macOS 26 SDK, which linked the macOS 26 screenshot classes strongly, so dyld refused to load the helper on older macOS and Settings reported it could not connect. The build now weak-links the framework and fails if any ScreenCaptureKit reference is strong. --- apps/desktop/scripts/build-native.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/desktop/scripts/build-native.ts b/apps/desktop/scripts/build-native.ts index ea5c8af243e..eb0d3f1e99d 100644 --- a/apps/desktop/scripts/build-native.ts +++ b/apps/desktop/scripts/build-native.ts @@ -89,6 +89,7 @@ function compileComputerUse(): void { try { execFileSync('xcrun', ['lipo', binary, '-verify_arch', 'arm64', 'x86_64']) execFileSync('codesign', ['--verify', '--strict', bundle]) + assertWeakScreenCaptureKit(binary) return } catch { rmSync(bundle, { recursive: true, force: true }) @@ -108,6 +109,11 @@ function compileComputerUse(): void { '-O', '-target', `${arch}-apple-macosx14.0`, + // The macOS 26 screenshot classes do not exist on 14/15; a strong reference stops the helper loading there. + '-Xlinker', + '-weak_framework', + '-Xlinker', + 'ScreenCaptureKit', 'native/computer-use/ComputerUse.swift', '-o', output, @@ -118,9 +124,27 @@ function compileComputerUse(): void { } execFileSync('xcrun', ['lipo', '-create', ...parts, '-output', binary], { stdio: 'inherit' }) for (const part of parts) rmSync(part) + assertWeakScreenCaptureKit(binary) execFileSync('codesign', ['--force', '--sign', '-', bundle], { stdio: 'inherit' }) recordNativeBuild('computer-use', outputs) logger.info('Compiled native macOS Computer Use helper') } +/** + * The helper targets macOS 14 but uses ScreenCaptureKit classes added later behind `#available`. + * Runners build on the newest macOS, where a strong reference still loads, so this is the only + * place a helper that dyld would refuse on older macOS is caught before it ships. + */ +function assertWeakScreenCaptureKit(binary: string) { + const strong = execFileSync('nm', ['-m', binary], { encoding: 'utf8' }) + .split('\n') + .filter( + (line) => line.includes('(undefined) external') && line.includes('(from ScreenCaptureKit)') + ) + if (strong.length > 0) + throw new Error( + `The Computer Use helper links ScreenCaptureKit strongly and would not load on macOS 14/15:\n${strong.join('\n')}` + ) +} + if (args.includes('--computer-use')) compileComputerUse()