From 28ce0c0b239e7feea8cdaafae9aa871eb2a6ef2c Mon Sep 17 00:00:00 2001 From: kdletters <61648117+kdletters@users.noreply.github.com> Date: Mon, 5 Oct 2026 18:52:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5=E9=94=99=E8=AF=AF=E6=AD=A3?= =?UTF-8?q?=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 保留浏览器发现配置 DevTools 和清理原因 通过浏览器健康定向测试 --- .../src-tauri/src/browser/process.rs | 38 ++++++++++++++----- ...GC命令错误结构化与错误报告口径-2026-10-01.md | 1 + ...€�里程碑】AGC错误具体文本展示-2026-10-04.md | 1 + 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/browser/process.rs b/apps/ai-game-creator-shell/src-tauri/src/browser/process.rs index ac46bbbda..66862b26e 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/browser/process.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/browser/process.rs @@ -198,6 +198,23 @@ impl BrowserLaunchFailure { } } + fn setup_with_detail(code: &'static str, detail: impl Into) -> Self { + let detail = detail.into(); + Self { + code, + stage: BrowserLaunchStage::Setup, + recoverable: false, + subprocess_exited: true, + cleanup_confirmed: true, + detail: Some( + crate::sanitize_diagnostic_message(&detail, None) + .chars() + .take(1200) + .collect(), + ), + } + } + fn from_launch_error( error: OwnedBrowserLaunchError, subprocess_exited: bool, @@ -666,10 +683,12 @@ async fn launch_browser_attempt( executable: &std::path::Path, proxy_bypass_list: &str, ) -> Result { - let temporary = create_browser_process_temp_dir() - .map_err(|_| BrowserLaunchFailure::setup("browser-temp-unavailable"))?; - let config = browser_config(executable, &temporary, proxy_bypass_list) - .map_err(|_| BrowserLaunchFailure::setup("browser-config-invalid"))?; + let temporary = create_browser_process_temp_dir().map_err(|error| { + BrowserLaunchFailure::setup_with_detail("browser-temp-unavailable", error) + })?; + let config = browser_config(executable, &temporary, proxy_bypass_list).map_err(|error| { + BrowserLaunchFailure::setup_with_detail("browser-config-invalid", error) + })?; launch_owned_browser(config, executable, temporary).await } @@ -685,15 +704,16 @@ async fn launch_browser_with_recovery( /// 仅验证浏览器启动和真实 CDP,不加载项目、不生成试玩凭证。 /// 每次独立 profile;既不串行化其它工具,也不继承 Codex 的临时 HOME。 pub(crate) async fn check_browser_health() -> Result { - let discovered = discover_chrome_or_edge().map_err(|_| "browser-not-found")?; + let discovered = + discover_chrome_or_edge().map_err(|error| format!("browser-not-found:{error}"))?; let owned = launch_browser_with_recovery(&discovered.executable_path, "<-loopback").await?; let version = tokio::time::timeout(Duration::from_secs(5), owned.browser().version()).await; - if owned.shutdown().await.is_err() { - return Err("browser-cleanup-failed".into()); + if let Err(error) = owned.shutdown().await { + return Err(format!("browser-cleanup-failed:{error}")); } let version = version - .map_err(|_| "browser-cdp-timeout")? - .map_err(|_| "browser-cdp-failed")?; + .map_err(|_| "browser-cdp-timeout:等待 DevTools 版本响应超过 5000 ms".to_string())? + .map_err(|error| format!("browser-cdp-failed:{error}"))?; if !safe_version_label(&version.product) || !safe_version_label(&version.protocol_version) { return Err("browser-version-invalid".into()); } diff --git a/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md b/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md index 42ec51ead..e853f1829 100644 --- a/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md +++ b/docs/adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md @@ -115,6 +115,7 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接 - 插件 stdout RPC 读取线程不得吞掉 `fill_buf`、UTF-8 或大小上限错误后伪装成“插件进程已退出”;读线程通过挂起 RPC 的错误通道传播真实原因。 - Codex CLI/Agent Runner 的 stderr、子任务 join、请求序列化/响应解析和本地资源/字体读取错误保留底层 `std::io`、serde 与 UTF-8 原因;路径安全校验仍单独使用稳定的安全拒绝码。 - Codex Provider proxy 的请求体读取/JSON 改写、上游请求、响应构造和 SSE 传输错误也必须把 serde、join、reqwest 或流错误写入返回正文,不能只回 `provider upstream unavailable`。 +- 浏览器健康检查的发现、临时目录、配置、DevTools 版本请求和清理失败保留底层错误/超时阶段;稳定浏览器码用于分类,但不能覆盖诊断正文。 - 浏览器启动/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 daa45726f..f4fffb4cd 100644 --- a/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md +++ b/docs/project-memory/plans/【里程碑】AGC错误具体文本展示-2026-10-04.md @@ -18,6 +18,7 @@ DirectProject 回合失败在确认不是客户端内部不可归类故障时, - 插件 stdout RPC 的 `fill_buf`、UTF-8 和响应大小错误通过挂起 RPC 传播,不能在读取线程里吞掉后统一说“插件进程已退出”。 - Codex CLI/Agent Runner 及本地素材/字体读取保留 stderr、join、序列化/解析、UTF-8 和 OS 错误正文;路径边界拒绝仍保留稳定安全码。 - Codex Provider proxy 的请求体改写、上游发送、响应构造和 SSE 错误保留底层正文,避免代理层再次把具体网络/解析故障压成单一 unavailable。 +- 浏览器健康检查不再把发现、配置、DevTools 版本和清理失败只返回机器码;阶段码保留,同时带底层错误或明确的超时预算。 - Transport / Stream / IPC / host process / memory exhaustion 的回归测试与错误事件证据。 ## 不做