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// JSONValue.swift3// Zyquo Agent4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// A Codable representation of arbitrary JSON, used to embed tool parameter9// JSON Schemas and tool_use inputs verbatim inside Encodable wire requests10// (JSONEncoder cannot encode `Any`).11//1213import Foundation1415/// Arbitrary JSON, encodable/decodable losslessly.16enum JSONValue: Codable, Hashable {17 case null18 case bool(Bool)19 case number(Double)20 case string(String)21 case array([JSONValue])22 case object([String: JSONValue])2324 init(from decoder: Decoder) throws {25 let container = try decoder.singleValueContainer()26 if container.decodeNil() {27 self = .null28 } else if let b = try? container.decode(Bool.self) {29 self = .bool(b)30 } else if let n = try? container.decode(Double.self) {31 self = .number(n)32 } else if let s = try? container.decode(String.self) {33 self = .string(s)34 } else if let a = try? container.decode([JSONValue].self) {35 self = .array(a)36 } else if let o = try? container.decode([String: JSONValue].self) {37 self = .object(o)38 } else {39 throw DecodingError.dataCorruptedError(in: container, debugDescription: "unrecognized JSON value")40 }41 }4243 func encode(to encoder: Encoder) throws {44 var container = encoder.singleValueContainer()45 switch self {46 case .null: try container.encodeNil()47 case .bool(let b): try container.encode(b)48 case .number(let n):49 // Preserve integer-looking numbers without a trailing ".0".50 if n.truncatingRemainder(dividingBy: 1) == 0,51 n >= Double(Int64.min), n <= Double(Int64.max) {52 try container.encode(Int64(n))53 } else {54 try container.encode(n)55 }56 case .string(let s): try container.encode(s)57 case .array(let a): try container.encode(a)58 case .object(let o): try container.encode(o)59 }60 }6162 /// Parses a JSON string (e.g. a ToolSpec's parameter schema). Returns nil63 /// on malformed input.64 static func parse(_ jsonString: String) -> JSONValue? {65 guard let data = jsonString.data(using: .utf8) else { return nil }66 return try? JSONDecoder().decode(JSONValue.self, from: data)67 }6869 /// The canonical empty-object schema, used when a tool declares no parameters70 /// or a schema string fails to parse (providers reject absent schemas).71 static let emptyObject = JSONValue.object([:])7273 /// Compact JSON serialization (used to turn tool_use inputs back into the74 /// normalized ToolCall.argumentsJSON string).75 var jsonString: String {76 guard let data = try? JSONEncoder().encode(self),77 let string = String(data: data, encoding: .utf8) else {78 return "{}"79 }80 return string81 }82}83