tool_useful/
error.rs

1//! Error types for tool execution.
2
3use thiserror::Error;
4
5/// Result type for tool operations
6pub type ToolResult<T> = Result<T, ToolError>;
7
8/// Errors that can occur during tool execution
9#[derive(Error, Debug)]
10pub enum ToolError {
11    #[error("Tool execution failed: {0}")]
12    ExecutionFailed(String),
13
14    #[error("Invalid arguments: {0}")]
15    InvalidArguments(String),
16
17    #[error("Tool execution timed out after {0:?}")]
18    Timeout(std::time::Duration),
19
20    #[error("Tool execution was cancelled")]
21    Cancelled,
22
23    #[error("Network error: {0}")]
24    Network(String),
25
26    #[error("IO error: {0}")]
27    Io(#[from] std::io::Error),
28
29    #[error("Serialization error: {0}")]
30    Serialization(#[from] serde_json::Error),
31
32    #[error("Validation error in field '{field}': {reason}")]
33    ValidationError { field: String, reason: String },
34
35    #[error("Resource limit exceeded: {0}")]
36    ResourceLimitExceeded(String),
37
38    #[error("Permission denied: {0}")]
39    PermissionDenied(String),
40
41    #[error("Tool not found: {0}")]
42    ToolNotFound(String),
43
44    #[error("Custom error: {0}")]
45    Custom(Box<dyn std::error::Error + Send + Sync>),
46}
47
48impl ToolError {
49    pub fn execution_failed(msg: impl Into<String>) -> Self {
50        ToolError::ExecutionFailed(msg.into())
51    }
52
53    pub fn invalid_arguments(msg: impl Into<String>) -> Self {
54        ToolError::InvalidArguments(msg.into())
55    }
56
57    pub fn network(msg: impl Into<String>) -> Self {
58        ToolError::Network(msg.into())
59    }
60
61    pub fn validation(field: impl Into<String>, reason: impl Into<String>) -> Self {
62        ToolError::ValidationError {
63            field: field.into(),
64            reason: reason.into(),
65        }
66    }
67
68    pub fn resource_limit(msg: impl Into<String>) -> Self {
69        ToolError::ResourceLimitExceeded(msg.into())
70    }
71
72    pub fn permission_denied(msg: impl Into<String>) -> Self {
73        ToolError::PermissionDenied(msg.into())
74    }
75
76    pub fn tool_not_found(name: impl Into<String>) -> Self {
77        ToolError::ToolNotFound(name.into())
78    }
79
80    pub fn custom(err: impl std::error::Error + Send + Sync + 'static) -> Self {
81        ToolError::Custom(Box::new(err))
82    }
83
84    pub fn kind(&self) -> ErrorKind {
85        match self {
86            ToolError::ExecutionFailed(_) => ErrorKind::Execution,
87            ToolError::InvalidArguments(_) | ToolError::ValidationError { .. } => {
88                ErrorKind::Validation
89            }
90            ToolError::Timeout(_) => ErrorKind::Timeout,
91            ToolError::Network(_) => ErrorKind::Network,
92            ToolError::PermissionDenied(_) => ErrorKind::Permission,
93            ToolError::ResourceLimitExceeded(_) => ErrorKind::Resource,
94            _ => ErrorKind::Other,
95        }
96    }
97
98    pub fn is_retryable(&self) -> bool {
99        matches!(
100            self.kind(),
101            ErrorKind::Network | ErrorKind::Timeout | ErrorKind::Resource
102        )
103    }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum ErrorKind {
108    Execution,
109    Validation,
110    Network,
111    Timeout,
112    Permission,
113    Resource,
114    Other,
115}