From 1c059740bac4b2647171e4454f60c6f69ade813d Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:34:27 -0700 Subject: [PATCH 01/11] Mark the multi-backend API as AnyLanguageModel extensions --- Sources/AnyLanguageModel/Availability.swift | 9 +++ Sources/AnyLanguageModel/LanguageModel.swift | 21 +++++++ .../LanguageModelSession.swift | 63 ++++++++++++++++++- Sources/AnyLanguageModel/Transcript.swift | 2 + 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/Sources/AnyLanguageModel/Availability.swift b/Sources/AnyLanguageModel/Availability.swift index eacaf786..f3e4516a 100644 --- a/Sources/AnyLanguageModel/Availability.swift +++ b/Sources/AnyLanguageModel/Availability.swift @@ -1,4 +1,13 @@ /// The availability status for a specific language model. +/// +/// This generic type replaces Foundation Models' `SystemLanguageModel.Availability` +/// so that each model can report its own reasons for being unavailable. +/// The cases have the same names, +/// so a `switch` over a model's `availability` works with both frameworks. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public enum Availability { /// The model is ready for making requests. case available diff --git a/Sources/AnyLanguageModel/LanguageModel.swift b/Sources/AnyLanguageModel/LanguageModel.swift index 082aa5f3..9a9039da 100644 --- a/Sources/AnyLanguageModel/LanguageModel.swift +++ b/Sources/AnyLanguageModel/LanguageModel.swift @@ -1,5 +1,20 @@ import Foundation +/// A type that generates responses for a language model session. +/// +/// Model providers conform to this protocol +/// so that a ``LanguageModelSession`` can use them. +/// A conforming type reports its availability, +/// generates complete and streamed responses, +/// and can define its own custom generation options. +/// +/// - Note: This API is exclusive to AnyLanguageModel. +/// On OS 26, a Foundation Models session always uses `SystemLanguageModel`; +/// this protocol is what lets a session use any provider. +/// Foundation Models 27 adds its own `LanguageModel` protocol +/// with different requirements, +/// so using this protocol means your code is no longer drop-in compatible +/// with the Foundation Models framework. public protocol LanguageModel: Sendable { associatedtype UnavailableReason @@ -100,6 +115,12 @@ extension LanguageModel { ) } + /// A Boolean value that indicates whether the model is ready for requests. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// Foundation Models provides `isAvailable` only on `SystemLanguageModel`. public var isAvailable: Bool { if case .available = availability { return true diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index f027b894..5d4c69fb 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -2,6 +2,10 @@ import Foundation import Observation /// Controls transcript retention when generation fails or is cancelled. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public struct TranscriptErrorHandlingPolicy: Sendable, Equatable { private let shouldRevert: Bool @@ -23,6 +27,10 @@ public final class LanguageModelSession: @unchecked Sendable { /// On failure, `nil` retains the prompt without committing streaming checkpoints. /// Streaming cancellation never commits the partial answer as a completed response, regardless /// of this policy. These defaults do not claim Foundation Models behavioral parity. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public var transcriptErrorHandlingPolicy: TranscriptErrorHandlingPolicy? { get { access(keyPath: \.transcriptErrorHandlingPolicy) @@ -54,17 +62,39 @@ public final class LanguageModelSession: @unchecked Sendable { @ObservationIgnored private let responseRelays = Locked<[UUID: Task]>([:]) /// Waits for transcript cleanup of all streaming relays registered when this call begins. - /// Relays started later are excluded. Cancelling this wait does not cancel generation. - /// Call after cancelling consumers and before persisting the transcript. This is an - /// AnyLanguageModel extension; nonstreaming operations must be awaited separately. + /// + /// Relays started later are excluded. + /// Cancelling this wait does not cancel generation. + /// Call after cancelling consumers and before persisting the transcript. + /// Nonstreaming operations must be awaited separately. /// Do not call from a tool executing within one of the included responses. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. nonisolated public func waitForResponseCompletion() async { let tasks = responseRelays.withLock { Array($0.values) } for task in tasks { await task.value } } private let model: any LanguageModel + + /// The tools that the model can call during the session. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// It's public so that language models outside this module + /// can read the session's tools. public let tools: [any Tool] + + /// The instructions for the session, if any. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// It's public so that language models outside this module + /// can read the session's instructions. public let instructions: Instructions? /// A delegate that observes and controls tool execution. @@ -77,6 +107,17 @@ public final class LanguageModelSession: @unchecked Sendable { /// with the Foundation Models framework. @ObservationIgnored public var toolExecutionDelegate: (any ToolExecutionDelegate)? + /// Creates a session with a model, tools, + /// and instructions that you build with a result builder. + /// + /// - Note: Unlike Foundation Models, + /// which defaults `model` to `SystemLanguageModel.default`, + /// AnyLanguageModel requires the `model` argument + /// and accepts any type that conforms to ``LanguageModel``. + /// Code that omits `model` doesn't compile with AnyLanguageModel; + /// pass `SystemLanguageModel.default` to use the system model. + /// Code that passes another model + /// is no longer drop-in compatible with the Foundation Models framework. public convenience init( model: any LanguageModel, tools: [any Tool] = [], @@ -85,6 +126,11 @@ public final class LanguageModelSession: @unchecked Sendable { try self.init(model: model, tools: tools, instructions: instructions()) } + /// Creates a session with a model, tools, and instructions as a string. + /// + /// - Note: Unlike Foundation Models, + /// AnyLanguageModel requires the `model` argument + /// and accepts any ``LanguageModel``. public convenience init( model: any LanguageModel, tools: [any Tool] = [], @@ -93,6 +139,11 @@ public final class LanguageModelSession: @unchecked Sendable { self.init(model: model, tools: tools, instructions: Instructions(instructions), transcript: Transcript()) } + /// Creates a session with a model, tools, and optional instructions. + /// + /// - Note: Unlike Foundation Models, + /// AnyLanguageModel requires the `model` argument + /// and accepts any ``LanguageModel``. public convenience init( model: any LanguageModel, tools: [any Tool] = [], @@ -101,6 +152,12 @@ public final class LanguageModelSession: @unchecked Sendable { self.init(model: model, tools: tools, instructions: instructions, transcript: Transcript()) } + /// Creates a session with a model and tools + /// that continues from an existing transcript. + /// + /// - Note: Unlike Foundation Models, + /// AnyLanguageModel requires the `model` argument + /// and accepts any ``LanguageModel``. public convenience init( model: any LanguageModel, tools: [any Tool] = [], diff --git a/Sources/AnyLanguageModel/Transcript.swift b/Sources/AnyLanguageModel/Transcript.swift index edd6c939..a201041d 100644 --- a/Sources/AnyLanguageModel/Transcript.swift +++ b/Sources/AnyLanguageModel/Transcript.swift @@ -376,6 +376,8 @@ public struct Transcript: Sendable, Equatable, Codable { /// should interpret or modify them. /// /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public var providerMetadata: [String: String]? public init( From c794f5887aa0af49caccde5c222f2cd4d150db28 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:35:20 -0700 Subject: [PATCH 02/11] Mark custom generation options as AnyLanguageModel extensions --- Sources/AnyLanguageModel/GenerationOptions.swift | 8 ++++++++ .../AnyLanguageModel/Models/AnthropicLanguageModel.swift | 3 +++ Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift | 3 +++ Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift | 3 +++ Sources/AnyLanguageModel/Models/MLXLanguageModel.swift | 5 +++-- Sources/AnyLanguageModel/Models/OllamaLanguageModel.swift | 3 +++ Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift | 3 +++ .../Models/OpenResponsesLanguageModel.swift | 3 +++ 8 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Sources/AnyLanguageModel/GenerationOptions.swift b/Sources/AnyLanguageModel/GenerationOptions.swift index f28ab57f..cd2352a9 100644 --- a/Sources/AnyLanguageModel/GenerationOptions.swift +++ b/Sources/AnyLanguageModel/GenerationOptions.swift @@ -138,6 +138,10 @@ public struct GenerationOptions: Sendable, Equatable { /// /// - Parameter modelType: The language model type to get or set custom options for. /// - Returns: The custom options for the specified model type, or `nil` if none are set. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public subscript( custom modelType: Model.Type ) -> Model.CustomGenerationOptions? { @@ -219,6 +223,10 @@ extension GenerationOptions { /// } /// } /// ``` +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public protocol CustomGenerationOptions: Equatable, Sendable {} extension Never: CustomGenerationOptions {} diff --git a/Sources/AnyLanguageModel/Models/AnthropicLanguageModel.swift b/Sources/AnyLanguageModel/Models/AnthropicLanguageModel.swift index 2f7dd7cc..a9ef9768 100644 --- a/Sources/AnyLanguageModel/Models/AnthropicLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/AnthropicLanguageModel.swift @@ -30,6 +30,9 @@ import OrderedCollections public struct AnthropicLanguageModel: LanguageModel { /// Custom generation options specific to Anthropic's Claude API. /// + /// Reached through `GenerationOptions[custom: AnthropicLanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Use this type to pass additional parameters that are not part of the /// standard ``GenerationOptions``, such as Anthropic-specific sampling /// parameters and metadata. diff --git a/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift b/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift index ba06a0c8..4b777db3 100644 --- a/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift @@ -16,6 +16,9 @@ public struct GeminiLanguageModel: LanguageModel { /// Custom generation options specific to Gemini models. /// + /// Reached through `GenerationOptions[custom: GeminiLanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Use this type to configure Gemini-specific features like thinking mode /// and server-side tools through ``GenerationOptions``. /// diff --git a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift index 68c5ea1d..636552fb 100644 --- a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift @@ -66,6 +66,9 @@ import Foundation /// Custom generation options specific to llama.cpp. /// + /// Reached through `GenerationOptions[custom: LlamaLanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Use this type to pass llama.cpp-specific sampling parameters that are /// not part of the standard ``GenerationOptions``. /// diff --git a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift index d911cb3f..1c4f18c1 100644 --- a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift @@ -201,8 +201,9 @@ import Foundation /// Configures MLX-specific generation behavior. /// - /// Set these values through ``GenerationOptions`` using - /// `GenerationOptions[custom: MLXLanguageModel.self]`. + /// Set these values through + /// `GenerationOptions[custom: MLXLanguageModel.self]`, + /// an AnyLanguageModel extension. public struct CustomGenerationOptions: AnyLanguageModel.CustomGenerationOptions, Codable { /// Configures KV-cache behavior for MLX generation. public struct KVCache: Codable, Equatable, Sendable { diff --git a/Sources/AnyLanguageModel/Models/OllamaLanguageModel.swift b/Sources/AnyLanguageModel/Models/OllamaLanguageModel.swift index 9a5fd206..27da52f8 100644 --- a/Sources/AnyLanguageModel/Models/OllamaLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OllamaLanguageModel.swift @@ -20,6 +20,9 @@ public struct OllamaLanguageModel: LanguageModel { /// Custom generation options specific to Ollama. /// + /// Reached through `GenerationOptions[custom: OllamaLanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Use this type to pass additional model parameters that are not part /// of the standard ``GenerationOptions``. /// diff --git a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift index ac297f9f..87175bcf 100644 --- a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift @@ -38,6 +38,9 @@ public struct OpenAILanguageModel: LanguageModel { /// Custom generation options specific to OpenAI-compatible APIs. /// + /// Reached through `GenerationOptions[custom: OpenAILanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Use this type to pass additional parameters that are not part of the /// standard ``GenerationOptions``, such as sampling parameters, penalties, /// and vendor-specific extensions. diff --git a/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift index 82dfb46a..b12d7cb1 100644 --- a/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift @@ -27,6 +27,9 @@ public struct OpenResponsesLanguageModel: LanguageModel { /// Custom generation options for Open Responses–compatible APIs. /// + /// Reached through `GenerationOptions[custom: OpenResponsesLanguageModel.self]`, + /// an AnyLanguageModel extension. + /// /// Includes Open Responses–specific fields such as ``toolChoice`` (including /// ``ToolChoice/allowedTools(tools:mode:)``), ``allowedTools``, and /// reasoning/text options. Use ``extraBody`` for parameters not yet modeled. From d23f937b26d31fdc994e0446374c920e5c311064 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:35:56 -0700 Subject: [PATCH 03/11] Mark image inputs as AnyLanguageModel extensions --- .../LanguageModelSession.swift | 40 +++++++++++++++++++ Sources/AnyLanguageModel/Transcript.swift | 38 ++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index 5d4c69fb..b0838376 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -866,6 +866,11 @@ extension LanguageModelSession { // MARK: - Image Convenience Methods extension LanguageModelSession { + /// Produces a text response to a prompt and an image. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. @discardableResult nonisolated public func respond( to prompt: String, @@ -879,6 +884,11 @@ extension LanguageModelSession { ) } + /// Produces a text response to a prompt and images. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. @discardableResult nonisolated public func respond( to prompt: String, @@ -894,6 +904,11 @@ extension LanguageModelSession { ) } + /// Produces a response of the specified type to a prompt and an image. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. @discardableResult nonisolated public func respond( to prompt: String, @@ -911,6 +926,11 @@ extension LanguageModelSession { ) } + /// Produces a response of the specified type to a prompt and images. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. @discardableResult nonisolated public func respond( to prompt: String, @@ -981,6 +1001,11 @@ extension LanguageModelSession { } } + /// Streams a text response to a prompt and an image. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public func streamResponse( to prompt: String, image: Transcript.ImageSegment, @@ -993,6 +1018,11 @@ extension LanguageModelSession { ) } + /// Streams a text response to a prompt and images. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public func streamResponse( to prompt: String, images: [Transcript.ImageSegment], @@ -1007,6 +1037,11 @@ extension LanguageModelSession { ) } + /// Streams a response of the specified type to a prompt and an image. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. nonisolated public func streamResponse( to prompt: String, image: Transcript.ImageSegment, @@ -1023,6 +1058,11 @@ extension LanguageModelSession { ) } + /// Streams a response of the specified type to a prompt and images. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. nonisolated public func streamResponse( to prompt: String, images: [Transcript.ImageSegment], diff --git a/Sources/AnyLanguageModel/Transcript.swift b/Sources/AnyLanguageModel/Transcript.swift index a201041d..cfe18bc6 100644 --- a/Sources/AnyLanguageModel/Transcript.swift +++ b/Sources/AnyLanguageModel/Transcript.swift @@ -65,6 +65,12 @@ public struct Transcript: Sendable, Equatable, Codable { case structure(StructuredSegment) /// A segment containing an image. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// Foundation Models 27 adds prompt attachments, + /// so this API will change to match them in AnyLanguageModel 2.0. case image(ImageSegment) /// The stable identity of the entity associated with this instance. @@ -116,6 +122,12 @@ public struct Transcript: Sendable, Equatable, Codable { /// Use this type to include images alongside text and structured content when /// constructing `Transcript` entries. Images can be provided as raw data with a /// MIME type or by URL. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// Foundation Models 27 adds prompt attachments, + /// so this API will change to match them in AnyLanguageModel 2.0. public struct ImageSegment: Sendable, Identifiable, Equatable, Codable { /// The stable identity of the entity associated with this instance. public var id: String @@ -124,6 +136,10 @@ public struct Transcript: Sendable, Equatable, Codable { public let source: Source /// The origin of an image's content. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public enum Source: Sendable, Equatable, Codable { /// Image bytes and their MIME type (for example, `image/jpeg`). case data(Data, mimeType: String) @@ -197,6 +213,12 @@ public struct Transcript: Sendable, Equatable, Codable { } /// Errors that can occur when converting platform images to encoded data. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// Foundation Models 27 adds prompt attachments, + /// so this API will change to match them in AnyLanguageModel 2.0. public enum ImageEncodingError: Error { /// The image couldn't be converted to the requested format. case imageConversionFailed @@ -514,6 +536,10 @@ extension Transcript.StructuredSegment: CustomStringConvertible { extension Transcript.ImageSegment { /// Preferred image encodings for image conversion. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public enum Format: Sendable { /// JPEG encoding with the specified compression quality. case jpeg(compressionQuality: Double = 0.9) @@ -547,6 +573,10 @@ extension Transcript.ImageSegment { /// - image: The source image to encode. /// - format: The target encoding. Defaults to JPEG with 0.9 quality. /// - Throws: ``Transcript/ImageEncodingError-swift.enum/imageConversionFailed`` if encoding fails. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public init(image: UIImage, format: Format = .jpeg()) throws { let (data, mimeType) = try Self.encode(image, format: format) self.init(data: data, mimeType: mimeType) @@ -593,6 +623,10 @@ extension Transcript.ImageSegment { /// - image: The source image to encode. /// - format: The target encoding. Defaults to JPEG with 0.9 quality. /// - Throws: ``Transcript/ImageEncodingError-swift.enum/imageConversionFailed`` if encoding fails. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public init(image: NSImage, format: Format = .jpeg()) throws { let (data, mimeType) = try Self.encode(image, format: format) self.init(data: data, mimeType: mimeType) @@ -649,6 +683,10 @@ extension Transcript.ImageSegment { /// - image: The source image to encode. /// - format: The target encoding. Defaults to JPEG with 0.9 quality. /// - Throws: ``Transcript/ImageEncodingError-swift.enum/imageConversionFailed`` if encoding fails. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and will change to match Foundation Models 27 prompt attachments + /// in AnyLanguageModel 2.0. public init(image: CGImage, format: Format = .jpeg()) throws { let (data, mimeType) = try Self.encode(image, format: format) self.init(data: data, mimeType: mimeType) From 6ce109f3fa1fab155459f7d4a7eb1f453bb6e83c Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:36:35 -0700 Subject: [PATCH 04/11] Note AnyLanguageModel's additional Codable conformances --- Sources/AnyLanguageModel/GeneratedContent.swift | 8 ++++++++ Sources/AnyLanguageModel/GenerationID.swift | 4 ++++ Sources/AnyLanguageModel/LanguageModelSession.swift | 6 ++++++ Sources/AnyLanguageModel/Transcript.swift | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/Sources/AnyLanguageModel/GeneratedContent.swift b/Sources/AnyLanguageModel/GeneratedContent.swift index 7b8cc15b..a6904dca 100644 --- a/Sources/AnyLanguageModel/GeneratedContent.swift +++ b/Sources/AnyLanguageModel/GeneratedContent.swift @@ -4,6 +4,10 @@ import CoreFoundation /// A type that represents structured, generated content. /// /// Generated content may contain a single value, an array, or key-value pairs with unique keys. +/// +/// - Note: The `Codable` conformance is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public struct GeneratedContent: Sendable, Equatable, Generable, CustomDebugStringConvertible, Codable { /// An instance of the generation schema. public static var generationSchema: GenerationSchema { @@ -338,6 +342,10 @@ extension GeneratedContent { /// /// `Kind` represents the various types of JSON-compatible data that can be held within /// a `GeneratedContent` instance, including primitive types, arrays, and structured objects. + /// + /// - Note: The `Codable` conformance is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public enum Kind: Equatable, Sendable { /// Represents a null value. diff --git a/Sources/AnyLanguageModel/GenerationID.swift b/Sources/AnyLanguageModel/GenerationID.swift index 08816b26..0d537bd9 100644 --- a/Sources/AnyLanguageModel/GenerationID.swift +++ b/Sources/AnyLanguageModel/GenerationID.swift @@ -41,6 +41,10 @@ import struct Foundation.UUID /// } /// } /// ``` +/// +/// - Note: The `Codable` conformance is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public struct GenerationID: Sendable, Hashable, Codable { private let uuid: UUID diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index b0838376..ac4aac89 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -352,6 +352,12 @@ public final class LanguageModelSession: @unchecked Sendable { /// Matches the token-usage API in Foundation Models 27. /// Counts default to zero when the provider does not report them. /// Usage is cumulative across the response's tool rounds. + /// + /// - Note: This API is exclusive to AnyLanguageModel on OS 26. + /// It follows the Foundation Models 27 `Usage` API, + /// so code that uses it ports to Foundation Models on OS 27. + /// The `Codable` and `Equatable` conformances are exclusive to AnyLanguageModel; + /// Foundation Models 27 doesn't provide them. public struct Usage: Sendable, Equatable, Codable { /// Token counts for the input submitted to the model. public struct Input: Sendable, Equatable, Codable { diff --git a/Sources/AnyLanguageModel/Transcript.swift b/Sources/AnyLanguageModel/Transcript.swift index cfe18bc6..33b7ad79 100644 --- a/Sources/AnyLanguageModel/Transcript.swift +++ b/Sources/AnyLanguageModel/Transcript.swift @@ -1,6 +1,13 @@ import Foundation /// A type that represents a conversation history between a user and a language model. +/// +/// - Note: Foundation Models makes only `Transcript` and `GenerationSchema` `Codable`. +/// The `Codable` conformances of the nested transcript types, +/// such as ``Transcript/Entry`` and ``Transcript/Segment``, +/// are exclusive to AnyLanguageModel, +/// and using them means your code is no longer drop-in compatible +/// with the Foundation Models framework. public struct Transcript: Sendable, Equatable, Codable { private var entries: [Entry] From 53430cc8c805f7836e033761cfde3436aa2820e6 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:37:48 -0700 Subject: [PATCH 05/11] Note public initializers that Foundation Models keeps private --- .../AnyLanguageModel/GenerationGuide.swift | 5 ++++ .../LanguageModelFeedback.swift | 10 +++++++ .../LanguageModelSession.swift | 27 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/Sources/AnyLanguageModel/GenerationGuide.swift b/Sources/AnyLanguageModel/GenerationGuide.swift index d2a67402..84a4b782 100644 --- a/Sources/AnyLanguageModel/GenerationGuide.swift +++ b/Sources/AnyLanguageModel/GenerationGuide.swift @@ -8,6 +8,11 @@ public struct GenerationGuide: Sendable { var minimum: Double? var maximum: Double? + /// Creates a guide with no constraints. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public for language models outside this module; + /// Foundation Models doesn't make it public. public init() {} init(minimumCount: Int?, maximumCount: Int?) { diff --git a/Sources/AnyLanguageModel/LanguageModelFeedback.swift b/Sources/AnyLanguageModel/LanguageModelFeedback.swift index f1b9fd10..f3c8c956 100644 --- a/Sources/AnyLanguageModel/LanguageModelFeedback.swift +++ b/Sources/AnyLanguageModel/LanguageModelFeedback.swift @@ -1,3 +1,8 @@ +/// Feedback about a model's response. +/// +/// - Note: The ``sentiment`` and ``issues`` properties are exclusive to AnyLanguageModel. +/// They're public for language models outside this module; +/// Foundation Models doesn't make them public. public struct LanguageModelFeedback { /// A sentiment regarding the model's response. public enum Sentiment: Sendable, CaseIterable, Equatable, Hashable { @@ -92,6 +97,11 @@ public struct LanguageModelFeedback { /// - Parameters: /// - sentiment: A sentiment for the model's response. /// - issues: Issues with the model's response. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public so that language models outside this module + /// can create feedback; + /// Foundation Models doesn't make it public. public init(sentiment: Sentiment, issues: [Issue]) { self.sentiment = sentiment self.issues = issues diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index ac4aac89..9cf082c1 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -491,6 +491,11 @@ public final class LanguageModelSession: @unchecked Sendable { /// - rawContent: The raw content produced by the model. /// - transcriptEntries: Transcript entries associated with the response. /// - usage: Provider-reported token usage. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public so that language models outside this module + /// can create responses; + /// Foundation Models doesn't make it public. public init( content: Content, rawContent: GeneratedContent, @@ -1142,6 +1147,13 @@ extension LanguageModelSession { } public struct Refusal: Sendable { + /// The transcript entries associated with the refusal. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// Foundation Models takes transcript entries in the initializer + /// but doesn't make this property public. public let transcriptEntries: [Transcript.Entry] public init(transcriptEntries: [Transcript.Entry]) { @@ -1231,6 +1243,11 @@ extension LanguageModelSession { /// - content: The complete response content. /// - rawContent: The raw content produced by the model. /// - usage: Provider-reported token usage. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public so that language models outside this module + /// can create response streams; + /// Foundation Models doesn't make it public. public init( content: Content, rawContent: GeneratedContent, @@ -1249,6 +1266,11 @@ extension LanguageModelSession { /// Creates a response stream that yields snapshots from an async stream. /// - Parameter stream: The snapshot stream to relay. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public so that language models outside this module + /// can create response streams; + /// Foundation Models doesn't make it public. public init(stream: AsyncThrowingStream) { // When streaming, snapshots arrive from the upstream sequence, so no fallback is required. self.fallbackSnapshot = nil @@ -1280,6 +1302,11 @@ extension LanguageModelSession { /// - rawContent: The raw content produced by the model. /// - transcriptEntries: Transcript entries accumulated so far (tool calls/outputs). /// - usage: Provider-reported token usage so far. + /// + /// - Note: This initializer is exclusive to AnyLanguageModel. + /// It's public so that language models outside this module + /// can create snapshots; + /// Foundation Models doesn't make it public. public init( content: Content.PartiallyGenerated, rawContent: GeneratedContent, From 1488ebfe45941993691a24090617f476322ece16 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:38:19 -0700 Subject: [PATCH 06/11] Mark AnyLanguageModel error types as extensions --- Sources/AnyLanguageModel/GeneratedContent.swift | 5 +++++ Sources/AnyLanguageModel/Models/CoreMLLanguageModel.swift | 4 ++++ Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift | 4 ++++ Sources/AnyLanguageModel/Models/MLXLanguageModel.swift | 4 ++++ Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift | 4 ++++ .../AnyLanguageModel/Models/OpenResponsesLanguageModel.swift | 4 ++++ 6 files changed, 25 insertions(+) diff --git a/Sources/AnyLanguageModel/GeneratedContent.swift b/Sources/AnyLanguageModel/GeneratedContent.swift index a6904dca..0f386c7d 100644 --- a/Sources/AnyLanguageModel/GeneratedContent.swift +++ b/Sources/AnyLanguageModel/GeneratedContent.swift @@ -401,6 +401,11 @@ extension GeneratedContent { // MARK: - GeneratedContentError +/// Errors that can occur when converting generated content to a value. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public enum GeneratedContentError: Error, Hashable { case propertyNotFound(String) case typeMismatch diff --git a/Sources/AnyLanguageModel/Models/CoreMLLanguageModel.swift b/Sources/AnyLanguageModel/Models/CoreMLLanguageModel.swift index 05c3aebd..3aa74e2d 100644 --- a/Sources/AnyLanguageModel/Models/CoreMLLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/CoreMLLanguageModel.swift @@ -315,6 +315,10 @@ } /// Errors that can occur when working with Core ML language models. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. @available(macOS 15.0, iOS 18.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) public enum CoreMLLanguageModelError: LocalizedError { /// The provided model isn't a compiled Core ML model. diff --git a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift index 636552fb..08269e40 100644 --- a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift @@ -2605,6 +2605,10 @@ import Foundation } /// Errors that can occur when using LlamaLanguageModel + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public enum LlamaLanguageModelError: Error, LocalizedError { case modelLoadFailed case contextInitializationFailed diff --git a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift index 1c4f18c1..dbc58c99 100644 --- a/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/MLXLanguageModel.swift @@ -2041,6 +2041,10 @@ import Foundation // MARK: - Structured JSON Generation /// Errors that can occur when using MLXLanguageModel. + /// + /// - Note: This API is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. public enum MLXLanguageModelError: Error, LocalizedError { case invalidVocabSize case unsupportedJSONValueType diff --git a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift index 87175bcf..38cde097 100644 --- a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift @@ -2012,6 +2012,10 @@ private func extractToolCallsFromOutput(_ output: [JSONValue]?) -> [OpenAIToolCa // MARK: - Errors /// Errors that can occur when using ``OpenAILanguageModel``. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public enum OpenAILanguageModelError: LocalizedError { /// The response contained no output to use. /// diff --git a/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift index b12d7cb1..7742e866 100644 --- a/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenResponsesLanguageModel.swift @@ -1243,6 +1243,10 @@ private enum OpenResponsesStreamEvent: Decodable, Sendable { // MARK: - Errors /// Errors that can occur when using ``OpenResponsesLanguageModel``. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public enum OpenResponsesLanguageModelError: LocalizedError, Sendable { /// The response contained no output to use. /// From f112a5f8ac4566debeb08608715a12ade897ab9e Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:38:43 -0700 Subject: [PATCH 07/11] Note APIs that follow Foundation Models 27 --- .../AnyLanguageModel/LanguageModelSession.swift | 16 ++++++++++++++++ .../Models/SystemLanguageModel.swift | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index 9cf082c1..5fa32c09 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -52,6 +52,10 @@ public final class LanguageModelSession: @unchecked Sendable { /// /// Counts increase as responses and streaming snapshots report usage. /// Restoring a transcript does not restore usage from previous sessions. + /// + /// - Note: This property is exclusive to AnyLanguageModel on OS 26. + /// It follows the Foundation Models 27 `LanguageModelSession.usage` API, + /// so code that uses it ports to Foundation Models on OS 27. public var usage: Usage { access(keyPath: \.usage) return state.withLock { $0.usage } @@ -481,6 +485,10 @@ public final class LanguageModelSession: @unchecked Sendable { /// Provider-reported token usage, /// with zero counts for values the provider does not report. + /// + /// - Note: This property is exclusive to AnyLanguageModel on OS 26. + /// It follows the Foundation Models 27 `Response.usage` API, + /// so code that uses it ports to Foundation Models on OS 27. public let usage: Usage internal let providerMetadata: [String: String]? @@ -1288,10 +1296,18 @@ extension LanguageModelSession { /// Transcript entries (tool calls and outputs) produced so far while streaming. /// Cumulative across tool rounds; /// empty for providers that don't stream tool activity. + /// + /// - Note: This property is exclusive to AnyLanguageModel on OS 26. + /// It follows the Foundation Models 27 `ResponseStream.Snapshot.transcriptEntries` API, + /// so code that uses it ports to Foundation Models on OS 27. public var transcriptEntries: ArraySlice /// Provider-reported counts so far, /// with zero counts for values the provider does not report. + /// + /// - Note: This property is exclusive to AnyLanguageModel on OS 26. + /// It follows the Foundation Models 27 `ResponseStream.Snapshot.usage` API, + /// so code that uses it ports to Foundation Models on OS 27. public var usage: Usage internal var providerMetadata: [String: String]? diff --git a/Sources/AnyLanguageModel/Models/SystemLanguageModel.swift b/Sources/AnyLanguageModel/Models/SystemLanguageModel.swift index d4f10119..1b60f349 100644 --- a/Sources/AnyLanguageModel/Models/SystemLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/SystemLanguageModel.swift @@ -64,6 +64,11 @@ #endif /// Whether the model accepts image input. + /// + /// - Note: This property is exclusive to AnyLanguageModel + /// and using it means your code is no longer drop-in compatible + /// with the Foundation Models framework. + /// In Foundation Models 27, check whether `capabilities` contains `.vision` instead. public var supportsImageInput: Bool { #if compiler(>=6.4) && !os(tvOS) && !os(watchOS) if #available(macOS 27.0, iOS 27.0, visionOS 27.0, *) { From dcb69072f9578c24199dcfa0be3a4563884f970d Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:41:51 -0700 Subject: [PATCH 08/11] Pass a model in the GenerationID example --- Sources/AnyLanguageModel/GenerationID.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/AnyLanguageModel/GenerationID.swift b/Sources/AnyLanguageModel/GenerationID.swift index 0d537bd9..80d95c8e 100644 --- a/Sources/AnyLanguageModel/GenerationID.swift +++ b/Sources/AnyLanguageModel/GenerationID.swift @@ -13,7 +13,7 @@ import struct Foundation.UUID /// } /// /// struct PeopleView: View { -/// @State private var session = LanguageModelSession() +/// @State private var session = LanguageModelSession(model: SystemLanguageModel.default) /// @State private var people = [Person.PartiallyGenerated]() /// /// var body: some View { From e4705b75f5ca26215655c546e0148c573ff86855 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 05:41:52 -0700 Subject: [PATCH 09/11] Document differences from Foundation Models in the README --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/README.md b/README.md index d153b838..846356ab 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ All you need to do is change your import statement: + import AnyLanguageModel ``` +Anything AnyLanguageModel adds beyond Apple's API +is marked as an extension in its documentation +and listed in [Differences from Foundation Models](#differences-from-foundation-models), +along with the few Foundation Models APIs it doesn't implement yet. + ```swift struct WeatherTool: Tool { let name = "getWeather" @@ -373,6 +378,10 @@ use a vision-capable model For llama.cpp, pass the model's multimodal projector with `mmprojPath:`. +> [!NOTE] +> Image inputs are an AnyLanguageModel extension. +> See [Differences from Foundation Models](#differences-from-foundation-models). + ### Tool Calling Tool calling is supported by all providers. @@ -432,6 +441,10 @@ actor ToolExecutionObserver: ToolExecutionDelegate { session.toolExecutionDelegate = ToolExecutionObserver() ``` +> [!NOTE] +> Tool execution delegates are an AnyLanguageModel extension. +> See [Differences from Foundation Models](#differences-from-foundation-models). + ### Token Usage Inspect token counts with `response.usage` @@ -492,6 +505,61 @@ the latest value is kept for each metadata key. > [Foundation Models 27 usage API](https://developer.apple.com/documentation/foundationmodels/languagemodelsession/usage-swift.struct). > `Codable` and `Equatable` support are AnyLanguageModel extensions. +## Differences from Foundation Models + +Code that uses an extension compiles only with AnyLanguageModel. +Each extension's documentation comment says so. + +### Extensions + +- `LanguageModel` and `Availability`: + the protocol that lets a session use any model provider. + Foundation Models 27 adds its own `LanguageModel` protocol + with different requirements. + Session initializers require a `model:` argument + instead of defaulting to `SystemLanguageModel.default`. +- `GenerationOptions[custom:]` and `CustomGenerationOptions`: + options for one provider, + described in that provider's section under [Providers](#providers). +- `respond(to:images:)`, `Transcript.ImageSegment`, and `Transcript.Segment.image`: + [image inputs](#image-inputs). + Foundation Models 27 adds prompt attachments, + and AnyLanguageModel 2.0 will change to match them. +- `ToolExecutionDelegate`, `ToolExecutionDecision`, and `toolExecutionDelegate`: + [observing and controlling tool calls](#tool-calling). +- `transcriptErrorHandlingPolicy` and `waitForResponseCompletion()`: + what a transcript keeps when a request fails or is cancelled. +- `LanguageModelSession.tools` and `instructions`: + the session's tools and instructions, + for language models defined outside AnyLanguageModel. +- `Usage` and the `usage` properties: + [token usage](#token-usage), + which follows the Foundation Models 27 API. +- Public initializers for `Response`, `ResponseStream`, `ResponseStream.Snapshot`, + `GenerationGuide`, and `LanguageModelFeedback`, + for language models defined outside AnyLanguageModel. +- `Codable` conformance for `GeneratedContent`, `GenerationID`, `Usage`, + and the types nested in `Transcript`. +- `GeneratedContentError` and each provider's error type. + +### Behavior differences + +- A session adds the prompt to its transcript before the model responds, + as a single text segment. +- A structured response is recorded in the transcript as JSON text, + not as a structured segment. +- A session created from a transcript restores `instructions` + only when the first entry is instructions with a single text segment. + +### Not yet implemented + +- `@Generable(description:representNilExplicitlyInGeneratedContent:)` + and the matching `GenerationSchema` and `DynamicGenerationSchema` initializers +- `DynamicGenerationSchema.null` +- `logFeedbackAttachment(sentiment:issues:desiredResponseText:)` + and `logFeedbackAttachment(sentiment:issues:desiredResponseContent:)` +- `SystemLanguageModel.supportedLanguages`, `supportsLocale(_:)`, and `tokenCount(for:)` + ## Providers ### Apple Foundation Models From bb9ed8b16957504bb9b1a73de30a84363e0d92d5 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 08:59:18 -0700 Subject: [PATCH 10/11] Describe the README's extension list as a summary --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 846356ab..5a12ebda 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,10 @@ All you need to do is change your import statement: ``` Anything AnyLanguageModel adds beyond Apple's API -is marked as an extension in its documentation -and listed in [Differences from Foundation Models](#differences-from-foundation-models), -along with the few Foundation Models APIs it doesn't implement yet. +is marked as an extension in its documentation. +[Differences from Foundation Models](#differences-from-foundation-models) +summarizes these extensions +and lists the few Foundation Models APIs it doesn't implement yet. ```swift struct WeatherTool: Tool { @@ -507,8 +508,11 @@ the latest value is kept for each metadata key. ## Differences from Foundation Models -Code that uses an extension compiles only with AnyLanguageModel. -Each extension's documentation comment says so. +Code that uses an extension doesn't compile with Foundation Models on OS 26. +Each extension's documentation comment says so, +and extensions that follow a Foundation Models 27 API, +such as token usage, +say which API they follow. ### Extensions @@ -541,6 +545,11 @@ Each extension's documentation comment says so. - `Codable` conformance for `GeneratedContent`, `GenerationID`, `Usage`, and the types nested in `Transcript`. - `GeneratedContentError` and each provider's error type. +- `JSONValue`: + JSON values for provider options such as `extraBody`. +- Smaller additions to existing types, + such as `LanguageModel.isAvailable`, `SystemLanguageModel.supportsImageInput`, + `Transcript.ToolCall.providerMetadata`, and `GenerationError.Refusal.transcriptEntries`. ### Behavior differences From 838ef5ff42095b455a6f5eead985b480fbf1a2e2 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 2 Oct 2026 09:34:11 -0700 Subject: [PATCH 11/11] Mark JSONValue as an AnyLanguageModel extension --- Sources/AnyLanguageModel/Shared/JSONValue.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/AnyLanguageModel/Shared/JSONValue.swift b/Sources/AnyLanguageModel/Shared/JSONValue.swift index 5d3c3156..7a1cf8e9 100644 --- a/Sources/AnyLanguageModel/Shared/JSONValue.swift +++ b/Sources/AnyLanguageModel/Shared/JSONValue.swift @@ -1,4 +1,8 @@ import enum JSONSchema.JSONValue /// A type-safe representation of JSON values used by AnyLanguageModel APIs. +/// +/// - Note: This API is exclusive to AnyLanguageModel +/// and using it means your code is no longer drop-in compatible +/// with the Foundation Models framework. public typealias JSONValue = JSONSchema.JSONValue