@@ -244,11 +244,11 @@ describe("openai-responses reasoning replay", () => {
244244 resolveReplayableResponsesMessageId ( {
245245 replayResponsesItemIds : true ,
246246 textSignatureId : "msg_commentary" ,
247- textSignaturePhase : "commentary" ,
248247 fallbackId : "msg_0" ,
248+ fallbackOrdinal : 0 ,
249249 previousReplayItemWasReasoning : false ,
250250 } ) ,
251- ) . toBe ( "msg_commentary" ) ;
251+ ) . toBeUndefined ( ) ;
252252
253253 expect (
254254 resolveReplayableResponsesMessageId ( {
@@ -270,7 +270,7 @@ describe("openai-responses reasoning replay", () => {
270270 } ) ;
271271
272272 it . each ( [ "commentary" , "final_answer" ] as const ) (
273- "replays assistant message phase metadata for %s" ,
273+ "replays assistant message id and phase metadata for %s when paired with reasoning " ,
274274 async ( phase ) => {
275275 const assistantWithText = buildAssistantMessage ( {
276276 stopReason : "stop" ,
@@ -301,6 +301,34 @@ describe("openai-responses reasoning replay", () => {
301301 } ,
302302 ) ;
303303
304+ it . each ( [ "commentary" , "final_answer" ] as const ) (
305+ "omits phase-tagged assistant message id for %s when reasoning is absent" ,
306+ async ( phase ) => {
307+ const assistantWithText = buildAssistantMessage ( {
308+ stopReason : "stop" ,
309+ content : [
310+ {
311+ type : "text" ,
312+ text : "hello" ,
313+ textSignature : JSON . stringify ( { v : 1 , id : `msg_${ phase } ` , phase } ) ,
314+ } ,
315+ ] ,
316+ } ) ;
317+
318+ const { input } = await runAbortedOpenAIResponsesStream ( {
319+ messages : [
320+ { role : "user" , content : "Hi" , timestamp : Date . now ( ) } ,
321+ assistantWithText ,
322+ { role : "user" , content : "Ok" , timestamp : Date . now ( ) } ,
323+ ] ,
324+ } ) ;
325+
326+ const [ replayedMessage ] = extractInputMessages ( input ) ;
327+ expect ( replayedMessage ) . toMatchObject ( { phase } ) ;
328+ expect ( replayedMessage ) . not . toHaveProperty ( "id" ) ;
329+ } ,
330+ ) ;
331+
304332 it ( "replays a synthetic id while preserving phase for id-less text signatures" , async ( ) => {
305333 // After a reasoning drop the sanitizer keeps the phase but removes the msg_*
306334 // id. The conversion must then emit a unique synthetic id per text block AND
0 commit comments