mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat: 扩展 cache creation token 细分统计与 effective_input_tokens 计费逻辑
- 新增 cache_creation_ephemeral_5m/1h_input_tokens 字段,区分不同 TTL 的缓存写入 token - 引入 effective_input_tokens(扣除 cache read 后的有效输入 token),暴露给 usage 接口 - billing 规则生成器支持 5m/1h ephemeral cache 独立定价与分级计费 - usage_mapper 增加 Claude/Anthropic 格式映射,修复 OpenAI responses 格式字段兼容性 - 迁移逻辑增强:支持 checksum 容错、applied/pending 数量日志、逐步执行信息输出 - executor 抽离 LocalExecutionRequestOutcome 类型,统一 sync/stream 路径返回语义 - provider-transport auth 层新增 complete passthrough headers 构建逻辑 - 前端 usage 类型全面补充 effective_input_tokens、cache_creation_tokens、total_input_context 字段
This commit is contained in:
@@ -184,6 +184,7 @@ pub fn apply_codex_openai_cli_special_headers(
|
||||
if let Some(account_id) = extract_codex_account_id(decrypted_auth_config_raw) {
|
||||
provider_request_headers.insert("chatgpt-account-id".to_string(), account_id);
|
||||
}
|
||||
|
||||
if !provider_request_headers
|
||||
.get("x-client-request-id")
|
||||
.map(|value| !value.trim().is_empty())
|
||||
@@ -200,6 +201,7 @@ pub fn apply_codex_openai_cli_special_headers(
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
|
||||
let Some(short_id) = prompt_cache_key.and_then(build_short_codex_header_id) else {
|
||||
return;
|
||||
};
|
||||
@@ -213,6 +215,7 @@ pub fn apply_codex_openai_cli_special_headers(
|
||||
.eq_ignore_ascii_case("openai:compact")
|
||||
&& !header_map_has_non_empty_value(original_headers, "conversation_id")
|
||||
{
|
||||
provider_request_headers.insert("conversation_id".to_string(), short_id);
|
||||
let session_id = provider_request_headers.get("session_id").unwrap();
|
||||
provider_request_headers.insert("conversation_id".to_string(), session_id.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +124,18 @@ pub fn build_cross_format_openai_cli_request_body(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::build_local_openai_cli_request_body;
|
||||
use super::{build_cross_format_openai_cli_request_body, build_local_openai_chat_request_body};
|
||||
use serde_json::json;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
fn object_keys(value: &Value) -> Vec<&str> {
|
||||
value
|
||||
.as_object()
|
||||
.expect("json object")
|
||||
.keys()
|
||||
.map(String::as_str)
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_openai_chat_cross_format_request_body_from_openai_cli_source() {
|
||||
@@ -148,6 +158,29 @@ mod tests {
|
||||
assert_eq!(provider_request_body["messages"][0]["content"], "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_openai_cli_request_body_preserves_original_field_order() {
|
||||
let body_json: Value = serde_json::from_str(
|
||||
r#"{
|
||||
"model": "gpt-5",
|
||||
"include": ["reasoning.encrypted_content"],
|
||||
"input": [],
|
||||
"instructions": "Keep order"
|
||||
}"#,
|
||||
)
|
||||
.expect("request json should parse");
|
||||
|
||||
let provider_request_body =
|
||||
build_local_openai_cli_request_body(&body_json, "gpt-5-upstream", false)
|
||||
.expect("openai cli body should build");
|
||||
|
||||
assert_eq!(
|
||||
object_keys(&provider_request_body),
|
||||
vec!["model", "include", "input", "instructions"]
|
||||
);
|
||||
assert_eq!(provider_request_body["model"], "gpt-5-upstream");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_streaming_local_openai_chat_request_body_with_include_usage() {
|
||||
let body_json = json!({
|
||||
|
||||
Reference in New Issue
Block a user