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

@@ -0,0 +1,26 @@
use crate::AppState;
use super::super::super::{AUTH_API_KEY_LAST_USED_MAX_ENTRIES, AUTH_API_KEY_LAST_USED_TTL};
impl AppState {
pub(crate) async fn touch_auth_api_key_last_used_best_effort(&self, api_key_id: &str) {
let api_key_id = api_key_id.trim();
if api_key_id.is_empty() || !self.data.has_auth_api_key_writer() {
return;
}
if !self.auth_api_key_last_used_cache.should_touch(
api_key_id,
AUTH_API_KEY_LAST_USED_TTL,
AUTH_API_KEY_LAST_USED_MAX_ENTRIES,
) {
return;
}
if let Err(err) = self.data.touch_auth_api_key_last_used(api_key_id).await {
tracing::warn!(
api_key_id = %api_key_id,
error = ?err,
"gateway auth api key last_used_at touch failed"
);
}
}
}

View File

@@ -1,3 +1,4 @@
mod api_keys;
mod sessions;
mod user_lifecycle;
mod user_provisioning;

View File

@@ -1,12 +1,11 @@
use crate::{AppState, GatewayError};
use crate::{AppState, GatewayError, GatewayUserSessionView};
impl AppState {
pub(crate) async fn find_user_session(
&self,
user_id: &str,
session_id: &str,
) -> Result<Option<crate::data::state::StoredUserSessionRecord>, GatewayError>
{
) -> Result<Option<GatewayUserSessionView>, GatewayError> {
#[cfg(test)]
if let Some(store) = self.auth_session_store.as_ref() {
let key = format!("{user_id}:{session_id}");
@@ -14,20 +13,21 @@ impl AppState {
.lock()
.expect("auth session store should lock")
.get(&key)
.cloned());
.cloned()
.map(Into::into));
}
self.data
.find_user_session(user_id, session_id)
.await
.map(|value| value.map(Into::into))
.map_err(|err| GatewayError::Internal(err.to_string()))
}
pub(crate) async fn list_user_sessions(
&self,
user_id: &str,
) -> Result<Vec<crate::data::state::StoredUserSessionRecord>, GatewayError>
{
) -> Result<Vec<GatewayUserSessionView>, GatewayError> {
#[cfg(test)]
if let Some(store) = self.auth_session_store.as_ref() {
let prefix = format!("{user_id}:");
@@ -46,12 +46,13 @@ impl AppState {
.cmp(&left.last_seen_at)
.then_with(|| right.created_at.cmp(&left.created_at))
});
return Ok(sessions);
return Ok(sessions.into_iter().map(Into::into).collect());
}
self.data
.list_user_sessions(user_id)
.await
.map(|sessions| sessions.into_iter().map(Into::into).collect())
.map_err(|err| GatewayError::Internal(err.to_string()))
}
@@ -112,11 +113,14 @@ impl AppState {
.map_err(|err| GatewayError::Internal(err.to_string()))
}
pub(crate) async fn create_user_session(
pub(crate) async fn create_user_session<T>(
&self,
session: crate::data::state::StoredUserSessionRecord,
) -> Result<Option<crate::data::state::StoredUserSessionRecord>, GatewayError>
session: T,
) -> Result<Option<GatewayUserSessionView>, GatewayError>
where
T: Into<GatewayUserSessionView>,
{
let session = session.into();
#[cfg(test)]
if let Some(store) = self.auth_session_store.as_ref() {
let now = session
@@ -138,14 +142,16 @@ impl AppState {
}
guard.insert(
format!("{}:{}", session.user_id, session.id),
session.clone(),
session.clone().into(),
);
return Ok(Some(session));
}
let raw_session: crate::data::state::StoredUserSessionRecord = session.into();
self.data
.create_user_session(&session)
.create_user_session(&raw_session)
.await
.map(|value| value.map(Into::into))
.map_err(|err| GatewayError::Internal(err.to_string()))
}