diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/agent_tools/creation.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/agent_tools/creation.rs index 6b2dacc91..b4095a084 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/agent_tools/creation.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/agent_tools/creation.rs @@ -91,7 +91,13 @@ pub(crate) fn create_ui_design_doc_from_images( Ok(asset) => asset, Err(error) => { let _ = fs::remove_file(&absolute_path); - return Err(error); + // 文档没登记成功时,本次顺带登记的设计图也不该留在 manifest 里。 + return match drop_manifest_assets(root, &[], ®istered_image_ids) { + Ok(()) => Err(error), + Err(rollback_error) => Err(format!( + "UI 设计文档登记失败:{error};reconciliation-required: 回滚未完成:{rollback_error}" + )), + }; } }; if let Err(error) = @@ -279,14 +285,23 @@ fn rollback_created_document( registered_image_ids: &[String], absolute_path: &Path, ) -> Result<(), String> { - let mut manifest = read_existing_manifest_for_project(root)?; - manifest - .assets - .retain(|entry| entry.id != asset_id && !registered_image_ids.contains(&entry.id)); - write_manifest(&root.join(".agent/manifest.json"), &manifest)?; + drop_manifest_assets(root, &[asset_id], registered_image_ids)?; fs::remove_file(absolute_path).map_err(|error| format!("删除未完成 UI 设计资源失败:{error}")) } +/// 把本次新建或新登记、但已判定失败的资源条目从 manifest 里摘掉。 +fn drop_manifest_assets( + root: &Path, + asset_ids: &[&str], + registered_image_ids: &[String], +) -> Result<(), String> { + let mut manifest = read_existing_manifest_for_project(root)?; + manifest.assets.retain(|entry| { + !asset_ids.contains(&entry.id.as_str()) && !registered_image_ids.contains(&entry.id) + }); + write_manifest(&root.join(".agent/manifest.json"), &manifest) +} + /// UI 设计文档的确定性命名:从已登记文档数 + 1 起找第一个既未被占用、 /// 也未登记进 manifest 的 `ui/UI 设计 N.json`,不覆盖任何既有文件。 pub(crate) fn next_ui_design_path(