1use a2a_types::{Artifact as A2AArtifact, Message as A2AMessage, Part as A2APart, Role as A2ARole};
4use uuid::Uuid;
5
6use crate::agent::Artifact;
7use crate::models::{Content, ContentPart, Role};
8
9pub fn create_a2a_message(
11 context_id: Option<&str>,
12 task_id: Option<&str>,
13 role: Role,
14 content: Content,
15) -> A2AMessage {
16 let parts: Vec<A2APart> = content
17 .into_parts()
18 .into_iter()
19 .filter_map(ContentPart::into_a2a_part)
20 .collect();
21
22 let proto_role = match role {
23 Role::User => A2ARole::User,
24 Role::Assistant | Role::System | Role::Tool => A2ARole::Agent,
25 };
26
27 A2AMessage {
28 message_id: Uuid::new_v4().to_string(),
29 role: proto_role as i32,
30 context_id: context_id.unwrap_or_default().to_string(),
31 task_id: task_id.unwrap_or_default().to_string(),
32 parts,
33 reference_task_ids: Vec::new(),
34 extensions: Vec::new(),
35 metadata: None,
36 }
37}
38
39pub fn artifact_to_a2a(artifact: &Artifact) -> A2AArtifact {
41 let parts: Vec<A2APart> = artifact
42 .content()
43 .clone()
44 .into_parts()
45 .into_iter()
46 .filter_map(ContentPart::into_a2a_part)
47 .collect();
48
49 A2AArtifact {
50 artifact_id: artifact.name().to_string(),
51 parts,
52 name: artifact.name().to_string(),
53 description: String::new(),
54 extensions: Vec::new(),
55 metadata: None,
56 }
57}
58
59pub fn artifacts_to_a2a(artifacts: &[Artifact]) -> Vec<A2AArtifact> {
61 artifacts.iter().map(artifact_to_a2a).collect()
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::agent::Artifact;
68
69 #[test]
70 fn create_a2a_message_maps_roles_and_parts() {
71 let content = Content::from_text("Hello");
72 let message =
73 create_a2a_message(Some("ctx-1"), Some("task-2"), Role::User, content.clone());
74
75 assert_eq!(message.context_id, "ctx-1");
76 assert_eq!(message.task_id, "task-2");
77 assert_eq!(message.role, A2ARole::User as i32);
78 assert_eq!(message.parts.len(), content.parts().len());
79 }
80
81 #[test]
82 fn artifact_conversion_preserves_name_and_parts() {
83 let artifact = Artifact::from_text("notes.txt", "example");
84 let converted = artifact_to_a2a(&artifact);
85 assert_eq!(converted.artifact_id, "notes.txt");
86 assert_eq!(converted.name, "notes.txt");
87 assert_eq!(converted.parts.len(), artifact.content().parts().len());
88
89 let multiple = artifacts_to_a2a(&[artifact.clone(), artifact]);
90 assert_eq!(multiple.len(), 2);
91 }
92}