1use gemini_genai_rs::session::SessionError;
4
5pub type AgentResult<T> = std::result::Result<T, AgentError>;
10
11#[derive(Debug, thiserror::Error)]
13pub enum AgentError {
14 #[error("Session error: {0}")]
16 Session(#[from] SessionError),
17
18 #[error("Tool error: {0}")]
20 Tool(#[from] ToolError),
21
22 #[error("Unknown agent: {0}")]
24 UnknownAgent(String),
25
26 #[error("Transfer requested to agent: {0}")]
28 TransferRequested(String),
29
30 #[error("Agent transfer failed: {0}")]
32 TransferFailed(String),
33
34 #[error("Agent session closed")]
36 SessionClosed,
37
38 #[error("Timeout")]
40 Timeout,
41
42 #[error("Configuration error: {0}")]
44 Config(String),
45
46 #[error("{0}")]
48 Other(String),
49}
50
51#[derive(Debug, Clone, thiserror::Error)]
53pub enum ToolError {
54 #[error("Tool execution failed: {0}")]
56 ExecutionFailed(String),
57
58 #[error("Tool not found: {0}")]
60 NotFound(String),
61
62 #[error("Invalid arguments: {0}")]
64 InvalidArgs(String),
65
66 #[error("Tool cancelled")]
68 Cancelled,
69
70 #[error("Tool execution timed out after {0:?}")]
72 Timeout(std::time::Duration),
73
74 #[error("{0}")]
76 Other(String),
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use std::time::Duration;
83
84 #[test]
85 fn agent_error_display_messages() {
86 let err = AgentError::UnknownAgent("foo".into());
87 assert_eq!(err.to_string(), "Unknown agent: foo");
88
89 let err = AgentError::TransferRequested("bar".into());
90 assert_eq!(err.to_string(), "Transfer requested to agent: bar");
91
92 let err = AgentError::TransferFailed("baz".into());
93 assert_eq!(err.to_string(), "Agent transfer failed: baz");
94
95 let err = AgentError::SessionClosed;
96 assert_eq!(err.to_string(), "Agent session closed");
97
98 let err = AgentError::Timeout;
99 assert_eq!(err.to_string(), "Timeout");
100
101 let err = AgentError::Config("bad value".into());
102 assert_eq!(err.to_string(), "Configuration error: bad value");
103
104 let err = AgentError::Other("something".into());
105 assert_eq!(err.to_string(), "something");
106 }
107
108 #[test]
109 fn agent_error_from_session_error() {
110 use gemini_genai_rs::session::SessionError;
111 use gemini_genai_rs::session::WebSocketError;
112
113 let ws_err = SessionError::WebSocket(WebSocketError::ConnectionRefused("refused".into()));
114 let agent_err: AgentError = ws_err.into();
115 let msg = agent_err.to_string();
116 assert!(msg.contains("Session error"), "got: {msg}");
117 }
118
119 #[test]
120 fn agent_error_from_tool_error() {
121 let tool_err = ToolError::NotFound("my_tool".into());
122 let agent_err: AgentError = tool_err.into();
123 let msg = agent_err.to_string();
124 assert!(msg.contains("Tool error"), "got: {msg}");
125 assert!(msg.contains("my_tool"), "got: {msg}");
126 }
127
128 #[test]
129 fn tool_error_display_messages() {
130 assert_eq!(
131 ToolError::ExecutionFailed("boom".into()).to_string(),
132 "Tool execution failed: boom"
133 );
134 assert_eq!(
135 ToolError::NotFound("x".into()).to_string(),
136 "Tool not found: x"
137 );
138 assert_eq!(
139 ToolError::InvalidArgs("bad".into()).to_string(),
140 "Invalid arguments: bad"
141 );
142 assert_eq!(ToolError::Cancelled.to_string(), "Tool cancelled");
143 assert_eq!(ToolError::Other("misc".into()).to_string(), "misc");
144 }
145
146 #[test]
147 fn tool_error_timeout_shows_duration() {
148 let err = ToolError::Timeout(Duration::from_secs(5));
149 let msg = err.to_string();
150 assert!(msg.contains("5s"), "got: {msg}");
151 assert!(msg.contains("timed out"), "got: {msg}");
152 }
153
154 #[test]
155 fn tool_error_is_clone() {
156 let err = ToolError::ExecutionFailed("test".into());
157 let cloned = err.clone();
158 assert_eq!(err.to_string(), cloned.to_string());
159
160 let err2 = ToolError::Timeout(Duration::from_millis(100));
161 let cloned2 = err2.clone();
162 assert_eq!(err2.to_string(), cloned2.to_string());
163 }
164}