diff --git a/docs/technical/【技术方案】UI编辑器自动分离工作流-2026-09-08.md b/docs/technical/【技术方案】UI编辑器自动分离工作流-2026-09-08.md new file mode 100644 index 000000000..c21e40e68 --- /dev/null +++ b/docs/technical/【技术方案】UI编辑器自动分离工作流-2026-09-08.md @@ -0,0 +1,75 @@ +# UI 编辑器自动分离工作流 + +更新时间:`2026-09-08` + +## 目标 + +将 UI 编辑器现有“用户先提供独立图片/图标,再执行组件绑定”的入口替换为自动分离:结构识别阶段直接返回可渲染组件草稿,分离阶段按整页叶节点批次调用图片编辑模型,再由视觉模型确认处理图中的区域与目标节点。 + +## 识别结果 + +- `recognize` 返回完整 `Node.components` 草稿,不再要求用户先导入独立素材。 +- `components` 为空表示纯节点。 +- `ImageComponent.target_graphic = None` 表示图片组件等待分离结果回填;它不是“明确没有图片”。 +- 当前约束:需要分离的节点最多包含一个 `ImageComponent`,回填暂使用该节点的第一个图片组件。 +- 组件容器“一种组件类型最多一个”的正式重构列为 TODO;当前 `Vec` 仅按上述约束使用。 +- 组件草稿直接保存在正式 UI Node 中;临时 separation tree 不复制组件。 + +## Separation tree + +- recognition 完成后由 UI tree 构造临时 separation tree。 +- 纯节点、纯 Text 节点和不需要切图的节点在构造时过滤;被过滤节点的可处理 children 向上透传。 +- separation tree 只保留真实待处理节点。 +- 一个 batch 是整页当前所有互不重叠叶节点。 +- 一个 batch 的最小处理单元是:一次 image-edit + 一次 visual binding。 +- batch 成功后从 pending tree 移除对应叶节点,并把结果放入 bound 容器;失败节点移入 problematic 容器,流程继续消费剩余树。 +- 不额外维护节点状态枚举;节点是否仍在 pending tree、`rework_count` 和 problematic 容器共同表达状态。 + +## 图片编辑与视觉绑定 + +- image-edit 使用源 UI design 图片及由 Rust 生成的绿色标记/紫色重建输入。 +- 请求尺寸始终使用源 UI design 尺寸;Raw GPT Image 2 API 保证返回相同尺寸,客户端不额外做尺寸拒绝检查。 +- 视觉 binding 输入源图与处理图,必须为当前 batch 每个节点恰好返回一次 `Ok` 或 `NeedRework`。 +- `Ok` 返回 `NodeId + BindingArea`;Rust 仅校验 NodeId、区域边界和非零尺寸,不检查与原节点框的偏差,也不要求区域不重叠。 +- `NeedRework` 携带短问题描述。结构化工具调用失败时使用可复用 repair harness,把错误反馈给模型并额外请求一次;image-edit 不使用该 harness。 +- 达到模块级重做常量后,节点移入 problematic;不中断整条工作流,最终统一通知用户。 +- 父节点背景重建由 image-edit 模型完成,不由 Rust 硬编码重建算法完成。 + +## 临时 sidecar + +- separation 状态不写入 UI JSON,也不进入 manifest。 +- sidecar 目录按 UI manifest `asset_id` 生成,复用 `generated_file_stem(asset_id)` 的安全字符替换和 SHA-256 摘要规则,位于项目 `ui/` 下。 +- 目录只保存一份当前 separation state,而不是每 batch 一个状态文件。 +- state 文件只保留 `schema_version`、pending tree、bound 结果和 problematic 节点,不重复保存 `projectId / assetId / uiStateRevision`。 +- sidecar 只在 separation 未完成期间存在;完成后删除 state JSON。 +- 当前只持久化已经完成的 batch;正在执行 batch 的恢复语义列 TODO。 +- 临时图片可跨重启保留。raw image-edit 返回图、绿色/紫色标记图、处理图和 cut 图片当前都保留用于 debug;理论上只应在内存中,清理/归档策略列 TODO。 + +## bound 与 problematic + +- bound 结果仅保存 `NodeId + cut_image_path`,不保存 `BindingArea` 或 component kind。 +- problematic 记录原始 NodeId、问题描述和 `rework_count`;原始 UI Node 保留不变。 +- `SeparationDTO` 不返回计数字段,只返回 `bound_nodes` 与 `problematic_nodes`。 +- separation Rust 流程不自动登记项目级 SpriteAsset。 +- 前端调用方消费 `SeparationDTO.bound_nodes`,复制/登记 cut 图片为项目级 SpriteAsset,再回填对应 Node 的第一个 Image component。 +- 每次重做产生新的 SpriteAssetId,不假设 NodeId 到 SpriteAssetId 的稳定映射。 +- sidecar 中的图片保留,正式 SpriteAsset 的最终清理策略列 TODO。 + +## 重启与 Raw GPT Image 2 + +- 已保存的 separation state 是跨重启继续工作的最小单位;重启后从上一个已保存 batch 的状态继续。 +- 当前执行中的 batch 是否持久化、以及如何避免 image-edit 成功后在 patch 前崩溃导致重复调用,列为 TODO。 +- Raw endpoint 每次 HTTP 调用都是一次新操作;客户端不保存或复用 raw operation ID,不实现第二套本地幂等账本。 +- 后端 raw operation 的持久状态与扣费后崩溃恢复窗口,遵循 Raw GPT Image 2 方案中的独立 TODO。 + +## TODO + +- `Vec` 重构为一种组件类型最多一个的容器。 +- 当前第一个 Image component 回填规则的正式替代方案。 +- 正在执行 batch 的持久化和恢复。 +- 前端复制、登记 SpriteAsset、回填 State 的精确 IPC/提交合同。 +- 临时图片清理/归档策略。 +- 手动抠图能力。 +- problematic 对更高层 workflow 完成门禁的最终定义。 +- separation workflow 与 manifest/stage 的接入。 +- Raw GPT Image 2 后端 raw operation 持久状态及恢复 worker。