universal_tool_core/
error.rs1use schemars::JsonSchema;
2use serde::Deserialize;
3use serde::Serialize;
4use std::collections::HashMap;
5use thiserror::Error;
6
7#[derive(Debug, Error, Serialize, Deserialize, JsonSchema)]
9pub struct ToolError {
10 pub code: ErrorCode,
12 pub message: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub details: Option<HashMap<String, serde_json::Value>>,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
21pub enum ErrorCode {
22 BadRequest,
23 InvalidArgument,
24 NotFound,
25 PermissionDenied,
26 Internal,
27 Timeout,
28 Conflict,
29 NetworkError,
30 ExternalServiceError,
31 ExecutionFailed,
32 SerializationError,
33 IoError,
34}
35
36impl std::fmt::Display for ToolError {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "[{:?}] {}", self.code, self.message)
40 }
41}
42
43impl ToolError {
45 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
47 Self {
48 code,
49 message: message.into(),
50 details: None,
51 }
52 }
53
54 pub fn with_details(mut self, details: HashMap<String, serde_json::Value>) -> Self {
56 self.details = Some(details);
57 self
58 }
59
60 pub fn with_detail(mut self, key: &str, value: impl Into<serde_json::Value>) -> Self {
62 let mut details = self.details.unwrap_or_default();
63 details.insert(key.to_string(), value.into());
64 self.details = Some(details);
65 self
66 }
67
68 pub fn internal(message: impl Into<String>) -> Self {
70 Self::new(ErrorCode::Internal, message)
71 }
72
73 pub fn not_found(message: impl Into<String>) -> Self {
74 Self::new(ErrorCode::NotFound, message)
75 }
76
77 pub fn invalid_input(message: impl Into<String>) -> Self {
78 Self::new(ErrorCode::InvalidArgument, message)
79 }
80
81 pub fn conflict(message: impl Into<String>) -> Self {
82 Self::new(ErrorCode::Conflict, message)
83 }
84}
85
86impl From<std::io::Error> for ToolError {
88 fn from(err: std::io::Error) -> Self {
89 Self::new(ErrorCode::ExecutionFailed, err.to_string())
90 }
91}
92
93impl From<serde_json::Error> for ToolError {
94 fn from(err: serde_json::Error) -> Self {
95 Self::new(ErrorCode::InvalidArgument, err.to_string())
96 }
97}
98
99impl From<String> for ToolError {
100 fn from(err: String) -> Self {
101 Self::new(ErrorCode::ExecutionFailed, err)
102 }
103}
104
105impl From<&str> for ToolError {
106 fn from(err: &str) -> Self {
107 Self::new(ErrorCode::ExecutionFailed, err)
108 }
109}