diff --git a/Sources/AnyLanguageModel/LanguageModelSession.swift b/Sources/AnyLanguageModel/LanguageModelSession.swift index 50ea2ec3..f5bba577 100644 --- a/Sources/AnyLanguageModel/LanguageModelSession.swift +++ b/Sources/AnyLanguageModel/LanguageModelSession.swift @@ -739,8 +739,22 @@ extension LanguageModelSession { init(stream: AsyncThrowingStream) { // Fallback values when consumers call collect() before any snapshots arrive // These will be replaced by the last yielded snapshot during collect() - self.content = (try? Content(GeneratedContent(""))) ?? ("" as! Content) - self.rawContent = GeneratedContent("") + if Content.self == String.self { + self.content = "" as! Content + self.rawContent = GeneratedContent("") + } else { + // For structured types, create from empty properties dictionary + // We need to create an instance that can call asPartiallyGenerated() without crashing + let emptyContent = GeneratedContent(properties: [:]) + if let instance = try? Content(emptyContent) { + self.content = instance + } else { + // Fallback: try with an empty string content + let fallbackContent = GeneratedContent("") + self.content = (try? Content(fallbackContent)) ?? ("" as! Content) + } + self.rawContent = emptyContent + } self.streaming = stream } diff --git a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift index e86a6065..80756425 100644 --- a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift @@ -344,21 +344,18 @@ public struct OpenAILanguageModel: LanguageModel { raw = GeneratedContent(accumulatedText) content = (accumulatedText as! Content).asPartiallyGenerated() } else { - // Try to parse as JSON, falling back to string if incomplete - raw = - (try? GeneratedContent(json: accumulatedText)) - ?? GeneratedContent(accumulatedText) - if let parsed = try? type.init(raw) { - content = parsed.asPartiallyGenerated() + // Try to parse as JSON for structured types + if let jsonContent = try? GeneratedContent(json: accumulatedText), + let _ = try? type.init(jsonContent) { + // Successfully parsed JSON into the structured type + raw = jsonContent + // Create PartiallyGenerated from the raw content + content = try? Content.PartiallyGenerated(jsonContent) } else { - // Fallback: try to create from empty properties, or skip this chunk - if let emptyParsed = try? type.init(GeneratedContent(properties: [:])) { - content = emptyParsed.asPartiallyGenerated() - } else { - // Last resort: skip this chunk - raw = GeneratedContent(accumulatedText) - content = nil - } + // Can't parse yet, try with empty content as placeholder + let emptyContent = GeneratedContent(properties: [:]) + raw = emptyContent + content = try? Content.PartiallyGenerated(emptyContent) } } @@ -435,21 +432,18 @@ public struct OpenAILanguageModel: LanguageModel { raw = GeneratedContent(accumulatedText) content = (accumulatedText as! Content).asPartiallyGenerated() } else { - // Try to parse as JSON, falling back to string if incomplete - raw = - (try? GeneratedContent(json: accumulatedText)) - ?? GeneratedContent(accumulatedText) - if let parsed = try? type.init(raw) { - content = parsed.asPartiallyGenerated() + // Try to parse as JSON for structured types + if let jsonContent = try? GeneratedContent(json: accumulatedText), + let _ = try? type.init(jsonContent) { + // Successfully parsed JSON into the structured type + raw = jsonContent + // Create PartiallyGenerated from the raw content + content = try? Content.PartiallyGenerated(jsonContent) } else { - // Fallback: try to create from empty properties, or use string fallback - if let emptyParsed = try? type.init(GeneratedContent(properties: [:])) { - content = emptyParsed.asPartiallyGenerated() - } else { - // Last resort: skip this chunk - raw = GeneratedContent(accumulatedText) - content = nil - } + // Can't parse yet, try with empty content as placeholder + let emptyContent = GeneratedContent(properties: [:]) + raw = emptyContent + content = try? Content.PartiallyGenerated(emptyContent) } }