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// PersistenceService.swift3// Zyquo Agent4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// JSON persistence in ~/Library/Application Support/ZyquoAgent/:9// vault.zq encrypted API-key vault (SecureKeyStore)10// Workspaces/ per-task working directories (WorkspaceManager)11// settings.json, personas.json, … generic documents12//13// Ported from Zyquo Cloud (root folder renamed ZyquoCloud → ZyquoAgent;14// Cloud's per-conversation persistence is superseded by Agent's Task15// persistence, which arrives with the Agent layer).16//1718import Foundation1920struct PersistenceService {21 static let shared = PersistenceService()2223 let rootDirectory: URL24 /// Per-task working directories root (Phase 2 Workspace layer).25 var workspacesDirectory: URL { rootDirectory.appendingPathComponent("Workspaces") }2627 private let encoder: JSONEncoder28 private let decoder: JSONDecoder2930 init(rootDirectory: URL? = nil) {31 let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]32 self.rootDirectory = rootDirectory ?? base.appendingPathComponent("ZyquoAgent")33 encoder = JSONEncoder()34 encoder.outputFormatting = [.prettyPrinted, .sortedKeys]35 encoder.dateEncodingStrategy = .iso860136 decoder = JSONDecoder()37 decoder.dateDecodingStrategy = .iso860138 try? FileManager.default.createDirectory(at: workspacesDirectory, withIntermediateDirectories: true)39 }4041 // MARK: - Generic documents (personas, templates, settings…)4243 func load<T: Decodable>(_ type: T.Type, from fileName: String) -> T? {44 let url = rootDirectory.appendingPathComponent(fileName)45 guard let data = try? Data(contentsOf: url) else { return nil }46 return try? decoder.decode(type, from: data)47 }4849 func save<T: Encodable>(_ value: T, to fileName: String) {50 let url = rootDirectory.appendingPathComponent(fileName)51 guard let data = try? encoder.encode(value) else { return }52 try? data.write(to: url, options: .atomic)53 }54}55