@@ -9,13 +9,14 @@ import { describe, expect, it } from 'vitest';
99import { TokenizerType } from '../../../../util/common/tokenizer' ;
1010import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation' ;
1111import { ILogService } from '../../../log/common/logService' ;
12+ import { IResponseDelta } from '../../../networking/common/fetch' ;
1213import { IChatEndpoint , ICreateEndpointBodyOptions } from '../../../networking/common/networking' ;
1314import { TelemetryData } from '../../../telemetry/common/telemetryData' ;
1415import { SpyingTelemetryService } from '../../../telemetry/node/spyingTelemetryService' ;
1516import { createFakeStreamResponse } from '../../../test/node/fetcher' ;
1617import { createPlatformServices } from '../../../test/node/services' ;
1718import { CustomDataPartMimeTypes } from '../../common/endpointTypes' ;
18- import { createResponsesRequestBody , processResponseFromChatEndpoint , responseApiInputToRawMessagesForLogging } from '../responsesApi' ;
19+ import { createResponsesRequestBody , OpenAIResponsesProcessor , processResponseFromChatEndpoint , responseApiInputToRawMessagesForLogging } from '../responsesApi' ;
1920
2021describe ( 'responseApiInputToRawMessagesForLogging' , ( ) => {
2122
@@ -270,28 +271,33 @@ describe('createResponsesRequestBody', () => {
270271 return endpoint ;
271272 } ;
272273
273- it ( 'only sends response output ids for phased assistant messages ' , ( ) => {
274+ it ( 'sends response output ids independently from phase ' , ( ) => {
274275 const services = createPlatformServices ( ) ;
275276 const accessor = services . createTestingAccessor ( ) ;
276277 const endpoint = createTestEndpoint ( ) ;
277278
278279 const nonPhaseAssistant = createAssistantMessage ( [
279280 { type : Raw . ChatCompletionContentPartKind . Text , text : 'plain assistant reply' } ,
281+ { type : Raw . ChatCompletionContentPartKind . Opaque , value : { type : CustomDataPartMimeTypes . ResponseOutputMessageId , responseOutputMessageId : 'msg_plain' } } ,
280282 ] ) ;
281283 const phaseAssistant = createAssistantMessage ( [
282284 { type : Raw . ChatCompletionContentPartKind . Text , text : 'phase assistant reply' } ,
283- { type : Raw . ChatCompletionContentPartKind . Opaque , value : { type : CustomDataPartMimeTypes . PhaseData , phase : 'tool_calling' , responseOutputMessageId : 'msg_phase' } } ,
285+ { type : Raw . ChatCompletionContentPartKind . Opaque , value : { type : CustomDataPartMimeTypes . ResponseOutputMessageId , responseOutputMessageId : 'msg_phase' } } ,
286+ { type : Raw . ChatCompletionContentPartKind . Opaque , value : { type : CustomDataPartMimeTypes . PhaseData , phase : 'tool_calling' } } ,
284287 ] ) ;
285288
286289 const body = createResponsesRequestBody ( accessor , createRequestOptions ( [ nonPhaseAssistant , phaseAssistant ] ) , endpoint . model , endpoint ) ;
287290 const input = body . input as OpenAI . Responses . ResponseInputItem [ ] ;
288291
289292 expect ( input ) . toHaveLength ( 2 ) ;
290- expect ( input [ 0 ] ) . toEqual ( {
293+ expect ( input [ 0 ] ) . toMatchObject ( {
291294 role : 'assistant' ,
292- content : [ { type : 'input_text' , text : 'plain assistant reply' } ] ,
295+ content : [ { type : 'output_text' , text : 'plain assistant reply' , annotations : [ ] } ] ,
296+ id : 'msg_plain' ,
297+ status : 'completed' ,
293298 type : 'message' ,
294299 } ) ;
300+ expect ( input [ 0 ] ) . toHaveProperty ( 'phase' , undefined ) ;
295301 expect ( input [ 1 ] ) . toEqual ( {
296302 role : 'assistant' ,
297303 content : [ { type : 'output_text' , text : 'phase assistant reply' , annotations : [ ] } ] ,
@@ -304,6 +310,34 @@ describe('createResponsesRequestBody', () => {
304310 accessor . dispose ( ) ;
305311 services . dispose ( ) ;
306312 } ) ;
313+
314+ it ( 'streams response output ids even when no phase is present' , async ( ) => {
315+ const telemetryData = TelemetryData . createAndMarkAsIssued ( { modelCallId : 'model-call-1' } , { } ) ;
316+ const deltas : IResponseDelta [ ] = [ ] ;
317+ const processor = new OpenAIResponsesProcessor ( telemetryData , 'req_123' , 'gh_123' ) ;
318+
319+ processor . push ( {
320+ type : 'response.output_item.done' ,
321+ sequence_number : 0 ,
322+ output_index : 0 ,
323+ item : {
324+ id : 'msg_plain' ,
325+ role : 'assistant' ,
326+ content : [ { type : 'output_text' , text : 'plain assistant reply' , annotations : [ ] } ] ,
327+ status : 'completed' ,
328+ type : 'message' ,
329+ }
330+ } as OpenAI . Responses . ResponseOutputItemDoneEvent , async ( _text , _index , delta : IResponseDelta ) => {
331+ deltas . push ( delta ) ;
332+ return undefined ;
333+ } ) ;
334+
335+ expect ( deltas ) . toEqual ( [ {
336+ text : '' ,
337+ responseOutputMessageId : 'msg_plain' ,
338+ phase : undefined ,
339+ } ] ) ;
340+ } ) ;
307341} ) ;
308342
309343describe ( 'processResponseFromChatEndpoint telemetry' , ( ) => {
0 commit comments