1pub mod broker;
36pub mod schema;
37pub mod storage;
38pub mod task;
39pub mod worker;
40
41#[cfg(feature = "server")]
42pub mod server;
43
44pub use broker::{Broker, BrokerError, InMemoryBroker};
45pub use schema::*;
46pub use storage::{InMemoryStorage, Storage, StorageError};
47pub use task::{Task, TaskError, TaskResult, TaskStatus};
48pub use worker::{AgentWorker, WorkerHandle};
49
50pub use serdes_ai_agent::Agent;
52
53use std::sync::Arc;
54
55pub fn agent_to_a2a<Deps, Output>(
75 agent: Agent<Deps, Output>,
76 config: A2AConfig,
77) -> A2AServer<Deps, Output>
78where
79 Deps: Send + Sync + 'static,
80 Output: Send + Sync + 'static,
81{
82 A2AServer::new(agent, config)
83}
84
85pub struct A2AServer<Deps, Output> {
92 agent: Arc<Agent<Deps, Output>>,
93 config: A2AConfig,
94 storage: Arc<dyn Storage>,
95 broker: Arc<dyn Broker>,
96}
97
98impl<Deps, Output> A2AServer<Deps, Output>
99where
100 Deps: Send + Sync + 'static,
101 Output: Send + Sync + 'static,
102{
103 pub fn new(agent: Agent<Deps, Output>, config: A2AConfig) -> Self {
105 Self {
106 agent: Arc::new(agent),
107 config,
108 storage: Arc::new(InMemoryStorage::new()),
109 broker: Arc::new(InMemoryBroker::new()),
110 }
111 }
112
113 pub fn with_storage(mut self, storage: impl Storage + 'static) -> Self {
115 self.storage = Arc::new(storage);
116 self
117 }
118
119 pub fn with_broker(mut self, broker: impl Broker + 'static) -> Self {
121 self.broker = Arc::new(broker);
122 self
123 }
124
125 pub fn agent_card(&self) -> AgentCard {
127 self.config.to_agent_card()
128 }
129
130 pub fn agent(&self) -> &Agent<Deps, Output> {
132 &self.agent
133 }
134
135 pub fn storage(&self) -> &dyn Storage {
137 self.storage.as_ref()
138 }
139
140 pub fn broker(&self) -> &dyn Broker {
142 self.broker.as_ref()
143 }
144
145 pub fn storage_arc(&self) -> Arc<dyn Storage> {
147 Arc::clone(&self.storage)
148 }
149
150 pub fn broker_arc(&self) -> Arc<dyn Broker> {
152 Arc::clone(&self.broker)
153 }
154}
155
156impl<Deps, Output> std::fmt::Debug for A2AServer<Deps, Output> {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 f.debug_struct("A2AServer")
159 .field("config", &self.config)
160 .finish_non_exhaustive()
161 }
162}
163
164pub mod prelude {
166 pub use crate::{
167 agent_to_a2a, A2AConfig, A2AServer, AgentCard, Artifact, Broker, InMemoryBroker,
168 InMemoryStorage, Message, MessageRole, Part, Skill, Storage, Task, TaskIdParams,
169 TaskResult, TaskSendParams, TaskStatus,
170 };
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_config_builder() {
179 let config = A2AConfig::new()
180 .name("test-agent")
181 .url("http://localhost:8000")
182 .description("A test agent");
183
184 assert_eq!(config.name, "test-agent");
185 assert_eq!(config.url, "http://localhost:8000");
186 assert_eq!(config.description, Some("A test agent".to_string()));
187 }
188
189 #[test]
190 fn test_agent_card_creation() {
191 let config = A2AConfig::new()
192 .name("my-agent")
193 .url("http://localhost:9000")
194 .skill(Skill {
195 id: "chat".to_string(),
196 name: "Chat".to_string(),
197 description: Some("General conversation".to_string()),
198 tags: vec!["general".to_string()],
199 });
200
201 let card = config.to_agent_card();
202 assert_eq!(card.name, "my-agent");
203 assert_eq!(card.url, "http://localhost:9000");
204 assert_eq!(card.skills.len(), 1);
205 assert_eq!(card.skills[0].id, "chat");
206 }
207}