1use anyhow::Error as AnyhowError;
2use thiserror::Error;
3
4pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Debug, Error)]
9pub enum Error {
10 #[error("Agent configuration error: {0}")]
14 AgentConfig(String),
15
16 #[error("Agent execution error: {0}")]
18 AgentExecution(String),
19
20 #[error("Provider API error: {0}")]
23 ProviderApi(String),
24
25 #[error("Provider authentication error: {0}")]
27 ProviderAuth(String),
28
29 #[error("Provider rate limit exceeded: retry after {retry_after_secs}s")]
31 ProviderRateLimit {
32 retry_after_secs: u64,
34 },
35
36 #[error("Tool not found: {0}")]
39 ToolNotFound(String),
40
41 #[error("Tool execution error: {tool_name} - {message}")]
43 ToolExecution {
44 tool_name: String,
46 message: String,
48 },
49
50 #[error("Tool execution blocked: {tool_name} requires approval but no handler was available")]
52 ToolApprovalRequired {
53 tool_name: String,
55 },
56
57 #[error("Invalid tool arguments for {tool_name}: {message}")]
59 ToolArguments {
60 tool_name: String,
62 message: String,
64 },
65
66 #[error("Message parse error: {0}")]
69 MessageParse(String),
70
71 #[error("Message serialization error: {0}")]
73 MessageSerialize(#[from] serde_json::Error),
74
75 #[error("Stream interrupted: {0}")]
78 StreamInterrupted(String),
79
80 #[error("Stream timeout after {timeout_secs}s")]
82 StreamTimeout {
83 timeout_secs: u64,
85 },
86
87 #[error("Memory storage error: {0}")]
90 MemoryStorage(String),
91
92 #[error("Memory retrieval error: {0}")]
94 MemoryRetrieval(String),
95
96 #[cfg(feature = "trading")]
99 #[error("Strategy configuration error: {0}")]
100 StrategyConfig(String),
101
102 #[cfg(feature = "trading")]
104 #[error("Strategy execution error: {0}")]
105 StrategyExecution(String),
106
107 #[cfg(feature = "trading")]
109 #[error("Condition evaluation error: {0}")]
110 ConditionEvaluation(String),
111
112 #[cfg(feature = "trading")]
115 #[error("Risk check failed: {check_name} - {reason}")]
116 RiskCheckFailed {
117 check_name: String,
119 reason: String,
121 },
122
123 #[cfg(feature = "trading")]
125 #[error("Risk limit exceeded: {limit_type} - current: {current}, max: {max}")]
126 RiskLimitExceeded {
127 limit_type: String,
129 current: String,
131 max: String,
133 },
134
135 #[cfg(feature = "trading")]
138 #[error("Simulation error: {0}")]
139 Simulation(String),
140
141 #[error("Agent coordination error: {0}")]
144 AgentCoordination(String),
145
146 #[error("Agent communication error: {0}")]
148 AgentCommunication(String),
149
150 #[error("HTTP error: {0}")]
153 Http(#[from] reqwest::Error),
154
155 #[error("IO error: {0}")]
158 Io(#[from] std::io::Error),
159
160 #[error("Internal error: {0}")]
163 Internal(String),
164
165 #[error("{0}")]
167 Other(AnyhowError),
168}
169
170impl Error {
171 pub fn agent_config(msg: impl Into<String>) -> Self {
173 Self::AgentConfig(msg.into())
174 }
175
176 pub fn tool_execution(tool_name: impl Into<String>, message: impl Into<String>) -> Self {
178 Self::ToolExecution {
179 tool_name: tool_name.into(),
180 message: message.into(),
181 }
182 }
183
184 #[cfg(feature = "trading")]
186 pub fn risk_check_failed(check_name: impl Into<String>, reason: impl Into<String>) -> Self {
187 Self::RiskCheckFailed {
188 check_name: check_name.into(),
189 reason: reason.into(),
190 }
191 }
192
193 pub fn is_retryable(&self) -> bool {
195 matches!(
196 self,
197 Self::ProviderRateLimit { .. }
198 | Self::StreamInterrupted(_)
199 | Self::StreamTimeout { .. }
200 | Self::Http(_)
201 )
202 }
203}