use a2a_protocol_types::events::StreamResponse;
use a2a_protocol_types::responses::SendMessageResponse;
use a2a_protocol_types::task::Task;
use super::super::{RequestHandler, SendMessageResult};
use super::Started;
use super::decisions::shape_response_history;
use crate::error::ServerResult;
use crate::streaming::InMemoryQueueReader;
impl RequestHandler {
async fn hydrate_response_history(&self, task: &mut Task, history_length: Option<u32>) {
if history_length.is_none() {
return;
}
if let Ok(Some(stored)) = self.task_store.get(&task.id).await {
task.history = stored.history;
}
}
pub(super) async fn respond_replay(
&self,
task: Task,
streaming: bool,
response_history_length: Option<u32>,
) -> ServerResult<SendMessageResult> {
let mut snapshot = task;
shape_response_history(&mut snapshot, response_history_length);
if !streaming {
return Ok(SendMessageResult::Response(SendMessageResponse::Task(
snapshot,
)));
}
let task_id = snapshot.id.clone();
let terminal = snapshot.status.state.is_terminal();
let first = a2a_protocol_types::events::StreamResponse::Task(snapshot);
let reader = if terminal {
InMemoryQueueReader::snapshot_then_end(first)
} else {
self.event_queue_manager
.subscribe_with_snapshot(&task_id, first.clone())
.await
.unwrap_or_else(|| InMemoryQueueReader::snapshot_then_end(first))
.with_reattach(self.subscribe_reattach_hook(task_id.clone()))
};
Ok(SendMessageResult::Stream(reader))
}
pub(super) async fn respond_in_background(
&self,
started: Started,
streaming: bool,
response_history_length: Option<u32>,
) -> SendMessageResult {
let Started {
task,
reader,
persistence_rx,
executor_handle,
cancel,
gate,
} = started;
self.spawn_background_event_processor(
task.id.clone(),
executor_handle,
persistence_rx,
task.clone(),
super::super::event_processing::ProcessorLinks { cancel, gate },
);
let mut snapshot = task;
self.hydrate_response_history(&mut snapshot, response_history_length)
.await;
shape_response_history(&mut snapshot, response_history_length);
if streaming {
let mut reader = reader;
reader.set_first_event(StreamResponse::Task(snapshot));
SendMessageResult::Stream(reader)
} else {
drop(reader);
SendMessageResult::Response(SendMessageResponse::Task(snapshot))
}
}
pub(super) async fn respond_blocking(
&self,
started: Started,
response_history_length: Option<u32>,
) -> ServerResult<SendMessageResult> {
let Started {
task,
reader,
executor_handle,
..
} = started;
let collector = self.sync_collector();
let tenant = crate::store::tenant::TenantContext::current();
let collection = self
.in_flight
.background()
.spawn(crate::rpc_span::in_current_span(
crate::store::tenant::TenantContext::scope(tenant, async move {
collector
.collect_events(reader, task.id, executor_handle)
.await
}),
));
let collected = collection.await.map_err(|e| {
crate::error::ServerError::Internal(format!("event collection ended abnormally: {e}"))
})??;
if let Some(message) = collected.direct_message {
return Ok(SendMessageResult::Response(SendMessageResponse::Message(
message,
)));
}
let mut final_task = collected.task;
self.hydrate_response_history(&mut final_task, response_history_length)
.await;
shape_response_history(&mut final_task, response_history_length);
Ok(SendMessageResult::Response(SendMessageResponse::Task(
final_task,
)))
}
}