Fix actor-isolation warnings in ExternalMCPManager's tool conversion

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).
This commit is contained in:
2026-08-16 15:24:48 +02:00
parent 4d65ab7703
commit acda09942c
2 changed files with 21 additions and 14 deletions
+12 -8
View File
@@ -223,28 +223,32 @@ struct StreamChunk {
// MARK: - Tool Definition // 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 type: String
let function: Function let function: Function
struct Function: Codable { nonisolated struct Function: Codable {
let name: String let name: String
let description: String let description: String
let parameters: Parameters let parameters: Parameters
struct Parameters: Codable { nonisolated struct Parameters: Codable {
let type: String let type: String
let properties: [String: Property] let properties: [String: Property]
let required: [String]? let required: [String]?
struct Property: Codable { nonisolated struct Property: Codable {
let type: String let type: String
let description: String let description: String
let `enum`: [String]? let `enum`: [String]?
let items: Items? let items: Items?
/// Item schema for `type: "array"` properties (e.g. an array of strings). /// Item schema for `type: "array"` properties (e.g. an array of strings).
struct Items: Codable { nonisolated struct Items: Codable {
let type: String let type: String
} }
+9 -6
View File
@@ -9,12 +9,12 @@ import Foundation
/// `.http` fields are `url`/`bearerToken`/`headers`. Kept as one flat struct rather than an enum /// `.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 /// 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. /// 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 stdio
case http case http
} }
struct ExternalMCPServer: Codable, Identifiable, Sendable { nonisolated struct ExternalMCPServer: Codable, Identifiable, Sendable {
var id: UUID var id: UUID
var name: String var name: String
var transportKind: MCPTransportKind var transportKind: MCPTransportKind
@@ -191,24 +191,27 @@ struct MCPToolsListResult: Decodable {
let nextCursor: String? 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 name: String
let description: String? let description: String?
let inputSchema: MCPInputSchema let inputSchema: MCPInputSchema
} }
struct MCPInputSchema: Decodable { nonisolated struct MCPInputSchema: Decodable {
let type: String let type: String
let properties: [String: MCPPropertySchema]? let properties: [String: MCPPropertySchema]?
let required: [String]? let required: [String]?
} }
struct MCPPropertySchema: Decodable { nonisolated struct MCPPropertySchema: Decodable {
let type: String? let type: String?
let description: String? let description: String?
let `enum`: [String]? let `enum`: [String]?
let items: MCPItemsSchema? let items: MCPItemsSchema?
struct MCPItemsSchema: Decodable { let type: String? } nonisolated struct MCPItemsSchema: Decodable { let type: String? }
} }
struct MCPToolCallResult: Decodable { struct MCPToolCallResult: Decodable {