use std::time::Duration;
#[derive(Debug, thiserror::Error)]
pub enum ProviderError {
#[error("network error: {0}")]
Network(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("rate limited, retry after {retry_after:?}")]
RateLimit {
retry_after: Option<Duration>,
},
#[error("model loading: {0}")]
ModelLoading(String),
#[error("timeout after {0:?}")]
Timeout(Duration),
#[error("service unavailable: {0}")]
ServiceUnavailable(String),
#[error("authentication failed: {0}")]
Authentication(String),
#[error("invalid request: {0}")]
InvalidRequest(String),
#[error("model not found: {0}")]
ModelNotFound(String),
#[error("insufficient resources: {0}")]
InsufficientResources(String),
#[error("stream error: {0}")]
StreamError(String),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl ProviderError {
#[must_use]
pub fn is_retryable(&self) -> bool {
matches!(
self,
Self::Network(_)
| Self::RateLimit { .. }
| Self::ModelLoading(_)
| Self::Timeout(_)
| Self::ServiceUnavailable(_)
)
}
}
#[derive(Debug, thiserror::Error)]
pub enum ToolError {
#[error("tool not found: {0}")]
NotFound(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("execution failed: {0}")]
ExecutionFailed(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("cancelled")]
Cancelled,
#[error("model retry requested: {0}")]
ModelRetry(String),
}
#[derive(Debug, thiserror::Error)]
pub enum ContextError {
#[error("compaction failed: {0}")]
CompactionFailed(String),
#[error("provider error during summarization: {0}")]
Provider(#[from] ProviderError),
}
#[derive(Debug, thiserror::Error)]
pub enum LoopError {
#[error("provider error: {0}")]
Provider(#[from] ProviderError),
#[error("tool error: {0}")]
Tool(#[from] ToolError),
#[error("context error: {0}")]
Context(#[from] ContextError),
#[error("max turns reached ({0})")]
MaxTurns(usize),
#[error("terminated by hook: {0}")]
HookTerminated(String),
#[error("cancelled")]
Cancelled,
#[error("usage limit exceeded: {0}")]
UsageLimitExceeded(String),
}
#[derive(Debug, thiserror::Error)]
pub enum DurableError {
#[error("activity failed: {0}")]
ActivityFailed(String),
#[error("workflow cancelled")]
Cancelled,
#[error("signal timeout")]
SignalTimeout,
#[error("continue as new: {0}")]
ContinueAsNew(String),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
#[derive(Debug, thiserror::Error)]
pub enum McpError {
#[error("connection failed: {0}")]
Connection(String),
#[error("initialization failed: {0}")]
Initialization(String),
#[error("tool call failed: {0}")]
ToolCall(String),
#[error("transport error: {0}")]
Transport(String),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
#[derive(Debug, thiserror::Error)]
pub enum HookError {
#[error("hook failed: {0}")]
Failed(String),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
#[derive(Debug, thiserror::Error)]
pub enum EmbeddingError {
#[error("authentication failed: {0}")]
Authentication(String),
#[error("rate limited, retry after {retry_after:?}")]
RateLimit {
retry_after: Option<std::time::Duration>,
},
#[error("invalid request: {0}")]
InvalidRequest(String),
#[error("network error: {0}")]
Network(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl EmbeddingError {
#[must_use]
pub fn is_retryable(&self) -> bool {
matches!(self, Self::RateLimit { .. } | Self::Network(_))
}
}
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
#[error("not found: {0}")]
NotFound(String),
#[error("serialization error: {0}")]
Serialization(String),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
#[derive(Debug, thiserror::Error)]
pub enum SandboxError {
#[error("execution failed: {0}")]
ExecutionFailed(String),
#[error("sandbox error: {0}")]
SetupFailed(String),
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}