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 00940673a..d35ae9383 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 @@ -4898,18 +4898,30 @@ mod tests { GameCreationAppAssetKind::Image ); - let trailing_newline = match resource_generation_input(&json!({ + assert_eq!( + resource_generation_input(&json!({ + "kind": "video", + "mode": "create", + "prompt": "生成过场\n", + "assetName": "开场" + })) + .expect("首尾换行按普通空白裁掉,不能报控制字符") + .prompt, + "生成过场" + ); + + let interior_newline = match resource_generation_input(&json!({ "kind": "video", "mode": "create", - "prompt": "生成过场\n", + "prompt": "生成\n过场", "assetName": "开场" })) { - Ok(_) => panic!("落在首尾的控制字符不能被 trim 静默吞掉"), + Ok(_) => panic!("中间的控制字符仍必须被拒绝"), Err(error) => error.to_user_msg(), }; assert!( - trailing_newline.contains("prompt 含有控制字符"), - "{trailing_newline}" + interior_newline.contains("prompt 含有控制字符"), + "{interior_newline}" ); let whitespace_only = diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs index 67c29cbcb..1460a49ea 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/arguments.rs @@ -37,19 +37,17 @@ pub(crate) fn optional_text, E>( let Some(value) = value.as_str() else { return Err(field.not_text(value.to_string())); }; - let trimmed = value.trim(); - if trimmed.is_empty() { + let value = value.trim(); + if value.is_empty() { return Err(field.empty()); } - // 控制字符必须按原串判定:否则落在首尾的 `\n`/`\t` 会被 trim 静默吞掉, - // 同一个字符在中间报错、在边上通过。 + if value.chars().count() > field.max_chars() { + return Err(field.too_long(value.chars().count(), field.max_chars())); + } if value.chars().any(char::is_control) { return Err(field.has_control_characters()); } - if trimmed.chars().count() > field.max_chars() { - return Err(field.too_long(trimmed.chars().count(), field.max_chars())); - } - Ok(Some(trimmed.to_string())) + Ok(Some(value.to_string())) } /// 一页列表结果:`offset` 是起始下标,`limit` 是这一次最多返回多少项。