From 80e916097b36281b68ab579e9e08cb39519bd472 Mon Sep 17 00:00:00 2001 From: Pallav Agarwal Date: Fri, 13 Oct 2023 00:26:22 -0400 Subject: [PATCH] Correctly handle partial JSON at the end of the chunk --- Sources/OpenAI/Private/StreamingSession.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Sources/OpenAI/Private/StreamingSession.swift b/Sources/OpenAI/Private/StreamingSession.swift index 55902f09..e2d52e57 100644 --- a/Sources/OpenAI/Private/StreamingSession.swift +++ b/Sources/OpenAI/Private/StreamingSession.swift @@ -28,6 +28,8 @@ final class StreamingSession: NSObject, Identifiable, URLSe return session }() + private var prevChunkBuffer = "" + init(urlRequest: URLRequest) { self.urlRequest = urlRequest } @@ -47,14 +49,16 @@ final class StreamingSession: NSObject, Identifiable, URLSe onProcessingError?(self, StreamingError.unknownContent) return } - let jsonObjects = stringContent + let jsonObjects = "\(prevChunkBuffer)\(stringContent)" .components(separatedBy: "data:") .filter { $0.isEmpty == false } .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + prevChunkBuffer = "" + guard jsonObjects.isEmpty == false, jsonObjects.first != streamingCompletionMarker else { return } - jsonObjects.forEach { jsonContent in + jsonObjects.enumerated().forEach { (index, jsonContent) in guard jsonContent != streamingCompletionMarker else { return } @@ -77,7 +81,12 @@ final class StreamingSession: NSObject, Identifiable, URLSe let decoded = try JSONDecoder().decode(APIErrorResponse.self, from: jsonData) onProcessingError?(self, decoded) } catch { - onProcessingError?(self, apiError) + if index == jsonObjects.count - 1 { + // Chunk ends in a partial JSON + prevChunkBuffer = "data: \(jsonContent)" + } else { + onProcessingError?(self, apiError) + } } } }