use std::ffi::NulError;
use std::fmt;
use std::sync::PoisonError as StdPoisonError;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
ModelNotAvailable,
DeviceNotEligible,
AppleIntelligenceNotEnabled,
ModelNotReady,
InvalidInput(String),
GenerationError(String),
Timeout(String),
ToolCall(ToolCallError),
InternalError(String),
PoisonError,
Json(String),
}
#[derive(Debug, Clone)]
pub struct ToolCallError {
pub tool_name: String,
pub arguments: serde_json::Value,
pub inner_error: String,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::ModelNotAvailable => {
write!(f, "FoundationModels is not available on this device")
}
Error::DeviceNotEligible => write!(f, "Device is not eligible for Apple Intelligence"),
Error::AppleIntelligenceNotEnabled => {
write!(f, "Apple Intelligence is not enabled in system settings")
}
Error::ModelNotReady => {
write!(
f,
"Model is not ready (downloading or other system reasons)"
)
}
Error::InvalidInput(msg) => write!(f, "Invalid input: {msg}"),
Error::GenerationError(msg) => write!(f, "Generation error: {msg}"),
Error::Timeout(msg) => write!(f, "Operation timed out: {msg}"),
Error::ToolCall(err) => {
write!(f, "Tool '{}' failed: {}", err.tool_name, err.inner_error)
}
Error::InternalError(msg) => write!(f, "Internal error: {msg}"),
Error::PoisonError => write!(f, "A lock was poisoned"),
Error::Json(msg) => write!(f, "JSON error: {msg}"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl From<NulError> for Error {
fn from(_: NulError) -> Self {
Error::InvalidInput("String contains null byte".to_string())
}
}
impl<T> From<StdPoisonError<T>> for Error {
fn from(_: StdPoisonError<T>) -> Self {
Error::PoisonError
}
}
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Error::Json(err.to_string())
}
}
impl fmt::Display for ToolCallError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Tool '{}' failed with arguments {}: {}",
self.tool_name, self.arguments, self.inner_error
)
}
}
impl std::error::Error for ToolCallError {}