Skip to main content

systemprompt_agent/models/a2a/protocol/
requests.rs

1use super::push_notification::{
2    DeleteTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest,
3    ListTaskPushNotificationConfigRequest, PushNotificationConfig,
4    SetTaskPushNotificationConfigRequest, TaskResubscriptionRequest,
5};
6use crate::models::a2a::jsonrpc::{JsonRpcResponse, RequestId};
7use crate::models::a2a::{AgentCard, Task, TaskState};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
11pub struct MessageSendParams {
12    pub message: crate::models::a2a::Message,
13    pub configuration: Option<MessageSendConfiguration>,
14    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
15}
16
17#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
18#[serde(rename_all = "camelCase")]
19pub struct MessageSendConfiguration {
20    pub accepted_output_modes: Option<Vec<String>>,
21    pub history_length: Option<u32>,
22    pub push_notification_config: Option<PushNotificationConfig>,
23    pub blocking: Option<bool>,
24}
25
26#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
27pub struct TaskQueryParams {
28    pub id: String,
29    pub history_length: Option<u32>,
30}
31
32#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
33pub struct TaskIdParams {
34    pub id: String,
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
38pub struct A2aRequest {
39    pub method: String,
40    pub params: serde_json::Value,
41}
42
43#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
44#[serde(untagged)]
45pub enum A2aResponse {
46    SendMessage(SendMessageResponse),
47    GetTask(GetTaskResponse),
48    CancelTask(CancelTaskResponse),
49    GetAuthenticatedExtendedCard(GetAuthenticatedExtendedCardResponse),
50    SendStreamingMessage(SendStreamingMessageResponse),
51}
52
53pub type SendMessageResponse = JsonRpcResponse<Task>;
54pub type GetTaskResponse = JsonRpcResponse<Task>;
55pub type CancelTaskResponse = JsonRpcResponse<Task>;
56pub type GetAuthenticatedExtendedCardResponse = JsonRpcResponse<AgentCard>;
57pub type SendStreamingMessageResponse = JsonRpcResponse<Task>;
58
59#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
60pub struct A2aJsonRpcRequest {
61    pub jsonrpc: String,
62    pub method: String,
63    pub params: serde_json::Value,
64    pub id: RequestId,
65}
66
67impl A2aJsonRpcRequest {
68    pub fn parse_request(&self) -> Result<A2aRequestParams, A2aParseError> {
69        match self.method.as_str() {
70            "message/send" => {
71                let params: MessageSendParams = serde_json::from_value(self.params.clone())
72                    .map_err(|e| A2aParseError::InvalidParams {
73                        method: self.method.clone(),
74                        error: e.to_string(),
75                    })?;
76                Ok(A2aRequestParams::SendMessage(params))
77            },
78            "tasks/get" => {
79                let params: TaskQueryParams =
80                    serde_json::from_value(self.params.clone()).map_err(|e| {
81                        A2aParseError::InvalidParams {
82                            method: self.method.clone(),
83                            error: e.to_string(),
84                        }
85                    })?;
86                Ok(A2aRequestParams::GetTask(params))
87            },
88            "tasks/cancel" => {
89                let params: TaskIdParams =
90                    serde_json::from_value(self.params.clone()).map_err(|e| {
91                        A2aParseError::InvalidParams {
92                            method: self.method.clone(),
93                            error: e.to_string(),
94                        }
95                    })?;
96                Ok(A2aRequestParams::CancelTask(params))
97            },
98            "agent/getAuthenticatedExtendedCard" => {
99                let params: serde_json::Value = serde_json::from_value(self.params.clone())
100                    .map_err(|e| A2aParseError::InvalidParams {
101                        method: self.method.clone(),
102                        error: e.to_string(),
103                    })?;
104                Ok(A2aRequestParams::GetAuthenticatedExtendedCard(params))
105            },
106            "message/stream" => {
107                let params: MessageSendParams = serde_json::from_value(self.params.clone())
108                    .map_err(|e| A2aParseError::InvalidParams {
109                        method: self.method.clone(),
110                        error: e.to_string(),
111                    })?;
112                Ok(A2aRequestParams::SendStreamingMessage(params))
113            },
114            "tasks/resubscribe" => {
115                let params: TaskResubscriptionRequest = serde_json::from_value(self.params.clone())
116                    .map_err(|e| A2aParseError::InvalidParams {
117                        method: self.method.clone(),
118                        error: e.to_string(),
119                    })?;
120                Ok(A2aRequestParams::TaskResubscription(params))
121            },
122            "tasks/pushNotificationConfig/set" => {
123                let params: SetTaskPushNotificationConfigRequest =
124                    serde_json::from_value(self.params.clone()).map_err(|e| {
125                        A2aParseError::InvalidParams {
126                            method: self.method.clone(),
127                            error: e.to_string(),
128                        }
129                    })?;
130                Ok(A2aRequestParams::SetTaskPushNotificationConfig(params))
131            },
132            "tasks/pushNotificationConfig/get" => {
133                let params: GetTaskPushNotificationConfigRequest =
134                    serde_json::from_value(self.params.clone()).map_err(|e| {
135                        A2aParseError::InvalidParams {
136                            method: self.method.clone(),
137                            error: e.to_string(),
138                        }
139                    })?;
140                Ok(A2aRequestParams::GetTaskPushNotificationConfig(params))
141            },
142            "tasks/pushNotificationConfig/list" => {
143                let params: ListTaskPushNotificationConfigRequest =
144                    serde_json::from_value(self.params.clone()).map_err(|e| {
145                        A2aParseError::InvalidParams {
146                            method: self.method.clone(),
147                            error: e.to_string(),
148                        }
149                    })?;
150                Ok(A2aRequestParams::ListTaskPushNotificationConfig(params))
151            },
152            "tasks/pushNotificationConfig/delete" => {
153                let params: DeleteTaskPushNotificationConfigRequest =
154                    serde_json::from_value(self.params.clone()).map_err(|e| {
155                        A2aParseError::InvalidParams {
156                            method: self.method.clone(),
157                            error: e.to_string(),
158                        }
159                    })?;
160                Ok(A2aRequestParams::DeleteTaskPushNotificationConfig(params))
161            },
162            _ => Err(A2aParseError::UnsupportedMethod {
163                method: self.method.clone(),
164            }),
165        }
166    }
167}
168
169#[derive(Debug, Clone, PartialEq)]
170pub enum A2aRequestParams {
171    SendMessage(MessageSendParams),
172    GetTask(TaskQueryParams),
173    CancelTask(TaskIdParams),
174    GetAuthenticatedExtendedCard(serde_json::Value),
175    SendStreamingMessage(MessageSendParams),
176    TaskResubscription(TaskResubscriptionRequest),
177    SetTaskPushNotificationConfig(SetTaskPushNotificationConfigRequest),
178    GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest),
179    ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest),
180    DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest),
181}
182
183#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
184pub enum A2aParseError {
185    #[error("Unsupported method: {method}")]
186    UnsupportedMethod { method: String },
187
188    #[error("Invalid parameters for method '{method}': {error}")]
189    InvalidParams { method: String, error: String },
190}
191
192impl A2aResponse {
193    pub fn send_message(task: Task, id: RequestId) -> Self {
194        Self::SendMessage(JsonRpcResponse {
195            jsonrpc: "2.0".to_string(),
196            id,
197            result: Some(task),
198            error: None,
199        })
200    }
201
202    pub fn get_task(task: Task, id: RequestId) -> Self {
203        Self::GetTask(JsonRpcResponse {
204            jsonrpc: "2.0".to_string(),
205            id,
206            result: Some(task),
207            error: None,
208        })
209    }
210
211    pub fn cancel_task(task: Task, id: RequestId) -> Self {
212        Self::CancelTask(JsonRpcResponse {
213            jsonrpc: "2.0".to_string(),
214            id,
215            result: Some(task),
216            error: None,
217        })
218    }
219}
220
221#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
222pub struct TaskNotFoundError {
223    pub task_id: String,
224    pub message: String,
225    pub code: i32,
226    pub data: serde_json::Value,
227}
228
229#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
230pub struct TaskNotCancelableError {
231    pub task_id: String,
232    pub state: TaskState,
233    pub message: String,
234    pub code: i32,
235    pub data: serde_json::Value,
236}
237
238#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
239pub struct UnsupportedOperationError {
240    pub operation: String,
241    pub message: String,
242    pub code: i32,
243    pub data: serde_json::Value,
244}