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// 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