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:
fawney19
2026-04-09 13:51:50 +08:00
parent 4fc95adfb9
commit b0b40c16ff
97 changed files with 5816 additions and 1881 deletions

View File

@@ -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());
}