@@ -329,6 +329,65 @@ impl<C: StreamableHttpClient> StreamableHttpClientWorker<C> {
329329 } )
330330 }
331331
332+ /// Convert an SSE stream into JSON-RPC messages with reconnect semantics.
333+ ///
334+ /// This is used for request-scoped SSE responses as well as the standalone
335+ /// GET stream. A request-scoped stream can close before its response arrives,
336+ /// and SEP-1699 requires the client to honor `retry` and resume with
337+ /// `Last-Event-ID` in that case.
338+ fn reconnecting_sse_to_jsonrpc (
339+ stream : BoxedSseStream ,
340+ client : C ,
341+ session_id : Arc < str > ,
342+ uri : Arc < str > ,
343+ auth_header : Option < String > ,
344+ custom_headers : HashMap < HeaderName , HeaderValue > ,
345+ retry_config : Arc < dyn SseRetryPolicy > ,
346+ ) -> impl Stream < Item = Result < ServerJsonRpcMessage , StreamableHttpError < C :: Error > > > + Send + ' static
347+ {
348+ SseAutoReconnectStream :: new (
349+ stream,
350+ StreamableHttpClientReconnect {
351+ client,
352+ session_id,
353+ uri,
354+ auth_header,
355+ custom_headers,
356+ } ,
357+ retry_config,
358+ )
359+ }
360+
361+ /// Convert a POST response SSE stream into JSON-RPC messages.
362+ ///
363+ /// Stateful sessions can resume via GET when the response stream closes
364+ /// before the server sends the matching JSON-RPC response. Stateless
365+ /// transports do not have enough state to resume, so they keep the raw
366+ /// SSE-to-JSON-RPC mapping.
367+ fn response_sse_to_jsonrpc (
368+ stream : BoxedSseStream ,
369+ session_id : Option < Arc < str > > ,
370+ client : C ,
371+ uri : Arc < str > ,
372+ auth_header : Option < String > ,
373+ custom_headers : HashMap < HeaderName , HeaderValue > ,
374+ retry_config : Arc < dyn SseRetryPolicy > ,
375+ ) -> BoxStream < ' static , Result < ServerJsonRpcMessage , StreamableHttpError < C :: Error > > > {
376+ match session_id {
377+ Some ( session_id) => Self :: reconnecting_sse_to_jsonrpc (
378+ stream,
379+ client,
380+ session_id,
381+ uri,
382+ auth_header,
383+ custom_headers,
384+ retry_config,
385+ )
386+ . boxed ( ) ,
387+ None => Self :: raw_sse_to_jsonrpc ( stream) . boxed ( ) ,
388+ }
389+ }
390+
332391 async fn execute_sse_stream (
333392 sse_stream : impl Stream < Item = Result < ServerJsonRpcMessage , StreamableHttpError < C :: Error > > >
334393 + Send
@@ -775,8 +834,17 @@ impl<C: StreamableHttpClient> Worker for StreamableHttpClientWorker<C> {
775834 Ok ( ( ) )
776835 }
777836 Ok ( StreamableHttpPostResponse :: Sse ( stream, ..) ) => {
837+ let sse_stream = Self :: response_sse_to_jsonrpc (
838+ stream,
839+ session_id. clone ( ) ,
840+ self . client . clone ( ) ,
841+ config. uri . clone ( ) ,
842+ config. auth_header . clone ( ) ,
843+ protocol_headers. clone ( ) ,
844+ self . config . retry_config . clone ( ) ,
845+ ) ;
778846 streams. spawn ( Self :: execute_sse_stream (
779- Self :: raw_sse_to_jsonrpc ( stream ) ,
847+ sse_stream ,
780848 sse_worker_tx. clone ( ) ,
781849 true ,
782850 transport_task_ct. child_token ( ) ,
@@ -800,8 +868,17 @@ impl<C: StreamableHttpClient> Worker for StreamableHttpClientWorker<C> {
800868 Ok ( ( ) )
801869 }
802870 Ok ( StreamableHttpPostResponse :: Sse ( stream, ..) ) => {
871+ let sse_stream = Self :: response_sse_to_jsonrpc (
872+ stream,
873+ session_id. clone ( ) ,
874+ self . client . clone ( ) ,
875+ config. uri . clone ( ) ,
876+ config. auth_header . clone ( ) ,
877+ protocol_headers. clone ( ) ,
878+ self . config . retry_config . clone ( ) ,
879+ ) ;
803880 streams. spawn ( Self :: execute_sse_stream (
804- Self :: raw_sse_to_jsonrpc ( stream ) ,
881+ sse_stream ,
805882 sse_worker_tx. clone ( ) ,
806883 true ,
807884 transport_task_ct. child_token ( ) ,
0 commit comments