- Replace complex gradient animations with clean, minimal tab design - Migrate from @lobehub/icons CDN to local SVG assets for better reliability - Fix clippy warning in error.rs (use inline format args) - Improve code formatting in skill service and commands - Reduce CSS complexity in AppSwitcher component (removed blur effects and gradients) - Update BrandIcons to use imported local SVG files instead of dynamic image loading This improves performance, reduces external dependencies, and provides a cleaner UI experience.
122 lines
2.8 KiB
Rust
122 lines
2.8 KiB
Rust
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("MCP 校验失败: {0}")]
|
|
McpValidation(String),
|
|
#[error("{0}")]
|
|
Message(String),
|
|
#[error("{zh} ({en})")]
|
|
Localized {
|
|
key: &'static str,
|
|
zh: String,
|
|
en: String,
|
|
},
|
|
}
|
|
|
|
impl AppError {
|
|
pub fn io(path: impl AsRef<Path>, source: std::io::Error) -> Self {
|
|
Self::Io {
|
|
path: path.as_ref().display().to_string(),
|
|
source,
|
|
}
|
|
}
|
|
|
|
pub fn json(path: impl AsRef<Path>, source: serde_json::Error) -> Self {
|
|
Self::Json {
|
|
path: path.as_ref().display().to_string(),
|
|
source,
|
|
}
|
|
}
|
|
|
|
pub fn toml(path: impl AsRef<Path>, source: toml::de::Error) -> Self {
|
|
Self::Toml {
|
|
path: path.as_ref().display().to_string(),
|
|
source,
|
|
}
|
|
}
|
|
|
|
pub fn localized(key: &'static str, zh: impl Into<String>, en: impl Into<String>) -> Self {
|
|
Self::Localized {
|
|
key,
|
|
zh: zh.into(),
|
|
en: en.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> From<PoisonError<T>> for AppError {
|
|
fn from(err: PoisonError<T>) -> Self {
|
|
Self::Lock(err.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<AppError> for String {
|
|
fn from(err: AppError) -> Self {
|
|
err.to_string()
|
|
}
|
|
}
|
|
|
|
/// 格式化为 JSON 错误字符串,前端可解析为结构化错误
|
|
pub fn format_skill_error(
|
|
code: &str,
|
|
context: &[(&str, &str)],
|
|
suggestion: Option<&str>,
|
|
) -> String {
|
|
use serde_json::json;
|
|
|
|
let mut ctx_map = serde_json::Map::new();
|
|
for (key, value) in context {
|
|
ctx_map.insert(key.to_string(), json!(value));
|
|
}
|
|
|
|
let error_obj = json!({
|
|
"code": code,
|
|
"context": ctx_map,
|
|
"suggestion": suggestion,
|
|
});
|
|
|
|
serde_json::to_string(&error_obj).unwrap_or_else(|_| {
|
|
// 如果 JSON 序列化失败,返回简单格式
|
|
format!("ERROR:{code}")
|
|
})
|
|
}
|