SPB Git

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%
2.5 KB · 78 lines swift
Raw Blame History
1//2//  AgentStep.swift3//  Zyquo Agent4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  One iteration of the plan→act→observe→reflect loop: the assistant's thought9//  and text, the tool call(s) it issued, and the observed result(s). Steps are10//  the unit the UI renders as cards, the Transcript persists, and the11//  MemoryManager compacts.12//1314import Foundation1516/// Lifecycle of a single step.17enum AgentStepStatus: String, Codable, Sendable {18    /// Model output still streaming in.19    case streaming20    /// Tool call held at the policy gate, waiting for the user.21    case awaitingApproval22    /// Tool call(s) executing.23    case executing24    case completed25    case failed26    /// User denied the action or cancelled mid-step.27    case cancelled28}2930/// One executed (or in-flight) tool call inside a step, with its observation.31struct AgentToolInvocation: Codable, Identifiable, Sendable {32    var id: String { call.id }33    var call: ToolCall34    var result: ToolResult?35    /// Exit code for process-backed tools (bash, osascript).36    var exitCode: Int32?37    /// How the policy gate resolved this action.38    var policyDecision: PolicyDecisionRecord?39    var startedAt: Date?40    var finishedAt: Date?41}4243/// Snapshot of the gate's ruling on an action, kept for the step card and audit.44struct PolicyDecisionRecord: Codable, Sendable {45    enum Ruling: String, Codable, Sendable {46        case autoAllowed47        case approvedByUser48        case editedAndApproved49        case denied50    }51    var ruling: Ruling52    var riskLabel: String?53    /// Explanation shown on the approval card.54    var rationale: String?55}5657/// One iteration of the agent loop.58struct AgentStep: Codable, Identifiable, Sendable {59    var id: UUID = UUID()60    /// 1-based position in the run.61    var index: Int62    var status: AgentStepStatus = .streaming63    /// Reasoning-model thinking (collapsible in UI); nil for non-reasoning models.64    var thinking: String?65    /// The assistant's visible text for this turn (thought line and/or final answer).66    var text: String67    var toolInvocations: [AgentToolInvocation] = []68    var startedAt: Date = Date()69    var finishedAt: Date?70    /// Tokens consumed by this step's model turn (for LoopGuard budgets).71    var inputTokens: Int?72    var outputTokens: Int?7374    /// True when the model produced a final answer (no tool calls) — the loop's75    /// termination signal.76    var isFinal: Bool { toolInvocations.isEmpty && status == .completed }77}78