diff --git a/server-rs/crates/api-server/src/openai_image_generation.rs b/server-rs/crates/api-server/src/openai_image_generation.rs index a80d03749..e276d2cea 100644 --- a/server-rs/crates/api-server/src/openai_image_generation.rs +++ b/server-rs/crates/api-server/src/openai_image_generation.rs @@ -5,7 +5,7 @@ use platform_image::{ VECTOR_ENGINE_PROVIDER, build_image_http_client, create_image_edit, create_image_edit_with_references, create_image_edit_with_references_and_model, create_image_generation, create_image_generation_with_model, - create_nanobanana_generate_content, + create_nanobanana_generate_content, missing_reference_images_error, }; #[cfg(test)] use platform_image::{build_image_request_body, images_edit_url, images_generation_url}; @@ -320,6 +320,21 @@ pub(crate) async fn create_openai_image_edit_with_references( "negativePromptChars": negative_prompt.map(str::chars).map(Iterator::count), "referenceImageCount": reference_images.len(), }); + // 中文注释:先做本地参考图校验,避免 provider 客户端缺失时在校验前 panic。 + if reference_images.is_empty() { + return map_platform_image_result( + settings, + Err(missing_reference_images_error( + ImageProvider::Tiantoken, + failure_context, + )), + "image_edit_with_references", + failure_context, + request_payload, + started_at_micros, + ) + .await; + } let provider_client = settings.client_for_model(GPT_IMAGE_2_5_EDIT_MODEL); let provider_settings = settings.provider_settings_for_model(GPT_IMAGE_2_5_EDIT_MODEL); let result = create_image_edit_with_references( @@ -364,6 +379,21 @@ pub(crate) async fn create_openai_image_edit_with_references_and_model( "negativePromptChars": negative_prompt.map(str::chars).map(Iterator::count), "referenceImageCount": reference_images.len(), }); + // 中文注释:先做本地参考图校验,避免 provider 客户端缺失时在校验前 panic。 + if reference_images.is_empty() { + return map_platform_image_result( + settings, + Err(missing_reference_images_error( + ImageProvider::Tiantoken, + failure_context, + )), + "image_edit_with_references", + failure_context, + request_payload, + started_at_micros, + ) + .await; + } let provider_client = settings.client_for_model(model); let provider_settings = settings.provider_settings_for_model(model); let result = create_image_edit_with_references_and_model( diff --git a/server-rs/crates/platform-image/src/image_provider/mod.rs b/server-rs/crates/platform-image/src/image_provider/mod.rs index 118e9af4d..a0695bfcb 100644 --- a/server-rs/crates/platform-image/src/image_provider/mod.rs +++ b/server-rs/crates/platform-image/src/image_provider/mod.rs @@ -26,5 +26,6 @@ pub use runtime::{ create_image_edit, create_image_edit_with_references, create_image_edit_with_references_and_model, create_image_generation, create_image_generation_with_model, create_nanobanana_generate_content, download_remote_image, + missing_reference_images_error, }; pub use transport::{build_image_http_client, build_image_provider_client}; diff --git a/server-rs/crates/platform-image/src/image_provider/runtime/error.rs b/server-rs/crates/platform-image/src/image_provider/runtime/error.rs index a58f2d247..b05e44117 100644 --- a/server-rs/crates/platform-image/src/image_provider/runtime/error.rs +++ b/server-rs/crates/platform-image/src/image_provider/runtime/error.rs @@ -1,6 +1,19 @@ use std::{error::Error, fmt}; -use crate::image_provider::{audit::PlatformImageFailureAudit, util::is_timeout_message}; +use crate::image_provider::{ + audit::PlatformImageFailureAudit, types::ImageProvider, util::is_timeout_message, +}; + +/// 图片编辑缺少参考图时的统一错误;调用方可在解析 provider 客户端之前先行校验。 +pub fn missing_reference_images_error( + provider: ImageProvider, + failure_context: &str, +) -> PlatformImageError { + PlatformImageError::InvalidRequest { + provider: provider.as_str(), + message: format!("{failure_context}:缺少参考图,图片编辑需要至少一张参考图。"), + } +} #[derive(Clone, Debug)] pub enum PlatformImageError { 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 a98687c1c..808fc6873 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 @@ -19,7 +19,7 @@ use crate::image_provider::{ map_curl_error, send_image_json_request_with_curl, send_image_multipart_edit_request_with_curl, }, - error::PlatformImageError, + error::{PlatformImageError, missing_reference_images_error}, image_source::resolve_reference_images, request::{ build_image_edit_request_log_params, build_image_request_body_with_model, @@ -499,10 +499,10 @@ pub async fn create_image_edit_with_references_and_model( } })?; if reference_images.is_empty() { - return Err(PlatformImageError::InvalidRequest { - provider: settings.provider.as_str(), - message: format!("{failure_context}:缺少参考图,图片编辑需要至少一张参考图。"), - }); + return Err(missing_reference_images_error( + settings.provider, + failure_context, + )); } if reference_images.len() > VECTOR_ENGINE_IMAGE_EDIT_MAX_REFERENCE_IMAGES { return Err(PlatformImageError::InvalidRequest { diff --git a/server-rs/crates/platform-image/src/image_provider/runtime/mod.rs b/server-rs/crates/platform-image/src/image_provider/runtime/mod.rs index 88a04c640..63bf83afb 100644 --- a/server-rs/crates/platform-image/src/image_provider/runtime/mod.rs +++ b/server-rs/crates/platform-image/src/image_provider/runtime/mod.rs @@ -11,7 +11,7 @@ pub(crate) use crate::image_provider::transport::curl as curl_transport; pub use audit::PlatformImageFailureAudit; pub(crate) use audit::build_failure_audit; pub(crate) use budget::{effective_request_timeout_ms, request_budget_exhausted_error}; -pub use error::{PlatformImageError, PlatformImageStatusHint}; +pub use error::{PlatformImageError, PlatformImageStatusHint, missing_reference_images_error}; pub use executor::{ create_image_edit, create_image_edit_with_references, create_image_edit_with_references_and_model, create_image_generation, diff --git a/server-rs/crates/platform-image/src/lib.rs b/server-rs/crates/platform-image/src/lib.rs index 654062eac..7f7a69d5b 100644 --- a/server-rs/crates/platform-image/src/lib.rs +++ b/server-rs/crates/platform-image/src/lib.rs @@ -15,7 +15,8 @@ pub use image_provider::{ create_image_edit_with_references, create_image_edit_with_references_and_model, create_image_generation, create_image_generation_with_model, create_nanobanana_generate_content, download_remote_image, images_edit_url, - images_generation_url, nanobanana_generate_content_url, resolve_image_provider, + images_generation_url, missing_reference_images_error, nanobanana_generate_content_url, + resolve_image_provider, }; pub use pixel_art_snapper::{ PIXEL_ART_ALPHA_COVERAGE_THRESHOLD, PIXEL_ART_ANALYSIS_COLORS, PIXEL_ART_KMEANS_SAMPLE_LIMIT,