use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Agent error: {0}")]
Agent(String),
#[error("Tool error: {0}")]
Tool(String),
#[error("LLM error: {0}")]
Llm(String),
#[error("Memory error: {0}")]
Memory(String),
#[error("Workflow error: {0}")]
Workflow(String),
#[error("Config error: {0}")]
Config(String),
#[error("Embedding error: {0}")]
Embedding(String),
#[error("Serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("YAML error: {0}")]
Yaml(#[from] serde_yaml::Error),
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("{context}: {source}")]
WithContext {
context: String,
#[source]
source: Box<Error>,
},
}
impl Error {
pub fn agent(msg: impl Into<String>) -> Self {
Self::Agent(msg.into())
}
pub fn tool(msg: impl Into<String>) -> Self {
Self::Tool(msg.into())
}
pub fn llm(msg: impl Into<String>) -> Self {
Self::Llm(msg.into())
}
pub fn memory(msg: impl Into<String>) -> Self {
Self::Memory(msg.into())
}
pub fn workflow(msg: impl Into<String>) -> Self {
Self::Workflow(msg.into())
}
pub fn config(msg: impl Into<String>) -> Self {
Self::Config(msg.into())
}
pub fn io(msg: impl Into<String>) -> Self {
Self::Io(std::io::Error::other(msg.into()))
}
pub fn handoff(msg: impl Into<String>) -> Self {
Self::Workflow(format!("Handoff error: {}", msg.into()))
}
pub fn with_context(self, context: impl Into<String>) -> Self {
Self::WithContext {
context: context.into(),
source: Box::new(self),
}
}
}
pub trait ResultExt<T> {
fn context(self, context: impl Into<String>) -> Result<T>;
}
impl<T> ResultExt<T> for Result<T> {
fn context(self, context: impl Into<String>) -> Result<T> {
self.map_err(|e| e.with_context(context))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::agent("test error");
assert_eq!(err.to_string(), "Agent error: test error");
}
#[test]
fn test_error_with_context() {
let err = Error::tool("failed to execute").with_context("search_web");
assert!(err.to_string().contains("search_web"));
}
}