a2a_types/
lib.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// A2A Protocol Types
5/// Based on A2A Protocol Specification JSON Schema
6/// Only includes types explicitly defined in a2a.json
7
8// ============================================================================
9// JSON-RPC 2.0 Base Types (from schema)
10// ============================================================================
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct JSONRPCMessage {
14    pub jsonrpc: String, // Always "2.0"
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub id: Option<JSONRPCId>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum JSONRPCId {
22    String(String),
23    Integer(i64),
24    Null,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct JSONRPCRequest {
29    pub jsonrpc: String, // Always "2.0"
30    pub method: String,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub params: Option<serde_json::Value>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct JSONRPCSuccessResponse {
37    pub jsonrpc: String, // Always "2.0"
38    pub result: serde_json::Value,
39    pub id: Option<JSONRPCId>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct JSONRPCErrorResponse {
44    pub jsonrpc: String, // Always "2.0"
45    pub error: JSONRPCError,
46    pub id: Option<JSONRPCId>,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct JSONRPCError {
51    pub code: i32,
52    pub message: String,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub data: Option<serde_json::Value>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
58#[serde(untagged)]
59pub enum JSONRPCResponse {
60    Success(JSONRPCSuccessResponse),
61    Error(JSONRPCErrorResponse),
62}
63
64// ============================================================================
65// A2A Error Types (from schema definitions)
66// ============================================================================
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct JSONParseError {
70    #[serde(default = "default_json_parse_error_code")]
71    pub code: i32, // -32700
72    #[serde(default = "default_json_parse_error_message")]
73    pub message: String,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub data: Option<serde_json::Value>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct InvalidRequestError {
80    #[serde(default = "default_invalid_request_error_code")]
81    pub code: i32, // -32600
82    #[serde(default = "default_invalid_request_error_message")]
83    pub message: String,
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub data: Option<serde_json::Value>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct MethodNotFoundError {
90    #[serde(default = "default_method_not_found_error_code")]
91    pub code: i32, // -32601
92    #[serde(default = "default_method_not_found_error_message")]
93    pub message: String,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub data: Option<serde_json::Value>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct InvalidParamsError {
100    #[serde(default = "default_invalid_params_error_code")]
101    pub code: i32, // -32602
102    #[serde(default = "default_invalid_params_error_message")]
103    pub message: String,
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub data: Option<serde_json::Value>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct InternalError {
110    #[serde(default = "default_internal_error_code")]
111    pub code: i32, // -32603
112    #[serde(default = "default_internal_error_message")]
113    pub message: String,
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub data: Option<serde_json::Value>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct TaskNotFoundError {
120    #[serde(default = "default_task_not_found_error_code")]
121    pub code: i32, // -32001
122    #[serde(default = "default_task_not_found_error_message")]
123    pub message: String,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub data: Option<serde_json::Value>,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct TaskNotCancelableError {
130    #[serde(default = "default_task_not_cancelable_error_code")]
131    pub code: i32, // -32002
132    #[serde(default = "default_task_not_cancelable_error_message")]
133    pub message: String,
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub data: Option<serde_json::Value>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct PushNotificationNotSupportedError {
140    #[serde(default = "default_push_notification_not_supported_error_code")]
141    pub code: i32, // -32003
142    #[serde(default = "default_push_notification_not_supported_error_message")]
143    pub message: String,
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub data: Option<serde_json::Value>,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct UnsupportedOperationError {
150    #[serde(default = "default_unsupported_operation_error_code")]
151    pub code: i32, // -32004
152    #[serde(default = "default_unsupported_operation_error_message")]
153    pub message: String,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub data: Option<serde_json::Value>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct ContentTypeNotSupportedError {
160    #[serde(default = "default_content_type_not_supported_error_code")]
161    pub code: i32, // -32005
162    #[serde(default = "default_content_type_not_supported_error_message")]
163    pub message: String,
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub data: Option<serde_json::Value>,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct InvalidAgentResponseError {
170    #[serde(default = "default_invalid_agent_response_error_code")]
171    pub code: i32, // -32006
172    #[serde(default = "default_invalid_agent_response_error_message")]
173    pub message: String,
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub data: Option<serde_json::Value>,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct AuthenticatedExtendedCardNotConfiguredError {
180    #[serde(default = "default_authenticated_extended_card_not_configured_error_code")]
181    pub code: i32, // -32007
182    #[serde(default = "default_authenticated_extended_card_not_configured_error_message")]
183    pub message: String,
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub data: Option<serde_json::Value>,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
189#[serde(untagged)]
190pub enum A2AError {
191    JSONParse(JSONParseError),
192    InvalidRequest(InvalidRequestError),
193    MethodNotFound(MethodNotFoundError),
194    InvalidParams(InvalidParamsError),
195    Internal(InternalError),
196    TaskNotFound(TaskNotFoundError),
197    TaskNotCancelable(TaskNotCancelableError),
198    PushNotificationNotSupported(PushNotificationNotSupportedError),
199    UnsupportedOperation(UnsupportedOperationError),
200    ContentTypeNotSupported(ContentTypeNotSupportedError),
201    InvalidAgentResponse(InvalidAgentResponseError),
202    AuthenticatedExtendedCardNotConfigured(AuthenticatedExtendedCardNotConfiguredError),
203}
204
205// Default functions for error codes and messages
206fn default_json_parse_error_code() -> i32 {
207    -32700
208}
209fn default_json_parse_error_message() -> String {
210    "Invalid JSON payload".to_string()
211}
212fn default_invalid_request_error_code() -> i32 {
213    -32600
214}
215fn default_invalid_request_error_message() -> String {
216    "Request payload validation error".to_string()
217}
218fn default_method_not_found_error_code() -> i32 {
219    -32601
220}
221fn default_method_not_found_error_message() -> String {
222    "Method not found".to_string()
223}
224fn default_invalid_params_error_code() -> i32 {
225    -32602
226}
227fn default_invalid_params_error_message() -> String {
228    "Invalid parameters".to_string()
229}
230fn default_internal_error_code() -> i32 {
231    -32603
232}
233fn default_internal_error_message() -> String {
234    "Internal error".to_string()
235}
236fn default_task_not_found_error_code() -> i32 {
237    -32001
238}
239fn default_task_not_found_error_message() -> String {
240    "Task not found".to_string()
241}
242fn default_task_not_cancelable_error_code() -> i32 {
243    -32002
244}
245fn default_task_not_cancelable_error_message() -> String {
246    "Task cannot be canceled".to_string()
247}
248fn default_push_notification_not_supported_error_code() -> i32 {
249    -32003
250}
251fn default_push_notification_not_supported_error_message() -> String {
252    "Push Notification is not supported".to_string()
253}
254fn default_unsupported_operation_error_code() -> i32 {
255    -32004
256}
257fn default_unsupported_operation_error_message() -> String {
258    "This operation is not supported".to_string()
259}
260fn default_content_type_not_supported_error_code() -> i32 {
261    -32005
262}
263fn default_content_type_not_supported_error_message() -> String {
264    "Incompatible content types".to_string()
265}
266fn default_invalid_agent_response_error_code() -> i32 {
267    -32006
268}
269fn default_invalid_agent_response_error_message() -> String {
270    "Invalid agent response".to_string()
271}
272fn default_authenticated_extended_card_not_configured_error_code() -> i32 {
273    -32007
274}
275fn default_authenticated_extended_card_not_configured_error_message() -> String {
276    "Authenticated Extended Card is not configured".to_string()
277}
278
279// ============================================================================
280// A2A Core Protocol Types (from schema)
281// ============================================================================
282
283#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
284#[serde(rename_all = "kebab-case")]
285pub enum TaskState {
286    Submitted,
287    Working,
288    InputRequired,
289    Completed,
290    Canceled,
291    Failed,
292    Rejected,
293    AuthRequired,
294    Unknown,
295}
296
297#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
298pub struct TaskStatus {
299    pub state: TaskState,
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub timestamp: Option<String>, // ISO 8601 datetime
302    #[serde(skip_serializing_if = "Option::is_none")]
303    pub message: Option<Message>,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
307pub struct Task {
308    pub kind: String, // Always "task"
309    pub id: String,
310    #[serde(rename = "contextId")]
311    pub context_id: String,
312    pub status: TaskStatus,
313    #[serde(skip_serializing_if = "Vec::is_empty")]
314    pub history: Vec<Message>,
315    #[serde(skip_serializing_if = "Vec::is_empty")]
316    pub artifacts: Vec<Artifact>,
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub metadata: Option<HashMap<String, serde_json::Value>>,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
322#[serde(rename_all = "lowercase")]
323pub enum MessageRole {
324    User,
325    Agent,
326}
327
328impl PartialEq<&str> for MessageRole {
329    fn eq(&self, other: &&str) -> bool {
330        matches!(
331            (self, *other),
332            (MessageRole::User, "user")
333                | (MessageRole::Agent, "agent")
334                | (MessageRole::Agent, "assistant")
335        )
336    }
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
340pub struct Message {
341    pub kind: String, // Always "message"
342    #[serde(rename = "messageId")]
343    pub message_id: String,
344    pub role: MessageRole,
345    pub parts: Vec<Part>,
346    #[serde(skip_serializing_if = "Option::is_none", rename = "contextId")]
347    pub context_id: Option<String>,
348    #[serde(skip_serializing_if = "Option::is_none", rename = "taskId")]
349    pub task_id: Option<String>,
350    #[serde(skip_serializing_if = "Vec::is_empty", rename = "referenceTaskIds")]
351    pub reference_task_ids: Vec<String>,
352    #[serde(skip_serializing_if = "Vec::is_empty")]
353    pub extensions: Vec<String>,
354    #[serde(skip_serializing_if = "Option::is_none")]
355    pub metadata: Option<HashMap<String, serde_json::Value>>,
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
359#[serde(tag = "kind", rename_all = "lowercase")]
360pub enum Part {
361    Text {
362        text: String,
363        #[serde(skip_serializing_if = "Option::is_none")]
364        metadata: Option<HashMap<String, serde_json::Value>>,
365    },
366    File {
367        file: FileContent,
368        #[serde(skip_serializing_if = "Option::is_none")]
369        metadata: Option<HashMap<String, serde_json::Value>>,
370    },
371    Data {
372        data: serde_json::Value,
373        #[serde(skip_serializing_if = "Option::is_none")]
374        metadata: Option<HashMap<String, serde_json::Value>>,
375    },
376}
377
378impl Part {
379    pub fn as_data(&self) -> Option<&serde_json::Value> {
380        match self {
381            Part::Data { data, .. } => Some(data),
382            _ => None,
383        }
384    }
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
388#[serde(untagged)]
389pub enum FileContent {
390    WithBytes(FileWithBytes),
391    WithUri(FileWithUri),
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
395pub struct FileBase {
396    #[serde(skip_serializing_if = "Option::is_none", rename = "mimeType")]
397    pub mime_type: Option<String>,
398    #[serde(skip_serializing_if = "Option::is_none")]
399    pub name: Option<String>,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
403pub struct FileWithBytes {
404    #[serde(flatten)]
405    pub base: FileBase,
406    pub bytes: String, // base64-encoded
407}
408
409#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
410pub struct FileWithUri {
411    #[serde(flatten)]
412    pub base: FileBase,
413    pub uri: String,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
417pub struct Artifact {
418    #[serde(rename = "artifactId")]
419    pub artifact_id: String,
420    pub parts: Vec<Part>,
421    #[serde(skip_serializing_if = "Option::is_none")]
422    pub name: Option<String>,
423    #[serde(skip_serializing_if = "Option::is_none")]
424    pub description: Option<String>,
425    #[serde(skip_serializing_if = "Vec::is_empty")]
426    pub extensions: Vec<String>,
427    #[serde(skip_serializing_if = "Option::is_none")]
428    pub metadata: Option<HashMap<String, serde_json::Value>>,
429}
430
431// ============================================================================
432// A2A Method Parameter Types (from schema)
433// ============================================================================
434
435#[derive(Debug, Clone, Serialize, Deserialize)]
436pub struct MessageSendParams {
437    pub message: Message,
438    #[serde(skip_serializing_if = "Option::is_none")]
439    pub configuration: Option<MessageSendConfiguration>,
440    #[serde(skip_serializing_if = "Option::is_none")]
441    pub metadata: Option<HashMap<String, serde_json::Value>>,
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize, Default)]
445pub struct MessageSendConfiguration {
446    #[serde(skip_serializing_if = "Option::is_none")]
447    pub blocking: Option<bool>,
448    #[serde(skip_serializing_if = "Option::is_none", rename = "historyLength")]
449    pub history_length: Option<i32>,
450    #[serde(skip_serializing_if = "Vec::is_empty", rename = "acceptedOutputModes")]
451    pub accepted_output_modes: Vec<String>,
452    #[serde(
453        skip_serializing_if = "Option::is_none",
454        rename = "pushNotificationConfig"
455    )]
456    pub push_notification_config: Option<PushNotificationConfig>,
457}
458
459#[derive(Debug, Clone, Serialize, Deserialize)]
460pub struct PushNotificationConfig {
461    pub url: String,
462    #[serde(skip_serializing_if = "Option::is_none")]
463    pub id: Option<String>,
464    #[serde(skip_serializing_if = "Option::is_none")]
465    pub token: Option<String>,
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub authentication: Option<PushNotificationAuthenticationInfo>,
468}
469
470#[derive(Debug, Clone, Serialize, Deserialize)]
471pub struct PushNotificationAuthenticationInfo {
472    pub schemes: Vec<String>,
473    #[serde(skip_serializing_if = "Option::is_none")]
474    pub credentials: Option<String>,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize)]
478pub struct TaskIdParams {
479    pub id: String,
480    #[serde(skip_serializing_if = "Option::is_none")]
481    pub metadata: Option<HashMap<String, serde_json::Value>>,
482}
483
484#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct TaskQueryParams {
486    pub id: String,
487    #[serde(skip_serializing_if = "Option::is_none", rename = "historyLength")]
488    pub history_length: Option<i32>,
489    #[serde(skip_serializing_if = "Option::is_none")]
490    pub metadata: Option<HashMap<String, serde_json::Value>>,
491}
492
493#[derive(Debug, Clone, Serialize, Deserialize)]
494pub struct TaskPushNotificationConfig {
495    #[serde(rename = "taskId")]
496    pub task_id: String,
497    #[serde(rename = "pushNotificationConfig")]
498    pub push_notification_config: PushNotificationConfig,
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize)]
502#[serde(untagged)]
503pub enum GetTaskPushNotificationConfigParams {
504    TaskIdOnly(TaskIdParams),
505    WithConfigId(GetTaskPushNotificationConfigParamsWithId),
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize)]
509pub struct GetTaskPushNotificationConfigParamsWithId {
510    pub id: String,
511    #[serde(rename = "pushNotificationConfigId")]
512    pub push_notification_config_id: String,
513    #[serde(skip_serializing_if = "Option::is_none")]
514    pub metadata: Option<HashMap<String, serde_json::Value>>,
515}
516
517#[derive(Debug, Clone, Serialize, Deserialize)]
518pub struct ListTaskPushNotificationConfigParams {
519    pub id: String,
520    #[serde(skip_serializing_if = "Option::is_none")]
521    pub metadata: Option<HashMap<String, serde_json::Value>>,
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct DeleteTaskPushNotificationConfigParams {
526    pub id: String,
527    #[serde(rename = "pushNotificationConfigId")]
528    pub push_notification_config_id: String,
529    #[serde(skip_serializing_if = "Option::is_none")]
530    pub metadata: Option<HashMap<String, serde_json::Value>>,
531}
532
533// ============================================================================
534// A2A Request Types (from schema)
535// ============================================================================
536
537#[derive(Debug, Clone, Serialize, Deserialize)]
538pub struct SendMessageRequest {
539    pub jsonrpc: String, // Always "2.0"
540    pub method: String,  // Always "message/send"
541    pub params: MessageSendParams,
542    pub id: JSONRPCId,
543}
544
545#[derive(Debug, Clone, Serialize, Deserialize)]
546pub struct SendStreamingMessageRequest {
547    pub jsonrpc: String, // Always "2.0"
548    pub method: String,  // Always "message/stream"
549    pub params: MessageSendParams,
550    pub id: JSONRPCId,
551}
552
553#[derive(Debug, Clone, Serialize, Deserialize)]
554pub struct GetTaskRequest {
555    pub jsonrpc: String, // Always "2.0"
556    pub method: String,  // Always "tasks/get"
557    pub params: TaskQueryParams,
558    pub id: JSONRPCId,
559}
560
561#[derive(Debug, Clone, Serialize, Deserialize)]
562pub struct CancelTaskRequest {
563    pub jsonrpc: String, // Always "2.0"
564    pub method: String,  // Always "tasks/cancel"
565    pub params: TaskIdParams,
566    pub id: JSONRPCId,
567}
568
569#[derive(Debug, Clone, Serialize, Deserialize)]
570pub struct SetTaskPushNotificationConfigRequest {
571    pub jsonrpc: String, // Always "2.0"
572    pub method: String,  // Always "tasks/pushNotificationConfig/set"
573    pub params: TaskPushNotificationConfig,
574    pub id: JSONRPCId,
575}
576
577#[derive(Debug, Clone, Serialize, Deserialize)]
578pub struct GetTaskPushNotificationConfigRequest {
579    pub jsonrpc: String, // Always "2.0"
580    pub method: String,  // Always "tasks/pushNotificationConfig/get"
581    pub params: GetTaskPushNotificationConfigParams,
582    pub id: JSONRPCId,
583}
584
585#[derive(Debug, Clone, Serialize, Deserialize)]
586pub struct ListTaskPushNotificationConfigRequest {
587    pub jsonrpc: String, // Always "2.0"
588    pub method: String,  // Always "tasks/pushNotificationConfig/list"
589    pub params: ListTaskPushNotificationConfigParams,
590    pub id: JSONRPCId,
591}
592
593#[derive(Debug, Clone, Serialize, Deserialize)]
594pub struct DeleteTaskPushNotificationConfigRequest {
595    pub jsonrpc: String, // Always "2.0"
596    pub method: String,  // Always "tasks/pushNotificationConfig/delete"
597    pub params: DeleteTaskPushNotificationConfigParams,
598    pub id: JSONRPCId,
599}
600
601#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct TaskResubscriptionRequest {
603    pub jsonrpc: String, // Always "2.0"
604    pub method: String,  // Always "tasks/resubscribe"
605    pub params: TaskIdParams,
606    pub id: JSONRPCId,
607}
608
609#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct GetAuthenticatedExtendedCardRequest {
611    pub jsonrpc: String, // Always "2.0"
612    pub method: String,  // Always "agent/getAuthenticatedExtendedCard"
613    pub id: JSONRPCId,
614}
615
616#[derive(Debug, Clone, Serialize, Deserialize)]
617#[serde(untagged)]
618pub enum A2ARequest {
619    SendMessage(SendMessageRequest),
620    SendStreamingMessage(SendStreamingMessageRequest),
621    GetTask(GetTaskRequest),
622    CancelTask(CancelTaskRequest),
623    SetTaskPushNotificationConfig(SetTaskPushNotificationConfigRequest),
624    GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest),
625    TaskResubscription(TaskResubscriptionRequest),
626    ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest),
627    DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest),
628    GetAuthenticatedExtendedCard(GetAuthenticatedExtendedCardRequest),
629}
630
631// ============================================================================
632// A2A Response Types (from schema)
633// ============================================================================
634
635#[derive(Debug, Clone, Serialize, Deserialize)]
636#[serde(untagged)]
637pub enum SendMessageResult {
638    Task(Task),
639    Message(Message),
640}
641
642#[derive(Debug, Clone, Serialize, Deserialize)]
643pub struct SendMessageSuccessResponse {
644    pub jsonrpc: String, // Always "2.0"
645    pub result: SendMessageResult,
646    pub id: Option<JSONRPCId>,
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
650#[serde(untagged)]
651pub enum SendMessageResponse {
652    Success(Box<SendMessageSuccessResponse>),
653    Error(JSONRPCErrorResponse),
654}
655
656#[derive(Debug, Clone, Serialize, Deserialize)]
657#[serde(untagged)]
658pub enum SendStreamingMessageResult {
659    Task(Task),
660    Message(Message),
661    TaskStatusUpdate(TaskStatusUpdateEvent),
662    TaskArtifactUpdate(TaskArtifactUpdateEvent),
663}
664
665#[derive(Debug, Clone, Serialize, Deserialize)]
666pub struct SendStreamingMessageSuccessResponse {
667    pub jsonrpc: String, // Always "2.0"
668    pub result: SendStreamingMessageResult,
669    pub id: Option<JSONRPCId>,
670}
671
672#[derive(Debug, Clone, Serialize, Deserialize)]
673#[serde(untagged)]
674pub enum SendStreamingMessageResponse {
675    Success(Box<SendStreamingMessageSuccessResponse>),
676    Error(JSONRPCErrorResponse),
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct GetTaskSuccessResponse {
681    pub jsonrpc: String, // Always "2.0"
682    pub result: Task,
683    pub id: Option<JSONRPCId>,
684}
685
686#[derive(Debug, Clone, Serialize, Deserialize)]
687#[serde(untagged)]
688pub enum GetTaskResponse {
689    Success(Box<GetTaskSuccessResponse>),
690    Error(JSONRPCErrorResponse),
691}
692
693#[derive(Debug, Clone, Serialize, Deserialize)]
694pub struct CancelTaskSuccessResponse {
695    pub jsonrpc: String, // Always "2.0"
696    pub result: Task,
697    pub id: Option<JSONRPCId>,
698}
699
700#[derive(Debug, Clone, Serialize, Deserialize)]
701#[serde(untagged)]
702pub enum CancelTaskResponse {
703    Success(Box<CancelTaskSuccessResponse>),
704    Error(JSONRPCErrorResponse),
705}
706
707#[derive(Debug, Clone, Serialize, Deserialize)]
708pub struct SetTaskPushNotificationConfigSuccessResponse {
709    pub jsonrpc: String, // Always "2.0"
710    pub result: TaskPushNotificationConfig,
711    pub id: Option<JSONRPCId>,
712}
713
714#[derive(Debug, Clone, Serialize, Deserialize)]
715#[serde(untagged)]
716pub enum SetTaskPushNotificationConfigResponse {
717    Success(SetTaskPushNotificationConfigSuccessResponse),
718    Error(JSONRPCErrorResponse),
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize)]
722pub struct GetTaskPushNotificationConfigSuccessResponse {
723    pub jsonrpc: String, // Always "2.0"
724    pub result: TaskPushNotificationConfig,
725    pub id: Option<JSONRPCId>,
726}
727
728#[derive(Debug, Clone, Serialize, Deserialize)]
729#[serde(untagged)]
730pub enum GetTaskPushNotificationConfigResponse {
731    Success(GetTaskPushNotificationConfigSuccessResponse),
732    Error(JSONRPCErrorResponse),
733}
734
735#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct ListTaskPushNotificationConfigSuccessResponse {
737    pub jsonrpc: String, // Always "2.0"
738    pub result: Vec<TaskPushNotificationConfig>,
739    pub id: Option<JSONRPCId>,
740}
741
742#[derive(Debug, Clone, Serialize, Deserialize)]
743#[serde(untagged)]
744pub enum ListTaskPushNotificationConfigResponse {
745    Success(ListTaskPushNotificationConfigSuccessResponse),
746    Error(JSONRPCErrorResponse),
747}
748
749#[derive(Debug, Clone, Serialize, Deserialize)]
750pub struct DeleteTaskPushNotificationConfigSuccessResponse {
751    pub jsonrpc: String,                   // Always "2.0"
752    pub result: Option<serde_json::Value>, // null on success
753    pub id: Option<JSONRPCId>,
754}
755
756#[derive(Debug, Clone, Serialize, Deserialize)]
757#[serde(untagged)]
758pub enum DeleteTaskPushNotificationConfigResponse {
759    Success(DeleteTaskPushNotificationConfigSuccessResponse),
760    Error(JSONRPCErrorResponse),
761}
762
763#[derive(Debug, Clone, Serialize, Deserialize)]
764pub struct GetAuthenticatedExtendedCardSuccessResponse {
765    pub jsonrpc: String, // Always "2.0"
766    pub result: AgentCard,
767    pub id: Option<JSONRPCId>,
768}
769
770#[derive(Debug, Clone, Serialize, Deserialize)]
771#[serde(untagged)]
772pub enum GetAuthenticatedExtendedCardResponse {
773    Success(Box<GetAuthenticatedExtendedCardSuccessResponse>),
774    Error(JSONRPCErrorResponse),
775}
776
777// ============================================================================
778// A2A Agent Card and Discovery Types (from schema)
779// ============================================================================
780
781#[derive(Debug, Clone, Serialize, Deserialize)]
782#[serde(rename_all = "UPPERCASE")]
783pub enum TransportProtocol {
784    #[serde(rename = "JSONRPC")]
785    JsonRpc,
786    #[serde(rename = "GRPC")]
787    Grpc,
788    #[serde(rename = "HTTP+JSON")]
789    HttpJson,
790}
791
792#[derive(Debug, Clone, Serialize, Deserialize)]
793pub struct AgentInterface {
794    pub transport: TransportProtocol,
795    pub url: String,
796}
797
798#[derive(Debug, Clone, Serialize, Deserialize)]
799pub struct AgentExtension {
800    pub uri: String,
801    #[serde(skip_serializing_if = "Option::is_none")]
802    pub description: Option<String>,
803    #[serde(skip_serializing_if = "Option::is_none")]
804    pub required: Option<bool>,
805    #[serde(skip_serializing_if = "Option::is_none")]
806    pub params: Option<HashMap<String, serde_json::Value>>,
807}
808
809#[derive(Debug, Clone, Serialize, Deserialize)]
810pub struct AgentCapabilities {
811    #[serde(skip_serializing_if = "Option::is_none")]
812    pub streaming: Option<bool>,
813    #[serde(skip_serializing_if = "Option::is_none", rename = "pushNotifications")]
814    pub push_notifications: Option<bool>,
815    #[serde(
816        skip_serializing_if = "Option::is_none",
817        rename = "stateTransitionHistory"
818    )]
819    pub state_transition_history: Option<bool>,
820    #[serde(skip_serializing_if = "Vec::is_empty")]
821    pub extensions: Vec<AgentExtension>,
822}
823
824#[derive(Debug, Clone, Serialize, Deserialize)]
825pub struct AgentProvider {
826    pub organization: String,
827    pub url: String,
828}
829
830#[derive(Debug, Clone, Serialize, Deserialize)]
831pub struct AgentSkill {
832    pub id: String,
833    pub name: String,
834    pub description: String,
835    pub tags: Vec<String>,
836    #[serde(skip_serializing_if = "Vec::is_empty")]
837    pub examples: Vec<String>,
838    #[serde(skip_serializing_if = "Vec::is_empty", rename = "inputModes")]
839    pub input_modes: Vec<String>,
840    #[serde(skip_serializing_if = "Vec::is_empty", rename = "outputModes")]
841    pub output_modes: Vec<String>,
842    #[serde(skip_serializing_if = "Vec::is_empty")]
843    pub security: Vec<HashMap<String, Vec<String>>>,
844}
845
846#[derive(Debug, Clone, Serialize, Deserialize)]
847pub struct AgentCardSignature {
848    #[serde(rename = "protected")]
849    pub protected_header: String, // Base64url-encoded
850    pub signature: String, // Base64url-encoded
851    #[serde(skip_serializing_if = "Option::is_none")]
852    pub header: Option<HashMap<String, serde_json::Value>>,
853}
854
855#[derive(Debug, Clone, Serialize, Deserialize)]
856pub struct AgentCard {
857    pub name: String,
858    pub description: String,
859    pub version: String,
860    #[serde(rename = "protocolVersion")]
861    pub protocol_version: String, // defaults to "0.3.0"
862    pub url: String,
863    #[serde(rename = "preferredTransport")]
864    pub preferred_transport: TransportProtocol, // defaults to JSONRPC
865    pub capabilities: AgentCapabilities,
866    #[serde(rename = "defaultInputModes")]
867    pub default_input_modes: Vec<String>,
868    #[serde(rename = "defaultOutputModes")]
869    pub default_output_modes: Vec<String>,
870    pub skills: Vec<AgentSkill>,
871    #[serde(skip_serializing_if = "Option::is_none")]
872    pub provider: Option<AgentProvider>,
873    #[serde(skip_serializing_if = "Vec::is_empty", rename = "additionalInterfaces")]
874    pub additional_interfaces: Vec<AgentInterface>,
875    #[serde(skip_serializing_if = "Option::is_none", rename = "documentationUrl")]
876    pub documentation_url: Option<String>,
877    #[serde(skip_serializing_if = "Option::is_none", rename = "iconUrl")]
878    pub icon_url: Option<String>,
879    #[serde(skip_serializing_if = "Vec::is_empty")]
880    pub security: Vec<HashMap<String, Vec<String>>>,
881    #[serde(skip_serializing_if = "Option::is_none", rename = "securitySchemes")]
882    pub security_schemes: Option<HashMap<String, SecurityScheme>>,
883    #[serde(skip_serializing_if = "Vec::is_empty")]
884    pub signatures: Vec<AgentCardSignature>,
885    #[serde(
886        skip_serializing_if = "Option::is_none",
887        rename = "supportsAuthenticatedExtendedCard"
888    )]
889    pub supports_authenticated_extended_card: Option<bool>,
890}
891
892// ============================================================================
893// Security and Authentication Types (from schema)
894// ============================================================================
895
896#[derive(Debug, Clone, Serialize, Deserialize)]
897#[serde(tag = "type", rename_all = "camelCase")]
898pub enum SecurityScheme {
899    #[serde(rename = "apiKey")]
900    ApiKey(APIKeySecurityScheme),
901    #[serde(rename = "http")]
902    Http(HTTPAuthSecurityScheme),
903    #[serde(rename = "oauth2")]
904    OAuth2(Box<OAuth2SecurityScheme>),
905    #[serde(rename = "openIdConnect")]
906    OpenIdConnect(OpenIdConnectSecurityScheme),
907    #[serde(rename = "mutualTLS")]
908    MutualTLS(MutualTLSSecurityScheme),
909}
910
911#[derive(Debug, Clone, Serialize, Deserialize)]
912pub struct APIKeySecurityScheme {
913    #[serde(rename = "type")]
914    pub scheme_type: String, // Always "apiKey"
915    pub name: String,
916    #[serde(rename = "in")]
917    pub location: APIKeyLocation,
918    #[serde(skip_serializing_if = "Option::is_none")]
919    pub description: Option<String>,
920}
921
922#[derive(Debug, Clone, Serialize, Deserialize)]
923#[serde(rename_all = "lowercase")]
924pub enum APIKeyLocation {
925    Query,
926    Header,
927    Cookie,
928}
929
930#[derive(Debug, Clone, Serialize, Deserialize)]
931pub struct HTTPAuthSecurityScheme {
932    #[serde(rename = "type")]
933    pub scheme_type: String, // Always "http"
934    pub scheme: String,
935    #[serde(skip_serializing_if = "Option::is_none")]
936    pub description: Option<String>,
937    #[serde(skip_serializing_if = "Option::is_none", rename = "bearerFormat")]
938    pub bearer_format: Option<String>,
939}
940
941#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct OAuth2SecurityScheme {
943    #[serde(rename = "type")]
944    pub scheme_type: String, // Always "oauth2"
945    pub flows: OAuthFlows,
946    #[serde(skip_serializing_if = "Option::is_none")]
947    pub description: Option<String>,
948    #[serde(skip_serializing_if = "Option::is_none", rename = "oauth2MetadataUrl")]
949    pub oauth2_metadata_url: Option<String>,
950}
951
952#[derive(Debug, Clone, Serialize, Deserialize)]
953pub struct OpenIdConnectSecurityScheme {
954    #[serde(rename = "type")]
955    pub scheme_type: String, // Always "openIdConnect"
956    #[serde(rename = "openIdConnectUrl")]
957    pub open_id_connect_url: String,
958    #[serde(skip_serializing_if = "Option::is_none")]
959    pub description: Option<String>,
960}
961
962#[derive(Debug, Clone, Serialize, Deserialize)]
963pub struct MutualTLSSecurityScheme {
964    #[serde(rename = "type")]
965    pub scheme_type: String, // Always "mutualTLS"
966    #[serde(skip_serializing_if = "Option::is_none")]
967    pub description: Option<String>,
968}
969
970#[derive(Debug, Clone, Serialize, Deserialize)]
971pub struct OAuthFlows {
972    #[serde(skip_serializing_if = "Option::is_none", rename = "authorizationCode")]
973    pub authorization_code: Option<AuthorizationCodeOAuthFlow>,
974    #[serde(skip_serializing_if = "Option::is_none")]
975    pub implicit: Option<ImplicitOAuthFlow>,
976    #[serde(skip_serializing_if = "Option::is_none")]
977    pub password: Option<PasswordOAuthFlow>,
978    #[serde(skip_serializing_if = "Option::is_none", rename = "clientCredentials")]
979    pub client_credentials: Option<ClientCredentialsOAuthFlow>,
980}
981
982#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct AuthorizationCodeOAuthFlow {
984    #[serde(rename = "authorizationUrl")]
985    pub authorization_url: String,
986    #[serde(rename = "tokenUrl")]
987    pub token_url: String,
988    pub scopes: HashMap<String, String>,
989    #[serde(skip_serializing_if = "Option::is_none", rename = "refreshUrl")]
990    pub refresh_url: Option<String>,
991}
992
993#[derive(Debug, Clone, Serialize, Deserialize)]
994pub struct ImplicitOAuthFlow {
995    #[serde(rename = "authorizationUrl")]
996    pub authorization_url: String,
997    pub scopes: HashMap<String, String>,
998    #[serde(skip_serializing_if = "Option::is_none", rename = "refreshUrl")]
999    pub refresh_url: Option<String>,
1000}
1001
1002#[derive(Debug, Clone, Serialize, Deserialize)]
1003pub struct PasswordOAuthFlow {
1004    #[serde(rename = "tokenUrl")]
1005    pub token_url: String,
1006    pub scopes: HashMap<String, String>,
1007    #[serde(skip_serializing_if = "Option::is_none", rename = "refreshUrl")]
1008    pub refresh_url: Option<String>,
1009}
1010
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1012pub struct ClientCredentialsOAuthFlow {
1013    #[serde(rename = "tokenUrl")]
1014    pub token_url: String,
1015    pub scopes: HashMap<String, String>,
1016    #[serde(skip_serializing_if = "Option::is_none", rename = "refreshUrl")]
1017    pub refresh_url: Option<String>,
1018}
1019
1020// ============================================================================
1021// Convenience Types
1022// ============================================================================
1023
1024/// Main agent response type that can be either a Task or Message
1025#[derive(Debug, Clone, Serialize, Deserialize)]
1026#[serde(untagged)]
1027pub enum AgentResponse {
1028    Task(Task),
1029    Message(Message),
1030}
1031
1032// ============================================================================
1033// Streaming Event Types (from schema)
1034// ============================================================================
1035
1036#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1037pub struct TaskStatusUpdateEvent {
1038    pub kind: String, // Always "status-update"
1039    #[serde(rename = "taskId")]
1040    pub task_id: String,
1041    #[serde(rename = "contextId")]
1042    pub context_id: String,
1043    pub status: TaskStatus,
1044    #[serde(rename = "final")]
1045    pub is_final: bool,
1046    #[serde(skip_serializing_if = "Option::is_none")]
1047    pub metadata: Option<HashMap<String, serde_json::Value>>,
1048}
1049
1050#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1051pub struct TaskArtifactUpdateEvent {
1052    pub kind: String, // Always "artifact-update"
1053    #[serde(rename = "taskId")]
1054    pub task_id: String,
1055    #[serde(rename = "contextId")]
1056    pub context_id: String,
1057    pub artifact: Artifact,
1058    #[serde(skip_serializing_if = "Option::is_none")]
1059    pub append: Option<bool>,
1060    #[serde(skip_serializing_if = "Option::is_none", rename = "lastChunk")]
1061    pub last_chunk: Option<bool>,
1062    #[serde(skip_serializing_if = "Option::is_none")]
1063    pub metadata: Option<HashMap<String, serde_json::Value>>,
1064}