use std::time::Duration;
use crate::value_objects::RateLimit;
#[derive(Debug, Clone, thiserror::Error)]
pub enum ToolError {
#[error("tool '{name}' not found")]
NotFound { name: String },
#[error("multiple tools named '{name}' are registered")]
MultipleFound { name: String },
#[error("invalid arguments for tool '{name}': {message}")]
InvalidArguments { name: String, message: String },
#[error("tool '{name}' failed: {message}")]
Runtime { name: String, message: String },
#[error("tool '{name}' requires approval but wasn't approved")]
ApprovalDenied { name: String },
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("{provider} rate limited{}", .retry_after.map(|d| format!(", retry after {d:?}")).unwrap_or_default())]
RateLimited {
provider: String,
retry_after: Option<Duration>,
limits: Vec<RateLimit>,
},
#[error("{provider} is overloaded")]
Overloaded { provider: String },
#[error("{provider} request too large: {details}")]
RequestTooLarge { provider: String, details: String },
#[error("failed to decode stream event from {provider}: {message}")]
StreamDecode { provider: String, message: String },
#[error("failed to decode structured output from {provider}: {message}")]
StructuredDecode {
provider: String,
message: String,
context: Box<StructuredDecodeContext>,
},
#[error("failed to decode response from {provider}: {message}")]
Decode { provider: String, message: String },
#[error("{provider} does not support {capability}")]
Unsupported {
provider: String,
capability: &'static str,
},
#[error("unknown provider '{0}'")]
UnknownProvider(String),
#[error("{provider} error ({status}): {message}")]
Provider {
provider: String,
status: u16,
kind: Option<String>,
message: String,
},
#[error("missing configuration: {0}")]
Config(String),
#[error(transparent)]
Tool(#[from] ToolError),
#[error(transparent)]
Json(#[from] serde_json::Error),
#[cfg(feature = "http")]
#[error(transparent)]
Http(#[from] reqwest::Error),
#[cfg(feature = "http")]
#[error("http middleware error: {0}")]
Middleware(#[from] reqwest_middleware::Error),
#[cfg(feature = "mcp")]
#[error("mcp error: {message}")]
Mcp { message: String },
#[error("{message}")]
Store { message: String },
}
#[derive(Debug, Clone)]
pub struct StructuredDecodeContext {
pub raw: String,
pub finish_reason: crate::value_objects::FinishReason,
pub usage: crate::value_objects::Usage,
pub meta: crate::value_objects::Meta,
}
impl Error {
pub fn unsupported(provider: impl Into<String>, capability: &'static str) -> Self {
Error::Unsupported {
provider: provider.into(),
capability,
}
}
}