diff --git a/CHANGELOG.md b/CHANGELOG.md index 902971f..47672c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.2.2 + +### 🐛 Bug Fixes +- **Fixed Xcode 27 build failure** ("switch must be exhaustive") in the iOS and macOS plugins. The Xcode 27 SDK adds new cases to the non-frozen Foundation Models enums `Transcript.Entry` (`.reasoning`) and `Transcript.Segment` (`.attachment`, `.custom`), which broke the exhaustive `switch` statements in `serializeSegment` and `mapTranscriptEntries`. +- Added `@unknown default` clauses to all `switch` statements over non-frozen Apple framework enums (`Transcript.Entry`, `Transcript.Segment`, and `LanguageModelSession.GenerationError`) so the plugin keeps compiling as Apple adds enum cases in future SDKs. + +### ✨ Improvements +- **First-class handling of reasoning transcripts on Xcode 27+.** When built with a Swift 6.4+ toolchain (Xcode 27+), `.reasoning` transcript entries are serialized with a dedicated `reasoning` role and their segments are mapped just like other entries, and `.attachment`/`.custom` segments are serialized explicitly. This is gated behind `#if compiler(>=6.4)` so the plugin continues to build on Xcode 26 (where those cases do not exist), falling back to the `@unknown default` behavior there. + ## 0.2.1 ### 📚 Documentation Improvements diff --git a/ios/Classes/FoundationModelsFrameworkPlugin.swift b/ios/Classes/FoundationModelsFrameworkPlugin.swift index d0f4db8..30893fe 100644 --- a/ios/Classes/FoundationModelsFrameworkPlugin.swift +++ b/ios/Classes/FoundationModelsFrameworkPlugin.swift @@ -365,6 +365,21 @@ import AppKit role = "response" segmentsText = response.segments.map(serializeSegment) content = segmentsText.joined(separator: "\n") + #if compiler(>=6.4) + // `.reasoning` was added to `Transcript.Entry` in the Xcode 27 / iOS 26+ SDK. + // Gate it on the Swift 6.4+ toolchain (Xcode 27+) so this still builds on + // Xcode 26, where the case does not exist; older toolchains use `@unknown default`. + case .reasoning(let reasoning): + role = "reasoning" + segmentsText = reasoning.segments.map(serializeSegment) + content = segmentsText.joined(separator: "\n") + #endif + @unknown default: + // Handle any further entry kinds added in future SDKs without breaking the build. + role = "unknown" + let description = String(describing: entry) + segmentsText = [description] + content = description } return TranscriptEntry(id: entry.id, role: role, content: content, segments: segmentsText) @@ -378,6 +393,18 @@ import AppKit return textSegment.content case .structure(let structuredSegment): return String(describing: structuredSegment.content) + #if compiler(>=6.4) + // `.attachment` and `.custom` were added to `Transcript.Segment` in the + // Xcode 27 / iOS 26+ SDK. Gate them on the Swift 6.4+ toolchain (Xcode 27+) so + // this still builds on Xcode 26; older toolchains use `@unknown default`. + case .attachment(let attachmentSegment): + return String(describing: attachmentSegment) + case .custom(let customSegment): + return String(describing: customSegment) + #endif + @unknown default: + // Handle any further segment kinds added in future SDKs. + return String(describing: segment) } } @available(iOS 26.0, macOS 15.0, *) @@ -430,6 +457,9 @@ import AppKit return FoundationModelsError.requestFailed("Unsupported guide") case .unsupportedLanguageOrLocale(_): return FoundationModelsError.requestFailed("Unsupported language or locale") + @unknown default: + // Handle generation error cases added in newer SDKs without breaking the build. + return FoundationModelsError.requestFailed("Generation failed") } } diff --git a/macos/Classes/FoundationModelsFrameworkPlugin.swift b/macos/Classes/FoundationModelsFrameworkPlugin.swift index 4d369d6..790cd4d 100644 --- a/macos/Classes/FoundationModelsFrameworkPlugin.swift +++ b/macos/Classes/FoundationModelsFrameworkPlugin.swift @@ -365,6 +365,21 @@ import AppKit role = "response" segmentsText = response.segments.map(serializeSegment) content = segmentsText.joined(separator: "\n") + #if compiler(>=6.4) + // `.reasoning` was added to `Transcript.Entry` in the Xcode 27 / macOS 26+ SDK. + // Gate it on the Swift 6.4+ toolchain (Xcode 27+) so this still builds on + // Xcode 26, where the case does not exist; older toolchains use `@unknown default`. + case .reasoning(let reasoning): + role = "reasoning" + segmentsText = reasoning.segments.map(serializeSegment) + content = segmentsText.joined(separator: "\n") + #endif + @unknown default: + // Handle any further entry kinds added in future SDKs without breaking the build. + role = "unknown" + let description = String(describing: entry) + segmentsText = [description] + content = description } return TranscriptEntry(id: entry.id, role: role, content: content, segments: segmentsText) @@ -378,6 +393,18 @@ import AppKit return textSegment.content case .structure(let structuredSegment): return String(describing: structuredSegment.content) + #if compiler(>=6.4) + // `.attachment` and `.custom` were added to `Transcript.Segment` in the + // Xcode 27 / macOS 26+ SDK. Gate them on the Swift 6.4+ toolchain (Xcode 27+) so + // this still builds on Xcode 26; older toolchains use `@unknown default`. + case .attachment(let attachmentSegment): + return String(describing: attachmentSegment) + case .custom(let customSegment): + return String(describing: customSegment) + #endif + @unknown default: + // Handle any further segment kinds added in future SDKs. + return String(describing: segment) } } @available(iOS 26.0, macOS 26.0, *) @@ -430,6 +457,9 @@ import AppKit return FoundationModelsError.requestFailed("Unsupported guide") case .unsupportedLanguageOrLocale(_): return FoundationModelsError.requestFailed("Unsupported language or locale") + @unknown default: + // Handle generation error cases added in newer SDKs without breaking the build. + return FoundationModelsError.requestFailed("Generation failed") } } diff --git a/pubspec.yaml b/pubspec.yaml index ecc916d..00ac37d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: foundation_models_framework description: A Flutter package for integrating with Apple's Foundation Models framework on iOS and macOS devices. Provides session-based language model interactions with Apple Intelligence features. -version: 0.2.1 +version: 0.2.2 homepage: https://github.com/dmakwt/flutter_foundation_models_framework repository: https://github.com/dmakwt/flutter_foundation_models_framework issue_tracker: https://github.com/dmakwt/flutter_foundation_models_framework/issues