Merge branch 'master' into feat/ui-editor-better-offset-ui
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
- [UI 编辑器变换角点偏移编辑器](./technical/【设计】UI编辑器变换角点偏移编辑器-2026-09-03.md)
|
||||
- [UI 编辑器子节点显示规则](./technical/【技术方案】UI编辑器子节点显示规则-2026-08-18.md)
|
||||
- [UI 编辑会话模块边界](./technical/【前端架构】UI编辑会话模块边界-2026-08-19.md)
|
||||
- [UI 编辑器撤销重做规范](./【UI编辑器】撤销重做规范-2026-09-03.md)
|
||||
|
||||
## 图片画布与媒体
|
||||
|
||||
|
||||
@@ -7612,6 +7612,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 配置:有无 AGC LLM Key 都只支持 `openai_responses`;非空 Key 映射后 base URL 与逐 Agent model/effort 生效,Key 只经专用环境变量;空 Key 只桥接用户 Codex `auth.json`,移除继承环境 Key。`stream=true` 复用现有 durable final-reply delta;`webSearchEnabled=true`、`openai_chat / anthropic` 必须显式切换 `provider`,不得静默忽略已有 LLM 配置。
|
||||
- 安全与恢复:app-server 使用隔离临时 `CODEX_HOME` 与 OS HOME,只桥接认证,不加载用户 MCP/config/skills/hooks;启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力,固定 read-only、network off、never approval,AGC 是唯一 ToolHost。取消覆盖 turn-start 回包前窗口并只发送单 turn interrupt;已开始 turn 的连接/终态未知直接标记 reconciliation,明确 failed/interrupted 不自动重试。模式与 durable 指纹取同一配置快照。
|
||||
- 资源与退出:pool 按实际凭据快照/base URL/API kind/CLI 版本和节点 run 身份隔离;空 AppData Key 只允许桥接一次性读取的有界 `auth.json` 快照,并用同一字节快照生成池指纹,宿主 `CODEX_API_KEY` 对 app-server 与一次性 CLI 都必须移除。节点进程与 thread 均有上限并只淘汰 inactive LRU;stdout NDJSON 与 stderr 无换行记录均有硬上限,stderr 原文不得写入错误或日志,只记录固定分类、总字节数、SHA-256 与可取得的退出状态。Runner 正常、强制、watchdog 退出显式关池;Linux child 绑定 parent-death signal,避免 Runner 被强杀后遗留带凭据孤儿进程。
|
||||
- DirectProject 会话恢复补充:Codex thread 继续使用 `ephemeral=true`,不保存或恢复 Codex 原生 thread。项目对话 `.agent/conversations/project.jsonl` 是唯一聊天事实源;仅当 app-server 连接没有可用的项目 thread(通常是进程重启或 thread 被淘汰)时,AGC 才读取全部 `user`、`assistant`、`tool` 行,按原顺序渲染为简单的 `user:` / `assistant:` / `tool:` 文本后,再追加本次新 user 请求发送给新 thread;已有 thread 的普通消息仍只发送新 user。app-server 意外中断时,已收到的 partial 文本作为普通 `assistant` 消息追加,并在末尾写入 `unexpected interrupt happened here`;断开处理与下一次发送均可重复追加,但使用普通消息 `messageId` 幂等。项目打开不再根据“只有 user 没有 assistant”自动重发旧请求;Direct 不新增 retry 入口。Runtime Agent 的恢复合同保持独立,不消费项目 Direct 对话历史。
|
||||
- 兼容迁移:已有 AppData 未写 `agentMode` 时,仅当全局及逐 Agent 都是 `openai_responses` 才迁入 app-server;任何 `openai_chat / anthropic` 路由保持 `provider`,防止项目自动恢复先于用户改配置而批量失败。新安装仍默认 app-server;已确认兼容 Responses 的旧端点可由用户显式切换且继续使用原 model/base URL/API Key。
|
||||
- 关联:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md` V1.52。
|
||||
|
||||
@@ -7937,6 +7938,17 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 任务最终状态不再提前绑定平台画布、preview、static smoke 或发布产物检查;这些内容不参与该档位的完成判定,也不会因缺失而重置已完成任务。父 run 在任务图进入终态后直接收束并回复。
|
||||
- 本档位仍沿用现有项目根和工具权限边界;本次调整只解除流程编排与平台产物验收前置,不新增第二套任务系统。
|
||||
|
||||
## 2026-09-02 DirectProject replay 取舍与 thread 原子判定
|
||||
|
||||
- DirectProject 的全量 replay、简单 `user:` / `assistant:` / `tool:` 前缀和普通 assistant partial(末尾 `unexpected interrupt happened here`)都是有意的当前产品合同:分别保证 AGC JSONL 事实源无损重建、保持 prompt 形状稳定且不引入 envelope breaking change、让模型明确知道上次输出在中断处结束。后续若调整任一项,必须先更新恢复合同与兼容策略。
|
||||
- replay 与 thread 创建必须使用同一临界区结果。`turn_gate` 内的 `thread_for()` 原子返回 `(CodexThreadLease, created)`;只有 `created=true` 时才读取项目 JSONL 并构造历史 prompt,复用已有 thread 时只发送当前 user,避免并发首请求重复注入历史。
|
||||
|
||||
## 2026-09-03 DirectProject replay 有界滑动窗口
|
||||
|
||||
- DirectProject 继续以 `.agent/conversations/project.jsonl` 作为不可变、append-only 唯一事实源;窗口只生成本次恢复请求的派生 prompt,不写回 JSONL,不创建 Runtime compaction summary 或 sidecar。
|
||||
- 新建/恢复 ephemeral Codex thread 时,replay 使用 `contextWindowTokens`、`autoCompactTokenLimit`、本次 `maxOutputTokens` 与 4096 安全余量计算预算,从最新记录向前选择连续完整的 `user` / `assistant` / `tool` 行;超预算旧前缀被省略,单条记录不截断,当前 user request 始终保留。
|
||||
- 发生省略时在 prompt 开头加入普通 `system: Earlier conversation history was omitted due to context budget.` 提示;当前请求本身超过硬上下文预算则直接失败。该策略是 Direct 专用滑动窗口,不复用 Runtime Agent 的摘要、tail 或 session compaction 生命周期。
|
||||
|
||||
## 2026-08-31 AGC 错误报告与诊断上传
|
||||
|
||||
- AGC 采用 IDEA 风格的当前进程错误池:按 fingerprint 合并 React / window / Promise / Tauri / Agent 错误,重启后不恢复,不使用 run 或 run_id。
|
||||
|
||||
@@ -226,6 +226,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
|
||||
|
||||
- 模式升级:`agentMode` 扩为 `codex_app_server / codex_cli / provider`,新默认为 `codex_app_server`;V1.51 的一次性 `codex exec` 保留为显式兼容模式,HTTP Provider 保留为非 Responses 配置及故障回退模式。
|
||||
- 进程与节点:External Runner 按“有效 Agent LLM 凭据/Responses 路由 + `projectId/agentId/sessionId/runId`”隔离长期 `codex app-server --stdio`,即每个权威节点 run 直接持有自己的 Codex CLI 子进程与 ephemeral thread,每次完整权威请求映射 turn。同一节点 turn 串行,节点之间进程级隔离;单节点连接失败不得使其它节点同时失去终态。Codex thread 不写 durable recovery;节点完成、重启、retry、handoff 和 finalization 仍只认 AGC 账本。
|
||||
- DirectProject replay:Codex thread 仍保持 `ephemeral=true`。`.agent/conversations/project.jsonl` 是聊天唯一、append-only 事实源;每个 GUI turn 在发起 app-server turn 前,先把渲染后的规范化 user prompt 以 `direct-codex:{clientTurnId}:user` 幂等追加,持久化失败则不发起 turn 并公开 failed;LLM 失败 / 中断时保留该 user 记录,重试同一 `clientTurnId` 只复用它。仅当 app-server 连接没有可用的项目 thread(通常是进程重启或 thread 被淘汰)时,AGC 才读取历史,按原顺序渲染为简单 `user:` / `assistant:` / `tool:` 行,再追加本次新 user request,发送给新建 thread;已有 thread 的普通消息仍只发送新 user。为避免持久增长的历史超过模型上下文,replay builder 使用全局 `contextWindowTokens`、`autoCompactTokenLimit`、本次 `maxOutputTokens` 和 4096 安全余量计算输入预算,从最新记录向前选择连续、完整的消息;超预算的旧前缀只在本次 prompt 中省略,不改写 JSONL、不写 summary/sidecar、不拆分单条记录。发生省略时在 prompt 开头加入普通 `system: Earlier conversation history was omitted due to context budget.` 行;当前 user request 始终保留,若其自身超过硬上下文预算则直接失败。这里的简单 role 前缀和普通 assistant partial(末尾 `unexpected interrupt happened here`)仍是产品合同:保持 prompt 形状稳定、避免 envelope breaking change,并让模型明确知道上次输出在断开处结束。app-server 意外中断时,已收到的 partial 文本按普通 `assistant` 消息追加;断开处理和下一次发送都可尝试写入,依赖普通 `messageId` 幂等。项目打开只读取历史,不因 user-only 记录自动重发;Direct 不提供 retry 入口。Runtime Agent 继续使用独立的 runtime/context 恢复链路,不读取 DirectProject 对话作为原生 thread history。
|
||||
- LLM 配置:`apiKind` 始终只接受 `openai_responses`;非空 Key 转换为 app-server model provider,base URL 生效,Key 仅走专用环境变量;空 Key 只桥接用户 Codex `auth.json`,不继承环境 `CODEX_API_KEY`。设置面板在 app-server 模式继续显示并保存 model、effort、stream、全局/逐 Agent Key 与路由配置;`openai_chat / anthropic` 明确提示切 `provider`,不得悄悄忽略。`stream=true` 接入 app-server 文本 delta;`webSearchEnabled=true` 只允许 DirectProject 经客户端审核的 `agc_web_search` 使用,不得启用 Codex 原生 webSearch 或任意网络。
|
||||
- 安全与取消:临时 cwd、隔离 `CODEX_HOME` 与 OS HOME、read-only、network off、never approval,并在启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力;取消从 turn-start pending 阶段就跟踪且只 interrupt 当前 turn。已发送 turn 后连接断开或终态丢失进入 reconciliation,只关闭当前节点进程且不重放同一 request slot;明确 failed/interrupted 不按 transport 重试。
|
||||
- remote-control 认证边界:没有 ChatGPT `auth.json` 的 API Key / provider-proxy app-server 在启动时设置 Codex 内部环境变量 `CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1`,让 remote-control 以 `desired_state=Disabled` 启动,避免上游进入 1Hz 认证重试;不再依赖需要 ChatGPT 登录态的 `remoteControl/disable` RPC。只有实际桥接 ChatGPT 登录态的 AuthBridge 保持 remote-control 可用。API Key 子进程同时使用 `RUST_LOG=warn` 收敛剩余预期噪音,不伪造 `auth.json` 或静默继续。
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# UI 编辑器拖动变换提交边界
|
||||
|
||||
## 当前约定
|
||||
|
||||
UI 编辑器预览中的节点拖动和缩放在指针移动期间只更新预览层的临时变换,不写入编辑器 State。指针松开时才把最后一次有效变换提交到 State,因此一次拖动或缩放只产生一次正式编辑更新。
|
||||
|
||||
指针取消、页面切换、树切换、组件卸载或没有超过拖动阈值时,不提交变换,并清理临时预览值。指针松开后的最终变换属于正常 State 修改,会参与脏状态、保存和后端持久化;仅拖动期间的临时变换不会进入这些流程。资产文件也不会因该交互被删除。
|
||||
|
||||
## 实现边界
|
||||
|
||||
- `useNodeTransformInteraction` 保存手势起始变换和最后一次有效变换。
|
||||
- `UiTreeRenderer` 通过 `previewTransforms` 渲染临时变换。
|
||||
- `canvas.updateNodeTransform` 仅在 `pointerup` 提交,`pointercancel` 不提交。
|
||||
- 拖动和缩放继续共用单指针捕获与有限数校验。
|
||||
@@ -0,0 +1,69 @@
|
||||
# UI 编辑器撤销与重做规范
|
||||
|
||||
## 目标
|
||||
|
||||
UI 编辑器支持撤销最近一次或多次作品编辑,并支持重做被撤销的编辑,降低误操作返工成本,同时保持现有保存、AI 工作流和资产文件行为不变。
|
||||
|
||||
## 适用范围
|
||||
|
||||
撤销历史属于当前 UI 编辑会话,历史只保存可序列化的编辑器 `State` 快照,不保存页面临时状态。
|
||||
|
||||
纳入历史的操作:
|
||||
|
||||
- 设计图名称、描述、角色和从属关系修改;
|
||||
- 设计图、精灵、字体资源的新增、删除和元数据修改;
|
||||
- 节点新增、删除、移动、Transform、Layout、元数据、子节点显示模式修改;
|
||||
- 组件新增、删除、排序和字段修改;
|
||||
- AI suggest、recognize、merge,以及批量导入、批量删除等批量 State 修改,整次成功调用作为一条记录;
|
||||
- bind 按后端批次逐次提交,每个成功 batch 作为一条独立记录,便于逐批撤销;
|
||||
- 节点拖动或缩放,按一次按下到松开的连续操作作为一条记录。
|
||||
|
||||
不纳入历史的操作:
|
||||
|
||||
- 选择项、隐藏节点、工作流步骤、面板展开状态和画布视口等 UI 临时状态;
|
||||
- 打开/切换项目、服务端重新加载和清空编辑器;这些操作替换 State 后重置历史;
|
||||
- 保存、自动保存、生成代码、发布请求本身;撤销只改变本地 State,后续保存才同步远端;
|
||||
- 素材上传、AI 生成等已发生的外部副作用;若副作用同时落地了本地 State,只撤销本地 State 变化;
|
||||
- no-op、锁定、校验失败或目标不存在的操作。
|
||||
|
||||
导入资源被撤销时只回退编辑器 State 中的资源记录和引用,不删除已经写入磁盘的资产文件;重做恢复原资源 ID 与文件引用。
|
||||
|
||||
## 历史模型
|
||||
|
||||
- 栈按会话全局维护,最多保留最近 100 条事务;超限丢弃最旧记录。
|
||||
- 每条记录保存 `before` 与 `after` 的完整结构化 State 快照,快照不复制二进制文件内容。
|
||||
- 提交前后快照相同则不产生记录。
|
||||
- 撤销将当前 State 恢复为记录的 `before`,并把记录移入 redo 栈;重做恢复 `after`。
|
||||
- 撤销后发生新的有效编辑时清空 redo 栈。
|
||||
- 撤销/重做恢复 State 时不得再次写入历史。
|
||||
|
||||
## 事务边界
|
||||
|
||||
- 普通字段、按钮和列表操作一次成功调用对应一条记录。
|
||||
- 节点拖动/缩放期间只更新预览层临时变换;松开时提交最终变换并生成一条记录。取消、卸载、切换资源、未越过阈值或无变化不提交。
|
||||
- 每次有效 `commit` 或 `replaceState` 都直接生成一条记录;bind 的每个成功 batch 独立提交。失败 batch 不产生记录,已完成的前序 batch 保留。
|
||||
- 颜色选择器、九宫格边界拖动等连续控件在交互期间使用本地 draft 预览,释放或确认时一次提交。
|
||||
|
||||
## 用户入口
|
||||
|
||||
- 桌面端页面工具栏提供撤销和重做按钮。
|
||||
- 非文本编辑目标聚焦编辑器时支持 `Cmd/Ctrl+Z` 撤销、`Cmd/Ctrl+Shift+Z` 和 `Ctrl+Y` 重做。
|
||||
- `input`、`textarea`、`select`、`contenteditable` 以及按钮/链接等控件交给浏览器原生行为,不拦截文本撤销。
|
||||
- 无可撤销或重做记录时按钮禁用,并提供可访问名称。
|
||||
|
||||
## 脏状态与选择
|
||||
|
||||
撤销和重做恢复的 State 继续参与现有 dirty 判定、保存和后端持久化。历史快照不包含当前设计图、节点选择、隐藏集合或视口;恢复后若当前选择已不存在,页面清理无效选择并保持安全空态。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 单次字段编辑可撤销和重做。
|
||||
2. 连续多次编辑按逆序撤销。
|
||||
3. 节点拖动/缩放一次手势只产生一条记录,取消和零变化不产生记录。
|
||||
4. AI suggest/recognize/merge 一次调用只产生一条记录;bind 每个成功 batch 产生一条记录,失败不产生该 batch 记录。
|
||||
5. 撤销后新编辑清空 redo。
|
||||
6. 加载/切换/清空重置历史;保存/自动保存不清空历史。
|
||||
7. 撤销/重做资源导入不删除资产文件,并恢复原资源引用。
|
||||
8. 工具栏按钮、禁用态和桌面快捷键可用,文本控件保留原生撤销。
|
||||
9. no-op、锁定、校验失败和不存在目标不进入历史。
|
||||
10. 颜色选择器和九宫格边界拖动不会按每个 pointer move 写入 State。
|
||||
Reference in New Issue
Block a user