1717use Prism \Prism \Streaming \Events \CitationEvent ;
1818use Prism \Prism \Streaming \Events \ErrorEvent ;
1919use Prism \Prism \Streaming \Events \ProviderToolEvent ;
20+ use Prism \Prism \Streaming \Events \StepFinishEvent ;
21+ use Prism \Prism \Streaming \Events \StepStartEvent ;
2022use Prism \Prism \Streaming \Events \StreamEndEvent ;
2123use Prism \Prism \Streaming \Events \StreamEvent ;
2224use Prism \Prism \Streaming \Events \StreamStartEvent ;
@@ -76,15 +78,21 @@ protected function processStream(Response $response, Request $request, int $dept
7678 $ streamEvent = $ this ->processEvent ($ event );
7779
7880 if ($ streamEvent instanceof Generator) {
79- yield from $ streamEvent ;
81+ // Re-yield items to avoid key conflicts when using collect()
82+ foreach ($ streamEvent as $ item ) {
83+ yield $ item ;
84+ }
8085 } elseif ($ streamEvent instanceof StreamEvent) {
8186 yield $ streamEvent ;
8287 }
8388 }
8489
8590 // Handle tool calls if present
8691 if ($ this ->state ->hasToolCalls ()) {
87- yield from $ this ->handleToolCalls ($ request , $ depth );
92+ // Re-yield items to avoid key conflicts when using collect()
93+ foreach ($ this ->handleToolCalls ($ request , $ depth ) as $ item ) {
94+ yield $ item ;
95+ }
8896 }
8997 }
9098
@@ -109,8 +117,9 @@ protected function processEvent(array $event): StreamEvent|Generator|null
109117
110118 /**
111119 * @param array<string, mixed> $event
120+ * @return Generator<StreamEvent>
112121 */
113- protected function handleMessageStart (array $ event ): StreamStartEvent
122+ protected function handleMessageStart (array $ event ): Generator
114123 {
115124 $ message = $ event ['message ' ] ?? [];
116125 $ this ->state ->withMessageId ($ message ['id ' ] ?? EventID::generate ());
@@ -126,12 +135,21 @@ protected function handleMessageStart(array $event): StreamStartEvent
126135 ));
127136 }
128137
129- return new StreamStartEvent (
138+ yield new StreamStartEvent (
130139 id: EventID::generate (),
131140 timestamp: time (),
132141 model: $ message ['model ' ] ?? 'unknown ' ,
133142 provider: 'anthropic '
134143 );
144+
145+ if ($ this ->state ->shouldEmitStepStart ()) {
146+ $ this ->state ->markStepStarted ();
147+
148+ yield new StepStartEvent (
149+ id: EventID::generate (),
150+ timestamp: time ()
151+ );
152+ }
135153 }
136154
137155 /**
@@ -228,10 +246,17 @@ protected function handleMessageDelta(array $event): null
228246
229247 /**
230248 * @param array<string, mixed> $event
249+ * @return Generator<StreamEvent>
231250 */
232- protected function handleMessageStop (array $ event ): StreamEndEvent
251+ protected function handleMessageStop (array $ event ): Generator
233252 {
234- return new StreamEndEvent (
253+ $ this ->state ->markStepFinished ();
254+ yield new StepFinishEvent (
255+ id: EventID::generate (),
256+ timestamp: time ()
257+ );
258+
259+ yield new StreamEndEvent (
235260 id: EventID::generate (),
236261 timestamp: time (),
237262 finishReason: FinishReason::Stop, // Default, will be updated by message_delta
@@ -492,6 +517,13 @@ protected function handleToolCalls(Request $request, int $depth): Generator
492517
493518 $ request ->addMessage (new ToolResultMessage ($ toolResults ));
494519
520+ // Emit step finish after tool calls
521+ $ this ->state ->markStepFinished ();
522+ yield new StepFinishEvent (
523+ id: EventID::generate (),
524+ timestamp: time ()
525+ );
526+
495527 // Continue streaming if within step limit
496528 $ depth ++;
497529 if ($ depth < $ request ->maxSteps ()) {
0 commit comments