refactor: 优化调度候选排序与用量写入链路并改进 Fernet 缓存与前端批量列表

This commit is contained in:
fawney19
2026-04-21 16:19:07 +08:00
parent c5c56ff92f
commit 25a2b417be
77 changed files with 4801 additions and 2881 deletions

View File

@@ -80,7 +80,7 @@ pub use crate::conversion::{
pub use crate::finalize::common::{
build_generated_tool_call_id, build_local_success_background_report,
build_local_success_conversion_background_report, canonicalize_tool_arguments,
prepare_local_success_response_parts,
prepare_local_success_response_parts, prepare_local_success_response_parts_owned,
};
pub use crate::finalize::sse::{encode_done_sse, encode_json_sse, map_claude_stop_reason};
pub use crate::finalize::standard::claude::stream::{ClaudeClientEmitter, ClaudeProviderState};

View File

@@ -21,7 +21,13 @@ pub fn prepare_local_success_response_parts(
headers: &BTreeMap<String, String>,
body_json: &Value,
) -> serde_json::Result<(Vec<u8>, BTreeMap<String, String>)> {
let mut headers = headers.clone();
prepare_local_success_response_parts_owned(headers.clone(), body_json)
}
pub fn prepare_local_success_response_parts_owned(
mut headers: BTreeMap<String, String>,
body_json: &Value,
) -> serde_json::Result<(Vec<u8>, BTreeMap<String, String>)> {
headers.remove("content-encoding");
headers.remove("content-length");
headers.insert("content-type".to_string(), "application/json".to_string());
@@ -77,7 +83,7 @@ mod tests {
use super::{
build_generated_tool_call_id, build_local_success_background_report,
build_local_success_conversion_background_report, canonicalize_tool_arguments,
prepare_local_success_response_parts,
prepare_local_success_response_parts, prepare_local_success_response_parts_owned,
};
use aether_usage_runtime::GatewaySyncReportRequest;
use std::collections::BTreeMap;
@@ -127,6 +133,37 @@ mod tests {
);
}
#[test]
fn prepare_local_success_response_parts_owned_normalizes_headers() {
let headers = BTreeMap::from([
("content-encoding".to_string(), "gzip".to_string()),
("content-length".to_string(), "999".to_string()),
("x-test".to_string(), "1".to_string()),
]);
let (body_bytes, normalized_headers) =
prepare_local_success_response_parts_owned(headers, &serde_json::json!({"ok": true}))
.expect("response parts should serialize");
assert_eq!(
serde_json::from_slice::<Value>(&body_bytes).expect("json body"),
serde_json::json!({"ok": true})
);
assert_eq!(
normalized_headers.get("content-type").map(String::as_str),
Some("application/json")
);
assert!(!normalized_headers.contains_key("content-encoding"));
let expected_length = body_bytes.len().to_string();
assert_eq!(
normalized_headers.get("content-length").map(String::as_str),
Some(expected_length.as_str())
);
assert_eq!(
normalized_headers.get("x-test").map(String::as_str),
Some("1")
);
}
#[test]
fn build_local_success_background_report_maps_finalize_kind() {
let payload = GatewaySyncReportRequest {

View File

@@ -1,3 +1,5 @@
use std::borrow::Cow;
use aether_provider_transport::url::{
build_claude_messages_url, build_gemini_content_url, build_openai_chat_url,
build_openai_cli_url, build_passthrough_path_url,
@@ -30,13 +32,13 @@ pub fn build_standard_request_body(
body_rules: Option<&Value>,
user_api_key_id: Option<&str>,
) -> Option<Value> {
let canonical_request = normalize_standard_request_to_openai_chat_request(
let canonical_request = normalize_standard_request_to_openai_chat_request_cow(
body_json,
client_api_format,
request_path,
)?;
let mut provider_request_body = build_standard_request_body_from_canonical(
&canonical_request,
canonical_request.as_ref(),
mapped_model,
provider_api_format,
upstream_is_stream,
@@ -99,14 +101,29 @@ pub fn normalize_standard_request_to_openai_chat_request(
client_api_format: &str,
request_path: &str,
) -> Option<Value> {
normalize_standard_request_to_openai_chat_request_cow(
body_json,
client_api_format,
request_path,
)
.map(Cow::into_owned)
}
fn normalize_standard_request_to_openai_chat_request_cow<'a>(
body_json: &'a Value,
client_api_format: &str,
request_path: &str,
) -> Option<Cow<'a, Value>> {
match client_api_format.trim().to_ascii_lowercase().as_str() {
"openai:chat" => Some(body_json.clone()),
"openai:chat" => Some(Cow::Borrowed(body_json)),
"openai:cli" | "openai:compact" => {
normalize_openai_cli_request_to_openai_chat_request(body_json)
normalize_openai_cli_request_to_openai_chat_request(body_json).map(Cow::Owned)
}
"claude:chat" | "claude:cli" => {
normalize_claude_request_to_openai_chat_request(body_json).map(Cow::Owned)
}
"claude:chat" | "claude:cli" => normalize_claude_request_to_openai_chat_request(body_json),
"gemini:chat" | "gemini:cli" => {
normalize_gemini_request_to_openai_chat_request(body_json, request_path)
normalize_gemini_request_to_openai_chat_request(body_json, request_path).map(Cow::Owned)
}
_ => None,
}