From 7c67a6fcc0789263e90acda81839657384579937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Thu, 1 Oct 2026 15:39:56 +0800 Subject: [PATCH] =?UTF-8?q?agc=5Fgenerate=5Fimage=20=E7=9A=84=20kind=20?= =?UTF-8?q?=E4=BC=A0=E4=BA=86=E9=9D=9E=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E9=9D=99=E9=BB=98=E5=BD=93=E6=88=90=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bridge_image_generation_kind 原来用 and_then(Value::as_str)…unwrap_or("image"):{"kind":true}、{"kind":5}、{"kind":[]} 都会被当成 image 继续生成;空串也会被静默当默认值 - 改成按 schema 语义区分:缺省与显式 null 用默认 image;字符串按原值走 canonical 校验(空串/未知值走 KindUnsupported);其它类型返回新的 GenerateImageError::KindNotText { got } - 测试补四条断言:kind=true 报「kind 必须是字符串」、kind="" 报「不是受支持的素材类型」、缺省与 null 仍解析为 image 验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 41 passed;agent:: tests::project:: 1078 passed(两条失败为既有 flaky:art_director_request_exposes_canvas_only_for_the_keyed_owner_route / background_agent_runtime_can_generate_platform_art_asset,单独重跑通过) --- .../src-tauri/src/agent/direct_tool_bridge.rs | 50 ++++++++++++++++--- .../src/agent/tool/generate_image/error.rs | 4 ++ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs index 4c791e640..00940673a 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs @@ -2900,12 +2900,16 @@ fn generate_image_grid_axis( fn bridge_image_generation_kind( arguments: &Value, ) -> Result { - let kind = arguments - .get("kind") - .and_then(Value::as_str) - .map(str::trim) - .filter(|value| !value.is_empty()) - .unwrap_or("image"); + // 缺省与显式 null 用 schema 声明的默认值;给了别的类型不许静默当 image。 + let kind = match arguments.get("kind") { + None | Some(Value::Null) => "image", + Some(Value::String(value)) => value.trim(), + Some(value) => { + return Err(GenerateImageError::KindNotText { + got: value.to_string(), + }) + } + }; normalize_platform_art_asset_generation_kind(kind).ok_or_else(|| { GenerateImageError::KindUnsupported { got: kind.to_string(), @@ -4860,6 +4864,40 @@ mod tests { #[test] fn non_text_field_values_report_a_type_error_instead_of_an_empty_value() { + let kind_not_text = match generate_image_input(&json!({ + "prompt": "像素风主角", + "kind": true + })) { + Ok(_) => panic!("kind 不是字符串时必须被拒绝"), + Err(error) => error.to_user_msg(), + }; + assert!( + kind_not_text.contains("kind 必须是字符串"), + "{kind_not_text}" + ); + + let kind_empty = match generate_image_input(&json!({ + "prompt": "像素风主角", + "kind": "" + })) { + Ok(_) => panic!("空 kind 必须被拒绝,不能再静默当 image"), + Err(error) => error.to_user_msg(), + }; + assert!(kind_empty.contains("不是受支持的素材类型"), "{kind_empty}"); + + assert_eq!( + generate_image_input(&json!({ "prompt": "像素风主角" })) + .map(|input| input.kind) + .expect("缺省 kind 仍默认 image"), + GameCreationAppAssetKind::Image + ); + assert_eq!( + generate_image_input(&json!({ "prompt": "像素风主角", "kind": null })) + .map(|input| input.kind) + .expect("显式 null 仍按默认 image"), + GameCreationAppAssetKind::Image + ); + let trailing_newline = match resource_generation_input(&json!({ "kind": "video", "mode": "create", diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/generate_image/error.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/generate_image/error.rs index 847c35299..2bf337653 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/generate_image/error.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/generate_image/error.rs @@ -20,6 +20,7 @@ pub(crate) enum GenerateImageError { PromptTooLong { got_chars: usize, max_chars: usize }, PromptHasControlCharacters, PromptNotText { got: String }, + KindNotText { got: String }, KindUnsupported { got: String }, AspectRatioEmpty, AspectRatioTooLong { got_chars: usize, max_chars: usize }, @@ -83,6 +84,9 @@ impl ToolFailure for GenerateImageError { Self::PromptNotText { got } => format!( "生成图片失败:prompt 必须是字符串,当前是「{got}」。" ), + Self::KindNotText { got } => { + format!("生成图片失败:kind 必须是字符串,当前是「{got}」。") + } Self::KindUnsupported { got } => format!( "生成图片失败:kind「{got}」不是受支持的素材类型,只允许 {}。", platform_art_asset_generation_kind_list()