提交qiming-mcp-proxy

This commit is contained in:
Codex
2026-06-01 13:03:20 +08:00
parent 9e9486b7c2
commit afb3d9f4e6
394 changed files with 124494 additions and 0 deletions

View File

@@ -0,0 +1,344 @@
use axum::Json;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use config::ConfigError;
use serde_json::json;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum VoiceCliError {
#[error("{0}")]
Config(String),
#[error("{0}")]
AudioProcessing(String),
#[error("{0}")]
Transcription(String),
#[error("{0}")]
Model(String),
#[error("{0}")]
FileIo(String),
#[error("{0}")]
Http(String),
#[error("{0}")]
Serialization(String),
#[error("{0}")]
Json(String),
#[error("{0}")]
ConfigRs(String),
#[error("{0}")]
Daemon(String),
#[error("{0}")]
UnsupportedFormat(String),
#[error("{0}")]
FileTooLarge(String),
#[error("{0}")]
ModelNotFound(String),
#[error("{0}")]
InvalidModelName(String),
// Worker pool related errors
#[error("{0}")]
WorkerPoolError(String),
#[error("{0}")]
TranscriptionTimeout(String),
#[error("{0}")]
TranscriptionFailed(String),
// Audio processing specific errors
#[error("{0}")]
AudioConversionFailed(String),
#[error("{0}")]
AudioProbeError(String),
#[error("{0}")]
TempFileError(String),
// Multipart form handling errors
#[error("{0}")]
MultipartError(String),
#[error("{0}")]
MissingField(String),
// Network related errors
#[error("{0}")]
Network(String),
// Storage related errors
#[error("{0}")]
Storage(String),
// Task management errors
#[error("{0}")]
TaskManagementDisabled(String),
#[error("{0}")]
NotFound(String),
#[error("{0}")]
Initialization(String),
// TTS related errors
#[error("{0}")]
TtsError(String),
#[error("{0}")]
InvalidInput(String),
#[error("{0}")]
Io(String),
}
impl VoiceCliError {
// ===========================================
// 工厂方法 - 创建带国际化消息的错误
// ===========================================
pub fn config_error(detail: impl Into<String>) -> Self {
Self::Config(t!("errors.voice.config", detail = detail.into()).to_string())
}
pub fn audio_processing_error(detail: impl Into<String>) -> Self {
Self::AudioProcessing(
t!("errors.voice.audio_processing", detail = detail.into()).to_string(),
)
}
pub fn transcription_error(detail: impl Into<String>) -> Self {
Self::Transcription(t!("errors.voice.transcription", detail = detail.into()).to_string())
}
pub fn model_error(detail: impl Into<String>) -> Self {
Self::Model(t!("errors.voice.model", detail = detail.into()).to_string())
}
pub fn file_io_error(detail: impl Into<String>) -> Self {
Self::FileIo(t!("errors.voice.file_io", detail = detail.into()).to_string())
}
pub fn http_error(detail: impl Into<String>) -> Self {
Self::Http(t!("errors.voice.http", detail = detail.into()).to_string())
}
pub fn serialization_error(detail: impl Into<String>) -> Self {
Self::Serialization(t!("errors.voice.serialization", detail = detail.into()).to_string())
}
pub fn json_error(detail: impl Into<String>) -> Self {
Self::Json(t!("errors.voice.json", detail = detail.into()).to_string())
}
pub fn config_rs_error(detail: impl Into<String>) -> Self {
Self::ConfigRs(t!("errors.voice.config_rs", detail = detail.into()).to_string())
}
pub fn daemon_error(detail: impl Into<String>) -> Self {
Self::Daemon(t!("errors.voice.daemon", detail = detail.into()).to_string())
}
pub fn unsupported_format(detail: impl Into<String>) -> Self {
Self::UnsupportedFormat(
t!("errors.voice.unsupported_format", detail = detail.into()).to_string(),
)
}
pub fn file_too_large(size: usize, max: usize) -> Self {
Self::FileTooLarge(t!("errors.voice.file_too_large", size = size, max = max).to_string())
}
pub fn model_not_found(model: impl Into<String>) -> Self {
Self::ModelNotFound(t!("errors.voice.model_not_found", model = model.into()).to_string())
}
pub fn invalid_model_name(model: impl Into<String>) -> Self {
Self::InvalidModelName(
t!("errors.voice.invalid_model_name", model = model.into()).to_string(),
)
}
pub fn worker_pool_error(detail: impl Into<String>) -> Self {
Self::WorkerPoolError(t!("errors.voice.worker_pool", detail = detail.into()).to_string())
}
pub fn transcription_timeout(seconds: u64) -> Self {
Self::TranscriptionTimeout(
t!("errors.voice.transcription_timeout", seconds = seconds).to_string(),
)
}
pub fn transcription_failed(detail: impl Into<String>) -> Self {
Self::TranscriptionFailed(
t!("errors.voice.transcription_failed", detail = detail.into()).to_string(),
)
}
pub fn audio_conversion_failed(detail: impl Into<String>) -> Self {
Self::AudioConversionFailed(
t!(
"errors.voice.audio_conversion_failed",
detail = detail.into()
)
.to_string(),
)
}
pub fn audio_probe_error(detail: impl Into<String>) -> Self {
Self::AudioProbeError(
t!("errors.voice.audio_probe_error", detail = detail.into()).to_string(),
)
}
pub fn temp_file_error(detail: impl Into<String>) -> Self {
Self::TempFileError(t!("errors.voice.temp_file_error", detail = detail.into()).to_string())
}
pub fn multipart_error(detail: impl Into<String>) -> Self {
Self::MultipartError(t!("errors.voice.multipart_error", detail = detail.into()).to_string())
}
pub fn missing_field(field: impl Into<String>) -> Self {
Self::MissingField(t!("errors.voice.missing_field", field = field.into()).to_string())
}
pub fn network_error(detail: impl Into<String>) -> Self {
Self::Network(t!("errors.voice.network", detail = detail.into()).to_string())
}
pub fn storage_error(detail: impl Into<String>) -> Self {
Self::Storage(t!("errors.voice.storage", detail = detail.into()).to_string())
}
pub fn task_management_disabled() -> Self {
Self::TaskManagementDisabled(t!("errors.voice.task_management_disabled").to_string())
}
pub fn not_found(resource: impl Into<String>) -> Self {
Self::NotFound(t!("errors.voice.not_found", resource = resource.into()).to_string())
}
pub fn initialization_error(detail: impl Into<String>) -> Self {
Self::Initialization(t!("errors.voice.initialization", detail = detail.into()).to_string())
}
pub fn tts_error(detail: impl Into<String>) -> Self {
Self::TtsError(t!("errors.voice.tts", detail = detail.into()).to_string())
}
pub fn invalid_input(detail: impl Into<String>) -> Self {
Self::InvalidInput(t!("errors.voice.invalid_input", detail = detail.into()).to_string())
}
pub fn io_error(detail: impl Into<String>) -> Self {
Self::Io(t!("errors.voice.io", detail = detail.into()).to_string())
}
}
// ===========================================
// 从外部错误类型转换
// ===========================================
impl From<std::io::Error> for VoiceCliError {
fn from(err: std::io::Error) -> Self {
Self::file_io_error(err.to_string())
}
}
impl From<reqwest::Error> for VoiceCliError {
fn from(err: reqwest::Error) -> Self {
Self::http_error(err.to_string())
}
}
impl From<serde_yaml::Error> for VoiceCliError {
fn from(err: serde_yaml::Error) -> Self {
Self::serialization_error(err.to_string())
}
}
impl From<serde_json::Error> for VoiceCliError {
fn from(err: serde_json::Error) -> Self {
Self::json_error(err.to_string())
}
}
impl From<ConfigError> for VoiceCliError {
fn from(err: ConfigError) -> Self {
Self::config_rs_error(err.to_string())
}
}
impl IntoResponse for VoiceCliError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
VoiceCliError::Config(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::AudioProcessing(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::Transcription(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::Model(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::FileIo(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::Http(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::Serialization(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::Json(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::Daemon(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::UnsupportedFormat(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::FileTooLarge(_) => (StatusCode::PAYLOAD_TOO_LARGE, self.to_string()),
VoiceCliError::ModelNotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
VoiceCliError::InvalidModelName(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::WorkerPoolError(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::TranscriptionTimeout(_) => {
(StatusCode::REQUEST_TIMEOUT, self.to_string())
}
VoiceCliError::TranscriptionFailed(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::AudioConversionFailed(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::AudioProbeError(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::TempFileError(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::MultipartError(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::MissingField(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::Network(_) => (StatusCode::BAD_GATEWAY, self.to_string()),
VoiceCliError::Storage(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::ConfigRs(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::TaskManagementDisabled(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::NotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
VoiceCliError::Initialization(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
VoiceCliError::TtsError(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
VoiceCliError::InvalidInput(_) => (StatusCode::BAD_REQUEST, self.to_string()),
VoiceCliError::Io(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
};
let body = Json(json!({
"error": error_message,
"status": status.as_u16()
}));
(status, body).into_response()
}
}
pub type Result<T> = std::result::Result<T, VoiceCliError>;