agc_generate_image 的 kind 传了非字符串不再静默当成 image

- 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,单独重跑通过)
This commit is contained in:
2026-10-01 15:39:56 +08:00
parent 3f70c69119
commit 7c67a6fcc0
2 changed files with 48 additions and 6 deletions
@@ -2900,12 +2900,16 @@ fn generate_image_grid_axis(
fn bridge_image_generation_kind(
arguments: &Value,
) -> Result<GameCreationAppAssetKind, GenerateImageError> {
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",
@@ -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()