Merge remote-tracking branch 'origin/master' into feat/jenkins-mac-build
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 17s
Project CI / Backend tests (pull_request) Failing after 19s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 20s
Project CI / Native shell tests (pull_request) Failing after 19s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 19s
Project CI / Frontend tests (pull_request) Failing after 6s
Project CI / AI game creator shell web tests (pull_request) Failing after 12s
Project CI / Repository checks (pull_request) Failing after 12s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 17s
Project CI / Backend tests (pull_request) Failing after 19s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 20s
Project CI / Native shell tests (pull_request) Failing after 19s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 19s
Project CI / Frontend tests (pull_request) Failing after 6s
Project CI / AI game creator shell web tests (pull_request) Failing after 12s
Project CI / Repository checks (pull_request) Failing after 12s
# Conflicts: # docs/project-memory/shared-memory/pitfalls.md
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
# AGC Godot 编辑器插件接入
|
||||
|
||||
> 文档状态:`current`
|
||||
> 规范关系:承接 AGC 通用插件宿主与编辑器适配主规范
|
||||
|
||||
更新时间:`2026-09-20`
|
||||
|
||||
## 目标与边界
|
||||
|
||||
常用操作指导随客户端审核 Skill pack 提供,入口为 `agc-godot-editor`。DirectProject 按需读取 [Skill 入口](../../apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-godot-editor/SKILL.md) 和其常用操作参考;Runtime 的 `godot.editor.execute` 工具说明包含同一参考正文。指导覆盖场景/节点、owner、PackedScene、资源、UI、保存与撤销,不新增专用操作工具,不改变执行授权。
|
||||
|
||||
原文示例在 Godot 4.7.2 标准版 headless 工程验证了节点回读、局部撤销、PackedScene 存读、居中 UI 结构、无缩略图保存重开及只读旧文件写失败时保留内存修改。`save_scene_as` 不返回错误码,指南在重开前核验磁盘包含本次预期变更,不能以旧文件可加载作为保存成功证据。复验时设置 `AGC_GODOT_TEST_EXECUTABLE`,运行 `node --test plugins/agc-godot-editor/native/gdextension/tests/guide-examples.test.mjs`。正式 Ctrl+Z 历史、运行中停止、GUI 缩略图保存及 UI 视觉仍未由该测试验收。
|
||||
|
||||
独立图形环境补验已确认该示例在 800×600、480×800、1280×720 三种实际渲染尺寸下中文和按钮正常显示、容器居中且无裁切;此结果只覆盖示例布局,不代表按钮已接入游戏逻辑或其他 UI 已验收。
|
||||
|
||||
将 Godot 编辑器操控接入现有 AGC PluginHost、EditorAdapter、Runner、内置插件开关、权限审计和 Agent 工具链。Windows x64 的 Godot 4.7 及以上标准编辑器是首个实现目标,实机验收使用 4.7.2;其他平台和 .NET 编辑器不得从该结果推断支持。
|
||||
|
||||
初版工程路径支持 Windows 本地盘符目录;UNC/网络共享路径在准备描述文件前明确拒绝。链接/reparse point 继续按同一文件边界失败关闭。
|
||||
|
||||
DLL 原件随 AGC 安装包放在插件资源目录中;Godot Windows 加载器会在被加载文件旁生成 `~DLL`,因此宿主在 AGC 私有配置目录的运行缓存中按编辑器实例和构建身份准备临时加载副本。AGC 向项目新增一个可扫描的受管 `.gdextension` 描述文件,通过绝对路径引用该实例的加载副本;Godot 可自动生成其同名 `.uid` 伴生文件。DLL 不复制进工程。重新聚焦 Godot 后,由官方文件扫描完成首次加载;不需要用户打开或运行脚本,不创建 EditorPlugin addon,不修改 project.godot 或业务场景文件。编译工具链只属于开发与打包环境,不要求终端用户安装编译器。
|
||||
|
||||
本次包含连接、状态、GDScript 执行和真实回执、断开及资源清理,并验证通过代码读取和修改独立测试场景。专用截图/输入/场景工具目录、云服务、额外 MCP 服务、公开后端 API 和发布上传不在本次范围;通用执行可以调用 EditorInterface,不能把文件生成冒充编辑器内执行。
|
||||
|
||||
## 入口与归属
|
||||
|
||||
- 插件 id 为 `agc-godot-editor`,适配器为 `godot-editor`;命令 `godot.editor.execute`、连接能力 `godot.editor.connection`,DirectProject 工具为 `agc_godot_execute`。复用已有扩展列表和启用开关,不建立平行插件管理页面。
|
||||
- 项目发现沿用现有 Godot 工作区合同:工作区根保持用户选定目录;实际 Godot 根由普通 project.godot 在根或唯一一层子目录中确定。准备描述文件和读取 Godot 缓存只作用于实际 Godot 根,通用文件工具/Runtime 的工作区根不改变。
|
||||
- 平台、内置开关、项目及目标身份必须在执行入口重新检查。插件只能处理宿主传入的当前受控项目,模型不能覆盖项目路径、DLL 路径、端口、令牌或目标实例。
|
||||
- Godot 的插件列表、启动和 Agent 工具目录继续按当前 Godot 项目过滤;Cocos/Unity 沿用各自不按工程类型过滤的合同。前端统一消费宿主列表自动启动三种编辑器插件,不在界面重复推断项目类型。Godot 的项目切换仍撤销旧插件上下文并停止旧实例。
|
||||
- 插件启动先完成项目事件订阅并接收当前受控项目快照,再注册命令和连接能力;命令可见时必须已经具备执行上下文。订阅期间收到的新项目事件优先于迟到的初始快照。
|
||||
- 只连接已打开且唯一匹配真实工程路径的 Godot Editor;校验 PID、进程启动身份、Godot 版本、握手中的工程路径与会话代次。多个候选、非编辑器、路径不符或已退出的进程均拒绝,不启动或关闭用户编辑器。
|
||||
- GUI、DirectProject 和 Agent Runtime 的原生操作统一由长寿命 Runner 持有。项目切换使连接失效,迟到回执不能改变新项目状态。
|
||||
|
||||
## 分发与描述文件
|
||||
|
||||
- Windows 原生构建使用 x64 C11 编译器;MSVC 需先初始化 Visual Studio 的 x64 开发环境,以同时提供 PATH、INCLUDE 与 LIB。ABI 临时存储使用 128 字节、C11 `_Alignas(16)` 显式对齐,不依赖 MSVC C 模式未提供的 `max_align_t`;定向验证运行 `plugins/agc-godot-editor/native/gdextension/build.ps1 -Compiler cl.exe`。
|
||||
|
||||
- 安装资源布局为 `plugins/agc-godot-editor/native/gdextension/bin/win-x64/agc_godot_editor.dll`,邻接元数据记录协议、构建身份和 DLL SHA256。开发模式允许宿主提供仓库插件目录中的同结构产物;RPC 不接受自定义 DLL 候选。
|
||||
- 缓存根仅由宿主提供,为其私有配置目录下的 `godot-editor-runtime`;按 `PID + startedFileTime + buildId` 隔离,所有路径分量受控且拒绝链接/reparse point。复制前验证安装原件及元数据,缓存已有文件必须匹配来源、归属及 SHA,不能加载被替换的同名文件。受管描述同时保留原件与加载副本身份,重启恢复不得把工程给出的任意 DLL 路径当作受信任来源。
|
||||
- 实际模块核验同时覆盖加载副本及 Godot 在同目录生成的精确 `~agc_godot_editor.dll`,要求规范化路径和 DLL 字节身份一致。确认原生卸载后,只清理本实例、本构建、内容未变的缓存文件;不能跨编辑器删除或复用影子副本。安装位置更新和实例 PID 重用都必须重新验证。
|
||||
- 原生扩展只加载自身受信任包内的实现;GDScript 桥源码编译进 DLL,目标工程不能替换引导脚本。保留 Godot 官方 ABI 来源及 MIT 许可;生成的 DLL、缓存和机器路径不提交。
|
||||
- 描述文件固定为实际 Godot 根下的 `agc-editor-bridge.gdextension`,带 AGC 所有权标记和构建身份。首次使用可创建,内容一致时不重写;安装路径或构建身份变化时只更新本插件拥有的文件。已有同名非受管文件、链接/reparse point 或未知内容必须拒绝覆盖。
|
||||
- `.agent`、点号目录和 `.gdignore` 路径不会被 Godot 自动扫描,因此描述文件不能放在那里。会话发现文件仅放在 `.godot/agc/` 缓存内,不进入 manifest、对话或日志;校验缓存各级目录没有链接跳转。
|
||||
- 描述文件及引擎自动生成的 `.uid` 按同一归属管理:创建描述文件前已有孤立同名 UID 时拒绝接管;扫描生成后在 `.godot/agc/` 记录描述内容及 UID 内容指纹。重连、升级和清理核对此记录,仅删除原内容未变的本插件伴生文件;记录丢失、用户改动或未知同名文件时保留并报告,不把“格式合法”当作删除授权。
|
||||
- connect/execute 可以准备受管描述文件,并尝试把经过验证的目标编辑器窗口置前触发扫描;若系统不允许聚焦或握手未就绪,返回明确的未派发错误,提示重新聚焦后连接。连接重试不重放业务代码。
|
||||
- 升级、断开和禁用时先通过有效旧连接停用内存桥/卸载原生扩展,再清理与本会话匹配的受管描述文件和会话缓存。用户改动过的文件不删除;无可信握手时不能把删除文件当作已卸载。编辑器已退出时允许清理已确认归属的本地痕迹。
|
||||
- 安装目录可能只读;插件不得向 DLL 所在目录写令牌、状态或日志。
|
||||
- 安装位置/构建身份升级必须先确认旧扩展已卸载,再原子更新受管描述文件。旧 DLL 仍被目标进程加载、shutdown 结果不明或旧会话无法核实时,保留痕迹并返回可诊断错误,不用替换引用冒充完成升级。
|
||||
- 正式描述文件禁用自动 DLL 热重载;首次聚焦发现加载不受此设置影响。版本/路径更新走上述受控卸载和新加载,防止引擎自动热重载越过正在执行或待核对的任务。
|
||||
|
||||
## 执行协议与结果
|
||||
|
||||
引擎端协议固定为 `agc.godot.editor.v1`。本机回环 TCP 的 JSONL 每个请求包含 `protocol`、正整数 `id`、`generation`、`token`、`method` 和 `params`;方法为 `status`、`execute`、`shutdown`。会话缓存字段为 `protocol`、`buildId`、`pid`、`startedFileTime`(字符串)、`generation`、`projectPath`、`version`、`port`、`token`。文件名为 `editor-bridge-<pid>.json`,单文件最多 64 KiB。每次加载产生随机代次和令牌,端口只监听 127.0.0.1。
|
||||
|
||||
每条响应回显 `protocol/id/generation/pid/projectPath/buildId`,并包含 `result`;执行的 result 沿用 AGC 结构:`ok`、`status`、`dispatched`、`retryAllowed:false`、成功 `result` 或失败 `error:{code,message}`,可附有界日志。状态为 `completed`、`failed`、`needs-reconciliation`。连接状态沿用 `EditorConnectionInfo`,可增加代次、就绪与版本诊断字段。
|
||||
|
||||
`execute.params` 固定为 `{code:string,timeoutMs:integer}`;`timeoutMs` 为 1..60000 的剩余预算。`status.params` 和 `shutdown.params` 均为空对象。status 的 result 为 `{connected:true,pid,projectPath,version,generation,buildId,executing:boolean}`。shutdown 在没有在途执行时返回 `{accepted:true,status:"shutting-down"}`,仅表示停机请求已受理;桥在发送该回执后移除自己的会话缓存、关闭监听并卸载扩展。宿主必须继续校验同一目标进程的原生模块已卸载、原代次会话消失,才允许删除/替换描述文件或投影为断开完成。拒绝停机返回 `{accepted:false,error:{code,message}}`,不能把 accepted 当作卸载完成回执。
|
||||
|
||||
- GDScript 是可含 return/await 的函数体,非空、不含 NUL,最多 128 KiB;请求和回执最多 2 MiB,日志有界。执行运行于编辑器主线程,临时桥的 owner=null,不加入用户场景。
|
||||
- 只有真实执行完成且没有捕获到脚本运行错误才返回 completed。编译失败和确定运行失败返回可修复诊断,不以 nil 返回值伪装成功;空值返回本身仍是合法结果。执行日志不暴露令牌或宿主凭据。
|
||||
- 使用同一总期限覆盖发现、准备、连接、发送和读取;并发写执行立即拒绝,不积压截止后可能被派发的代码。原生服务不自动重发 execute。
|
||||
- 发送前的参数/路径/权限/平台/未连接错误为 `failed, dispatched:false`;发送后的超时、断线、损坏或身份不符回执为 `needs-reconciliation, dispatched:true, retryAllowed:false`。
|
||||
- 主线程无限循环不能承诺硬中止。async 未返回或运行状态不明时必须保留不确定阻断,不能因重连、插件启停、切换工程或 Runner 自动重启消除。
|
||||
- await 全程保持单执行占用;未完成或结果不确定期间,shutdown/禁用/切换只能禁止新增执行,不能卸载正在使用的桥或清除 fence。待状态已知且无在途执行后再完成资源清理;不确定时返回明确待核对状态。
|
||||
- 复用现有执行回执确认机制:Runner 派发前持久化请求身份;调用者确认完整匹配的终态回执后才能清理 pending。丢失最后一跳回执保持阻断,只有核对后退出全部 AGC/Runner 并重新打开才能恢复。
|
||||
- fence 的持久范围是同一完整宿主会话:自动重启 Runner、新窗口、JS 插件重载均不能清除。只有用户已核对编辑器状态、全部旧 AGC/Runner 退出,且新 GUI 同时独占现有 GUI 参与锁与 Runner 实例锁时,才能沿用现有恢复入口开始新的宿主会话;该规则与 Unity 一致,不建立另一套自动 reconcile。
|
||||
|
||||
## 契约与兼容
|
||||
|
||||
不修改服务端 API、DTO 结构、SpacetimeDB schema 或游戏持久业务数据。已有项目命令目录增加 `godot.editor.execute`,默认权限为 confirm,Rust 与 TypeScript 镜像保持一致;实际执行继续服从当前运行档及项目权限策略。通用 EditorAdapter 文档允许编辑器适配器按自身已授权合同维护受管引导文件;Cocos/Unity 的不写工程连接行为保持原约定。内置开关和审计继续使用已有存储。现有项目没有描述文件时按首次连接创建,不引入历史兼容路径。
|
||||
|
||||
## 验收
|
||||
|
||||
| 条款 | 必须取得的证据 |
|
||||
| --- | --- |
|
||||
| 包与来源 | 原生 DLL 构建、官方 ABI/许可、源码内无机器路径;staging 校验 DLL 及元数据只进入 Windows x64 资源 |
|
||||
| 受管文件 | 首次生成、幂等、安装路径更新、非受管文件冲突、路径穿越/链接拒绝、正常卸载及异常保留 |
|
||||
| 目标身份 | 根/一层 Godot 项目,PID/启动身份/工程/代次/构建身份校验;错误目标拒绝 |
|
||||
| 宿主接入 | manifest、启停、开关、权限、Runner RPC、DirectProject/Runtime 工具和项目切换定向测试 |
|
||||
| 执行 | 42、场景读取与独立场景修改/撤销、nil、编译错、运行错、async、有界日志和拒绝并发 |
|
||||
| 不确定结果 | 发送前后失败分类、超时/断线/损坏回执、ACK 归属、插件及 Runner 重启不解除阻断 |
|
||||
| 实机 | 已打开的独立 Godot 4.7.2 工程中无需脚本 UI 操作的首次加载、执行、卸载、重新连接;DLL 保持安装资源布局且原有工程文件哈希不变 |
|
||||
| 仓库门禁 | 相关 Rust/JS/前端定向测试、类型检查、文档索引、编码和 git diff --check;真实编辑器、打包资源与安装包 UI 的结果分别说明 |
|
||||
|
||||
## 已确定的产品选择
|
||||
|
||||
用户明确选择 DLL 原件留在 AGC 安装目录,并确认每个编辑器的临时加载副本放 AGC 缓存,工程内不复制 DLL。正式实现已按下列证据重新验收,前置 PoC 不作为交付依据。
|
||||
|
||||
## 本地验收结果(2026-09-20)
|
||||
|
||||
Windows x64、Godot 4.7.2 标准编辑器的本地实现验收通过。证据保存在 gitignored 的 `.app/diagnostics/`,不随源码提交;复验入口保留在插件源码和现有测试中。下列测试集合存在交叉,不相加为总用例数。
|
||||
|
||||
| 验收面 | 已取得的证据 |
|
||||
| --- | --- |
|
||||
| 原生服务与文件边界 | `godot-cache-tests-final.log`:30 项通过;覆盖受管文件及 UID、目标身份、缓存来源/哈希、安装更新、实例隔离、链接拒绝、异常保留和不确定状态 |
|
||||
| 真实引擎原生执行 | `godot-native-final-tests.log`:12 项通过、0 跳过;真实 headless Godot 验证同步/async、编译/运行错、超时占用、有界输出、代次拒绝及卸载重连 |
|
||||
| 插件与宿主 | `godot-plugin-js-final.log`:Cocos/Unity/Godot JS 共 31 项通过;`godot-shell-final-tests.log`:Godot 过滤 29 项通过;`godot-host-final-tests.log`:PluginHost 16 项通过,含切项目撤销旧上下文、派发前取消及派发后回执丢失 |
|
||||
| 共享权限与前端 | `godot-web-final-tests.log`:28 项通过;Rust 命令权限契约通过,AGC typecheck 通过;Godot 命令继续使用默认 confirm |
|
||||
| 现有宿主回归 | EditorAdapter、Unity、Runner 重启 fence 和缺失 endpoint 清理的定向测试通过;构建脚本、workspace、CI 路由和 rustfmt hook 定向测试通过 |
|
||||
| 原生 GUI | `godot-plugin-verified-20260920/evidence/native-gui-smoke.log`:同一编辑器内返回 42/null、读取场景、增加节点后撤销、await、编译/运行错误、卸载、重连及再次卸载成功 |
|
||||
| 多实例与只读安装 | 同目录 `parallel-live-modules.json`、`parallel-verified-summary.json`:两个编辑器同时使用不同缓存路径的官方 `~DLL`,均返回 42、确认卸载,安装原件只读且未变 |
|
||||
| 安装位置更新 | 同目录 `install-location-smoke.log`:旧连接卸载、新安装来源生成新代次和引用、返回 42、清理两代缓存;两个安装来源及原有工程文件均未变 |
|
||||
| 真实 Runner | 同目录 `runner-smoke-psapi.log`:standalone Runner 经正式执行/ACK 路径取得真实 Godot 回执,拒绝错误 ACK,接受正确 ACK,完成场景修改/撤销及断开;`runner-restart-before.log`、`runner-restart-after.log`:新 Runner 无需重新连接即可恢复原归属并清理旧桥 |
|
||||
| 资源与收尾 | 完整 Windows feature debug 构建通过;当前 `src-tauri/resources/plugins/agc-godot-editor` 仅含 manifest、入口、DLL、元数据、许可和来源六个文件,其 DLL 与实机测试一致;同目录 `final-cleanup.json` 确认工程及安装来源哈希未变、自建 GUI 正常退出 |
|
||||
|
||||
正式 Runner smoke 使用安装资源布局下的 debug 可执行文件,不等同于 NSIS 安装包 UI 验证。本次未运行安装包 UI smoke、真实 Provider 生成或远端 CI,未制作发布包或上传发布;其他 Godot 版本、.NET 编辑器与其他平台仍须各自验收。AGC 全量聚合门禁不在上述定向结果中。
|
||||
|
||||
### 复验入口
|
||||
|
||||
从仓库根运行,原生构建要求 Windows x64 C 编译器。先把 `AGC_GODOT_TEST_EXECUTABLE` 设置为待验证的标准 Godot 编辑器绝对路径;未设置时 headless 测试会跳过,不能视为实机通过。
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -File plugins/agc-godot-editor/native/gdextension/build.ps1
|
||||
node --test plugins/agc-godot-editor/native/gdextension/tests/native-smoke.test.mjs
|
||||
cargo test --locked --manifest-path plugins/agc-godot-editor/native/godot-editor-bridge/Cargo.toml
|
||||
npm run agc:plugins:test
|
||||
cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --features cocos-editor-execute,unity-editor-execute,godot-editor-execute godot
|
||||
cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --features cocos-editor-execute,unity-editor-execute,godot-editor-execute plugin_host
|
||||
npx vitest run apps/ai-game-creator-shell/tests/pluginHost.test.ts packages/shared/src/contracts/gameCreationApp.test.ts --threads=false
|
||||
npm run typecheck --workspace @genarrative/ai-game-creator-shell
|
||||
npm run check:doc-index
|
||||
npm run check:encoding
|
||||
git diff --check
|
||||
```
|
||||
|
||||
真实 GUI 使用 `native/godot-editor-bridge/examples/live_smoke.rs`;安装位置变更使用同目录的 `install_location_smoke.rs`。二者要求显式传入自有可丢弃工程、已打开编辑器 PID、可信安装 DLL、工程外私有缓存及 `--allow-fixture-mutations`,具体参数见源码用法。多实例验证分别传入两个工程和 PID,通过 `live_smoke` 的 `--hold-ms` 让加载时间重叠,同时核验原生模块路径。Runner 复验须经正式长度前缀 RPC、完整 ACK 和私有配置恢复路径,不能用原生示例替代 Runner 证据。
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
## 目标与非目标
|
||||
|
||||
常用操作指导随客户端审核 Skill pack 提供,入口为 `agc-unity-editor`。DirectProject 按需读取 [Skill 入口](../../apps/ai-game-creator-shell/src-tauri/resources/agc-skills/agc-unity-editor/SKILL.md) 和其常用操作参考;Runtime 的 `unity.editor.execute` 工具说明包含同一参考正文。指导覆盖查询、对象/组件、Prefab、资源、UI、保存与撤销,不新增专用操作工具,不改变执行授权。
|
||||
|
||||
指南示例在独立 Unity 6000.3.7f1 Mono 工程经真实 Attach 验证,覆盖查询、创建/修改、Undo、Prefab override 保存重开、Canvas 及播放切换;不据此推断 UI 视觉、第三方包或其他版本已验收。复验入口为 `native/unity-editor-bridge/tests/guide_examples.rs`:按文件头显式设置 fixture 的 helper、项目与 PID 环境变量后,运行 `cargo test --locked --manifest-path plugins/agc-unity-editor/native/unity-editor-bridge/Cargo.toml --test guide_examples -- --ignored --nocapture`;它直接提取随包指南代码,而非维护示例副本。
|
||||
|
||||
将 DotCraft.Unity 0.4.3 对应的 Attach 执行核心接入 AGC 现有插件系统,使当前 Unity 项目能够探测编辑器、建立连接、执行 C# 并获得真实结果。复用既有扩展列表、内置插件开关、权限、审计、EditorAdapter 和 Agent 工具通路。
|
||||
|
||||
首期只支持 Windows x64 的 Unity Mono Editor。连接不修改项目文件、不安装 UPM 包、不启动或关闭用户编辑器。不引入 DotCraft.Harness、另一套 Agent Runtime、MCP 服务或聊天界面;截图、热重载专用工具、macOS、Linux 和 Unity CoreCLR 不属于本次交付。
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
# 【技术方案】AGC 后端框架整理与演进路线
|
||||
|
||||
更新时间:`2026-09-18`
|
||||
|
||||
## 结论
|
||||
|
||||
可以整理,而且不需要从零重写。当前 AGC 已经具备一套可复用的后端骨架,但它还不是一个可以直接部署的统一 AGC backend:共享 Runtime 目前是库级内核,本地 Tauri 持有项目执行事实,`server-rs` 持有云端平台业务,三者之间还需要 application adapter 和契约收口。现有骨架包括:
|
||||
|
||||
- `server-rs/crates/agent-runtime-core` 是不依赖产品和框架的 Runtime 执行内核。
|
||||
- `server-rs/crates/agent-runtime-orchestration` 是任务图、依赖波次和修复影响计算。
|
||||
- `server-rs/crates/platform-agent` 是 AGC 壳独立 path dependency 使用的游戏任务图、角色和游戏产物规则适配层;它被 `server-rs` 默认 workspace 排除,不能反向成为通用 Runtime 内核。
|
||||
- `apps/ai-game-creator-shell/src-tauri/src/agent`、`project`、`runner` 是本地 AGC 执行宿主。
|
||||
- `server-rs/crates/module-*`、`spacetime-module`、`spacetime-client`、`api-server` 和 `platform-*` 已覆盖领域、持久化、HTTP/BFF 和外部服务适配。
|
||||
|
||||
现在的主要问题是能力已经分布在多个入口,缺少一个对开发者可见的 AGC backend application facade 和统一的跨边界状态合同。目标应是整理边界和调用方向,逐步收拢入口,不新建第二套 Agent Runtime、第二套会话库或第二个业务真相。
|
||||
|
||||
## 目标
|
||||
|
||||
AGC backend 对外提供一个稳定的“项目开发运行时”能力面:接收用户意图,绑定项目身份,规划或执行 Agent Run,调用受控工具和平台能力,持久化可恢复状态,发布可观察事件,并把本地项目产物或云端资源结果返回给客户端。客户端本地宿主通过共享契约和平台 adapter 与云端交互,不直接把 `module-*` 当作本地 IO 层。
|
||||
|
||||
框架需要同时支持两种执行位置:
|
||||
|
||||
1. **本地宿主执行**:Agent 需要直接读写用户项目、启动本地进程、访问本地预览或编辑器时,在 Tauri Rust 宿主中执行。
|
||||
2. **云端控制面执行**:认证、账户、模型目录、编辑器资源、异步生成、计费、快照上传和公开 API 在 `server-rs` 中执行。
|
||||
|
||||
两者共享领域合同、Runtime 语义和错误分类,但不共享不适合跨进程的本地副作用实现。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不把 Tauri 本地文件、进程、浏览器或 Codex app-server 搬进云端。
|
||||
- 不把 `api-server` 变成任意代码执行器,也不让前端直接访问 SpacetimeDB。
|
||||
- 不引入 LangChain、AutoGen、OpenAI Agents SDK sidecar 或另一套调度器作为 AGC 核心。
|
||||
- 不恢复已退役的旧创作入口、旧作品架或旧后端服务。
|
||||
- 不在本次整理中改变现有公开 API、SpacetimeDB 表字段、OpenAPI 或本地项目文件格式。
|
||||
|
||||
## 逻辑分层
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
UI[AGC Web UI / Tauri commands]
|
||||
HOST[AGC Local Host\nTauri Rust]
|
||||
CORE[Shared Agent Runtime\nagent-runtime-core]
|
||||
ORCH[Task Graph\nagent-runtime-orchestration]
|
||||
CONTRACT[Shared contracts\nshared-contracts]
|
||||
DOMAIN[Cloud domain modules\nmodule-*]
|
||||
API[Cloud Control Plane\napi-server Axum]
|
||||
DATA[Data plane\nspacetime-client -> SpacetimeDB]
|
||||
PLATFORM[Platform adapters\nplatform-llm / image / oss / auth / ...]
|
||||
PROJECT[Local Project Plane\nfiles / manifest / JSONL / locks / checkpoints]
|
||||
|
||||
UI --> HOST
|
||||
UI --> API
|
||||
HOST --> CORE
|
||||
HOST --> ORCH
|
||||
HOST --> CONTRACT
|
||||
HOST --> PROJECT
|
||||
API --> CONTRACT
|
||||
API --> DOMAIN
|
||||
API --> DATA
|
||||
API --> PLATFORM
|
||||
PLATFORM --> DATA
|
||||
```
|
||||
|
||||
这张图是调用方向,不表示所有层都必须变成新的 crate。当前 `api-server` 不依赖或执行本地 `agent-runtime-core`/`agent-runtime-orchestration`;如果未来明确引入云端 Runner,再单独增加云端 Runtime host,不把本地项目 Run 事实迁移到 API handler。现有目录已经能承载大部分边界,先用 facade、trait 和契约测试固化边界,再决定是否需要物理拆 crate。
|
||||
|
||||
### 1. Shared Runtime kernel
|
||||
|
||||
`agent-runtime-core` 只负责通用运行事实和确定性决策:Run、Action、Observation、Tool execution、Completion、Recovery、Provider contract、Capability registry 和 Runtime event。它不能依赖 Tauri、Axum、SpacetimeDB、具体提示词、权限实现或 AGC 业务表。
|
||||
|
||||
`agent-runtime-orchestration` 只负责任务图:Agent catalog 校验、依赖关系、ready task、wave 和下游修复影响。它不持有线程、Provider、工具、数据库或产品持久化。
|
||||
|
||||
这两层是 AGC 与其他未来 Agent 宿主共享的内核,不能把 AGC 特有规则反向塞回去。
|
||||
|
||||
### 2. Domain and contract layer
|
||||
|
||||
领域规则留在现有 `module-*`:
|
||||
|
||||
| 领域 | 当前承载位置 | 负责内容 |
|
||||
| --- | --- | --- |
|
||||
| 主站画布 Agent 会话 | `module-editor-agent` | 画布会话归属、标题、消息元数据、领域校验;不是 DirectProject 本地会话事实源 |
|
||||
| Runtime / AI task | `module-runtime`、`module-ai` | Runtime 设置、模型目录、AI task 状态和输入校验 |
|
||||
| 编辑器项目和资源 | `module-assets`、`spacetime-module` 相关 storage | 项目、资源、版本绑定、生成任务和事务规则 |
|
||||
| 认证和账户 | `module-auth`、`platform-auth` | 身份、会话和认证平台适配 |
|
||||
|
||||
跨端 DTO、公开请求/响应和错误码留在 `shared-contracts`。目标边界是领域层不发 HTTP、不读本地文件、不调用 LLM、不直接拿 OSS 客户端;当前部分 `module-*` 仍通过 feature 或 service 依赖平台 crate,这属于后续收口债务,不应继续扩大。
|
||||
|
||||
### 3. Local AGC host
|
||||
|
||||
`apps/ai-game-creator-shell/src-tauri` 是本地 backend,不只是 UI 的 IPC 薄壳。普通 Tauri command 只负责鉴权、确认和 UI bridge;真正的 LLM、工具循环、队列和恢复由独立的 `--agent-runner` 执行者完成。它负责:
|
||||
|
||||
- `agent`:DirectProject、Runtime driver、Runtime protocol、工具桥、Codex app-server/CLI、Provider handoff 和恢复。
|
||||
- `project`:项目根边界、manifest、JSONL 会话、checkpoint、资源编辑、文件读写、项目写锁和版本替换。
|
||||
- `runner`:跨窗口共享的 Agent Runner、loopback 协议、owner/watchdog、连接和生命周期。
|
||||
- `browser`、`preview`、`process_session`:受控预览、浏览器试玩、本地进程会话及证据。
|
||||
- `editor_adapter`、`plugin_host`:编辑器桥接和插件能力,不向 Agent 暴露原始 pipe、句柄或未绑定项目身份的执行面。
|
||||
- `platform_session`、`http_client`:平台身份/凭据和云端 API 调用。
|
||||
|
||||
本地宿主可以复用共享 Runtime crate 和 `platform-agent`,但项目文件、资源权限、完成门、Prompt Bundle、DirectProject/Planning V2 和 Runner IPC 都属于 AGC adapter/host,不能迁回 Runtime core。
|
||||
|
||||
`main.rs`、`agent.rs` 和命令注册只应是组合层。新的业务规则应进入对应功能域或 Runtime contract,不能继续堆进入口文件。
|
||||
|
||||
### 4. Cloud control plane
|
||||
|
||||
`api-server` 是云端 HTTP/SSE/BFF 和跨模块编排层。它不持有本地 `--agent-runner` 的项目 Run 事实;除非未来明确引入云端 Runner,否则云端只持有平台业务、异步 operation 和可公开投影。现有入口包括:
|
||||
|
||||
- `/api/ai/tasks`:AI task 生命周期。
|
||||
- `/api/editor/*` 与 `/api/external/v1/editor/*`:编辑器项目、资源和生成操作。
|
||||
- `/api/agc/project-snapshots/*`:AGC 项目文件与 manifest 快照上传。
|
||||
- `/admin/api/agc-models`:AGC 模型目录管理。
|
||||
- 编辑器 Agent 会话、外部生成任务、运行设置和诊断/追踪相关接口。
|
||||
|
||||
这些路由可以继续按领域模块存在,但需要分成两个语义清晰的 facade:
|
||||
|
||||
- **本地 host coordinator**:在 Tauri 宿主内统一 `start_run`、`resume_run`、`cancel_run`、`get_run` 和本地事件投影,事实源仍是项目 `.agent/runtime/**` 与 Runner。
|
||||
- **云端 application service**:在 `api-server` 统一 `submit_operation`、`get_operation`、`reconcile_operation`、AI task、外部生成和快照调用,复用现有领域 service、队列和 SpacetimeDB procedure。
|
||||
|
||||
两者可以共享 DTO、错误分类和 correlation 字段,但当前不新增统一的云端 `/runs` API,也不把本地 Run 伪装成云端持久化记录。
|
||||
|
||||
### 5. Platform adapters
|
||||
|
||||
LLM、图片/音频/视频、OSS、认证、语音和编辑器外部服务继续放在 `platform-*`。适配器只返回受约束的 Provider/Job/Asset 结果;重试、幂等、扣费、结果落库和公开错误映射由上层 application/domain contract 决定。
|
||||
|
||||
## 数据真相和存储边界
|
||||
|
||||
### 本地项目平面
|
||||
|
||||
以下事实属于当前授权项目,由本地宿主负责读写和恢复:
|
||||
|
||||
- 项目源文件、`manifest`、版本和资源绑定的本地投影。
|
||||
- `.agent` 下的会话 JSONL、Runtime journal、action/observation、checkpoint 和诊断摘要。
|
||||
- 项目写锁、Runner owner、进程会话、预览注册和浏览器证据。
|
||||
|
||||
本地写入必须经过项目身份校验、项目根边界、普通文件/reparse point 检查、写锁和现有权限策略。云端 API 不直接读写用户项目目录。
|
||||
|
||||
### 云端业务平面
|
||||
|
||||
以下事实属于服务端:
|
||||
|
||||
- 登录身份、refresh session、钱包/计费和模型目录。
|
||||
- 编辑器项目、资源、版本绑定、生成任务、任务事件和结果引用。
|
||||
- 错误报告、追踪事件和公开 read model;快照当前以受控 OSS manifest/对象键、审计和诊断能力为主,不假定已经存在 SpacetimeDB 快照元数据表。
|
||||
|
||||
当前 SpacetimeDB 没有通用的 AGC Agent Run/Action/Event/Confirmation/Plan 表;`runtime_snapshot` 不能直接当作 AGC Agent Runtime 持久化。若未来把 Run 迁到云端,必须另立清晰的持久化合同;本路线默认本地 `.agent/runtime/**` 继续是 DirectProject 的事实源。
|
||||
|
||||
SpacetimeDB 表、reducer、procedure 和事务 adapter 只留在 `spacetime-module`;服务端访问统一走 `spacetime-client` facade。
|
||||
|
||||
### OSS / 大对象平面
|
||||
|
||||
会话正文、项目快照文件和媒体大对象继续按现有合同进入 OSS;SpacetimeDB 只保存归属、对象键、版本、状态和必要摘要。OSS key 必须由服务端根据已验证的身份/项目 ID 生成,客户端不能把任意对象键当作归属证明。
|
||||
|
||||
## 统一执行合同
|
||||
|
||||
本地 Run 和云端异步操作可以有不同实现,但公开状态应映射到同一组语义:
|
||||
|
||||
```text
|
||||
intent
|
||||
-> accepted
|
||||
-> queued
|
||||
-> running
|
||||
-> waiting (user / confirmation / provider retry / external job)
|
||||
-> succeeded | failed | cancelled | needs-reconciliation
|
||||
```
|
||||
|
||||
- `accepted` 表示请求已经被持久化并得到稳定身份,不表示 child 已经开始执行。
|
||||
- `running` 必须由真正持有执行权的 Runner/worker 写入 started 事实后才能公开。
|
||||
- `waiting` 必须有可恢复的原因和下一步信息,不能由前端计时器伪造。
|
||||
- 外部结果未知、不能安全重放时进入 `needs-reconciliation`,禁止自动重放或伪造成功。
|
||||
- 取消、失败、恢复、重试和最终回复都必须保留同一 Run/operation 身份及可追踪的 event 顺序。
|
||||
|
||||
现有 `RunStatus`、`ActionStatus`、`ObservationStatus`、AI task 状态、ExternalGenerationJob 状态和项目生成账本可以继续各自保留;application facade 只提供上述语义映射,不强行把它们合并成一张跨域表。
|
||||
|
||||
## 核心调用链
|
||||
|
||||
### 本地 DirectProject
|
||||
|
||||
```text
|
||||
UI
|
||||
-> Tauri command
|
||||
-> DirectProject / Runtime driver
|
||||
-> Runner / Codex app-server
|
||||
-> Runtime tool policy
|
||||
-> project owner + write lock
|
||||
-> local files / manifest / JSONL / checkpoint
|
||||
-> Runtime event projection
|
||||
-> UI
|
||||
```
|
||||
|
||||
工具执行失败时,属于可修复的构建、验证或试玩错误,可以把脱敏上下文反馈给同一 LLM 回合并有界重试;鉴权、项目身份、权限、传输断开、取消、历史损坏和付费操作不确定等边界必须失败关闭。
|
||||
|
||||
### 云端资源/生成操作
|
||||
|
||||
```text
|
||||
AGC tool or UI
|
||||
-> api-server route
|
||||
-> auth + project ownership + idempotency
|
||||
-> module-* validation
|
||||
-> spacetime-client facade
|
||||
-> durable operation / queue
|
||||
-> platform-* provider
|
||||
-> OSS result
|
||||
-> SpacetimeDB result projection
|
||||
-> API polling/SSE
|
||||
```
|
||||
|
||||
计费、外部 job、结果安装和重试必须围绕 durable operation 编排,不能把 Provider 返回成功当成业务完成的唯一证据。
|
||||
|
||||
### 项目快照
|
||||
|
||||
```text
|
||||
Local project snapshot
|
||||
-> authenticated /api/agc/project-snapshots/*
|
||||
-> body-size and file contract checks
|
||||
-> object storage
|
||||
-> snapshot metadata / diagnostic projection
|
||||
```
|
||||
|
||||
快照上传用于备份和诊断,不改变本地项目作为开发态文件真相的职责。
|
||||
|
||||
## 边界规则
|
||||
|
||||
1. **Runtime 与宿主分离**:核心 Runtime 只做状态决策;Tauri host、Runner 和 server worker 提供执行、持久化、时间和能力实现。
|
||||
2. **领域与 IO 分离**:`module-*` 不依赖 Axum、Tauri、Provider 或 OSS;HTTP handler 不复制领域校验。
|
||||
3. **文件系统单一入口**:任何 Agent 文件读写都经过项目 scope、写锁和受控工具;不能在 API 或前端加旁路写入。
|
||||
4. **外部服务单一入口**:LLM、生成、OSS、认证等外部调用只经 `platform-*`,不能在业务 handler 里散落裸 HTTP。
|
||||
5. **数据访问单一入口**:`api-server` 和本地需要的云端调用使用 `spacetime-client` facade,不直接拼 SpacetimeDB 请求。
|
||||
6. **前端只消费投影**:前端不推导正式业务状态,不直接访问本地项目数据库或 SpacetimeDB。
|
||||
7. **身份与凭据分离**:同一身份的 access token 轮换不使在途 Run 失效;换号、退出或 origin 变化必须使旧 Run 停止后续副作用。
|
||||
8. **可恢复优先**:持久动作、异步生成、Runner 续跑、外部结果回填和最终状态写入必须有稳定 ID、版本/CAS 或幂等键。
|
||||
|
||||
## 当前缺口
|
||||
|
||||
### 缺少 AGC application facade
|
||||
|
||||
能力散落在 `agent`、`editor_project.rs`、`external_editor_api.rs`、`ai_tasks.rs`、快照路由和生成队列中。它们各自可用,但调用方难以判断一项用户意图应该走本地 Run、云端 task 还是外部 generation operation。
|
||||
|
||||
**整理方向**:先建立逻辑 facade 和 capability catalog,保留现有路由作为 adapter;只有当两个以上入口共享同一业务流程时,才下沉 application service。
|
||||
|
||||
### 本地和云端状态语义重复
|
||||
|
||||
本地 Runtime、AI task、ExternalGenerationJob 和项目资源 operation 都有自己的 accepted/running/failed/retry 表达。状态不能强行合表,但需要统一事件字段:`subject_id`、`run_or_operation_id`、`stage`、`revision`、`occurred_at`、`retryable`、`public_summary` 和 `correlation_id`。
|
||||
|
||||
### 组合层偏重
|
||||
|
||||
AGC Tauri 的 `main.rs`、`agent.rs` 和部分命令模块已经包含大量注册与兼容出口。后续工作应按功能域继续拆分,但每次只移动一个边界并保持公开导出、命令名称和测试合同不变。
|
||||
|
||||
### 云端大文件模块偏重
|
||||
|
||||
`api-server` 的编辑器项目、External Editor API 和生成队列承担了较多请求解析、领域校验、计费、队列和结果投影。后续应把领域输入校验和 operation service 继续下沉到 `module-*`/application 层,handler 只保留鉴权、解析、调用和响应映射。
|
||||
|
||||
### 契约目录需要集中
|
||||
|
||||
AGC 本地 IPC、Runner 协议、Runtime snapshot、云端 API、SpacetimeDB procedure 和 OSS key 规则目前分布在代码及专题文档中。应建立一个只读的 AGC capability/contract catalog,列出入口、调用方、状态源、权限、幂等键、恢复策略和证据位置;它不是新的运行时注册表。
|
||||
|
||||
## 演进路线
|
||||
|
||||
### 第一阶段:框架定界
|
||||
|
||||
- 将本文件作为 AGC backend 主规范。
|
||||
- 维护 capability catalog,给每个现有入口标注 `local-host`、`cloud-control-plane` 或 `shared-runtime`。
|
||||
- 为本地 Run、云端 task、外部 generation 和快照上传补齐统一 correlation/idempotency 字段的映射表。
|
||||
- 不改 API、schema 和文件格式。
|
||||
|
||||
### 第二阶段:统一 application facade
|
||||
|
||||
- 在现有 `api-server` modules 之上增加薄的 AGC application service/facade。
|
||||
- 先收拢 Run 查询、事件查询、取消、恢复和 operation reconcile;生成业务仍复用现有队列和平台适配器。
|
||||
- 本地 Tauri 侧将 DirectProject、Runtime driver 和 Runner 的入口分成 `command adapter -> application coordinator -> runtime host` 三层。
|
||||
- 用契约测试锁定调用方向,防止前端或 handler 绕过 domain/client facade。
|
||||
|
||||
### 第三阶段:持久化与恢复收口
|
||||
|
||||
- 为本地 Runtime journal、云端 AI task、外部 generation job 和项目资源 operation 逐项定义 accepted/running/waiting/terminal 的写入点。
|
||||
- 补齐重启、重复提交、迟到回调、同身份 token 轮换、换号和 unknown outcome 的恢复测试。
|
||||
- 继续保持本地项目文件与云端业务数据的双平面,不做隐式云同步。
|
||||
|
||||
### 第四阶段:能力插件化
|
||||
|
||||
- 以 capability contract 接入编辑器 adapter、图像/音频/视频生成、浏览器试玩和 UI workflow。
|
||||
- 每个能力声明输入约束、权限、写入范围、计费/异步语义、产物身份和验证证据。
|
||||
- Cocos 等编辑器桥接继续通过通用 plugin host,不把编辑器进程控制细节泄漏给 Runtime core。
|
||||
|
||||
### 第五阶段:观测和发布门禁
|
||||
|
||||
- 统一 Run/operation 的 request ID、correlation ID、client marker、错误分类、诊断事件和公开摘要。
|
||||
- 建立 AGC backend smoke:健康检查、鉴权、最小 Run、工具拒绝、快照体积边界、异步生成轮询和恢复。
|
||||
- 把真实 Provider、登录态、Windows Runner 和本地预览作为单独运行时证据,不用静态检查替代。
|
||||
|
||||
## 验收标准与证据
|
||||
|
||||
| 条款 | 验收方式 | 证据 |
|
||||
| --- | --- | --- |
|
||||
| 共享 Runtime 不依赖产品 IO | `cargo check/test -p agent-runtime-core -p agent-runtime-orchestration` 与依赖检查 | crate 依赖和测试输出 |
|
||||
| 本地工具只能在授权项目内执行 | AGC Rust 项目 scope、symlink/reparse、写锁和权限定向测试 | `apps/ai-game-creator-shell/src-tauri` 测试报告 |
|
||||
| 云端路由不绕过 domain/client | api-server 定向测试和源码依赖检查 | handler、module、spacetime-client 调用证据 |
|
||||
| 重复提交不产生重复副作用 | 本地 Run、AI task、ExternalGenerationJob 和生成 operation 幂等测试 | 稳定 ID/receipt/CAS 断言 |
|
||||
| 未知外部结果失败关闭 | provider/queue/reconcile 测试 | `needs-reconciliation` 终态证据 |
|
||||
| 认证续期不误杀在途 Run | session 与 Runtime 定向测试 | 同身份凭据轮换、换号失效证据 |
|
||||
| 快照上传受控 | `/api/agc/project-snapshots/*` API smoke | 鉴权、体积、项目归属和 OSS key 断言 |
|
||||
| 公开状态可追踪 | request/correlation/client marker 与错误摘要测试 | tracking、诊断事件和公开 response |
|
||||
| 文档与代码口径一致 | `npm run check:doc-index`、`npm run check:encoding`、`git diff --check` | 命令输出 |
|
||||
|
||||
## 决策
|
||||
|
||||
1. AGC backend 采用“共享 Runtime 内核 + 本地执行宿主 + 云端控制面 + 领域/平台适配器”的逻辑框架;`platform-agent` 继续承载 AGC 游戏特化规则,不能被当作通用内核。
|
||||
2. 先整理本地 host coordinator、云端 application service、contract catalog 和测试边界,再决定是否需要新增物理 crate;当前不新建平行 `agc-runtime`。
|
||||
3. 本地项目文件和云端业务数据保持双平面,快照是受控上传能力,不是开发态主数据同步。
|
||||
4. `agent-runtime-core` 与 `agent-runtime-orchestration` 保持产品无关;AGC 规则进入 host、application 或 `module-*`。
|
||||
5. 公开 API、SpacetimeDB schema、生成绑定和现有本地文件合同在后续实现阶段保持兼容,任何 breaking change 单独走 SDD 和迁移评审。
|
||||
|
||||
## 未决问题
|
||||
|
||||
- AGC application facade 第一批要覆盖哪些调用方:仅客户端本地 Run,还是同时纳入外部编辑器 API。
|
||||
- 云端是否需要持久化 AGC Run 元数据,还是继续以本地 Run 为主、云端只持久化资源和异步 operation。
|
||||
- capability catalog 最终作为文档、生成的共享 DTO,还是仅作为测试清单;在未证明需要运行时发现前,不把它做成新的动态插件注册中心。
|
||||
- 是否有明确的云端 Runner 需求;在没有多租户后台执行需求前,不把本地 Runner 迁移到服务端。
|
||||
@@ -0,0 +1,62 @@
|
||||
# AGC 总版本号与发号
|
||||
|
||||
更新时间:`2026-09-20`
|
||||
|
||||
## 背景
|
||||
|
||||
AGC 客户端此前按「渠道各自比高水位自增」发号:`dev-win` 与 `dev-mac` 各自读自己的渠道清单,`prepareReleaseVersion()` 取本地版本与远端高水位的较大值再 `patch + 1`。两个渠道因此天然拿到不同的号,统一构建无法保证 Windows 与 macOS 是同一个版本,手工填号或并发发号还会出现重号与回退。
|
||||
|
||||
本方案把客户端版本号收敛成单一发号源,渠道只写自己本次拿到的号。
|
||||
|
||||
## 版本源
|
||||
|
||||
- 唯一事实源是 OSS 对象 `agc/global-version.json`,字段:`version`、`updatedAt`、`channel`、`commit`、`buildId`。
|
||||
- 渠道清单(`agc/<channel>/latest.json`)仍写各自本次的版本号,但不再承担发号职责。
|
||||
- 仓库里由构建改写的 5 个版本文件(`apps/ai-game-creator-shell/package.json`、根 `package-lock.json`、`src-tauri/tauri.conf.json`、`src-tauri/Cargo.toml`、`src-tauri/Cargo.lock`)继续按现状由构建改写,**只作构建输入参考、不作为事实源**,不提交、不参与发号。
|
||||
|
||||
## 发号规则
|
||||
|
||||
- `next = 总号 + 1`;总号不存在时先一次性播种,见下节。
|
||||
- 顺序固定为「先写总号 → 再构建 → 再发渠道清单」;任何一步失败都不回滚,只烧号。
|
||||
- 统一构建:发一次号,通过 `AGC_RELEASE_VERSION` 同时传给 `dev-win`、`dev-mac`(以及后续渠道),各渠道共用同一个号。
|
||||
- 单渠道热修:发一次号,只传给该渠道;其他渠道清单保持原值。
|
||||
- 显式传入 `AGC_RELEASE_VERSION` 的构建不再自行发号,只做高水位断言。
|
||||
|
||||
## 并发控制
|
||||
|
||||
- 发号收口到专用 Jenkins Job `Genarrative-Agc-Global-Version-Issue`(`disableConcurrentBuilds()` + 写后回读校验)。集群未安装 `lockable-resources` 插件,因此以 Job 级串行 + 写后回读兜底:写完总号后立刻回读,若远端值与本次写下不一致即失败关闭(号已烧,不重试、不回滚),由人工确认后再发。
|
||||
- 各渠道构建只接收号,不自己加;本地手工兜底路径(未传 `AGC_RELEASE_VERSION`)同样走「读总号 → +1 → 写回 → 回读校验」。
|
||||
- 不允许裸读改写:任何路径都必须经过发号模块,写后回读不一致即失败关闭。
|
||||
|
||||
## 一次性播种
|
||||
|
||||
- 基线 `seed = max(仓库当前版本, agc/dev-win/latest.json, agc/dev-mac/latest.json, agc/latest.json 旧指针)`。
|
||||
- 播种只写基线本身,不递增、不烧号;首个发放号是基线 + 1。
|
||||
- 播种入口:`node apps/ai-game-creator-shell/scripts/issue-global-version.mjs --seed-only`,或发号 Job 勾选 `SEED_ONLY`。
|
||||
|
||||
## 实现位置
|
||||
|
||||
- 发号模块:`apps/ai-game-creator-shell/scripts/agc-global-version.mjs`(读总号 / 播种 / 发号 / 写后回读 / 渠道高水位断言 / dry-run 预览)。
|
||||
- 发号入口:`apps/ai-game-creator-shell/scripts/issue-global-version.mjs`(CI 与本地共用,输出固定为 `AGC_GLOBAL_VERSION=<version>`)。
|
||||
- 构建侧:`build-release.mjs` 的 `prepareReleaseVersion()` 优先采用传入总号,未传入时现场发号;`resolveRemoteHighWaterVersion()` 降级为断言来源,只用于「请求号低于本渠道清单版本即失败关闭」。
|
||||
- CI:`jenkins/Jenkinsfile.agc-global-version-issue` + `jenkins/agc-global-version-issue-job-config.xml`;调度管线 `jenkins/Jenkinsfile.scheduled-revision-trigger` 与手动管线先调发号 Job,再把号透传给 AGC Build。
|
||||
|
||||
## 不改的东西
|
||||
|
||||
- `appUpdate.ts` 与官方 updater 的比较逻辑、渠道清单端点。
|
||||
- `release-oss.mjs` 上传流程。
|
||||
- `agc/latest.json` 只由 `dev-win` 写入。
|
||||
- 主站下载检查的读取源,不接总号。
|
||||
|
||||
## 边界约定
|
||||
|
||||
- `dev-mac` 在 macOS 构建机本地发布时同样只接收号(发号 Job 或本地发号脚本),不允许手动填号。
|
||||
- `AGC_RELEASE_DRY_RUN` 只读总号并预览 +1,不写回、不烧号。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 统一构建后,`dev-win` 与 `dev-mac` 清单版本相同且等于总号。
|
||||
2. 单渠道热修后,只有该渠道清单变化,总号 +1,其他渠道清单原值不动。
|
||||
3. 热修后再统一构建,总号继续 +1,其他渠道版本跳过中间号。
|
||||
4. 并发两次发号不出现重号。
|
||||
5. 传入低于本渠道当前版本的号时构建失败关闭。
|
||||
@@ -20,6 +20,7 @@ packages/agc-plugin-sdk/src/index.ts
|
||||
server-rs/crates/editor-adapter-api/src/lib.rs
|
||||
plugins/agc-cocos-editor/ (第一个编辑器插件包)
|
||||
plugins/agc-unity-editor/ (Unity Mono 编辑器插件包)
|
||||
plugins/agc-godot-editor/ (Godot GDExtension 编辑器插件包)
|
||||
```
|
||||
|
||||
现有 DirectProject 的 Skill/MCP 导入仍保留。它们是 Codex 扩展注入链路,不等同于本宿主管理的可运行 AGC Plugin。
|
||||
@@ -77,7 +78,7 @@ Cocos 与 Unity 插件的可见性、启动、面板、插件 RPC 和 Agent 工
|
||||
### 工程上下文与真实编辑器目标
|
||||
|
||||
- 工程类型只用于工程识别及对应工程工作流,不作为 `agc-cocos-editor` / `agc-unity-editor` 的管理、面板或工具目录门禁。Runtime、DirectProject MCP、工具策略快照和模型上下文使用一致规则;工具已暴露不代表真实编辑器已连接或操作已成功。
|
||||
- 前端对宿主列表中的 Cocos 与 Unity 插件分别根据适配器支持、启用、Runtime 入口和运行状态投影自动启动,不按项目类型二选一;自动启动不自动展开编辑器面板。
|
||||
- 前端对宿主列表中的 Cocos、Unity 与 Godot 插件分别根据适配器支持、启用、Runtime 入口和运行状态投影自动启动,不按项目类型二选一;自动启动不自动展开编辑器面板。Godot 是否属于当前项目由宿主过滤,Cocos/Unity 保持工程类型独立性。
|
||||
- 项目切换不因新工程类型不同而停止插件或隐藏工具;当前受控项目上下文仍须按既有顺序更新,旧编辑器连接失效。旧请求与回执保留原项目归属,不能更新新项目连接状态。
|
||||
- 实际编辑器操作仍须取得有效的当前受控项目和与之匹配的真实编辑器目标。宿主注入项目路径,显式路径必须与当前受控项目一致;适配器继续校验真实工程结构、目标 PID、进程身份、版本与握手。无项目、不匹配的工程目录、无编辑器或不支持的平台均应在发送编辑器操作前明确失败,不回退到其它项目或任意编辑器进程。
|
||||
- 插件启用状态、manifest 适配器绑定、`editor.rpc` 权限、超时与并发拒绝、执行结果不确定阻断均保持原合同。取消工程类型过滤不增加自动重试,不清除项目切换或重启插件前已经产生的不确定状态。
|
||||
@@ -132,8 +133,29 @@ Unity 插件复用此扩展点,GUI 适配器通过已有 Runner RPC 转发到
|
||||
Windows x64 的 Attach helper 来源、构建工具链和执行回执合同见
|
||||
[Unity 插件接入](./【技术方案】AGC Unity编辑器插件接入-2026-09-18.md)。
|
||||
|
||||
Godot 使用同一 Runner 执行与回执确认层,按引擎分别保存 pending/uncertain 状态,不能相互确认或清除。`godot-editor` 的受控连接允许按用户已选方案维护项目内 `.gdextension` 引用及 Godot 自动生成的 UID;DLL 随安装资源分发,探测仍只读,原始项目配置和场景不改。具体文件归属、GDScript 错误/async、升级卸载与分发合同见 [Godot 插件接入](<./【技术方案】AGC Godot编辑器插件接入-2026-09-20.md>)。
|
||||
|
||||
## 编辑器常用操作指导
|
||||
|
||||
Unity 与 Godot 的常用操作指导由客户端既有审核 Skill pack 随包提供;每个引擎有独立入口和常用操作参考,不新增执行工具或任意文件读取入口。DirectProject 在隔离 Skill 目录发现指导,也可通过已有 `agc_read_skill_resource` 按审核名称和相对路径读取。Agent Runtime 的对应执行工具说明包含同一份常用操作参考,避免只覆盖 Codex 原生 Skill 路径。正文只有一个源码来源,清单指纹与安装投影必须一致。
|
||||
|
||||
指导覆盖场景/层级查询、对象或节点的创建/修改/删除、组件或属性、Prefab/PackedScene、资源引用、基础 UI、打开/保存场景、运行/停止及诊断。示例是提交给现有 execute 的代码正文,说明前置状态、预期回读和保存/撤销语义,不写宿主路径、PID、令牌或桥接安装动作。读说明不连接编辑器、不授权修改;执行仍受原插件开关、平台、项目和权限门禁控制。
|
||||
|
||||
每个引擎的操作参考不超过 14 KiB UTF-8,并独立包含执行参数和失败边界;Direct 常驻提示只给读取路由,16K 字符预算内必须保留两个引擎的指南入口。Runtime 的最终工具定义须完整包含对应参考,不能因截断丢失末尾内容,也不能在该执行工具不可用时额外注入正文。
|
||||
|
||||
通用 CapabilityRegistry 保留原有短描述和 4000 字符约束;完整参考只在已注册能力转换为 Provider 函数工具时附加,按 UTF-8/LF 规范化并校验 14 KiB 上限。不扩大 core 的任务、能力或摘要长度合同。
|
||||
|
||||
执行载荷仅有 `code`;Direct 工具的顶层参数为 `{code}`,Runtime 原生函数沿用 `{reason,input:{code}}` 外层,指南必须按实际工具 schema 区分这两种调用格式。
|
||||
|
||||
确定失败也可能已经产生部分修改;未知结果继续禁止自动重放。Unity 使用实际场景与对象身份,区分 Undo、Prefab override、保存和 Domain Reload。Godot 使用真实编辑场景根、为需保存的新节点设置 owner,区分独立 UndoRedo 回滚与编辑器历史,避免承诺未验证的 Ctrl+Z。主线程同步死循环不可硬中止。
|
||||
|
||||
验收要求:两个入口均能取得审核正文,源码与安装后的字节一致;非法路径及未登记资源继续拒绝;系统提示能够发现指南但不塞入全部示例;从指南原文提取代码做真实临时工程验证,至少覆盖查询、修改与回读、局部撤销、场景持久化、资源实例化和 UI。未实测操作和平台须在交付记录中明确,不把 API 示例当作已有独立工具。
|
||||
|
||||
当前证据覆盖本地指南读取/安装、最终工具描述、真实编辑器执行示例及 Godot 示例图形渲染。Unity GUI 视觉和真实 Provider 读取指南后调用编辑器的端到端链路尚未验收,不能由定向测试或前置状态检查推断通过。
|
||||
|
||||
## Tauri 命令
|
||||
|
||||
|
||||
`list_agc_extensions` 返回统一的 Plugin/Skill/MCP catalog;`list_agc_plugins`、`refresh_agc_plugins`、`start_agc_plugin`、`stop_agc_plugin`、`reload_agc_plugin`、`call_agc_plugin` 和 `read_agc_plugin_panel` 提供 Runtime Plugin 管理入口;`set_agc_plugin_project_path` 设置当前项目的受控上下文。编辑器适配器通过宿主 registry 和 Plugin RPC 使用,不增加编辑器专属 Tauri 命令。
|
||||
|
||||
编辑器操作统一走 `host.rpc`:插件用 `extensions.world.genarrative.agc.adapter` 或显式 `adapter` 参数选择适配器,宿主校验 `editor.rpc` 权限后调用 `EditorAdapter::rpc`。项目上下文通过 `host.events.subscribe` 的响应和 `project.changed` 事件 payload 下发,插件不需要自己扫描目录。
|
||||
@@ -150,7 +172,7 @@ OpenAI 官方 Plugins 文档将 Skills、MCP Server 和可选 UI 定义为同一
|
||||
- Rust:manifest 路径/权限校验、目录扫描、权限拒绝和通用适配器 registry 边界单测;`cargo check --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml`。
|
||||
- 前端:`agc-plugin-sdk` TypeScript 编译、宿主服务类型检查,以及 `PluginPanelHost` 的挂载/卸载测试。
|
||||
- 内置插件开关:`builtin_plugins` 单测覆盖默认值、持久化往返、坏文件失败关闭,以及“禁用后工具目录里不再出现该工具”;`plugin_host` 单测覆盖禁用后不能启动、启用后回到 stopped。
|
||||
- 工程类型独立性:覆盖无当前项目、普通 AGC、Godot、Cocos、Unity 上下文中的插件列表、启动、面板、RPC 与 Runtime/DirectProject 工具目录一致性;项目切换不因类型变化停止插件。保留禁用开关、缺失原生适配器、平台/feature、显式跨项目路径拒绝与真实编辑器目标校验的独立反例;非引擎目录不能仅因工具可见就通过实际操作校验。
|
||||
- Cocos/Unity 工程类型独立性:覆盖无当前项目、普通 AGC、Godot、Cocos、Unity 上下文中的插件列表、启动、面板、RPC 与 Runtime/DirectProject 工具目录一致性;项目切换不因类型变化停止这两个插件。Godot 单独验证当前工程门禁、切项目撤销旧上下文与停止旧实例。保留禁用开关、缺失原生适配器、平台/feature、显式跨项目路径拒绝与真实编辑器目标校验的独立反例;非引擎目录不能仅因工具可见就通过实际操作校验。
|
||||
- 插件工作区:`cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml` 覆盖工作区扫描与 manifest 启用状态;`cargo test --manifest-path plugins/agc-cocos-editor/native/cocos-editor-bridge/Cargo.toml` 覆盖 Cocos 适配器;`node --test plugins/agc-cocos-editor/src/entry.test.mjs` 覆盖插件入口协议与 manifest 一致性。
|
||||
- 通用仓库门禁:`npm run check:encoding`、`git diff --check`;发布前仍需单独执行 AGC package smoke 和安装包 smoke。
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
记录格式版本为 `schemaVersion: 1`。`recordedAtMs` 是记录时间,`historicalModelConfirmed` 仅在响应观测或可信历史恢复时为 `true`;它在请求快照和当前配置补录时为 `false`。上述本地 fixture 不替代真实供应商或安装包验收。
|
||||
|
||||
## 2026-09-20 Godot 编辑器插件
|
||||
|
||||
已有 Godot 工程通过内置 `agc-godot-editor` 接入 `godot.editor.execute` / `agc_godot_execute`,复用通用 PluginHost、EditorAdapter、Runner、可用开关和权限审计。DLL 随 AGC 安装资源分发,项目内受管描述文件触发官方 GDExtension 聚焦加载;工作区与实际 Godot 根继续遵守双根合同。GDScript 的真实完成、编译/运行错误、await 和不确定回执按 [Godot 编辑器插件接入](<./【技术方案】AGC Godot编辑器插件接入-2026-09-20.md>) 验收,不能用原型或模拟回执替代正式实机结果。
|
||||
|
||||
## 2026-09-17 GameCreationApp 资源 kind:唯一词汇表、严格解析与 `app_log!` 留痕
|
||||
|
||||
本节覆盖 2026-09-15 节里关于「canonical 字符串列表 / legacy 别名表 / `tracing` 留痕 / ts-rs 生成路径」的表述;枚举成员集合、「不迁移、不静默转换」的总体口径不变。
|
||||
@@ -91,6 +95,14 @@ Rust 侧在 `server-rs/crates/shared-contracts` 维护唯一权威 `GameCreation
|
||||
|
||||
客户端平台服务固定为 dev,登录页不提供服务器选择。凭据按 origin 隔离迁移;官网下载入口汇总最新渠道清单,自动展示已有首装包的 Windows/Mac 平台及架构。完整合同见 [AGC 客户端更新检查与下载](./【技术方案】AGC客户端更新检查与下载-2026-08-31.md) 的“官网下载与客户端服务地址”。
|
||||
|
||||
## Agent 提示词与回合测试边界
|
||||
|
||||
预览快捷操作的 UI 回归按独立命令及必要的连续操作拆分,每例使用新的项目 fixture、invoke mock 和页面,项目打开后再采样副作用调用计数。保留命令输出、草稿填入、焦点、权限确认和原生参数断言;预览启停、快照回滚取消、导出确认与取消作为各自短流程验证,使用默认测试超时。定向运行 `npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts -t "预览快捷操作:"`。
|
||||
|
||||
提示词拼装测试核对动态错误、外置片段和实际 Provider 请求结构,避免绑定可自由润色的中文原句。源码载荷限制由实际动作校验与 Provider 修复测试覆盖;工具参数自动修复和超预算上下文压缩继续验证恢复结果、状态及私有信息隔离。Direct 消息原样转发复用生产请求转换测试,文件变化与版本幂等直接测试生产文件投影函数,删除测试专用的重复回合编排。
|
||||
|
||||
Rust 分片日志在失败时输出有界 stdout 尾部中的失败段,保留 panic 位置、断言详情和 Rust 汇总;selected 只表示该分片选中的用例数量。成功分片保留简短摘要。定向验证使用相关 Rust 用例与 `node --test apps/ai-game-creator-shell/scripts/run-rust-shell-test-shards.test.mjs`。
|
||||
|
||||
## 策划 Agent 批量局部修改
|
||||
|
||||
`patch_file` 的所有 edits 均匹配同一份原文件,参数顺序不影响结果。完成唯一匹配与不重叠校验后,按原文起点升序拼接未修改片段与替换文本,最后一次性写入;任一校验失败时不写文件。回归用例覆盖乱序 edits、中文内容与替换长度增减,并核对完整落盘内容。此行为仅属于策划 Agent 文件工具。
|
||||
@@ -1393,7 +1405,7 @@ game-project/
|
||||
|
||||
- 普通项目对话由一个 project-bound Codex app-server thread 执行。客户端系统提示词包含最小工程合同、项目 prompts 和审核 Skill 索引;源码与 Skill 正文按任务需要读取。提示词、工具描述与 Skill 直接描述当前任务、输入和成功条件,细节按调用需要提供。
|
||||
- 首页提供“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。每次首页提交自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 作为受限结构化首轮上下文传给同一 Codex thread。
|
||||
- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
|
||||
- `agc-skill-pack.v1` 包含完整游戏交付流程、项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影,以及 Unity/Godot 编辑器常用操作八项审核 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
|
||||
- DirectProject 连接客户端内置的 `agc_tools` STDIO MCP,并在启动时接入客户端扩展仓库中用户已启用的独立第三方 STDIO/HTTP MCP 配置。内置工具包括审核引用读取、图片生成、标准陶泥儿美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive 语义生成、已登记图片去背景、desktop/mobile 浏览器试玩和受控 `agc_web_search`。内置 MCP 进程负责协议;真实浏览器、付费平台调用与受控搜索通过随机 loopback 地址回到客户端主进程,GUI 登录态、开发者 Key、项目路径、revision、operation 与幂等键由客户端持有并隔离于模型上下文。内置与用户启用的第三方 MCP 工具沿用 DirectProject 自动批准方式;付费资源工具由客户端绑定稳定回合身份、串行执行并优先恢复匹配账本。`llm.webSearchEnabled` 控制 DirectProject 的 AGC 受控搜索工具暴露与执行。原生工具与审批权限以下方“DirectProject Codex 完整访问覆盖”为准。
|
||||
- 陶泥儿生成复用持久幂等账本、operation 恢复、来源/下载/PNG 解码和 manifest 登记;普通客户端使用当前 AGC 登录会话及账号路由,受控的 ExternalDeveloper 发布模式在客户端内部使用按服务器 origin 隔离的私有 Key。凭据失效、来源不明或结果未知时失败关闭,不能自动换 Key 或重新扣费。
|
||||
- 自定义 LLM API Key 路由在 DirectHome/DirectProject 经 loopback `/responses` 流式代理转发。代理使用请求自带的 Bearer,并剥离开发网关错误携带的 `X-Codex-*` ChatGPT 账户额度头,按实际 API Provider 响应判断请求结果。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 策划 Agent 生产迁移与工作区浏览方案
|
||||
|
||||
更新时间:2026-09-10
|
||||
更新时间:2026-09-20
|
||||
状态:已完成(2026-09-18)
|
||||
|
||||
> 现状说明(2026-09-18):本文记录的迁移已完成,当前策划入口统一使用 Design Agent。旧 Planning V1/V2 会话、专用命令、审批卡和展示适配已删除;文中提到的 V2 文件仅代表迁移时的参考来源,不得作为现行实现、回退路径或测试迁移目标。
|
||||
@@ -180,6 +180,8 @@ concept → top_design → architecture → systems → tdd → consultant
|
||||
|
||||
模板、范例、类型资料和没有明确要求自动注入的文档继续保持选读。必读资源缺失、为空或读取失败时,只记录诊断并继续请求 Provider,不阻断阶段推进。
|
||||
|
||||
星露谷分析示例的资源路径统一为 `templates/stardew-analysis.md`,分册与示例中的引用保持一致;通过 `read_resource` 读取时使用目录登记的资源 ID `templates.stardew_analysis`。
|
||||
|
||||
根据当前原型 `resources/catalog.json`,自动注入清单为:
|
||||
|
||||
| 当前阶段 | 全文注入的资源 ID | 资源文件 |
|
||||
@@ -206,13 +208,15 @@ concept → top_design → architecture → systems → tdd → consultant
|
||||
|
||||
`systems: []` 是已确定的行为,不是迁移时需要补齐的缺口。`project/analysis.md`、`project/决策台账.md`、`project/dialog.md` 保持原型中的共享过程文件口径,不升级为新的审批必需项。速览卡保留原型结构提示,但 Runtime 与 UI 不解析其章节或内容字段。
|
||||
|
||||
过程文档记录关键依据、决定和待办,不要求实时完整,也不应重复正式设计文档;阶段提交前补齐影响验收的关键记录。顶层设计的分册、模板和示例保留核心定位及按需说明的易混淆方向与排除理由,不强制使用固定的“不是 X,而是 Y”句式。
|
||||
|
||||
进入下一阶段必须由用户批准触发。Runtime 推进后向 Agent 追加明确的用户行为语义,例如“用户已批准上一阶段,现在进入顶层设计阶段”,避免 Agent 误认为 Runtime 自行推进。
|
||||
|
||||
## 7. 审批与澄清交互
|
||||
|
||||
### 7.1 阶段审批
|
||||
|
||||
Agent 完成当前阶段后必须调用 `submit_phase_for_approval`。普通文本中的“批准”“确认”“进入下一阶段”等内容不改变 Runtime 阶段。
|
||||
Agent 完成五个策划阶段中的当前阶段后必须调用 `submit_phase_for_approval`。需要用户选择的关键问题先通过问询解决,阶段审批用于检阅已完成的产物;可以保留不阻塞当前阶段的后续事项和待原型验证项。普通文本中的“批准”“确认”“进入下一阶段”等内容不改变 Runtime 阶段。
|
||||
|
||||
提交时 Runtime 只检查:
|
||||
|
||||
@@ -234,7 +238,7 @@ UI 使用“批准”和“继续修改”两个文字按钮,分别配 Lucide
|
||||
- 选择“继续修改”后,再次出现新的审批请求前,不能重复批准旧请求;
|
||||
- 不实现 `/approve`、`批准`、`确认` 等文本检测。
|
||||
|
||||
批准与拒绝通过带请求身份的结构化命令处理。后端只接受当前待审批请求;重复点击同一已处理请求不再次推进,旧卡不能批准新的请求。此处校验请求身份与会话状态,不对文件增加指纹、快照或内容校验。进入顾问态后不自主安排新任务。
|
||||
批准与拒绝通过带请求身份的结构化命令处理。后端只接受当前待审批请求;重复点击同一已处理请求不再次推进,旧卡不能批准新的请求。此处校验请求身份与会话状态,不对文件增加指纹、快照或内容校验。顾问阶段遵照用户的具体指示行动,不自主推进项目或主动安排下一步,不提交阶段审批;完成单次用户请求不结束顾问态。
|
||||
|
||||
### 7.2 澄清
|
||||
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
# Responses API 与 Agents SDK 迁移评估
|
||||
|
||||
更新时间:`2026-09-07`
|
||||
|
||||
## 结论
|
||||
|
||||
本次评估不建议把 Genarrative 的核心 Agent Runtime 整体迁移到 OpenAI Agents SDK。建议保留 `platform-llm` 的 Responses / Chat / Anthropic 协议适配、Tauri/Rust Runtime、项目文件与进程工具、审批、权限与沙箱、持久会话、任务图、重试、恢复、计费和现有 Codex app-server 路径。
|
||||
|
||||
可以保留一个有明确边界的 Agents SDK 试验:只在可信的服务端或受控 Tauri bridge 中,为 Project Supervisor / 专业 Agent 的只读交互聊天提供可选的 `Agent + Runner` 编排、只读专家路由和统一 tracing。该试验必须通过现有 Runtime 工具网关和事件投影,不能让 SDK 直接读写项目、启动进程、提交媒体任务、扣费或持有正式状态。
|
||||
|
||||
理由是当前系统已经拥有比 SDK 默认能力更严格的业务控制面。技术方案已经明确规定 AGC Runtime 由 Genarrative 自己掌控,不把 OpenAI Agents SDK sidecar 作为核心,只借鉴 Agent、Tools、Handoffs、Guardrails、Tracing 抽象(见 `docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` 的“技术选择”)。OpenAI 官方 Agents 文档也把 SDK 定位为建立在 Responses API 之上的编排层:SDK 用 `Agent` 和 `Runner` 管理 turns、tools、guardrails、handoffs 和 sessions;如果应用自己拥有这套循环,直接使用 Responses API 是合理路径。[Agents SDK Agents 指南](https://openai.github.io/openai-agents-python/agents/)
|
||||
|
||||
## 现状盘点
|
||||
|
||||
### Responses 协议层
|
||||
|
||||
`server-rs/crates/platform-llm/src/lib.rs` 定义了协议中立的 `LlmRunRequest` / `LlmRunResponse`。请求包含模型、system/user/assistant 消息、图像输入、`max_output_tokens`、web search、reasoning effort、text verbosity、function tools 和 `tool_choice`(约第 167–194 行)。默认 `LlmApiKind` 是 `openai_responses`,同时显式支持 `openai_chat` 和 `anthropic`。
|
||||
|
||||
Responses 请求在 `build_request_body` 中映射到 `/responses`,包括 `input`、`stream`、`max_output_tokens`、原生 `web_search`、function tools、`tool_choice`、`reasoning.effort` 和 `text.verbosity`(约第 2321–2404 行)。消息映射保持 Responses 的角色差异:system/user 文本使用 `input_text`,assistant 文本使用 `output_text`,图像使用 `input_image`(约第 2895–2973 行)。
|
||||
|
||||
非流式响应会从 `output_text` 和 `function_call` 中恢复正文、工具调用、usage、finish reason 和 response id。`LlmClient::run` 负责请求验证、HTTP 执行、响应读取和协议解析(约第 1550–1585 行)。
|
||||
|
||||
流式 `LlmClient::stream_run` 自己维护 SSE 解析、UTF-8 分块、Responses `response.output_text.delta`、`response.output_item.added`、`response.function_call_arguments.delta/done`、`response.completed` / `response.incomplete`、错误和尾部异常处理(约第 1596–1869 行)。工具调用按 Responses `output_index` 聚合,完整参数由终态事件校正;工具分片没有完成信号时会失败关闭;只把文本增量和 finish reason 交给上层,工具调用留在最终 `LlmRunResponse.tool_calls`。
|
||||
|
||||
`server-rs/crates/platform-llm/src/provider_adapter.rs` 把该 client 接入 `agent-runtime-core` 的 Provider registry。Responses 适配器宣告 Streaming、FunctionTools、RequiredToolChoice、ImageInput、WebSearch、ReasoningEffort 和 TextVerbosity 能力。`platform-llm/README.md` 明确规定该 crate 只负责文本协议适配,不承接上下文、后台执行、业务状态或工具副作用。
|
||||
|
||||
### AGC 的生成工作流
|
||||
|
||||
`apps/ai-game-creator-shell/src-tauri/src/agent/generation/loop_orchestration.rs` 仍保留一条文件驱动的确定性生成链:
|
||||
|
||||
1. Planner 读取用户需求、短期/长期记忆和项目黑板,生成 `.agent/spec.md`。
|
||||
2. Orchestrator 根据 spec、findings 和 manifest 生成 agenda / task graph。
|
||||
3. 按依赖 wave 并行生成设计、美术、程序等角色 brief,并写入本轮 pass 产物。
|
||||
4. Generator 根据 spec、findings、brief、素材和 agenda 生成结构化游戏草稿。
|
||||
5. Evaluator 写入 `.agent/findings.md`,失败时进入下一 pass 的修复范围。
|
||||
6. 产物写入、静态检查和试玩验证由 Runtime 完成,而不是由模型回复宣称完成。
|
||||
|
||||
Planner / Generator 使用独立的 system/user prompt 和严格结构化输出。Generator 选择 `run` 或 `stream_run`,但 legacy 生成 loop 的 streaming callback 为空,流式主要用于传输和容错;Generator 对 `EmptyResponse` 有有界重试,随后解析和校验 JSON。
|
||||
|
||||
这条链路的任务图、文件写入、Evaluator 反馈和产物门禁具有明确业务语义,不适合交给一个 SDK run loop 隐式管理。
|
||||
|
||||
### 后台 Runtime tool-plan 工作流
|
||||
|
||||
`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/provider_request_builders.rs` 和 `provider_tool_plan.rs` 为每个后台 turn 动态构造请求:
|
||||
|
||||
- 读取当前 Agent、Session、Run、Goal Contract、Acceptance Graph、黑板、项目摘要、受控观察和运行中追加指令。
|
||||
- 按 Agent 身份、run profile、项目阶段、审批策略和验证门动态收窄工具目录。
|
||||
- 以严格 JSON Schema function tools 暴露 `file.*`、`project.*`、`command.*`、`preview.*`、`canvas.*`、`asset.*`、`memory.*`、`task.*`、`agent.*`、`goal_contract`、`acceptance_update`、`update_agent_plan` 和 `respond_to_user` 等能力。
|
||||
- 普通 Runtime tool-plan 要求模型直接调用白名单函数,并将计划更新、工具动作、观察和最终回复拆成可持久化的协议阶段。
|
||||
- 工具调用解析后进入 `agent/runtime_tools/*`,再经过权限、路径、项目写锁、确认、revision、验证和 receipt 门禁;模型不能直接执行副作用。
|
||||
- Provider 成功结果先写入 handoff / lifecycle / Agent DB,再由 Runtime 消费;重复、迟到、身份冲突或无法确定终态时进入 `needs-reconciliation`,不自动重放。
|
||||
|
||||
`agent_native_tools.rs` 生成严格工具 schema,工具策略与动态目录由 Runtime 控制。当前工具目录和工具执行已经是领域合同,不是简单的 JSON function-call wrapper。
|
||||
|
||||
### 交互聊天和流式行为
|
||||
|
||||
交互层在 `apps/ai-game-creator-shell/src-tauri/src/agent/interaction.rs` 中使用一个受限 interaction kernel:普通问答直接回复,只有确实需要宿主持久能力时才调用一个 function tool;高影响请求先澄清,不擅自启动 Runtime。它复用现有 Provider registry,流式异常可按稳定错误类型回退一次非流式请求。
|
||||
|
||||
Tauri command `chat_with_game_creator_role_agent_stream` 会先写入用户消息,再发出 `started` 事件,随后发出带 `delta_text`、`accumulated_text` 和 `finish_reason` 的 `delta` 事件,最终发出 `completed` 或 `failed`(`apps/ai-game-creator-shell/src-tauri/src/commands.rs` 约第 1199–1335 行)。React 侧按项目、Agent、Run 和加载代次过滤迟到事件,以 `requestAnimationFrame` 合并正文,失败时保留已接收的完整正文。
|
||||
|
||||
后台 final reply 还使用 `AgentRuntimeResponseStreamPublisher` 将流持久化到 `.agent/runtime/response-streams/<hashed-agent>/<hashed-run>.json`。记录绑定 Agent/Task/Session/Run、request slot、steer cursor、响应 revision、sequence、status、正文和 finish reason,并支持 `streaming → ready → committed/failed/discarded` 的恢复和去重。SDK 流必须先转译到这一合同,不能绕过它直接推送 UI。
|
||||
|
||||
### Codex app-server 路径
|
||||
|
||||
AGC 当前默认路线可以是 `codex_app_server`。`codex_app_server.rs` 通过 JSON-RPC `turn/start` / `turn/completed` 管理独立 thread/turn,消费 agent message、activity、item、MCP 工具和终态事件,并把增量正文映射回 `LlmStreamDelta`。`config.rs` 要求该模式使用 `apiKind=openai_responses`。
|
||||
|
||||
这条路径已经是另一种 agentic transport,且包含 workspace mode、进程生命周期、MCP 审计、硬超时和 passive-item 边界。它不能与 Agents SDK 直接互换;任何试验都必须保留该模式及其回滚能力。
|
||||
|
||||
### API Server、Router 和其他调用方
|
||||
|
||||
`server-rs/crates/api-server/src/llm/mod.rs` 提供账号鉴权的 `/api/llm/responses` 代理:客户端只传平台 access token,服务器解析账号 Router credential、模型目录和计费,删除客户端的 `apiKey`、`baseUrl`、provider、api kind、agent mode 等控制字段,再将 `stream`、`input`、`tools`、`metadata` 转发到 Responses endpoint。流式代理等待 `response.completed` / `response.incomplete` 后才结算额度。
|
||||
|
||||
`platform-editor-agent` 仍有自己的 `Agent`/memory/tool harness,但其编辑器对话目前固定使用 OpenAI Chat;图片、音频、UI 识别、画布生成等 helper 具有各自的严格结构化合同。它们不应因为 AGC 聊天试验而一起迁移。
|
||||
|
||||
## Prompt、工具和状态边界
|
||||
|
||||
### Prompt 分类
|
||||
|
||||
| 类别 | 当前入口 | 主要约束 | 迁移判断 |
|
||||
|---|---|---|---|
|
||||
| Planner / Generator | `generation/prompt_context.rs`、`loop_orchestration.rs` | 严格 JSON、文件产物、Evaluator pass、模型输出不能伪造写入/验证 | 保留 Responses / 当前编排 |
|
||||
| Runtime tool-plan | `runtime_actions/provider_request_builders.rs`、`prompt.rs` | 动态工具目录、身份策略、Goal/Acceptance、动作数量、确认和完成门 | 保留 Rust Runtime;SDK 只可作为未来只读 adapter |
|
||||
| Final reply | `provider_final_reply.rs`、`provider_request_builders.rs` | 只能依据 observation,不能声称未发生副作用;规划 Agent 有固定信封 | 保留现有路径,若试验仅转译文本事件 |
|
||||
| Interaction chat | `interaction.rs`、`prompt.rs` | 普通问答与单宿主工具决策;可流式;适合路由/澄清 | 唯一优先试验边界 |
|
||||
| Editor / media helpers | `platform-editor-agent`、`api-server/llm`、各媒体 prompt | Chat/Responses 混合、严格 JSON、计费和外部副作用 | 保留现有协议和专用 harness |
|
||||
|
||||
### 工具、委派和 handoff 的语义差异
|
||||
|
||||
当前 `agent.delegate` / isolated join 是持久任务调度动作,包含 parent/child ID、delivery、认领、all-join、恢复和完成门;Provider handoff sidecar 是跨 Runner 边界保存一次成功 Provider 响应。这两者都不等于 Agents SDK 的 handoff。
|
||||
|
||||
Agents SDK 的 handoff 是模型可见的工具式路由:一次 handoff 后由专业 Agent 接管同一 run 的对话;SDK 文档还区分了“manager + agents as tools”和“handoffs”。[Agents 组合模式](https://openai.github.io/openai-agents-js/guides/agents/)
|
||||
|
||||
因此:
|
||||
|
||||
- Supervisor 的只读问答可以使用 manager + `agent.asTool()`,保留 Supervisor 作为唯一面向用户的回复所有者。
|
||||
- 需要真正转移对话控制的只读专家咨询才考虑 SDK handoff,并通过 `inputFilter` 限定传入历史。
|
||||
- 任何涉及文件、命令、进程、媒体、审批、项目 revision、manifest、验证或 Git 的意图,必须先转成 Runtime 可验证的动作/委派请求,由 Rust 决定是否允许;SDK handoff 不能创建正式 child Run,也不能绕过 `agent.delegate`。
|
||||
|
||||
### 状态管理
|
||||
|
||||
当前正式状态由 `.agent/conversations/**/*.jsonl`、`.agent/runtime/**/*.json`、Agent DB、任务队列、manifest/revision、handoff/retry/confirmation ledger 和 finalization journal 组成。`AgentRuntimeProviderRequestSnapshot` 绑定 project/agent/task/session/run/source、goal revision/fingerprint、steer cursor、request kind/slot、web search 和 planning session binding。
|
||||
|
||||
Agents SDK 可以使用 `Session`、`conversationId`、`previousResponseId` 或 `RunState`,但官方文档提醒不要把多种历史策略叠加使用。[Agents SDK Sessions](https://openai.github.io/openai-agents-js/guides/sessions/)
|
||||
|
||||
本项目即使引入试验,也只能选择一个“临时模型上下文”策略;`.agent` 对话、Runtime sidecar 和 Agent DB 仍是唯一正式事实源。SDK session 不拥有 project revision、工具 action、审批、billing、retry、resume 或 finalization。重启恢复必须先恢复 Genarrative sidecar,再决定是否重建 SDK run。
|
||||
|
||||
## 是否需要更 agentic 的架构
|
||||
|
||||
核心 Runtime 已经具备更 agentic 的架构,而且它比通用 SDK loop 多了本项目所需的持久治理:
|
||||
|
||||
- 工具:严格 schema、身份目录、按角色/阶段动态收窄、auto/confirm/deny、项目锁和 revision。
|
||||
- 交接:静态专业 Agent、动态 isolated child、delivery receipt、all-join、恢复和 parent run 收束。
|
||||
- Guardrails:路径/文件类型、sandbox、权限、确认、Goal Contract、Acceptance Graph、验证 gate、最终回复门禁和敏感信息脱敏。
|
||||
- Tracing / audit:run trace、event、Agent DB、tool receipt、Provider lifecycle、request fingerprint 和 response stream sidecar。
|
||||
- Streaming:Responses SSE / Codex item events → Runtime stream publisher → Tauri events → 前端按 identity/sequence/revision 去重。
|
||||
- 状态:session catalog、JSONL conversation、Runtime state、task queue、retry/handoff sidecar、context compaction 和 crash recovery。
|
||||
|
||||
因此,整体迁移只会把已有能力复制一遍,带来两套 turn loop、两套状态、两套重试和两套工具授权;收益不足以抵消安全和恢复风险。
|
||||
|
||||
Agents SDK 对局部交互仍有增量价值:
|
||||
|
||||
| 能力 | 在本项目的真实收益 | 可接受边界 |
|
||||
|---|---|---|
|
||||
| Agent loop | 减少只读聊天中手写单轮/多轮和路由 glue code | 只用于交互聊天或只读专家问答 |
|
||||
| Tools | 统一工具参数解析、工具结果与模型 turn | function tool 只调用 Rust RPC 的窄只读 facade |
|
||||
| Handoffs / agents-as-tools | 更容易表达 Supervisor→专家的语言路由 | 不创建正式 Runtime child;推荐 manager + agents-as-tools |
|
||||
| Guardrails | 可增加聊天输入/输出格式和工具输入校验 | 不能替换 Rust 权限、确认、sandbox、revision gate |
|
||||
| Streaming | 提供 raw model、run item、agent updated 等统一事件 | 先转成现有 response-stream 记录,必须等待 `stream.completed` |
|
||||
| Tracing | 补充 generation/tool/handoff/guardrail latency 和 token span | 关联现有 run IDs,关闭敏感数据或自定义脱敏 processor |
|
||||
|
||||
官方 Streaming 文档明确说明 `toTextStream()` 只给正文,工具、handoff、approval 等需要消费完整事件流;流结束后还可能进行 session 持久化或 compaction,因此必须等待 `completed`。[Agents SDK Streaming](https://openai.github.io/openai-agents-js/guides/streaming/)
|
||||
|
||||
官方 Tracing 文档说明默认会记录 run/task/agent/turn、generation、function tool、guardrail 和 handoff spans,并支持自定义 trace processor;这对排查延迟和工具路由有价值,但也意味着 prompt 和工具数据必须显式设置敏感数据策略。[Agents SDK Tracing](https://openai.github.io/openai-agents-js/guides/tracing/)
|
||||
|
||||
## 推荐架构边界
|
||||
|
||||
```text
|
||||
Tauri / React
|
||||
│ 现有 invoke + Tauri events
|
||||
▼
|
||||
Genarrative Rust Runtime(正式事实源)
|
||||
├─ session / conversation / task / revision / approval / recovery
|
||||
├─ tool policy / sandbox / filesystem / process / media / billing
|
||||
├─ existing response-stream sidecar and Agent DB
|
||||
└─ Provider seam
|
||||
├─ current LlmClient + platform-llm (Responses/Chat/Anthropic)
|
||||
├─ Codex app-server (existing route)
|
||||
└─ optional Agents SDK adapter (experimental, read-only chat only)
|
||||
│
|
||||
└─ trusted Node/TS process or Tauri bridge; never browser bundle
|
||||
```
|
||||
|
||||
可选 adapter 的职责应是:接收 Rust 生成的已脱敏 prompt/context snapshot;创建有限的 `Agent`、工具和可选只读专家;调用 `run(..., {stream: true})`;把 SDK event 转成现有 `ProviderStreamEvent` / `LlmStreamDelta` / Runtime observation;将最终文本和工具意图返回 Rust。Adapter 不得读取项目绝对路径、凭据、签名 URL 或任意环境变量,也不得自行重试有副作用的工具。
|
||||
|
||||
建议在试验中优先使用 manager + agents-as-tools,而不是让 SDK handoff 成为对话所有权切换。这样 Supervisor 仍是唯一的用户回复所有者,SDK 专家只返回短的只读咨询结果。若确实需要 handoff,必须由 Rust 提前给出允许目标集合,并在 SDK handoff callback 中再次校验目标和输入;模型传入的 routing metadata 只能作为受限说明,不能改变权限或项目目标。
|
||||
|
||||
## 模型与 Provider 建议
|
||||
|
||||
OpenAI 官方模型页当前建议:复杂推理和编码优先 GPT-6 Astra,平衡能力与成本选择 GPT-5.6 Terra,高量低成本选择 GPT-5.6 Luna;最新模型可通过 Responses API 和 Client SDK 使用。[OpenAI Models](https://developers.openai.com/api/docs/models)
|
||||
|
||||
这不构成一次模型迁移任务:AGC 当前已有官方 Router / catalog alias 和每 Agent 配置,官方 route 已使用 `gpt-6-astra` 语义,客户端不能绕过服务器模型目录直接选择任意模型。迁移试验应冻结当前已配置模型和 reasoning/verbosity,先测编排差异;若要对 GPT-5.6 Terra/Luna 或其他新模型做基准,应作为独立模型评估,不与 SDK 迁移同时变更。
|
||||
|
||||
Agents SDK 试验只适合经过验证的 OpenAI Responses 路径。`openai_chat`、`anthropic`、VectorEngine/Ark 等兼容网关继续走 `platform-llm`,不要假设它们支持 SDK 的 hosted tools、server-managed conversation、Responses WebSocket 或完整事件形状。若自定义 base URL 不能稳定返回 function tool 和 SSE 终态事件,直接回退现有 Provider adapter。
|
||||
|
||||
## 测试与文档建议
|
||||
|
||||
现有测试应作为不可削弱的迁移门禁:
|
||||
|
||||
- `cargo test -p platform-llm --manifest-path server-rs/Cargo.toml`:Responses body、tool schema、图像输入、非流式 function call、SSE text/tool 聚合、completed/incomplete 恢复、参数截断、尾部错误、超时和重试。
|
||||
- `cargo test -p platform-agent-harness --manifest-path server-rs/Cargo.toml`:staged memory 提交/回滚、非法 JSON 修复、deadline、顺序工具和确认。
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider -- --test-threads=1`:Provider、stream fallback、工具计划、retry、handoff、redaction 和 context compaction。
|
||||
- `apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs` 及 `runtime_actions/response_stream_tests.rs`:stream sidecar 的 identity、sequence、reconnect、commit、discard、steer 和恢复。
|
||||
- `apps/ai-game-creator-shell/tests/appSurface/response-stream.suite.ts`、conversation/session、supervisor runtime、handoff、retry、runner-kill suites:UI 状态和真实恢复合同。
|
||||
- 现有 deterministic E2E 和 opt-in live Provider smoke 继续保留;live 测试不能成为默认 CI 依赖。
|
||||
|
||||
如果实施 SDK 试验,再增加:
|
||||
|
||||
1. **差分 fixture**:同一脱敏输入同时跑现有 Responses adapter 和 SDK adapter,比较最终文本、tool name/arguments、finish reason、usage、模型和错误分类;不执行真实副作用。
|
||||
2. **事件转译合同**:覆盖 raw model delta、message output、tool called/output、agent updated、handoff requested/occurred、approval interruption、completed 的顺序、重复和取消。
|
||||
3. **持久流恢复**:中途进程退出、tail error、重复事件、sequence 回退、steer cursor 变化和 finalization 竞态,都必须回到现有 sidecar 语义。
|
||||
4. **Session/RunState 隔离**:证明 SDK session/RunState 不能替换 `.agent/conversations`、`.agent/runtime` 和 Agent DB;恢复后不得重放已提交 file/media/process/billing action。
|
||||
5. **工具授权和幂等**:未经 Rust policy 允许的 tool/handoff 被拒;retry、handoff、approval resume 不产生重复副作用。
|
||||
6. **Tracing 脱敏**:trace processor 中不存在 API key、Cookie、签名 URL、绝对路径、原始工具参数、项目源码和用户私密正文;trace/group/workflow ID 可关联现有 project/session/run/agent ID。
|
||||
7. **兼容网关能力探测**:分别验证 HTTP Responses、function tools、SSE completed/incomplete、图像输入和错误事件;不因模型名推断 endpoint 能力。
|
||||
8. **回滚差分**:SDK 失败、超时、unsupported event、handoff 拒绝和 stream 取消都回到现有 `provider` 或 `codex_app_server`,且响应和 conversation 只落一次。
|
||||
|
||||
文档建议在真正开始试验时再更新:
|
||||
|
||||
- 为 AGC 增加 setup README:只在可信 Node/TS 进程或 bridge 安装并 pin `@openai/agents` 与 `zod`;说明 custom base URL、HTTP Responses transport、AppData credential、tracing key 与禁用/脱敏策略。SDK 不得打进浏览器 bundle,不能使用 Vite 暴露的 API key。
|
||||
- 更新 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md` 的 LLM/Responses 段,补充 adapter feature flag、custom provider 能力限制、trace privacy、canary 与 rollback 命令。
|
||||
- 更新 `server-rs/crates/platform-llm/README.md`,声明 SDK 若加入只位于协议层之上的编排 adapter,Responses/Chat/Anthropic parser 和错误/stream 合同仍由 `platform-llm` 负责。
|
||||
- 新增迁移 runbook,写明 `.agent` 状态不迁移、不删除、不由 SDK 接管,测试矩阵和恢复证据要求。
|
||||
|
||||
## 分阶段迁移计划
|
||||
|
||||
### Phase 0:合同冻结(先做)
|
||||
|
||||
- 固定当前 `LlmRunRequest`、有效工具 schema、prompt bundle、model/api kind、reasoning/verbosity、stream 开关、retry/backoff、request fingerprint 和错误分类的 golden fixture。
|
||||
- 固定现有 response-stream sidecar 的 schema、identity、sequence、status、revision、steer cursor 和 finalization 行为。
|
||||
- 固定 `platform-llm`、AGC provider tests、response-stream tests、supervisor/handoff/recovery E2E 为 baseline。
|
||||
- 明确试验只允许 `provider` 的 OpenAI Responses 交互聊天;`codex_app_server`、Chat、Anthropic、legacy Planner/Generator 和项目副作用不进入首轮。
|
||||
|
||||
退出条件:所有 baseline 通过,且没有任何 SDK 依赖或状态格式变更。
|
||||
|
||||
### Phase 1:受控 SDK adapter(开发环境)
|
||||
|
||||
- 在受信任的 Node/TS 服务或 Tauri bridge 中增加可选 adapter;不要在 React/browser bundle 中调用 SDK。
|
||||
- Adapter 只收 Rust 传来的脱敏 context snapshot,使用 `Agent`、窄只读 function tools 和 manager-style `agents as tools`。
|
||||
- Rust 继续分配 project/session/run/request slot 和 action identity;SDK 的 run id、session 或 trace id 只作关联元数据。
|
||||
- 所有 tool function 必须调用 Rust RPC 的只读 facade;写文件、命令、进程、媒体、外部 editor、审批、billing 和 Git 均拒绝。
|
||||
- Adapter 将 SDK stream events 映射成既有 response-stream publisher 输入,等待 `stream.completed` 后才返回最终结果。
|
||||
|
||||
退出条件:没有 SDK 直连项目文件/凭据;只读聊天的 text/tool/stream parity fixture 通过;中止和重复事件不破坏 sidecar。
|
||||
|
||||
### Phase 2:影子差分与 tracing bridge
|
||||
|
||||
- 对脱敏的历史聊天 fixture 同时运行 current Provider 和 SDK adapter,但 SDK 侧不执行工具副作用。
|
||||
- 记录 final text、tool intent、事件延迟、首 token 延迟、token usage、错误类型、重试次数和取消行为,不记录原始 secret/prompt/tool payload。
|
||||
- SDK tracing 使用稳定 workflow name,例如 `genarrative-agc-interaction`;group id 绑定 session,metadata 只放哈希后的 project/agent/run/request identity。默认关闭敏感数据,或用自定义 processor 做字段级脱敏,并在任务结束 flush。
|
||||
- 统计差异而不是立即替换当前路径:结构化工具意图必须相同,文本差异需人工抽样,SDK 不得增加重复请求或扣费。
|
||||
|
||||
退出条件:在代表性 fixture 上,SDK 没有重复副作用、身份错配、公共信息泄漏、流式重复和不可解释的额外成本;否则停止试验。
|
||||
|
||||
### Phase 3:小流量可选 canary
|
||||
|
||||
- 用按 Agent / 项目 / build 的 feature flag 只开放给开发调试入口或内部用户。
|
||||
- 运行时检测 custom endpoint 是否支持 function tools、SSE terminal event 和目标 Responses 字段;不支持就选择旧 Provider。
|
||||
- SDK stream、handoff、approval 或 tracing 任一异常时,按“尚未产生副作用”条件回退;若已经产生 Rust action,必须先以 action ledger / reconciliation 处理,禁止盲目重试。
|
||||
- 保持同一个 UI event 和 conversation projection,不让用户看到两种状态模型。
|
||||
|
||||
退出条件:canary 的成功率、首 token 延迟、终态延迟、工具意图一致率、恢复成功率、重复副作用数、泄漏数和成本达到事先设定门槛,并连续多个版本稳定。
|
||||
|
||||
### Phase 4:仅在数据支持时扩大
|
||||
|
||||
最多把只读 Supervisor/role chat 扩到更多内部聊天场景。不要因此迁移:
|
||||
|
||||
- Planner→Generator→Evaluator 文件工作流。
|
||||
- 自主构建和正式 Runtime tool-plan。
|
||||
- `agent.delegate`、isolated child、all-join、DAG 和 manifest scheduler。
|
||||
- 文件、命令、进程、媒体、External Editor、Git、preview 和审批工具。
|
||||
- `platform-llm` 的 Chat/Anthropic/兼容网关和 API-server Router/billing。
|
||||
- Codex app-server DirectProject 路径。
|
||||
|
||||
只有在未来需求明确要求 SDK 的原生能力,并能证明它不会与上述合同冲突时,才另立架构决策评估核心迁移;本报告不预设该迁移。
|
||||
|
||||
## 回滚说明
|
||||
|
||||
- 首要回滚是关闭 feature flag,将该 Agent route 指回现有 `provider` 或 `codex_app_server`;不改 `.agent` 对话、Runtime state、Agent DB、manifest、revision 或 receipt schema。
|
||||
- SDK adapter 只允许生成可丢弃的临时 run/trace 记录。关闭后这些记录不参与恢复和最终回复;已有 Rust response-stream / finalization 记录继续按原逻辑收口。
|
||||
- 如果 SDK 已返回 tool intent 但 Rust 尚未提交 action,直接丢弃该意图并重新走旧 route;如果 Rust 已提交 action,必须按现有 receipt、ledger 和 reconciliation 恢复,不能用 SDK 重试覆盖。
|
||||
- 不通过自动降级重复调用可能产生计费或媒体副作用的请求。重试仍由现有 Runtime retry identity、attempt、backoff 和 provider handoff 控制。
|
||||
- 不把 SDK Session、Conversation ID、Previous Response ID 或 trace export 当作恢复依据;它们失效时不影响本地正式状态。
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] `platform-llm` 的 Responses request/response/SSE/tool parser 全量通过。
|
||||
- [ ] Chat、Anthropic、Codex app-server 和 legacy Planner/Generator 路径行为未变化。
|
||||
- [ ] SDK adapter 只在可信服务端/bridge 运行,浏览器 bundle 和前端环境变量没有 SDK key。
|
||||
- [ ] current Responses 与 SDK adapter 的 prompt、tool schema、tool choice、model、reasoning、verbosity 和 output budget 差分通过。
|
||||
- [ ] SDK stream event → `LlmStreamDelta` / `ProviderStreamEvent` → response-stream sidecar 的映射通过。
|
||||
- [ ] `started → delta → completed/failed` Tauri event 合同、sequence/revision/steer/session/run identity 和 UI 去重通过。
|
||||
- [ ] `stream.completed`、session persistence、approval interruption 和 cancellation 都被正确等待/收口。
|
||||
- [ ] SDK tool/handoff 不能绕过 Rust policy、confirmation、sandbox、project lock、revision、billing 或 finalization gate。
|
||||
- [ ] handoff/agents-as-tools 只作用于只读咨询;正式 `agent.delegate` 和 isolated join 仍由 Rust scheduler 管理。
|
||||
- [ ] 进程退出、网络尾错、重复事件、Runner kill、retry、steer 和 resume 不产生重复副作用或重复 assistant message。
|
||||
- [ ] trace 关联到现有 project/session/run/agent identity,敏感 prompt、路径、源码、凭据和 tool args 均不出现在 trace/export/log。
|
||||
- [ ] custom Responses endpoint 的 function tools、SSE terminal event、图像输入和错误事件能力已显式探测。
|
||||
- [ ] canary 指标满足门槛;若不满足,feature flag 可立即切回旧 route。
|
||||
- [ ] 文档已更新 setup、tracing privacy、provider capability、测试矩阵和 rollback runbook。
|
||||
Reference in New Issue
Block a user