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%
3.5 KB · 89 lines swift
Raw Blame History
1//2//  Tool.swift3//  Zyquo Agent4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  The tool contract. A Tool exposes a JSON-Schema described capability to the9//  model and executes validated calls inside a task's workspace. Execution is10//  streaming (chunks surface live in the UI/terminal drawer), cancellable, and11//  — for anything that touches the system — always pre-cleared by the12//  PolicyEngine before `execute` runs a side effect.13//1415import Foundation1617/// Live output emitted while a tool runs (streamed to the transcript and the18/// Activity/Terminal drawer line by line).19enum ToolOutputChunk: Sendable {20    case stdout(String)21    case stderr(String)22    /// Informational progress that is neither stdout nor stderr (e.g. "wrote 3 files").23    case note(String)24}2526/// Everything a tool needs from its surroundings to run one call.27struct ToolExecutionContext: Sendable {28    /// The task's working directory — cwd for shell commands, root for file tools.29    let workspaceURL: URL30    /// Safety gate: every side-effecting action is classified and, if needed,31    /// held for user approval before it runs.32    let policy: PolicyEngine33    /// Append-only record of every executed action.34    let audit: AuditLog35    /// Streams live output chunks to the UI as they happen.36    let onOutput: @Sendable (ToolOutputChunk) -> Void37    /// Tracks files the agent creates/modifies (badges, checkpoints). Optional38    /// so contexts without a managed workspace (tests, scratch runs) still work.39    var workspaceManager: WorkspaceManager? = nil40}4142/// Outcome of one tool call, before it is threaded back to the model as a43/// `ToolResult`.44struct ToolExecutionResult: Sendable {45    /// Text handed back to the model (stdout+stderr, file contents, listings…).46    var content: String47    /// True when the tool failed (non-zero exit, missing file, denied action).48    var isError: Bool = false4950    static func success(_ content: String) -> ToolExecutionResult {51        ToolExecutionResult(content: content)52    }5354    static func failure(_ message: String) -> ToolExecutionResult {55        ToolExecutionResult(content: message, isError: true)56    }57}5859/// A capability the agent can invoke. Conform and register in `ToolRegistry`60/// to make a new tool available to every agent-capable model.61protocol Tool: Sendable {62    /// Wire name the model calls (snake_case, stable across releases).63    var name: String { get }64    /// Model-facing usage documentation — written like onboarding docs: what it65    /// does, when to use it, constraints, failure modes.66    var description: String { get }67    /// JSON Schema for the arguments object.68    var parametersSchema: JSONValue { get }6970    /// Runs one validated call. Must route any system side effect through71    /// `context.policy` first and honor Task cancellation promptly.72    func execute(arguments: JSONValue, context: ToolExecutionContext) async throws -> ToolExecutionResult73}7475extension Tool {76    /// The provider-neutral spec handed to models via the normalized interface77    /// (ToolSpec carries the schema as a serialized JSON string).78    var toolSpec: ToolSpec {79        let schemaString: String80        if let data = try? JSONEncoder().encode(parametersSchema),81           let encoded = String(data: data, encoding: .utf8) {82            schemaString = encoded83        } else {84            schemaString = #"{"type":"object"}"#85        }86        return ToolSpec(name: name, description: description, parametersJSONSchema: schemaString)87    }88}89