@@ -41,6 +41,7 @@ use tracing::{
4141use types:: {
4242 ContentBlock ,
4343 Message ,
44+ MessageStartEvent ,
4445 MessageStopEvent ,
4546 MetadataEvent ,
4647 Role ,
@@ -403,6 +404,8 @@ struct StreamParseState {
403404 parsing_tool_use : Option < ( String , String , String ) > ,
404405 /// Buffered metadata event returned from the response stream
405406 metadata : Option < MetadataEvent > ,
407+ /// Buffered message start event returned from the response stream
408+ message_start : Option < MessageStartEvent > ,
406409 /// Buffered message stop event returned from the response stream
407410 message_stop : Option < MessageStopEvent > ,
408411 /// Buffered error event returned from the response stream
@@ -425,6 +428,7 @@ impl StreamParseState {
425428 user_message,
426429 message_id : None ,
427430 metadata : None ,
431+ message_start : None ,
428432 message_stop : None ,
429433 stream_err : None ,
430434 ended_time : None ,
@@ -433,15 +437,12 @@ impl StreamParseState {
433437 }
434438
435439 pub fn next ( & mut self , ev : Option < StreamResult > , buf : & mut Vec < AgentLoopEventKind > ) {
436- if self . errored {
437- if let Some ( ev) = ev {
438- warn ! ( ?ev, "ignoring unexpected event after having received an error" ) ;
439- }
440- return ;
441- }
442-
443440 let Some ( ev) = ev else {
444441 // No event received means the stream has ended.
442+ debug_assert ! (
443+ self . ended_time. is_none( ) ,
444+ "unexpected call to next after stream has already ended"
445+ ) ;
445446 self . ended_time = Some ( self . ended_time . unwrap_or ( Instant :: now ( ) ) ) ;
446447 self . errored = self . errored || !self . invalid_tool_uses . is_empty ( ) ;
447448 let result = self . make_result ( ) ;
@@ -453,14 +454,31 @@ impl StreamParseState {
453454 return ;
454455 } ;
455456
457+ if self . errored {
458+ warn ! ( ?ev, "ignoring unexpected event after having received an error" ) ;
459+ return ;
460+ }
461+
462+ // Debug assertion that we always start with either a MessageStart, or an error.
463+ match & ev {
464+ StreamResult :: Ok ( StreamEvent :: MessageStart ( _) ) | StreamResult :: Err ( _) => ( ) ,
465+ other @ StreamResult :: Ok ( _) => debug_assert ! (
466+ self . message_start. is_some( ) ,
467+ "received an unexpected event at the start of the response stream: {:?}" ,
468+ other
469+ ) ,
470+ }
471+
456472 // Pushing low-level stream events in case end users want to consume these directly. Likely
457473 // not required.
458474 buf. push ( AgentLoopEventKind :: Stream ( ev. clone ( ) ) ) ;
459475
460476 match ev {
461477 StreamResult :: Ok ( s) => match s {
462478 StreamEvent :: MessageStart ( ev) => {
479+ debug_assert ! ( self . message_start. is_none( ) ) ;
463480 debug_assert ! ( ev. role == Role :: Assistant ) ;
481+ self . message_start = Some ( ev) ;
464482 } ,
465483 StreamEvent :: MessageStop ( ev) => {
466484 debug_assert ! ( self . message_stop. is_none( ) ) ;
@@ -547,7 +565,6 @@ impl StreamParseState {
547565 ) ;
548566 self . stream_err = Some ( err) ;
549567 self . errored = true ;
550- self . ended_time = Some ( Instant :: now ( ) ) ;
551568 } ,
552569 }
553570 }
0 commit comments