Skip to main content

autoagents_core/agent/
error.rs

1#[cfg(not(target_arch = "wasm32"))]
2use ractor::SpawnErr;
3use std::fmt::Debug;
4use thiserror::Error;
5
6/// Error type for RunnableAgent operations
7#[derive(Debug, Error)]
8pub enum RunnableAgentError {
9    /// Error from the agent executor
10    #[error("Agent execution failed: {0}")]
11    ExecutorError(String),
12
13    /// Error during task processing
14    #[error("Task processing failed: {0}")]
15    TaskError(String),
16
17    /// Error when agent is not found
18    #[error("Agent not found: {0}")]
19    AgentNotFound(uuid::Uuid),
20
21    /// Error during agent initialization
22    #[error("Agent initialization failed: {0}")]
23    InitializationError(String),
24
25    /// Error when sending events
26    #[error("Failed to send event: {0}")]
27    EventSendError(String),
28
29    /// Error from agent state operations
30    #[error("Agent state error: {0}")]
31    StateError(String),
32
33    /// Error from agent state operations
34    #[error("Downcast task error")]
35    DowncastTaskError,
36
37    /// Error during serialization/deserialization
38    #[error("Serialization error: {0}")]
39    SerializationError(String),
40
41    /// Error during serialization/deserialization
42    #[error("EmptyTx")]
43    EmptyTx,
44
45    /// Abort the Execution
46    #[error("Abort the execution")]
47    Abort,
48
49    /// Generic error wrapper for any std::error::Error
50    #[error(transparent)]
51    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
52}
53
54impl RunnableAgentError {
55    /// Create an executor error from any error type
56    pub fn executor_error(error: impl std::error::Error) -> Self {
57        Self::ExecutorError(error.to_string())
58    }
59
60    /// Create a task error
61    pub fn task_error(msg: impl Into<String>) -> Self {
62        Self::TaskError(msg.into())
63    }
64
65    /// Create an event send error
66    pub fn event_send_error(error: impl std::error::Error) -> Self {
67        Self::EventSendError(error.to_string())
68    }
69}
70
71/// Specific conversion for tokio mpsc send errors
72#[cfg(not(target_arch = "wasm32"))]
73impl<T> From<tokio::sync::mpsc::error::SendError<T>> for RunnableAgentError
74where
75    T: Debug + Send + 'static,
76{
77    fn from(error: tokio::sync::mpsc::error::SendError<T>) -> Self {
78        Self::EventSendError(error.to_string())
79    }
80}
81
82#[derive(Debug, thiserror::Error)]
83pub enum AgentBuildError {
84    #[error("Build Failure")]
85    BuildFailure(String),
86
87    #[cfg(not(target_arch = "wasm32"))]
88    #[error("SpawnError")]
89    SpawnError(#[from] SpawnErr),
90}
91
92impl AgentBuildError {
93    pub fn build_failure(msg: impl Into<String>) -> Self {
94        Self::BuildFailure(msg.into())
95    }
96}
97
98#[derive(Error, Debug)]
99pub enum AgentResultError {
100    #[error("No output available in result")]
101    NoOutput,
102
103    #[error("Failed to deserialize executor output: {0}")]
104    DeserializationError(#[from] serde_json::Error),
105
106    #[error("Agent output extraction error: {0}")]
107    AgentOutputError(String),
108}
109
110impl AgentResultError {
111    pub fn agent_output_error(msg: impl Into<String>) -> Self {
112        Self::AgentOutputError(msg.into())
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119    use tokio::sync::mpsc;
120
121    #[test]
122    fn test_runnable_agent_error_display() {
123        let error = RunnableAgentError::ExecutorError("Test error".to_string());
124        assert_eq!(error.to_string(), "Agent execution failed: Test error");
125
126        let error = RunnableAgentError::TaskError("Task failed".to_string());
127        assert_eq!(error.to_string(), "Task processing failed: Task failed");
128
129        let error = RunnableAgentError::AgentNotFound(uuid::Uuid::new_v4());
130        assert!(error.to_string().contains("Agent not found:"));
131    }
132
133    #[test]
134    fn test_runnable_agent_error_constructors() {
135        let error = RunnableAgentError::executor_error(std::io::Error::other("IO error"));
136        assert!(matches!(error, RunnableAgentError::ExecutorError(_)));
137
138        let error = RunnableAgentError::task_error("Custom task error");
139        assert!(matches!(error, RunnableAgentError::TaskError(_)));
140
141        let error = RunnableAgentError::event_send_error(std::io::Error::new(
142            std::io::ErrorKind::BrokenPipe,
143            "Send failed",
144        ));
145        assert!(matches!(error, RunnableAgentError::EventSendError(_)));
146    }
147
148    #[tokio::test]
149    async fn test_runnable_agent_error_from_mpsc_send_error() {
150        let (_tx, rx) = mpsc::channel::<String>(1);
151        drop(rx); // Close receiver to cause send error
152
153        let (tx, _rx) = mpsc::channel::<String>(1);
154        drop(tx); // This will cause an error when we try to send
155
156        // Create a send error manually for testing
157        let result: Result<(), mpsc::error::SendError<String>> =
158            Err(mpsc::error::SendError("test message".to_string()));
159
160        if let Err(send_error) = result {
161            let agent_error: RunnableAgentError = send_error.into();
162            assert!(matches!(agent_error, RunnableAgentError::EventSendError(_)));
163        }
164    }
165
166    #[test]
167    fn test_agent_build_error_display() {
168        let error = AgentBuildError::BuildFailure("Failed to build agent".to_string());
169        assert_eq!(error.to_string(), "Build Failure");
170
171        let error = AgentBuildError::build_failure("Custom build failure");
172        assert!(matches!(error, AgentBuildError::BuildFailure(_)));
173    }
174
175    #[test]
176    fn test_agent_result_error_display() {
177        let error = AgentResultError::NoOutput;
178        assert_eq!(error.to_string(), "No output available in result");
179
180        let error = AgentResultError::AgentOutputError("Custom output error".to_string());
181        assert_eq!(
182            error.to_string(),
183            "Agent output extraction error: Custom output error"
184        );
185
186        let error = AgentResultError::agent_output_error("Helper constructor error");
187        assert!(matches!(error, AgentResultError::AgentOutputError(_)));
188    }
189
190    #[test]
191    fn test_agent_result_error_from_json_error() {
192        let invalid_json = "{ invalid json }";
193        let json_error: Result<serde_json::Value, serde_json::Error> =
194            serde_json::from_str(invalid_json);
195
196        if let Err(json_err) = json_error {
197            let agent_error: AgentResultError = json_err.into();
198            assert!(matches!(
199                agent_error,
200                AgentResultError::DeserializationError(_)
201            ));
202        }
203    }
204
205    #[test]
206    fn test_error_debug_formatting() {
207        let error = RunnableAgentError::InitializationError("Init failed".to_string());
208        let debug_str = format!("{error:?}");
209        assert!(debug_str.contains("InitializationError"));
210        assert!(debug_str.contains("Init failed"));
211    }
212}