spb/zyquo-agent Public MIT
The autonomous agent that actually operates your Mac — plans, runs real commands, verifies its own work.
Swift 94.7%
Shell 4.1%
Python 0.7%
Makefile 0.5%
1//2// UIApprovalPresenter.swift3// Zyquo Agent4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Bridges the PolicyEngine's ApprovalPresenting protocol to the UI: when the9// gate holds an action, the presenter parks the engine on a10// CheckedContinuation and publishes a PendingApproval to the RunController;11// the inline approval card resolves it (Approve / Approve & remember / Edit /12// Deny). Resolution is single-shot — a second resolve is ignored.13//1415import Foundation1617/// One approval request surfaced to the UI, carrying its resolution hook.18struct PendingApproval: Identifiable, Sendable {19 let id = UUID()20 let action: ActionRequest21 let risk: RiskAssessment22 private let resolver: ApprovalResolver2324 init(action: ActionRequest, risk: RiskAssessment, continuation: CheckedContinuation<ApprovalResolution, Never>) {25 self.action = action26 self.risk = risk27 self.resolver = ApprovalResolver(continuation: continuation)28 }2930 /// Resolves the request exactly once; later calls are no-ops.31 func resolve(_ resolution: ApprovalResolution) {32 resolver.resolve(resolution)33 }34}3536/// Single-shot continuation wrapper (thread-safe).37private final class ApprovalResolver: @unchecked Sendable {38 private let lock = NSLock()39 private var continuation: CheckedContinuation<ApprovalResolution, Never>?4041 init(continuation: CheckedContinuation<ApprovalResolution, Never>) {42 self.continuation = continuation43 }4445 func resolve(_ resolution: ApprovalResolution) {46 lock.lock()47 let continuation = self.continuation48 self.continuation = nil49 lock.unlock()50 continuation?.resume(returning: resolution)51 }52}5354/// The ApprovalPresenting implementation the UI wires into the PolicyEngine.55/// `onRequest` is installed by the RunController and hops to the MainActor.56final class UIApprovalPresenter: ApprovalPresenting, @unchecked Sendable {57 private let lock = NSLock()58 private var _onRequest: (@Sendable (PendingApproval) -> Void)?5960 /// Installed by the RunController before the run starts.61 var onRequest: (@Sendable (PendingApproval) -> Void)? {62 get { lock.lock(); defer { lock.unlock() }; return _onRequest }63 set { lock.lock(); defer { lock.unlock() }; _onRequest = newValue }64 }6566 func requestApproval(for action: ActionRequest, risk: RiskAssessment) async -> ApprovalResolution {67 guard let onRequest else {68 // No UI attached (should not happen in app runs): fail closed.69 return .deny70 }71 return await withCheckedContinuation { continuation in72 onRequest(PendingApproval(action: action, risk: risk, continuation: continuation))73 }74 }75}76