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