mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 18:37:46 +08:00
236 lines
7.6 KiB
Rust
236 lines
7.6 KiB
Rust
use serde_json::{json, Value};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum CandidateFailureDiagnosticKind {
|
|
RequestBodyBuild,
|
|
RequestConversion,
|
|
BodyRules,
|
|
HeaderRules,
|
|
UrlBuild,
|
|
TransportAuth,
|
|
EnvelopeBuild,
|
|
}
|
|
|
|
impl CandidateFailureDiagnosticKind {
|
|
pub const fn as_str(self) -> &'static str {
|
|
match self {
|
|
Self::RequestBodyBuild => "request_body_build",
|
|
Self::RequestConversion => "request_conversion",
|
|
Self::BodyRules => "body_rules",
|
|
Self::HeaderRules => "header_rules",
|
|
Self::UrlBuild => "url_build",
|
|
Self::TransportAuth => "transport_auth",
|
|
Self::EnvelopeBuild => "envelope_build",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct CandidateFailureDiagnostic {
|
|
kind: CandidateFailureDiagnosticKind,
|
|
path: String,
|
|
message: String,
|
|
source: Option<String>,
|
|
client_api_format: Option<String>,
|
|
provider_api_format: Option<String>,
|
|
safe_to_show: bool,
|
|
details: Option<Value>,
|
|
}
|
|
|
|
impl CandidateFailureDiagnostic {
|
|
pub fn new(
|
|
kind: CandidateFailureDiagnosticKind,
|
|
path: impl Into<String>,
|
|
message: impl Into<String>,
|
|
) -> Self {
|
|
Self {
|
|
kind,
|
|
path: path.into(),
|
|
message: message.into(),
|
|
source: None,
|
|
client_api_format: None,
|
|
provider_api_format: None,
|
|
safe_to_show: true,
|
|
details: None,
|
|
}
|
|
}
|
|
|
|
pub fn source(mut self, source: impl Into<String>) -> Self {
|
|
self.source = Some(source.into());
|
|
self
|
|
}
|
|
|
|
pub fn details(mut self, details: Value) -> Self {
|
|
self.details = Some(details);
|
|
self
|
|
}
|
|
|
|
pub fn formats(
|
|
mut self,
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
) -> Self {
|
|
self.client_api_format = Some(client_api_format.into());
|
|
self.provider_api_format = Some(provider_api_format.into());
|
|
self
|
|
}
|
|
|
|
pub fn has_specific_path(&self) -> bool {
|
|
let path = self.path.trim();
|
|
!path.is_empty() && path != "$"
|
|
}
|
|
|
|
pub fn to_extra_data(&self) -> Value {
|
|
let diagnostic = self.to_value();
|
|
let mut extra_data = json!({
|
|
"failure_diagnostic": diagnostic,
|
|
});
|
|
|
|
// Compatibility for current usage UI and already persisted trace readers.
|
|
if let Some(object) = extra_data.as_object_mut() {
|
|
match self.kind {
|
|
CandidateFailureDiagnosticKind::RequestBodyBuild => {
|
|
object.insert(
|
|
"request_body_build_error".to_string(),
|
|
json!({
|
|
"path": self.path,
|
|
"message": self.message,
|
|
"client_api_format": self.client_api_format,
|
|
"provider_api_format": self.provider_api_format,
|
|
}),
|
|
);
|
|
}
|
|
CandidateFailureDiagnosticKind::RequestConversion => {
|
|
object.insert(
|
|
"request_conversion_error".to_string(),
|
|
json!({
|
|
"path": self.path,
|
|
"message": self.message,
|
|
"client_api_format": self.client_api_format,
|
|
"provider_api_format": self.provider_api_format,
|
|
}),
|
|
);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
extra_data
|
|
}
|
|
|
|
pub fn upstream_url_missing(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::UrlBuild,
|
|
"$.endpoint",
|
|
"无法构建上游请求地址;请检查 base_url、custom_path、API 格式和模型映射",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn header_rules_apply_failed(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::HeaderRules,
|
|
"$.endpoint.header_rules",
|
|
"Header 规则应用失败;请检查规则格式、条件配置,或是否试图覆盖受保护认证头",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn body_rules_apply_failed(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::BodyRules,
|
|
"$.endpoint.body_rules",
|
|
"Body 规则应用失败;请检查规则格式、条件配置,或规则输出是否仍是当前上游支持的请求体",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn body_rules_unsupported_for_binary_upload(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::BodyRules,
|
|
"$.endpoint.body_rules",
|
|
"二进制上传暂不支持本地应用 Body 规则;请移除该 Endpoint 的 Body 规则或改用 JSON 请求体",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn provider_request_body_missing(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::RequestBodyBuild,
|
|
"$",
|
|
"无法构建上游请求体;请检查请求体是否为支持的 JSON object,以及该任务类型必需字段是否存在且取值受支持",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn request_conversion_failed(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
message: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::RequestConversion,
|
|
"$",
|
|
message,
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
pub fn envelope_build_failed(
|
|
client_api_format: impl Into<String>,
|
|
provider_api_format: impl Into<String>,
|
|
source: impl Into<String>,
|
|
) -> Self {
|
|
Self::new(
|
|
CandidateFailureDiagnosticKind::EnvelopeBuild,
|
|
"$",
|
|
"无法构建上游请求封装;请检查该 Provider 的认证配置、模型映射、Endpoint Body 规则和当前请求体是否兼容",
|
|
)
|
|
.formats(client_api_format, provider_api_format)
|
|
.source(source)
|
|
}
|
|
|
|
fn to_value(&self) -> Value {
|
|
json!({
|
|
"kind": self.kind.as_str(),
|
|
"path": self.path,
|
|
"message": self.message,
|
|
"source": self.source,
|
|
"client_api_format": self.client_api_format,
|
|
"provider_api_format": self.provider_api_format,
|
|
"safe_to_show": self.safe_to_show,
|
|
"details": self.details,
|
|
"stage": "request",
|
|
"source_format": self.client_api_format,
|
|
"target_format": self.provider_api_format,
|
|
})
|
|
}
|
|
}
|