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:
fawney19
2026-04-10 17:44:55 +08:00
parent 5014e2f5fd
commit 010ab127e2
64 changed files with 4217 additions and 477 deletions

View File

@@ -129,6 +129,13 @@ fn build_dimensions(input: &BillingUsageInput) -> BTreeMap<String, Value> {
input.input_tokens,
input.cache_read_tokens,
);
let classified_cache_creation_tokens = input
.cache_creation_ephemeral_5m_tokens
.saturating_add(input.cache_creation_ephemeral_1h_tokens);
let cache_creation_uncategorized_tokens = input
.cache_creation_tokens
.saturating_sub(classified_cache_creation_tokens)
.max(0);
let total_input_context = input
.input_tokens
.saturating_add(input.cache_creation_tokens)
@@ -141,6 +148,18 @@ fn build_dimensions(input: &BillingUsageInput) -> BTreeMap<String, Value> {
"cache_creation_tokens".to_string(),
json!(input.cache_creation_tokens),
),
(
"cache_creation_ephemeral_5m_tokens".to_string(),
json!(input.cache_creation_ephemeral_5m_tokens),
),
(
"cache_creation_ephemeral_1h_tokens".to_string(),
json!(input.cache_creation_ephemeral_1h_tokens),
),
(
"cache_creation_uncategorized_tokens".to_string(),
json!(cache_creation_uncategorized_tokens),
),
(
"cache_read_tokens".to_string(),
json!(input.cache_read_tokens),
@@ -159,6 +178,15 @@ fn build_dimensions(input: &BillingUsageInput) -> BTreeMap<String, Value> {
),
]);
out.insert(
"cache_creation_ephemeral_5m_ttl_minutes".to_string(),
json!(5),
);
out.insert(
"cache_creation_ephemeral_1h_ttl_minutes".to_string(),
json!(60),
);
if let Some(cache_ttl_minutes) = input.cache_ttl_minutes {
out.insert(
"cache_ttl_minutes".to_string(),
@@ -223,6 +251,8 @@ mod tests {
input_tokens: 1_000,
output_tokens: 500,
cache_creation_tokens: 0,
cache_creation_ephemeral_5m_tokens: 0,
cache_creation_ephemeral_1h_tokens: 0,
cache_read_tokens: 100,
cache_ttl_minutes: Some(60),
},