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// Message.swift3// Zyquo Agent4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Ported from Zyquo Cloud, extended with the normalized tool-calling fields9// (docs/PROVIDER-REUSE.md §5.3): `toolCalls` on assistant turns and10// `toolResults` on the turn that feeds results back. Clients render these11// per wire format (OpenAI `tool_calls` + role:"tool" messages; Anthropic12// `tool_use` assistant blocks + `tool_result` user blocks) — Message is the13// provider-neutral turn representation the agent loop works with.14//1516import Foundation1718/// One turn in a conversation transcript.19struct Message: Codable, Identifiable, Hashable {20 enum Role: String, Codable {21 case system22 case user23 case assistant24 }2526 let id: UUID27 var role: Role28 var text: String29 /// Reasoning/thinking text streamed by reasoning models (collapsible in the UI).30 var reasoning: String?31 /// Image attachments (user messages, vision models).32 var attachments: [Attachment]33 /// Web-search citations (Perplexity).34 var citations: [Citation]35 /// Tool calls emitted by the model on this assistant turn. Threaded back to36 /// the provider verbatim so multi-step tool history round-trips correctly.37 var toolCalls: [ToolCall]?38 /// Tool results being returned to the model. Clients render these as39 /// role:"tool" messages (OpenAI schema) or tool_result user blocks (Anthropic).40 var toolResults: [ToolResult]?41 /// Model that produced this message (assistant turns) or was targeted (user turns).42 var modelID: String?43 var provider: ProviderID?44 var usage: TokenUsage?45 /// Estimated USD cost computed from catalog pricing at receive time.46 var estimatedCost: Double?47 var createdAt: Date48 /// Set while a response is streaming; exactly one message can be streaming at a time.49 var isStreaming: Bool = false50 /// Human-readable error if generation failed mid-message.51 var errorText: String?5253 init(54 id: UUID = UUID(),55 role: Role,56 text: String,57 reasoning: String? = nil,58 attachments: [Attachment] = [],59 citations: [Citation] = [],60 toolCalls: [ToolCall]? = nil,61 toolResults: [ToolResult]? = nil,62 modelID: String? = nil,63 provider: ProviderID? = nil,64 usage: TokenUsage? = nil,65 estimatedCost: Double? = nil,66 createdAt: Date = Date()67 ) {68 self.id = id69 self.role = role70 self.text = text71 self.reasoning = reasoning72 self.attachments = attachments73 self.citations = citations74 self.toolCalls = toolCalls75 self.toolResults = toolResults76 self.modelID = modelID77 self.provider = provider78 self.usage = usage79 self.estimatedCost = estimatedCost80 self.createdAt = createdAt81 }8283 /// An assistant turn carrying the model's tool calls (text may be empty).84 static func assistantToolCalls(_ calls: [ToolCall], text: String = "", reasoning: String? = nil) -> Message {85 Message(role: .assistant, text: text, reasoning: reasoning, toolCalls: calls)86 }8788 /// The turn that returns tool results to the model. Multiple results in one89 /// turn cover parallel tool calls.90 static func toolResultsMessage(_ results: [ToolResult]) -> Message {91 Message(role: .user, text: "", toolResults: results)92 }93}9495/// A file attached to a user message. Images go to vision models as base64;96/// text files are injected into the prompt.97struct Attachment: Codable, Identifiable, Hashable {98 enum Kind: String, Codable {99 case image100 case textFile101 }102103 let id: UUID104 var kind: Kind105 var fileName: String106 /// image: raw image bytes; textFile: UTF-8 contents.107 var data: Data108 /// MIME type for images (image/png, image/jpeg, image/webp, image/gif).109 var mimeType: String110111 init(id: UUID = UUID(), kind: Kind, fileName: String, data: Data, mimeType: String) {112 self.id = id113 self.kind = kind114 self.fileName = fileName115 self.data = data116 self.mimeType = mimeType117 }118}119120/// A numbered web source backing an assistant answer (Perplexity sonar family).121struct Citation: Codable, Identifiable, Hashable {122 let id: UUID123 var index: Int124 var url: URL125 var title: String?126127 init(id: UUID = UUID(), index: Int, url: URL, title: String? = nil) {128 self.id = id129 self.index = index130 self.url = url131 self.title = title132 }133}134