mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-11 19:59:50 +08:00
feat: provider api_formats 可空继承、OpenAI 图片 edit/variation 与用量配额多项补强
- 鉴权: provider_api_keys.api_formats 改为可空,OAuth 托管 key 自动继承 provider endpoints 激活格式,相关 handler/测试同步更新 - 图片 planner: OpenAI 图片路由新增 edit/variation 操作并完善参数校验、响应合并与流式处理 - 用量: user me usage 返回区分 client_requested_stream/upstream_is_stream,前端 usage 列表筛选与展示增强 - 统计: stats_daily_model 新增 cache_creation_ephemeral_5m/1h tokens 字段与回填链路 - 配额/observability: quota repository 新增内存与 SQL 扩展,admin observability usage 字段扩充 - 其它: OAuth 导入/轮询收敛、provider 汇总与 pool admin 读写链路小修、新增 system_config 缓存与 provider template handler Closes #318 Co-authored-by: Entropy.Xu <[email protected]>
This commit is contained in:
@@ -3,8 +3,6 @@ use crate::handlers::admin::request::AdminAppState;
|
||||
use aether_data_contracts::repository::provider_catalog::{
|
||||
StoredProviderCatalogEndpoint, StoredProviderCatalogKey,
|
||||
};
|
||||
use aether_data_contracts::repository::quota::StoredProviderQuotaSnapshot;
|
||||
use futures_util::future::join_all;
|
||||
use serde_json::json;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
@@ -235,17 +233,6 @@ pub(crate) async fn build_admin_providers_summary_payload(
|
||||
.or_default()
|
||||
.insert(row.global_model_id);
|
||||
}
|
||||
let quota_snapshots_by_provider = join_all(provider_ids.iter().map(|provider_id| async {
|
||||
let quota_snapshot = state
|
||||
.read_provider_quota_snapshot(provider_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten();
|
||||
(provider_id.clone(), quota_snapshot)
|
||||
}))
|
||||
.await
|
||||
.into_iter()
|
||||
.collect::<BTreeMap<String, Option<StoredProviderQuotaSnapshot>>>();
|
||||
let now_unix_secs = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
@@ -268,9 +255,7 @@ pub(crate) async fn build_admin_providers_summary_payload(
|
||||
.get(&provider.id)
|
||||
.map(Vec::as_slice)
|
||||
.unwrap_or(&[]),
|
||||
quota_snapshots_by_provider
|
||||
.get(&provider.id)
|
||||
.and_then(Option::as_ref),
|
||||
None,
|
||||
model_stats_by_provider.get(&provider.id),
|
||||
active_global_model_ids,
|
||||
now_unix_secs,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::handlers::admin::shared::unix_secs_to_rfc3339;
|
||||
use crate::handlers::public::{
|
||||
provider_key_api_formats, request_candidate_event_unix_ms, request_candidate_status_label,
|
||||
};
|
||||
use crate::handlers::public::{request_candidate_event_unix_ms, request_candidate_status_label};
|
||||
use crate::provider_key_auth::provider_key_effective_api_formats;
|
||||
use aether_data_contracts::repository::candidates::{
|
||||
RequestCandidateStatus, StoredRequestCandidate,
|
||||
};
|
||||
@@ -66,7 +65,9 @@ pub(crate) fn build_admin_provider_summary_value(
|
||||
keys_by_endpoint.entry(endpoint.id.clone()).or_default();
|
||||
}
|
||||
for key in keys {
|
||||
for api_format in provider_key_api_formats(key) {
|
||||
for api_format in
|
||||
provider_key_effective_api_formats(key, &provider.provider_type, endpoints)
|
||||
{
|
||||
if let Some(endpoint_id) = format_to_endpoint_id.get(&api_format) {
|
||||
keys_by_endpoint
|
||||
.entry(endpoint_id.clone())
|
||||
@@ -131,6 +132,26 @@ pub(crate) fn build_admin_provider_summary_value(
|
||||
.and_then(|cfg| cfg.get("architecture_id"))
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(ToOwned::to_owned);
|
||||
let billing_type = quota_snapshot
|
||||
.map(|quota| quota.billing_type.clone())
|
||||
.or_else(|| provider.billing_type.clone());
|
||||
let monthly_quota_usd = quota_snapshot
|
||||
.and_then(|quota| quota.monthly_quota_usd)
|
||||
.or(provider.monthly_quota_usd);
|
||||
let monthly_used_usd = quota_snapshot
|
||||
.map(|quota| quota.monthly_used_usd)
|
||||
.or(provider.monthly_used_usd);
|
||||
let quota_reset_day = quota_snapshot
|
||||
.and_then(|quota| quota.quota_reset_day)
|
||||
.or(provider.quota_reset_day);
|
||||
let quota_last_reset_at = quota_snapshot
|
||||
.and_then(|quota| quota.quota_last_reset_at_unix_secs)
|
||||
.or(provider.quota_last_reset_at_unix_secs)
|
||||
.and_then(unix_secs_to_rfc3339);
|
||||
let quota_expires_at = quota_snapshot
|
||||
.and_then(|quota| quota.quota_expires_at_unix_secs)
|
||||
.or(provider.quota_expires_at_unix_secs)
|
||||
.and_then(unix_secs_to_rfc3339);
|
||||
|
||||
json!({
|
||||
"id": provider.id.clone(),
|
||||
@@ -142,16 +163,12 @@ pub(crate) fn build_admin_provider_summary_value(
|
||||
"keep_priority_on_conversion": provider.keep_priority_on_conversion,
|
||||
"enable_format_conversion": provider.enable_format_conversion,
|
||||
"is_active": provider.is_active,
|
||||
"billing_type": quota_snapshot.map(|quota| quota.billing_type.clone()),
|
||||
"monthly_quota_usd": quota_snapshot.and_then(|quota| quota.monthly_quota_usd),
|
||||
"monthly_used_usd": quota_snapshot.map(|quota| quota.monthly_used_usd),
|
||||
"quota_reset_day": quota_snapshot.and_then(|quota| quota.quota_reset_day),
|
||||
"quota_last_reset_at": quota_snapshot
|
||||
.and_then(|quota| quota.quota_last_reset_at_unix_secs)
|
||||
.and_then(unix_secs_to_rfc3339),
|
||||
"quota_expires_at": quota_snapshot
|
||||
.and_then(|quota| quota.quota_expires_at_unix_secs)
|
||||
.and_then(unix_secs_to_rfc3339),
|
||||
"billing_type": billing_type,
|
||||
"monthly_quota_usd": monthly_quota_usd,
|
||||
"monthly_used_usd": monthly_used_usd,
|
||||
"quota_reset_day": quota_reset_day,
|
||||
"quota_last_reset_at": quota_last_reset_at,
|
||||
"quota_expires_at": quota_expires_at,
|
||||
"max_retries": provider.max_retries,
|
||||
"proxy": provider.proxy.clone(),
|
||||
"stream_first_byte_timeout": provider.stream_first_byte_timeout_secs,
|
||||
|
||||
Reference in New Issue
Block a user