diff --git a/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs b/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs index fa86a2753..5b4926924 100644 --- a/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs +++ b/server-rs/crates/platform-image/src/image_provider/runtime/executor.rs @@ -216,6 +216,7 @@ pub async fn create_image_generation_with_model( "ImageProvider 图片生成 HTTP 返回" ); let response_text = response.body; + let task_id_prefix = image_task_id_prefix(settings.provider, None); match handle_image_response( http_client, request_url.as_str(), @@ -228,7 +229,7 @@ pub async fn create_image_generation_with_model( Some(prompt.chars().count()), Some(reference_images.len()), candidate_count, - "vector-engine", + task_id_prefix.as_str(), settings.request_deadline, ) .await @@ -406,6 +407,7 @@ pub async fn create_nanobanana_generate_content( "ImageProvider nanobanana2 图片生成 HTTP 返回" ); let response_text = response.body; + let task_id_prefix = image_task_id_prefix(settings.provider, Some("nanobanana")); handle_image_response( http_client, request_url.as_str(), @@ -418,7 +420,7 @@ pub async fn create_nanobanana_generate_content( Some(prompt.chars().count()), Some(reference_image_count), 1, - "vector-engine-nanobanana", + task_id_prefix.as_str(), settings.request_deadline, ) .await @@ -657,6 +659,7 @@ pub async fn create_image_edit_with_references_and_model( "ImageProvider 图片编辑 HTTP 返回" ); let response_text = response.body; + let task_id_prefix = image_task_id_prefix(settings.provider, Some("edit")); match handle_image_response( http_client, request_url.as_str(), @@ -669,7 +672,7 @@ pub async fn create_image_edit_with_references_and_model( Some(prompt.chars().count()), Some(reference_image_count), candidate_count, - "vector-engine-edit", + task_id_prefix.as_str(), settings.request_deadline, ) .await @@ -695,7 +698,7 @@ pub async fn create_image_edit_with_references_and_model( /// executor 用 `settings.base_url`/`settings.api_key` 发请求,如果调用方传入了属于 /// 另一个 provider 的模型,就会把错误的密钥/网关当成目标端点。这里显式 fail fast, /// 避免静默地把请求发到不匹配的 provider。 -fn ensure_provider_matches_model( +pub(crate) fn ensure_provider_matches_model( settings: &ImageProviderSettings, model: &str, failure_context: &str, @@ -718,6 +721,15 @@ fn ensure_provider_matches_model( Ok(()) } +/// 兜底 task id 前缀:必须跟随实际 provider,否则 Tiantoken 任务的 +/// `task_id` 会带着 `vector-engine` 前缀进入持久化与审计。 +fn image_task_id_prefix(provider: ImageProvider, task_kind: Option<&str>) -> String { + match task_kind { + Some(kind) => format!("{}-{kind}", provider.as_str()), + None => provider.as_str().to_string(), + } +} + fn preferred_image_upstream_model(requested_model: &str) -> &str { // Provider routing is selected by api-server at the task boundary. Keep the // concrete value intact here so retries stay on the same model and legacy