mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
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:
94
crates/aether-billing/src/pricing.rs
Normal file
94
crates/aether-billing/src/pricing.rs
Normal 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,
|
||||
}
|
||||
Reference in New Issue
Block a user