@@ -447,6 +447,11 @@ export class CodexAppServerEventProjector {
447447 if ( ! delta ) {
448448 return ;
449449 }
450+ this . rememberAssistantPhase ( readItem ( params . item ) ) ;
451+ const phase = readString ( params , "phase" ) ;
452+ if ( phase ) {
453+ this . assistantPhaseByItem . set ( itemId , phase ) ;
454+ }
450455 if ( ! this . assistantStarted ) {
451456 this . assistantStarted = true ;
452457 await this . params . onAssistantMessageStart ?.( ) ;
@@ -456,10 +461,13 @@ export class CodexAppServerEventProjector {
456461 this . assistantTextByItem . set ( itemId , text ) ;
457462 if ( this . isCommentaryAssistantItem ( itemId ) ) {
458463 this . emitCommentaryProgress ( { itemId, text } ) ;
464+ } else if ( this . shouldStreamAssistantPartial ( itemId ) ) {
465+ await this . params . onPartialReply ?.( { text, delta } ) ;
459466 }
460467 // Codex app-server can emit multiple agentMessage items per turn, including
461468 // intermediate coordination/progress prose. Keep those deltas internal until
462- // turn completion chooses the last assistant item as the user-visible reply.
469+ // their phase identifies terminal answer text or turn completion chooses the
470+ // last assistant item as the user-visible reply.
463471 }
464472
465473 private async handleReasoningDelta (
@@ -970,6 +978,10 @@ export class CodexAppServerEventProjector {
970978 return this . assistantPhaseByItem . get ( itemId ) === "commentary" ;
971979 }
972980
981+ private shouldStreamAssistantPartial ( itemId : string ) : boolean {
982+ return this . assistantPhaseByItem . get ( itemId ) === "final_answer" ;
983+ }
984+
973985 private emitCommentaryProgress ( params : { itemId : string ; text : string } ) : void {
974986 const progressText = params . text . replace ( / \s + / g, " " ) . trim ( ) ;
975987 if (
0 commit comments