From acda09942c69a5edc008888ad6b301aaf5b1da6c Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Sun, 16 Aug 2026 15:24:48 +0200 Subject: [PATCH] Fix actor-isolation warnings in ExternalMCPManager's tool conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ExternalMCPManager.convertToolDefinition/convertInputSchema were made nonisolated static func in an earlier session for direct unit testing, but this project's -default-isolation=MainActor makes every type implicitly main-actor-isolated unless marked nonisolated — so those functions referencing Tool.Function.Parameters.Property's init and ExternalMCPServer.slug (both plain data types with no explicit isolation) triggered "main actor-isolated ... can not be referenced from a nonisolated context" warnings, surfacing as Xcode's opaque "exit code 0 but produced no further output" compile failure in a Release build. Marked Tool (and all its nested types) in AIProvider.swift, and ExternalMCPServer/MCPTransportKind/MCPToolDefinition/MCPInputSchema/ MCPPropertySchema in ExternalMCPModels.swift, nonisolated at the type level - they're plain DTOs for JSON request/response mapping with no reason to be actor-isolated at all. Verified with a clean Release build (matching how the warnings were originally surfaced). --- oAI/Providers/AIProvider.swift | 20 ++++++++++++-------- oAI/Services/ExternalMCPModels.swift | 15 +++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/oAI/Providers/AIProvider.swift b/oAI/Providers/AIProvider.swift index 77b9285..3cd06a8 100644 --- a/oAI/Providers/AIProvider.swift +++ b/oAI/Providers/AIProvider.swift @@ -223,28 +223,32 @@ struct StreamChunk { // MARK: - Tool Definition -struct Tool: Codable { +// Plain data types for JSON tool-schema encoding — marked `nonisolated` throughout (each nested +// type independently, since `-default-isolation=MainActor` doesn't cascade isolation-freedom from +// an outer type to its nested declarations) so they stay usable from `nonisolated` contexts like +// ExternalMCPManager's pure conversion helpers, not just from the main actor. +nonisolated struct Tool: Codable { let type: String let function: Function - - struct Function: Codable { + + nonisolated struct Function: Codable { let name: String let description: String let parameters: Parameters - - struct Parameters: Codable { + + nonisolated struct Parameters: Codable { let type: String let properties: [String: Property] let required: [String]? - - struct Property: Codable { + + nonisolated struct Property: Codable { let type: String let description: String let `enum`: [String]? let items: Items? /// Item schema for `type: "array"` properties (e.g. an array of strings). - struct Items: Codable { + nonisolated struct Items: Codable { let type: String } diff --git a/oAI/Services/ExternalMCPModels.swift b/oAI/Services/ExternalMCPModels.swift index e6e221c..b4fb906 100644 --- a/oAI/Services/ExternalMCPModels.swift +++ b/oAI/Services/ExternalMCPModels.swift @@ -9,12 +9,12 @@ import Foundation /// `.http` fields are `url`/`bearerToken`/`headers`. Kept as one flat struct rather than an enum /// with associated values — simpler `Codable` and simpler settings-JSON storage, at the cost of /// each server config carrying some always-unused fields for its transport. -enum MCPTransportKind: String, Codable, Sendable, CaseIterable { +nonisolated enum MCPTransportKind: String, Codable, Sendable, CaseIterable { case stdio case http } -struct ExternalMCPServer: Codable, Identifiable, Sendable { +nonisolated struct ExternalMCPServer: Codable, Identifiable, Sendable { var id: UUID var name: String var transportKind: MCPTransportKind @@ -191,24 +191,27 @@ struct MCPToolsListResult: Decodable { let nextCursor: String? } -struct MCPToolDefinition: Decodable { +// Plain DTOs read from ExternalMCPManager.convertToolDefinition/convertInputSchema — both +// `nonisolated static func` (for direct unit testing) — so these must stay `nonisolated` too, +// same reasoning as `Tool` in AIProvider.swift. +nonisolated struct MCPToolDefinition: Decodable { let name: String let description: String? let inputSchema: MCPInputSchema } -struct MCPInputSchema: Decodable { +nonisolated struct MCPInputSchema: Decodable { let type: String let properties: [String: MCPPropertySchema]? let required: [String]? } -struct MCPPropertySchema: Decodable { +nonisolated struct MCPPropertySchema: Decodable { let type: String? let description: String? let `enum`: [String]? let items: MCPItemsSchema? - struct MCPItemsSchema: Decodable { let type: String? } + nonisolated struct MCPItemsSchema: Decodable { let type: String? } } struct MCPToolCallResult: Decodable {