1use a2a::*;
4use futures::stream::BoxStream;
5use serde_json::Value;
6use std::collections::HashMap;
7
8use crate::middleware::{ServiceParams, User};
9
10pub struct ExecutorContext {
12 pub message: Option<Message>,
14 pub task_id: TaskId,
16 pub stored_task: Option<Task>,
18 pub context_id: String,
20 pub metadata: Option<HashMap<String, Value>>,
22 pub user: Option<User>,
24 pub service_params: ServiceParams,
26 pub tenant: Option<String>,
28}
29
30impl ExecutorContext {
31 pub fn task_info(&self) -> (TaskId, String) {
32 (self.task_id.clone(), self.context_id.clone())
33 }
34}
35
36#[async_trait::async_trait]
42pub trait AgentExecutor: Send + Sync + 'static {
43 fn execute(&self, ctx: ExecutorContext)
45 -> BoxStream<'static, Result<StreamResponse, A2AError>>;
46
47 fn cancel(&self, ctx: ExecutorContext) -> BoxStream<'static, Result<StreamResponse, A2AError>>;
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_executor_context_task_info() {
57 let ctx = ExecutorContext {
58 message: None,
59 task_id: "t1".into(),
60 stored_task: None,
61 context_id: "c1".into(),
62 metadata: None,
63 user: None,
64 service_params: HashMap::new(),
65 tenant: None,
66 };
67 let (tid, cid) = ctx.task_info();
68 assert_eq!(tid, "t1");
69 assert_eq!(cid, "c1");
70 }
71}