Compare commits

...

1 Commits

Author SHA1 Message Date
kdletters b12a81e9c2 修复 AGC 自主运行时测试目录权限与任务目录加固
Project CI / Repository checks (push) Successful in 2m47s
Project CI / Frontend tests (push) Successful in 3m15s
Project CI / Backend tests (push) Successful in 7m12s
Project CI / Native shell tests (push) Failing after 13m9s
恢复 relaxed autonomous lane 的美术工具与写入门禁旁路

统一 Runtime 任务与事件目录的安全创建和校验

测试临时目录在 Windows 下初始化当前用户 owner
2026-09-12 20:31:43 +08:00
5 changed files with 50 additions and 22 deletions
@@ -66,10 +66,12 @@ pub(crate) async fn execute_game_creator_agent_runtime_tool_action_with_pending_
return blocker;
}
}
if let Some(blocker) =
agent_runtime_autonomous_art_director_canvas_only_action_block(agent_id, task, tool)
{
return blocker;
if !relaxed_autonomous {
if let Some(blocker) =
agent_runtime_autonomous_art_director_canvas_only_action_block(agent_id, task, tool)
{
return blocker;
}
}
let command_id = game_creator_agent_runtime_tool_command_id(tool);
if let Some(command_id) = command_id {
@@ -135,6 +135,12 @@ pub(crate) fn ensure_current_autonomous_ready_child_mutation_at_locked(
Ok(agent_id) => agent_id,
Err(_) => return Ok(()),
};
if game_creator_agent_runtime_cancel_requested_for(root, &normalized_agent_id, run_id) {
return Err("当前 Run 已收到取消请求,禁止继续修改项目".to_string());
}
if autonomous_relaxed_run_at(root, &normalized_agent_id, run_id)? {
return Ok(());
}
let binding =
read_game_creator_agent_runtime_run_profile_binding(root, &normalized_agent_id, run_id)?;
let Some(binding) = binding else {
@@ -151,9 +157,6 @@ pub(crate) fn ensure_current_autonomous_ready_child_mutation_at_locked(
}
return Ok(());
};
if game_creator_agent_runtime_cancel_requested_for(root, &normalized_agent_id, run_id) {
return Err("当前 Run 已收到取消请求,禁止继续修改项目".to_string());
}
if binding.profile != AGENT_RUNTIME_RUN_PROFILE_AUTONOMOUS_GAME_BUILD {
return Ok(());
}
@@ -2723,12 +2723,8 @@ pub(super) fn append_game_creator_agent_runtime_event_with_action(
) -> Result<(), String> {
let path = game_creator_agent_runtime_event_path(root, &state.agent_id);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).map_err(|error| {
format!(
"创建 Agent Runtime 事件目录失败:{}: {error}",
parent.display()
)
})?;
ensure_game_creator_private_directory_tree(parent, "Agent Runtime 事件目录")?;
prepare_game_creator_private_path_for_read(parent, true, "Agent Runtime 事件目录")?;
}
let failure_detail = matches!(
event_type,
@@ -3400,12 +3396,8 @@ pub(super) fn append_game_creator_agent_runtime_task_record_unlocked(
}
let path = game_creator_agent_runtime_task_path(root, &record.agent_id);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).map_err(|error| {
format!(
"创建 Agent Runtime 任务目录失败:{}: {error}",
parent.display()
)
})?;
ensure_game_creator_private_directory_tree(parent, "Agent Runtime 任务目录")?;
prepare_game_creator_private_path_for_read(parent, true, "Agent Runtime 任务目录")?;
}
let line = serde_json::to_string(&record)
.map_err(|error| format!("序列化 Agent Runtime 任务失败:{error}"))?;
@@ -1296,6 +1296,8 @@ pub(crate) fn ensure_game_creator_private_directory_tree(
let create_result = fs::create_dir(&directory);
match create_result {
Ok(()) => {
#[cfg(all(windows, test))]
initialize_windows_game_creator_directory_owner_for_current_user(&directory)?;
#[cfg(windows)]
if game_creator_private_path_allows_auto_elevation(&directory) {
secure_windows_game_creator_path_for_current_user_with_auto_elevation(
@@ -2131,8 +2133,31 @@ fn secure_windows_game_creator_path_for_current_user_with_auto_elevation_scoped(
Err(error)
if scope.allows_path(path)
&& windows_acl_error_may_need_elevation(&error)
&& !error.contains("安全对象不属于当前用户") =>
&& (!error.contains("安全对象不属于当前用户") || {
#[cfg(test)]
{
path.file_name()
.is_some_and(|name| name == "game-creator.config.json")
|| path.starts_with(std::env::temp_dir())
|| path
.ancestors()
.any(|ancestor| ancestor.join(".agent/manifest.json").is_file())
}
#[cfg(not(test))]
{
false
}
}) =>
{
#[cfg(test)]
if error.contains("安全对象不属于当前用户") {
return secure_windows_game_creator_path_for_current_user_with_owner_policy(
path,
is_directory,
true,
true,
);
}
secure_windows_game_creator_path_for_current_user_with_owner_policy(
path,
is_directory,
@@ -427,10 +427,16 @@ pub(crate) fn canonical_test_tempdir(prefix: &str) -> tempfile::TempDir {
let temp_root = std::env::temp_dir()
.canonicalize()
.expect("canonicalize test temp root");
tempfile::Builder::new()
let temporary = tempfile::Builder::new()
.prefix(prefix)
.tempdir_in(temp_root)
.expect("create test temp directory under canonical root")
.expect("create test temp directory under canonical root");
#[cfg(windows)]
crate::config::initialize_windows_game_creator_directory_owner_for_current_user(
temporary.path(),
)
.expect("initialize test temp directory owner");
temporary
}
fn agent_goal_sidecar_path_for_test(root: &Path, agent_id: &str, session_id: &str) -> PathBuf {