mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-10 19:29:50 +08:00
feat(admin): 实现系统数据导入导出功能,支持提供商和模型批量配置
This commit is contained in:
@@ -3,7 +3,7 @@ use crate::handlers::admin::provider::shared::paths::{
|
||||
admin_provider_id_for_manage_path, is_admin_providers_root,
|
||||
};
|
||||
use crate::handlers::admin::provider::shared::payloads::{
|
||||
AdminProviderCreateRequest, AdminProviderUpdateRequest,
|
||||
AdminProviderCreateRequest, AdminProviderUpdatePatch,
|
||||
};
|
||||
use crate::handlers::admin::provider::write::provider::build_admin_fixed_provider_endpoint_record;
|
||||
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
|
||||
@@ -137,8 +137,8 @@ pub(crate) async fn maybe_build_local_admin_provider_writes_response(
|
||||
"请求体必须是合法的 JSON 对象",
|
||||
)));
|
||||
};
|
||||
let payload = match serde_json::from_value::<AdminProviderUpdateRequest>(raw_value) {
|
||||
Ok(payload) => payload,
|
||||
let patch = match AdminProviderUpdatePatch::from_object(raw_payload) {
|
||||
Ok(patch) => patch,
|
||||
Err(_) => {
|
||||
return Ok(Some(build_admin_provider_bad_request_response(
|
||||
"请求体必须是合法的 JSON 对象",
|
||||
@@ -156,7 +156,7 @@ pub(crate) async fn maybe_build_local_admin_provider_writes_response(
|
||||
))));
|
||||
};
|
||||
let updated_record = match state
|
||||
.build_admin_update_provider_record(&existing_provider, &raw_payload, payload)
|
||||
.build_admin_update_provider_record(&existing_provider, patch)
|
||||
.await
|
||||
{
|
||||
Ok(record) => record,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::handlers::admin::provider::shared::paths::admin_update_key_id;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderKeyUpdateRequest;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderKeyUpdatePatch;
|
||||
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
|
||||
use crate::GatewayError;
|
||||
use axum::{
|
||||
@@ -46,8 +46,8 @@ pub(super) async fn maybe_handle(
|
||||
let Some(raw_payload) = raw_value.as_object().cloned() else {
|
||||
return Ok(Some(bad_request_response("请求体必须是合法的 JSON 对象")));
|
||||
};
|
||||
let payload = match serde_json::from_value::<AdminProviderKeyUpdateRequest>(raw_value) {
|
||||
Ok(payload) => payload,
|
||||
let patch = match AdminProviderKeyUpdatePatch::from_object(raw_payload) {
|
||||
Ok(patch) => patch,
|
||||
Err(_) => return Ok(Some(bad_request_response("请求体必须是合法的 JSON 对象"))),
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ pub(super) async fn maybe_handle(
|
||||
};
|
||||
|
||||
let updated_record = match state
|
||||
.build_admin_update_provider_key_record(&provider, &existing_key, &raw_payload, payload)
|
||||
.build_admin_update_provider_key_record(&provider, &existing_key, patch)
|
||||
.await
|
||||
{
|
||||
Ok(record) => record,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::handlers::admin::shared::AdminTypedObjectPatch;
|
||||
use aether_admin::provider::endpoints as admin_provider_endpoints_pure;
|
||||
use aether_data_contracts::repository::provider_catalog::{
|
||||
StoredProviderCatalogEndpoint, StoredProviderCatalogKey,
|
||||
@@ -82,3 +83,6 @@ pub(crate) struct AdminProviderEndpointUpdateRequest {
|
||||
#[serde(default)]
|
||||
pub(crate) format_acceptance_config: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
pub(crate) type AdminProviderEndpointUpdatePatch =
|
||||
AdminTypedObjectPatch<AdminProviderEndpointUpdateRequest>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::extractors::admin_endpoint_id;
|
||||
use super::payloads::{
|
||||
build_admin_provider_endpoint_response, endpoint_key_counts_by_format,
|
||||
AdminProviderEndpointUpdateRequest,
|
||||
AdminProviderEndpointUpdatePatch,
|
||||
};
|
||||
use super::support::build_admin_endpoints_data_unavailable_response;
|
||||
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
|
||||
@@ -75,8 +75,8 @@ pub(super) async fn maybe_handle(
|
||||
.into_response(),
|
||||
));
|
||||
};
|
||||
let payload = match serde_json::from_value::<AdminProviderEndpointUpdateRequest>(raw_value) {
|
||||
Ok(payload) => payload,
|
||||
let patch = match AdminProviderEndpointUpdatePatch::from_object(raw_payload) {
|
||||
Ok(patch) => patch,
|
||||
Err(_) => {
|
||||
return Ok(Some(
|
||||
(
|
||||
@@ -118,12 +118,7 @@ pub(super) async fn maybe_handle(
|
||||
));
|
||||
};
|
||||
let updated_record = match state
|
||||
.build_admin_update_provider_endpoint_record(
|
||||
&provider,
|
||||
&existing_endpoint,
|
||||
&raw_payload,
|
||||
payload,
|
||||
)
|
||||
.build_admin_update_provider_endpoint_record(&provider, &existing_endpoint, patch)
|
||||
.await
|
||||
{
|
||||
Ok(record) => record,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::payloads::build_admin_provider_model_response;
|
||||
use crate::handlers::admin::provider::shared::paths::admin_provider_model_route_parts;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderModelUpdateRequest;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderModelUpdatePatch;
|
||||
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
|
||||
use crate::GatewayError;
|
||||
use axum::{
|
||||
@@ -75,8 +75,8 @@ pub(super) async fn maybe_handle(
|
||||
.into_response(),
|
||||
));
|
||||
};
|
||||
let payload = match serde_json::from_value::<AdminProviderModelUpdateRequest>(raw_value) {
|
||||
Ok(payload) => payload,
|
||||
let patch = match AdminProviderModelUpdatePatch::from_object(raw_payload) {
|
||||
Ok(patch) => patch,
|
||||
Err(_) => {
|
||||
return Ok(Some(
|
||||
(
|
||||
@@ -88,7 +88,7 @@ pub(super) async fn maybe_handle(
|
||||
}
|
||||
};
|
||||
let record = match state
|
||||
.build_admin_provider_model_update_record(&existing, &raw_payload, payload)
|
||||
.build_admin_provider_model_update_record(&existing, patch)
|
||||
.await
|
||||
{
|
||||
Ok(record) => record,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::handlers::admin::shared::AdminTypedObjectPatch;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -83,6 +84,8 @@ pub(crate) struct AdminProviderKeyUpdateRequest {
|
||||
pub(crate) fingerprint: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
pub(crate) type AdminProviderKeyUpdatePatch = AdminTypedObjectPatch<AdminProviderKeyUpdateRequest>;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(crate) struct AdminProviderKeyBatchDeleteRequest {
|
||||
pub(crate) ids: Vec<String>,
|
||||
@@ -187,6 +190,8 @@ pub(crate) struct AdminProviderUpdateRequest {
|
||||
pub(crate) config: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
pub(crate) type AdminProviderUpdatePatch = AdminTypedObjectPatch<AdminProviderUpdateRequest>;
|
||||
|
||||
pub(crate) const CODEX_WHAM_USAGE_URL: &str = "https://chatgpt.com/backend-api/wham/usage";
|
||||
pub(crate) const KIRO_USAGE_LIMITS_PATH: &str = "/getUsageLimits";
|
||||
pub(crate) const KIRO_USAGE_SDK_VERSION: &str = "1.0.0";
|
||||
@@ -248,6 +253,9 @@ pub(crate) struct AdminProviderModelUpdateRequest {
|
||||
pub(crate) config: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
pub(crate) type AdminProviderModelUpdatePatch =
|
||||
AdminTypedObjectPatch<AdminProviderModelUpdateRequest>;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(crate) struct AdminBatchAssignGlobalModelsRequest {
|
||||
pub(crate) global_model_ids: Vec<String>,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderKeyUpdateRequest;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderKeyUpdatePatch;
|
||||
use crate::handlers::admin::provider::write::normalize::{
|
||||
normalize_auth_type, validate_vertex_api_formats,
|
||||
};
|
||||
@@ -17,11 +17,11 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
state: &AdminAppState<'_>,
|
||||
provider: &StoredProviderCatalogProvider,
|
||||
existing: &StoredProviderCatalogKey,
|
||||
raw_payload: &serde_json::Map<String, serde_json::Value>,
|
||||
payload: AdminProviderKeyUpdateRequest,
|
||||
patch: AdminProviderKeyUpdatePatch,
|
||||
) -> Result<StoredProviderCatalogKey, String> {
|
||||
let state = state.as_ref();
|
||||
let mut updated = existing.clone();
|
||||
let (fields, payload) = patch.into_parts();
|
||||
let current_auth_type = normalize_auth_type(Some(&existing.auth_type))?;
|
||||
let target_auth_type = payload
|
||||
.auth_type
|
||||
@@ -34,7 +34,7 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
.as_deref()
|
||||
.is_some_and(|_| target_auth_type != current_auth_type);
|
||||
|
||||
let api_key_present = raw_payload.contains_key("api_key");
|
||||
let api_key_present = fields.contains("api_key");
|
||||
let api_key_value = payload
|
||||
.api_key
|
||||
.as_deref()
|
||||
@@ -44,7 +44,7 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
return Err("api_key 不能为空".to_string());
|
||||
}
|
||||
|
||||
let auth_config_present = raw_payload.contains_key("auth_config");
|
||||
let auth_config_present = fields.contains("auth_config");
|
||||
let auth_config = normalize_json_object(payload.auth_config, "auth_config")?;
|
||||
let auth_config_object = auth_config
|
||||
.as_ref()
|
||||
@@ -182,7 +182,7 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("api_formats") {
|
||||
if fields.contains("api_formats") {
|
||||
let api_formats = normalize_string_list(payload.api_formats)
|
||||
.ok_or_else(|| "api_formats 为必填字段".to_string())?;
|
||||
validate_vertex_api_formats(&provider.provider_type, &target_auth_type, &api_formats)?;
|
||||
@@ -201,30 +201,30 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
}
|
||||
updated.name = trimmed.to_string();
|
||||
}
|
||||
if raw_payload.contains_key("rate_multipliers") {
|
||||
if fields.contains("rate_multipliers") {
|
||||
updated.rate_multipliers =
|
||||
normalize_json_object(payload.rate_multipliers, "rate_multipliers")?;
|
||||
}
|
||||
if let Some(internal_priority) = payload.internal_priority {
|
||||
updated.internal_priority = internal_priority;
|
||||
}
|
||||
if raw_payload.contains_key("global_priority_by_format") {
|
||||
if fields.contains("global_priority_by_format") {
|
||||
updated.global_priority_by_format = normalize_json_object(
|
||||
payload.global_priority_by_format,
|
||||
"global_priority_by_format",
|
||||
)?;
|
||||
}
|
||||
if raw_payload.contains_key("rpm_limit") {
|
||||
if fields.contains("rpm_limit") {
|
||||
updated.rpm_limit = payload.rpm_limit;
|
||||
if payload.rpm_limit.is_none() {
|
||||
updated.learned_rpm_limit = None;
|
||||
}
|
||||
}
|
||||
if raw_payload.contains_key("allowed_models") {
|
||||
if fields.contains("allowed_models") {
|
||||
updated.allowed_models =
|
||||
normalize_string_list(payload.allowed_models).map(|value| json!(value));
|
||||
}
|
||||
if raw_payload.contains_key("capabilities") {
|
||||
if fields.contains("capabilities") {
|
||||
updated.capabilities = normalize_json_object(payload.capabilities, "capabilities")?;
|
||||
}
|
||||
if let Some(cache_ttl_minutes) = payload.cache_ttl_minutes {
|
||||
@@ -236,7 +236,7 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
if let Some(is_active) = payload.is_active {
|
||||
updated.is_active = is_active;
|
||||
}
|
||||
if raw_payload.contains_key("note") {
|
||||
if fields.contains("note") {
|
||||
updated.note = payload
|
||||
.note
|
||||
.map(|value| value.trim().to_string())
|
||||
@@ -245,22 +245,22 @@ pub(crate) async fn build_admin_update_provider_key_record(
|
||||
if let Some(auto_fetch_models) = payload.auto_fetch_models {
|
||||
updated.auto_fetch_models = auto_fetch_models;
|
||||
}
|
||||
if raw_payload.contains_key("locked_models") {
|
||||
if fields.contains("locked_models") {
|
||||
updated.locked_models =
|
||||
normalize_string_list(payload.locked_models).map(|value| json!(value));
|
||||
}
|
||||
if raw_payload.contains_key("model_include_patterns") {
|
||||
if fields.contains("model_include_patterns") {
|
||||
updated.model_include_patterns =
|
||||
normalize_string_list(payload.model_include_patterns).map(|value| json!(value));
|
||||
}
|
||||
if raw_payload.contains_key("model_exclude_patterns") {
|
||||
if fields.contains("model_exclude_patterns") {
|
||||
updated.model_exclude_patterns =
|
||||
normalize_string_list(payload.model_exclude_patterns).map(|value| json!(value));
|
||||
}
|
||||
if raw_payload.contains_key("proxy") {
|
||||
if fields.contains("proxy") {
|
||||
updated.proxy = normalize_json_object(payload.proxy, "proxy")?;
|
||||
}
|
||||
if raw_payload.contains_key("fingerprint") {
|
||||
if fields.contains("fingerprint") {
|
||||
updated.fingerprint = normalize_json_object(payload.fingerprint, "fingerprint")?;
|
||||
}
|
||||
if auth_config_present && !auth_type_switch && updated.auth_type != "api_key" {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderUpdateRequest;
|
||||
use crate::handlers::admin::provider::shared::payloads::AdminProviderUpdatePatch;
|
||||
use crate::handlers::admin::provider::shared::support::{
|
||||
normalize_provider_billing_type, parse_optional_rfc3339_unix_secs,
|
||||
};
|
||||
@@ -11,15 +11,15 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
pub(crate) async fn build_admin_update_provider_record(
|
||||
state: &AdminAppState<'_>,
|
||||
existing: &StoredProviderCatalogProvider,
|
||||
raw_payload: &serde_json::Map<String, serde_json::Value>,
|
||||
payload: AdminProviderUpdateRequest,
|
||||
patch: AdminProviderUpdatePatch,
|
||||
) -> Result<StoredProviderCatalogProvider, String> {
|
||||
let state = state.as_ref();
|
||||
let mut updated = existing.clone();
|
||||
let (fields, payload) = patch.into_parts();
|
||||
|
||||
if let Some(value) = raw_payload.get("name") {
|
||||
if fields.contains("name") {
|
||||
let Some(name) = payload.name.as_deref() else {
|
||||
return Err(if value.is_null() {
|
||||
return Err(if fields.is_null("name") {
|
||||
"name 不能为空".to_string()
|
||||
} else {
|
||||
"name 必须是字符串".to_string()
|
||||
@@ -41,9 +41,9 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
updated.name = trimmed.to_string();
|
||||
}
|
||||
|
||||
let target_provider_type = if let Some(value) = raw_payload.get("provider_type") {
|
||||
let target_provider_type = if fields.contains("provider_type") {
|
||||
let Some(provider_type) = payload.provider_type.as_deref() else {
|
||||
return Err(if value.is_null() {
|
||||
return Err(if fields.is_null("provider_type") {
|
||||
"provider_type 不能为空".to_string()
|
||||
} else {
|
||||
"provider_type 必须是字符串".to_string()
|
||||
@@ -56,17 +56,17 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
updated.provider_type.clone()
|
||||
};
|
||||
|
||||
if raw_payload.contains_key("description") {
|
||||
if fields.contains("description") {
|
||||
updated.description = payload
|
||||
.description
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty());
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("website") {
|
||||
if fields.contains("website") {
|
||||
updated.website = match payload.website {
|
||||
None => {
|
||||
if value.is_null() {
|
||||
if fields.is_null("website") {
|
||||
None
|
||||
} else {
|
||||
return Err("website 必须是字符串".to_string());
|
||||
@@ -85,9 +85,9 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("billing_type") {
|
||||
if fields.contains("billing_type") {
|
||||
let Some(billing_type) = payload.billing_type.as_deref() else {
|
||||
return Err(if value.is_null() {
|
||||
return Err(if fields.is_null("billing_type") {
|
||||
"billing_type 不能为空".to_string()
|
||||
} else {
|
||||
"billing_type 必须是字符串".to_string()
|
||||
@@ -96,8 +96,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
updated.billing_type = Some(normalize_provider_billing_type(billing_type)?);
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("monthly_quota_usd") {
|
||||
if value.is_null() {
|
||||
if fields.contains("monthly_quota_usd") {
|
||||
if fields.is_null("monthly_quota_usd") {
|
||||
updated.monthly_quota_usd = None;
|
||||
} else {
|
||||
let Some(monthly_quota_usd) = payload.monthly_quota_usd else {
|
||||
@@ -110,8 +110,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("quota_reset_day") {
|
||||
if value.is_null() {
|
||||
if fields.contains("quota_reset_day") {
|
||||
if fields.is_null("quota_reset_day") {
|
||||
updated.quota_reset_day = None;
|
||||
} else {
|
||||
let Some(quota_reset_day) = payload.quota_reset_day else {
|
||||
@@ -124,8 +124,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("quota_last_reset_at") {
|
||||
if value.is_null() {
|
||||
if fields.contains("quota_last_reset_at") {
|
||||
if fields.is_null("quota_last_reset_at") {
|
||||
updated.quota_last_reset_at_unix_secs = None;
|
||||
} else {
|
||||
let Some(raw) = payload.quota_last_reset_at.as_deref() else {
|
||||
@@ -138,8 +138,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("quota_expires_at") {
|
||||
if value.is_null() {
|
||||
if fields.contains("quota_expires_at") {
|
||||
if fields.is_null("quota_expires_at") {
|
||||
updated.quota_expires_at_unix_secs = None;
|
||||
} else {
|
||||
let Some(raw) = payload.quota_expires_at.as_deref() else {
|
||||
@@ -150,9 +150,9 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = raw_payload.get("provider_priority") {
|
||||
if fields.contains("provider_priority") {
|
||||
let Some(provider_priority) = payload.provider_priority else {
|
||||
return Err(if value.is_null() {
|
||||
return Err(if fields.is_null("provider_priority") {
|
||||
"provider_priority 不能为空".to_string()
|
||||
} else {
|
||||
"provider_priority 必须是整数".to_string()
|
||||
@@ -164,21 +164,21 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
updated.provider_priority = provider_priority;
|
||||
}
|
||||
|
||||
if let Some(_value) = raw_payload.get("keep_priority_on_conversion") {
|
||||
if fields.contains("keep_priority_on_conversion") {
|
||||
let Some(keep_priority_on_conversion) = payload.keep_priority_on_conversion else {
|
||||
return Err("keep_priority_on_conversion 必须是布尔值".to_string());
|
||||
};
|
||||
updated.keep_priority_on_conversion = keep_priority_on_conversion;
|
||||
}
|
||||
|
||||
if let Some(_value) = raw_payload.get("is_active") {
|
||||
if fields.contains("is_active") {
|
||||
let Some(is_active) = payload.is_active else {
|
||||
return Err("is_active 必须是布尔值".to_string());
|
||||
};
|
||||
updated.is_active = is_active;
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("concurrent_limit") {
|
||||
if fields.contains("concurrent_limit") {
|
||||
updated.concurrent_limit = match payload.concurrent_limit {
|
||||
Some(value) if value >= 0 => Some(value),
|
||||
Some(_) => return Err("concurrent_limit 必须是非负整数".to_string()),
|
||||
@@ -186,7 +186,7 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
};
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("max_retries") {
|
||||
if fields.contains("max_retries") {
|
||||
updated.max_retries = match payload.max_retries {
|
||||
Some(value) if (0..=999).contains(&value) => Some(value),
|
||||
Some(_) => return Err("max_retries 必须是 0 到 999 之间的整数".to_string()),
|
||||
@@ -194,11 +194,11 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
};
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("proxy") {
|
||||
if fields.contains("proxy") {
|
||||
updated.proxy = normalize_json_object(payload.proxy, "proxy")?;
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("stream_first_byte_timeout") {
|
||||
if fields.contains("stream_first_byte_timeout") {
|
||||
updated.stream_first_byte_timeout_secs = match payload.stream_first_byte_timeout {
|
||||
Some(value) if (1.0..=300.0).contains(&value) => Some(value),
|
||||
Some(_) => {
|
||||
@@ -208,7 +208,7 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
};
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("request_timeout") {
|
||||
if fields.contains("request_timeout") {
|
||||
updated.request_timeout_secs = match payload.request_timeout {
|
||||
Some(value) if (1.0..=600.0).contains(&value) => Some(value),
|
||||
Some(_) => return Err("request_timeout 必须是 1 到 600 之间的数字".to_string()),
|
||||
@@ -216,14 +216,14 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(_value) = raw_payload.get("enable_format_conversion") {
|
||||
if fields.contains("enable_format_conversion") {
|
||||
let Some(enable_format_conversion) = payload.enable_format_conversion else {
|
||||
return Err("enable_format_conversion 必须是布尔值".to_string());
|
||||
};
|
||||
updated.enable_format_conversion = enable_format_conversion;
|
||||
}
|
||||
|
||||
let config_seed = if raw_payload.contains_key("config") {
|
||||
let config_seed = if fields.contains("config") {
|
||||
normalize_json_object(payload.config, "config")?
|
||||
} else {
|
||||
updated.config.clone()
|
||||
@@ -232,11 +232,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
.and_then(|value| value.as_object().cloned())
|
||||
.unwrap_or_default();
|
||||
|
||||
if raw_payload.contains_key("claude_code_advanced") {
|
||||
if raw_payload
|
||||
.get("claude_code_advanced")
|
||||
.is_some_and(serde_json::Value::is_null)
|
||||
{
|
||||
if fields.contains("claude_code_advanced") {
|
||||
if fields.is_null("claude_code_advanced") {
|
||||
config_map.remove("claude_code_advanced");
|
||||
} else {
|
||||
if target_provider_type != "claude_code" {
|
||||
@@ -251,11 +248,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
config_map.remove("claude_code_advanced");
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("pool_advanced") {
|
||||
if raw_payload
|
||||
.get("pool_advanced")
|
||||
.is_some_and(serde_json::Value::is_null)
|
||||
{
|
||||
if fields.contains("pool_advanced") {
|
||||
if fields.is_null("pool_advanced") {
|
||||
config_map.remove("pool_advanced");
|
||||
} else {
|
||||
let value = normalize_json_object(payload.pool_advanced, "pool_advanced")?
|
||||
@@ -264,11 +258,8 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if raw_payload.contains_key("failover_rules") {
|
||||
if raw_payload
|
||||
.get("failover_rules")
|
||||
.is_some_and(serde_json::Value::is_null)
|
||||
{
|
||||
if fields.contains("failover_rules") {
|
||||
if fields.is_null("failover_rules") {
|
||||
config_map.remove("failover_rules");
|
||||
} else {
|
||||
let value = normalize_json_object(payload.failover_rules, "failover_rules")?
|
||||
|
||||
Reference in New Issue
Block a user