1use thiserror::Error;
30
31#[derive(Error, Debug)]
35pub enum Error {
36 #[error("HTTP request failed: {method} {url} - status {status}: {message}")]
38 HttpRequest {
39 method: String,
41 url: String,
43 status: u16,
45 message: String,
47 },
48
49 #[error("Cache operation '{operation}' failed for key '{key}': {message}")]
51 Cache {
52 operation: String,
54 key: String,
56 message: String,
58 },
59
60 #[error("MCP protocol error in '{context}': {message}")]
62 Mcp {
63 context: String,
65 message: String,
67 },
68
69 #[error("Initialization failed for '{component}': {message}")]
71 Initialization {
72 component: String,
74 message: String,
76 },
77
78 #[error("Configuration error for '{field}': {message}")]
80 Config {
81 field: String,
83 message: String,
85 },
86
87 #[error("Parse failed for '{input}'{position}: {message}")]
89 Parse {
90 input: String,
92 position: String,
94 message: String,
96 },
97
98 #[error("Authentication failed for '{provider}': {message}")]
100 Auth {
101 provider: String,
103 message: String,
105 },
106
107 #[error("IO error: {0}")]
109 Io(#[from] std::io::Error),
110
111 #[error("JSON error: {0}")]
113 Json(#[from] serde_json::Error),
114
115 #[error("URL parse error: {0}")]
117 Url(#[from] url::ParseError),
118
119 #[error("HTTP client error: {0}")]
121 Reqwest(#[from] reqwest::Error),
122
123 #[error("Unknown error: {0}")]
125 Other(String),
126}
127
128pub type Result<T> = std::result::Result<T, Error>;
132
133impl Error {
134 #[must_use]
143 pub fn http_request(
144 method: impl Into<String>,
145 url: impl Into<String>,
146 status: u16,
147 message: impl Into<String>,
148 ) -> Self {
149 Self::HttpRequest {
150 method: method.into(),
151 url: url.into(),
152 status,
153 message: message.into(),
154 }
155 }
156
157 #[must_use]
165 pub fn cache(
166 operation: impl Into<String>,
167 key: Option<String>,
168 message: impl Into<String>,
169 ) -> Self {
170 Self::Cache {
171 operation: operation.into(),
172 key: key.unwrap_or_else(|| "N/A".to_string()),
173 message: message.into(),
174 }
175 }
176
177 #[must_use]
184 pub fn mcp(context: impl Into<String>, message: impl Into<String>) -> Self {
185 Self::Mcp {
186 context: context.into(),
187 message: message.into(),
188 }
189 }
190
191 #[must_use]
198 pub fn initialization(component: impl Into<String>, message: impl Into<String>) -> Self {
199 Self::Initialization {
200 component: component.into(),
201 message: message.into(),
202 }
203 }
204
205 #[must_use]
212 pub fn config(field: impl Into<String>, message: impl Into<String>) -> Self {
213 Self::Config {
214 field: field.into(),
215 message: message.into(),
216 }
217 }
218
219 #[must_use]
227 pub fn parse(
228 input: impl Into<String>,
229 position: Option<usize>,
230 message: impl Into<String>,
231 ) -> Self {
232 Self::Parse {
233 input: input.into(),
234 position: position.map_or_else(String::new, |p| format!(" at position {p}")),
235 message: message.into(),
236 }
237 }
238
239 #[must_use]
246 pub fn auth(provider: impl Into<String>, message: impl Into<String>) -> Self {
247 Self::Auth {
248 provider: provider.into(),
249 message: message.into(),
250 }
251 }
252}
253
254impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
255 fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
256 Error::Other(err.to_string())
257 }
258}
259
260impl From<anyhow::Error> for Error {
261 fn from(err: anyhow::Error) -> Self {
262 Error::Other(err.to_string())
263 }
264}