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 28593 additions and 20666 deletions

View File

@@ -1,7 +1,7 @@
use std::time::{SystemTime, UNIX_EPOCH};
use aether_contracts::ExecutionResult;
use aether_data::repository::video_tasks::{
use aether_data_contracts::repository::video_tasks::{
StoredVideoTask, VideoTaskQueryFilter, VideoTaskStatus,
};
use axum::body::Body;
@@ -63,7 +63,7 @@ pub(crate) async fn get_video_task_stats(
pub(crate) async fn get_video_task_detail(
State(state): State<AppState>,
Path(task_id): Path<String>,
) -> Result<Json<aether_data::repository::video_tasks::StoredVideoTask>, axum::response::Response> {
) -> Result<Json<StoredVideoTask>, axum::response::Response> {
let task = read_video_task_detail(&state, &task_id)
.await
.map_err(IntoResponse::into_response)?;

View File

@@ -1,4 +1,6 @@
use aether_data::repository::video_tasks::{StoredVideoTask, UpsertVideoTask, VideoTaskStatus};
use aether_data_contracts::repository::video_tasks::{
StoredVideoTask, UpsertVideoTask, VideoTaskStatus,
};
use axum::response::IntoResponse;
use axum::Json;
use serde_json::{json, Map, Value};
@@ -126,19 +128,16 @@ async fn execute_video_task_cancel_plan(
trace_id: &str,
plan: aether_contracts::ExecutionPlan,
) -> Result<(), axum::response::Response> {
let result = crate::execution_runtime::execute_execution_runtime_sync_plan(
state,
Some(trace_id),
&plan,
)
.await
.map_err(|err| {
GatewayError::UpstreamUnavailable {
trace_id: trace_id.to_string(),
message: format!("{err:?}"),
}
.into_response()
})?;
let result =
crate::execution_runtime::execute_execution_runtime_sync_plan(state, Some(trace_id), &plan)
.await
.map_err(|err| {
GatewayError::UpstreamUnavailable {
trace_id: trace_id.to_string(),
message: format!("{err:?}"),
}
.into_response()
})?;
if result.status_code >= 400 {
let status = axum::http::StatusCode::from_u16(result.status_code)

View File

@@ -2,6 +2,8 @@ mod http;
mod query;
mod runtime;
pub(crate) use crate::video_tasks::VideoTaskService;
pub use crate::video_tasks::VideoTaskTruthSourceMode;
pub(crate) use http::{
build_video_task_video_response, cancel_video_task, cancel_video_task_record,
get_video_task_detail, get_video_task_stats, get_video_task_video, list_video_tasks,
@@ -15,5 +17,3 @@ pub(crate) use runtime::{
execute_video_task_refresh_plan, finalize_video_task_if_terminal, spawn_video_task_poller,
VideoTaskPollerConfig,
};
pub(crate) use crate::video_tasks::VideoTaskService;
pub use crate::video_tasks::VideoTaskTruthSourceMode;

View File

@@ -1,7 +1,8 @@
use std::collections::BTreeMap;
use aether_data::repository::video_tasks::{
StoredVideoTask, VideoTaskModelCount, VideoTaskQueryFilter, VideoTaskStatusCount,
use aether_data_contracts::repository::video_tasks::{
StoredVideoTask, VideoTaskModelCount, VideoTaskQueryFilter, VideoTaskStatus,
VideoTaskStatusCount,
};
use serde::Serialize;
@@ -150,9 +151,7 @@ pub(crate) async fn read_video_task_stats(
.filter(|entry| {
matches!(
entry.status,
aether_data::repository::video_tasks::VideoTaskStatus::Submitted
| aether_data::repository::video_tasks::VideoTaskStatus::Queued
| aether_data::repository::video_tasks::VideoTaskStatus::Processing
VideoTaskStatus::Submitted | VideoTaskStatus::Queued | VideoTaskStatus::Processing
)
})
.map(|entry| entry.count)
@@ -181,17 +180,17 @@ fn map_model_counts(counts: Vec<VideoTaskModelCount>) -> BTreeMap<String, u64> {
.collect()
}
fn status_key(status: aether_data::repository::video_tasks::VideoTaskStatus) -> String {
fn status_key(status: VideoTaskStatus) -> String {
match status {
aether_data::repository::video_tasks::VideoTaskStatus::Pending => "pending",
aether_data::repository::video_tasks::VideoTaskStatus::Submitted => "submitted",
aether_data::repository::video_tasks::VideoTaskStatus::Queued => "queued",
aether_data::repository::video_tasks::VideoTaskStatus::Processing => "processing",
aether_data::repository::video_tasks::VideoTaskStatus::Completed => "completed",
aether_data::repository::video_tasks::VideoTaskStatus::Failed => "failed",
aether_data::repository::video_tasks::VideoTaskStatus::Cancelled => "cancelled",
aether_data::repository::video_tasks::VideoTaskStatus::Expired => "expired",
aether_data::repository::video_tasks::VideoTaskStatus::Deleted => "deleted",
VideoTaskStatus::Pending => "pending",
VideoTaskStatus::Submitted => "submitted",
VideoTaskStatus::Queued => "queued",
VideoTaskStatus::Processing => "processing",
VideoTaskStatus::Completed => "completed",
VideoTaskStatus::Failed => "failed",
VideoTaskStatus::Cancelled => "cancelled",
VideoTaskStatus::Expired => "expired",
VideoTaskStatus::Deleted => "deleted",
}
.to_string()
}

View File

@@ -2,12 +2,15 @@ use std::time::Duration;
use aether_billing::enrich_usage_event_with_billing;
use aether_contracts::{ExecutionErrorKind, ExecutionResult};
use aether_data::repository::video_tasks::{StoredVideoTask, UpsertVideoTask, VideoTaskStatus};
use aether_data_contracts::repository::video_tasks::{
StoredVideoTask, UpsertVideoTask, VideoTaskStatus,
};
use aether_usage_runtime::{build_upsert_usage_record_from_event, settle_usage_if_needed};
use serde_json::{Map, Value};
use tokio::task::JoinHandle;
use tracing::{info, warn};
use crate::log_ids::short_request_id;
use crate::usage::event::{UsageEvent, UsageEventData, UsageEventType};
use crate::video_tasks::{LocalVideoTaskReadRefreshPlan, LocalVideoTaskSnapshot};
use crate::{AppState, GatewayError};
@@ -98,7 +101,7 @@ async fn poll_video_tasks_once(state: &AppState, batch_size: usize) -> Result<us
info!(
event_name = "video_task_status_updated",
log_type = "event",
request_id = %stored.request_id,
request_id = %short_request_id(stored.request_id.as_str()),
task_id = %stored.id,
status = ?stored.status,
"gateway updated video task status from poll refresh"
@@ -119,7 +122,7 @@ async fn poll_video_tasks_once(state: &AppState, batch_size: usize) -> Result<us
info!(
event_name = "video_task_status_updated",
log_type = "event",
request_id = %stored.request_id,
request_id = %short_request_id(stored.request_id.as_str()),
task_id = %stored.id,
status = ?stored.status,
"gateway updated video task status from poll refresh"
@@ -442,7 +445,7 @@ pub(crate) async fn finalize_video_task_if_terminal(state: &AppState, task: &Sto
warn!(
event_name = "video_task_finalize_billing_enrichment_failed",
log_type = "event",
request_id = %task.request_id,
request_id = %short_request_id(task.request_id.as_str()),
error = %err,
"gateway video task finalize failed to enrich billing"
);
@@ -454,7 +457,7 @@ pub(crate) async fn finalize_video_task_if_terminal(state: &AppState, task: &Sto
warn!(
event_name = "video_task_finalize_settlement_failed",
log_type = "event",
request_id = %task.request_id,
request_id = %short_request_id(task.request_id.as_str()),
error = %err,
"gateway video task finalize failed to settle usage"
);
@@ -465,7 +468,7 @@ pub(crate) async fn finalize_video_task_if_terminal(state: &AppState, task: &Sto
warn!(
event_name = "video_task_finalize_usage_upsert_failed",
log_type = "event",
request_id = %task.request_id,
request_id = %short_request_id(task.request_id.as_str()),
error = %err,
"gateway video task finalize failed to upsert usage"
);
@@ -475,7 +478,7 @@ pub(crate) async fn finalize_video_task_if_terminal(state: &AppState, task: &Sto
warn!(
event_name = "video_task_finalize_usage_build_failed",
log_type = "event",
request_id = %task.request_id,
request_id = %short_request_id(task.request_id.as_str()),
error = %err,
"gateway video task finalize failed to build usage record"
);