File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -110,6 +110,7 @@ extension OpenAIClient {
110110
111111 func extractDeltas( from chunk: StreamingChunk ) throws -> [ StreamDelta ] {
112112 var deltas : [ StreamDelta ] = [ ]
113+ var emittedFinished = false
113114 for choice in chunk. choices ?? [ ] {
114115 if let reasoning = choice. delta. reasoning ?? choice. delta. reasoningContent, !reasoning. isEmpty {
115116 deltas. append ( . reasoning( reasoning) )
@@ -121,8 +122,12 @@ extension OpenAIClient {
121122 try extractAudioDeltas ( from: choice. delta, into: & deltas)
122123 if choice. finishReason != nil {
123124 deltas. append ( . finished( usage: chunk. usage. map ( \. tokenUsage) ) )
125+ emittedFinished = true
124126 }
125127 }
128+ if !emittedFinished, let usage = chunk. usage {
129+ deltas. append ( . finished( usage: usage. tokenUsage) )
130+ }
126131 return deltas
127132 }
128133
Original file line number Diff line number Diff line change @@ -406,7 +406,7 @@ struct StreamingChunkParsingTests {
406406 }
407407
408408 @Test
409- func streamingChunkWithoutChoicesDecodesCleanly ( ) throws {
409+ func streamingChunkWithUsageOnlyEmitsFinished ( ) throws {
410410 let json = """
411411 {
412412 " usage " : {
@@ -419,9 +419,13 @@ struct StreamingChunkParsingTests {
419419 let chunk = try client. parseStreamingChunk ( Data ( json. utf8) )
420420 let deltas = try client. extractDeltas ( from: chunk)
421421
422- #expect( deltas. isEmpty)
423- #expect( chunk. usage? . promptTokens == 100 )
424- #expect( chunk. usage? . completionTokens == 50 )
422+ #expect( deltas. count == 1 )
423+ if case let . finished( usage) = deltas. first {
424+ #expect( usage? . input == 100 )
425+ #expect( usage? . output == 50 )
426+ } else {
427+ Issue . record ( " Expected .finished delta with usage " )
428+ }
425429 }
426430
427431 @Test
You can’t perform that action at this time.
0 commit comments