Fix setup: shell PATH, restart race, Tailscale wait, macOS 27 grants
This commit is contained in:
@@ -80,7 +80,7 @@ func appElement(_ pid: pid_t) -> AXUIElement {
|
||||
|
||||
func requireTrust() throws {
|
||||
if !AXIsProcessTrusted() {
|
||||
throw ToolError("byre lacks Accessibility, so no app's tree can be read or acted on; the human must switch byre on in System Settings → Privacy & Security → Accessibility")
|
||||
throw ToolError("byre lacks \(deviceControl), so no app's tree can be read or acted on; the human must switch \(grantee) on in System Settings → Privacy & Security → \(deviceControl)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,24 @@ import ApplicationServices
|
||||
import ScreenCaptureKit
|
||||
|
||||
let orionBundle = "com.kagi.kagimacOS"
|
||||
let deviceControl = "Device Control and Data Access"
|
||||
|
||||
// The server and the app each run byre-hands, and System Settings lists them as two entries: the server's helper by its file name, the app by its own.
|
||||
let grantee: String = {
|
||||
var pid = getppid()
|
||||
while pid > 1 {
|
||||
var buf = [CChar](repeating: 0, count: Int(MAXPATHLEN))
|
||||
if proc_pidpath(pid, &buf, UInt32(buf.count)) > 0, String(cString: buf).hasSuffix(".app/Contents/MacOS/Byre") {
|
||||
return "Byre (with byre's app icon)"
|
||||
}
|
||||
var info = proc_bsdinfo()
|
||||
if proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &info, Int32(MemoryLayout<proc_bsdinfo>.size)) <= 0 {
|
||||
break
|
||||
}
|
||||
pid = pid_t(info.pbi_ppid)
|
||||
}
|
||||
return "byre (with the black terminal icon)"
|
||||
}()
|
||||
|
||||
func permission(_ name: String, _ status: String, _ detail: String, _ pane: String) -> [String: String] {
|
||||
return ["name": name, "status": status, "detail": detail, "settings": "x-apple.systempreferences:com.apple.preference.security?Privacy_\(pane)"]
|
||||
@@ -14,26 +32,26 @@ func checkScreenRecording() async -> [String: String] {
|
||||
return permission("Screen Recording", "granted", "Listed the screen (displays: \(content.displays.count), windows: \(content.windows.count)).", "ScreenCapture")
|
||||
} catch {
|
||||
CGRequestScreenCaptureAccess()
|
||||
return permission("Screen Recording", "missing", "Listing the screen failed (\(error.localizedDescription)). Switch byre on in Screen Recording.", "ScreenCapture")
|
||||
return permission("Screen Recording", "missing", "Listing the screen failed (\(error.localizedDescription)). Switch \(grantee) on in Screen Recording.", "ScreenCapture")
|
||||
}
|
||||
}
|
||||
|
||||
func checkAccessibility() -> [String: String] {
|
||||
if !AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeUnretainedValue(): true] as CFDictionary) {
|
||||
return permission("Accessibility", "missing", "Switch byre on in Accessibility.", "Accessibility")
|
||||
return permission(deviceControl, "missing", "Switch \(grantee) on in \(deviceControl).", "Accessibility")
|
||||
}
|
||||
guard let finder = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.finder").first else {
|
||||
return permission("Accessibility", "unchecked", "Granted, but Finder isn't running to read its menu bar.", "Accessibility")
|
||||
return permission(deviceControl, "unchecked", "Granted, but Finder isn't running to read its menu bar.", "Accessibility")
|
||||
}
|
||||
do {
|
||||
guard let bar = try attr(appElement(finder.processIdentifier), kAXMenuBarAttribute) else {
|
||||
return permission("Accessibility", "missing", "Granted, but reading Finder's menu bar returned nothing. Switch byre off and on again in Accessibility.", "Accessibility")
|
||||
return permission(deviceControl, "missing", "Granted, but reading Finder's menu bar returned nothing. Switch \(grantee) off and on again in \(deviceControl).", "Accessibility")
|
||||
}
|
||||
return permission("Accessibility", "granted", "Read Finder's menu bar (menus: \(try children(bar as! AXUIElement).count)).", "Accessibility")
|
||||
return permission(deviceControl, "granted", "Read Finder's menu bar (menus: \(try children(bar as! AXUIElement).count)).", "Accessibility")
|
||||
} catch let e as ToolError {
|
||||
return permission("Accessibility", "missing", e.message, "Accessibility")
|
||||
return permission(deviceControl, "missing", e.message, "Accessibility")
|
||||
} catch {
|
||||
return permission("Accessibility", "missing", "\(error)", "Accessibility")
|
||||
return permission(deviceControl, "missing", "\(error)", "Accessibility")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +62,7 @@ func checkOrion() -> [String: String] {
|
||||
let target = NSAppleEventDescriptor(bundleIdentifier: orionBundle)
|
||||
let status = AEDeterminePermissionToAutomateTarget(target.aeDesc, typeWildCard, typeWildCard, true)
|
||||
if status != noErr {
|
||||
return permission("Automation of Orion", "missing", "macOS refused Apple events to Orion (\(status)). Switch Orion on under byre in Automation.", "Automation")
|
||||
return permission("Automation of Orion", "missing", "macOS refused Apple events to Orion (\(status)). Switch Orion on under \(grantee) in Automation.", "Automation")
|
||||
}
|
||||
do {
|
||||
let windows = try osa("tell application \"Orion\" to count windows").int32Value
|
||||
@@ -65,7 +83,7 @@ func checkFolder(_ name: String, _ path: String) -> [String: String] {
|
||||
let entries = try FileManager.default.contentsOfDirectory(atPath: dir)
|
||||
return permission(name, "granted", "Listed \(dir) (entries: \(entries.count)).", "FilesAndFolders")
|
||||
} catch {
|
||||
return permission(name, "missing", "Listing \(dir) failed (\(error.localizedDescription)). Switch \(name) on under byre in Files & Folders.", "FilesAndFolders")
|
||||
return permission(name, "missing", "Listing \(dir) failed (\(error.localizedDescription)). Switch \(name) on under \(grantee) in Files & Folders.", "FilesAndFolders")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user