release: v1.10.0

This commit is contained in:
coso
2026-04-13 13:07:08 +08:00
parent 0f15b8a71e
commit bf03e44ac7
273 changed files with 12344 additions and 26363 deletions
+18 -1
View File
@@ -6,7 +6,7 @@
//! **Validates: Requirements 9.1**
use crate::database::dao::api_key_provider::{
ApiKeyEntry, ApiKeyProvider, ApiProviderType, ProviderWithKeys,
ApiKeyEntry, ApiKeyProvider, ApiProviderPromptCacheMode, ApiProviderType, ProviderWithKeys,
};
use crate::database::system_providers::get_system_providers;
use crate::database::DbConnection;
@@ -35,6 +35,7 @@ pub struct AddCustomProviderRequest {
pub project: Option<String>,
pub location: Option<String>,
pub region: Option<String>,
pub prompt_cache_mode: Option<String>,
}
/// 更新 Provider 请求
@@ -51,6 +52,7 @@ pub struct UpdateProviderRequest {
pub project: Option<String>,
pub location: Option<String>,
pub region: Option<String>,
pub prompt_cache_mode: Option<String>,
/// 自定义模型列表
pub custom_models: Option<Vec<String>>,
}
@@ -81,6 +83,8 @@ pub struct ProviderDisplay {
pub region: Option<String>,
/// 自定义模型列表
pub custom_models: Vec<String>,
/// 当前 Provider 声明的 Prompt Cache 模式(前端优先使用该值,不再只按 type 猜)
pub prompt_cache_mode: Option<String>,
pub api_key_count: usize,
pub created_at: String,
pub updated_at: String,
@@ -156,6 +160,9 @@ fn provider_to_display(provider: &ApiKeyProvider, api_key_count: usize) -> Provi
location: provider.location.clone(),
region: provider.region.clone(),
custom_models: provider.custom_models.clone(),
prompt_cache_mode: provider
.effective_prompt_cache_mode()
.map(|mode| mode.to_string()),
api_key_count,
created_at: provider.created_at.to_rfc3339(),
updated_at: provider.updated_at.to_rfc3339(),
@@ -306,6 +313,11 @@ pub fn add_custom_api_key_provider(
request.project,
request.location,
request.region,
request
.prompt_cache_mode
.map(|mode| mode.parse::<ApiProviderPromptCacheMode>())
.transpose()
.map_err(|e: String| format!("无效的 Prompt Cache 模式: {e}"))?,
)?;
Ok(provider_to_display(&provider, 0))
@@ -338,6 +350,11 @@ pub fn update_api_key_provider(
request.project,
request.location,
request.region,
request
.prompt_cache_mode
.map(|mode| mode.parse::<ApiProviderPromptCacheMode>())
.transpose()
.map_err(|e: String| format!("无效的 Prompt Cache 模式: {e}"))?,
request.custom_models,
)?;
@@ -2049,6 +2049,10 @@ fn resolve_runtime_message_usage_from_session(
.cached_input_tokens
.filter(|value| *value >= 0)
.map(|value| value as u32),
cache_creation_input_tokens: session
.cache_creation_input_tokens
.filter(|value| *value >= 0)
.map(|value| value as u32),
})
}
_ => None,
@@ -2082,6 +2086,7 @@ fn persist_latest_assistant_message_usage(
usage.input_tokens,
usage.output_tokens,
usage.cached_input_tokens,
usage.cache_creation_input_tokens,
)?;
Ok(())
}
@@ -2110,6 +2115,11 @@ fn build_compaction_session_metrics_update(
} else {
Some(0)
};
let cache_creation_input_tokens = if usage.usage.output_tokens.is_some() {
usage.usage.cache_creation_input_tokens
} else {
Some(0)
};
let current_window_tokens = usage
.usage
@@ -2121,6 +2131,7 @@ fn build_compaction_session_metrics_update(
schedule_id,
current_window_tokens,
cached_input_tokens,
cache_creation_input_tokens,
accumulated_total_tokens: accumulated_total,
accumulated_input_tokens: accumulated_input,
accumulated_output_tokens: accumulated_output,
@@ -3482,6 +3493,7 @@ mod tests {
.input_tokens(Some(60))
.output_tokens(Some(30))
.cached_input_tokens(Some(12))
.cache_creation_input_tokens(Some(4))
.accumulated_total_tokens(Some(300))
.accumulated_input_tokens(Some(200))
.accumulated_output_tokens(Some(100))
@@ -3494,7 +3506,9 @@ mod tests {
let usage = ProviderUsage::new(
"gpt-4.1".to_string(),
Usage::new(Some(120), Some(45), Some(165)).with_cached_input_tokens(Some(90)),
Usage::new(Some(120), Some(45), Some(165))
.with_cached_input_tokens(Some(90))
.with_cache_creation_input_tokens(Some(30)),
);
update_compaction_session_metrics(&session_config, &usage)
@@ -3510,6 +3524,7 @@ mod tests {
assert_eq!(updated.input_tokens, Some(45));
assert_eq!(updated.output_tokens, Some(0));
assert_eq!(updated.cached_input_tokens, Some(90));
assert_eq!(updated.cache_creation_input_tokens, Some(30));
assert_eq!(updated.accumulated_total_tokens, Some(465));
assert_eq!(updated.accumulated_input_tokens, Some(320));
assert_eq!(updated.accumulated_output_tokens, Some(145));
@@ -3538,6 +3553,7 @@ mod tests {
.input_tokens(Some(120))
.output_tokens(Some(60))
.cached_input_tokens(Some(24))
.cache_creation_input_tokens(Some(8))
.accumulated_total_tokens(Some(700))
.accumulated_input_tokens(Some(500))
.accumulated_output_tokens(Some(200))
@@ -3563,6 +3579,7 @@ mod tests {
assert_eq!(updated.input_tokens, Some(0));
assert_eq!(updated.output_tokens, Some(0));
assert_eq!(updated.cached_input_tokens, Some(0));
assert_eq!(updated.cache_creation_input_tokens, Some(0));
assert_eq!(updated.accumulated_total_tokens, Some(700));
assert_eq!(updated.accumulated_input_tokens, Some(500));
assert_eq!(updated.accumulated_output_tokens, Some(200));
@@ -3591,6 +3608,7 @@ mod tests {
.input_tokens(Some(10))
.output_tokens(Some(10))
.cached_input_tokens(Some(6))
.cache_creation_input_tokens(Some(2))
.accumulated_total_tokens(Some(200))
.accumulated_input_tokens(Some(120))
.accumulated_output_tokens(Some(80))
@@ -3601,7 +3619,9 @@ mod tests {
let session_config = SessionConfigBuilder::new(&session.id).build();
let usage = ProviderUsage::new(
"gpt-4.1".to_string(),
Usage::new(Some(30), Some(15), Some(45)).with_cached_input_tokens(Some(18)),
Usage::new(Some(30), Some(15), Some(45))
.with_cached_input_tokens(Some(18))
.with_cache_creation_input_tokens(Some(6)),
);
update_compaction_session_metrics(&session_config, &usage)
@@ -3617,6 +3637,7 @@ mod tests {
assert_eq!(updated.input_tokens, Some(15));
assert_eq!(updated.output_tokens, Some(0));
assert_eq!(updated.cached_input_tokens, Some(18));
assert_eq!(updated.cache_creation_input_tokens, Some(6));
assert_eq!(updated.accumulated_total_tokens, Some(245));
assert_eq!(updated.accumulated_input_tokens, Some(150));
assert_eq!(updated.accumulated_output_tokens, Some(95));
@@ -3642,6 +3663,7 @@ mod tests {
.input_tokens(Some(204))
.output_tokens(Some(88))
.cached_input_tokens(Some(160))
.cache_creation_input_tokens(Some(48))
.apply()
.await
.expect("写入 usage 失败");
@@ -3654,8 +3676,9 @@ mod tests {
value.input_tokens,
value.output_tokens,
value.cached_input_tokens,
value.cache_creation_input_tokens,
)),
Some((204, 88, Some(160)))
Some((204, 88, Some(160), Some(48)))
);
}
other => panic!("收到意外事件: {:?}", other),
+1
View File
@@ -253,6 +253,7 @@ pub async fn save_relay_api_key(
None, // project
None, // location
None, // region
None, // prompt_cache_mode
)
.map_err(|e| ConnectError {
code: "CREATE_PROVIDER_FAILED".to_string(),