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