autoagents_core/
protocol.rs

1use crate::agent::task::Task;
2use crate::tool::ToolCallResult;
3use autoagents_llm::chat::StreamChoice;
4use serde::{Deserialize, Serialize};
5use std::any::{Any, TypeId};
6use std::fmt::Debug;
7use std::sync::Arc;
8use uuid::Uuid;
9
10/// Submission IDs are used to track actor tasks
11pub type SubmissionId = Uuid;
12
13/// Agent IDs are used to identify actors
14pub type ActorID = Uuid;
15
16/// Session IDs are used to identify sessions
17pub type RuntimeID = Uuid;
18
19/// Event IDs are used to correlate events with their responses
20pub type EventId = Uuid;
21
22/// Protocol events represent the various events that can occur during actor execution
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub enum Event {
25    // /// A new task has been submitted to an agent
26    NewTask {
27        actor_id: ActorID,
28        task: Task,
29    },
30
31    /// A task has started execution
32    TaskStarted {
33        sub_id: SubmissionId,
34        actor_id: ActorID,
35        task_description: String,
36    },
37
38    /// A task has been completed
39    TaskComplete {
40        sub_id: SubmissionId,
41        result: String,
42    },
43
44    /// A task encountered an error
45    TaskError {
46        sub_id: SubmissionId,
47        error: String,
48    },
49
50    #[serde(skip)]
51    PublishMessage {
52        topic_name: String,
53        topic_type: TypeId,
54        message: Arc<dyn Any + Send + Sync>,
55    },
56
57    SendMessage {
58        message: String,
59        actor_id: ActorID,
60    },
61
62    /// Tool call requested (with ID)
63    ToolCallRequested {
64        id: String,
65        tool_name: String,
66        arguments: String,
67    },
68
69    /// Tool call completed (with ID and result)
70    ToolCallCompleted {
71        id: String,
72        tool_name: String,
73        result: serde_json::Value,
74    },
75
76    /// Tool call has failed
77    ToolCallFailed {
78        id: String,
79        tool_name: String,
80        error: String,
81    },
82
83    /// A turn has started
84    TurnStarted {
85        turn_number: usize,
86        max_turns: usize,
87    },
88
89    /// A turn has completed
90    TurnCompleted {
91        turn_number: usize,
92        final_turn: bool,
93    },
94
95    /// Streaming chunk from agent
96    StreamChunk {
97        sub_id: SubmissionId,
98        chunk: StreamChoice,
99    },
100
101    /// Streaming tool call chunk
102    StreamToolCall {
103        sub_id: SubmissionId,
104        tool_call: serde_json::Value,
105    },
106
107    /// Streaming completed
108    StreamComplete {
109        sub_id: SubmissionId,
110    },
111}
112
113/// Internal events that are processed within the runtime
114#[derive(Debug)]
115pub enum InternalEvent {
116    /// Process a protocol event
117    ProtocolEvent(Event),
118    /// Shutdown signal
119    Shutdown,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub enum StreamingTurnResult {
124    Complete(String),
125    ToolCallsProcessed(Vec<ToolCallResult>),
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131    use serde_json::json;
132
133    #[test]
134    fn test_event_serialization_new_task() {
135        let _ = Uuid::new_v4();
136        let event = Event::NewTask {
137            actor_id: Default::default(),
138            task: Task::new(String::from("test")),
139        };
140
141        //Check if serialization and deserilization works properly
142        let serialized = serde_json::to_string(&event).unwrap();
143        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
144
145        match deserialized {
146            Event::NewTask { task, .. } => {
147                assert_eq!(task.prompt, "test");
148            }
149            _ => panic!("Expected NewTask variant"),
150        }
151    }
152
153    #[test]
154    fn test_event_serialization_task_started() {
155        let event = Event::TaskStarted {
156            sub_id: Uuid::new_v4(),
157            actor_id: Default::default(),
158            task_description: "Started task".to_string(),
159        };
160
161        let serialized = serde_json::to_string(&event).unwrap();
162        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
163
164        match deserialized {
165            Event::TaskStarted {
166                task_description, ..
167            } => {
168                assert_eq!(task_description, "Started task");
169            }
170            _ => panic!("Expected TaskStarted variant"),
171        }
172    }
173
174    #[test]
175    fn test_event_serialization_tool_calls() {
176        let tool_call_requested = Event::ToolCallRequested {
177            id: "call_123".to_string(),
178            tool_name: "test_tool".to_string(),
179            arguments: "{\"param\": \"value\"}".to_string(),
180        };
181
182        let serialized = serde_json::to_string(&tool_call_requested).unwrap();
183        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
184
185        match deserialized {
186            Event::ToolCallRequested {
187                id,
188                tool_name,
189                arguments,
190            } => {
191                assert_eq!(id, "call_123");
192                assert_eq!(tool_name, "test_tool");
193                assert_eq!(arguments, "{\"param\": \"value\"}");
194            }
195            _ => panic!("Expected ToolCallRequested variant"),
196        }
197    }
198
199    #[test]
200    fn test_event_serialization_tool_call_completed() {
201        let result = json!({"output": "tool result"});
202        let event = Event::ToolCallCompleted {
203            id: "call_456".to_string(),
204            tool_name: "completed_tool".to_string(),
205            result: result.clone(),
206        };
207
208        let serialized = serde_json::to_string(&event).unwrap();
209        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
210
211        match deserialized {
212            Event::ToolCallCompleted {
213                id,
214                tool_name,
215                result: res,
216            } => {
217                assert_eq!(id, "call_456");
218                assert_eq!(tool_name, "completed_tool");
219                assert_eq!(res, result);
220            }
221            _ => panic!("Expected ToolCallCompleted variant"),
222        }
223    }
224
225    #[test]
226    fn test_event_serialization_tool_call_failed() {
227        let event = Event::ToolCallFailed {
228            id: "call_789".to_string(),
229            tool_name: "failed_tool".to_string(),
230            error: "Tool execution failed".to_string(),
231        };
232
233        let serialized = serde_json::to_string(&event).unwrap();
234        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
235
236        match deserialized {
237            Event::ToolCallFailed {
238                id,
239                tool_name,
240                error,
241            } => {
242                assert_eq!(id, "call_789");
243                assert_eq!(tool_name, "failed_tool");
244                assert_eq!(error, "Tool execution failed");
245            }
246            _ => panic!("Expected ToolCallFailed variant"),
247        }
248    }
249
250    #[test]
251    fn test_event_serialization_turn_events() {
252        let turn_started = Event::TurnStarted {
253            turn_number: 1,
254            max_turns: 10,
255        };
256
257        let serialized = serde_json::to_string(&turn_started).unwrap();
258        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
259
260        match deserialized {
261            Event::TurnStarted {
262                turn_number,
263                max_turns,
264            } => {
265                assert_eq!(turn_number, 1);
266                assert_eq!(max_turns, 10);
267            }
268            _ => panic!("Expected TurnStarted variant"),
269        }
270
271        let turn_completed = Event::TurnCompleted {
272            turn_number: 1,
273            final_turn: false,
274        };
275
276        let serialized = serde_json::to_string(&turn_completed).unwrap();
277        let deserialized: Event = serde_json::from_str(&serialized).unwrap();
278
279        match deserialized {
280            Event::TurnCompleted {
281                turn_number,
282                final_turn,
283            } => {
284                assert_eq!(turn_number, 1);
285                assert!(!final_turn);
286            }
287            _ => panic!("Expected TurnCompleted variant"),
288        }
289    }
290
291    #[test]
292    fn test_uuid_types() {
293        let submission_id: SubmissionId = Uuid::new_v4();
294        let agent_id: ActorID = Uuid::new_v4();
295        let runtime_id: RuntimeID = Uuid::new_v4();
296        let event_id: EventId = Uuid::new_v4();
297
298        // Test that all UUID types can be used interchangeably
299        assert_ne!(submission_id, agent_id);
300        assert_ne!(runtime_id, event_id);
301    }
302}