1use std::borrow::Cow;
4
5use thiserror::Error;
6
7pub type ToolResult<T> = Result<T, ToolError>;
9
10#[derive(Error, Debug)]
12#[non_exhaustive]
13pub enum ToolError {
14 #[error("Tool '{name}' not found")]
16 ToolNotFound {
17 name: Cow<'static, str>,
19 },
20
21 #[error("Invalid parameters for tool '{tool}': {message}")]
23 InvalidParameters {
24 tool: Cow<'static, str>,
26 message: Cow<'static, str>,
28 },
29
30 #[error("Tool '{tool}' execution failed: {message}")]
32 ExecutionFailed {
33 tool: Cow<'static, str>,
35 message: Cow<'static, str>,
37 },
38
39 #[error("Schema validation failed for tool '{tool}': {message}")]
41 SchemaValidation {
42 tool: Cow<'static, str>,
44 message: Cow<'static, str>,
46 },
47
48 #[error("Tool registration failed: {message}")]
50 RegistrationError {
51 message: Cow<'static, str>,
53 },
54
55 #[error("Serialization error for tool '{tool}': {source}")]
57 SerializationError {
58 tool: Cow<'static, str>,
60 #[source]
62 source: serde_json::Error,
63 },
64
65 #[error("Timeout error for tool '{tool}': execution exceeded {timeout:?}")]
74 TimeoutError {
75 tool: Cow<'static, str>,
77 timeout: std::time::Duration,
79 },
80
81 #[error("Tool '{tool}' execution panicked")]
86 ExecutionPanicked {
87 tool: Cow<'static, str>,
89 },
90}
91
92impl ToolError {
93 pub fn is_retryable(&self) -> bool {
95 matches!(
96 self,
97 ToolError::TimeoutError { .. } | ToolError::ExecutionFailed { .. }
98 )
99 }
100}
101
102pub struct ErrorContext {
104 tool_name: Option<String>,
105}
106
107impl ErrorContext {
108 pub fn new() -> Self {
110 Self { tool_name: None }
111 }
112
113 pub fn with_tool(mut self, tool_name: impl Into<String>) -> Self {
115 self.tool_name = Some(tool_name.into());
116 self
117 }
118
119 fn get_tool_name(&self) -> String {
120 self.tool_name
121 .clone()
122 .unwrap_or_else(|| "unknown".to_string())
123 }
124
125 pub fn tool_not_found(self) -> ToolError {
127 ToolError::ToolNotFound {
128 name: Cow::Owned(self.get_tool_name()),
129 }
130 }
131
132 pub fn invalid_parameters(self, message: impl Into<String>) -> ToolError {
134 ToolError::InvalidParameters {
135 tool: Cow::Owned(self.get_tool_name()),
136 message: Cow::Owned(message.into()),
137 }
138 }
139
140 pub fn execution_failed(self, message: impl Into<String>) -> ToolError {
142 ToolError::ExecutionFailed {
143 tool: Cow::Owned(self.get_tool_name()),
144 message: Cow::Owned(message.into()),
145 }
146 }
147
148 pub fn schema_validation(self, message: impl Into<String>) -> ToolError {
150 ToolError::SchemaValidation {
151 tool: Cow::Owned(self.get_tool_name()),
152 message: Cow::Owned(message.into()),
153 }
154 }
155
156 pub fn serialization_error(self, source: serde_json::Error) -> ToolError {
158 ToolError::SerializationError {
159 tool: Cow::Owned(self.get_tool_name()),
160 source,
161 }
162 }
163
164 pub fn timeout_error(self, timeout: std::time::Duration) -> ToolError {
166 ToolError::TimeoutError {
167 tool: Cow::Owned(self.get_tool_name()),
168 timeout,
169 }
170 }
171}
172
173impl Default for ErrorContext {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179pub fn error_context() -> ErrorContext {
181 ErrorContext::new()
182}