合并 master 并保留外部生成 worker 模式

合入 master 的生产健康巡检、JumpHop 和 SpacetimeDB 更新
保留外部生成 worker、队列/内联模式与 lease guard 口径
合并 Server-Provision 工具复用、health patrol 和外部生成 worker systemd 配置
补齐 SpacetimeDB 生成绑定并通过本地检查
This commit is contained in:
2026-06-10 21:26:53 +08:00
93 changed files with 7872 additions and 2244 deletions

View File

@@ -12,6 +12,7 @@ use platform_speech::{
const DEFAULT_INTERNAL_API_SECRET: &str = "genarrative-dev-internal-bridge";
const SPACETIME_LOCAL_CONFIG_FILE: &str = "spacetime.local.json";
const DEFAULT_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS: u64 = 2;
pub(crate) const DEFAULT_VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS: u64 = 1_000_000;
// 集中管理 api-server 的启动配置,避免入口层直接散落环境变量解析逻辑。
@@ -124,6 +125,7 @@ pub struct AppConfig {
pub spacetime_token: Option<String>,
pub spacetime_pool_size: u32,
pub spacetime_procedure_timeout: Duration,
pub spacetime_health_check_timeout: Duration,
pub llm_provider: LlmProvider,
pub llm_base_url: String,
pub llm_api_key: Option<String>,
@@ -139,9 +141,10 @@ pub struct AppConfig {
pub dashscope_reference_image_model: String,
pub dashscope_cover_image_model: String,
pub dashscope_image_request_timeout_ms: u64,
pub apimart_base_url: String,
pub apimart_api_key: Option<String>,
pub apimart_image_request_timeout_ms: u64,
// 中文注释Apimart 已于 2026-06 弃用LLM 文本调用统一迁移到 VectorEngine同时支持 Chat Completions / Responses 协议)。
// pub apimart_base_url: String,
// pub apimart_api_key: Option<String>,
// pub apimart_image_request_timeout_ms: u64,
pub vector_engine_base_url: String,
pub vector_engine_api_key: Option<String>,
pub vector_engine_image_request_timeout_ms: u64,
@@ -331,6 +334,9 @@ impl Default for AppConfig {
spacetime_token: None,
spacetime_pool_size: 4,
spacetime_procedure_timeout: Duration::from_secs(30),
spacetime_health_check_timeout: Duration::from_secs(
DEFAULT_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS,
),
llm_provider: LlmProvider::Ark,
llm_base_url: String::new(),
llm_api_key: None,
@@ -349,9 +355,9 @@ impl Default for AppConfig {
dashscope_reference_image_model: String::new(),
dashscope_cover_image_model: String::new(),
dashscope_image_request_timeout_ms: 150_000,
apimart_base_url: String::new(),
apimart_api_key: None,
apimart_image_request_timeout_ms: 180_000,
// apimart_base_url: String::new(),
// apimart_api_key: None,
// apimart_image_request_timeout_ms: 180_000,
vector_engine_base_url: String::new(),
vector_engine_api_key: None,
vector_engine_image_request_timeout_ms: DEFAULT_VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS,
@@ -788,6 +794,12 @@ impl AppConfig {
config.spacetime_procedure_timeout =
Duration::from_secs(spacetime_procedure_timeout_seconds);
}
if let Some(spacetime_health_check_timeout_seconds) =
read_first_duration_seconds_env(&["GENARRATIVE_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS"])
{
config.spacetime_health_check_timeout =
Duration::from_secs(spacetime_health_check_timeout_seconds);
}
if let Some(llm_provider) =
read_first_llm_provider_env(&["GENARRATIVE_LLM_PROVIDER", "LLM_PROVIDER"])
@@ -876,17 +888,17 @@ impl AppConfig {
config.dashscope_image_request_timeout_ms = dashscope_image_request_timeout_ms;
}
if let Some(apimart_base_url) = read_first_non_empty_env(&["APIMART_BASE_URL"]) {
config.apimart_base_url = apimart_base_url;
}
config.apimart_api_key = read_first_non_empty_env(&["APIMART_API_KEY"]);
if let Some(apimart_image_request_timeout_ms) =
read_first_positive_u64_env(&["APIMART_IMAGE_REQUEST_TIMEOUT_MS"])
{
config.apimart_image_request_timeout_ms = apimart_image_request_timeout_ms;
}
// 中文注释Apimart 已于 2026-06 弃用LLM 文本调用统一迁移到 VectorEngine。
// 保留以下历史加载代码,后续删除:
// if let Some(apimart_base_url) = read_first_non_empty_env(&["APIMART_BASE_URL"]) {
// config.apimart_base_url = apimart_base_url;
// }
// config.apimart_api_key = read_first_non_empty_env(&["APIMART_API_KEY"]);
// if let Some(apimart_image_request_timeout_ms) =
// read_first_positive_u64_env(&["APIMART_IMAGE_REQUEST_TIMEOUT_MS"])
// {
// config.apimart_image_request_timeout_ms = apimart_image_request_timeout_ms;
// }
if let Some(vector_engine_base_url) = read_first_non_empty_env(&["VECTOR_ENGINE_BASE_URL"])
{
@@ -1331,7 +1343,7 @@ mod tests {
assert!(config.llm_model.is_empty());
assert!(config.llm_base_url.is_empty());
assert!(config.apimart_base_url.is_empty());
// assert!(config.apimart_base_url.is_empty());
assert!(config.vector_engine_base_url.is_empty());
assert!(config.ark_character_video_base_url.is_empty());
assert_eq!(config.hyper3d_base_url, "https://api.hyper3d.com/api/v2");
@@ -1498,11 +1510,11 @@ mod tests {
assert_eq!(config.llm_provider, LlmProvider::OpenAiCompatible);
assert_eq!(config.llm_base_url, "https://llm.internal.example/v1");
assert_eq!(config.llm_model, "internal-text-model");
assert_eq!(
config.apimart_base_url,
"https://responses.internal.example/v1"
);
assert_eq!(config.apimart_image_request_timeout_ms, 190_000);
// assert_eq!(
// config.apimart_base_url,
// "https://responses.internal.example/v1"
// );
// assert_eq!(config.apimart_image_request_timeout_ms, 190_000);
assert_eq!(
config.vector_engine_base_url,
"https://vector.internal.example"
@@ -1822,6 +1834,26 @@ mod tests {
}
}
#[test]
fn from_env_reads_spacetime_health_check_timeout() {
let _guard = ENV_LOCK
.get_or_init(|| Mutex::new(()))
.lock()
.expect("env lock should not poison");
unsafe {
std::env::remove_var("GENARRATIVE_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS");
std::env::set_var("GENARRATIVE_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS", "3");
}
let config = AppConfig::from_env();
assert_eq!(config.spacetime_health_check_timeout.as_secs(), 3);
unsafe {
std::env::remove_var("GENARRATIVE_SPACETIME_HEALTH_CHECK_TIMEOUT_SECONDS");
}
}
#[test]
fn default_keeps_structured_llm_web_search_disabled() {
let config = AppConfig::default();