Initial TrueGrowth source import
This commit is contained in:
@@ -0,0 +1,733 @@
|
||||
## Context
|
||||
|
||||
当前生图反馈主要依赖 `WorkZone`:
|
||||
|
||||
- 提交时在画布中插入固定尺寸的卡片
|
||||
- 卡片内部展示标题、状态、步骤列表与删除/隐藏按钮
|
||||
- 自动插入完成后再删除卡片
|
||||
|
||||
这种设计适合表达工作流存在,但不适合表达“图片对象即将落入画布”的过程。问题主要有:
|
||||
|
||||
- 过程对象抢占画布注意力,打断创作空间
|
||||
- 固定卡片高度在单图场景下留白过多
|
||||
- 生图反馈的核心不是步骤明细,而是“会落在哪、会长成什么比例、现在到了哪个阶段”
|
||||
- 当前状态同步分散在 `AIInputBar`、`useWorkflowSubmission`、`useTaskWorkflowSync`、`useAutoInsertToCanvas` 中,后续继续在 `WorkZone` 上叠交互会进一步放大复杂度
|
||||
|
||||
## Goals
|
||||
|
||||
- 让生图过程在画布中表现为“对象正在诞生”,而非“任务卡片正在执行”
|
||||
- 优先利用提交时即可获得的几何信息,建立可信的一致性反馈
|
||||
- 在结果未返回前,通过锚点表达位置、比例与状态,而不伪装已知内容
|
||||
- 保留失败重试、详情追踪和恢复能力
|
||||
- 首版只覆盖 `image` 类型任务,不改造其他任务类型
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- 不在首版统一视频、音频、文本、流程图等其他任务反馈
|
||||
- 不在首版默认引入强品牌化的传送门或粒子特效
|
||||
- 不依赖结果侧稳定返回 `width/height` 元数据来决定首版锚点几何
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. 生图改为 `Generation Anchor`
|
||||
|
||||
生图提交后,系统在预期插入位置创建轻量锚点,而不是默认创建大面积 `WorkZone` 卡片。
|
||||
|
||||
锚点的职责只有四类:
|
||||
|
||||
- 表达“已受理”
|
||||
- 表达“预期落点”
|
||||
- 表达“预期几何外壳”
|
||||
- 表达“当前阶段 + 主动作”
|
||||
|
||||
步骤详情、历史记录、错误细节默认不在画布中展开。
|
||||
|
||||
### 2. 三档几何策略
|
||||
|
||||
#### `Frame-first`
|
||||
|
||||
若提交时已存在:
|
||||
|
||||
- `targetFrameId`
|
||||
- `targetFrameDimensions`
|
||||
|
||||
则锚点直接继承 Frame 外壳,在该容器内部完成生成、显影与结果接管。
|
||||
|
||||
#### `Size-first`
|
||||
|
||||
若不存在 Frame,但已存在明确的 `size`,则使用 `size` 作为锚点外壳的比例来源。该策略与当前插入逻辑一致,因为首版插入已经依赖 `parseSizeToPixels(size)` 进行几何推导。
|
||||
|
||||
#### `Ghost-anchor`
|
||||
|
||||
若既无 Frame 又无稳定比例信息,则仅创建轻量出生点锚点,不伪装为完整图片框。待结果返回后,再从出生点平滑 morph 为真实图片。
|
||||
|
||||
### 3. 用户态状态机
|
||||
|
||||
生图锚点统一使用以下用户态:
|
||||
|
||||
- `submitted`
|
||||
- `queued`
|
||||
- `generating`
|
||||
- `developing`
|
||||
- `inserting`
|
||||
- `completed`
|
||||
- `failed`
|
||||
|
||||
状态解释:
|
||||
|
||||
- `submitted`: 用户点击后,任务已创建,输入条需要立即确认
|
||||
- `queued`: 请求已受理但尚未进入明显执行
|
||||
- `generating`: 模型正在生成结果
|
||||
- `developing`: 结果已返回,正在准备插入或执行轻显影
|
||||
- `inserting`: 正在把真实图片插入画布并与锚点连续过渡
|
||||
- `completed`: 图片已稳定落位,锚点将短暂停留后淡出
|
||||
- `failed`: 保留失败节点,允许重试或查看详情
|
||||
|
||||
#### 用户态文案规范
|
||||
|
||||
首版默认文案应保持“对象正在诞生”的语义,而不是暴露底层工作流术语:
|
||||
|
||||
- `submitted`: 已提交,等待执行
|
||||
- `queued`: 请求已受理,等待执行
|
||||
- `generating`: 图片正在生成,请稍候
|
||||
- `developing`: 结果已返回,正在准备显影
|
||||
- `inserting`: 正在放入画布
|
||||
- `completed`: 图片已稳定落位
|
||||
- `failed`: 生成失败,请重试
|
||||
|
||||
允许在特定交互瞬间使用更细的提示文案,例如:
|
||||
|
||||
- 主线程回退时:请求已受理,正在转入本地执行
|
||||
- 用户点击重试时:正在重新触发,请稍候
|
||||
|
||||
但这些文案必须仍然映射回上述统一用户态,不允许新增平行状态名。
|
||||
|
||||
### 4. 详情层收敛
|
||||
|
||||
锚点默认只展示:
|
||||
|
||||
- 当前阶段文案
|
||||
- 轻进度
|
||||
- 一个主动作
|
||||
|
||||
详细步骤、错误明细、历史版本应进入任务详情层,而不是在画布中展开完整 `WorkZone`。
|
||||
|
||||
#### 职责边界
|
||||
|
||||
`Generation Anchor` 负责:
|
||||
|
||||
- 受理确认
|
||||
- 预期落点
|
||||
- 预期几何外壳
|
||||
- 当前阶段
|
||||
- 轻进度
|
||||
- 当前上下文中的恢复动作
|
||||
|
||||
任务详情层负责:
|
||||
|
||||
- 完整步骤列表
|
||||
- 错误详情与调试信息
|
||||
- 历史记录与重试历史
|
||||
- 批量结果管理
|
||||
- 非画布主路径的任务追踪
|
||||
|
||||
画布中的锚点不应默认展开完整步骤列表,也不应承载需要持续滚动阅读的信息。
|
||||
|
||||
### 5. 渐进迁移
|
||||
|
||||
首版仅对 `image` 类型启用 `Generation Anchor`。
|
||||
|
||||
- `image`:默认启用 Anchor
|
||||
- 其他类型:继续使用现有 `WorkZone` 或现有任务反馈
|
||||
|
||||
这样能避免一次性改造所有任务语义,也能降低对现有任务同步链路的影响。
|
||||
|
||||
## State Mapping
|
||||
|
||||
首版建议由一个统一的 view model 负责把现有信号映射成锚点状态:
|
||||
|
||||
- 提交态信号:
|
||||
- `expectedInsertPosition`
|
||||
- `targetFrameId`
|
||||
- `targetFrameDimensions`
|
||||
- `size`
|
||||
- 任务执行信号:
|
||||
- `Task.status`
|
||||
- `Task.progress`
|
||||
- `Task.executionPhase`
|
||||
- 后处理信号:
|
||||
- `workflowCompletionService`
|
||||
- 自动插入开始/完成事件
|
||||
|
||||
映射规则示例:
|
||||
|
||||
- 任务创建后但未进入稳定进度更新:`submitted`
|
||||
- `TaskExecutionPhase.SUBMITTING`: `queued`
|
||||
- `Task.progress` 持续推进:`generating`
|
||||
- 任务已成功但后处理未完成:`developing`
|
||||
- 图片正在落入画布:`inserting`
|
||||
- 后处理完成并已插入:`completed`
|
||||
- 任意执行或插入失败:`failed`
|
||||
|
||||
## UI Model
|
||||
|
||||
建议新增面向 UI 的锚点模型:
|
||||
|
||||
- `anchorType`: `frame | ratio | ghost | stack`
|
||||
- `phase`
|
||||
- `position`
|
||||
- `dimensions`
|
||||
- `progress`
|
||||
- `title`
|
||||
- `subtitle`
|
||||
- `primaryAction`
|
||||
- `secondaryAction`
|
||||
- `transitionMode`
|
||||
|
||||
该模型只表达画布中锚点需要展示什么,不直接持有完整工作流对象。
|
||||
|
||||
## Integration Notes
|
||||
|
||||
- 输入条负责第一层反馈:点击后立即显示“已提交”
|
||||
- 画布锚点负责第二层反馈:表达位置、比例、阶段
|
||||
- 任务详情层负责第三层反馈:步骤明细、失败原因、历史记录
|
||||
- 现有 `WorkZone` 首版可作为非生图路径保留,不与生图锚点混用
|
||||
|
||||
## Architecture Alignment
|
||||
|
||||
### Runtime Topology
|
||||
|
||||
首版推荐的运行时拓扑如下:
|
||||
|
||||
1. `AIInputBar`
|
||||
- 负责生图提交入口
|
||||
- 产出提交期几何上下文
|
||||
- 调用 `ImageGenerationAnchorTransforms.insertAnchor`
|
||||
- 触发输入条“已提交”反馈
|
||||
|
||||
2. `with-image-generation-anchor`
|
||||
- 负责 `generation-anchor` 元素的画布承载与渲染
|
||||
- 管理 anchor 元素的插入、更新、删除与命中
|
||||
|
||||
3. `useImageGenerationAnchorController`
|
||||
- 负责把原始信号映射为 UI model
|
||||
- 不直接写画布,只输出“应该显示什么”
|
||||
|
||||
4. `useImageGenerationAnchorSync`
|
||||
- 负责监听任务与后处理事件
|
||||
- 负责按 `taskId / workflowId` 找到 anchor
|
||||
- 负责把 controller 产出的状态回写到画布元素
|
||||
|
||||
5. `useAutoInsertToCanvas`
|
||||
- 负责真实图片落图
|
||||
- 负责驱动 `developing -> inserting -> completed`
|
||||
- 负责在插入完成后让 anchor 收口
|
||||
|
||||
6. `WorkZone`
|
||||
- 生图首版不再作为默认反馈
|
||||
- 仅保留给非生图任务与旧路径兼容
|
||||
|
||||
### Ownership Matrix
|
||||
|
||||
#### `AIInputBar`
|
||||
|
||||
拥有:
|
||||
|
||||
- `generationType === 'image'` 分流决策
|
||||
- `expectedInsertPosition`
|
||||
- `targetFrameId`
|
||||
- `targetFrameDimensions`
|
||||
- `requestedSize`
|
||||
- `currentImageAnchorIdRef`
|
||||
- 输入条首段反馈
|
||||
|
||||
不拥有:
|
||||
|
||||
- anchor 运行中阶段推进
|
||||
- 刷新恢复
|
||||
- 自动插入后的收口
|
||||
- 全局任务同步
|
||||
|
||||
#### `Drawnix`
|
||||
|
||||
拥有:
|
||||
|
||||
- 注册 `with-image-generation-anchor`
|
||||
- 挂载 `useImageGenerationAnchorSync`
|
||||
- 在 board ready / task storage ready 后进行恢复协调
|
||||
|
||||
不拥有:
|
||||
|
||||
- 提交期几何推导
|
||||
- 真实插入行为本身
|
||||
|
||||
#### `useImageGenerationAnchorSync`
|
||||
|
||||
拥有:
|
||||
|
||||
- 从 `taskQueueService`、`workflowCompletionService`、插入事件读取状态
|
||||
- 根据 `taskId / workflowId` 查找 anchor
|
||||
- 调用 transforms 更新 anchor 元素
|
||||
|
||||
不拥有:
|
||||
|
||||
- 具体 JSX 渲染
|
||||
- 业务提交入口
|
||||
|
||||
#### `useAutoInsertToCanvas`
|
||||
|
||||
拥有:
|
||||
|
||||
- 结果 URL 到画布对象的真实插入
|
||||
- 插入前后的 anchor 状态推进
|
||||
- 插入失败到失败态的回写
|
||||
|
||||
不拥有:
|
||||
|
||||
- anchor 初次创建
|
||||
- 输入条即时反馈
|
||||
|
||||
### Data Contracts
|
||||
|
||||
#### Submission Context
|
||||
|
||||
建议定义一个单独的提交期上下文对象,避免多个模块重复各自取值:
|
||||
|
||||
- `workflowId`
|
||||
- `taskIds`
|
||||
- `expectedInsertPosition`
|
||||
- `targetFrameId`
|
||||
- `targetFrameDimensions`
|
||||
- `requestedSize`
|
||||
- `prompt`
|
||||
- `count`
|
||||
- `createdAt`
|
||||
|
||||
来源:
|
||||
|
||||
- `AIInputBar`
|
||||
|
||||
用途:
|
||||
|
||||
- 创建 anchor
|
||||
- 恢复定位
|
||||
- 插入时兜底寻找几何上下文
|
||||
|
||||
#### Anchor View Model
|
||||
|
||||
建议定义一个稳定的 UI model,避免 JSX 直接依赖任务/工作流对象:
|
||||
|
||||
- `anchorType`
|
||||
- `phase`
|
||||
- `progressMode: 'indeterminate' | 'percent' | 'steps'`
|
||||
- `progressValue`
|
||||
- `title`
|
||||
- `subtitle`
|
||||
- `showFrameShell`
|
||||
- `showRatioShell`
|
||||
- `showGhostPulse`
|
||||
- `canRetry`
|
||||
- `canOpenDetails`
|
||||
- `transitionMode: 'fade' | 'morph' | 'frame-fill' | 'stack-expand'`
|
||||
|
||||
### Runtime Sequence
|
||||
|
||||
#### 提交阶段
|
||||
|
||||
1. `AIInputBar` 解析生图请求
|
||||
2. 推导 `expectedInsertPosition / Frame / size`
|
||||
3. 构造 submission context
|
||||
4. 创建 `generation-anchor`
|
||||
5. 提交任务到工作流 / 任务队列
|
||||
|
||||
#### 执行阶段
|
||||
|
||||
1. `taskQueueService` 发出 `taskCreated / taskUpdated`
|
||||
2. `useImageGenerationAnchorSync` 读取任务状态
|
||||
3. `useImageGenerationAnchorController` 把 `Task.status / progress / executionPhase` 映射为 `submitted / queued / generating`
|
||||
4. transforms 更新 anchor 元素
|
||||
|
||||
#### 后处理阶段
|
||||
|
||||
1. 任务成功返回结果 URL
|
||||
2. `workflowCompletionService` 发出后处理开始
|
||||
3. anchor 切到 `developing`
|
||||
4. `useAutoInsertToCanvas` 开始插入
|
||||
5. anchor 切到 `inserting`
|
||||
6. 图片落图成功后,anchor 切到 `completed` 并收口
|
||||
|
||||
#### 失败阶段
|
||||
|
||||
1. 任务失败或插入失败
|
||||
2. `useImageGenerationAnchorSync` / `useAutoInsertToCanvas` 写回失败态
|
||||
3. anchor 保留失败节点
|
||||
4. 用户可原位重试或打开详情
|
||||
|
||||
## Implementation Breakdown
|
||||
|
||||
### 1. 元素层拆分
|
||||
|
||||
首版不建议在现有 `workzone` 元素上继续追加“生图锚点”模式,而是新增独立的画布元素类型:
|
||||
|
||||
- `generation-anchor`
|
||||
|
||||
原因:
|
||||
|
||||
- `workzone` 语义是“工作流过程面板”
|
||||
- `generation-anchor` 语义是“结果出生点”
|
||||
- 两者在几何、交互密度、恢复逻辑和删除时机上都不同
|
||||
- 生图首版需要与非生图路径并行存在,独立元素类型更利于渐进迁移
|
||||
|
||||
插件实现建议优先参考现有的轻元素模式,而不是继续沿用 `with-workzone` 的重型编排模式:
|
||||
|
||||
- 参考 `withCard` / `CardGenerator` 的 `foreignObject + React root + generator` 范式
|
||||
- 参考 `withAudioNode` / `AudioNodeGenerator` 的“轻元素 + 实时状态渲染”模式
|
||||
- 若后续需要手动缩放,再单独增加 resize companion plugin,参考 `with-card-resize` / `with-audio-node-resize`
|
||||
|
||||
不建议参考 `withTool` 的消息桥式重型模式,因为 anchor 不是一个 iframe 工具,也不应承担任务编排职责。
|
||||
|
||||
### 2. 建议新增文件
|
||||
|
||||
#### 类型层
|
||||
|
||||
- `packages/drawnix/src/types/image-generation-anchor.types.ts`
|
||||
|
||||
职责:
|
||||
|
||||
- 定义 `PlaitImageGenerationAnchor`
|
||||
- 定义 `anchorType`
|
||||
- 定义用户态 `phase`
|
||||
- 定义提交期几何上下文与主动作字段
|
||||
|
||||
建议字段:
|
||||
|
||||
- `workflowId`
|
||||
- `taskIds`
|
||||
- `anchorType: 'frame' | 'ratio' | 'ghost' | 'stack'`
|
||||
- `phase`
|
||||
- `progress`
|
||||
- `requestedSize`
|
||||
- `expectedInsertPosition`
|
||||
- `targetFrameId`
|
||||
- `targetFrameDimensions`
|
||||
- `resultUrl`
|
||||
- `error`
|
||||
- `zoom`
|
||||
|
||||
#### 渲染层
|
||||
|
||||
- `packages/drawnix/src/components/image-generation-anchor/ImageGenerationAnchorContent.tsx`
|
||||
- `packages/drawnix/src/components/image-generation-anchor/image-generation-anchor.scss`
|
||||
- `packages/drawnix/src/components/image-generation-anchor/index.ts`
|
||||
|
||||
职责:
|
||||
|
||||
- 渲染 `Frame Anchor`
|
||||
- 渲染 `Ratio Anchor`
|
||||
- 渲染 `Ghost-anchor`
|
||||
- 渲染失败态与主动作
|
||||
|
||||
约束:
|
||||
|
||||
- 只做展示,不直接 claim / resume / 查询任务状态
|
||||
- 不持有工作流恢复逻辑
|
||||
|
||||
#### 插件层
|
||||
|
||||
- `packages/drawnix/src/plugins/with-image-generation-anchor.ts`
|
||||
|
||||
职责:
|
||||
|
||||
- 注册 `generation-anchor` 元素
|
||||
- 创建 `foreignObject`
|
||||
- 管理激活态边框与点击命中
|
||||
- 提供 transforms:
|
||||
- `insertAnchor`
|
||||
- `updateAnchorState`
|
||||
- `updateGeometry`
|
||||
- `removeAnchor`
|
||||
- `getById`
|
||||
- `getAnchorByTaskId`
|
||||
- `getAnchorByWorkflowId`
|
||||
- `getAllAnchors`
|
||||
|
||||
边界约束:
|
||||
|
||||
- 插件层只提供元素能力
|
||||
- 不直接订阅 `taskQueueService`
|
||||
- 不直接处理 workflow 恢复
|
||||
- 不直接决定 anchor 何时完成或消失
|
||||
|
||||
#### 状态映射层
|
||||
|
||||
- `packages/drawnix/src/hooks/useImageGenerationAnchorController.ts`
|
||||
- `packages/drawnix/src/utils/image-generation-anchor-view-model.ts`
|
||||
|
||||
职责:
|
||||
|
||||
- 将提交期几何信号 + 任务状态 + 后处理状态映射为 anchor UI model
|
||||
- 统一决定:
|
||||
- `anchorType`
|
||||
- `phase`
|
||||
- `progress`
|
||||
- `title/subtitle`
|
||||
- `primaryAction`
|
||||
- `transitionMode`
|
||||
|
||||
关键原则:
|
||||
|
||||
- UI 不直接认 `taskQueueService`、`workflowSubmissionService` 或 `workflowCompletionService` 的原始对象
|
||||
- UI 只认 `ImageGenerationAnchorController` 产出的 anchor view model
|
||||
- controller 是 image anchor 的单一状态源
|
||||
|
||||
建议保持该层为纯映射或轻控制器,不直接操作 DOM。
|
||||
|
||||
#### 同步层
|
||||
|
||||
- `packages/drawnix/src/hooks/useImageGenerationAnchorSync.ts`
|
||||
|
||||
职责:
|
||||
|
||||
- 在 board 级别监听 `taskQueueService`
|
||||
- 在 board 级别监听后处理 / 自动插入事件
|
||||
- 在刷新恢复后重新同步 anchor 状态
|
||||
- 将更新写回 `ImageGenerationAnchorTransforms`
|
||||
|
||||
边界约束:
|
||||
|
||||
- `sync` 只负责订阅和归一化原始事件
|
||||
- `sync` 不直接做业务判断
|
||||
- `sync` 允许重复事件、乱序事件和恢复事件
|
||||
- `controller` 负责幂等推进和去重
|
||||
|
||||
该 hook 应由 `Drawnix` 持有,而不是由 `AIInputBar` 或单个 anchor 组件持有。
|
||||
|
||||
### 3. 现有文件改动范围
|
||||
|
||||
#### `AIInputBar.tsx`
|
||||
|
||||
保留职责:
|
||||
|
||||
- 判断当前是否是 `image` 类型提交
|
||||
- 计算 `expectedInsertPosition`
|
||||
- 解析 `targetFrameId / targetFrameDimensions`
|
||||
- 计算 `requestedSize`
|
||||
- 在提交时创建首个 anchor
|
||||
- 提供输入条“已提交”即时反馈
|
||||
|
||||
移出职责:
|
||||
|
||||
- 不再负责生图默认大 `WorkZone` 创建
|
||||
- 不再通过 `currentWorkZoneIdRef` 驱动生图的完整生命周期
|
||||
- 不再直接订阅 `taskQueueService.observeTaskUpdates()`
|
||||
- 不再直接订阅 `workflowCompletionService.observeCompletionEvents()`
|
||||
- 不再直接基于 image 路径写 `WorkZoneTransforms.update/remove`
|
||||
|
||||
建议新增:
|
||||
|
||||
- `currentImageAnchorIdRef`
|
||||
|
||||
并保留现有:
|
||||
|
||||
- `currentWorkZoneIdRef`
|
||||
|
||||
作为非生图路径兼容。
|
||||
|
||||
#### `useAutoInsertToCanvas.ts`
|
||||
|
||||
新增职责:
|
||||
|
||||
- 根据 `taskId` 查找 image anchor
|
||||
- 在“结果已返回但未插入”时切换到 `developing`
|
||||
- 在“开始插入”时切换到 `inserting`
|
||||
- 在“插入完成”时执行 anchor → image 的收口
|
||||
- 在失败时更新为失败节点
|
||||
|
||||
需要替换的当前耦合:
|
||||
|
||||
- 现有 `findWorkZoneForTask`
|
||||
- 现有基于 WorkZone 的 `expectedInsertPosition / targetFrameDimensions` 读取
|
||||
- 现有生图完成后直接删除 WorkZone 的逻辑
|
||||
- 现有依赖 `ai-generation-complete` 解锁输入条的生图路径
|
||||
|
||||
#### `drawnix.tsx`
|
||||
|
||||
新增职责:
|
||||
|
||||
- 注册 `with-image-generation-anchor`
|
||||
- 挂载 `useImageGenerationAnchorSync`
|
||||
|
||||
保留职责:
|
||||
|
||||
- 现有 `WorkZone` 恢复与同步先只服务非生图路径
|
||||
|
||||
建议调整:
|
||||
|
||||
- 让 `Drawnix` 成为 image anchor 的全局恢复入口
|
||||
- 不再让 `AIInputBar` 持有刷新恢复或跨任务同步逻辑
|
||||
- 现有 `restoreWorkZones`、workflow sync、task queue sync 中的 image 逻辑应迁移到 anchor sync,而不是继续直接写 WorkZone
|
||||
|
||||
#### `useWorkflowSubmission.ts`
|
||||
|
||||
建议调整:
|
||||
|
||||
- 将 image 类型从“默认 WorkZone 同步路径”中分流出来
|
||||
- 保持文本、Agent、非生图任务继续复用现有逻辑
|
||||
|
||||
说明:
|
||||
|
||||
生图首版的主要状态源更应该是:
|
||||
|
||||
- 提交期几何上下文
|
||||
- `taskQueueService`
|
||||
- 后处理 / 插入事件
|
||||
|
||||
而不是完整 `workflow` 步骤列表。
|
||||
|
||||
需要重点清理的耦合:
|
||||
|
||||
- 当前把 workflow 事件直接同步到 WorkZone 的分支
|
||||
- 当前把 image 路径当成默认 workflow 面板处理的分支
|
||||
|
||||
#### `with-workzone.ts` / `WorkZoneContent.tsx`
|
||||
|
||||
首版策略:
|
||||
|
||||
- 保留
|
||||
- 不扩展生图主路径
|
||||
- 仅服务非生图任务与兜底流程
|
||||
|
||||
后续可选策略:
|
||||
|
||||
- 当 image anchor 稳定后,再把生图相关分支从 WorkZone 中逐步收缩或删除
|
||||
|
||||
### 4. 状态层职责划分
|
||||
|
||||
建议把状态划成三层:
|
||||
|
||||
#### 提交期几何状态
|
||||
|
||||
来源:
|
||||
|
||||
- `AIInputBar`
|
||||
- 选区 / Frame
|
||||
- `size`
|
||||
|
||||
职责:
|
||||
|
||||
- 决定 anchor 初始位置与外壳类型
|
||||
- 是 `AIInputBar` 唯一应长期保有的 image 特有语义
|
||||
|
||||
#### 任务执行状态
|
||||
|
||||
来源:
|
||||
|
||||
- `taskQueueService`
|
||||
- `Task.progress`
|
||||
- `Task.executionPhase`
|
||||
|
||||
职责:
|
||||
|
||||
- 决定 `submitted / queued / generating`
|
||||
- 是任务生命周期的唯一执行真相,不直接决定最终收口
|
||||
|
||||
#### 后处理 / 插入状态
|
||||
|
||||
来源:
|
||||
|
||||
- `workflowCompletionService`
|
||||
- `useAutoInsertToCanvas`
|
||||
|
||||
职责:
|
||||
|
||||
- 决定 `developing / inserting / completed / failed`
|
||||
- 用于避免“任务已完成但图片尚未真正落图”时提前收口
|
||||
|
||||
### 5. 单一状态源约束
|
||||
|
||||
对于 image anchor,必须明确以下 ownership 约束:
|
||||
|
||||
- `AIInputBar` 只拥有提交瞬间快照,不拥有持续运行态
|
||||
- `WorkflowContext` / `workflowSubmissionService` 只拥有 workflow 计划真相,不拥有 anchor UI 真相
|
||||
- `taskQueueService` 只拥有任务执行真相
|
||||
- `workflowCompletionService` 只拥有后处理真相
|
||||
- `ImageGenerationAnchorController` 拥有唯一的 anchor 运行态
|
||||
|
||||
任何直接绕过 controller 写入 anchor UI 状态的路径,都视为架构违规。
|
||||
|
||||
### 6. 迁移顺序
|
||||
|
||||
推荐按以下顺序推进,避免双系统互相打架:
|
||||
|
||||
1. 新增 anchor 类型、plugin 与 view model
|
||||
2. 在 `AIInputBar` 中仅对 `image` 路径创建 anchor
|
||||
3. 在 `useAutoInsertToCanvas` 中接入 anchor 查找与完成态收口
|
||||
4. 在 `Drawnix` 中增加 anchor 同步 / 恢复 hook
|
||||
5. 将 image 路径从默认 `WorkZone` 更新链中分流
|
||||
6. 手工验证稳定后,再考虑清理 WorkZone 中的 image 分支
|
||||
|
||||
### 7. 为什么不复用 `WorkZone`
|
||||
|
||||
不推荐直接把 `WorkZoneContent` 改成“生图锚点样式”的主要原因:
|
||||
|
||||
- 仍会保留错误的元素语义
|
||||
- 仍会把大量工作流字段塞进画布元素
|
||||
- 仍会让生图依赖当前分散的 WorkZone 同步链
|
||||
- 会增加“单组件承担展示 + 恢复 + 兜底编排”的复杂度
|
||||
|
||||
独立元素类型虽然首版工作量更高,但长期边界更清晰。
|
||||
|
||||
## Audit And Review Plan
|
||||
|
||||
### 代码层重点审计
|
||||
|
||||
- 是否仍有 image 路径写入 `WorkZoneTransforms`
|
||||
- 是否存在 anchor 与 WorkZone 对同一 image 任务双写
|
||||
- 是否有组件直接读取 `taskQueueService` 并绕过 controller
|
||||
- 是否把恢复逻辑重新塞回展示组件
|
||||
- 是否在未知比例场景下错误创建完整比例框
|
||||
- 是否仍沿用 `ai-generation-complete` 作为 image 路径的唯一解锁信号
|
||||
|
||||
### 迁移层重点审计
|
||||
|
||||
- `AIInputBar` 创建 image anchor 后,是否仍然默认创建 WorkZone
|
||||
- `useAutoInsertToCanvas` 是否还依赖 `findWorkZoneForTask`
|
||||
- `drawnix.tsx` 的 WorkZone 恢复逻辑是否误处理 image anchor
|
||||
- `useWorkflowSubmission` 是否仍将 image 事件同步到 WorkZone
|
||||
- `useTaskWorkflowSync` 是否仍把 image 任务 fallback 到 WorkZone
|
||||
- 是否仍存在多个 `setTimeout(1500)` 竞争删除同一 image 反馈对象
|
||||
|
||||
### 手工验证重点
|
||||
|
||||
- 选中 Frame 的单图生图
|
||||
- 指定 `size` 的单图生图
|
||||
- 不指定 `size` 的单图生图
|
||||
- 同 prompt 多图生成
|
||||
- 失败后原位重试
|
||||
- 刷新页面后的锚点恢复
|
||||
- 自动插入完成后的收口行为
|
||||
|
||||
### Code Review 必查文件
|
||||
|
||||
- `packages/drawnix/src/components/ai-input-bar/AIInputBar.tsx`
|
||||
- `packages/drawnix/src/hooks/useAutoInsertToCanvas.ts`
|
||||
- `packages/drawnix/src/drawnix.tsx`
|
||||
- `packages/drawnix/src/hooks/useWorkflowSubmission.ts`
|
||||
- `packages/drawnix/src/hooks/useTaskWorkflowSync.ts`
|
||||
- `packages/drawnix/src/plugins/with-workzone.ts`
|
||||
- `packages/drawnix/src/plugins/with-image-generation-anchor.ts`
|
||||
- `packages/drawnix/src/services/workflow-completion-service.ts`
|
||||
- `packages/drawnix/src/services/task-queue-service.ts`
|
||||
|
||||
## Risks
|
||||
|
||||
- 若锚点状态映射继续分散在多个 hook 与组件中,会重新产生“多处同步”的维护问题
|
||||
- 若在未知比例时仍强制生成完整图片框,会造成锚点与最终结果不一致
|
||||
- 若首版同时覆盖多任务类型,会让锚点语义被稀释,增加复杂度
|
||||
|
||||
## Mitigations
|
||||
|
||||
- 首版限制在 `image` 类型
|
||||
- 将状态映射收敛到单一 view model / controller
|
||||
- 将几何策略明确为 `Frame-first / Size-first / Ghost-anchor`
|
||||
- 保留现有 `WorkZone` 给非生图路径,降低迁移风险
|
||||
@@ -0,0 +1,26 @@
|
||||
# Change: update image generation anchor feedback
|
||||
|
||||
## Why
|
||||
当前生图提交后默认在画布内创建 `WorkZone` 进度卡。该反馈方式能够表达“系统正在执行”,但不符合无限画布的创作语义:用户希望看到的是“图片对象正在诞生”,而不是“任务卡片正在运行”。
|
||||
|
||||
同时,生图与文本、分析、Agent 工具调用不同,结果天然会落入画布,因此其过程反馈也应优先围绕“落点、比例、对象连续性”设计,而不是围绕“工作流步骤列表”设计。
|
||||
|
||||
## What Changes
|
||||
- 为 AI 生图引入新的 `Generation Anchor` 反馈对象,替代默认的大面积 `WorkZone` 卡片
|
||||
- 按提交时可获得的几何信息,定义三档锚点策略:
|
||||
- `Frame-first`
|
||||
- `Size-first`
|
||||
- `Ghost-anchor`
|
||||
- 为生图定义统一的用户态状态机:`submitted`、`queued`、`generating`、`developing`、`inserting`、`completed`、`failed`
|
||||
- 将生图的详细执行信息收敛到任务详情层,不再默认在画布中展示完整步骤卡片
|
||||
- 保留失败重试、历史可追踪和刷新恢复能力,但以锚点节点而非过程卡片的形式呈现
|
||||
|
||||
## Impact
|
||||
- Affected specs: `image-generation-feedback`
|
||||
- Affected code:
|
||||
- `packages/drawnix/src/components/ai-input-bar/AIInputBar.tsx`
|
||||
- `packages/drawnix/src/hooks/useAutoInsertToCanvas.ts`
|
||||
- `packages/drawnix/src/plugins/with-workzone.ts`
|
||||
- `packages/drawnix/src/components/workzone-element/WorkZoneContent.tsx`
|
||||
- `packages/drawnix/src/services/task-queue-service.ts`
|
||||
- `packages/drawnix/src/services/canvas-operations/canvas-insertion.ts`
|
||||
@@ -0,0 +1,78 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Image Generation SHALL Use Canvas Anchors Instead Of Default Progress Cards
|
||||
|
||||
The system SHALL represent image-generation progress in the canvas through lightweight generation anchors instead of default large workflow cards.
|
||||
|
||||
#### Scenario: User submits a single image generation request
|
||||
- **WHEN** the user submits an `image` generation request from the AI input bar
|
||||
- **THEN** the canvas SHALL show a lightweight generation anchor near the expected insertion location
|
||||
- **AND** SHALL NOT default to a large progress card for that image request
|
||||
|
||||
#### Scenario: Non-image tasks keep existing feedback behavior
|
||||
- **WHEN** the user submits a non-image generation request
|
||||
- **THEN** the system MAY continue to use the existing task feedback behavior
|
||||
- **AND** SHALL NOT be forced into the image anchor presentation model
|
||||
|
||||
### Requirement: Image Generation Anchors SHALL Derive Geometry From Submission-Time Signals
|
||||
|
||||
The system SHALL determine the image anchor geometry from the strongest available submission-time signals before the final image result is returned.
|
||||
|
||||
#### Scenario: Anchor inherits frame geometry
|
||||
- **GIVEN** the user submits image generation while a target frame is selected
|
||||
- **AND** the request contains `targetFrameId` and `targetFrameDimensions`
|
||||
- **WHEN** the anchor is created
|
||||
- **THEN** the anchor SHALL use the frame geometry as its primary outer shell
|
||||
|
||||
#### Scenario: Anchor inherits requested aspect ratio
|
||||
- **GIVEN** the request has no target frame
|
||||
- **AND** the request contains a valid `size` ratio
|
||||
- **WHEN** the anchor is created
|
||||
- **THEN** the anchor SHALL derive its aspect ratio from that requested size
|
||||
|
||||
#### Scenario: Anchor falls back to a ghost anchor
|
||||
- **GIVEN** the request has no target frame
|
||||
- **AND** the request has no stable ratio signal
|
||||
- **WHEN** the anchor is created
|
||||
- **THEN** the system SHALL create a lightweight ghost anchor instead of a full image frame placeholder
|
||||
|
||||
### Requirement: Image Generation SHALL Expose User-Centered Lifecycle States
|
||||
|
||||
The system SHALL map image generation into user-centered lifecycle states that prioritize creation continuity over raw workflow details.
|
||||
|
||||
#### Scenario: User sees lifecycle progression
|
||||
- **WHEN** an image generation task progresses from submission to insertion
|
||||
- **THEN** the UI SHALL express the lifecycle using user-facing states such as `submitted`, `queued`, `generating`, `developing`, `inserting`, `completed`, and `failed`
|
||||
- **AND** SHALL allow those states to be rendered without exposing the full internal workflow step list in the canvas by default
|
||||
|
||||
### Requirement: Completed Images SHALL Replace Anchors With Spatial Continuity
|
||||
|
||||
The system SHALL transition from anchor to final image with spatial continuity so the result appears to emerge from the same canvas location.
|
||||
|
||||
#### Scenario: Image result is inserted into the canvas
|
||||
- **WHEN** the image generation result is ready and the insertion flow begins
|
||||
- **THEN** the final image SHALL take over the anchor location with a continuous visual transition
|
||||
- **AND** the anchor SHALL fade out after the image is stably inserted
|
||||
|
||||
### Requirement: Failed Image Generation SHALL Preserve Contextual Recovery
|
||||
|
||||
The system SHALL preserve a contextual recovery point when image generation fails.
|
||||
|
||||
#### Scenario: Image generation fails before insertion
|
||||
- **WHEN** an image generation task fails
|
||||
- **THEN** the anchor SHALL remain in place as a failure node
|
||||
- **AND** SHALL expose a retry path without requiring the user to rediscover the original insertion context
|
||||
|
||||
### Requirement: Image Generation Anchors SHALL Defer Detailed Execution History To Task Details
|
||||
|
||||
The system SHALL keep canvas anchors lightweight and defer detailed execution history to the task detail layer.
|
||||
|
||||
#### Scenario: Canvas anchor shows only concise progress context
|
||||
- **WHEN** an image generation anchor is rendered in the canvas
|
||||
- **THEN** it SHALL prioritize stage, lightweight progress, and direct recovery actions
|
||||
- **AND** SHALL NOT default to rendering the full workflow step list inside the canvas object
|
||||
|
||||
#### Scenario: Users need detailed failure or history information
|
||||
- **WHEN** the user requests more detail about an image generation task
|
||||
- **THEN** the system SHALL provide that information through the task detail layer
|
||||
- **AND** the anchor MAY offer a navigation affordance without becoming the primary detail container
|
||||
@@ -0,0 +1,40 @@
|
||||
## 1. Product Rules
|
||||
- [x] 1.1 定义生图锚点的用户态状态机与文案规范
|
||||
- [x] 1.2 定义 `Frame-first / Size-first / Ghost-anchor` 三档几何策略
|
||||
- [x] 1.3 明确生图锚点与任务详情层的职责边界
|
||||
|
||||
## 2. State Model
|
||||
- [x] 2.1 新增 `image-generation-anchor.types.ts`,定义 anchor 元素、用户态与几何上下文
|
||||
- [x] 2.2 新增 anchor view model / controller,统一映射任务状态、进度与后处理阶段
|
||||
- [x] 2.3 收敛生图反馈所需的提交期几何信号(插入点、Frame、size)
|
||||
- [x] 2.4 为失败重试与刷新恢复定义统一的锚点状态转换
|
||||
- [x] 2.5 定义 submission context 与 anchor view model 的字段契约,避免多模块各自拼装
|
||||
- [x] 2.6 明确 controller 为 image anchor 的单一状态源,禁止其他模块直接双写 UI 状态
|
||||
|
||||
## 3. UI Implementation
|
||||
- [x] 3.1 新增 `with-image-generation-anchor.ts`,注册 `generation-anchor` 元素与 transforms
|
||||
- [x] 3.2 新增 `ImageGenerationAnchorContent.tsx` 与样式文件,替代生图默认大卡片
|
||||
- [x] 3.3 实现 `Frame Anchor` 与 `Ratio Anchor` 的首版渲染
|
||||
- [x] 3.4 实现 `Ghost-anchor` 兜底渲染
|
||||
- [x] 3.5 实现锚点到真实图片的完成态过渡
|
||||
- [x] 3.6 实现失败态节点与重试入口
|
||||
|
||||
## 4. Workflow Integration
|
||||
- [x] 4.1 在 `AIInputBar` 中为 `image` 类型接入“已提交”即时反馈,并创建首个 anchor
|
||||
- [x] 4.2 在 `useAutoInsertToCanvas` 中基于 `taskId` 查找 anchor,驱动 `developing / inserting / completed / failed`
|
||||
- [x] 4.3 在 `Drawnix` 中挂载 image anchor 的同步 / 恢复 hook
|
||||
- [x] 4.4 为生图路径分流现有 `WorkZone`,避免默认展示大卡片
|
||||
- [x] 4.5 保留非生图任务对现有 `WorkZone` 的兼容
|
||||
- [x] 4.6 调整 `useWorkflowSubmission`,避免 image 路径继续走默认 WorkZone 同步
|
||||
- [x] 4.7 调整 `useTaskWorkflowSync`,避免 image 任务 fallback 到 WorkZone
|
||||
- [x] 4.8 清理 image 路径中的重复 `setTimeout` 删除与 `ai-generation-complete` 双写依赖
|
||||
|
||||
## 5. Validation
|
||||
- [x] 5.1 验证选中 Frame 生图时的锚点几何一致性
|
||||
- [x] 5.2 验证指定 `size` 生图时的比例一致性
|
||||
- [x] 5.3 验证无 Frame / 无稳定比例时的 `Ghost-anchor` 降级体验
|
||||
- [x] 5.4 验证生图路径不再默认创建大 `WorkZone` 卡片
|
||||
- [x] 5.5 验证失败、重试、刷新恢复与自动插入完成后的收口行为
|
||||
- [x] 5.6 Code review 审计 image 路径是否仍残留 `WorkZoneTransforms` 双写
|
||||
- [x] 5.7 验证非图片任务仍保持旧 WorkZone 路径不受影响
|
||||
- [x] 5.8 手工审计 `AIInputBar`、`Drawnix`、`useAutoInsertToCanvas`、`useWorkflowSubmission`、`useTaskWorkflowSync` 的 image 路径 ownership
|
||||
Reference in New Issue
Block a user