adk_server/a2a/
types.rs

1use serde::{Deserialize, Serialize};
2use serde_json::{Map, Value};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5#[serde(rename_all = "lowercase")]
6pub enum Role {
7    User,
8    Agent,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct FileContent {
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub name: Option<String>,
15    #[serde(skip_serializing_if = "Option::is_none", rename = "mimeType")]
16    pub mime_type: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub bytes: Option<String>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub uri: Option<String>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(untagged)]
25pub enum Part {
26    Text {
27        text: String,
28        #[serde(skip_serializing_if = "Option::is_none")]
29        metadata: Option<Map<String, Value>>,
30    },
31    File {
32        file: FileContent,
33        #[serde(skip_serializing_if = "Option::is_none")]
34        metadata: Option<Map<String, Value>>,
35    },
36    Data {
37        data: Map<String, Value>,
38        #[serde(skip_serializing_if = "Option::is_none")]
39        metadata: Option<Map<String, Value>>,
40    },
41}
42
43impl Part {
44    pub fn text(text: String) -> Self {
45        Part::Text { text, metadata: None }
46    }
47
48    pub fn file(file: FileContent) -> Self {
49        Part::File { file, metadata: None }
50    }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct Message {
55    pub role: Role,
56    pub parts: Vec<Part>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub metadata: Option<Map<String, Value>>,
59    #[serde(rename = "messageId")]
60    pub message_id: String,
61    #[serde(skip_serializing_if = "Option::is_none", rename = "taskId")]
62    pub task_id: Option<String>,
63    #[serde(skip_serializing_if = "Option::is_none", rename = "contextId")]
64    pub context_id: Option<String>,
65}
66
67impl Message {
68    pub fn builder() -> MessageBuilder {
69        MessageBuilder::default()
70    }
71}
72
73#[derive(Default)]
74pub struct MessageBuilder {
75    role: Option<Role>,
76    parts: Vec<Part>,
77    metadata: Option<Map<String, Value>>,
78    message_id: Option<String>,
79    task_id: Option<String>,
80    context_id: Option<String>,
81}
82
83impl MessageBuilder {
84    pub fn role(mut self, role: Role) -> Self {
85        self.role = Some(role);
86        self
87    }
88
89    pub fn parts(mut self, parts: Vec<Part>) -> Self {
90        self.parts = parts;
91        self
92    }
93
94    pub fn metadata(mut self, metadata: Option<Map<String, Value>>) -> Self {
95        self.metadata = metadata;
96        self
97    }
98
99    pub fn message_id(mut self, id: String) -> Self {
100        self.message_id = Some(id);
101        self
102    }
103
104    pub fn build(self) -> Message {
105        Message {
106            role: self.role.unwrap_or(Role::User),
107            parts: self.parts,
108            metadata: self.metadata,
109            message_id: self.message_id.unwrap_or_default(),
110            task_id: self.task_id,
111            context_id: self.context_id,
112        }
113    }
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct Artifact {
118    #[serde(rename = "artifactId")]
119    pub artifact_id: String,
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub name: Option<String>,
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub description: Option<String>,
124    pub parts: Vec<Part>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub metadata: Option<Map<String, Value>>,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub extensions: Option<Vec<String>>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
132pub enum TaskState {
133    Submitted,
134    Working,
135    InputRequired,
136    Completed,
137    Failed,
138    Canceled,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct TaskStatus {
143    pub state: TaskState,
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub message: Option<String>,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct TaskStatusUpdateEvent {
150    #[serde(rename = "taskId")]
151    pub task_id: String,
152    #[serde(skip_serializing_if = "Option::is_none", rename = "contextId")]
153    pub context_id: Option<String>,
154    pub status: TaskStatus,
155    #[serde(rename = "finalUpdate")]
156    pub final_update: bool,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct TaskArtifactUpdateEvent {
161    #[serde(rename = "taskId")]
162    pub task_id: String,
163    #[serde(skip_serializing_if = "Option::is_none", rename = "contextId")]
164    pub context_id: Option<String>,
165    pub artifact: Artifact,
166    pub append: bool,
167    #[serde(rename = "lastChunk")]
168    pub last_chunk: bool,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
172#[serde(untagged)]
173pub enum UpdateEvent {
174    TaskStatusUpdate(TaskStatusUpdateEvent),
175    TaskArtifactUpdate(TaskArtifactUpdateEvent),
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct AgentSkill {
180    pub id: String,
181    pub name: String,
182    pub description: String,
183    pub tags: Vec<String>,
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub examples: Option<Vec<String>>,
186}
187
188impl AgentSkill {
189    pub fn new(id: String, name: String, description: String, tags: Vec<String>) -> Self {
190        Self { id, name, description, tags, examples: None }
191    }
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct AgentCapabilities {
196    pub streaming: bool,
197    #[serde(rename = "pushNotifications")]
198    pub push_notifications: bool,
199    #[serde(rename = "stateTransitionHistory")]
200    pub state_transition_history: bool,
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub extensions: Option<Vec<String>>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct AgentCard {
207    pub name: String,
208    pub description: String,
209    pub url: String,
210    pub version: String,
211    #[serde(rename = "protocolVersion")]
212    pub protocol_version: String,
213    pub capabilities: AgentCapabilities,
214    pub skills: Vec<AgentSkill>,
215}
216
217impl AgentCard {
218    pub fn builder() -> AgentCardBuilder {
219        AgentCardBuilder::default()
220    }
221}
222
223#[derive(Default)]
224pub struct AgentCardBuilder {
225    name: Option<String>,
226    description: Option<String>,
227    url: Option<String>,
228    version: Option<String>,
229    capabilities: Option<AgentCapabilities>,
230    skills: Vec<AgentSkill>,
231}
232
233impl AgentCardBuilder {
234    pub fn name(mut self, name: String) -> Self {
235        self.name = Some(name);
236        self
237    }
238
239    pub fn description(mut self, description: String) -> Self {
240        self.description = Some(description);
241        self
242    }
243
244    pub fn url(mut self, url: String) -> Self {
245        self.url = Some(url);
246        self
247    }
248
249    pub fn version(mut self, version: String) -> Self {
250        self.version = Some(version);
251        self
252    }
253
254    pub fn capabilities(mut self, capabilities: AgentCapabilities) -> Self {
255        self.capabilities = Some(capabilities);
256        self
257    }
258
259    pub fn skills(mut self, skills: Vec<AgentSkill>) -> Self {
260        self.skills = skills;
261        self
262    }
263
264    pub fn build(self) -> AgentCard {
265        AgentCard {
266            name: self.name.unwrap_or_default(),
267            description: self.description.unwrap_or_default(),
268            url: self.url.unwrap_or_default(),
269            version: self.version.unwrap_or_else(|| "1.0.0".to_string()),
270            protocol_version: "0.3.0".to_string(),
271            capabilities: self.capabilities.unwrap_or(AgentCapabilities {
272                streaming: false,
273                push_notifications: false,
274                state_transition_history: false,
275                extensions: None,
276            }),
277            skills: self.skills,
278        }
279    }
280}