mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +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:
110
crates/aether-billing/src/schema.rs
Normal file
110
crates/aether-billing/src/schema.rs
Normal file
@@ -0,0 +1,110 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub const BILLING_SNAPSHOT_SCHEMA_VERSION: &str = "2.0";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BillingSnapshotStatus {
|
||||
Complete,
|
||||
Incomplete,
|
||||
NoRule,
|
||||
Legacy,
|
||||
}
|
||||
|
||||
impl BillingSnapshotStatus {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Complete => "complete",
|
||||
Self::Incomplete => "incomplete",
|
||||
Self::NoRule => "no_rule",
|
||||
Self::Legacy => "legacy",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BillingSnapshotStatus {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct BillingSnapshot {
|
||||
pub schema_version: String,
|
||||
pub rule_id: Option<String>,
|
||||
pub rule_name: Option<String>,
|
||||
pub scope: Option<String>,
|
||||
pub expression: Option<String>,
|
||||
pub resolved_dimensions: BTreeMap<String, serde_json::Value>,
|
||||
pub resolved_variables: BTreeMap<String, serde_json::Value>,
|
||||
pub cost_breakdown: BTreeMap<String, f64>,
|
||||
pub total_cost: f64,
|
||||
pub tier_index: Option<i64>,
|
||||
pub tier_info: Option<serde_json::Value>,
|
||||
pub missing_required: Vec<String>,
|
||||
pub status: BillingSnapshotStatus,
|
||||
pub calculated_at: String,
|
||||
pub engine_version: String,
|
||||
}
|
||||
|
||||
impl Default for BillingSnapshot {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
schema_version: BILLING_SNAPSHOT_SCHEMA_VERSION.to_string(),
|
||||
rule_id: None,
|
||||
rule_name: None,
|
||||
scope: None,
|
||||
expression: None,
|
||||
resolved_dimensions: BTreeMap::new(),
|
||||
resolved_variables: BTreeMap::new(),
|
||||
cost_breakdown: BTreeMap::new(),
|
||||
total_cost: 0.0,
|
||||
tier_index: None,
|
||||
tier_info: None,
|
||||
missing_required: Vec::new(),
|
||||
status: BillingSnapshotStatus::NoRule,
|
||||
calculated_at: String::new(),
|
||||
engine_version: "2.0".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BillingSnapshot {
|
||||
pub fn dimensions_used(&self) -> &BTreeMap<String, serde_json::Value> {
|
||||
&self.resolved_dimensions
|
||||
}
|
||||
|
||||
pub fn cost(&self) -> f64 {
|
||||
self.total_cost
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CostResult {
|
||||
pub cost: f64,
|
||||
pub status: BillingSnapshotStatus,
|
||||
pub snapshot: BillingSnapshot,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{BillingSnapshot, BillingSnapshotStatus};
|
||||
|
||||
#[test]
|
||||
fn snapshot_aliases_dimensions_and_cost() {
|
||||
let mut snapshot = BillingSnapshot {
|
||||
total_cost: 1.25,
|
||||
status: BillingSnapshotStatus::Complete,
|
||||
..BillingSnapshot::default()
|
||||
};
|
||||
snapshot
|
||||
.resolved_dimensions
|
||||
.insert("input_tokens".to_string(), serde_json::json!(10));
|
||||
|
||||
assert_eq!(snapshot.cost(), 1.25);
|
||||
assert_eq!(
|
||||
snapshot.dimensions_used().get("input_tokens"),
|
||||
Some(&serde_json::json!(10))
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user