66 lines
2.2 KiB
Swift
66 lines
2.2 KiB
Swift
/// Computer Use: semantic AX and background-safe macOS computer use.
|
|
///
|
|
/// Four modes:
|
|
/// mcp — run the MCP server over stdio
|
|
/// --check — print permission status as JSON to stdout and exit
|
|
/// --list-apps — print running regular apps as JSON to stdout and exit
|
|
/// (default) — open the permission setup GUI
|
|
|
|
import AppKit
|
|
import Foundation
|
|
|
|
setbuf(stdout, nil)
|
|
|
|
let args = CommandLine.arguments
|
|
let subcommand = args.count >= 2 ? args[1] : ""
|
|
|
|
switch subcommand {
|
|
case "mcp":
|
|
if ProcessInfo.processInfo.environment["OPENWORK_COMPUTER_USE_CURSOR_OVERLAY"] == "0" {
|
|
let server = MCPServer()
|
|
await server.run()
|
|
} else {
|
|
await runMCPServerWithOverlay()
|
|
}
|
|
case "--check":
|
|
// Fresh process → fresh TCC read → always accurate.
|
|
let status = ComputerUsePermissions.status()
|
|
let json = "{\"ok\":\(status.ok),\"accessibility\":\(status.accessibility),\"screenRecording\":\(status.screenRecording)}"
|
|
print(json)
|
|
exit(0)
|
|
case "--list-apps":
|
|
// Running regular apps (Dock-visible). Needs no TCC permissions, so this
|
|
// is safe to call from the composer at any time.
|
|
let apps = NSWorkspace.shared.runningApplications
|
|
.filter { $0.activationPolicy == .regular }
|
|
.compactMap(\.localizedName)
|
|
.sorted { $0.localizedCaseInsensitiveCompare($1) == .orderedAscending }
|
|
let payload: [String: Any] = ["ok": true, "apps": apps]
|
|
let data = (try? JSONSerialization.data(withJSONObject: payload)) ?? Data("{\"ok\":false,\"apps\":[]}".utf8)
|
|
print(String(decoding: data, as: UTF8.self))
|
|
exit(0)
|
|
default:
|
|
await runPermissionSetupApp()
|
|
}
|
|
|
|
@MainActor
|
|
func runMCPServerWithOverlay() async {
|
|
NSApplication.shared.setActivationPolicy(.accessory)
|
|
let server = MCPServer()
|
|
Task.detached {
|
|
await server.run()
|
|
await MainActor.run {
|
|
NSApplication.shared.terminate(nil)
|
|
}
|
|
}
|
|
NSApplication.shared.run()
|
|
}
|
|
|
|
@MainActor
|
|
func runPermissionSetupApp() async {
|
|
NSApplication.shared.setActivationPolicy(.regular)
|
|
let appDelegate = PermissionSetupAppDelegate()
|
|
NSApplication.shared.delegate = appDelegate
|
|
NSApplication.shared.run()
|
|
}
|