补齐 DirectProject 项目根工作区的 MCP 桥与试玩提示词
Project CI / Repository checks (push) Successful in 3m32s
Project CI / Backend tests (push) Successful in 5m32s
Project CI / Frontend tests (push) Successful in 6m7s
Project CI / Native shell tests (push) Failing after 12m24s

agc_tools MCP 工作目录校验改为直接把当前目录作为项目根解析,不再假设 game/ 子目录或反推 parent。

直连浏览器证据提示词同步为项目根 cwd,并更新对应断言与测试。
This commit is contained in:
2026-08-27 10:14:53 +08:00
parent 6d36d625ad
commit f1605de4d4
2 changed files with 12 additions and 15 deletions
@@ -3344,7 +3344,7 @@ fn direct_browser_evidence_prompt(
),
};
format!(
"[AGC 浏览器事实证据]\nattempt={attempt}; completionError={completion_status}; browser={browser_status}; codeFingerprintChanged={output_changed}\n{}\n诊断与平台素材运行时观察:{}\n交互探针:{}\n客户端已保存结构化证据;它是事实输入,不代表 Codex 已阅读截图或已经完成修复。当前 cwd 是真实 `game/` 目录;按需读取实际文件,并自行决定是否修改、再次试玩或直接回复。AGC 只负责启动浏览器、采集证据和执行项目边界,Codex 负责解释结果。",
"[AGC 浏览器事实证据]\nattempt={attempt}; completionError={completion_status}; browser={browser_status}; codeFingerprintChanged={output_changed}\n{}\n诊断与平台素材运行时观察:{}\n交互探针:{}\n客户端已保存结构化证据;它是事实输入,不代表 Codex 已阅读截图或已经完成修复。当前 cwd 是项目根目录;按需读取实际文件,并自行决定是否修改、再次试玩或直接回复。AGC 只负责启动浏览器、采集证据和执行项目边界,Codex 负责解释结果。",
viewport_lines.join("\n"),
if details.is_empty() {
"无额外硬失败详情".to_string()
@@ -5882,7 +5882,7 @@ mod tests {
assert!(prompt.contains("completionError="));
assert!(prompt.contains("未在源码中引用任何已登记的陶泥儿平台图片"));
assert!(prompt.contains("本次未启动 Chromium"));
assert!(prompt.contains("当前 cwd 是真实 `game/` 目录"));
assert!(prompt.contains("当前 cwd 是项目根目录"));
}
fn direct_browser_evidence_fixture(
@@ -6011,7 +6011,7 @@ mod tests {
prompt.contains("未在 Canvas/WebGL 渲染调用中观察到已登记陶泥儿图片"),
"{prompt}"
);
assert!(prompt.contains("当前 cwd 是真实 `game/` 目录"), "{prompt}");
assert!(prompt.contains("当前 cwd 是项目根目录"), "{prompt}");
assert!(prompt.contains("Codex 负责解释结果"), "{prompt}");
assert!(!prompt.contains(".agent/runtime/"), "{prompt}");
}
@@ -407,21 +407,18 @@ fn mcp_tool_result(text: String, images: Vec<String>, is_error: bool) -> Value {
fn validate_direct_tools_project_root(workspace: &Path) -> Result<PathBuf, String> {
if !workspace.is_absolute() || !workspace.is_dir() {
return Err("当前 MCP 工作目录不是有效的绝对 game 工作区".to_string());
return Err("当前 MCP 工作目录不是有效的项目根工作区".to_string());
}
let workspace = workspace
.canonicalize()
.map_err(|_| "当前 MCP game 工作区无法安全解析".to_string())?;
let project_root = workspace
.parent()
.ok_or_else(|| "当前 MCP game 工作区缺少项目根".to_string())?;
.map_err(|_| "当前 MCP 项目根工作区无法安全解析".to_string())?;
let (project_root, expected_workspace) =
super::codex_app_server::resolve_direct_codex_project_authority(project_root)?;
super::codex_app_server::resolve_direct_codex_project_authority(&workspace)?;
if workspace != expected_workspace {
return Err("当前 MCP 工作目录不是项目的受控 game 工作区".to_string());
return Err("当前 MCP 工作目录不是项目的受控工作区".to_string());
}
if !project_root.join(".agent/manifest.json").is_file() {
return Err("当前 MCP game 工作区不属于已初始化的陶泥儿项目".to_string());
return Err("当前 MCP 工作区不属于已初始化的陶泥儿项目".to_string());
}
enforce_project_permission_policy(&project_root, "conversation.read")?;
Ok(project_root)
@@ -1101,8 +1098,8 @@ mod tests {
}
#[test]
fn direct_tools_resolve_the_project_only_from_the_real_game_workspace() {
let temporary = crate::tests::canonical_test_tempdir("direct-tools-game-workspace-");
fn direct_tools_resolve_the_project_only_from_the_project_root_workspace() {
let temporary = crate::tests::canonical_test_tempdir("direct-tools-project-workspace-");
let root = temporary.path();
init_local_game_project_at(root, "direct-tools-project", "受控 MCP 工作区测试")
.expect("init project");
@@ -1110,10 +1107,10 @@ mod tests {
std::fs::create_dir_all(&game).expect("game workspace");
assert_eq!(
validate_direct_tools_project_root(&game).expect("resolve project from game"),
validate_direct_tools_project_root(root).expect("resolve project from root"),
root.canonicalize().expect("canonical project")
);
assert!(validate_direct_tools_project_root(root).is_err());
assert!(validate_direct_tools_project_root(&game).is_err());
}
#[test]