文档登记失败时回滚本次顺带登记的设计图

ui_editor/agent_tools/creation.rs 登记文档资源失败时先摘掉 prepare_design_images 登记进来的图片条目,避免 manifest 留下没有文档引用的孤儿设计图
把「按 id 摘条目」抽成 drop_manifest_assets,rollback_created_document 复用同一实现
This commit is contained in:
2026-09-24 15:58:24 +08:00
parent 588768bff0
commit ac870fd41a
@@ -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, &[], &registered_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(