mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
feat: 全栈功能增强 - 扩展 provider/pool 管理、完善调度与数据层、重构前端 Pool 页面
后端: - 扩展 pool_admin payloads 和 provider query models,增强 endpoint key 管理 - 完善 scheduler-core 候选排序与请求候选逻辑 - 增强 usage-runtime 写入、provider-transport 网络层与 OAuth 刷新 - 改进 AI pipeline 响应转换与流式处理 - 扩展 global_models/provider_catalog 数据层查询能力 - 增强 video-tasks-core 多 provider 支持 - 新增大量集成测试覆盖 pool/keys/provider_query/frontdoor 前端: - 重构 PoolManagement 页面,拆分状态管理/对话框逻辑到独立模块 - 新增 poolAdvancedDialog/poolSchedulingDialog/poolManagementState/poolMobilePresentation 工具函数及测试 - 改进 Dialog 组件与 provider tabs 显示 部署: - 更新 Rust CI workflow 和 Dockerfile 构建配置 Closes #275 Co-authored-by: AAEE86 <ppk0227@hotmail.com>
This commit is contained in:
@@ -1,18 +1,35 @@
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
pub fn build_video_follow_up_report_context(
|
||||
request_id: &str,
|
||||
user_id: &str,
|
||||
api_key_id: &str,
|
||||
task_id: &str,
|
||||
provider_id: &str,
|
||||
endpoint_id: &str,
|
||||
key_id: &str,
|
||||
provider_name: Option<&str>,
|
||||
model_name: Option<&str>,
|
||||
client_api_format: &str,
|
||||
provider_api_format: &str,
|
||||
) -> Value {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct VideoFollowUpReportContextInput<'a> {
|
||||
pub request_id: &'a str,
|
||||
pub user_id: &'a str,
|
||||
pub api_key_id: &'a str,
|
||||
pub task_id: &'a str,
|
||||
pub provider_id: &'a str,
|
||||
pub endpoint_id: &'a str,
|
||||
pub key_id: &'a str,
|
||||
pub provider_name: Option<&'a str>,
|
||||
pub model_name: Option<&'a str>,
|
||||
pub client_api_format: &'a str,
|
||||
pub provider_api_format: &'a str,
|
||||
}
|
||||
|
||||
pub fn build_video_follow_up_report_context(input: VideoFollowUpReportContextInput<'_>) -> Value {
|
||||
let VideoFollowUpReportContextInput {
|
||||
request_id,
|
||||
user_id,
|
||||
api_key_id,
|
||||
task_id,
|
||||
provider_id,
|
||||
endpoint_id,
|
||||
key_id,
|
||||
provider_name,
|
||||
model_name,
|
||||
client_api_format,
|
||||
provider_api_format,
|
||||
} = input;
|
||||
|
||||
let mut context = Map::new();
|
||||
context.insert(
|
||||
"request_id".to_string(),
|
||||
@@ -84,23 +101,26 @@ pub fn resolve_follow_up_auth(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{build_video_follow_up_report_context, resolve_follow_up_auth};
|
||||
use super::{
|
||||
build_video_follow_up_report_context, resolve_follow_up_auth,
|
||||
VideoFollowUpReportContextInput,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn builds_follow_up_report_context_with_transport_metadata() {
|
||||
let context = build_video_follow_up_report_context(
|
||||
"req_123",
|
||||
"user_123",
|
||||
"key_123",
|
||||
"task_123",
|
||||
"provider_123",
|
||||
"endpoint_123",
|
||||
"transport_key_123",
|
||||
Some("provider-name"),
|
||||
Some("model-name"),
|
||||
"openai:video",
|
||||
"openai:video",
|
||||
);
|
||||
let context = build_video_follow_up_report_context(VideoFollowUpReportContextInput {
|
||||
request_id: "req_123",
|
||||
user_id: "user_123",
|
||||
api_key_id: "key_123",
|
||||
task_id: "task_123",
|
||||
provider_id: "provider_123",
|
||||
endpoint_id: "endpoint_123",
|
||||
key_id: "transport_key_123",
|
||||
provider_name: Some("provider-name"),
|
||||
model_name: Some("model-name"),
|
||||
client_api_format: "openai:video",
|
||||
provider_api_format: "openai:video",
|
||||
});
|
||||
|
||||
assert_eq!(context["request_id"].as_str(), Some("req_123"));
|
||||
assert_eq!(context["provider_id"].as_str(), Some("provider_123"));
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
build_video_follow_up_report_context, current_unix_timestamp_secs, gemini_metadata_video_url,
|
||||
request_body_string, request_body_u32, resolve_follow_up_auth, GeminiVideoTaskSeed,
|
||||
LocalVideoTaskFollowUpPlan, LocalVideoTaskReadResponse, LocalVideoTaskSnapshot,
|
||||
LocalVideoTaskStatus, DEFAULT_VIDEO_TASK_MAX_POLL_COUNT,
|
||||
LocalVideoTaskStatus, VideoFollowUpReportContextInput, DEFAULT_VIDEO_TASK_MAX_POLL_COUNT,
|
||||
DEFAULT_VIDEO_TASK_POLL_INTERVAL_SECONDS,
|
||||
};
|
||||
|
||||
@@ -233,17 +233,19 @@ impl GeminiVideoTaskSeed {
|
||||
},
|
||||
report_kind: Some("gemini_video_cancel_sync_finalize".to_string()),
|
||||
report_context: Some(build_video_follow_up_report_context(
|
||||
&self.persistence.request_id,
|
||||
&user_id,
|
||||
&api_key_id,
|
||||
&self.local_short_id,
|
||||
&self.transport.provider_id,
|
||||
&self.transport.endpoint_id,
|
||||
&self.transport.key_id,
|
||||
self.transport.provider_name.as_deref(),
|
||||
Some(self.model.as_str()),
|
||||
"gemini:video",
|
||||
"gemini:video",
|
||||
VideoFollowUpReportContextInput {
|
||||
request_id: &self.persistence.request_id,
|
||||
user_id: &user_id,
|
||||
api_key_id: &api_key_id,
|
||||
task_id: &self.local_short_id,
|
||||
provider_id: &self.transport.provider_id,
|
||||
endpoint_id: &self.transport.endpoint_id,
|
||||
key_id: &self.transport.key_id,
|
||||
provider_name: self.transport.provider_name.as_deref(),
|
||||
model_name: Some(self.model.as_str()),
|
||||
client_api_format: "gemini:video",
|
||||
provider_api_format: "gemini:video",
|
||||
},
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ mod util;
|
||||
pub use body::{
|
||||
context_text, context_u64, request_body_string, request_body_text, request_body_u32,
|
||||
};
|
||||
pub use follow_up::{build_video_follow_up_report_context, resolve_follow_up_auth};
|
||||
pub use follow_up::{
|
||||
build_video_follow_up_report_context, resolve_follow_up_auth, VideoFollowUpReportContextInput,
|
||||
};
|
||||
pub use gemini::map_gemini_stored_task_to_read_response;
|
||||
pub use openai::map_openai_stored_task_to_read_response;
|
||||
pub use path::{
|
||||
|
||||
@@ -11,7 +11,8 @@ use crate::{
|
||||
parse_video_content_variant, request_body_string, request_body_u32, resolve_follow_up_auth,
|
||||
LocalVideoTaskContentAction, LocalVideoTaskFollowUpPlan, LocalVideoTaskReadResponse,
|
||||
LocalVideoTaskSnapshot, LocalVideoTaskStatus, OpenAiVideoTaskSeed,
|
||||
DEFAULT_VIDEO_TASK_MAX_POLL_COUNT, DEFAULT_VIDEO_TASK_POLL_INTERVAL_SECONDS,
|
||||
VideoFollowUpReportContextInput, DEFAULT_VIDEO_TASK_MAX_POLL_COUNT,
|
||||
DEFAULT_VIDEO_TASK_POLL_INTERVAL_SECONDS,
|
||||
};
|
||||
|
||||
pub fn map_openai_stored_task_to_read_response(
|
||||
@@ -208,34 +209,36 @@ impl OpenAiVideoTaskSeed {
|
||||
)
|
||||
};
|
||||
|
||||
Some(LocalVideoTaskContentAction::StreamPlan(ExecutionPlan {
|
||||
request_id: trace_id.to_string(),
|
||||
candidate_id: None,
|
||||
provider_name: self.transport.provider_name.clone(),
|
||||
provider_id: self.transport.provider_id.clone(),
|
||||
endpoint_id: self.transport.endpoint_id.clone(),
|
||||
key_id: self.transport.key_id.clone(),
|
||||
method: "GET".to_string(),
|
||||
url,
|
||||
headers,
|
||||
content_type: None,
|
||||
content_encoding: None,
|
||||
body: RequestBody {
|
||||
json_body: None,
|
||||
body_bytes_b64: None,
|
||||
body_ref: None,
|
||||
Some(LocalVideoTaskContentAction::StreamPlan(Box::new(
|
||||
ExecutionPlan {
|
||||
request_id: trace_id.to_string(),
|
||||
candidate_id: None,
|
||||
provider_name: self.transport.provider_name.clone(),
|
||||
provider_id: self.transport.provider_id.clone(),
|
||||
endpoint_id: self.transport.endpoint_id.clone(),
|
||||
key_id: self.transport.key_id.clone(),
|
||||
method: "GET".to_string(),
|
||||
url,
|
||||
headers,
|
||||
content_type: None,
|
||||
content_encoding: None,
|
||||
body: RequestBody {
|
||||
json_body: None,
|
||||
body_bytes_b64: None,
|
||||
body_ref: None,
|
||||
},
|
||||
stream: true,
|
||||
client_api_format: "openai:video".to_string(),
|
||||
provider_api_format: "openai:video".to_string(),
|
||||
model_name: self
|
||||
.model
|
||||
.clone()
|
||||
.or_else(|| self.transport.model_name.clone()),
|
||||
proxy: self.transport.proxy.clone(),
|
||||
tls_profile: self.transport.tls_profile.clone(),
|
||||
timeouts: self.transport.timeouts.clone(),
|
||||
},
|
||||
stream: true,
|
||||
client_api_format: "openai:video".to_string(),
|
||||
provider_api_format: "openai:video".to_string(),
|
||||
model_name: self
|
||||
.model
|
||||
.clone()
|
||||
.or_else(|| self.transport.model_name.clone()),
|
||||
proxy: self.transport.proxy.clone(),
|
||||
tls_profile: self.transport.tls_profile.clone(),
|
||||
timeouts: self.transport.timeouts.clone(),
|
||||
}))
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn client_body_json(&self) -> Value {
|
||||
@@ -342,17 +345,19 @@ impl OpenAiVideoTaskSeed {
|
||||
},
|
||||
report_kind: Some("openai_video_delete_sync_finalize".to_string()),
|
||||
report_context: Some(build_video_follow_up_report_context(
|
||||
&self.persistence.request_id,
|
||||
&user_id,
|
||||
&api_key_id,
|
||||
&self.local_task_id,
|
||||
&self.transport.provider_id,
|
||||
&self.transport.endpoint_id,
|
||||
&self.transport.key_id,
|
||||
self.transport.provider_name.as_deref(),
|
||||
model_name.as_deref(),
|
||||
"openai:video",
|
||||
"openai:video",
|
||||
VideoFollowUpReportContextInput {
|
||||
request_id: &self.persistence.request_id,
|
||||
user_id: &user_id,
|
||||
api_key_id: &api_key_id,
|
||||
task_id: &self.local_task_id,
|
||||
provider_id: &self.transport.provider_id,
|
||||
endpoint_id: &self.transport.endpoint_id,
|
||||
key_id: &self.transport.key_id,
|
||||
provider_name: self.transport.provider_name.as_deref(),
|
||||
model_name: model_name.as_deref(),
|
||||
client_api_format: "openai:video",
|
||||
provider_api_format: "openai:video",
|
||||
},
|
||||
)),
|
||||
})
|
||||
}
|
||||
@@ -466,17 +471,19 @@ impl OpenAiVideoTaskSeed {
|
||||
},
|
||||
report_kind: Some("openai_video_cancel_sync_finalize".to_string()),
|
||||
report_context: Some(build_video_follow_up_report_context(
|
||||
&self.persistence.request_id,
|
||||
&user_id,
|
||||
&api_key_id,
|
||||
&self.local_task_id,
|
||||
&self.transport.provider_id,
|
||||
&self.transport.endpoint_id,
|
||||
&self.transport.key_id,
|
||||
self.transport.provider_name.as_deref(),
|
||||
model_name.as_deref(),
|
||||
"openai:video",
|
||||
"openai:video",
|
||||
VideoFollowUpReportContextInput {
|
||||
request_id: &self.persistence.request_id,
|
||||
user_id: &user_id,
|
||||
api_key_id: &api_key_id,
|
||||
task_id: &self.local_task_id,
|
||||
provider_id: &self.transport.provider_id,
|
||||
endpoint_id: &self.transport.endpoint_id,
|
||||
key_id: &self.transport.key_id,
|
||||
provider_name: self.transport.provider_name.as_deref(),
|
||||
model_name: model_name.as_deref(),
|
||||
client_api_format: "openai:video",
|
||||
provider_api_format: "openai:video",
|
||||
},
|
||||
)),
|
||||
})
|
||||
}
|
||||
@@ -513,19 +520,20 @@ impl OpenAiVideoTaskSeed {
|
||||
.entry("content-type".to_string())
|
||||
.or_insert_with(|| content_type.clone());
|
||||
|
||||
let mut report_context = build_video_follow_up_report_context(
|
||||
&self.persistence.request_id,
|
||||
&user_id,
|
||||
&api_key_id,
|
||||
&self.local_task_id,
|
||||
&self.transport.provider_id,
|
||||
&self.transport.endpoint_id,
|
||||
&self.transport.key_id,
|
||||
self.transport.provider_name.as_deref(),
|
||||
model_name.as_deref(),
|
||||
"openai:video",
|
||||
"openai:video",
|
||||
);
|
||||
let mut report_context =
|
||||
build_video_follow_up_report_context(VideoFollowUpReportContextInput {
|
||||
request_id: &self.persistence.request_id,
|
||||
user_id: &user_id,
|
||||
api_key_id: &api_key_id,
|
||||
task_id: &self.local_task_id,
|
||||
provider_id: &self.transport.provider_id,
|
||||
endpoint_id: &self.transport.endpoint_id,
|
||||
key_id: &self.transport.key_id,
|
||||
provider_name: self.transport.provider_name.as_deref(),
|
||||
model_name: model_name.as_deref(),
|
||||
client_api_format: "openai:video",
|
||||
provider_api_format: "openai:video",
|
||||
});
|
||||
if let Some(report_context_object) = report_context.as_object_mut() {
|
||||
report_context_object.insert("original_request_body".to_string(), body_json.clone());
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ pub struct LocalVideoTaskReadRefreshPlan {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum LocalVideoTaskContentAction {
|
||||
Immediate { status_code: u16, body_json: Value },
|
||||
StreamPlan(ExecutionPlan),
|
||||
StreamPlan(Box<ExecutionPlan>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
||||
Reference in New Issue
Block a user