1use serde::Serialize;
2
3#[derive(Debug, Clone)]
4pub enum ToolError {
5 UnknownAction {
6 message: String,
7 valid: Vec<String>,
8 hint: Option<String>,
9 },
10 MissingParam {
11 message: String,
12 param: String,
13 },
14 InvalidParam {
15 message: String,
16 param: String,
17 },
18 UnknownInstance {
19 message: String,
20 valid: Vec<String>,
21 },
22 AmbiguousTool {
23 message: String,
24 valid: Vec<String>,
25 },
26 ConfirmationRequired {
27 message: String,
28 },
29 Conflict {
30 message: String,
31 existing_id: String,
32 },
33 Forbidden {
34 message: String,
35 required_scopes: Vec<String>,
36 },
37 Sdk {
38 sdk_kind: String,
39 message: String,
40 },
41}
42
43impl Serialize for ToolError {
44 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
45 let value = match self {
46 Self::UnknownAction {
47 message,
48 valid,
49 hint,
50 } => serde_json::json!({
51 "kind": "unknown_action",
52 "message": message,
53 "valid": valid,
54 "hint": hint,
55 }),
56 Self::MissingParam { message, param } => {
57 serde_json::json!({"kind": "missing_param", "message": message, "param": param})
58 }
59 Self::InvalidParam { message, param } => {
60 serde_json::json!({"kind": "invalid_param", "message": message, "param": param})
61 }
62 Self::UnknownInstance { message, valid } => {
63 serde_json::json!({"kind": "unknown_instance", "message": message, "valid": valid})
64 }
65 Self::AmbiguousTool { message, valid } => {
66 serde_json::json!({"kind": "ambiguous_tool", "message": message, "valid": valid})
67 }
68 Self::ConfirmationRequired { message } => {
69 serde_json::json!({"kind": "confirmation_required", "message": message})
70 }
71 Self::Conflict {
72 message,
73 existing_id,
74 } => serde_json::json!({
75 "kind": "conflict",
76 "message": message,
77 "existing_id": existing_id,
78 }),
79 Self::Forbidden {
80 message,
81 required_scopes,
82 } => serde_json::json!({
83 "kind": "forbidden",
84 "message": message,
85 "required_scopes": required_scopes,
86 }),
87 Self::Sdk { sdk_kind, message } => {
88 serde_json::json!({"kind": sdk_kind, "message": message})
89 }
90 };
91 value.serialize(serializer)
92 }
93}
94
95impl std::fmt::Display for ToolError {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 match serde_json::to_string(self) {
98 Ok(value) => f.write_str(&value),
99 Err(_) => write!(f, "{self:?}"),
100 }
101 }
102}
103
104impl std::error::Error for ToolError {}
105
106impl ToolError {
107 #[must_use]
108 pub fn kind(&self) -> &str {
109 match self {
110 Self::UnknownAction { .. } => "unknown_action",
111 Self::MissingParam { .. } => "missing_param",
112 Self::InvalidParam { .. } => "invalid_param",
113 Self::UnknownInstance { .. } => "unknown_instance",
114 Self::AmbiguousTool { .. } => "ambiguous_tool",
115 Self::ConfirmationRequired { .. } => "confirmation_required",
116 Self::Conflict { .. } => "conflict",
117 Self::Forbidden { .. } => "forbidden",
118 Self::Sdk { sdk_kind, .. } => sdk_kind.as_str(),
119 }
120 }
121
122 #[must_use]
123 pub fn user_message(&self) -> &str {
124 match self {
125 Self::UnknownAction { message, .. }
126 | Self::MissingParam { message, .. }
127 | Self::InvalidParam { message, .. }
128 | Self::UnknownInstance { message, .. }
129 | Self::AmbiguousTool { message, .. }
130 | Self::ConfirmationRequired { message }
131 | Self::Conflict { message, .. }
132 | Self::Forbidden { message, .. }
133 | Self::Sdk { message, .. } => message.as_str(),
134 }
135 }
136
137 #[must_use]
138 pub fn internal_message(message: impl Into<String>) -> Self {
139 Self::Sdk {
140 sdk_kind: "internal_error".to_string(),
141 message: message.into(),
142 }
143 }
144}