From aaf43ec4212337501407295f64353acc3fd07b5a Mon Sep 17 00:00:00 2001 From: lhk Date: Tue, 29 Sep 2026 09:39:28 +0100 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Codex=20=E7=A7=81=E6=9C=89?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=9B=AE=E5=BD=95=E7=9A=84=20Windows=20UNC?= =?UTF-8?q?=20=E8=B7=AF=E5=BE=84=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 保留 UNC 网络共享根,避免规范化后变成相对路径 补充 UNC、盘符及普通路径回归测试 同步运行目录路径规范与共享决策记录 --- .../src/agent/codex_app_server/mod.rs | 41 +++++++++++++++---- .../shared-memory/decision-log.md | 1 + ...¹案】AI游戏创作智能体App实施计划-2026-06-24.md | 6 +++ 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs index f2e54e330..0a5995554 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs @@ -2193,15 +2193,20 @@ fn canonical_codex_private_runtime_dir( } let canonical = std::fs::canonicalize(path) .map_err(|error| format!("解析 Codex 私有运行目录失败:{}: {error}", path.display()))?; - Ok( - match canonical - .to_str() - .and_then(|value| value.strip_prefix("\\\\?\\")) - { - Some(stripped) => std::path::PathBuf::from(stripped), - None => canonical, - }, - ) + Ok(normalize_codex_private_runtime_path(canonical)) +} + +fn normalize_codex_private_runtime_path(path: std::path::PathBuf) -> std::path::PathBuf { + if let Some(value) = path.to_str() { + // UNC 命名空间必须恢复网络共享根,不能只去掉设备前缀后变成相对路径。 + if let Some(rest) = value.strip_prefix(r"\\?\UNC\") { + return std::path::PathBuf::from(format!(r"\\{rest}")); + } + if let Some(rest) = value.strip_prefix(r"\\?\") { + return std::path::PathBuf::from(rest); + } + } + path } fn prepare_isolated_game_creator_codex_home( @@ -6697,6 +6702,24 @@ mod tests { assert_eq!(resolved, outside.canonicalize().expect("canonical outside")); } + #[test] + fn codex_private_runtime_path_preserves_unc_and_drive_roots() { + for (input, expected) in [ + (r"\\?\UNC\server\share\session", r"\\server\share\session"), + (r"\\?\C:\Temp\session", r"C:\Temp\session"), + (r"\\server\share\session", r"\\server\share\session"), + (r"C:\Temp\session", r"C:\Temp\session"), + ("/private/tmp/session", "/private/tmp/session"), + ] { + let normalized = normalize_codex_private_runtime_path(input.into()); + assert_eq!(normalized, std::path::PathBuf::from(expected)); + #[cfg(windows)] + if input.starts_with('\\') || input.starts_with("C:") { + assert!(normalized.is_absolute()); + } + } + } + #[cfg(unix)] #[test] fn codex_private_runtime_dir_resolves_a_symlink_ancestor_and_rejects_an_inner_link() { diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 539bfa848..07789c0c0 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -3,6 +3,7 @@ ## 2026-09-29 Codex 私有运行目录先解析系统临时路径上的符号链接 - 决策:新建的 Codex 临时目录确认是普通目录后,先解析为真实路径并去掉 Windows `\\?\` 前缀,再创建 `codex-home`、`workspace` 和隔离用户目录。macOS 的 `/var`、`/tmp` 这类系统符号链接不再阻断 Game Agent 启动。 +- Windows 路径转换必须先将 `\\?\UNC\server\share\...` 恢复为 `\\server\share\...`;不能只删除 `\\?\`,否则网络共享路径会变成相对路径。盘符路径继续去掉 `\\?\` 前缀。 - 范围:`validate_game_creator_private_path_ancestors` 不放宽。AppData、客户端配置,以及临时目录内部新出现的符号链接,仍然拒绝。 - 关联:`apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs`。 diff --git a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md index 8ee04d922..5dd210419 100644 --- a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md +++ b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md @@ -1,5 +1,11 @@ # AI 游戏创作智能体 App 实施计划 +## 2026-09-29 Codex 私有运行目录路径解析 + +新建的私有运行目录先确认是普通目录并收紧权限,再解析真实路径,后续 `codex-home`、`workspace` 和隔离用户目录均在真实路径下创建,避免 macOS 系统临时目录的符号链接阻断启动。Windows 扩展 UNC 路径 `\\?\UNC\server\share\...` 必须转换为 `\\server\share\...`,盘符路径才直接去掉 `\\?\` 前缀;转换后保留绝对路径语义。私有子目录仍执行原有祖先符号链接与 reparse point 检查。 + +定向验证使用 Rust 单测过滤器 `codex_private_runtime_`,覆盖 UNC、盘符和普通路径转换,以及 Unix 祖先链接解析与内部链接拒绝;Windows 绝对路径断言在 Windows 测试环境执行。 + ## 2026-09-28 Web 环境版本探测的用户目录隔离 Node/npm 版本探测清空继承环境后,必须设置客户端创建的临时 `HOME`、`USERPROFILE`、`APPDATA` 和 `LOCALAPPDATA`,并指定空的用户及全局 npm 配置、临时缓存和临时工作目录。临时目录保留到探测子进程退出,不依赖 Windows 用户资料查询,也不读取用户或项目的 `.npmrc`。探测继续使用校验后的客户端运行时;初始化临时环境失败返回 `runtime-probe-home-unavailable`,不回退到系统 Node 或真实用户目录。