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
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
}
+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
/// 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 {