systemprompt_traits/
extension_error.rs1use http::StatusCode;
11
12#[derive(Debug, Clone)]
13pub struct ExtensionApiError {
14 pub code: String,
15 pub message: String,
16 pub status: StatusCode,
17}
18
19impl ExtensionApiError {
20 #[must_use]
21 pub fn new(code: impl Into<String>, message: impl Into<String>, status: StatusCode) -> Self {
22 Self {
23 code: code.into(),
24 message: message.into(),
25 status,
26 }
27 }
28}
29
30#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
31pub struct McpErrorData {
32 pub code: i32,
33 pub message: String,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub data: Option<serde_json::Value>,
38}
39
40impl McpErrorData {
41 #[must_use]
42 pub fn new(code: i32, message: impl Into<String>) -> Self {
43 Self {
44 code,
45 message: message.into(),
46 data: None,
47 }
48 }
49
50 #[must_use]
51 pub fn with_data(mut self, data: serde_json::Value) -> Self {
53 self.data = Some(data);
54 self
55 }
56}
57
58pub trait ExtensionError: std::error::Error + Send + Sync + 'static {
59 fn code(&self) -> &'static str;
60
61 fn status(&self) -> StatusCode {
62 StatusCode::INTERNAL_SERVER_ERROR
63 }
64
65 fn is_retryable(&self) -> bool {
66 false
67 }
68
69 fn user_message(&self) -> String {
70 self.to_string()
71 }
72
73 fn to_mcp_error(&self) -> McpErrorData {
74 McpErrorData {
75 code: i32::from(self.status().as_u16()),
76 message: self.user_message(),
77 data: Some(serde_json::json!({
78 "code": self.code(),
79 "retryable": self.is_retryable(),
80 })),
81 }
82 }
83
84 fn to_api_error(&self) -> ExtensionApiError {
85 ExtensionApiError {
86 code: self.code().to_owned(),
87 message: self.user_message(),
88 status: self.status(),
89 }
90 }
91}