@@ -815,14 +815,20 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV2 {
815815 // flag that checks if there have been client-side tool calls (not executed by openai)
816816 let hasFunctionCall = false
817817
818+ // Track reasoning by output_index instead of item_id
819+ // GitHub Copilot rotates encrypted item IDs on every event
818820 const activeReasoning : Record <
819- string ,
821+ number ,
820822 {
823+ canonicalId : string // the item.id from output_item.added
821824 encryptedContent ?: string | null
822825 summaryParts : number [ ]
823826 }
824827 > = { }
825828
829+ // Track current active reasoning output_index for correlating summary events
830+ let currentReasoningOutputIndex : number | null = null
831+
826832 // Track a stable text part id for the current assistant message.
827833 // Copilot may change item_id across text deltas; normalize to one id.
828834 let currentTextId : string | null = null
@@ -933,10 +939,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV2 {
933939 } ,
934940 } )
935941 } else if ( isResponseOutputItemAddedReasoningChunk ( value ) ) {
936- activeReasoning [ value . item . id ] = {
942+ activeReasoning [ value . output_index ] = {
943+ canonicalId : value . item . id ,
937944 encryptedContent : value . item . encrypted_content ,
938945 summaryParts : [ 0 ] ,
939946 }
947+ currentReasoningOutputIndex = value . output_index
940948
941949 controller . enqueue ( {
942950 type : "reasoning-start" ,
@@ -1091,22 +1099,25 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV2 {
10911099 currentTextId = null
10921100 }
10931101 } else if ( isResponseOutputItemDoneReasoningChunk ( value ) ) {
1094- const activeReasoningPart = activeReasoning [ value . item . id ]
1102+ const activeReasoningPart = activeReasoning [ value . output_index ]
10951103 if ( activeReasoningPart ) {
10961104 for ( const summaryIndex of activeReasoningPart . summaryParts ) {
10971105 controller . enqueue ( {
10981106 type : "reasoning-end" ,
1099- id : `${ value . item . id } :${ summaryIndex } ` ,
1107+ id : `${ activeReasoningPart . canonicalId } :${ summaryIndex } ` ,
11001108 providerMetadata : {
11011109 openai : {
1102- itemId : value . item . id ,
1110+ itemId : activeReasoningPart . canonicalId ,
11031111 reasoningEncryptedContent : value . item . encrypted_content ?? null ,
11041112 } ,
11051113 } ,
11061114 } )
11071115 }
1116+ delete activeReasoning [ value . output_index ]
1117+ if ( currentReasoningOutputIndex === value . output_index ) {
1118+ currentReasoningOutputIndex = null
1119+ }
11081120 }
1109- delete activeReasoning [ value . item . id ]
11101121 }
11111122 } else if ( isResponseFunctionCallArgumentsDeltaChunk ( value ) ) {
11121123 const toolCall = ongoingToolCalls [ value . output_index ]
@@ -1198,32 +1209,40 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV2 {
11981209 logprobs . push ( value . logprobs )
11991210 }
12001211 } else if ( isResponseReasoningSummaryPartAddedChunk ( value ) ) {
1212+ const activeItem =
1213+ currentReasoningOutputIndex !== null ? activeReasoning [ currentReasoningOutputIndex ] : null
1214+
12011215 // the first reasoning start is pushed in isResponseOutputItemAddedReasoningChunk.
1202- if ( value . summary_index > 0 ) {
1203- activeReasoning [ value . item_id ] ? .summaryParts . push ( value . summary_index )
1216+ if ( activeItem && value . summary_index > 0 ) {
1217+ activeItem . summaryParts . push ( value . summary_index )
12041218
12051219 controller . enqueue ( {
12061220 type : "reasoning-start" ,
1207- id : `${ value . item_id } :${ value . summary_index } ` ,
1221+ id : `${ activeItem . canonicalId } :${ value . summary_index } ` ,
12081222 providerMetadata : {
12091223 openai : {
1210- itemId : value . item_id ,
1211- reasoningEncryptedContent : activeReasoning [ value . item_id ] ? .encryptedContent ?? null ,
1224+ itemId : activeItem . canonicalId ,
1225+ reasoningEncryptedContent : activeItem . encryptedContent ?? null ,
12121226 } ,
12131227 } ,
12141228 } )
12151229 }
12161230 } else if ( isResponseReasoningSummaryTextDeltaChunk ( value ) ) {
1217- controller . enqueue ( {
1218- type : "reasoning-delta" ,
1219- id : `${ value . item_id } :${ value . summary_index } ` ,
1220- delta : value . delta ,
1221- providerMetadata : {
1222- openai : {
1223- itemId : value . item_id ,
1231+ const activeItem =
1232+ currentReasoningOutputIndex !== null ? activeReasoning [ currentReasoningOutputIndex ] : null
1233+
1234+ if ( activeItem ) {
1235+ controller . enqueue ( {
1236+ type : "reasoning-delta" ,
1237+ id : `${ activeItem . canonicalId } :${ value . summary_index } ` ,
1238+ delta : value . delta ,
1239+ providerMetadata : {
1240+ openai : {
1241+ itemId : activeItem . canonicalId ,
1242+ } ,
12241243 } ,
1225- } ,
1226- } )
1244+ } )
1245+ }
12271246 } else if ( isResponseFinishedChunk ( value ) ) {
12281247 finishReason = mapOpenAIResponseFinishReason ( {
12291248 finishReason : value . response . incomplete_details ?. reason ,
0 commit comments