feat: 扩展 Rust gateway 全功能模块,新增 billing/crypto/wallet crate 及完整数据层

- 新增 aether-billing、aether-crypto、aether-wallet 独立 crate
- aether-data 扩展 repository 层:announcements、auth_modules、billing、
  candidate_selection、gemini_file_mappings、global_models、management_tokens、
  oauth_providers、proxy_nodes、quota、users、wallet 等模块
- aether-gateway 新增 api/auth/billing/control/middleware/scheduler/usage/
  video_tasks/hooks/maintenance/model_fetch/provider_transport 等功能模块
- 重构 executor decision 和 gateway state 为模块目录结构
- 新增 gateway router、frontdoor 路由层及对应测试
- Python 侧 API 路由重构,新增 compat/support 模块
- 前端 Logo 组件更新及 Provider 管理页面调整
This commit is contained in:
fawney19
2026-03-31 19:19:04 +08:00
parent b5a0070023
commit ddf18fed9a
690 changed files with 235087 additions and 16301 deletions

View File

@@ -0,0 +1,94 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BillingModelPricingSnapshot {
pub provider_id: String,
pub provider_billing_type: Option<String>,
pub provider_api_key_id: Option<String>,
pub provider_api_key_rate_multipliers: Option<Value>,
pub provider_api_key_cache_ttl_minutes: Option<i64>,
pub global_model_id: String,
pub global_model_name: String,
pub global_model_config: Option<Value>,
pub default_price_per_request: Option<f64>,
pub default_tiered_pricing: Option<Value>,
pub model_id: Option<String>,
pub model_provider_model_name: Option<String>,
pub model_config: Option<Value>,
pub model_price_per_request: Option<f64>,
pub model_tiered_pricing: Option<Value>,
}
impl BillingModelPricingSnapshot {
pub fn effective_tiered_pricing(&self) -> Option<&Value> {
self.model_tiered_pricing
.as_ref()
.or(self.default_tiered_pricing.as_ref())
}
pub fn effective_price_per_request(&self) -> Option<f64> {
self.model_price_per_request
.or(self.default_price_per_request)
}
pub fn is_free_tier(&self) -> bool {
self.provider_billing_type
.as_deref()
.map(|value| value.eq_ignore_ascii_case("free_tier"))
.unwrap_or(false)
}
pub fn rate_multiplier_for_api_format(&self, api_format: Option<&str>) -> f64 {
let Some(api_format) = api_format.map(str::trim).filter(|value| !value.is_empty()) else {
return 1.0;
};
let normalized = api_format.to_ascii_lowercase();
let Some(mapping) = self
.provider_api_key_rate_multipliers
.as_ref()
.and_then(Value::as_object)
else {
return 1.0;
};
mapping
.get(&normalized)
.and_then(|value| value.as_f64())
.unwrap_or(1.0)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BillingUsageInput {
pub task_type: String,
pub api_format: Option<String>,
pub request_count: i64,
pub input_tokens: i64,
pub output_tokens: i64,
pub cache_creation_tokens: i64,
pub cache_read_tokens: i64,
pub cache_ttl_minutes: Option<i64>,
}
impl BillingUsageInput {
pub fn new(task_type: impl Into<String>) -> Self {
Self {
task_type: task_type.into(),
api_format: None,
request_count: 1,
input_tokens: 0,
output_tokens: 0,
cache_creation_tokens: 0,
cache_read_tokens: 0,
cache_ttl_minutes: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BillingComputation {
pub cost_result: crate::CostResult,
pub actual_total_cost: f64,
pub rate_multiplier: f64,
pub is_free_tier: bool,
}