use std::path::Path; use std::sync::PoisonError; use thiserror::Error; #[derive(Debug, Error)] pub enum AppError { #[error("配置错误: {0}")] Config(String), #[error("无效输入: {0}")] InvalidInput(String), #[error("IO 错误: {path}: {source}")] Io { path: String, #[source] source: std::io::Error, }, #[error("{context}: {source}")] IoContext { context: String, #[source] source: std::io::Error, }, #[error("JSON 解析错误: {path}: {source}")] Json { path: String, #[source] source: serde_json::Error, }, #[error("JSON 序列化失败: {source}")] JsonSerialize { #[source] source: serde_json::Error, }, #[error("TOML 解析错误: {path}: {source}")] Toml { path: String, #[source] source: toml::de::Error, }, #[error("锁获取失败: {0}")] Lock(String), #[error("供应商不存在: {0}")] ProviderNotFound(String), #[error("MCP 校验失败: {0}")] McpValidation(String), #[error("{0}")] Message(String), } impl AppError { pub fn io(path: impl AsRef, source: std::io::Error) -> Self { Self::Io { path: path.as_ref().display().to_string(), source, } } pub fn json(path: impl AsRef, source: serde_json::Error) -> Self { Self::Json { path: path.as_ref().display().to_string(), source, } } pub fn toml(path: impl AsRef, source: toml::de::Error) -> Self { Self::Toml { path: path.as_ref().display().to_string(), source, } } } impl From> for AppError { fn from(err: PoisonError) -> Self { Self::Lock(err.to_string()) } } impl From for String { fn from(err: AppError) -> Self { err.to_string() } }