生成图片的允许值与边界提成常量,校验与诊断文案共用同一份
- 新增 GENERATE_IMAGE_ASPECT_RATIOS / _IMAGE_SIZES / _SLICE_MODES 与 grid 轴、sliceCount 的 MIN/MAX 常量,放在 direct_tool_bridge 的 GENERATE_IMAGE_ARGUMENTS 旁 - generate_image_input 的 aspectRatio / imageSize / sliceMode / grid 轴区间 / sliceCount 区间校验改为读常量;generate_image/error.rs 的对应文案也改为读同一批常量(KindUnsupported 早已从 PLATFORM_ART_ASSET_GENERATION_KINDS 派生,这次把其余几组对齐) - 只改取值来源,判定范围与文案取值不变 - 未纳入本次:commands.rs 的 LOCAL_PROJECT_ASSET_ASPECT_RATIOS/_IMAGE_SIZES 与 agent_native_tools.rs 的 canvas.asset_generate schema 仍是各自的副本(面向非 agent 的栏目画布入口),统一它们属于另一次改动 验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: agent::direct_tools_mcp:: 71 passed
This commit is contained in:
@@ -2711,6 +2711,17 @@ async fn bridge_prepare_game_art(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// `agc_generate_image` 的受支持取值与边界:解析校验与失败文案共用同一份,
|
||||
/// 避免两边各写一遍、改动时静默漂移。
|
||||
pub(in crate::agent) const GENERATE_IMAGE_ASPECT_RATIOS: &[&str] =
|
||||
&["1:1", "2:3", "3:2", "9:16", "16:9"];
|
||||
pub(in crate::agent) const GENERATE_IMAGE_IMAGE_SIZES: &[&str] = &["0.5K", "1K", "2K"];
|
||||
pub(in crate::agent) const GENERATE_IMAGE_SLICE_MODES: &[&str] = &["connected-components", "grid"];
|
||||
pub(in crate::agent) const GENERATE_IMAGE_GRID_AXIS_MIN: u32 = 1;
|
||||
pub(in crate::agent) const GENERATE_IMAGE_GRID_AXIS_MAX: u32 = 32;
|
||||
pub(in crate::agent) const GENERATE_IMAGE_SLICE_COUNT_MIN: u64 = 1;
|
||||
pub(in crate::agent) const GENERATE_IMAGE_SLICE_COUNT_MAX: u64 = 256;
|
||||
|
||||
/// `agc_generate_image` 允许的入参字段。
|
||||
const GENERATE_IMAGE_ARGUMENTS: &[&str] = &[
|
||||
"prompt",
|
||||
@@ -2962,15 +2973,12 @@ pub(in crate::agent) fn generate_image_input(
|
||||
let aspect_ratio =
|
||||
generate_image_optional_text(arguments, GenerateImageTextField::AspectRatio)?
|
||||
.unwrap_or_else(|| "1:1".to_string());
|
||||
if !matches!(
|
||||
aspect_ratio.as_str(),
|
||||
"1:1" | "2:3" | "3:2" | "9:16" | "16:9"
|
||||
) {
|
||||
if !GENERATE_IMAGE_ASPECT_RATIOS.contains(&aspect_ratio.as_str()) {
|
||||
return Err(GenerateImageError::AspectRatioUnsupported { got: aspect_ratio });
|
||||
}
|
||||
let image_size = generate_image_optional_text(arguments, GenerateImageTextField::ImageSize)?
|
||||
.unwrap_or_else(|| "1K".to_string());
|
||||
if !matches!(image_size.as_str(), "0.5K" | "1K" | "2K") {
|
||||
if !GENERATE_IMAGE_IMAGE_SIZES.contains(&image_size.as_str()) {
|
||||
return Err(GenerateImageError::ImageSizeUnsupported { got: image_size });
|
||||
}
|
||||
let asset_name = generate_image_optional_text(arguments, GenerateImageTextField::AssetName)?
|
||||
@@ -2979,7 +2987,7 @@ pub(in crate::agent) fn generate_image_input(
|
||||
let slice_mode = generate_image_optional_text(arguments, GenerateImageTextField::SliceMode)?;
|
||||
if slice_mode
|
||||
.as_deref()
|
||||
.is_some_and(|mode| !matches!(mode, "connected-components" | "grid"))
|
||||
.is_some_and(|mode| !GENERATE_IMAGE_SLICE_MODES.contains(&mode))
|
||||
{
|
||||
return Err(GenerateImageError::SliceModeUnsupported {
|
||||
got: slice_mode.unwrap_or_default(),
|
||||
@@ -2991,7 +2999,9 @@ pub(in crate::agent) fn generate_image_input(
|
||||
return Err(GenerateImageError::GridAxesMissing);
|
||||
}
|
||||
for (axis, value) in [("gridX", grid_x), ("gridY", grid_y)] {
|
||||
if let Some(got) = value.filter(|value| !(1..=32).contains(value)) {
|
||||
if let Some(got) = value.filter(|value| {
|
||||
!(GENERATE_IMAGE_GRID_AXIS_MIN..=GENERATE_IMAGE_GRID_AXIS_MAX).contains(value)
|
||||
}) {
|
||||
return Err(GenerateImageError::GridOutOfRange { axis, got });
|
||||
}
|
||||
}
|
||||
@@ -3001,7 +3011,10 @@ pub(in crate::agent) fn generate_image_input(
|
||||
.map(|value| {
|
||||
value
|
||||
.as_u64()
|
||||
.filter(|count| (1..=256).contains(count))
|
||||
.filter(|count| {
|
||||
(GENERATE_IMAGE_SLICE_COUNT_MIN..=GENERATE_IMAGE_SLICE_COUNT_MAX)
|
||||
.contains(count)
|
||||
})
|
||||
.map(|count| count as usize)
|
||||
.ok_or_else(|| GenerateImageError::SliceCountInvalid {
|
||||
got: value.to_string(),
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
//!
|
||||
//! 这里只放错误本身;参数解析与工具执行留在 `direct_tool_bridge`。
|
||||
|
||||
use crate::agent::direct_tool_bridge::{
|
||||
GENERATE_IMAGE_ASPECT_RATIOS, GENERATE_IMAGE_GRID_AXIS_MAX, GENERATE_IMAGE_GRID_AXIS_MIN,
|
||||
GENERATE_IMAGE_IMAGE_SIZES, GENERATE_IMAGE_SLICE_COUNT_MAX, GENERATE_IMAGE_SLICE_COUNT_MIN,
|
||||
GENERATE_IMAGE_SLICE_MODES,
|
||||
};
|
||||
use crate::agent::generation::PLATFORM_ART_ASSET_GENERATION_KINDS;
|
||||
use crate::agent::tool::error::{ProjectPermissionRejection, ToolArgumentsRejection, ToolFailure};
|
||||
use shared_contracts::game_creation_app::GameCreationAppAssetKind;
|
||||
@@ -84,7 +89,8 @@ impl ToolFailure for GenerateImageError {
|
||||
"生成图片失败:aspectRatio 含有控制字符。".to_string()
|
||||
}
|
||||
Self::AspectRatioUnsupported { got } => format!(
|
||||
"生成图片失败:aspectRatio「{got}」不是受支持的比例,只能是 1:1、2:3、3:2、9:16、16:9。"
|
||||
"生成图片失败:aspectRatio「{got}」不是受支持的比例,只能是 {}。",
|
||||
GENERATE_IMAGE_ASPECT_RATIOS.join("、")
|
||||
),
|
||||
Self::ImageSizeEmpty => "生成图片失败:imageSize 传了空值。".to_string(),
|
||||
Self::ImageSizeTooLong {
|
||||
@@ -95,7 +101,8 @@ impl ToolFailure for GenerateImageError {
|
||||
"生成图片失败:imageSize 含有控制字符。".to_string()
|
||||
}
|
||||
Self::ImageSizeUnsupported { got } => format!(
|
||||
"生成图片失败:imageSize「{got}」不是受支持的图片尺寸,只能是 0.5K、1K、2K。"
|
||||
"生成图片失败:imageSize「{got}」不是受支持的图片尺寸,只能是 {}。",
|
||||
GENERATE_IMAGE_IMAGE_SIZES.join("、")
|
||||
),
|
||||
Self::AssetNameEmpty => "生成图片失败:assetName 传了空值。".to_string(),
|
||||
Self::AssetNameTooLong {
|
||||
@@ -122,7 +129,8 @@ impl ToolFailure for GenerateImageError {
|
||||
"生成图片失败:sliceMode 含有控制字符。".to_string()
|
||||
}
|
||||
Self::SliceModeUnsupported { got } => format!(
|
||||
"生成图片失败:sliceMode「{got}」不受支持,只允许 connected-components 或 grid。"
|
||||
"生成图片失败:sliceMode「{got}」不受支持,只允许 {}。",
|
||||
GENERATE_IMAGE_SLICE_MODES.join("、")
|
||||
),
|
||||
Self::GridAxisNotInteger { axis } => {
|
||||
format!("生成图片失败:{axis} 必须是整数。")
|
||||
@@ -131,10 +139,14 @@ impl ToolFailure for GenerateImageError {
|
||||
"生成图片失败:sliceMode=grid 必须同时提供 gridX 与 gridY。".to_string()
|
||||
}
|
||||
Self::GridOutOfRange { axis, got } => {
|
||||
format!("生成图片失败:{axis}={got} 超出范围,gridX/gridY 必须在 1 到 32 之间。")
|
||||
format!(
|
||||
"生成图片失败:{axis}={got} 超出范围,gridX/gridY 必须在 {GENERATE_IMAGE_GRID_AXIS_MIN} 到 {GENERATE_IMAGE_GRID_AXIS_MAX} 之间。"
|
||||
)
|
||||
}
|
||||
Self::SliceCountInvalid { got } => {
|
||||
format!("生成图片失败:sliceCount「{got}」非法,必须是 1 到 256 的整数。")
|
||||
format!(
|
||||
"生成图片失败:sliceCount「{got}」非法,必须是 {GENERATE_IMAGE_SLICE_COUNT_MIN} 到 {GENERATE_IMAGE_SLICE_COUNT_MAX} 的整数。"
|
||||
)
|
||||
}
|
||||
Self::SpritesheetSliceModeMissing => format!(
|
||||
"生成图片失败:kind={} 必须显式声明 sliceMode,没有默认值:需求要求等分网格、固定槽位或指定行列数时传 sliceMode=grid 并提供 gridX/gridY;自由排布、数量不定或只要求一张图集时传 sliceMode=connected-components。",
|
||||
|
||||
Reference in New Issue
Block a user