bamboo_agent/server/
error.rs1use actix_web::{http::StatusCode, HttpResponse, ResponseError};
19use serde::Serialize;
20use thiserror::Error;
21
22pub type Result<T, E = AppError> = std::result::Result<T, E>;
24
25#[derive(Debug, Error)]
27pub enum AppError {
28 #[error("Bad request: {0}")]
29 BadRequest(String),
30
31 #[error("Tool '{0}' not found")]
32 ToolNotFound(String),
33
34 #[error("Tool execution failed: {0}")]
35 ToolExecutionError(String),
36
37 #[error("Tool requires approval: {0}")]
38 ToolApprovalRequired(String),
39
40 #[error("{0} not found")]
41 NotFound(String),
42
43 #[error("Proxy authentication required")]
44 ProxyAuthRequired,
45
46 #[error("Internal server error: {0}")]
47 InternalError(#[from] anyhow::Error),
48
49 #[error("Storage error: {0}")]
50 StorageError(#[from] std::io::Error),
51
52 #[error("Serialization error: {0}")]
53 SerializationError(#[from] serde_json::Error),
54}
55
56#[derive(Serialize)]
57struct JsonError {
58 message: String,
59 r#type: String,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 code: Option<String>,
62}
63
64#[derive(Serialize)]
65struct JsonErrorWrapper {
66 error: JsonError,
67}
68
69impl ResponseError for AppError {
70 fn status_code(&self) -> StatusCode {
71 match self {
72 AppError::BadRequest(_) => StatusCode::BAD_REQUEST,
73 AppError::ToolNotFound(_) => StatusCode::NOT_FOUND,
74 AppError::ToolExecutionError(_) => StatusCode::BAD_REQUEST,
75 AppError::ToolApprovalRequired(_) => StatusCode::FORBIDDEN,
76 AppError::NotFound(_) => StatusCode::NOT_FOUND,
77 AppError::ProxyAuthRequired => StatusCode::PRECONDITION_REQUIRED,
78 AppError::InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR,
79 AppError::StorageError(_) => StatusCode::INTERNAL_SERVER_ERROR,
80 AppError::SerializationError(_) => StatusCode::INTERNAL_SERVER_ERROR,
81 }
82 }
83
84 fn error_response(&self) -> HttpResponse {
85 let status_code = self.status_code();
86 let error_response = JsonErrorWrapper {
87 error: JsonError {
88 message: self.to_string(),
89 r#type: "api_error".to_string(),
90 code: match self {
91 AppError::ProxyAuthRequired => Some("proxy_auth_required".to_string()),
92 _ => None,
93 },
94 },
95 };
96 HttpResponse::build(status_code).json(error_response)
97 }
98}