Files
openclaw/apps/macos/Sources/OpenClaw/ComputerControlProvider.swift
Peter Steinberger 98a8e0d63f fix(macos): prevent mismatched CUA driver endpoints (#123845)
* fix(macos): make CUA driver endpoint handoff atomic

* ci: record approved CUA env budget increase

* test: satisfy changed-gate hygiene

* style(macos): use failable endpoint string conversion

* fix(macos): strip retired CUA worker environment

* ci: constrain CUA env budget approval

* test(macos): isolate inherited CUA environment
2026-08-14 16:04:43 -07:00

111 lines
3.4 KiB
Swift

import Foundation
import OpenClawProtocol
enum ComputerControlProvider: String, CaseIterable, Sendable {
case peekaboo
case cua
static var peekabooComputerUseDescriptor: OpenClawProtocol.AnyCodable {
OpenClawProtocol.AnyCodable([
"contractVersion": 2,
"provider": [
"id": "peekaboo",
"label": "Peekaboo",
"generation": "peekaboo-v2:\(UUID().uuidString.lowercased())",
],
"actions": [
"screenshot",
"left_click",
"right_click",
"middle_click",
"double_click",
"triple_click",
"mouse_move",
"left_click_drag",
"left_mouse_down",
"left_mouse_up",
"scroll",
"type",
"key",
"hold_key",
"list_apps",
"list_windows",
"get_accessibility_tree",
"get_cursor_position",
"get_window_state",
"launch_app",
"kill_app",
"bring_to_front",
"set_value",
"invoke_menu",
],
"targets": ["screen", "window", "element"],
"deliveryModes": ["background", "foreground"],
"observations": ["image", "accessibility"],
"features": [
"recording": false,
"agentCursor": false,
"multiDisplay": true,
],
] as [String: Any])
}
static func current(
defaults: UserDefaults = AppDefaults.standard,
cuaAvailable: Bool = CuaDriverArtifact.bundledExecutableURL != nil) -> Self
{
guard let rawValue = defaults.string(forKey: computerControlProviderKey),
let provider = Self(rawValue: rawValue)
else { return .peekaboo }
if provider == .cua, !cuaAvailable { return .peekaboo }
return provider
}
var displayName: String {
switch self {
case .peekaboo: "Peekaboo"
case .cua: "CUA"
}
}
}
struct CuaDriverWorkerEndpoint: Encodable, Equatable, Sendable {
private let v = 1
let socketPath: String
let binaryPath: String
func environmentValue() throws -> String {
try String(bytes: JSONEncoder().encode(self), encoding: .utf8)!
}
}
enum CuaDriverWorkerEnvironment {
static let endpoint = "OPENCLAW_CUA_DRIVER_ENDPOINT"
static let inheritedFamilyPrefixes = [String(endpoint.dropLast("ENDPOINT".count)), "CUA_DRIVER_"]
}
enum CuaDriverArtifact {
static let resourceName = "cua-driver"
static var bundledExecutableURL: URL? {
self.executableURL(in: Bundle.main.resourceURL)
}
static func executableURL(
in resourceURL: URL?,
fileManager: FileManager = .default) -> URL?
{
guard let resourceURL else { return nil }
let candidate = resourceURL.appendingPathComponent(self.resourceName, isDirectory: false)
guard let values = try? candidate.resourceValues(forKeys: [
.isRegularFileKey,
.isSymbolicLinkKey,
]),
values.isRegularFile == true,
values.isSymbolicLink != true,
fileManager.isExecutableFile(atPath: candidate.path)
else { return nil }
return candidate
}
}