From 78641fcb2ee81bfad77ca32887b1a541695a874f Mon Sep 17 00:00:00 2001 From: Anthony Drendel Date: Tue, 3 Feb 2026 10:58:09 +0100 Subject: [PATCH 1/6] Fix running tests on macOS 15 (#100) --- .../APICompatibilityAnyLanguageModelTests.swift | 9 ++++++++- .../APICompatibilityFoundationModelsTests.swift | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift index a3d62967..217f8c59 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift @@ -3,8 +3,15 @@ import Testing #if canImport(FoundationModels) import AnyLanguageModel + private let isSystemLanguageModelAvailable: Bool = { + if #available(macOS 26.0, *) { + return SystemLanguageModel.default.isAvailable + } + return false + }() + @available(macOS 26.0, *) - @Test("AnyLanguageModel Drop-In Compatibility", .enabled(if: SystemLanguageModel.default.isAvailable)) + @Test("AnyLanguageModel Drop-In Compatibility", .enabled(if: isSystemLanguageModelAvailable)) func anyLanguageModelCompatibility() async throws { let model = SystemLanguageModel.default let session = LanguageModelSession( diff --git a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift index 6e446e79..fa3f3c40 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift @@ -3,8 +3,18 @@ import Testing #if canImport(FoundationModels) import FoundationModels + private let isFoundationModelsSystemLanguageModelAvailable: Bool = { + if #available(macOS 26.0, *) { + return SystemLanguageModel.default.isAvailable + } + return false + }() + @available(macOS 26.0, *) - @Test("FoundationModels Drop-In Compatibility", .enabled(if: SystemLanguageModel.default.isAvailable)) + @Test( + "FoundationModels Drop-In Compatibility", + .enabled(if: isFoundationModelsSystemLanguageModelAvailable) + ) func foundationModelsCompatibility() async throws { let model = SystemLanguageModel.default let session = LanguageModelSession( From 67d6a67047a87982c1ff5fc5300bec648b2354c8 Mon Sep 17 00:00:00 2001 From: Noor Bhatia <73331825+noorbhatia@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:37:45 +0530 Subject: [PATCH 2/6] Implement prewarm for MLXLanguageModel (#97) * Implement prewarm for MLXLanguageModel * Reduce prewarm to just loadContext --- .../Models/MLXLanguageModel.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift index 8f44b319..72a5a88c 100644 --- a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift @@ -357,6 +357,24 @@ import Foundation return LanguageModelSession.ResponseStream(stream: stream) } + + /// Prewarms the model + public func prewarm( + for session: LanguageModelSession, + promptPrefix: Prompt? + ) { + let modelId = self.modelId + let hub = self.hub + let directory = self.directory + + Task { + do { + _ = try await loadContext(modelId: modelId, hub: hub, directory: directory) + } catch { + // Ignore errors during prewarm + } + } + } } // MARK: - Options Mapping From e90b48f28125591830ecf6a6232360642e61d830 Mon Sep 17 00:00:00 2001 From: Anthony Drendel Date: Mon, 2 Feb 2026 17:27:43 +0100 Subject: [PATCH 3/6] Fix running tests on iOS 26 Simulator on macOS Sequia --- ...PICompatibilityAnyLanguageModelTests.swift | 4 +-- ...PICompatibilityFoundationModelsTests.swift | 4 +-- .../SystemLanguageModelTests.swift | 32 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift index 217f8c59..1cca521f 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift @@ -4,13 +4,13 @@ import Testing import AnyLanguageModel private let isSystemLanguageModelAvailable: Bool = { - if #available(macOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } return false }() - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test("AnyLanguageModel Drop-In Compatibility", .enabled(if: isSystemLanguageModelAvailable)) func anyLanguageModelCompatibility() async throws { let model = SystemLanguageModel.default diff --git a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift index fa3f3c40..4bb2394c 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift @@ -4,13 +4,13 @@ import Testing import FoundationModels private let isFoundationModelsSystemLanguageModelAvailable: Bool = { - if #available(macOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } return false }() - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test( "FoundationModels Drop-In Compatibility", .enabled(if: isFoundationModelsSystemLanguageModelAvailable) diff --git a/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift b/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift index 8b7d12d9..6d186df0 100644 --- a/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift @@ -3,7 +3,7 @@ import AnyLanguageModel #if canImport(FoundationModels) private let isSystemLanguageModelAvailable = { - if #available(macOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } else { return false @@ -88,7 +88,7 @@ import AnyLanguageModel .enabled(if: isSystemLanguageModelAvailable) ) struct SystemLanguageModelTests { - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func basicResponse() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -97,7 +97,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func withInstructions() async throws { let model = SystemLanguageModel() let session = LanguageModelSession( @@ -109,7 +109,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func withTemperature() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -122,7 +122,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func streamingString() async throws { guard isSystemLanguageModelAvailable else { return } let model: SystemLanguageModel = SystemLanguageModel() @@ -139,7 +139,7 @@ import AnyLanguageModel #expect(!snapshots.last!.rawContent.jsonString.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func streamingGeneratedContent() async throws { guard isSystemLanguageModelAvailable else { return } let model: SystemLanguageModel = SystemLanguageModel() @@ -159,7 +159,7 @@ import AnyLanguageModel #expect(!snapshots.last!.rawContent.jsonString.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func withTools() async throws { let weatherTool = WeatherTool() let session = LanguageModelSession(model: SystemLanguageModel.default, tools: [weatherTool]) @@ -180,7 +180,7 @@ import AnyLanguageModel #expect(content.contains("72°F")) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func conversationContext() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -222,7 +222,7 @@ import AnyLanguageModel // MARK: - Guided Generation Tests - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationSimpleStruct() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -234,7 +234,7 @@ import AnyLanguageModel #expect(!response.content.message.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithMultipleFields() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -248,7 +248,7 @@ import AnyLanguageModel #expect(!response.content.occupation.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationMathCalculation() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -263,7 +263,7 @@ import AnyLanguageModel #expect(combined.contains("15") || combined.contains("27") || combined.contains("42")) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationNestedStruct() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -279,7 +279,7 @@ import AnyLanguageModel #expect(response.content.rgb.blue >= 0 && response.content.rgb.blue <= 255) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithArray() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -295,7 +295,7 @@ import AnyLanguageModel } } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithEnumConstraint() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -308,7 +308,7 @@ import AnyLanguageModel #expect(response.content.confidence >= 0.0 && response.content.confidence <= 1.0) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithInstructions() async throws { let session = LanguageModelSession( model: SystemLanguageModel.default, @@ -325,7 +325,7 @@ import AnyLanguageModel #expect(!response.content.occupation.isEmpty) } - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) @Test func guidedGenerationStreaming() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) From b5bfde5477df3244430aa88338277d6d2f8affeb Mon Sep 17 00:00:00 2001 From: Anthony Drendel Date: Tue, 3 Feb 2026 22:39:21 +0100 Subject: [PATCH 4/6] Add required dependencies for AnyLanguageModelMacros --- Package.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 88e273ce..3916bf01 100644 --- a/Package.swift +++ b/Package.swift @@ -75,8 +75,10 @@ let package = Package( .macro( name: "AnyLanguageModelMacros", dependencies: [ - .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), ] ), .testTarget( From 6a29c154e2fefe2be1df8487fe45b999d5a9522e Mon Sep 17 00:00:00 2001 From: Anthony Drendel Date: Tue, 3 Feb 2026 22:39:48 +0100 Subject: [PATCH 5/6] Fix MLXLanguageModel compilation on watchOS --- Sources/AnyLanguageModel/Models/MLXLanguageModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift index 72a5a88c..9522fbca 100644 --- a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift @@ -1,11 +1,11 @@ import Foundation -#if canImport(UIKit) +#if canImport(UIKit) && canImport(CoreImage) import UIKit import CoreImage #endif -#if canImport(AppKit) +#if canImport(AppKit) && canImport(CoreImage) import AppKit import CoreImage #endif From bfe77f25fc0fd25048da559ad0fe1b59163d6d7d Mon Sep 17 00:00:00 2001 From: Anthony Drendel Date: Tue, 3 Feb 2026 22:40:46 +0100 Subject: [PATCH 6/6] Specify all targets in availability annotations --- ...PICompatibilityAnyLanguageModelTests.swift | 2 +- ...PICompatibilityFoundationModelsTests.swift | 2 +- .../SystemLanguageModelTests.swift | 32 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift index 1cca521f..9d6b3f6c 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift @@ -4,7 +4,7 @@ import Testing import AnyLanguageModel private let isSystemLanguageModelAvailable: Bool = { - if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } return false diff --git a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift index 4bb2394c..cc4f69ce 100644 --- a/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift +++ b/Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift @@ -4,7 +4,7 @@ import Testing import FoundationModels private let isFoundationModelsSystemLanguageModelAvailable: Bool = { - if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } return false diff --git a/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift b/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift index 6d186df0..60dc133b 100644 --- a/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/SystemLanguageModelTests.swift @@ -3,7 +3,7 @@ import AnyLanguageModel #if canImport(FoundationModels) private let isSystemLanguageModelAvailable = { - if #available(macOS 26.0, iOS 26.0, visionOS 26.0, *) { + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) { return SystemLanguageModel.default.isAvailable } else { return false @@ -88,7 +88,7 @@ import AnyLanguageModel .enabled(if: isSystemLanguageModelAvailable) ) struct SystemLanguageModelTests { - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func basicResponse() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -97,7 +97,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func withInstructions() async throws { let model = SystemLanguageModel() let session = LanguageModelSession( @@ -109,7 +109,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func withTemperature() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -122,7 +122,7 @@ import AnyLanguageModel #expect(!response.content.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func streamingString() async throws { guard isSystemLanguageModelAvailable else { return } let model: SystemLanguageModel = SystemLanguageModel() @@ -139,7 +139,7 @@ import AnyLanguageModel #expect(!snapshots.last!.rawContent.jsonString.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func streamingGeneratedContent() async throws { guard isSystemLanguageModelAvailable else { return } let model: SystemLanguageModel = SystemLanguageModel() @@ -159,7 +159,7 @@ import AnyLanguageModel #expect(!snapshots.last!.rawContent.jsonString.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func withTools() async throws { let weatherTool = WeatherTool() let session = LanguageModelSession(model: SystemLanguageModel.default, tools: [weatherTool]) @@ -180,7 +180,7 @@ import AnyLanguageModel #expect(content.contains("72°F")) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func conversationContext() async throws { let model: SystemLanguageModel = SystemLanguageModel() let session = LanguageModelSession(model: model) @@ -222,7 +222,7 @@ import AnyLanguageModel // MARK: - Guided Generation Tests - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationSimpleStruct() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -234,7 +234,7 @@ import AnyLanguageModel #expect(!response.content.message.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithMultipleFields() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -248,7 +248,7 @@ import AnyLanguageModel #expect(!response.content.occupation.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationMathCalculation() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -263,7 +263,7 @@ import AnyLanguageModel #expect(combined.contains("15") || combined.contains("27") || combined.contains("42")) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationNestedStruct() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -279,7 +279,7 @@ import AnyLanguageModel #expect(response.content.rgb.blue >= 0 && response.content.rgb.blue <= 255) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithArray() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -295,7 +295,7 @@ import AnyLanguageModel } } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithEnumConstraint() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default) @@ -308,7 +308,7 @@ import AnyLanguageModel #expect(response.content.confidence >= 0.0 && response.content.confidence <= 1.0) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationWithInstructions() async throws { let session = LanguageModelSession( model: SystemLanguageModel.default, @@ -325,7 +325,7 @@ import AnyLanguageModel #expect(!response.content.occupation.isEmpty) } - @available(macOS 26.0, iOS 26.0, visionOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) @Test func guidedGenerationStreaming() async throws { let session = LanguageModelSession(model: SystemLanguageModel.default)