refactor: 大规模模块拆分与代码精简,新增 ai-pipeline/data-contracts 独立 crate

- 新增 aether-ai-pipeline 和 aether-data-contracts crate,将 pipeline 逻辑与数据契约从 gateway 中解耦
- 重构 admin handlers:拆分单体模块为 auth/billing/endpoint/features/model/observability/provider/system 等独立子模块
- 合并 chat/cli 重复代码路径:精简 conversion、finalize、planner 中的 sync/chat/cli 分支
- 重构 scheduler/executor/data 层,引入 facade 模式降低模块间耦合
- 移除冗余的 intent 模块,将 plan_fallback/policy/stream_path/sync_path 迁移至 executor
- 前端适配:调整 admin API 调用和 provider 模型测试对话框
This commit is contained in:
fawney19
2026-04-07 02:50:19 +08:00
parent 763ff03a7b
commit 5d96d6673b
732 changed files with 28589 additions and 20662 deletions
@@ -0,0 +1,7 @@
mod types;
pub use types::{
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
AdminBillingRuleRecord, AdminBillingRuleWriteInput, BillingReadRepository,
StoredBillingModelContext,
};
@@ -0,0 +1,153 @@
use async_trait::async_trait;
use serde_json::Value;
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct StoredBillingModelContext {
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 StoredBillingModelContext {
#[allow(clippy::too_many_arguments)]
pub fn new(
provider_id: String,
provider_billing_type: Option<String>,
provider_api_key_id: Option<String>,
provider_api_key_rate_multipliers: Option<Value>,
provider_api_key_cache_ttl_minutes: Option<i64>,
global_model_id: String,
global_model_name: String,
global_model_config: Option<Value>,
default_price_per_request: Option<f64>,
default_tiered_pricing: Option<Value>,
model_id: Option<String>,
model_provider_model_name: Option<String>,
model_config: Option<Value>,
model_price_per_request: Option<f64>,
model_tiered_pricing: Option<Value>,
) -> Result<Self, crate::DataLayerError> {
if provider_id.trim().is_empty() {
return Err(crate::DataLayerError::UnexpectedValue(
"billing.provider_id is empty".to_string(),
));
}
if global_model_id.trim().is_empty() {
return Err(crate::DataLayerError::UnexpectedValue(
"billing.global_model_id is empty".to_string(),
));
}
if global_model_name.trim().is_empty() {
return Err(crate::DataLayerError::UnexpectedValue(
"billing.global_model_name is empty".to_string(),
));
}
Ok(Self {
provider_id,
provider_billing_type,
provider_api_key_id,
provider_api_key_rate_multipliers,
provider_api_key_cache_ttl_minutes,
global_model_id,
global_model_name,
global_model_config,
default_price_per_request,
default_tiered_pricing,
model_id,
model_provider_model_name,
model_config,
model_price_per_request,
model_tiered_pricing,
})
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AdminBillingRuleRecord {
pub id: String,
pub name: String,
pub task_type: String,
pub global_model_id: Option<String>,
pub model_id: Option<String>,
pub expression: String,
pub variables: Value,
pub dimension_mappings: Value,
pub is_enabled: bool,
pub created_at_unix_secs: u64,
pub updated_at_unix_secs: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AdminBillingRuleWriteInput {
pub name: String,
pub task_type: String,
pub global_model_id: Option<String>,
pub model_id: Option<String>,
pub expression: String,
pub variables: Value,
pub dimension_mappings: Value,
pub is_enabled: bool,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AdminBillingCollectorRecord {
pub id: String,
pub api_format: String,
pub task_type: String,
pub dimension_name: String,
pub source_type: String,
pub source_path: Option<String>,
pub value_type: String,
pub transform_expression: Option<String>,
pub default_value: Option<String>,
pub priority: i32,
pub is_enabled: bool,
pub created_at_unix_secs: u64,
pub updated_at_unix_secs: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AdminBillingCollectorWriteInput {
pub api_format: String,
pub task_type: String,
pub dimension_name: String,
pub source_type: String,
pub source_path: Option<String>,
pub value_type: String,
pub transform_expression: Option<String>,
pub default_value: Option<String>,
pub priority: i32,
pub is_enabled: bool,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AdminBillingPresetApplyResult {
pub preset: String,
pub mode: String,
pub created: u64,
pub updated: u64,
pub skipped: u64,
pub errors: Vec<String>,
}
#[async_trait]
pub trait BillingReadRepository: Send + Sync {
async fn find_model_context(
&self,
provider_id: &str,
provider_api_key_id: Option<&str>,
global_model_name: &str,
) -> Result<Option<StoredBillingModelContext>, crate::DataLayerError>;
}