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 03adbc863..f3aa2d797 100644 --- a/server-rs/crates/api-server/src/openai_image_generation.rs +++ b/server-rs/crates/api-server/src/openai_image_generation.rs @@ -243,7 +243,12 @@ pub(crate) async fn create_openai_image_edit_with_references_and_model( // 中文注释:先做本地参考图校验,避免 provider 客户端缺失时在校验前 panic。 // provider 归属与下方非空参考图路径保持一致,按模型解析而不是固定 Tiantoken。 if reference_images.is_empty() { - let provider = resolve_image_provider(model).unwrap_or(ImageProvider::Tiantoken); + let provider = match resolve_image_provider(model) { + Ok(provider) => provider, + // 这里只为一个本地校验错误选归属标签;未知模型无法归属 provider 时 + // 显式回落到 Tiantoken,不再用 unwrap_or 静默吞掉解析失败。 + Err(_) => ImageProvider::Tiantoken, + }; return map_platform_image_result( settings, Err(missing_reference_images_error(provider, failure_context)), diff --git a/server-rs/crates/platform-image/src/image_provider/protocol/request.rs b/server-rs/crates/platform-image/src/image_provider/protocol/request.rs index 23470a04e..f46fe299e 100644 --- a/server-rs/crates/platform-image/src/image_provider/protocol/request.rs +++ b/server-rs/crates/platform-image/src/image_provider/protocol/request.rs @@ -120,13 +120,13 @@ pub(crate) fn normalize_nanobanana_model(model: &str) -> &str { /// nanobanana 走 VectorEngine。业务模型名 `gpt-image-2.5` /// (`GPT_IMAGE_2_5_BUSINESS_NAME`) 必须在任务边界解析成具体 key;已删除的 /// `gpt-image-2-c` 命中即拒绝。`gpt-image-2` 仍按历史可读值接受。 -pub fn resolve_image_provider(model: &str) -> Result { +pub fn resolve_image_provider(model: &str) -> Result { match normalize_image_model(model) { GPT_IMAGE_2_MODEL | GPT_IMAGE_2_5_GENERATION_MODEL | GPT_IMAGE_2_5_EDIT_MODEL => { Ok(ImageProvider::Tiantoken) } NANOBANANA_2_MODEL => Ok(ImageProvider::VectorEngine), - _ => Err("不支持的图片模型"), + _ => Err(format!("不支持的图片模型:{model}")), } } 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 0f25bcd58..c907099f3 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 @@ -709,10 +709,11 @@ pub(crate) fn ensure_provider_matches_model( model: &str, failure_context: &str, ) -> Result<(), PlatformImageError> { + // `resolve_image_provider` 的错误信息已经带上被拒绝的模型名,这里不再重复拼接。 let resolved = resolve_image_provider(model).map_err(|message| PlatformImageError::InvalidRequest { provider: settings.provider.as_str(), - message: format!("{failure_context}:{message}:{model}"), + message: format!("{failure_context}:{message}"), })?; if resolved != settings.provider { return Err(PlatformImageError::InvalidRequest { diff --git a/server-rs/crates/platform-image/tests/image_provider.rs b/server-rs/crates/platform-image/tests/image_provider.rs index c1ca9439d..8c0f50fa1 100644 --- a/server-rs/crates/platform-image/tests/image_provider.rs +++ b/server-rs/crates/platform-image/tests/image_provider.rs @@ -220,7 +220,12 @@ fn nanobanana_generate_content_url_blank_model_falls_back_to_nanobanana_model() #[test] fn resolve_image_provider_rejects_business_model_and_accepts_concrete_models() { // 中文注释:业务模型名不是 provider model,必须在 api-server 任务边界先解析成具体 model。 - assert!(resolve_image_provider(GPT_IMAGE_2_5_BUSINESS_NAME).is_err()); + let business_model_error = + resolve_image_provider(GPT_IMAGE_2_5_BUSINESS_NAME).expect_err("业务模型名必须被拒绝"); + assert!( + business_model_error.contains(GPT_IMAGE_2_5_BUSINESS_NAME), + "拒绝原因必须带上被拒绝的模型名,实际为:{business_model_error}" + ); // 中文注释:已删除的 gpt-image-2-c 不再被任何层接受。 assert!(resolve_image_provider("gpt-image-2-c").is_err()); @@ -242,7 +247,12 @@ fn resolve_image_provider_rejects_business_model_and_accepts_concrete_models() { resolve_image_provider("gemini-3.1-flash-image-preview"), Ok(ImageProvider::VectorEngine) ); - assert!(resolve_image_provider("unknown-model").is_err()); + let unknown_model_error = + resolve_image_provider("unknown-model").expect_err("未知模型必须被拒绝"); + assert!( + unknown_model_error.contains("unknown-model"), + "拒绝原因必须带上被拒绝的模型名,实际为:{unknown_model_error}" + ); } #[tokio::test]