import Foundation import Logger import AppKit public enum XPCCommunicationBridgeError: Swift.Error, LocalizedError { case failedToCreateXPCConnection case xpcServiceError(Error) public var errorDescription: String? { switch self { case .failedToCreateXPCConnection: return "Failed to create XPC connection." case let .xpcServiceError(error): return "Connection to communication bridge error: \(error.localizedDescription)" } } } public class XPCCommunicationBridge { let service: XPCService let logger: Logger @XPCServiceActor var serviceEndpoint: NSXPCListenerEndpoint? public init(logger: Logger) { service = .init( kind: .machService( identifier: Bundle(for: XPCService.self) .object(forInfoDictionaryKey: "BUNDLE_IDENTIFIER_BASE") as! String + ".CommunicationBridge" ), interface: NSXPCInterface(with: CommunicationBridgeXPCServiceProtocol.self), logger: logger ) self.logger = logger } public func setDelegate(_ delegate: XPCServiceDelegate?) { service.delegate = delegate } @discardableResult public func launchExtensionServiceIfNeeded() async throws -> NSXPCListenerEndpoint? { try await withXPCServiceConnected { service, continuation in service.launchExtensionServiceIfNeeded { endpoint in continuation.resume(endpoint) } } } public func quit() async throws { try await withXPCServiceConnected { service, continuation in service.quit { continuation.resume(()) } } } public func updateServiceEndpoint(_ endpoint: NSXPCListenerEndpoint) async throws { try await withXPCServiceConnected { service, continuation in service.updateServiceEndpoint(endpoint: endpoint) { continuation.resume(()) } } } } extension XPCCommunicationBridge { @XPCServiceActor func withXPCServiceConnected( _ fn: @escaping (CommunicationBridgeXPCServiceProtocol, AutoFinishContinuation) -> Void ) async throws -> T { guard let connection = service.connection else { throw XPCCommunicationBridgeError.failedToCreateXPCConnection } do { return try await XPCShared.withXPCServiceConnected(connection: connection, fn) } catch { throw XPCCommunicationBridgeError.xpcServiceError(error) } } } @available(macOS 13.0, *) public func showBackgroundPermissionAlert() { let alert = NSAlert() alert.messageText = "Background Permission Required" alert.informativeText = "GitHub Copilot for Xcode needs permission to run in the background. Without this permission, features won't work correctly." alert.alertStyle = .warning alert.addButton(withTitle: "Open Settings") alert.addButton(withTitle: "Later") let response = alert.runModal() if response == .alertFirstButtonReturn { NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.LoginItems-Settings.extension")!) } }