use crate::envelope::{JsonRpcError, JsonRpcResponse};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum A2aError {
#[error("method not found: {0}")]
MethodNotFound(String),
#[error("invalid params: {0}")]
InvalidParams(String),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("bus error: {0}")]
Bus(#[from] klieo_core::error::BusError),
#[error("task not found: {0}")]
TaskNotFound(String),
#[error("server error: {0}")]
Server(String),
#[error("unauthorized: {0}")]
Unauthorized(String),
}
impl A2aError {
pub fn to_json_rpc_error(&self, request_id: serde_json::Value) -> JsonRpcResponse {
let (code, message) = match self {
Self::MethodNotFound(_) => (-32601, self.to_string()),
Self::InvalidParams(_) => (-32602, self.to_string()),
Self::Json(_) => (-32700, self.to_string()),
Self::Bus(_) | Self::TaskNotFound(_) | Self::Server(_) => (-32000, self.to_string()),
Self::Unauthorized(_) => (-32001, self.to_string()),
};
JsonRpcResponse {
jsonrpc: "2.0".to_string(),
id: request_id,
result: None,
error: Some(JsonRpcError {
code,
message,
data: None,
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn method_not_found_maps_to_minus_32601() {
let resp = A2aError::MethodNotFound("Foo".into()).to_json_rpc_error(json!(7));
assert_eq!(resp.error.unwrap().code, -32601);
}
#[test]
fn invalid_params_maps_to_minus_32602() {
let resp = A2aError::InvalidParams("missing field".into()).to_json_rpc_error(json!("a"));
assert_eq!(resp.error.unwrap().code, -32602);
}
#[test]
fn json_error_maps_to_minus_32700() {
let json_err = serde_json::from_str::<u32>("not json").unwrap_err();
let resp = A2aError::from(json_err).to_json_rpc_error(json!(null));
assert_eq!(resp.error.unwrap().code, -32700);
}
#[test]
fn unauthorized_maps_to_minus_32001() {
let resp = A2aError::Unauthorized("no token".into()).to_json_rpc_error(json!(1));
assert_eq!(resp.error.unwrap().code, -32001);
}
}