合并master并保留Spine序列帧修复
合并master当前工程、后端、前端和文档更新 按已确认方案解决Spine序列帧多模态、帧数和快速编辑冲突 保留当前分支底部工具栏宽度与隐藏滚动条样式
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,319 @@
|
||||
# AI 游戏创作 Agent Runtime 交互边界重构实施计划
|
||||
|
||||
更新时间:`2026-08-12`
|
||||
状态:评审中
|
||||
|
||||
## 0. 目标与范围
|
||||
|
||||
统一 Consumer(GUI / CLI / 自动化测试)与 Runtime 之间的公开交互边界,达到:
|
||||
|
||||
- **Consumer 只做两件事**:`render(state)` 与 `dispatch(intent)`,中间不保留决策。
|
||||
- **交互 Loop 收归后端 Supervisor Shell**:Consumer 不再根据 Runtime 状态自行选择 start / steer / confirm / retry / resume。
|
||||
- **GUI、CLI、测试夹具是同一套协议的平等 Consumer**,GUI 没有任何特权通道。
|
||||
- **Runner 自驱**:工作发现、恢复、继续执行不依赖 Consumer 在线或主动触发。
|
||||
|
||||
本重构**不重新设计 Runtime 内部执行模型**(Part D 保持黑盒),只补充 Shell 需要的边界能力。
|
||||
|
||||
### 不在本轮
|
||||
|
||||
- Agent 执行状态机(main_loop / task_queue / recovery)内部重构。
|
||||
- Runner 进程生命周期策略(开机自启 / 无 GUI 常驻)——自驱只限于"Runner 存活期间",保留 GUI 启动 + GUI-owner watchdog。
|
||||
- LLM / Provider / 提示词体系改动。
|
||||
|
||||
---
|
||||
|
||||
## 1. 交互 Loop 协议(Interaction Contract)
|
||||
|
||||
这是 Consumer 与 Supervisor Shell 之间唯一的公开协议。协议不绑定 transport(Tauri 命令 / Runner 协议 / 进程内函数均可用同一套 DTO)。
|
||||
|
||||
### 1.1 出向事件(Shell → Consumer)
|
||||
|
||||
| 事件 | 含义 | 现状落点 | 是否新增 |
|
||||
|---|---|---|---|
|
||||
| `progress` | 运行推进 | `status/phase` + `recentEvents` + `waitingOn/nextStep`,经 `read_game_creator_agent_runtimes` 与 `game-creator-agent-progress` 事件 | 收敛 |
|
||||
| `needs_input` | 等待澄清回答 | `userInputRequest` / phase `waiting-for-user-input`(`AgentRuntimeUserInputRequest`) | 收敛 |
|
||||
| `approval_required` | 等待开发者批准工具动作 | `pendingToolAction` / phase `waiting-for-confirmation`(`AgentRuntimePendingToolActionSummary`) | 收敛 |
|
||||
| `tool_request` | 工具已请求/执行中 | 现散在 `recentToolCalls` + phase `action` | **新增派生** |
|
||||
| `artifact` | 产物 / manifest 变化 | `game-creator-manifest-invalidated` + finalization journal | 收敛 |
|
||||
| `done` | 本轮终态 | `completed` + `AgentRuntimeFinalizationJournal` + responseStream `committed` | 收敛 |
|
||||
| `error` | 失败 / 需人工核对 | `failed` / `needs-reconciliation` + `error` | 收敛 |
|
||||
|
||||
协议 DTO(camelCase 序列化,与现有一致):
|
||||
|
||||
```rust
|
||||
enum AgentRuntimeOutboundEvent {
|
||||
Progress(AgentRuntimeProgress),
|
||||
NeedsInput { request: AgentRuntimeUserInputRequestView },
|
||||
ApprovalRequired { action: AgentRuntimePendingToolActionSummary },
|
||||
ToolRequest(AgentRuntimeToolRequest), // 新增:Shell 从 recentToolCalls+phase 投影
|
||||
Artifact(AgentRuntimeArtifactEvent), // 收敛 manifest-invalidated + finalization
|
||||
Done(AgentRuntimeDoneEvent),
|
||||
Error(AgentRuntimePublicError),
|
||||
}
|
||||
|
||||
struct AgentRuntimeProgress {
|
||||
project_path: String, agent_id: String, run_id: String,
|
||||
status: String, phase: String,
|
||||
current_task: String, current_action: String,
|
||||
plan_steps: Vec<AgentRuntimePlanStep>, active_plan_step_index: Option<u32>,
|
||||
waiting_on: String, next_step: String, // Shell 负责填充,Consumer 不再映射 phase→文案
|
||||
updated_at: u64,
|
||||
}
|
||||
```
|
||||
|
||||
> 与现状的关键差异:`progress` 里的 `waiting_on`/`next_step` 由 **Shell 填充**。当前是前端在 `model.ts:612/644` 硬编码 phase→中文文案,收归 Shell 后前端删除该映射。
|
||||
|
||||
### 1.2 入向命令(Consumer → Shell)
|
||||
|
||||
| 命令 | 吸收的旧命令 | 说明 |
|
||||
|---|---|---|
|
||||
| `submit_intent` | `start_*` / `steer_*` | 一条消息可能 steer 进现有 run,也可能 start 新 run,由 Shell 判定 |
|
||||
| `answer` | `answer_game_creator_agent_runtime_user_input` | 回答澄清 |
|
||||
| `approve` | `confirm_*` / `reject_*` | 批准或拒绝,含 policy 确认卡 |
|
||||
| `cancel` | `cancel_game_creator_agent_runtime_task` | 取消 |
|
||||
| `resume` | `resume_*` / `confirm_resume_*` / `retry_*` / `confirm_retry_*` / `schedule_game_creator_agent_ready_tasks` | 恢复/重试/调度统一入口 |
|
||||
|
||||
命令签名:
|
||||
|
||||
```rust
|
||||
#[tauri::command]
|
||||
async fn submit_game_creator_agent_intent(
|
||||
project_path: String, session_id: String, intent: String,
|
||||
run_profile: Option<String>, source: Option<String>,
|
||||
) -> Result<AgentRuntimeIntentResult, String>;
|
||||
|
||||
#[tauri::command]
|
||||
async fn answer_game_creator_agent_interaction(
|
||||
project_path: String, run_id: String, action_id: String,
|
||||
request_id: String, response_id: String, answers: BTreeMap<String, String>,
|
||||
) -> Result<AgentRuntimeResult, String>;
|
||||
|
||||
#[tauri::command]
|
||||
async fn approve_game_creator_agent_interaction(
|
||||
project_path: String, run_id: String, action_id: String,
|
||||
approved: bool, note: String,
|
||||
) -> Result<AgentRuntimeResult, String>;
|
||||
|
||||
#[tauri::command]
|
||||
async fn cancel_game_creator_agent_run(
|
||||
project_path: String, agent_id: String, run_id: String,
|
||||
) -> Result<AgentRuntimeResult, String>;
|
||||
|
||||
#[tauri::command]
|
||||
async fn resume_game_creator_agent_project(
|
||||
project_path: String,
|
||||
) -> Result<Vec<AgentRuntimeResult>, String>;
|
||||
```
|
||||
|
||||
协议外 API(不进交互 Loop,作为管理面保留在 Shell 上):goal CRUD、`compact`、会话管理、配置读写。
|
||||
|
||||
### 1.3 统一 InteractionRequired 语义
|
||||
|
||||
Shell 向 Consumer 暴露"必须等待外部回答"的单一概念,替代现在分散的 `pendingToolAction` / `userInputRequest` / policy 确认卡:
|
||||
|
||||
```rust
|
||||
enum AgentRuntimeInteractionRequired {
|
||||
UserInput { request: AgentRuntimeUserInputRequestView },
|
||||
Approval { action: AgentRuntimePendingToolActionSummary },
|
||||
PolicyApproval { policy: String }, // 新增:吸收 confirm_resume/confirm_retry 的 agent.resume 确认卡
|
||||
}
|
||||
```
|
||||
|
||||
> 现状的 `confirm_resume`(`commands.rs:1148`)与 `confirm_retry`(`commands.rs:1020`)是"要求用户确认策略"的产物,由 GUI 弹确认卡实现。收归 Shell 后,Shell 评估 `enforce_project_auto_permission_policy`(`verification.rs:813`),需要确认时返回 `InteractionRequired::PolicyApproval`,用户确认后经统一的 `approve` 命令继续。
|
||||
|
||||
---
|
||||
|
||||
## 2. 现状盘点与复用清单
|
||||
|
||||
### 2.1 可直接复用的资产(近 1 个月内形成,活跃演进期)
|
||||
|
||||
| 资产 | 位置 | 复用方式 |
|
||||
|---|---|---|
|
||||
| CLI 交互决策状态机 | `swarm_cli/turn_dispatch.rs:245` `decide_interaction_action`、`:48` `handle_swarm_user_turn`(steer/start、Reply/Execute/Resume、goal 门禁) | **整体上提**到后端 Shell(纯 Rust、无 UI 纠缠) |
|
||||
| Runner 自驱续跑定时器 | `runtime_driver/provider_recovery.rs` 的 `schedule_waiting_provider_retry_wake_after_lane_release` 等 | 已存在,P4 直接复用 |
|
||||
| 确定性 e2e | `scripts/agent-runtime-deterministic-playable-e2e.mjs` + `deterministic-lane-defense-provider.mjs`(`expectedProviderStats`/`expectedChildReport` 断言) | P0 基线扩展(协议级 trace) |
|
||||
| 版本协商 fallback | 前端 `model.ts:1186-1226` `isMissing*CommandError` | 迁移期新旧并存的标准模式 |
|
||||
| 逐命令幂等 | `accepted_run_id`(`runtime_state.rs:1548`)、runner requestId 缓存(`runner/protocol.rs:353`)、goal CAS | P1 设计直接沿用 |
|
||||
| 进程内集成测试 | `src-tauri/tests/`(`command_runtime.rs`、`runtime_actions/`、`collaboration/`、`goal.rs`) | P1-P6 每步回归的护栏 |
|
||||
|
||||
### 2.2 需要收敛/改造的点
|
||||
|
||||
| 点 | 位置 | 动作 |
|
||||
|---|---|---|
|
||||
| 前端 phase→文案映射 | `model.ts:612/644/974/1498/1554` | Shell 填充 `waiting_on/next_step` 后删除 |
|
||||
| 前端 steer/start 决策 | `model.ts:849` `submitProjectSupervisorRuntimeTask`、`App.tsx:5791` | 迁入 Shell(`submit_intent`) |
|
||||
| 前端 confirm/retry/resume 门禁 | `model.ts:1131-1154`、`panels.tsx:381-497` | 由 `InteractionRequired` + `approve/resume` 取代 |
|
||||
| 前端跨轮状态修补 | `model.ts:244` `normalizeAgentRuntimeState`、`:385` `mergeAgentRuntimeStateIntoMap` | 依赖 P2 Snapshot 稳定后删除 |
|
||||
| CLI 独立状态机 | `swarm_cli/turn_dispatch.rs` | 上提 Shell,CLI 只留终端交互(stdin/stdout/observer) |
|
||||
| 重复触发恢复 | `App.tsx:2799/10341`、`useDeveloperAgentPanel.ts:684`(启动时 resume)、`App.tsx:10550`(devMode schedule 按钮) | P4 后删除,由 Runner 自驱 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 分阶段实施计划
|
||||
|
||||
> 主线:**先建安全网 → 建统一入口 → 统一状态读取 → 收回决策 → Runner 自驱 → 迁移全部 Consumer → 删旧面**。
|
||||
|
||||
### P0 行为基线(安全网)
|
||||
|
||||
**目标**:在改动前建立可判断"公开行为是否变化"的验证能力。
|
||||
|
||||
- 复用 `deterministic-lane-defense-provider.mjs`,在现有 `agent-runtime-deterministic-playable-e2e.mjs` 基础上**增加协议级事件 trace**:
|
||||
- 录制一条确定性完整会话的**出向事件序列**(progress/needs_input/approval_required/done/error 的顺序与关键载荷),归一化 timestamp、`run_id`/`steer_id`/`request_id` 随机 ID、`accepted_run_id` 对账值。
|
||||
- 断言当前 master 的 trace 与预期一致(快照 diff)。
|
||||
- 建立统一的回归命令,P1-P6 每阶段结束必跑:
|
||||
- 确定性 e2e(功能正确性)
|
||||
- `src-tauri/tests/` 进程内集成测试(单元级护栏)
|
||||
- 协议级 trace(迁移等价性)
|
||||
- **不动 Runtime 代码**,只建安全网。
|
||||
|
||||
**验收**:上述三条命令在当前 master 全绿,trace 基线文件入库。
|
||||
|
||||
### P1+P2 统一入口 + 状态读取(adapter + Snapshot 投影)
|
||||
|
||||
**目标**:Consumer 改走新协议调用旧实现;状态读取收敛为稳定的公开 Snapshot。**旧接口全保留**为迁移期兼容路径。
|
||||
|
||||
**P1 适配器(`submit_intent` / `approve` / `answer` / `cancel` / `resume` 新命令)**:
|
||||
|
||||
> **P1 与 P3 的边界**:P1 只做"命令可用 + `submit_intent` 内部判定 steer/start"。`answer`/`approve`/`resume` 在 P1 **只是入口封装**(内部调旧函数),"收到交互该调哪个命令、能否重试"的判定**仍在前端**;到 P3 才把判定收走,前端只剩 `submit`/`respond` 两种动作。
|
||||
|
||||
- 新增 `src-tauri/src/agent/supervisor_shell/`,内含:
|
||||
- `intent.rs`:`submit_intent` 内部路由——读当前 runtime → 判定 steer/start(逻辑取自 `swarm_cli/turn_dispatch.rs` 的 steer 判定与前端 `matchingAgentRuntimeForSteer`)→ 调现有 `steer_game_creator_agent_runtime_task_for_profile_at` 或 `start_game_creator_supervisor_background_task_for_session_at` → 返回 `{ mode, accepted_run_id, runtime }`。
|
||||
- `interaction.rs`:`approve/answer/cancel` 薄封装现有 `confirm/reject/answer/cancel` 内部函数(P1 只封装,判定仍在前端)。
|
||||
- `resume.rs`:`resume_game_creator_agent_project` 吸收 `resume/confirm_resume/retry/confirm_retry/schedule_ready`——Shell 判定是否需 policy 确认、是否需先 cancel 再重试(`needs-reconciliation` 分支,逻辑取自 `App.tsx:6205` `handleProjectSupervisorRetry`)。
|
||||
- 新命令与旧命令**同时注册**(`main.rs` invoke_handler)。
|
||||
- 前端新增"调新命令 → 后端报 unknown command → 回退旧命令"的版本协商(复用 `isMissing*CommandError` 模式),保证打包版本不一致时旧链路可用。
|
||||
- **fallback 边界**:仅"命令不存在(版本不兼容)"确定性回退;写操作的其他错误原样呈现,不做盲目重试(防重复入队)。
|
||||
|
||||
**P2 Snapshot 投影(状态读取收敛)**:
|
||||
|
||||
> **投影 = 读模型**:把同一份 Runtime durable state(唯一事实来源)按一个稳定、精简、面向消费的 schema 重新导出,作为 Consumer 的权威视图。它**不是新的事实来源**,只是同一份事实的另一种呈现;Consumer 依赖投影,业务真相仍在 durable state。
|
||||
|
||||
- 新增 `supervisor_shell/snapshot.rs`:`AgentRuntimeSnapshot` 投影。
|
||||
- 输入:现有 `AgentRuntimeResult.state` + `recent_events`/`recent_tasks`/`response_stream`/`user_input_request`。
|
||||
- 输出:稳定的公开视图(agent/session/run 身份、status/phase、`InteractionRequired`、progress、终态、公开错误)。
|
||||
- **内部字段(recentToolCalls、observations、allowedTools、contextUsage 等)不进 Snapshot**。
|
||||
- 关键:**后端先补"稳定读取"**——现状前端 `normalizeAgentRuntimeState` 做跨轮 carry-forward,是因为后端 read 在恢复/竞态时字段不稳定。P2 后端投影保证同一 run 身份下字段自洽,前端才能删掉自己的修补。
|
||||
- 新增 `read_game_creator_agent_runtime_snapshot(s)` 命令(或改造现有 read 返回 Snapshot),旧 `read_game_creator_agent_runtime(s)` 保留。
|
||||
- 前端 `normalizeAgentRuntimeState` / `mergeAgentRuntimeStateIntoMap` / phase→文案映射**依赖 P2 稳定后删除**(本轮先做投影,下一阶段删前端逻辑)。
|
||||
|
||||
**验收**:
|
||||
- 新命令与旧命令对同一场景返回的终态一致(用 P0 trace + 确定性 e2e 断言)。
|
||||
- 前端在"走新 Snapshot"下渲染与旧路径一致(组件回归)。
|
||||
- 现有 `command_runtime.rs` / `collaboration/` 测试全绿(旧逻辑未动)。
|
||||
|
||||
### P3 Loop 收归 Supervisor Shell
|
||||
|
||||
**目标**:Consumer 只 dispatch 意图,不再持有生命周期判断。
|
||||
|
||||
- 完成 `submit_intent` / `approve` / `answer` / `cancel` / `resume` 对全部旧分叉的吸收(P1 已建,本轮做全):
|
||||
- `approve` 吸收 confirm/reject,并按 interaction kind 分派(`UserInput`/`Approval`/`PolicyApproval`)。
|
||||
- `resume` 吸收 resume/confirm_resume/retry/confirm_retry/schedule_ready。
|
||||
- 建立 `AgentRuntimeInteractionRequired`(见 1.3),Shell 统一暴露"需等待外部回答"。
|
||||
- Shell 负责填充 `waiting_on`/`next_step`(从 phase 映射,逻辑上提自 `model.ts:612/644`)。
|
||||
- 新增派生事件 `tool_request`(Shell 从 `recentToolCalls` + phase 投影)。
|
||||
- **前端删除**:
|
||||
- `submitProjectSupervisorRuntimeTask` 的 steer/start 决策(`model.ts:849`)。
|
||||
- `agentRuntimeCanCancel/CanRetry/CanConfirm` 门禁(`model.ts:1131-1154`)。
|
||||
- `App.tsx:5981/6127/6205` 的 confirm/retry/repair 路由逻辑。
|
||||
- CLI(`swarm_cli`)改为调用同一 Shell:决策逻辑上提后,CLI 只保留 stdin/stdout 终端交互与 observer 渲染。
|
||||
|
||||
**验收**:
|
||||
- CLI 走新协议跑通完整 supervisor+子 Agent 流程(`agent-swarm-test-chat.mjs` / 确定性 e2e)。
|
||||
- GUI 提交、确认、重试、恢复均通过统一 `submit_intent/approve/resume`,无 `steer_*`/`confirm_*`/`retry_*` 直接调用。
|
||||
- P0 协议级 trace 在"新旧实现各放一遍"下事件序列一致。
|
||||
|
||||
### P4 Runner 自驱
|
||||
|
||||
**目标**:工作发现、恢复、继续执行不依赖 Consumer 触发。**这是重构主线的一部分,不是独立项目。**
|
||||
|
||||
- 项目目录簿:`runner/state.rs` 的 `known_roots`(当前进程内)→ 持久化到 AppData(复用 runner 的 `--config-dir`),Runner 重启后仍知道持有过哪些项目。
|
||||
- 启动自恢复:`runner/server.rs` 启动完成后,对 known roots 调 `has_recoverable_game_creator_agent_background_tasks_at`(`recovery_scan.rs:425`),有可恢复工作则自动 `resume_game_creator_agent_background_tasks_at`。
|
||||
- 空闲自扫描:主 accept loop(`server.rs:275`,已有 25ms `EXTERNAL_AGENT_RUNNER_LOOP_INTERVAL`)内增加"是否有 pending 任务需 wake"的轻量检查,替代 Consumer 调 `schedule_game_creator_agent_ready_tasks` / `wake_pending`。
|
||||
- 吸收 `schedule_game_creator_agent_ready_tasks`:manifest ready 任务由 Runner 扫描发现并调度,删除前端 devMode 按钮(`App.tsx:10550`)。
|
||||
- **边界(不在本轮)**:Runner 仍由 GUI 启动(`main.rs:2124`),保留 GUI-owner watchdog(`server.rs:169`)与 `game_chat_release` 退出协议(`main.rs:2311`)。"自驱 = 存活期间自调度 + 启动自恢复",**不含**开机自启/无 GUI 常驻。
|
||||
- 对应删除前端恢复触发职责:`App.tsx:2799/10341`、`useDeveloperAgentPanel.ts:684` 的启动时 resume、resume 确认卡回调。
|
||||
|
||||
**验收**:
|
||||
- Runner 进程内:确认一个 pending 任务后无需任何 Consumer 调用即自动执行;恢复 pending 动作后自动续跑。
|
||||
- 确定性 e2e 增加"Runner 独立进程跑完整流程"用例(复用 `agent-runtime-real-e2e/harness/process.mjs` 的二进制编译能力)。
|
||||
- `confirm_resume` 恢复确认卡流程改为 `InteractionRequired::PolicyApproval` → `approve`。
|
||||
|
||||
### P5 迁移 GUI / CLI / Tests
|
||||
|
||||
**目标**:三类 Consumer 全部迁移到统一 Intent、Snapshot、Runtime Output。
|
||||
|
||||
- GUI:
|
||||
- 状态渲染改读 `AgentRuntimeSnapshot`;删除 `normalizeAgentRuntimeState` / `mergeAgentRuntimeStateIntoMap` / phase 文案映射。
|
||||
- 交互全走 `submit_intent/approve/answer/cancel/resume`;删除 steer/confirm/retry/resume 直接调用与门禁。
|
||||
- 保留只读消费形态:response stream 展示、对话合并、画布资产编排(这些不进 Loop 协议)。
|
||||
- CLI:`cli.rs` 与 `swarm_cli` 改用 Shell 命令;删除各自状态机(决策已上提)。
|
||||
- Tests:`src-tauri/tests/` 迁移到新命令;`agent-runtime-real-e2e` 与确定性 e2e 走同一协议。
|
||||
- 迁移顺序:先 CLI(最薄)→ 再 Tests → 最后 GUI(唯一消费 response stream / conversation 合并 / goal CAS / 委派修复路由,工作量最大)。
|
||||
|
||||
**验收**:GUI、CLI、Tests 调用面收敛到同一组命令,代码差异只剩输入输出形式。
|
||||
|
||||
### P6 删除旧公开面
|
||||
|
||||
**目标**:Interaction Contract 成为唯一稳定公开边界。
|
||||
|
||||
- 删除旧 Tauri 命令:`start_game_creator_agent_runtime_task` / `start_game_creator_supervisor_runtime_task` / `steer_*` / `confirm_*` / `reject_*` / `retry_*` / `confirm_retry_*` / `resume_game_creator_agent_runtime_tasks` / `confirm_resume_*` / `schedule_game_creator_agent_ready_tasks` / `read_game_creator_agent_runtime(s)`(`main.rs:2188-2208`)。
|
||||
- 删除对应后端 wrapper 与前端 `app/types.ts` 旧 DTO、旧事件协议、迁移期兼容逻辑。
|
||||
- 现有 start / steer / resume / recovery 能力作为 Shell 内部实现保留(改名/内联)。
|
||||
|
||||
**验收**:`grep` 无旧命令名残留;全量回归(P0 基线 + 单元 + e2e)全绿。
|
||||
|
||||
---
|
||||
|
||||
## 4. 迁移策略(新旧并存 + 等价性)
|
||||
|
||||
1. **接口即实现,不留空窗**:新命令从注册第一天起就是真实可用——内部套用现有旧函数(adapter 套旧实现是**常态、透明**,前端不知道也不关心)。不存在"接口先立、实现待填"的中间态;分阶段的不是"接口 vs 实现",而是"谁先切到新接口"。
|
||||
2. **新旧并存**:P1 起新命令与旧命令同时注册,Consumer 逐个切换,旧路径逐条下线(strangler fig)。
|
||||
3. **版本协商 fallback(仅用于迭代空窗期)**:前端调新命令,**仅当**后端报 unknown command(前端版本 ≠ 后端版本,打包错位)时回退旧命令;其他运行错误**原样呈现,不盲目重试**(防重复入队)。后端新版随应用覆盖到位后,fallback 即死代码,P6 删除。
|
||||
4. **等价性保障**:
|
||||
- 确定性 provider + 协议级 trace(P0)作为新旧实现的对照基线。
|
||||
- 进程内集成测试每阶段全跑。
|
||||
- 关键迁移点(steer/start 判定、resume 路由、needs-reconciliation 重试)用"同一输入 → 新旧实现输出一致"的单测锁定。
|
||||
|
||||
---
|
||||
|
||||
## 5. 里程碑与验收门禁
|
||||
|
||||
| 里程碑 | 交付 | 门禁 |
|
||||
|---|---|---|
|
||||
| M0 | P0 基线 + trace 入库 | 回归三件套全绿 |
|
||||
| M1 | P1 新命令 + adapter(新旧并存) | 新/旧命令终态一致;现有测试全绿 |
|
||||
| M2 | P2 Snapshot 投影 + 前端读 Snapshot | 前端删 normalize 后渲染回归一致 |
|
||||
| M3 | P3 Loop 收归(Intent + InteractionRequired) | CLI 走新协议跑通完整流程;前端无 steer/confirm/retry 直调 |
|
||||
| M4 | P4 Runner 自驱 | Runner 独立进程自动跑完;resume 确认走统一 approve |
|
||||
| M5 | P5 全部 Consumer 迁移 | GUI/CLI/Tests 调用面收敛到同一协议 |
|
||||
| M6 | P6 删旧面 | 无旧命令残留;全量回归绿 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 风险与未决问题
|
||||
|
||||
| 风险/问题 | 影响 | 缓解 |
|
||||
|---|---|---|
|
||||
| P2 依赖"后端 read 先稳定",否则前端不敢删 normalize | 阶段顺序敏感 | P2 后端投影先行,前端删逻辑放同一阶段尾 |
|
||||
| P4 自驱与 GUI-owner 安全模型冲突 | 若误解为"无 GUI 常驻"会引安全评审 | 计划内明确边界,实现不越界 |
|
||||
| steer/start 判定含 UX 语义(mode/source/runProfile、steerId 生成、acceptedRunId 对账) | 收归 Shell 后前端展示可能退化 | Shell 返回 `{ mode, accepted_run_id, steer_decision }` 补足展示信息 |
|
||||
| `tool_request` 无现成单一落点 | 需 Shell 派生投影 | 提前排进 P2/P3 投影工作量 |
|
||||
| 协议级 trace 的随机 ID 归一化 | 基线易碎 | 复用确定性 provider,归一化规则集中一处 |
|
||||
|
||||
## 7. 建议实施顺序(一句话)
|
||||
|
||||
P0 建安全网 → P1+P2(adapter + Snapshot,纯增量、旧接口全留、fallback 兜底)→ P3 收 Loop → P5 迁移(先 CLI 后 GUI)→ P6 删旧面;P4(Runner 自驱)作为主线中心件贯穿 M4,不单独立项,但边界(存活期间自调度,不含无 GUI 常驻)在计划内写死。
|
||||
|
||||
---
|
||||
|
||||
## 8. 相对原方案的调整点
|
||||
|
||||
本计划在原方案基础上做了以下调整,均基于 master 现状与既有安全模型:
|
||||
|
||||
1. **P0 基线**:原方案的 Golden Replay 改为"确定性 e2e + 协议级事件 trace"——在既有确定性 provider e2e(`deterministic-lane-defense-provider.mjs`)上扩展,录制协议级事件序列并归一化 timestamp 与随机 ID,不重建基线体系。
|
||||
|
||||
2. **P4 定位与边界**:原方案将"Supervisor Lifecycle Coordinator"列为独立阶段;现作为主线组成部分(里程碑 M4,不单独立项)。自驱限于"Runner 存活期间自调度 + 启动自恢复",排除"开机自启 / 无 GUI 常驻",与既有 GUI-owner 安全模型一致。
|
||||
|
||||
3. **术语收敛**:原方案"Interaction Contract / Intent / Snapshot"统一为本计划"交互 Loop 协议"(5 入向命令 + 7 出向事件)与"投影"(读模型),含义不变。
|
||||
|
||||
4. **迁移原则显式化**:接口即实现(adapter 套旧逻辑为常态);fallback 仅在版本空窗期、只认 unknown command。原方案未明确此点。
|
||||
File diff suppressed because one or more lines are too long
@@ -7,10 +7,10 @@
|
||||
|
||||
- 同一面板分为“AI生成/改造”和“视频直接转换”两个标签,旧配方默认恢复 AI;两个标签独立保留草稿;标签为分段按钮样式(明显可点击、带选中态),不再像标题。
|
||||
- AI 视频以 `motion` 表示动作视频、`appearance` 表示可选角色外观图(可多张);Provider 的 `reference_video` 负责动作、`reference_image` 负责外观。动作视频已选中后,外观图是可选的普通图片参考,不要求画布图层标记为 `character`;上传序列帧 PNG 作为一张完整参考图,不识别网格或拆帧。
|
||||
- 直接转换使用内部 `/api/editor/character-animations/video-conversions` 与 durable job `editor_character_animation_video_conversion`,固定免费、保留背景,不调用 Seedance、BgFilter 或其它去背景模型,也不重复保存源视频。**去背景暂缓**:直接转换的源视频背景非纯色,本地键色抠图不适用,待确定方案后再做。
|
||||
- 源视频仅接受 owner-scoped MP4/MOV,限制 50MB、2–15 秒。FFprobe 读取旋转后的显示尺寸、精确时长与平均 FPS;FFmpeg 覆盖完整时间轴,采样率为 `clamp(min(源平均 FPS, 8), 1, 8)`,产出 2–120 帧。
|
||||
- 直接转换使用内部 `/api/editor/character-animations/video-conversions` 与 durable job `editor_character_animation_video_conversion`,固定免费、保留背景,不调用 Seedance、BgFilter 或其它去背景模型,也不重复保存源视频;生成完成后如用户点击工具栏 `去背景`,再以独立的零泥点 durable 派生任务处理完整序列。
|
||||
- 源视频仅接受 owner-scoped MP4/MOV,限制 50MB、2–15 秒。FFprobe 读取旋转后的显示尺寸、精确时长与平均 FPS;先按 `clamp(min(源平均 FPS, 8), 1, 8)` 计算目标帧数,再把帧数限制到 2–66,并按 `最终帧数 ÷ 精确时长` 回算 FFmpeg 覆盖完整时间轴所用的实际采样率。
|
||||
- 480p/720p 表示最大长边,只缩小不放大。正式 `imageSequenceDurationMs` 等于探测时长,播放器、普通 ZIP 与 Spine JSON 的单帧时长统一按 `imageSequenceDurationMs ÷ frameCount`。
|
||||
- 直接转换仍落 `character-animation` / `image-sequence`,配方 action 为 `character-animation.convert`,来源槽位为 `source`。最多 120 帧时第一帧同时承载最终 resource/asset;角色动画拆帧允许 120 项,图标图集公开切片继续限制 64 项,既有 512 KiB/2 MiB JSON 门禁不放宽。
|
||||
- 直接转换仍落 `character-animation` / `image-sequence`,配方 action 为 `character-animation.convert`,来源槽位为 `source`。最多 66 帧时第一帧同时承载最终 resource/asset;角色动画拆帧允许 66 项,图标图集公开切片继续限制 64 项,既有 512 KiB/2 MiB JSON 门禁不放宽。
|
||||
- `/api/external/v1` 保持原图片模式,不暴露内部新增字段或直接转换接口,不修改 OpenAPI。
|
||||
|
||||
## 1. 文档目的
|
||||
@@ -93,7 +93,7 @@ manifest.txt
|
||||
|
||||
现有角色动作能力已经包含:
|
||||
|
||||
- 统一从底部工具栏“Spine序列帧动画”进入;不再从图层右键菜单或选中图层浮动工具栏暴露独立入口;当前选中视频(或带预览视频的序列帧)时,底部入口默认打开“视频直接转换”,其它情况默认打开“AI生成/改造”;
|
||||
- 底部工具栏保留“Spine序列帧动画”通用入口;角色图层的选中浮动工具栏和右键菜单保留 `生成动画` 快捷入口,但只打开同一个 `character-animation` generation dialog,不维护平行面板;当前选中视频(或带预览视频的序列帧)时,底部入口默认打开“视频直接转换”,其它情况默认打开“AI生成/改造”;
|
||||
- `character-animation` 生成占位框;
|
||||
- 动作描述;
|
||||
- 待机、行走、奔跑、跳跃、攻击、受击、倒下预设;
|
||||
@@ -232,7 +232,7 @@ flowchart LR
|
||||
|
||||
| 需求 | 当前能力 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| 工具栏在视频后新增入口 | 当前只能从角色图触发 | 需要新增底部入口 |
|
||||
| 工具栏在视频后新增入口 | 当前已有角色图 `生成动画` 快捷入口 | 新增底部通用入口并复用同一 dialog |
|
||||
| 纯文本生成 | 当前必须有角色源图 | 需要扩展后端 T2V |
|
||||
| 图片 + 文本 | 已实现角色立绘图生视频再抽帧 | 主要复用 |
|
||||
| 已有序列帧改造 | 仅有部分恢复/首帧能力,来源语义不完整 | 需要明确输入形态并补全 |
|
||||
@@ -242,7 +242,7 @@ flowchart LR
|
||||
| 动作“更多”逐行展开 | 当前只有固定 7 个预设 | 需要前端扩展 |
|
||||
| 1080p | Fast 前后端均不支持 | 暂不开放 |
|
||||
| 40 泥点/次 | 当前 480p × 4 秒恰好为 40;其他组合不同 | 需确认固定价还是按秒价 |
|
||||
| 去背景 | 当前生成链自动逐帧去背景 | 与需求中的手动动作冲突 |
|
||||
| 去背景 | AI 生成链自动透明化;直接转换保留背景 | 保留零泥点手动派生任务 |
|
||||
| 拆帧生成单 PNG | 帧对象已有,但没有全部登记为独立账号素材 | 可复用对象、补资产绑定 |
|
||||
| ZIP 下载 | 已完成且匹配附件 | 不重做 |
|
||||
|
||||
@@ -475,7 +475,7 @@ flowchart TD
|
||||
- 任一必需帧失败,整项失败,不发布残缺序列;
|
||||
- 明确失败退款;
|
||||
- 原子提交结果未知时按现有对账语义处理,不能先退款再猜提交失败;
|
||||
- 拆帧只复用已有对象,不应再次收 Seedance 生成费;若逐帧去背景改为手动动作,需要另行确定费用。
|
||||
- 拆帧只复用已有对象,不再次收 Seedance 生成费;手动去背景作为零泥点 durable 派生任务执行。
|
||||
|
||||
## 9. 提示词策略
|
||||
|
||||
@@ -520,11 +520,11 @@ flowchart TD
|
||||
|
||||
`ImageCanvasBottomToolbarView.tsx`:
|
||||
|
||||
- 在“生成视频”后保留唯一的“Spine 序列帧动画”入口;
|
||||
- 在“生成视频”后保留“Spine 序列帧动画”通用入口;
|
||||
- 点击后在视口中心创建统一的 `character-animation` generation dialog;
|
||||
- 统一面板内同时承载“AI生成/改造”和“视频直接转换”两个标签;
|
||||
- 当前选中视频或带预览视频的序列帧时默认进入“视频直接转换”,当前选中角色图时默认进入“AI生成/改造”,无适用选中图层时默认进入“AI生成/改造”;
|
||||
- 右键菜单和选中图层浮动工具栏不再提供“生成动画”或“视频转换为Spine序列帧动画”平行入口;
|
||||
- 角色图层右键菜单和选中图层浮动工具栏保留 `生成动画` 快捷入口,并复用上述统一 dialog;不新增“视频转换为Spine序列帧动画”平行入口;
|
||||
- 不在当前面板下方追加内容;移动端保持横向滚动或现有工具栏收纳规则。
|
||||
|
||||
`CanvasTool` 增加 `character-animation`,但不新增页面路由。
|
||||
@@ -601,19 +601,12 @@ flowchart TD
|
||||
|
||||
#### 去背景
|
||||
|
||||
当前后端默认已经逐帧去背景。推荐方案是:
|
||||
|
||||
- 生成结果始终为透明 RGBA;
|
||||
- 不再展示“去背景”,或仅在检测到历史不透明序列时展示;
|
||||
- 不重复对透明帧调用抠图 provider。
|
||||
|
||||
如果产品坚持“先保留纯色背景,用户点击后再去背景”,则必须改为派生任务:
|
||||
AI 生成链默认逐帧去背景,视频直接转换固定保留源背景。`character-animation` 浮动工具栏继续提供 `去背景`,与 `改造 / 拆帧 / 下载` 并列;点击后必须走现有 durable 派生任务,不得把序列第一帧当普通图片处理。派生任务保持以下边界:
|
||||
|
||||
- 原始不透明序列与透明序列是两个正式 resource;
|
||||
- 去背景全帧成功后一次性发布新序列;
|
||||
- 任一帧失败不产生残缺结果;
|
||||
- 需要单独确定泥点和失败退款;
|
||||
- 该选择会改变当前成熟链路,不建议作为默认。
|
||||
- 当前费用固定为 0 泥点,失败不产生不完整正式结果。
|
||||
|
||||
#### 拆帧
|
||||
|
||||
@@ -690,7 +683,7 @@ idle
|
||||
|
||||
- 改造完整恢复;
|
||||
- 拆帧绑定既有 frame asset objects;
|
||||
- 条件式去背景(若最终保留);
|
||||
- 保留零泥点 durable 去背景派生任务;
|
||||
- 顶部下载默认 Spine ZIP;
|
||||
- 元数据文案。
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ canvasCompletion?
|
||||
|
||||
场景参考图沿用普通图片生成的客户端前置门禁,最多 5 张;超限时不得发送 HTTP 请求。场景生成 POST 使用生成专用零重试策略,避免 inline 响应丢失后重复调用 Provider。
|
||||
|
||||
生成完成后的 `scene` 是静态图片素材:它属于画布素材标签的图片媒体族,允许用户把图片图层覆盖标记为 `scene`,并支持既有图片快速编辑链路。前端标签菜单与 SpacetimeDB 结构化布局白名单、前端快速编辑入口与 api-server 图片编辑白名单必须分别成对同步。该编辑能力不改变通用图片生成接口对 `kind = scene` / `assetKind = scene` 的拒绝;新场景仍必须从本节的结构化专用接口生成。
|
||||
|
||||
后端对模型、比例和清晰度先沿用 `normalize_editor_generation_options` 标准化,再使用标准化比例决定画幅描述和入队价格。
|
||||
|
||||
## 5. Prompt
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user