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:
fawney19
2026-04-23 14:42:51 +08:00
co-authored by Entropy.Xu
parent f55f22d2e8
commit fa328e18a1
128 changed files with 5583 additions and 690 deletions
@@ -36,12 +36,14 @@ impl<'a> AdminAppState<'a> {
&self,
key: &aether_data_contracts::repository::provider_catalog::StoredProviderCatalogKey,
provider_type: &str,
api_formats: &[String],
now_unix_secs: u64,
) -> serde_json::Value {
crate::handlers::admin::shared::build_admin_provider_key_response(
self.app,
key,
provider_type,
api_formats,
now_unix_secs,
)
}
@@ -274,6 +276,7 @@ impl<'a> AdminAppState<'a> {
String,
> {
use crate::api::ai::admin_endpoint_signature_parts;
use crate::handlers::admin::provider::write::provider::apply_admin_fixed_provider_endpoint_template_overrides;
use crate::handlers::public::{admin_requested_force_stream, normalize_admin_base_url};
use aether_admin::provider::endpoints as admin_provider_endpoints_pure;
let (fields, payload) = patch.into_parts();
@@ -346,6 +349,11 @@ impl<'a> AdminAppState<'a> {
.ok_or_else(|| format!("无效的 api_format: {}", updated.api_format))?;
updated.api_family = Some(api_family.to_string());
updated.endpoint_kind = Some(endpoint_kind.to_string());
apply_admin_fixed_provider_endpoint_template_overrides(
provider,
existing_endpoint,
&mut updated,
)?;
updated.updated_at_unix_secs = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()
@@ -113,6 +113,16 @@ impl<'a> AdminAppState<'a> {
.await
}
pub(crate) async fn read_provider_quota_snapshots(
&self,
provider_ids: &[String],
) -> Result<
Vec<aether_data_contracts::repository::quota::StoredProviderQuotaSnapshot>,
GatewayError,
> {
self.app.read_provider_quota_snapshots(provider_ids).await
}
pub(crate) async fn update_provider_catalog_key_health_state(
&self,
key_id: &str,
@@ -465,6 +465,7 @@ impl<'a> AdminAppState<'a> {
pub(crate) async fn create_provider_oauth_catalog_key(
&self,
provider_id: &str,
provider_type: &str,
name: &str,
access_token: &str,
auth_config: &serde_json::Map<String, serde_json::Value>,
@@ -478,6 +479,7 @@ impl<'a> AdminAppState<'a> {
crate::handlers::admin::provider::oauth::provisioning::create_provider_oauth_catalog_key(
self,
provider_id,
provider_type,
name,
access_token,
auth_config,
@@ -491,8 +493,10 @@ impl<'a> AdminAppState<'a> {
pub(crate) async fn update_existing_provider_oauth_catalog_key(
&self,
existing_key: &aether_data_contracts::repository::provider_catalog::StoredProviderCatalogKey,
provider_type: &str,
access_token: &str,
auth_config: &serde_json::Map<String, serde_json::Value>,
api_formats: &[String],
proxy: Option<serde_json::Value>,
expires_at_unix_secs: Option<u64>,
) -> Result<
@@ -502,8 +506,10 @@ impl<'a> AdminAppState<'a> {
crate::handlers::admin::provider::oauth::provisioning::update_existing_provider_oauth_catalog_key(
self,
existing_key,
provider_type,
access_token,
auth_config,
api_formats,
proxy,
expires_at_unix_secs,
)
@@ -94,7 +94,7 @@ impl<'a> AdminAppState<'a> {
pub(crate) fn fixed_provider_template(
&self,
provider_type: &str,
) -> Option<(&'static str, &'static [&'static str])> {
) -> Option<&'static crate::provider_transport::provider_types::FixedProviderTemplate> {
crate::provider_transport::provider_types::fixed_provider_template(provider_type)
}