gemini_adk_rs/a2a/
event_converter.rs1use super::types::{A2aMessage, A2aPart};
4use crate::events::Event;
5
6pub fn to_a2a_message(event: &Event) -> Option<A2aMessage> {
8 let role = if event.author == "user" {
9 "user"
10 } else {
11 "agent"
12 };
13
14 let mut parts = Vec::new();
15
16 if let Some(content) = &event.content {
18 if !content.is_empty() {
19 parts.push(A2aPart::Text {
20 text: content.clone(),
21 metadata: None,
22 });
23 }
24 }
25
26 if parts.is_empty() {
27 return None;
28 }
29
30 Some(A2aMessage {
31 message_id: event.id.clone(),
32 role: role.to_string(),
33 parts,
34 metadata: None,
35 })
36}
37
38pub fn to_adk_event(
40 event_json: &serde_json::Value,
41 invocation_id: &str,
42 agent_name: &str,
43) -> Option<Event> {
44 let message = event_json.get("message").or(Some(event_json));
46
47 if let Some(message) = message {
48 let role = message
49 .get("role")
50 .and_then(|v| v.as_str())
51 .unwrap_or("agent");
52 let author = if role == "user" {
53 "user".to_string()
54 } else {
55 agent_name.to_string()
56 };
57
58 let content = message
60 .get("parts")
61 .and_then(|p| p.as_array())
62 .map(|parts| {
63 parts
64 .iter()
65 .filter_map(|p| {
66 if p.get("kind").and_then(|k| k.as_str()) == Some("text") {
67 p.get("text").and_then(|t| t.as_str()).map(String::from)
68 } else {
69 None
70 }
71 })
72 .collect::<Vec<_>>()
73 .join("")
74 })
75 .filter(|s| !s.is_empty());
76
77 let mut event = Event::new(author, content);
78 event.invocation_id = invocation_id.to_string();
79 Some(event)
80 } else {
81 None
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn user_event_to_a2a_message() {
91 let event = Event::new("user", Some("Hello, agent!".to_string()));
92 let msg = to_a2a_message(&event).unwrap();
93 assert_eq!(msg.role, "user");
94 assert_eq!(msg.message_id, event.id);
95 assert_eq!(msg.parts.len(), 1);
96 match &msg.parts[0] {
97 A2aPart::Text { text, .. } => assert_eq!(text, "Hello, agent!"),
98 _ => panic!("Expected Text part"),
99 }
100 }
101
102 #[test]
103 fn agent_event_to_a2a_message() {
104 let event = Event::new("my-agent", Some("Here is your answer.".to_string()));
105 let msg = to_a2a_message(&event).unwrap();
106 assert_eq!(msg.role, "agent");
107 assert_eq!(msg.parts.len(), 1);
108 match &msg.parts[0] {
109 A2aPart::Text { text, .. } => assert_eq!(text, "Here is your answer."),
110 _ => panic!("Expected Text part"),
111 }
112 }
113
114 #[test]
115 fn empty_content_returns_none() {
116 let event = Event::new("user", None);
117 assert!(to_a2a_message(&event).is_none());
118 }
119
120 #[test]
121 fn empty_string_content_returns_none() {
122 let event = Event::new("user", Some(String::new()));
123 assert!(to_a2a_message(&event).is_none());
124 }
125
126 #[test]
127 fn to_adk_event_basic() {
128 let json = serde_json::json!({
129 "role": "agent",
130 "parts": [
131 { "kind": "text", "text": "Done!" }
132 ]
133 });
134 let event = to_adk_event(&json, "inv-1", "helper").unwrap();
135 assert_eq!(event.author, "helper");
136 assert_eq!(event.invocation_id, "inv-1");
137 assert_eq!(event.content.as_deref(), Some("Done!"));
138 }
139
140 #[test]
141 fn to_adk_event_user_role() {
142 let json = serde_json::json!({
143 "role": "user",
144 "parts": [
145 { "kind": "text", "text": "Request" }
146 ]
147 });
148 let event = to_adk_event(&json, "inv-2", "agent-x").unwrap();
149 assert_eq!(event.author, "user");
150 assert_eq!(event.content.as_deref(), Some("Request"));
151 }
152
153 #[test]
154 fn to_adk_event_nested_message() {
155 let json = serde_json::json!({
156 "message": {
157 "role": "agent",
158 "parts": [
159 { "kind": "text", "text": "Nested" }
160 ]
161 }
162 });
163 let event = to_adk_event(&json, "inv-3", "bot").unwrap();
164 assert_eq!(event.author, "bot");
165 assert_eq!(event.content.as_deref(), Some("Nested"));
166 }
167
168 #[test]
169 fn to_adk_event_no_text_parts() {
170 let json = serde_json::json!({
171 "role": "agent",
172 "parts": [
173 { "kind": "data", "data": {"key": "val"} }
174 ]
175 });
176 let event = to_adk_event(&json, "inv-4", "bot").unwrap();
177 assert!(event.content.is_none());
179 }
180
181 #[test]
182 fn to_adk_event_multiple_text_parts_concatenated() {
183 let json = serde_json::json!({
184 "role": "agent",
185 "parts": [
186 { "kind": "text", "text": "Hello " },
187 { "kind": "text", "text": "World" }
188 ]
189 });
190 let event = to_adk_event(&json, "inv-5", "bot").unwrap();
191 assert_eq!(event.content.as_deref(), Some("Hello World"));
192 }
193}