Merge branch 'master' into fix/chat-state
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 2m13s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 2m24s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 2m32s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 2m3s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m40s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m11s
Project CI / Native shell tests (pull_request) Failing after 2m25s
Project CI / AI game creator shell web tests (pull_request) Failing after 1m14s
Project CI / Frontend tests (pull_request) Failing after 2m59s
Project CI / Repository checks (pull_request) Failing after 3m17s
Project CI / Backend tests (pull_request) Successful in 7m15s

This commit is contained in:
2026-09-15 20:25:16 +08:00
106 changed files with 2023 additions and 1835 deletions
@@ -7,6 +7,8 @@
- `GET/PUT /admin/api/agc-models` 仅 owner 可用,返回完整配置;PUT 携带上次读取的 revision,冲突拒绝覆盖。
- `GET /api/llm/models` 返回启用项的 `id/displayName``defaultModelId` 和目录 `revision`,不返回实际模型名、Router 目录、凭据或能力原始数据。
- 客户端缓存最近 `revision`,在项目切换 / 对话表面挂载 / 下拉展开 / 窗口聚焦时条件刷新:`revision` 未变化不更新界面,同一时刻只保留一个在途请求,刷新失败保留上一次有效目录与本地选择。发起对话前用同一份快照校验所选模型仍启用,已停用或删除则回退默认模型并提示。
- 手动刷新立即显示进行中状态;真实刷新成功后显示完成反馈,即使 `revision` 未变化也有反馈。失败沿用有效缓存时仍显示失败,不能报告刷新成功;HTTP 状态和超时使用可辨认的提示。
- 模型目录与其它客户端 JSON API 的成功、失败响应体读取均复用 `readClientHttpResponseText` 的 15 秒上限;响应头已返回但响应体卡住时必须结束本次等待、释放目录在途请求并允许重试,迟到的响应不得覆盖新目录。
- AGC Responses 请求的 `model` 是稳定目录标识。服务端按当前目录映射实际模型名;未知、停用项拒绝,不回退其它模型。旧客户端无 AGC 标记时使用后台默认项。
- 输入框右下角选择模型,只显示别名;选择保存到客户端配置 `selectedModelId``selectedModelIsDefault`(当前选择是否来自平台默认项),从下一次请求生效。加载失败或选项停用时禁用提交并允许刷新,不显示实际 ID 作为兜底文案。
- `selectedModelIsDefault` 为真表示选择由平台默认项驱动(首次进入、默认项变化、所选模型失效回退),后台默认项变化时客户端跟随切换并提示;用户手动选择后置为假,不再被默认项变化覆盖。
@@ -19,4 +21,5 @@
- 目录领域校验、未知/停用模型拒绝、客户端响应不包含实际模型名。
- 后台鉴权、持久化 revision 冲突处理;客户端选择保存后重新读取,设置保存不覆盖选择。
- 目录 `revision` 条件刷新与并发触发去重、发送前回退默认模型、刷新失败可恢复。
- 响应体超时保留有效缓存、再次刷新重新请求、迟到响应不覆盖新目录;手动刷新进行中、同版本成功与缓存兜底失败反馈。
- AGC/admin-web 类型检查与定向测试、编码检查、Rust 定向检查、schema 一致性与 diff 检查。
@@ -265,7 +265,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- 模式合同:客户端 AppData 配置新增全局 `agentMode`,只接受 `codex_cli / provider`。缺省和新安装默认使用 `codex_cli`,原有 HTTP LLM Provider 路径完整保留并可显式切回 `provider`;切换只影响下一次节点请求,不新增 Runner、任务图、会话库、配置库或业务事实源。
- 调度边界:正式 DAG、manifest、Agent task/session/run 身份、队列、锁、委派、all-join、完成门、Provider lifecycle、持久 retry/handoff 与 `needs-reconciliation` 继续由现有 AGC Runtime 掌控。每个被调度节点在 `codex_cli` 模式下直接启动一次非交互 `codex exec` 充当该节点的推理 AgentCodex 返回当前 Runtime 广告函数的结构化调用,Runtime 仍是唯一 ToolHost,不允许 CLI 自己写项目、执行命令、调用 MCP 或形成第二套 revision / verification 真相。
- 安装包侧车:Windows x64 release 固定随 Tauri resource 打包 `@openai/codex@0.147.0` 的原生 `codex.exe`Rust build script 从 AGC 子包锁定依赖 stage 到 resource,并写入版本与 SHA-256 清单。Windows 侧车映射只写入 `tauri.windows.conf.json`,通用 `tauri.conf.json` 不得让 Linux / macOS 构建依赖未生成的 Windows 二进制。运行时只在文件摘要和 `codex-cli` 版本同时匹配清单时优先选内置侧车;缺失、损坏或版本漂移时跳过它,按既有 npm 安装、PATH 顺序回退。安装包同时携带 Apache-2.0 第三方声明;API Key、`auth.json`、Cookie、Token、用户 `CODEX_HOME`、用户配置和项目数据绝不打包。
- Windows x64 release 安装包只生成 NSIS,不生成 MSI:`tauri.windows.conf.json``bundle.targets` 固定为 `["nsis"]`,通用配置继续保留其它平台的默认打包目标。
- Windows x64 release 安装包只生成 NSIS,不生成 MSI:`tauri.windows.conf.json``bundle.targets` 固定为 `["nsis"]`,通用配置继续保留其它平台的默认打包目标。安装后的产品名、开始菜单 / 桌面快捷方式和 EXE 产品描述统一由 `tauri.conf.json``productName: "陶泥儿"` 生成;应用 identifier 与内部可执行文件名保持稳定。内置 Codex 资源安装到顶层 `coding-agent/win-x64/`,运行时从同一路径查找 `bin/codex.exe``manifest.json`;仓库 staging 仍使用 `resources/codex/win-x64/`,包内子目录、组件名、版本和完整性校验保持原合同。
- CLI 安全边界:CLI 固定使用 argv 启动,禁止 shell 拼接;工作目录使用本次请求专用的空临时目录,不把游戏项目绝对路径写入 prompt、stdout、stderr 或持久记录。调用固定使用 ephemeral、忽略用户配置和 exec rules、read-only sandbox、never approval,并关闭 Codex shell tool;只继承 CLI 运行和认证所需的最小环境,显式移除宿主 `CODEX_API_KEY`。用户级 Codex 登录态继续由本机 Codex 自己读取,API Key、auth 文件、Cookie、Token、`CODEX_HOME` 私有内容不得复制到项目配置、Runtime sidecar、Agent DB、conversation 或日志;stdout / stderr 无换行时也受硬上限约束,stderr 诊断只记录固定分类、字节数和 SHA-256。
- 协议边界:Runtime 把既有 `LlmRunRequest` 的消息和当前函数目录编码为有界 prompt,并从同一函数 JSON Schema 生成 Codex structured-output schema。CLI 输出转换为现有 `LlmRunResponse / LlmToolCall` 后,继续经过 native tool / MCP 参数校验、动作上限、权限、pending、receipt、验证与格式修复链;最终回复仍走唯一提交路径,不新增平行响应协议。
- 取消与恢复:Codex 子进程绑定当前 Provider request lifecycle,取消、暂停、Runner draining 或 GUI owner 丢失时终止并回收当前进程;started 后没有可信终态仍沿现有 Provider reconciliation 处理。`agentMode`、CLI 可执行身份和影响输出的 Codex 参数进入 `providerConfigFingerprint`,模式切换不得消费另一模式遗留的 retry/handoff。
@@ -1167,7 +1167,7 @@ game-project/
- `.agent/manifest.json` 的存储写边界使用同目录持久文件锁跨线程、跨进程串行化;锁必须覆盖旧 manifest 读取、不可变版本前缀校验、临时文件安装和安装后回读一致性校验。锁文件拒绝符号链接、非普通文件和异常所有权 / 硬链接;Windows 使用不共享写句柄,Unix 使用 `O_NOFOLLOW + flock`。旧快照在新版本安装后只能被拒绝,不能覆盖已追加版本。
- 后台 Agent 的 manifest 变化以共用 Runtime 状态投影 / 终态 emitter 作为失效因果点:`game-creator-agent-runtime-update` 的 Rust / TypeScript DTO 固定携带 `manifestInvalidated`,且 App 必须在 Supervisor、selected agent、session 和 run 身份的任何 early return 之前处理失效。GUI 进程内 Runtime 直接发该事件;External Runner 是独立进程、没有 GUI `AppHandle`,因此 Runner 协议 v5 的 `runner.attach_gui_owner` 必须登记 GUI 创建的随机 loopback 端口和 64 位随机令牌,Runner 的同一 emitter 通过受令牌保护的短连接转发 `game-creator-manifest-invalidated`。两条路径都只传项目路径与 Agent 身份,不复制 manifest,也不靠轮询补偿。
- Direct Codex 不伪造普通 Agent Runtime state。每张平台美术在本地文件与 manifest 提交成功后,统一通过 standalone `game-creator-manifest-invalidated` 发送 `projectPath + direct-codex-art`;只读恢复的已付费源图同样在 `register_local_asset_at` 成功后发送,下载、解码、文件写入或登记失败时不得发送成功失效。前端仍把 `game-creator-agent-progress` 仅用于进度文案;Direct Codex 整体命令成功、失败或超时 reject 后都追加一次 manifest 最终对账,只有完整成功才启动本地预览。
- Direct Codex 不伪造普通 Agent Runtime state。每张平台美术在本地文件与 manifest 提交成功后,统一通过 standalone `game-creator-manifest-invalidated` 发送 `projectPath + direct-codex-art`普通 `agc_generate_image` 同样在生成通道成功返回后、工具结果组装前发出通知,不能只覆盖标准美术包。只读恢复的已付费源图同样在 `register_local_asset_at` 成功后发送,下载、解码、文件写入或登记失败时不得发送成功失效。失效事件匹配当前项目时统一 Windows 盘符、UNC 与对应 verbatim 前缀的写法,实际重读始终使用当前项目保存的路径;该比较仅用于刷新提示,不替代后端路径与权限校验。前端仍把 `game-creator-agent-progress` 仅用于进度文案;Direct Codex 整体命令成功、失败或超时 reject 后都追加一次 manifest 最终对账,只有完整成功才启动本地预览。
- App 收到当前项目的 Runtime / relay 失效后重新调用 `get_local_game_manifest`。重读按项目 single-flight 合并事件风暴;读取中再到达失效只追加一轮串行重读,不并发提交同项目响应。应用结果同时校验组件仍挂载、当前项目路径和项目 scope version;项目切换、组件卸载或旧 scope 的迟到响应不得覆盖新项目。Project Supervisor 对外发布前以“revision 前读 -> manifest -> revision 后读”取得一致快照,再通过 `onManifestChange(projectPath, manifest, metadata)` 携带 `projectId + revision + source`;启动器按 `projectPath + projectId` 只接受更高 revision,同 revision 只接受内容一致的重复,旧轮询和同 revision 分叉都不得覆盖。资源列表、依赖图输入、任务状态、运行入口和正式版本卡必须在当前页面实时重投影,不要求关闭或重开项目。集成测试记录“事件未重新打开项目”的调用基线前,必须先等待项目写入最近列表后触发的只读目录状态刷新完成,不能把这项合法后台检查误算成失效事件副作用。
- `.agent/agent.db` 有界尾部读取报告截断时,审计 producer 映射失败关闭,不生成基于不完整审计的 producer、task flow 或对应任务环。前端收到截断 DTO 时只剔除 `producerAssignments``taskFlows` 与对应 `cyclicTaskIds`Rust 根据当前 manifest、精确资源引用和仍可信任务深度下限返回的 `dependencyDepths` 继续保留,前端只校验资源仍存在且深度为非负安全整数,不得自行重算或压平权威深度。精确引用边、reference connection index、`cyclicResourceIds` 与 unresolved references 同样继续保留。
-- 资源依赖 SVG 继续作为不可交互装饰层隐藏,但 dependency 画布通过 `aria-describedby` 提供当前可见精确引用和任务流的文本等价列表。中央资源聚焦按稳定 `resourceId` 驱动焦点状态:仅 `null -> id``idA -> idB` 聚焦详情 region,同一 ID 的 manifest 重投影不得抢走音频、视频、链接或关闭按钮焦点;显式收起和 Escape 恢复画布滚动并优先聚焦原触发卡片。聚焦资源被删除时清理 stale focused / selected ID,关闭详情并把焦点落到资源搜索框;项目切换或运行视图切换清除旧恢复意图,不得恢复旧项目卡片。橙色引用线及箭头使用对 `#fffdfa` 画布达到至少 `3:1` 的颜色。
@@ -1379,3 +1379,15 @@ DirectProject 使用 `approvalPolicy=never`,避免每次原生调用再经过
## 2026-09-14 新游戏策划到真实美术接入的连续交付
DirectProject 在收到完整游戏策划或游戏制作请求后,必须把视觉素材作为同一交付链路处理:先读取当前项目已登记资源;策划案包含角色、对象、背景、特效、界面或其它视觉实体且现有资源不满足时,Codex 必须在同一游戏实现任务中调用审核的 `agc_tools` 生图或编辑工具,读取返回的资源身份与相对路径,把真实产物接入游戏源码,再构建并验证实际渲染。生成了素材但源码仍使用 emoji、CSS 形状或临时占位图替代策划要求的视觉元素,不能报告游戏完成。只有策划明确不需要视觉素材,或现有已登记素材完全满足需求时,才允许跳过生图;图片生成、处理、登记和接入不因用户没有重复输入“生图”而降级为可选建议。
## 2026-09-15 AGC 统一错误事件、诊断落库与验收反馈
DirectProject、Agent Runtime、Provider、app-server、内置 MCP、命令执行、构建和浏览器试玩的失败必须先转换为统一的 `AgentRuntimeErrorEvent`,再分别投影到用户消息、运行面板和项目诊断文件;业务模块不得自行拼接只有一句“执行失败”的终态文案。统一事件至少包含 `schemaVersion / eventId / clientTurnId / source / stage / code / retryable / occurredAt / elapsedMs / publicText / recoveryHint / detailRef`,其中 `publicText` 是脱敏后的可行动摘要,`detailRef` 指向项目内有界诊断记录;Token、Cookie、URL/query、私钥、宿主绝对路径、原始请求正文和未脱敏 stderr 不得进入对话或用户可见文本。
项目内统一落库目录为 `.agent/runtime/errors/`,事件记录采用幂等 JSONL 或 JSON sidecar;写入失败不能覆盖原始业务错误,但必须在事件中标记 `persistenceFailed`。DirectProject 对话历史必须持久化本轮用户消息、终态错误的安全 assistant 投影和诊断引用,使下一轮能够读取上一轮失败证据。前端只展示 `publicText`,点击详情后按 `detailRef` 读取有界、脱敏的诊断,不直接展示私有 `detail`
`turn/completed` 等待超时必须区分 `idle-timeout``hard-timeout``transport-closed``failed-turn``invalid-terminal``tool-error`;收到内置工具参数错误后必须结束当前工具调用并进入可行动终态,不能继续使用越界的试玩 `attempt` 或无限等待。试玩次数由客户端按当前 `clientTurnId` 持久化分配,模型不能自由递增;超过上限必须返回一次终态并停止回合。
游戏素材完成门必须扫描实际参与构建的 `game/` 源码模块,读取 manifest 的登记身份与相对路径,并把构建后的 URL 映射回登记身份。固定素材路径只能作为兼容候选,不能作为唯一准入。已登记且被真实源码引用、被构建纳入并在浏览器证据中观察到的资源通过;未登记、来源不匹配或只存在于设计规范中的资源继续失败关闭。
验收至少覆盖:普通错误、结构化 app-server failed turn、idle/hard timeout、MCP 参数错误、历史落库失败、脱敏边界、下一轮诊断上下文、源码子模块素材引用、Vite 构建 URL 映射以及试玩次数上限。统一错误事件和诊断落库先于 UI 美化或增加重试预算;不能用延长超时、删除完成门或把失败投影为成功来规避问题。
@@ -344,7 +344,7 @@ UI 使用“批准”和“继续修改”两个文字按钮,分别配 Lucide
项目运行模式通过 `.agent/runtime-mode.json` 持久化。新建策划项目在进入工作台前写入 `design`;“做成游戏”先登记 `design_artifacts` 中尚未登记或登记信息已变化的策划产物,若 manifest 实际发生变化则在同一项目写锁范围内推进一次项目 revision,再写入 `game`。重复切换不重复登记或推进 revision。重新打开项目时通过 `get_design_agent_runtime_mode` 读取模式,完成后一次性挂载对应工作台,不能先挂载 GameAgent 再切回策划。旧项目缺少模式文件但存在策划会话时按 `design` 恢复;明确的 `game` 标记优先于残留策划会话。无模式也无策划会话的项目仍使用游戏工作台。
开发构建的策划工作区页头在“刷新”旁提供“快速准备做成游戏测试”按钮。该入口与策划 Debug 日志共用 `GENARRATIVE_AGC_DESIGN_DEBUG=1` 开关:开关未启用时按钮不显示,命令也不可执行。入口仅进行本地 fixture 和会话状态写入,不调用 Provider;完成后自动刷新文件树与阶段,通过 `design-agent-update` 状态事件同步右侧审批/阶段操作区。随后仍需点击正常的“做成游戏”按钮执行资产登记与运行时切换。
开发构建的策划工作区页头在“刷新”旁提供“快速准备做成游戏测试”按钮。策划 Debug 日志和该入口共用运行时环境变量 `GENARRATIVE_AGC_DESIGN_DEBUG=1`;前端通过 Tauri 查询当前构建是否具备 Debug 入口,只有 Debug 构建且变量启用时显示按钮,命令也不可执行。入口仅进行本地 fixture 和会话状态写入,不调用 Provider;完成后自动刷新文件树与阶段,通过 `design-agent-update` 状态事件同步右侧审批/阶段操作区。随后仍需点击正常的“做成游戏”按钮执行资产登记与运行时切换。
## 15. 策划 Agent reasoning 展示