use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("PDF processing error: {0}")]
Pdf(String),
#[error("Document not found: {0}")]
DocumentNotFound(String),
#[error("Chunk not found: {0}")]
ChunkNotFound(String),
#[error("Embedding error: {0}")]
Embedding(String),
#[error("Indexing error: {0}")]
Indexing(String),
#[error("Retrieval error: {0}")]
Retrieval(String),
#[error("Storage error: {0}")]
Storage(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("Network error: {0}")]
Network(String),
#[error("Daemon error: {0}")]
Daemon(String),
#[error("Schema validation error: {0}")]
Validation(String),
#[error("{resource} not found")]
NotFound {
resource: String,
},
#[error("I/O error: {message}")]
IoMessage {
message: String,
},
#[error("Parse error: {message}")]
Parse {
message: String,
},
#[error("Qdrant error: {0}")]
Qdrant(String),
#[error("Tantivy error: {0}")]
Tantivy(String),
#[cfg(feature = "arf")]
#[error("ARF error: {0}")]
ArfError(String),
#[error("Config library error: {0}")]
ConfigError(String),
#[cfg(feature = "memory")]
#[error("Memory error: {0}")]
Memory(String),
#[error("{context}: {source}")]
WithContext {
context: String,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("MCP error: {0}")]
Mcp(String),
#[error("M2 execution error: {0}")]
M2ExecutionError(String),
#[error("M2 rate limit exceeded")]
RateLimitExceeded,
#[error("M2 budget exceeded: {0} > {1}")]
BudgetExceeded(f64, f64),
#[error("M2 protocol validation error: {0}")]
M2ProtocolValidation(String),
#[error("M2 constraint violation: {0}")]
M2ConstraintViolation(String),
#[error("M2 framework incompatibility: {0}")]
M2FrameworkIncompatibility(String),
#[error("Resource exhausted: {0}")]
ResourceExhausted(String),
#[error("Template not found: {0}")]
TemplateNotFound(String),
#[error("Code intelligence error: {0}")]
CodeIntelligence(String),
#[error("M2 integration error: {0}")]
M2IntegrationError(String),
#[error("Timeout error: {0}")]
Timeout(String),
#[error("Dependency not met: {0}")]
DependencyNotMet(String),
#[error("Protocol generation error: {0}")]
ProtocolGenerationError(String),
#[error("ThinkTool execution error: {0}")]
ThinkToolExecutionError(String),
#[error("Rate limit error: {0}")]
RateLimit(String),
#[error("Authentication error: {0}")]
Authentication(String),
#[error("Authorization error: {0}")]
Authorization(String),
}
impl Error {
pub fn io(msg: impl Into<String>) -> Self {
Self::Io(std::io::Error::other(msg.into()))
}
pub fn parse(msg: impl Into<String>) -> Self {
let io_err = std::io::Error::new(std::io::ErrorKind::InvalidData, msg.into());
Self::Json(serde_json::Error::io(io_err))
}
pub fn pdf(msg: impl Into<String>) -> Self {
Self::Pdf(msg.into())
}
pub fn embedding(msg: impl Into<String>) -> Self {
Self::Embedding(msg.into())
}
pub fn indexing(msg: impl Into<String>) -> Self {
Self::Indexing(msg.into())
}
pub fn retrieval(msg: impl Into<String>) -> Self {
Self::Retrieval(msg.into())
}
pub fn query(msg: impl Into<String>) -> Self {
Self::Retrieval(msg.into())
}
pub fn storage(msg: impl Into<String>) -> Self {
Self::Storage(msg.into())
}
pub fn config(msg: impl Into<String>) -> Self {
Self::Config(msg.into())
}
pub fn network(msg: impl Into<String>) -> Self {
Self::Network(msg.into())
}
pub fn daemon(msg: impl Into<String>) -> Self {
Self::Daemon(msg.into())
}
pub fn validation(msg: impl Into<String>) -> Self {
Self::Validation(msg.into())
}
#[cfg(feature = "arf")]
pub fn arf_error(msg: impl Into<String>) -> Self {
Self::ArfError(msg.into())
}
pub fn with_context<E>(context: impl Into<String>, source: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Self::WithContext {
context: context.into(),
source: Box::new(source),
}
}
}
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Self::Network(err.to_string())
}
}
#[cfg(feature = "arf")]
impl From<config::ConfigError> for Error {
fn from(err: config::ConfigError) -> Self {
Self::ConfigError(err.to_string())
}
}
#[cfg(feature = "arf")]
impl From<sled::Error> for Error {
fn from(err: sled::Error) -> Self {
Self::Storage(err.to_string())
}
}
#[cfg(feature = "arf")]
impl From<anyhow::Error> for Error {
fn from(err: anyhow::Error) -> Self {
Self::arf_error(err.to_string())
}
}
#[cfg(feature = "arf")]
impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
fn from(err: tokio::sync::mpsc::error::SendError<T>) -> Self {
Self::arf_error(err.to_string())
}
}
#[cfg(feature = "memory")]
impl From<reasonkit_mem::MemError> for Error {
fn from(err: reasonkit_mem::MemError) -> Self {
Error::Memory(err.to_string())
}
}
pub trait ResultExt<T> {
fn context(self, context: impl Into<String>) -> Result<T>;
}
impl<T, E> ResultExt<T> for std::result::Result<T, E>
where
E: std::error::Error + Send + Sync + 'static,
{
fn context(self, context: impl Into<String>) -> Result<T> {
self.map_err(|e| Error::with_context(context, e))
}
}