a2a_client/components/
streaming.rs1use a2a_rs::{RetryPolicy, StreamItem};
4use axum::response::sse::{Event, KeepAlive, Sse};
5use futures::StreamExt;
6use std::{convert::Infallible, sync::Arc};
7use tracing::{error, warn};
8
9use crate::WebA2AClient;
10
11pub fn create_sse_stream(
21 client: Arc<WebA2AClient>,
22 task_id: String,
23) -> Sse<impl futures::Stream<Item = Result<Event, Infallible>>> {
24 let updates = client.subscribe_resilient(&task_id, RetryPolicy::default());
25
26 let stream = updates.filter_map(|result| async move {
27 let event = match result {
28 Ok(event) => event,
29 Err(e) => {
30 warn!("Stream error (ending): {}", e);
31 return None;
32 }
33 };
34
35 let (event_type, data) = match &event.item {
36 StreamItem::Task(task) => ("task-update", serde_json::to_string(task)),
37 StreamItem::StatusUpdate(status) => ("task-status", serde_json::to_string(status)),
38 StreamItem::ArtifactUpdate(artifact) => ("artifact", serde_json::to_string(artifact)),
39 };
40
41 match data {
42 Ok(json) => {
43 let mut sse = Event::default().event(event_type).data(json);
44 if let Some(id) = event.event_id {
45 sse = sse.id(id.to_string());
46 }
47 Some(Ok(sse))
48 }
49 Err(e) => {
50 error!("Failed to serialize {event_type}: {e}");
51 None
52 }
53 }
54 });
55
56 Sse::new(stream).keep_alive(KeepAlive::default())
57}