From f2946aaeca16d533c4604e7b43002ea0df772057 Mon Sep 17 00:00:00 2001 From: kdletters <61648117+kdletters@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:08:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=9D=E7=95=99=E5=B7=A5=E5=85=B7=E6=A1=A5?= =?UTF-8?q?=E5=92=8C=E9=AA=8C=E8=AF=81=E8=AF=81=E6=8D=AE=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 保留图片证据读取和哈希底层原因 补充 Direct 工具错误展示约定 --- .../src-tauri/src/agent/direct_tool_bridge.rs | 8 +++---- .../src-tauri/src/agent/direct_validation.rs | 23 ++++++++++--------- ...GC命令错误结构化与错误报告口径-2026-10-01.md | 1 + ...€�里程碑】AGC错误具体文本展示-2026-10-04.md | 1 + 4 files changed, 18 insertions(+), 15 deletions(-) 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 a3a32f57f..3133e14c3 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 @@ -1053,15 +1053,15 @@ fn bridge_resource_request_fingerprint(input: &DirectResourceGenerationInput) -> fn bridge_png_content(root: &Path, path: &Path) -> Result { let root = root .canonicalize() - .map_err(|_| "工具桥项目根无法安全解析".to_string())?; + .map_err(|error| format!("工具桥项目根无法安全解析:{error}"))?; let path = path .canonicalize() - .map_err(|_| "工具桥图片不存在".to_string())?; + .map_err(|error| format!("工具桥图片不存在或无法解析:{error}"))?; if !path.starts_with(&root) { return Err("工具桥图片越出当前项目边界".to_string()); } let metadata = - std::fs::symlink_metadata(&path).map_err(|_| "读取工具桥图片失败".to_string())?; + std::fs::symlink_metadata(&path).map_err(|error| format!("读取工具桥图片失败:{error}"))?; if metadata.file_type().is_symlink() || !metadata.is_file() || metadata.len() > DIRECT_TOOL_BRIDGE_MAX_IMAGE_BYTES @@ -1071,7 +1071,7 @@ fn bridge_png_content(root: &Path, path: &Path) -> Result { let (mut file, _) = open_project_snapshot_regular_file(&path, "工具桥图片")?; let mut bytes = Vec::new(); file.read_to_end(&mut bytes) - .map_err(|_| "读取工具桥图片失败".to_string())?; + .map_err(|error| format!("读取工具桥图片失败:{error}"))?; if !bytes.starts_with(b"\x89PNG\r\n\x1a\n") { return Err("工具桥图片不是有效 PNG".to_string()); } diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_validation.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_validation.rs index a42aed1b0..9fa876912 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_validation.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_validation.rs @@ -104,17 +104,17 @@ fn evidence_hashes(root: &Path, result: &Value) -> Result { return Err("validation-evidence: 证据不属于受控验证目录".into()); } let path = resolve_local_project_path(root, relative)?; - let meta = - std::fs::symlink_metadata(&path).map_err(|_| "validation-evidence: 证据文件丢失")?; + let meta = std::fs::symlink_metadata(&path) + .map_err(|error| format!("validation-evidence: 证据文件丢失:{error}"))?; if !meta.is_file() || meta.file_type().is_symlink() || meta.len() > 16 * 1024 * 1024 { return Err("validation-evidence: 证据类型或大小无效".into()); } let mut bytes = Vec::new(); std::fs::File::open(path) - .map_err(|_| "validation-evidence: 无法读取证据")? + .map_err(|error| format!("validation-evidence: 无法读取证据:{error}"))? .take(16 * 1024 * 1024 + 1) .read_to_end(&mut bytes) - .map_err(|_| "validation-evidence: 无法读取证据")?; + .map_err(|error| format!("validation-evidence: 无法读取证据:{error}"))?; if bytes.len() > 16 * 1024 * 1024 { return Err("validation-evidence: 证据文件在读取时超限".into()); } @@ -234,14 +234,15 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result { let mut bytes = 0u64; let mut visited = 0usize; while let Some(directory) = directories.pop() { - for entry in - std::fs::read_dir(&directory).map_err(|_| "validation-fingerprint: 读取项目失败")? + for entry in std::fs::read_dir(&directory) + .map_err(|error| format!("validation-fingerprint: 读取项目失败:{error}"))? { visited += 1; if visited > 20_000 { return Err("validation-fingerprint: 项目文件数超限".into()); } - let entry = entry.map_err(|_| "validation-fingerprint: 读取目录项失败")?; + let entry = entry + .map_err(|error| format!("validation-fingerprint: 读取目录项失败:{error}"))?; let name = entry.file_name().to_string_lossy().to_ascii_lowercase(); if matches!( name.as_str(), @@ -264,7 +265,7 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result { } let ty = entry .file_type() - .map_err(|_| "validation-fingerprint: 读取类型失败")?; + .map_err(|error| format!("validation-fingerprint: 读取类型失败:{error}"))?; let path = entry.path(); if !include_outputs && name == "dist" @@ -300,14 +301,14 @@ fn fingerprint(root: &Path, include_outputs: bool) -> Result { if name.starts_with("game-creator.config") { continue; } - let mut file = - std::fs::File::open(&path).map_err(|_| "validation-fingerprint: 打开输入失败")?; + let mut file = std::fs::File::open(&path) + .map_err(|error| format!("validation-fingerprint: 打开输入失败:{error}"))?; let mut digest = Sha256::new(); let mut buffer = [0u8; 64 * 1024]; loop { let read = file .read(&mut buffer) - .map_err(|_| "validation-fingerprint: 读取输入失败")?; + .map_err(|error| format!("validation-fingerprint: 读取输入失败:{error}"))?; if read == 0 { break; } diff --git a/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md b/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md index 949963a59..e066ee91c 100644 --- a/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md +++ b/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md @@ -117,6 +117,7 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接 - Codex Provider proxy 的请求体读取/JSON 改写、上游请求、响应构造和 SSE 传输错误也必须把 serde、join、reqwest 或流错误写入返回正文,不能只回 `provider upstream unavailable`。 - 浏览器健康检查的发现、临时目录、配置、DevTools 版本请求和清理失败保留底层错误/超时阶段;稳定浏览器码用于分类,但不能覆盖诊断正文。 - WebView 普通错误出口遇到 Tauri 的结构化对象时,优先展示 `message/detail/reason/code`,再有界序列化对象;不得把对象转成 `[object Object]` 后回落“未提供具体错误正文”。 +- Direct 工具桥图片读取和真实试玩验证证据的 OS 读取/哈希错误保留底层原因;路径越界、私有路径和安全拒绝仍使用稳定安全码。 - 浏览器启动/DevTools 握手与 Codex model-catalog 子进程失败保留 stderr、退出状态、解析错误和阶段;稳定机器码仍用于分类,但不能单独成为用户可见正文。 - Node/npm 环境探测和 Web scaffold 构建持续排空并保存有界 stdout/stderr 尾部,失败返回退出状态、超时阶段和脱敏正文;环境预检回执同时下发 `code` 与 `diagnostic`。 - HTTP 409 只有明确包含泥点不足事实时才映射为 `paidCreditsInsufficient`;Claude Code 的普通 409 冲突保留为 `upstreamFailed`。 diff --git a/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md b/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md index 2e333217d..df5ddfe51 100644 --- a/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md +++ b/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md @@ -20,6 +20,7 @@ DirectProject 回合失败在确认不是客户端内部不可归类故障时, - Codex Provider proxy 的请求体改写、上游发送、响应构造和 SSE 错误保留底层正文,避免代理层再次把具体网络/解析故障压成单一 unavailable。 - 浏览器健康检查不再把发现、配置、DevTools 版本和清理失败只返回机器码;阶段码保留,同时带底层错误或明确的超时预算。 - WebView 结构化对象错误保留 `message/detail/reason/code` 或有界 JSON 正文,避免 `[object Object]` 触发普通错误兜底。 +- Direct 工具桥图片与真实试玩证据读取/哈希错误保留 OS 正文,安全边界拒绝继续使用稳定码。 - Transport / Stream / IPC / host process / memory exhaustion 的回归测试与错误事件证据。 ## 不做