diff --git a/docs/README.md b/docs/README.md index 3bb4d0ea3..4ecca9b6f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -64,6 +64,7 @@ - [AGC 聊天 AI 润色与发送前提醒](./【功能说明】AGC聊天AI润色与发送前提醒-2026-09-10.md):提示词润色与发送前提醒的交互、失败与取消口径。 - [UI 工作流资源桥接与 Runtime 执行](./【技术方案】UI工作流资源桥接与Runtime执行-2026-08-24.md) - [UI 编辑器代码地图与模块职责](./technical/【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md):Rust `ui_editor` 模块、`features/ui-editor` 语义层与 `view/ui-editor` 视图层的职责划分与扩展指引。 +- [UI 编辑器 Agent 工具化重写](./technical/【技术方案】UI编辑器Agent工具化重写-2026-09-23.md):三个工具(建文档 / 跑工作流 / 出 JS)的契约、两步工作流、JSONL 检查点与模块布局。 - [UI 编辑器 Godot 容器布局](./technical/【技术方案】UI编辑器Godot容器布局模型-2026-08-18.md) - [UI 编辑器变换角点偏移编辑器](./technical/【设计】UI编辑器变换角点偏移编辑器-2026-09-03.md) - [UI 编辑器子节点显示规则](./technical/【技术方案】UI编辑器子节点显示规则-2026-08-18.md) diff --git a/docs/technical/【技术方案】UI编辑器Agent工具化重写-2026-09-23.md b/docs/technical/【技术方案】UI编辑器Agent工具化重写-2026-09-23.md new file mode 100644 index 000000000..b2d6c8c77 --- /dev/null +++ b/docs/technical/【技术方案】UI编辑器Agent工具化重写-2026-09-23.md @@ -0,0 +1,88 @@ +# UI 编辑器 Agent 工具化重写 + +更新时间:`2026-09-23` + +一句话定位:把 UI 编辑器今天由前端会话编排、由单个 `ui.workflow.run` 驱动的 Agent 链路,重写成三个各自只做一件事的工具——建文档、跑工作流、出 JS——且只有工作流工具带逐步骤崩溃恢复。 + +## 现状与问题 + +- `ui.workflow.run`(已退役)把发现页面、桥接设计图、结构识别、多树合并、组件绑定、回读、finalize 全塞进一个工具,工具参数本身就是工作流状态:模型不能只做其中一步,任何一步失败都只能整轮重来。 +- 步骤产物由前端 `useUiEditorPage.ts` 落 State 再保存,Agent 侧没有任何恢复点。 +- `merge` / `binding` 两条实验链路无现役价值,已随工具一起退役(`ui_editor/commands/merge.rs`、`binding.rs`、`ui_editor/workflow.rs` 已删除)。 + +## 工具契约 + +| 工具 | 输入 | 输出 | 恢复 | +| --- | --- | --- | --- | +| `ui-design-doc.from-images` | 1–4 张设计图,每张给 manifest `assetId` 或项目内相对路径 | 新建文档的 `assetId` 与 `relativePath` | 无状态 | +| `ui-design-doc.run-workflow` | 文档 `assetId` | 各步骤摘要与文档新 `revision` | 逐步骤 JSONL 检查点 | +| `ui-design-doc.into-js` | 文档 `assetId` | `ui/generated--.js` 路径与导出树 | 无状态 | + +工具名用 `<域>.<动作>` 形式,域内动作保留连字符(`from-images`、`run-workflow`、`into-js`);调用这些工具时项目根目录仍由 Runtime 注入,模型不得传入宿主路径。 + +### 建文档:`ui-design-doc.from-images` + +- 文档内设计图 id 直接采用该图在 manifest 里的 `assetId`;输入给相对路径时先登记成资源再用它的 `assetId`,不额外发明文档内身份。 +- 文档文件名沿用 `ui/UI 设计 N.json` 取号,不登记半成品命名(旧 `ui/ui-workflow-.json` 口径废弃)。 +- 每次调用都新建一份文档并登记:不做「原型 → 已存在文档」的幂等查找,原 `ensure_ui_design_resource_for_prototype` 的复用分支随之删除。 +- 建项与登记在项目写锁内完成;写盘失败要回滚已登记的 manifest 条目,不留半成品。 + +### 工作流:`ui-design-doc.run-workflow` + +只做三步,全部在 Rust 内完成,结果不回传前端编排: + +| 步骤 | 实现 | 产物 | +| --- | --- | --- | +| `recognize` | `recognize_ui_impl_with_provider` | `ui_trees`(每棵树的 `src_ui_design` 指向文档内设计图) | +| `separate` | `separate_ui_impl` | 切分图落盘 → 登记 asset → 转 `SpriteAsset` → 写入 State → 回填 `target_graphic`、清 `component_status`、写 `NeedReview` | +| `write-back` | `save_ui_design_state_at` | 文档新 `revision` | + +不再有合并、组件绑定与页面级 profile/finalize 阶段;`recognize` 之前不做任何前置发现。 + +## 崩溃恢复 + +检查点是文档旁一条追加式 JSONL 日志,方案与被否方案见 [ADR:UI 工作流检查点用追加式 JSONL 日志](../adr/【ADR】UI工作流检查点用追加式JSONL日志-2026-09-23.md)。 + +- 位置:`ui/.<文档文件名去扩展名>-workflow.jsonl`,与文档同级,不进 manifest、不推进项目 revision。 +- 行格式:`run`(原始 State 快照)、`recognize`(DTO)、`separate`(DTO)、`write-back`(新 revision);行内另带 `at` 时间戳。 +- 判据只有一条:「本步有没有对应的行」。每行必须一次性原子追加,崩溃留下的半行一律视为该步未完成。 +- 轮次:一轮以 `run` 行开头,以该轮第一行 `write-back` 结束;恢复只针对最后一个没有 `write-back` 的轮次。 +- 切分 op 内部的细粒度恢复仍由 `SeparationState` 承担(`ui-editor-separation-state.v2` sidecar),日志只记录工作流层面的步骤完成,不复制它的进度。 + +## 模块布局 + +### Rust + +```text +src/ui_editor/design_doc/ +├─ mod.rs 三个工具的对外入口与入参校验 +├─ creation.rs from-images:登记图片、建文档、manifest 注册、命名取号 +├─ checkpoint.rs JSONL 追加、读取、轮次判定 +├─ run_workflow.rs recognize → separate → write-back 编排与恢复 +└─ into_js.rs 复用 persistence 的代码生成 +src/agent/runtime_tools/ui_design_doc.rs 工具参数解析与 Runtime 侧调用 +``` + +每个文件只承担一件事;`checkpoint.rs` 不感知切分,`creation.rs` 不感知识别。 + +### 提示词目录模块 + +工具描述与参数文案一律进 `src-tauri/prompts/runtime/`,不在 Rust 里硬编码面向模型的中文长文案: + +- 新增文本目录 `texts/ui-design-doc.json`,在 `manifest.json` 的 `textCatalogs` 登记为 `uiDesignDoc`。 +- 键名规则 `<工具名>.<字段>`,工具名用下划线形式:`from_images.description`、`run_workflow.parameters.designDocAssetId` 等;Rust 侧用 `prompt_text!("uiDesignDoc.from_images.description")` 引用。 +- 构建期 `build_support/runtime_prompt_bundle.rs` 会校验目录已登记、key 非空、bundle 内没有未登记的 `.md`/`.json`,因此新增文件必须同步 `manifest.json`。 + +## 落地顺序 + +1. 清理 legacy(已完成:`ui.workflow.run`、`merge`、`binding` 与前端合并调用)。 +2. 术语与 ADR(已完成:`CONTEXT.md` 四个词条、检查点 ADR)。 +3. 本文档。 +4. 提示词目录模块 + 两个无状态工具(`from-images`、`into-js`)。 +5. `run-workflow` 与 JSONL 检查点。 +6. 前端收口:删 `uiDesignResourceBridge` 的 `ui-workflow.*` 优先级与 `project-development` 的自动打开分支。 + +## 关联文档 + +- [UI 编辑器代码地图与模块职责](./【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md) +- [UI 编辑器自动切分素材工作流](./【技术方案】UI编辑器自动切分素材工作流-2026-09-08.md) diff --git a/docs/technical/【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md b/docs/technical/【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md index 4b56b3629..f1fa67d6b 100644 --- a/docs/technical/【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md +++ b/docs/technical/【技术方案】UI编辑器代码地图与模块职责-2026-09-23.md @@ -11,12 +11,12 @@ view/ui-editor (页面/组件) └─ useUiEditorSession ← features/ui-editor (语义 + adapter) ├─ useUiEditorState / stateTransition / nodeTransformGeometry ├─ uiDesignStateStore → Tauri command - └─ invoke: recognize_ui / merge_ui / ... - └─ src-tauri/src/ui_editor (权威 State、校验、持久化、工作流) + └─ invoke: recognize_ui / separate_ui / ... + └─ src-tauri/src/ui_editor (权威 State、校验、持久化、切分) ``` - 唯一事实来源是项目内的 `ui_design` JSON 文档(含 `revision`),前端 State 只是它的编辑副本。 -- 所有跨进程类型由 Rust 经 `ts_rs` 生成到 `features/ui-editor/types/`(当前 56 个文件),前端不得手改。 +- 所有跨进程类型由 Rust 经 `ts_rs` 生成到 `features/ui-editor/types/`(当前 53 个文件),前端不得手改。 ## Rust 侧:`src-tauri/src/ui_editor` @@ -29,11 +29,10 @@ view/ui-editor (页面/组件) | `persistence.rs` | 文档读写、`revision` 乐观并发保存、领域校验(重复 ID、树/资源引用、组件状态)、代码生成写盘 | | `resource_bridge.rs` | 原型图 → `ui_design` 资源的桥接建项(持项目写锁,装 revision 0,仅首个设计图) | | `html_renderer/` | 由 State 生成 HTML 片段与 JS(maud + 布局/组件 CSS 映射),供预览与 `ui/generated-*.js` | -| `commands/` | LLM 工具链:`recognition`(结构识别)、`binding`(组件绑定)、`merge`(多树合并)、`separation/`(自动切分素材)、`utils.rs`(LLM 请求、重试、`required_tool_arguments`) | -| `workflow.rs` | 游戏页级工作流:发现 `game/ui-pages.json`、准备/识别/装状态/落阶段(`reference-ready → completed`)、`@genarrative-ui-page` 标记与 receipt 校验、生成最终路由 | +| `commands/` | LLM 工具链:`recognition`(结构识别)、`separation/`(自动切分素材)、`utils.rs`(LLM 请求、重试、`required_tool_arguments`) | | `commands/separation/` | 切分批处理、截图/预切、sidecar 恢复(inspect / finalize / discard)、patch 回写 | -关键命令(`main.rs` 注册):`load_ui_design_state`、`save_ui_design_state`、`generate_ui_design_code`、`ensure_ui_design_resource_for_prototype`、`recognize_ui`、`bind_components`、`merge_ui`、`separate_ui`、`inspect_separation_recovery`、`finalize_separation`、`discard_separation_recovery`。 +关键命令(`main.rs` 注册):`load_ui_design_state`、`save_ui_design_state`、`generate_ui_design_code`、`ensure_ui_design_resource_for_prototype`、`recognize_ui`、`separate_ui`、`inspect_separation_recovery`、`finalize_separation`、`discard_separation_recovery`。 保存语义(`save_ui_design_state_at`):`Saved` / `Unchanged` / `Conflict`(返回当前快照)三态;先 `validate_state` 再持锁重读比对 `expected_revision`,成功后推进项目 revision。代码生成只接受已保存的 revision,产物路径为 `ui/generated--.js`。 @@ -44,7 +43,7 @@ view/ui-editor (页面/组件) - `nodeTransformGeometry.ts`:State 级节点几何(页面矩形、父矩形、resize 手柄反演),预览/Inspector 共用。 - `stateInvariants.ts`:保存前不变量 projection,给视图稳定的中文失败信息;Rust 仍是权威校验。 - `uiDesignStateStore.ts`:`IUiDesignStateStore`(`load`/`save`/`generateCode`)+ Tauri 实现 + 内存替身。 -- 结果应用 seam:`recognition.ts`、`merge.ts`、`separationStatus.ts`(问题节点 → `NeedReview`)。 +- 结果应用 seam:`recognition.ts`、`separationStatus.ts`(问题节点 → `NeedReview`)。 - 概览 projection:`stageStatusOverview.ts`、`separationOverview.ts`。 - 前置校验:`requisites.ts` 在发起 LLM 操作前检查必需资源与结果完整性。 - 适配器:`importAdapter.ts`(图片解码、批量导入、字体准备)、`uiDesignResourceBridge.ts`(原型桥接)、`useUiEditorFontFaces.ts`(私有字体族加载)、`spriteBorder.ts`。 @@ -55,7 +54,7 @@ view/ui-editor (页面/组件) - `useUiEditorPage.ts`:`useUiEditorSession` 是视图与 adapter 的唯一协调边界,产出 `input` / `canvas` / `inspector` / `workflow` / `dialogs` / `save` 六个小 projection;视图不接收完整 controller。 - `index.tsx`:页面骨架(输入侧栏、预览、Inspector、工具栏、保存/生成结果弹窗、键盘快捷键绑定),由 `view/project-development` 挂载。 - `model.ts`:两步工作流(识别界面结构 / 自动切分素材)、导入种类、操作失败文案。 -- `operationLifecycle.ts`:suggestion/recognition/merge/separation 共用的异步操作 adapter。 +- `operationLifecycle.ts`:recognition/separation 共用的异步操作 adapter。 - `components/`:`InputSidebar`、`UiTreePanel`、`Inspector/*`(Transform、Components Text/Image、SpriteBorder)、`preview/*`(`PreviewWorkspace`、`UiTreeRenderer`、组件视图、排他子节点 tab、缩放/平移/拖拽手势)、工作流与结果弹窗。界面图没有独立显示名字段,列表与 Inspector 的统一显示名取 `path` basename(`view/project-development/resourceAssetDisplayName.ts`)。 - 已退役的 render mode 由会话级开关 `showFrame` / `showOriginImage` / `showComponent` 取代。