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 d419920b2..922b4cacb 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 @@ -14,7 +14,9 @@ use crate::agent::tool::edit_image::error::EditImageError; target_arch = "x86_64", any(feature = "unity-editor-execute", feature = "godot-editor-execute") ))] -use crate::agent::tool::editor_execute::error::{EditorExecuteError, EditorKind}; +use crate::agent::tool::editor_execute::error::{ + EditorExecuteError, EditorKind, EDITOR_CODE_MAX_BYTES, +}; use crate::agent::tool::environment_check::error::EnvironmentCheckError; use crate::agent::tool::error::{ bounded_echo, DirectExecutionGateRejection, DirectTurnGateRejection, ProjectManifestRejection, @@ -3663,8 +3665,17 @@ pub(in crate::agent) fn editor_execute_code_input( .get("code") .and_then(Value::as_str) .ok_or(EditorExecuteError::CodeNotText { editor })?; - if code.trim().is_empty() || code.len() > 131072 || code.contains('\0') { - return Err(EditorExecuteError::CodeInvalid); + if code.trim().is_empty() { + return Err(EditorExecuteError::CodeEmpty); + } + if code.len() > EDITOR_CODE_MAX_BYTES { + return Err(EditorExecuteError::CodeTooLong { + got_bytes: code.len(), + max_bytes: EDITOR_CODE_MAX_BYTES, + }); + } + if code.contains('\0') { + return Err(EditorExecuteError::CodeContainsNul); } Ok(code.to_string()) } diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/editor_execute/error.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/editor_execute/error.rs index 51db61dee..55e0f0138 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/editor_execute/error.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/editor_execute/error.rs @@ -5,6 +5,9 @@ use crate::agent::tool::error::{ProjectPermissionRejection, ToolArgumentsRejection, ToolFailure}; use serde_json::Value; +/// `code` 的长度上限(字节):编辑器适配器按 UTF-8 字节数收代码。 +pub(crate) const EDITOR_CODE_MAX_BYTES: usize = 131_072; + /// 两个编辑器执行工具之间的差异:插件身份、给用户看的编辑器名、代码语言名。 /// /// 差异做成枚举,错误变体只带 `EditorKind`,不在文案里手写编辑器名。 @@ -48,7 +51,15 @@ pub(crate) enum EditorExecuteError { CodeNotText { editor: EditorKind, }, - CodeInvalid, + /// `code` 只有空白。 + CodeEmpty, + /// `code` 含 NUL:适配器与传输层都不接受。 + CodeContainsNul, + /// `code` 超过 [`EDITOR_CODE_MAX_BYTES`]。 + CodeTooLong { + got_bytes: usize, + max_bytes: usize, + }, /// 编辑器适配器拒绝了这次执行,或回执不可用。 EditorRejected { cause: String, @@ -87,7 +98,12 @@ impl ToolFailure for EditorExecuteError { Self::CodeNotText { editor } => { format!("code 必须是 {}。", editor.language()) } - Self::CodeInvalid => "code 不能为空、包含 NUL 或超过 128 KiB。".to_string(), + Self::CodeEmpty => "code 不能为空。".to_string(), + Self::CodeContainsNul => "code 不能包含 NUL。".to_string(), + Self::CodeTooLong { + got_bytes, + max_bytes, + } => format!("code 有 {got_bytes} 字节,超过上限 {max_bytes} 字节。"), Self::EditorRejected { cause } => cause.to_string(), Self::ExecutionNotCompleted { editor, report } => { format!("{} 执行未完成:{report}", editor.label())