编辑器执行 code 的三种校验失败拆成独立变体

- EditorExecuteError 的 CodeInvalid 拆成 CodeEmpty / CodeContainsNul / CodeTooLong{got_bytes,max_bytes},每个 case 一个变体
- editor_execute/error.rs 新增 EDITOR_CODE_MAX_BYTES 常量,direct_tool_bridge 的校验改用该常量并分别返回对应变体
- 模型能从文案看出具体违反了哪条规则,不再只看到一句话笼统覆盖三种失败
This commit is contained in:
2026-10-01 17:55:41 +08:00
parent bab88d62e0
commit 7eb62b09e2
2 changed files with 32 additions and 5 deletions
@@ -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())
}
@@ -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())