use super::{USAGE, adapter, rpc};
use crate::client;
use std::{fmt, io};
#[derive(Debug)]
pub enum RelayError {
Input(io::Error),
ReceiptOutput {
cause: io::Error,
response: Vec<u8>,
},
ResultEncoding {
refusal: rpc::Refusal,
result: adapter::ToolResult,
},
Encoding(serde_json::Error),
Adapter(adapter::EncodeError),
Arguments(&'static str),
ConfigRead(io::Error),
ConfigDecode(serde_json::Error),
Runtime(crate::serve::runtime::Refusal),
SocketCap(client::Ended),
CapNotRepresentable,
}
impl fmt::Display for RelayError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let code = match self {
Self::Input(_) => "mcp_input_read_failed",
Self::ReceiptOutput { .. } => "mcp_output_write_failed",
Self::ResultEncoding { .. } | Self::Encoding(_) => "mcp_response_encoding_failed",
Self::Adapter(_) => "mcp_result_encoding_failed",
Self::Arguments(why) => {
return write!(formatter, "mcp_arguments_invalid: {why}; {USAGE}");
}
Self::ConfigRead(_) => "mcp_config_read_failed",
Self::ConfigDecode(_) => "mcp_config_invalid",
Self::Runtime(error) => return fmt::Display::fmt(error, formatter),
Self::SocketCap(_) => "mcp_socket_cap_unavailable",
Self::CapNotRepresentable => "mcp_frame_cap_unrepresentable",
};
formatter.write_str(code)
}
}
impl std::error::Error for RelayError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Input(error) | Self::ConfigRead(error) => Some(error),
Self::Encoding(error) | Self::ConfigDecode(error) => Some(error),
Self::Adapter(error) => Some(error),
Self::Runtime(error) => Some(error),
Self::ReceiptOutput { cause, .. } => Some(cause),
Self::ResultEncoding { .. }
| Self::Arguments(_)
| Self::SocketCap(_)
| Self::CapNotRepresentable => None,
}
}
}