mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
Fix system data import export flows
This commit is contained in:
@@ -49,7 +49,7 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use uuid::Uuid;
|
||||
|
||||
const ADMIN_SYSTEM_IMPORT_MAX_SIZE_BYTES: usize = 10 * 1024 * 1024;
|
||||
const ADMIN_SYSTEM_IMPORT_MAX_SIZE_BYTES: usize = 500 * 1024 * 1024;
|
||||
|
||||
fn invalid_request(detail: impl Into<String>) -> (http::StatusCode, Value) {
|
||||
(
|
||||
@@ -173,6 +173,9 @@ fn normalize_import_endpoint_format(value: &str) -> Result<String, String> {
|
||||
let normalized = match value.trim().to_ascii_lowercase().as_str() {
|
||||
"openai:cli" => "openai:responses",
|
||||
"openai:compact" => "openai:responses:compact",
|
||||
"openai_image" | "images" | "image" | "/v1/images/generations" | "/v1/images/edits" => {
|
||||
"openai:image"
|
||||
}
|
||||
"claude:chat" | "claude:cli" => "claude:messages",
|
||||
"gemini:chat" | "gemini:cli" => "gemini:generate_content",
|
||||
_ => value.trim(),
|
||||
@@ -956,7 +959,7 @@ impl<'a> AdminAppState<'a> {
|
||||
}
|
||||
|
||||
if request_body.len() > ADMIN_SYSTEM_DATA_IMPORT_MAX_SIZE_BYTES {
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 20MB")));
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 500MB")));
|
||||
}
|
||||
|
||||
let root = match serde_json::from_slice::<Value>(request_body) {
|
||||
@@ -1053,7 +1056,7 @@ impl<'a> AdminAppState<'a> {
|
||||
)));
|
||||
}
|
||||
if request_body.len() > ADMIN_SYSTEM_IMPORT_MAX_SIZE_BYTES {
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 10MB")));
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 500MB")));
|
||||
}
|
||||
|
||||
let parsed = routed!(parse_admin_system_config_import_request(request_body));
|
||||
@@ -1993,7 +1996,7 @@ impl<'a> AdminAppState<'a> {
|
||||
)));
|
||||
}
|
||||
if request_body.len() > ADMIN_SYSTEM_IMPORT_MAX_SIZE_BYTES {
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 10MB")));
|
||||
return Ok(Err(invalid_request("请求体大小不能超过 500MB")));
|
||||
}
|
||||
|
||||
let root = match serde_json::from_slice::<Value>(request_body) {
|
||||
@@ -3062,6 +3065,10 @@ mod tests {
|
||||
for (raw, expected) in [
|
||||
("openai:cli", "openai:responses"),
|
||||
("openai:compact", "openai:responses:compact"),
|
||||
("openai_image", "openai:image"),
|
||||
("images", "openai:image"),
|
||||
("/v1/images/generations", "openai:image"),
|
||||
("/v1/images/edits", "openai:image"),
|
||||
("claude:chat", "claude:messages"),
|
||||
("claude:cli", "claude:messages"),
|
||||
("gemini:chat", "gemini:generate_content"),
|
||||
|
||||
@@ -9,7 +9,7 @@ mod proxy_nodes;
|
||||
mod templates;
|
||||
|
||||
const ADMIN_SYSTEM_DATA_EXPORT_VERSION: &str = "1.0";
|
||||
const ADMIN_SYSTEM_DATA_IMPORT_MAX_SIZE_BYTES: usize = 20 * 1024 * 1024;
|
||||
const ADMIN_SYSTEM_DATA_IMPORT_MAX_SIZE_BYTES: usize = 500 * 1024 * 1024;
|
||||
|
||||
impl<'a> AdminAppState<'a> {
|
||||
pub(crate) async fn upsert_system_config_json_value(
|
||||
|
||||
@@ -478,6 +478,73 @@ async fn gateway_imports_admin_system_config_locally_and_persists_data() {
|
||||
let _ = upstream_url;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_imports_admin_system_config_openai_image_aliases() {
|
||||
let provider_catalog_repository = Arc::new(InMemoryProviderCatalogReadRepository::seed(
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
));
|
||||
let global_model_repository = Arc::new(InMemoryGlobalModelReadRepository::seed(Vec::<
|
||||
StoredPublicGlobalModel,
|
||||
>::new()));
|
||||
let data_state = build_admin_system_data_state_with_repositories(
|
||||
Arc::clone(&provider_catalog_repository),
|
||||
Arc::clone(&global_model_repository),
|
||||
);
|
||||
let gateway = build_router_with_state(
|
||||
AppState::new()
|
||||
.expect("gateway should build")
|
||||
.with_data_state_for_tests(data_state),
|
||||
);
|
||||
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
||||
|
||||
let mut payload = sample_system_import_payload();
|
||||
payload["providers"][0]["endpoints"][0]["api_format"] = json!("openai_image");
|
||||
payload["providers"][0]["api_keys"][0]["api_formats"] = json!(["images"]);
|
||||
payload["providers"][0]["api_keys"][0]["supported_endpoints"] = json!(["openai:image"]);
|
||||
payload["providers"][0]["models"][0]["supports_image_generation"] = json!(true);
|
||||
|
||||
let response = reqwest::Client::new()
|
||||
.post(format!("{gateway_url}/api/admin/system/config/import"))
|
||||
.header(GATEWAY_HEADER, "rust-phase3b")
|
||||
.header(TRUSTED_ADMIN_USER_ID_HEADER, "admin-user-123")
|
||||
.header(TRUSTED_ADMIN_USER_ROLE_HEADER, "admin")
|
||||
.header(TRUSTED_ADMIN_SESSION_ID_HEADER, "session-123")
|
||||
.json(&payload)
|
||||
.send()
|
||||
.await
|
||||
.expect("request should succeed");
|
||||
|
||||
let status = response.status();
|
||||
let body: Value = response.json().await.expect("json body should parse");
|
||||
assert_eq!(status, StatusCode::OK, "payload={body}");
|
||||
assert_eq!(body["stats"]["endpoints"]["created"], json!(1));
|
||||
assert_eq!(body["stats"]["keys"]["created"], json!(1));
|
||||
|
||||
let providers = provider_catalog_repository
|
||||
.list_providers(false)
|
||||
.await
|
||||
.expect("providers should load");
|
||||
let provider_ids = providers
|
||||
.iter()
|
||||
.map(|provider| provider.id.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let endpoints = provider_catalog_repository
|
||||
.list_endpoints_by_provider_ids(&provider_ids)
|
||||
.await
|
||||
.expect("endpoints should load");
|
||||
assert_eq!(endpoints[0].api_format, "openai:image");
|
||||
|
||||
let keys = provider_catalog_repository
|
||||
.list_keys_by_provider_ids(&provider_ids)
|
||||
.await
|
||||
.expect("keys should load");
|
||||
assert_eq!(keys[0].api_formats, Some(json!(["openai:image"])));
|
||||
|
||||
gateway_handle.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_returns_503_for_admin_system_config_import_when_local_data_is_unavailable() {
|
||||
let upstream_hits = Arc::new(Mutex::new(0usize));
|
||||
|
||||
@@ -625,10 +625,18 @@ fn assert_usage_and_pricing(
|
||||
expected.cache_read_tokens
|
||||
);
|
||||
assert_eq!(stored_usage.total_tokens, expected.total_tokens());
|
||||
assert_eq!(
|
||||
stored_usage.response_time_ms,
|
||||
Some(expected_response_time_ms)
|
||||
);
|
||||
if expected_ttfb_ms.is_some() {
|
||||
assert!(
|
||||
stored_usage.response_time_ms >= Some(expected_response_time_ms),
|
||||
"stream response_time_ms should be at least reported telemetry: expected >= {expected_response_time_ms:?}, got {:?}",
|
||||
stored_usage.response_time_ms
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
stored_usage.response_time_ms,
|
||||
Some(expected_response_time_ms)
|
||||
);
|
||||
}
|
||||
assert_eq!(stored_usage.first_byte_time_ms, expected_ttfb_ms);
|
||||
assert_eq!(
|
||||
stored_usage.settlement_input_price_per_1m(),
|
||||
|
||||
Reference in New Issue
Block a user