Skip to main content
Glama
PermissionHelpers.swift5.31 kB
import Foundation import PeekabooBridge import PeekabooCore /// Shared permission checking and formatting utilities enum PermissionHelpers { struct PermissionInfo: Codable { let name: String let isRequired: Bool let isGranted: Bool let grantInstructions: String } struct PermissionStatusResponse: Codable { let source: String let permissions: [PermissionInfo] } /// Try to fetch permissions from a remote Peekaboo Bridge host; falls back to local services on failure. @MainActor private static func remotePermissionsStatus(socketPath override: String? = nil) async -> PermissionsStatus? { let envSocket = ProcessInfo.processInfo.environment["PEEKABOO_BRIDGE_SOCKET"] let resolvedOverride = override ?? envSocket let candidates: [String] = if let explicit = resolvedOverride, !explicit.isEmpty { [explicit] } else { [ PeekabooBridgeConstants.peekabooSocketPath, PeekabooBridgeConstants.claudeSocketPath, PeekabooBridgeConstants.clawdisSocketPath, ] } let identity = PeekabooBridgeClientIdentity( bundleIdentifier: Bundle.main.bundleIdentifier, teamIdentifier: nil, processIdentifier: getpid(), hostname: Host.current().name ) for socketPath in candidates { let client = PeekabooBridgeClient(socketPath: socketPath) do { let handshake = try await client.handshake(client: identity, requestedHost: nil) guard handshake.supportedOperations.contains(.permissionsStatus) else { continue } return try await client.permissionsStatus() } catch { continue } } return nil } /// Get current permission status for all Peekaboo permissions static func getCurrentPermissions( services: any PeekabooServiceProviding, allowRemote: Bool = true, socketPath: String? = nil ) async -> [PermissionInfo] { let response = await self.getCurrentPermissionsWithSource( services: services, allowRemote: allowRemote, socketPath: socketPath ) return response.permissions } /// Get current permission status along with whether a remote helper responded. static func getCurrentPermissionsWithSource( services: any PeekabooServiceProviding, allowRemote: Bool = true, socketPath: String? = nil ) async -> PermissionStatusResponse { // Prefer remote host when available so sandboxes can reuse existing TCC grants. let remoteStatus = allowRemote ? await self.remotePermissionsStatus(socketPath: socketPath) : nil let status: PermissionsStatus = if let remoteStatus { remoteStatus } else { await Task { @MainActor in let screenRecording = await services.screenCapture.hasScreenRecordingPermission() let accessibility = await services.automation.hasAccessibilityPermission() return PermissionsStatus(screenRecording: screenRecording, accessibility: accessibility) }.value } let permissionList = [ PermissionInfo( name: "Screen Recording", isRequired: true, isGranted: status.screenRecording, grantInstructions: "System Settings > Privacy & Security > Screen Recording" ), PermissionInfo( name: "Accessibility", isRequired: true, isGranted: status.accessibility, grantInstructions: "System Settings > Privacy & Security > Accessibility" ) ] let source = remoteStatus != nil ? "bridge" : "local" return PermissionStatusResponse(source: source, permissions: permissionList) } /// Format permission status for display static func formatPermissionStatus(_ permission: PermissionInfo) -> String { // Format permission status for display let status = permission.isGranted ? "Granted" : "Not Granted" let requirement = permission.isRequired ? "Required" : "Optional" return "\(permission.name) (\(requirement)): \(status)" } /// Format permissions for help display with dynamic status static func formatPermissionsForHelp( services: any PeekabooServiceProviding) async -> String { // Format permissions for help display with dynamic status let permissions = await self.getCurrentPermissions(services: services) var output = ["PERMISSIONS:"] for permission in permissions { output.append(" \(self.formatPermissionStatus(permission))") // Only show grant instructions if permission is not granted if !permission.isGranted { output.append(" Grant via: \(permission.grantInstructions)") } } output.append("") output.append("Check detailed permission status:") output.append(" peekaboo permissions") return output.joined(separator: "\n") } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/steipete/Peekaboo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server