@@ -812,6 +812,92 @@ describe('doStream', () => {
812
812
expect ( reasoningDeltas ) . not . toContain ( 'Also ignored' ) ;
813
813
} ) ;
814
814
815
+ it ( 'should maintain correct reasoning order when content comes after reasoning (issue #7824)' , async ( ) => {
816
+ // This test reproduces the issue where reasoning appears first but then gets "pushed down"
817
+ // by content that comes later in the stream
818
+ server . urls [ 'https://openrouter.ai/api/v1/chat/completions' ] ! . response = {
819
+ type : 'stream-chunks' ,
820
+ chunks : [
821
+ // First chunk: Start with reasoning
822
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
823
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{"role":"assistant",` +
824
+ `"reasoning":"I need to think about this step by step..."},` +
825
+ `"logprobs":null,"finish_reason":null}]}\n\n` ,
826
+ // Second chunk: More reasoning
827
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
828
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{` +
829
+ `"reasoning":" First, I should analyze the request."},` +
830
+ `"logprobs":null,"finish_reason":null}]}\n\n` ,
831
+ // Third chunk: Even more reasoning
832
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
833
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{` +
834
+ `"reasoning":" Then I should provide a helpful response."},` +
835
+ `"logprobs":null,"finish_reason":null}]}\n\n` ,
836
+ // Fourth chunk: Content starts
837
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
838
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{"content":"Hello! "},` +
839
+ `"logprobs":null,"finish_reason":null}]}\n\n` ,
840
+ // Fifth chunk: More content
841
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
842
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{"content":"How can I help you today?"},` +
843
+ `"logprobs":null,"finish_reason":null}]}\n\n` ,
844
+ // Finish chunk
845
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
846
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[{"index":0,"delta":{},` +
847
+ `"logprobs":null,"finish_reason":"stop"}]}\n\n` ,
848
+ `data: {"id":"chatcmpl-order-test","object":"chat.completion.chunk","created":1711357598,"model":"gpt-3.5-turbo-0125",` +
849
+ `"system_fingerprint":"fp_3bc1b5746c","choices":[],"usage":{"prompt_tokens":17,"completion_tokens":30,"total_tokens":47}}\n\n` ,
850
+ 'data: [DONE]\n\n' ,
851
+ ] ,
852
+ } ;
853
+
854
+ const { stream } = await model . doStream ( {
855
+ prompt : TEST_PROMPT ,
856
+ } ) ;
857
+
858
+ const elements = await convertReadableStreamToArray ( stream ) ;
859
+
860
+ // The expected order should be:
861
+ // 1. reasoning-start
862
+ // 2. reasoning-delta (3 times)
863
+ // 3. reasoning-end (when text starts)
864
+ // 4. text-start
865
+ // 5. text-delta (2 times)
866
+ // 6. text-end (when stream finishes)
867
+
868
+ const streamOrder = elements . map ( el => el . type ) ;
869
+
870
+ // Find the positions of key events
871
+ const reasoningStartIndex = streamOrder . indexOf ( 'reasoning-start' ) ;
872
+ const reasoningEndIndex = streamOrder . indexOf ( 'reasoning-end' ) ;
873
+ const textStartIndex = streamOrder . indexOf ( 'text-start' ) ;
874
+
875
+ // Reasoning should come before text and end before text starts
876
+ expect ( reasoningStartIndex ) . toBeLessThan ( textStartIndex ) ;
877
+ expect ( reasoningEndIndex ) . toBeLessThan ( textStartIndex ) ;
878
+
879
+ // Verify reasoning content
880
+ const reasoningDeltas = elements
881
+ . filter ( ( el ) => el . type === 'reasoning-delta' )
882
+ . map ( ( el ) => ( el as { type : 'reasoning-delta' ; delta : string } ) . delta ) ;
883
+
884
+ expect ( reasoningDeltas ) . toEqual ( [
885
+ 'I need to think about this step by step...' ,
886
+ ' First, I should analyze the request.' ,
887
+ ' Then I should provide a helpful response.' ,
888
+ ] ) ;
889
+
890
+ // Verify text content
891
+ const textDeltas = elements
892
+ . filter ( ( el ) => el . type === 'text-delta' )
893
+ . map ( ( el ) => ( el as { type : 'text-delta' ; delta : string } ) . delta ) ;
894
+
895
+ expect ( textDeltas ) . toEqual ( [
896
+ 'Hello! ' ,
897
+ 'How can I help you today?' ,
898
+ ] ) ;
899
+ } ) ;
900
+
815
901
it ( 'should stream tool deltas' , async ( ) => {
816
902
server . urls [ 'https://openrouter.ai/api/v1/chat/completions' ] ! . response = {
817
903
type : 'stream-chunks' ,
0 commit comments