Compare commits

...

113 Commits

Author SHA1 Message Date
k88936 cb7db4923b Merge remote-tracking branch 'origin/master' into fix/chat-status-lost
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
#	docs/project-memory/shared-memory/pitfalls.md
2026-09-17 18:47:18 +08:00
k88936 e7bd6a339b 补首屏历史锚点的实现证据,里程碑验收那条转成已验收
证据要求新增「首屏锚点(已跑)」一条:Rust 22 条、闸门单测 10 条、appSurface 全量 475/457/17 与唯一既有失败的对照结论
里程碑验收「首屏边界只认订阅回执」那条打勾,并写明两处变异验证现象
决策记录把「验证方式(待跑)」改成已跑的实跑结果与变异验证结论
2026-09-17 18:46:37 +08:00
k88936 de4dfe8538 首屏历史改按订阅回执锚定,回执到达前不读首屏
锚点闸门抽到 directHistoryAnchorGate:开闸、同项目复用、消费后不再等待三件事只有一份实现
App 订阅 effect 复用首屏开好的闸门,success 时 settle 成回执的 lastCompletedItemId,订阅不可用/失败/切项目/清理时 settle 成 null
首屏切片只在新端边界 throughItemId 有值时带上它,非 replace 模式才等闸门,/history 手动重读仍按文件尾
测试 harness 的切片桩支持 throughItemId,setDirectThreadHistory 同时同步回执用的 lastCompletedItemId
新增 directHistoryAnchorGate 单测覆盖复用/消费回退规则,App 集成用例断言首屏锚在回执那条、回执先于首屏读取
2026-09-17 18:46:37 +08:00
k88936 110e9260a7 历史切片补新端锚点:首屏窗口取到订阅回执那条为止
direct_project_history 的分页锚点收敛成 DirectProjectHistoryAnchor:Newest(取文件尾)/ Before(不含锚点,翻页用)/ Through(含锚点,首屏边界用)
read_direct_project_history_slice 命令新增 throughItemId,与 beforeItemId 互斥,两个都传直接报错
新增三条用例:Through 含锚点且挡掉更新的条目、锚点是最老一条时仍把它算进窗口、锚点不存在时失败关闭
既有用例改走显式锚点(Newest / Before),行为不变
变异验证:把 anchor_seen 初始化成 true(等于忽略锚点)后四条锚点用例变红
2026-09-17 18:46:37 +08:00
k88936 fae02694fb 补首屏历史锚点的契约:切片新端边界只认订阅回执的 lastCompletedItemId
ADR 首屏锚点那条写清锚点语义:新端(较新一侧)边界含锚点条目,命令参数 throughItemId,更新条目只从运行态事件来,翻页仍用 firstItemId 的 beforeItemId 不含锚点
里程碑范围与已确认决策同步该口径,验收标准新增一条待验收行(首屏 throughItemId + 回执前不发请求)
实施计划第 6 步补上首屏读取等订阅回执、锚点缺失才退化取文件尾
决策记录新增 2026-09-17 条目,记下 manager 恒 None / commands 磁盘回填 / 前端自 1b40f030e 起不再读取的现状与本次决策
2026-09-17 18:46:37 +08:00
k88936 180a249a68 删掉聊天回读路径里已无人调用的回读函数与前端死类型
删除 Rust 侧 read_direct_tool_calls_at 与 read_direct_turn_stream_at:前端已改走项目对话历史,这两个回读函数不再有调用方
direct_tool_calls / direct_turn_stream 的模块注释与上限常量口径改成写侧,回读命令退役后不再提「回读」
direct_tool_calls 单测改为直接读盘断言落盘内容,删掉只服务已删回读的跳过损坏行 / 合并重复行 / 回读上限三条用例
写前读取的 UTF-8 容错用例改名为 tool_call_pre_read_skips_invalid_utf8_line 并补缺文件返回空表断言
app/types.ts 删除 GameCreatorDirectTurnUpdateEvent 与 TurnStream* 五个只服务旧事件链路的类型
工具卡片方案 §3 由「回读命令」改写为「落盘契约(写侧)」,文首修订说明同步
2026-09-17 18:46:36 +08:00
kdletters 1a7abfd059 AGC 项目定时快照上传(目标 OSS agc-dev) (#400)
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
## 交付内容

- 客户端新增 `project_snapshot` 模块:项目扫描与排除口径、增量索引、差异对比、上传编排、状态查询。
- 触发:工作区窗口存活期间的周期定时器 + 工作区窗口关闭(`CloseRequested`);应用退出只在有界预算内等待在途同步收尾,不重复发起。
- 服务端新增两条登录态路由 `POST /api/agc/project-snapshots/files` 与 `/manifest`,由 api-server 用服务端凭据写入私有前缀 `agc/project-snapshots/v1/{user}/{project}/`;客户端不持有 OSS 凭据、不直连 OSS。
- `platform-oss` 新增内部对象精确写入与探测、项目快照对象键构造;修复 `head_internal_object` 读 HEAD 响应长度恒为 0(会导致服务端"已存在即跳过"永不生效)。
- `shared-contracts` 新增 `agc_project_snapshots` DTO 与项目 ID、相对路径、摘要校验。
- 真实 OSS 存储层冒烟示例 + 客户端真实链路冒烟用例(`#[ignore]`,env 驱动)。
- 登记 `check-config.mjs` 的 native-only 命令白名单,恢复 `npm run agc` 可启动。

## 验证证据

- 存储层:`cargo run -p platform-oss --example agc_project_snapshot_live_smoke` 对真实 `agc-dev` 完成写入 → 读回(contentLength 32)→ 清单写入 → 探针清理。
- HTTP 层:登录态下 7 项校验(401 无 token、400 路径穿越/长度不一致/非法摘要/空正文/重复路径清单)全部符合预期且不写对象。
- 客户端链路(真实项目 gameagent-033b6cf3…):第一次 `synced uploaded=6 uploadedBytes=36694 remoteSkipped=6`,紧接着第二次 `no-op uploaded=0`。
- GUI 触发:`trigger=periodic ... uploaded=6`;把周期设为 600 秒排除干扰、改一个文件后关窗得到 `trigger=project-close ... revision=2 uploaded=1`,索引摘要由 `28d837cd84f8ab62` 推进到 `bff34e2e336d901f`(同步在进程退出前完成)。
- 门禁:AGC `project_snapshot` 14 passed(+1 ignored live)、api-server `project_snapshots` 3 passed、platform-oss 39 passed、shared-contracts 87 passed、`cargo fmt --check`(两处)、`check:encoding`、`check:doc-index`、`git diff --check`、`check-config.mjs` 全部通过。

## 已知未决(不阻塞本里程碑)

- 远端对象只增不减:没有删除路径,也没有 bucket 生命周期规则;要收口需要先定保留语义(清单引用 GC 还是 OSS 生命周期)。
- 部署环境需确认 `GENARRATIVE_AGC_PROJECT_SNAPSHOT_OSS_*` 或回退的 `ALIYUN_OSS_*` 具备目标 bucket 私有前缀的 `PutObject` 权限;未配置时接口返回 503、客户端失败关闭(不推进索引)。
- 缺少按用户/项目的配额与限流(error_reports 有每小时提交上限的先例,本功能没有)。
- 没有界面入口与状态可见性:`read_local_project_snapshot_state` 已注册但未接 UI,失败只写本机日志。

## 不做

- 不做云端下载/恢复、跨设备合并、版本回滚。
- 不改 `/api/external/v1` 与 External OpenAPI,不新增 SpacetimeDB 表。

---------

Co-authored-by: kdletters <61648117+kdletters@users.noreply.github.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/400
2026-09-17 18:34:51 +08:00
kdletters 1c5ff8f852 回填 AGC 更新渠道首次发布证据
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
- 记录 Genarrative-Agc-Windows-Build #68 成功发布 dev-win 渠道 0.1.48 与迁移桥
- 记录签名对象与渠道清单逐字一致、安装包尺寸与 SHA-256 与迁移桥登记一致
- 待执行项仅保留客户端真实升级闭环与签名失败拒绝安装
2026-09-17 18:25:26 +08:00
kdletters ce04d8cef4 AGC 发布流水线增加 OSS 演练开关
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m35s
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
- Jenkins 增加布尔参数 AGC_RELEASE_DRY_RUN,勾选后只构建并打印上传命令,不写入 OSS
- 参数转换为脚本读取的 AGC_RELEASE_DRY_RUN 环境变量,完成提示区分演练与真发
2026-09-17 18:14:57 +08:00
lhk229 504e26da43 修复策划agent panic死掉问题 (#405)
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/405
2026-09-17 18:11:54 +08:00
kdletters fc14190f58 图集切片模式改为必须显式声明并补齐决策要求 (#408)
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
## 背景

切图新增基于连通域的切分后,LLM 仍倾向显式传 `sliceMode=grid`:参数只存在于部分 LLM 可见面、带默认值、没有任何决策规则,生成结果也不回显生效模式。

## 变更

- 平台:`/api/editor/icon-spritesheets/generations` 与 `/api/external/v1/editor/icon-spritesheets/generations` 把 `sliceMode` 改为必填并移除默认值;缺失、空白或未知取值在引用解析、定价与任何 provider / OSS 副作用之前返回 `400`,错误统一带 `field` 与决策要求。
- 契约:`grid` 必须同时提供 `gridX`/`gridY`,`connected-components` 不接受网格尺寸;`sliceCount` 只约束连通域切分,请求与响应的公开上限统一为 `256`;OpenAPI 去掉默认值并补必填与失败语义。
- AGC:MCP 工具说明去掉默认值并补决策要求,桥接层新增可测试的切分声明校验;原生工具 `canvas.asset_generate` 暴露 `sliceMode/gridX/gridY/sliceCount` 并要求图集显式声明;生成结果回显 `sliceMode/gridX/gridY` 与 `slicePaths`;严格图集在本地提交前校验平台回显与请求声明一致。
- 标准美术包:显式声明 `connected-components` 加 `sliceCount=4`,并在四张 canonical 切片用途映射前校验数量,禁止截断或错位。
- 前端与画板:画板 Agent 工具装配与画板提交计划显式声明连通域切分;前端类型要求显式 `sliceMode` 并在本地校验声明自洽。
- 文档与 Skill:主规范、OpenAPI、AGC Skill、外部编辑器 Skill、里程碑与实施计划、共享决策记录同步更新。
- 测试环境:测试构建对提权 Windows 主机上系统临时目录的所有者偏差做一次性所有者初始化重试,临时目录之外的越权所有者继续失败关闭。

## 兼容性影响

省略 `sliceMode` 的旧调用方(含已发布但未更新的 AGC 客户端与第三方外部 API 调用方)会在图集生成上收到 `400`;这是本次"不允许默认值"的预期结果,仓库内自有调用方已全部改为显式声明。

## 验证

- 平台:`slice_mode_must_be_declared_*` 与 OpenAPI 契约测试通过;全量 `cargo test -p api-server` 1043 通过 / 11 失败(`wallet_refund_outbox` 临时文件 `拒绝访问`,已在改动前基线复现,属本机环境)。
- AGC:`slice` 30、`spritesheet` 21、`direct_tools_mcp` 23、`agent_native_tools` 16、`canvas_generation_tests` 83、提示词上限与桥接门禁各 1 条、`cargo check --tests` 全部通过。
- 前端:182 条定向测试与 `typecheck` 通过。
- 门禁:`cargo fmt --check`(两个 workspace)、`check:encoding`、`check:doc-index`、`git diff --check` 通过。
- 未验证:真实 Provider 与浏览器试玩、确定性 e2e 车道;整机全量 AGC 单进程运行在本机受提权 shell 的所有者与时序问题影响,不作为门禁信号。

---------

Co-authored-by: kdletters <61648117+kdletters@users.noreply.github.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/408
2026-09-17 18:10:34 +08:00
kdletters 5e4ff54a9d 删除模板工程内置的嵌套 package-lock
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
- 模板 fixture 内的 package-lock.json 触发 workspace 守卫的「禁止嵌套 lockfile」规则,导致 master 门禁失败
- 其余五个模板都只提交 project 内容与 package.json,删除该文件与它们保持一致
- 模板 zip 由发布脚本现场打包并重新计算大小与哈希,仓库内没有引用该 lock 的脚本或测试
2026-09-17 18:04:21 +08:00
kdletters 1f5b7b250a 修正首页推荐位用例断言到模板库
- 首页「灵感推荐」已被模板库推荐位替换,用例改为断言模板库推荐卡片、已下载徽标与共 N 个模板计数
- 用例改为断言点击推荐位进入模板库页面,且不触发下载或由模板创建项目
- 保留不请求已退役展示流接口的断言
2026-09-17 18:03:15 +08:00
kdletters a5fd25f10a 客户端更新切换到官方更新插件并按渠道分发
- 客户端接入 tauri-plugin-updater:原生侧注册插件,删除自研更新下载命令、下载进度事件与安装器启动逻辑
- 客户端更新服务与更新提示改走官方插件接口,删除自研清单解析、版本比较与下载实现
- 更新能力只授予客户端主窗口,移除只为自研清单放行的 OSS 白名单与 CSP 连接项
- 新增构建期更新检查开关:开发态默认关闭,agc 启动不请求更新清单、不显示更新入口
- 发布脚本按渠道生成官方更新插件清单与签名,universal macOS 产物同时挂两个平台键,缺签名失败关闭
- 发布脚本按渠道上传安装包、签名与渠道清单,并为 dev-win 生成旧协议 sha256 迁移清单
- 构建期按渠道注入更新端点配置,渠道与目标平台不匹配时发布失败关闭
- Jenkins 流水线新增渠道参数与签名凭据注入,归档补充签名与迁移清单
- 新增发布上传 dry-run 开关,只打印 ossutil 命令且不回显凭据
- 更新技术方案与开发运维文档,登记 macOS 渠道落地待办
2026-09-17 17:56:53 +08:00
kdletters 5db407c3dc 新增 AGC 模板库与由模板创建项目链路 (#396)
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m12s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m18s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m25s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 7m22s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m49s
Project CI / AI game creator shell Rust crates (push) Successful in 2m36s
Project CI / Repository checks (push) Failing after 1m11s
Project CI / Frontend tests (push) Failing after 4m37s
Project CI / AI game creator shell web tests (push) Failing after 4m6s
Project CI / Native shell tests (push) Successful in 9m39s
Project CI / Backend tests (push) Successful in 10m12s
## 交付范围

- OSS `agc-dev` bucket 的 `templates/` 前缀作为 AGC 游戏模板库(**去掉 `agc/` 这一层**;`agc/` 继续只放客户端安装包与更新清单)。
- 模板正文改为 zip(zip 根 == AGC 项目根,如 `game/index.html`);清单补齐 `tags`、封面字段与包大小/摘要,`templateVersion` 用于判断是否需要重下。
- 客户端:Rust 模板库模块、模板库全屏页、首页模板推荐位、左侧导航入口。

## 客户端行为

- `fetch_game_template_library`:读取并校验清单(≤4 MiB),缓存到 `<app_data>/templates/index.json`;网络失败回退本机缓存并标注 `source=cache`。
- `download_game_template`:按清单下载 zip(≤512 MiB),校验字节数与 SHA-256 后解压到 `<app_data>/templates/installed/<id>/<version>/`,最后写 `installed.json` 作为安装完成标记。
- `create_automatic_local_game_project_from_template`:先把模板文件铺进新项目目录,再走既有 `init_local_game_project_at` 补 `.agent` 清单与标准目录;失败删除半成品目录。
- 解压只接受普通文件与目录(拒绝绝对路径、`..`、盘符、符号链接),安装目录名由标识符白名单拼出;远端只信「受信任 OSS 主机 + 对象键」,清单里的地址字段不参与请求。
- UI:搜索(空白分隔多关键词「与」)、标签/运行时筛选、仅看已下载、封面卡片与已下载徽标;「使用模板」在版本落后时先重下再建项。

## 文档与脚本

- 主规范 `docs/technical/【技术方案】AGC模板库与模板建项-2026-09-17.md`;里程碑与实施计划见 `docs/project-memory/plans/`;`decision-log.md` 记录库路径、清单 schema、安装缓存目录与 CSP 约定。
- 发布脚本 `scripts/agc-template-library-publish.mjs`(`--dry-run` 校验 → 上传 → 回读校验)。
- 首页「灵感推荐」替换为模板库推荐位,删除本机灵感图目录与 `InspirationGallery.tsx`;`tauri.conf.json` 的 `img-src` 放行受信任 OSS 主机用于加载封面。

## 验证

- `cargo test --bin genarrative-ai-game-creator-shell template_library`:9 passed;`--ignored` 真连检查 `fetches_the_live_template_library_index` 通过。
- `npx vitest run src/features/template-library`:9 passed。
- `npm run typecheck`、`cargo fmt --check`、`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check` 均通过。
- OSS 侧匿名复核:`templates/index.json`、各 `cover.png` 与 `template.zip` 均返回 200。

## 未做 / 待确认

- 本轮未做客户端点击级人工验收(下一步单独验证并把结果补进此 PR)。
- 模板封面目前是占位标题卡,正式封面由后续模板包提供。

---------

Co-authored-by: kdletters <61648117+kdletters@users.noreply.github.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/396
2026-09-17 17:48:06 +08:00
lhk229 61e1021a4d Merge branch 'master' into fix/chat-status-lost
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
2026-09-17 17:17:57 +08:00
lhk229 de9e8e0c7f 修复运行时默认重试次数的测试断言
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Successful in 2m7s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m22s
Project CI / AI game creator shell Rust crates (push) Successful in 2m5s
Project CI / Repository checks (push) Successful in 5m27s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m9s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m10s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 6m27s
Project CI / Frontend tests (push) Successful in 6m34s
Project CI / Native shell tests (push) Successful in 7m57s
Project CI / Backend tests (push) Successful in 10m8s
Project CI / AI game creator shell web tests (push) Has been cancelled
将恢复默认配置的重试次数断言同步为10。
补充默认配置变更时的测试核对规则。
2026-09-17 17:03:45 +08:00
k88936 b7622f4a24 Merge remote-tracking branch 'origin/master' into fix/chat-status-lost
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
# Conflicts:
#	docs/project-memory/shared-memory/pitfalls.md
2026-09-17 16:57:47 +08:00
k88936 cb840c6e8c Merge branch 'master' into fix/chat-status-lost
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
#	docs/project-memory/shared-memory/pitfalls.md
2026-09-17 16:53:18 +08:00
k88936 0a9cdf6395 补 DirectProject 历史分页连拉的实现证据
里程碑前端连拉那条转成已验收,证据指向新单测与跨页同回合集成用例
证据要求补上本轮实跑结果与变异验证现象,避免再出现打勾但只覆盖一半
决策记录把验证口径写成具体条数与变异验证结论
2026-09-17 16:51:30 +08:00
k88936 e382d23892 补跨页同回合的历史分页回归用例
用 51 条历史复现用户报的现象:20 条工具条目整屏落进同一个折叠的执行过程
断言一次点击连拉两页拿到新用户气泡,并按 process-31 / process-11 两次锚点推进
断言连拉插入旧内容后视口仍停在原处,不被拉回列表底部
2026-09-17 16:49:08 +08:00
k88936 37ae7508b8 App 聊天历史分页改走连拉循环
首屏与「显示更早」共用 readDirectHistoryPages,不再各自单发一页
首屏基线取空并在守卫后一次性并入聊天 reducer,失败仍按原有语义抛出
「显示更早」按当前视图条目判断新回合,取到多页一次性并入并推进锚点
连拉中途失败保留已取到的页,报错统一走同一个出口
2026-09-17 16:39:24 +08:00
k88936 1ae6c6cd06 新增 DirectProject 历史分页连拉模块与单测
directHistoryPaging 按「合并后聊天投影回合数增加」判断可见反馈,出现新回合或 hasMore=false 即停
连拉上限 DIRECT_HISTORY_MAX_PAGES_PER_ACTION 放进 app/constants,每个操作最多 5 次请求
锚点未推进(items 为空 / firstItemId 为 null 或原地打转)时立即停手并收口 hasMore
某页读取失败不丢已取到的页,返回 error 交给调用方报错
directThreadChat 抽出 projectDirectHistoryItems,让分页判据与视图共用同一份投影
2026-09-17 16:27:09 +08:00
lhk229 c958e1955b Merge branch 'master' into opt/design-llm-call
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m57s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m54s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m18s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m37s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m55s
Project CI / AI game creator shell Rust crates (push) Successful in 2m17s
Project CI / Frontend tests (push) Failing after 3m52s
Project CI / Repository checks (push) Failing after 3m52s
Project CI / Native shell tests (push) Successful in 8m39s
Project CI / AI game creator shell web tests (push) Failing after 4m17s
Project CI / Backend tests (push) Successful in 9m45s
2026-09-17 16:26:16 +08:00
lhk229 1b579acf47 提高客户端LLM默认重试次数到10
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
内置默认值 DEFAULT_GAME_CREATOR_LLM_MAX_RETRIES 由 2 改为 10
随App分发的配置模板 game-creator.config.json 的 maxRetries 同步为 10
设置对话框草稿兜底值 maxRetries 同步为 10
2026-09-17 08:22:52 +00:00
k88936 ff84fa7b04 Merge pull request '修复推理档弹层被裁剪问题,增加 CSS 覆盖声明以确保窄布局下弹层完整显示。' (#401) from fix/effort-panel-overlay into master
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Reviewed-on: #401
2026-09-17 16:21:52 +08:00
k88936 459f8a60e5 文档先行:定死 DirectProject 历史分页连拉的可见性口径
把「可显示」判据明确为合并后聊天投影出现新回合,并写清每操作 5 页上限与锚点不前进即停
里程碑把原第 56 条按后端锚点回扫与前端连拉拆成两条独立验收项,前端那条先留待补证据
实施计划第 6 步同步口径,并把新分页单测加入验证命令
决策记录新增 2026-09-17 条目,记下落点、上限粒度、失败与竞态边界
2026-09-17 16:18:51 +08:00
k88936 1b56c0a586 Merge remote-tracking branch 'origin/master' into fix/effort-panel-overlay
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m32s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 6m18s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m56s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m5s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m14s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m58s
Project CI / Repository checks (pull_request) Successful in 4m14s
Project CI / Frontend tests (pull_request) Successful in 5m14s
Project CI / Native shell tests (pull_request) Successful in 8m38s
Project CI / Backend tests (pull_request) Successful in 9m40s
Project CI / AI game creator shell web tests (pull_request) Successful in 4m55s
# Conflicts:
#	docs/project-memory/shared-memory/pitfalls.md
2026-09-17 15:56:56 +08:00
k88936 efdb364a52 修复推理档弹层被裁剪问题,增加 CSS 覆盖声明以确保窄布局下弹层完整显示。
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
2026-09-17 15:54:07 +08:00
lhk229 ebc5dfe7db 修复策划工具乱序局部修改导致的中断 (#399)
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 6m39s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m11s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m2s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m29s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m18s
Project CI / AI game creator shell Rust crates (push) Successful in 2m47s
Project CI / Repository checks (push) Successful in 4m9s
Project CI / Frontend tests (push) Successful in 5m20s
Project CI / Native shell tests (push) Successful in 8m16s
Project CI / Backend tests (push) Successful in 9m49s
Project CI / AI game creator shell web tests (push) Successful in 4m4s
按原文位置排序并顺序拼接补丁,避免替换偏移失效。
新增乱序、中文与长度变化的局部修改回归测试。
同步策划 Agent 批量局部修改技术说明。

Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/399
2026-09-17 14:58:21 +08:00
kdletters cd9faae9b2 修复 agc_tools 媒体资源提示词上限并按 kind 暴露 (#398)
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
## 改动

- 提示词上限收敛为 `resource_edit_prompt_max_chars` 单一权威:`agc_tools` MCP 工具层、客户端受控工具桥与提交校验共用同一数字与拒绝文案,不再出现「schema 写 4000、真实上限按 kind 分」的分叉。
- `agc_create_or_derive_resource` 的 schema 逐 kind 声明 `prompt.maxLength`(background-music / sound-effect / video 与 character-animation),`prompt` 描述写明每个数字;`agc_edit_image` 继续用图片口径 32000。
- 工具桥不再用通用 4000 校验 prompt:图片编辑 4000~32000 的提示词不再被误报成「超出安全边界」。
- 源资源未登记时的错误文案补上可执行两步:先用 `agc_list_registered_assets` 选已有 localAssetId;只在项目里的文件先 `agc_list_project_files` 确认 `assetImportable=true`,再用 `agc_import_account_assets.localPaths` 登记后重试。`agc_remove_background` 复用同一条文案。
- skill 包 `agc-client-projection` 的 SKILL.md 与 projection-contract.md 写明四个上限,并说明超限要在本地收敛而不是原样重发;清单指纹同步到 `2026-08-26.18`(已合并 master 的抠图文案)。
- 前端 `resourceEditModel.ts` 补注释指向 Rust 权威函数,数字未动。
- decision-log、pitfalls 与《AI游戏创作智能体App实施计划》记录本轮口径;未改 External v1 契约 / OpenAPI、SpacetimeDB schema 与客户端 UI 行为。

## 问题

| 编号 | 问题 | 本 PR 状态 |
| --- | --- | --- |
| P1 | 背景音乐提示词真实上限 140,但 schema 只写 4000、skill 未写明,agent 写一句正常长度描述必被硬拒 | 已修复:口径单源 + 逐 kind 暴露 + skill 写明 |
| P2 | 音效 1900 与图片编辑 32000 的上限只在 Rust 内部生效,MCP 与工具桥各自硬编码或误报 | 已修复:三处共用同一函数,图片编辑不再误报安全边界 |
| P3 | 源资源未登记时只报「不属于当前项目已登记资源」,模型会原地重试 | 已修复:文案给出 `agc_list_registered_assets` 与登记工具两步动作 |
| P4 | 这两个工具此前没有端到端用例,同类漂移无法被门禁拦住 | 已补:MCP 工具层 → 真实工具桥 → 假平台的契约用例 + 两条按 kind 上限门禁 |

## 验证

- `agent::direct_tools_mcp::tests` 23 passed / 0 failed:含新增的按 kind 上限门禁、图片快速编辑契约(断言 `POST /api/editor/images/edits` 的路径、Bearer、Idempotency-Key、正文且不得回填 assetKind)、背景音乐契约(断言 `POST /api/editor/audios/background-music/generations` 的 `gptDescriptionPrompt` 与 `makeInstrumental`)、超限零桥请求、未登记源资源提示。
- `agent::direct_tool_bridge::tests` 18 passed / 7 failed;`agent::skill_pack` 4 passed;`npm run agc:skill-pack:check` 与 `skill-pack:test` 通过(version `2026-08-26.18`)。
- AGC `typecheck`(tsc + skill-pack check + check-config)、`resourceEditModel` 6 项前端测试、`npm run check:encoding`、`npm run check:doc-index`、`cargo fmt --check`、`git diff --check` 通过。
- 那 7 条(以及 `project::resource_editor` 45 条)失败与本 PR 无关:全部是 `tempfile::tempdir()` 的 `Windows 安全对象不属于当前用户`,已 stash 改动并用基线复跑确认失败集合一致。
- 未跑整包 AGC Rust 全量分片、`npm run lint` 聚合门禁与 CI;未做任何付费生成。工具 schema 与 skill 文案都在应用内,终端用户需重新构建客户端才能看到修复效果。

---------

Co-authored-by: kdletters <61648117+kdletters@users.noreply.github.com>
Reviewed-on: #398
2026-09-17 14:56:56 +08:00
k88936 63c495dab0 DirectProject 不再把 Codex 回显的用户消息下发给聊天
- 运行态条目投影新增回显过滤 direct_thread_visible_item,item/started 与 rawResponseItem/completed 两条路径共用
- is_direct_project_codex_user_item 提升为 pub(crate),落盘侧与运行态侧共用同一判据
- 新增 E2E direct_project_turn_does_not_forward_codex_user_echo_as_chat_items:修复前事件流会多出两条同文本用户条目(已做变异验证)
- 同步 ADR 与 shared-memory decision-log:回显过滤必须同时覆盖落盘与运行态两侧
2026-09-17 14:41:58 +08:00
k88936 b37d91882c Revert "修复DirectProject对话历史分页卡页"
This reverts commit 1b010fb1f8.
2026-09-17 14:38:39 +08:00
k88936 dd339638cc Revert "修复历史重读后旧消息追加到末尾的乱序"
This reverts commit 036395c6c9.
2026-09-17 14:38:22 +08:00
k88936 0caf998227 重新生成 ts-rs 前端绑定并让前端按 null 语义构造运行时区段
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 6m35s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m31s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m15s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m47s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m15s
Project CI / Repository checks (pull_request) Failing after 19s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m15s
Project CI / Frontend tests (pull_request) Failing after 5m44s
Project CI / AI game creator shell web tests (pull_request) Successful in 5m49s
Project CI / Native shell tests (pull_request) Successful in 10m42s
- 跑 export_bindings 后 prettier 格式化:DirectCodexUser* 5 个文件内容更新,新增 DirectCodexUserMessageEnvelope.ts 与 ui-editor 的 BindingChange/BindingDTO
- DirectCodexUserRuntimeRegionPart 的可选字段由 `?:` 变成 `T | null`(Rust Option 会显式序列化成 null,不是省略键)
- chatReferenceToContentPart 改用 `?? null`,消息条目的 satisfies 目标改为 DirectCodexUserItem(type:'message' 归到信封类型)
- ResourceReferenceInput 不再复制一份区段字面量,改为复用 chatReferenceToContentPart
- 验证:tsc --noEmit 通过;resourceReferences 等 5 个用例集 81 passed;appSurface 452 passed / 17 skipped(连跑两次)
2026-09-17 14:03:05 +08:00
suzmii d85622069d Merge pull request '修复 AGC 画布交互、JSON 识别与对话历史分页' (#390) from fix/agc-canvas-json into master
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 6m27s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m12s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 6m6s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m48s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m23s
Project CI / AI game creator shell Rust crates (push) Successful in 3m16s
Project CI / Frontend tests (push) Successful in 4m23s
Project CI / Repository checks (push) Successful in 5m0s
Project CI / Backend tests (push) Successful in 7m48s
Project CI / AI game creator shell web tests (push) Successful in 3m38s
Project CI / Native shell tests (push) Successful in 10m45s
Reviewed-on: #390
Reviewed-by: 孔令弘 <ink29535@proton.me>
2026-09-17 14:02:12 +08:00
suzmii 036395c6c9 修复历史重读后旧消息追加到末尾的乱序
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 7m9s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m24s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m26s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 6m49s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 7m23s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m49s
Project CI / Repository checks (pull_request) Failing after 4m16s
Project CI / Frontend tests (pull_request) Successful in 5m46s
Project CI / Native shell tests (pull_request) Successful in 9m22s
Project CI / Backend tests (pull_request) Successful in 10m6s
Project CI / AI game creator shell web tests (pull_request) Failing after 4m22s
区分历史回读与实时消息来源,保留运行时所有权语义
防止旧页消息在历史刷新后追加到最新回复末尾
增加重新读取历史后再次翻页的顺序和去重回归
同步对话历史规范与实施计划
2026-09-17 13:54:00 +08:00
k88936 9993b2feb5 通知分类收敛成生产读取器与单测共用的唯一实现
- direct_codex_notification_event 收编 resolution / request / item / rawItem / Terminal 全部分支,并接收 turnId
- 读取器删掉自己那份内联分类,只保留「必须有 turnId 才处理」与活动/正文节流
- agentMessage 缺 itemId 的告警与 direct-missing-item:{turnId} 兜底身份原样保留,避免行为变化
- 新增 direct_notification_classification_covers_the_reader_branches 钉住各分支;E2E 假 app-server 用例继续覆盖读取器
2026-09-17 13:47:32 +08:00
k88936 d348cf9064 线程 id 只按路径归一,不再受 manifest 可读性影响
- direct_thread_id_for_project 改用 resolve_direct_codex_project_authority(存在/是目录/canonicalize)
- 不再读 .agent/manifest.json:那次读取是连接池权威身份的要求,线程 id 只是路径 key
- 否则 manifest 在订阅时读失败、跑回合时读成功,会让符号链接等非 canonical 调用方路径算出两个线程 id,订阅绑到空线程
- 新增 direct_project_thread_id_ignores_manifest_readability,旧实现下会退回调用方原始字符串(已做变异验证)
2026-09-17 13:42:35 +08:00
k88936 e640219243 思考正文改走生产路径的 ReasoningDelta 通道
- 新增 direct_codex_reasoning_delta_event,两条 reasoning 增量通知只在这一处分类
- 生产 stdout 读取器改用该函数,并跳过「preparing 活动」的降级与活动节流(活动节流会按类别吃掉逐段正文)
- 旧分类函数 direct_codex_notification_event 同步改用它,避免两份实现再次分叉
- 单测 direct_reasoning_deltas_stream_text_while_plan_and_command_output_stay_activity 取代原先断言 Activity 的旧用例
- 新增 E2E codex_app_server_streams_reasoning_deltas_without_activity_fallback:把读取器的路由关掉即转红(已做变异验证)
2026-09-17 13:22:36 +08:00
suzmii d1f53fda4d Merge branch 'master' into fix/agc-canvas-json
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 6m49s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m21s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 7m56s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 6m50s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m1s
Project CI / Frontend tests (pull_request) Successful in 4m38s
Project CI / Repository checks (pull_request) Successful in 3m43s
Project CI / Backend tests (pull_request) Successful in 8m30s
Project CI / AI game creator shell web tests (pull_request) Successful in 4m7s
Project CI / Native shell tests (pull_request) Successful in 25m34s
2026-09-17 13:05:33 +08:00
lhk229 9169ae0dad Merge pull request '修复前端测试状态泄漏与异步断言竞态' (#397) from codex/ci-frontend-stability-20260917 into master
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m15s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m59s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m18s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m46s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m0s
Project CI / AI game creator shell Rust crates (push) Successful in 2m21s
Project CI / Frontend tests (push) Successful in 5m22s
Project CI / Repository checks (push) Successful in 4m26s
Project CI / Backend tests (push) Successful in 9m22s
Project CI / AI game creator shell web tests (push) Successful in 3m53s
Project CI / Native shell tests (push) Successful in 9m49s
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/397
2026-09-17 12:29:26 +08:00
lhk229 a68a9621a7 修复前端测试状态泄漏与异步断言竞态
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 7m4s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m12s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m43s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 7m7s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m48s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m7s
Project CI / Repository checks (pull_request) Successful in 4m50s
Project CI / Frontend tests (pull_request) Successful in 5m52s
Project CI / Backend tests (pull_request) Successful in 9m13s
Project CI / Native shell tests (pull_request) Successful in 8m3s
Project CI / AI game creator shell web tests (pull_request) Successful in 5m0s
隔离创作主页换签网络请求并使用独立响应

恢复快捷键选择状态、持久化路由和UI编辑页宿主mock

修正虚拟树尺寸与选择时序并纳入换签Hook测试

记录全量与随机顺序测试验证方式
2026-09-17 11:56:17 +08:00
suzmii 9d374a57b1 修正运行不可用提示的过期测试契约
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m28s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m54s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m32s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m0s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m17s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m52s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 5m46s
Project CI / AI game creator shell web tests (pull_request) Successful in 4m15s
Project CI / Native shell tests (pull_request) Successful in 9m21s
恢复运行提示与资源选择解耦的业务逻辑
更新界面源码契约测试,保留资源选中交互回归
补充运行提示及无障碍关联的验收口径
2026-09-17 11:51:14 +08:00
lhk229 d9431b51da 隔离创作主页资源预览测试缓存
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m6s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 7m16s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m38s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m56s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m6s
Project CI / AI game creator shell Rust crates (push) Successful in 2m36s
Project CI / Frontend tests (push) Failing after 4m59s
Project CI / Repository checks (push) Successful in 4m53s
Project CI / Native shell tests (push) Successful in 9m52s
Project CI / Backend tests (push) Successful in 10m33s
Project CI / AI game creator shell web tests (push) Successful in 4m13s
每个用例前后清理签名资源地址缓存,避免共享调度状态影响活动图片断言
2026-09-17 10:05:22 +08:00
suzmii 7f9dce5f79 修复画布运行不可用提示契约
恢复资源选中状态下运行提示的正确显示条件

使源码契约测试与实际行为保持一致
2026-09-17 09:48:19 +08:00
lhk229 9beb16f203 稳定CI测试并发与工作流 (#393)
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m12s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 7m25s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m46s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 8m8s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m51s
Project CI / AI game creator shell Rust crates (push) Successful in 2m8s
Project CI / Frontend tests (push) Failing after 4m23s
Project CI / Repository checks (push) Successful in 4m31s
Project CI / Backend tests (push) Successful in 9m14s
Project CI / Native shell tests (push) Successful in 9m5s
Project CI / AI game creator shell web tests (push) Successful in 5m19s
为Project CI增加同分支并发取消,避免旧运行覆盖新结果

将Vitest默认线程数固定为1,降低异步UI测试竞态

Reviewed-on: #393
Co-authored-by: Linghong <ink29535@proton.me>
Co-committed-by: Linghong <ink29535@proton.me>
2026-09-17 09:18:39 +08:00
lhk229 9b6ed8a4cf 整理抠图测试导入并明确对外说明边界
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m13s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m52s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m49s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m50s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 6m48s
Project CI / AI game creator shell Rust crates (push) Successful in 2m41s
Project CI / Frontend tests (push) Successful in 5m30s
Project CI / Repository checks (push) Successful in 4m22s
Project CI / Native shell tests (push) Successful in 9m3s
Project CI / Backend tests (push) Successful in 9m19s
Project CI / AI game creator shell web tests (push) Successful in 5m12s
将主站与客户端抠图测试模块的导入统一放到模块顶部
明确 provider 选择与兜底策略仅保留在内部技术方案中
2026-09-17 00:54:28 +08:00
lhk229 16deb0ad61 补齐抠图参数透传与验收
修复flat自动识别门禁并严格校验模式和颜色

保持旧请求幂等指纹并区分客户端抠图意图

同步工具说明和Skill契约并补充定向测试

记录真实BgFilter验证及本地数据库阻塞的待验收项
2026-09-17 00:54:28 +08:00
lhk229 13f56e644d 补充抠图模式调用说明
说明complex语义分割与flat纯色背景抠图

明确纯色背景优先使用flat并移除内部实现术语
2026-09-17 00:54:28 +08:00
lhk229 e08b031761 调整抠图模式参数说明 2026-09-17 00:54:28 +08:00
lhk229 70ad794b28 扩展AGC抠图客户端参数
支持complex与flat模式及auto背景色

保留旧客户端参数调用兼容性
2026-09-17 00:54:28 +08:00
lhk229 ca761e093c 接通抠图模式到BgFilter队列
透传backgroundMode和screenColor到内部worker

保留auto及省略颜色的下游识别语义
2026-09-17 00:54:28 +08:00
lhk229 a17367112f 增加主站抠图参数归一化
缺省模式兼容为complex并校验颜色格式

将auto颜色原样保留给BgFilter
2026-09-17 00:54:28 +08:00
lhk229 d7a0c3cffd 扩展主站抠图请求契约
增加backgroundMode和screenColor可选字段

同步External v1 OpenAPI抠图模式说明
2026-09-17 00:54:28 +08:00
lhk229 fa64819b6e 冻结BgFilter抠图服务契约
记录flat与complex模式及auto背景色行为

补充服务器认证头和当前运行版本
2026-09-17 00:54:28 +08:00
lhk229 f748d36d21 补充AGC抠图模式透传方案
新增主站与BgFilter模式及背景色契约

补充AGC客户端同步任务与兼容性规则

记录联调验收和发布回滚边界
2026-09-17 00:54:28 +08:00
k88936 da2ad83c3b 分页锚点改用文件里的原始 item id
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 6m22s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m34s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m49s
Project CI / Backend tests (pull_request) Failing after 10s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m49s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m7s
Project CI / Repository checks (pull_request) Failing after 10s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m19s
Project CI / Frontend tests (pull_request) Failing after 6m15s
Project CI / AI game creator shell web tests (pull_request) Failing after 5m47s
Project CI / Native shell tests (pull_request) Successful in 12m22s
- 新增 direct_project_history_anchor_id:优先取 project.jsonl 原始 id,缺 id 时退回归一身份兜底
- read_direct_project_history_items_slice_at 的锚点匹配与 first_item_id 都改用原始 id
- 工具条目的调用与输出共用 call_id,按归一身份当锚点会先跳过 output 再把上一屏的 function_call 带回来
- 原分页用例更名 history_window_paginates_upwards_by_item_id_anchor
- 新增 pagination_anchor_uses_raw_item_id_for_tool_call_pairs,旧实现下会返回 call-1 而非 fc-1(已做变异验证)
2026-09-17 00:24:01 +08:00
k88936 ad19c9475e 回扫的 terminated 改成按真实换行结尾判定
- DirectProjectHistoryReverseLines 增记 saw_delimiter,第一段按"文件是否以换行结尾"判定,之后的行按已切掉的分隔符判定
- 尾部残行(上一行完整、这一行没有换行)解析失败时改为跳过继续回扫,不再报错、也不再就地结束丢掉更早的完整历史
- 换行结尾的坏行(含文件第一段)与顺序读取保持一致地失败关闭
- 补两条回扫用例:尾部残行不丢更早条目、坏掉的第一段必须失败关闭(都按旧实现变异验证过)
2026-09-17 00:18:49 +08:00
k88936 975a2e577c 终止按钮改按综合繁忙信号判定
- handleCancelDirectCodexTurn 的守卫改用 supervisorChatBusy,与「终止」按钮的可见条件对齐
- 刚提交、turn.started 还没到达的窗口里点击终止不再回"当前没有正在运行的回合"
- chat-composer 用例补一条:生命周期事件缺席时也能发出 cancel_direct_codex_turn
2026-09-17 00:10:20 +08:00
k88936 1b40f030e7 删掉聊天 reducer 里没人读的订阅身份与首屏锚点
- DirectThreadChatState 去掉 subscriptionId 与 lastCompletedItemId 两个只写不读的字段
- resolveDirectThreadBootstrap 只把 bootstrap 事件 reduce 进状态,不再顺带写入这两个字段
- directThreadChat 单测改成断言聊天状态里不再出现这两个字段(bootstrap 载荷本身不变)
2026-09-17 00:05:57 +08:00
k88936 098693636a 分页切片开头的前导条目并进后面那个回合
- buildDirectChatTurns 先攒住第一个用户条目之前的过程条目,交给后面那个回合
- 不再渲染没有用户气泡的孤儿回合;整份历史都没有用户条目时仍保留一个回合
- directTurnPresentation 单测补一条分页切片从半截回合开头的情形
2026-09-17 00:02:11 +08:00
k88936 e17af3008e 首屏历史切片改到 staleness 守卫之后再并入聊天 reducer
- loadProjectConversation 不再在 read_direct_project_history_slice 的 then 回调里直接写 directThreadChat
- 切片先暂存,等 loadVersion / localProjectPathRef 守卫通过后再与 hasMore、锚点一起落到状态
- 现有 launcher 按项目路径 key 重挂载 App,跨项目污染暂不可复现;本次只是让这条写入与其它状态写入的时序一致
2026-09-16 23:59:29 +08:00
k88936 64bd006981 测试骨架的历史切片按 limit 与锚点分页
- harness.ts 的 read_direct_project_history_slice 按生产口径从队尾取一屏、锚点条目不进窗口
- 按本屏最老一条算 firstItemId,收满一屏后再有条目才算 hasMore
- project-development.suite.ts 补一条用例:26 条历史只显示尾部 20 条,点「显示更早的对话」按锚点取回前 6 条后按钮消失
2026-09-16 23:52:02 +08:00
k88936 6a4cb2bc18 测试骨架的 subscribe bootstrap 按生产口径过滤
- harness.ts 记录未完成条目集合、事件序号与最新生命周期锚点
- subscribe 只回放未完成条目与最新生命周期锚点,已完成条目与增量正文不再补发
- 去掉已下发事件的序号记录,避免序号表无限增长
2026-09-16 23:48:46 +08:00
k88936 1b3a3b003f 测试骨架不再重复下发 turn.started
- harness.ts 记录运行态"最新回合是否在跑",emitDirectThreadEvents 只在生命周期事件上更新
- completeDirectThreadTurn 仅在回合没在跑时补 turn.started,避免与用例先发的事件重叠
2026-09-16 23:45:19 +08:00
k88936 ff8e517c8e 清理 DirectProject 回合结束后丢弃回复正文的死语句
- App.tsx 不再绑定 chat_with_game_creator_direct_codex 的返回值,删掉 void reply
- 保留说明:回复正文按条目身份从线程事件 / 历史切片进聊天,本地不再补第二条
2026-09-16 23:42:58 +08:00
suzmii ecaf1e8cec Merge branch 'master' into fix/agc-canvas-json
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m50s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m22s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m19s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m9s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m45s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m38s
Project CI / Frontend tests (pull_request) Failing after 3m50s
Project CI / Repository checks (pull_request) Failing after 4m18s
Project CI / Native shell tests (pull_request) Successful in 8m2s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m31s
Project CI / Backend tests (pull_request) Successful in 8m50s
2026-09-16 22:58:25 +08:00
k88936 d874a13a92 补记 Node 26 下 vitest jsdom 用例的 localStorage 坑
- pitfalls 记录:Node 26 的实验性 globalThis.localStorage 会顶掉 jsdom 的 Storage,导致只声明 jsdom 的用例读到 undefined
- 给出跑法:NODE_OPTIONS=--localstorage-file=… 后 clientApi 与 chatPromptPolish 共 26 项转绿
- 里程碑证据更新为全量结果:125 files / 1676 passed / 17 skipped,tsc exit 0
2026-09-16 22:41:54 +08:00
k88936 5eba53a5cc 补齐 DirectProject 聊天真相源收敛的文档结论
- 主规范:运行态事件改为下发与历史切片同形的脱敏原始条目,不再只给类型与身份
- 主规范与 ADR 写清回执竞态:回执前到达的通知只能记欠账,回执到达后必须补一次 consume
- ADR 与实施计划说明 list_game_creator_direct_active_turns 有意保留,服务首页运行中项目列表
- 里程碑验收标准按自动化证据勾选,运行时验收与已知环境缺口单独标注
- 实施计划补 export_bindings 后需 prettier 生成目录、测试文件更名与竞态风险项
2026-09-16 22:16:24 +08:00
k88936 33ddb5de27 DirectProject 聊天框改用线程订阅作为唯一运行态来源
- App.tsx 删除 Direct 回合事件订阅、turn-stream/tool-calls 读取、活动回合快照接管与瞬时应答文本
- 新增 game-creator-direct-thread-notify 唤醒的 subscribe/consume 单飞循环,过期时重订一次
- 通知先于订阅回执到达时记一笔欠账,回执到达后补一次 consume,避免回合尾部事件卡在队列里
- 历史切片并入同一个 reducer,聊天条目只由 selectDirectChatEntries 投影
- ProjectSupervisorView 改为渲染用户气泡 / 执行过程折叠区 / 最终回复,运行态只保留一个 turnRunning
- directTurnPresentation 重写为条目分区:连续工具合块、本地运行期说明只作最终提示
- 测试改按订阅事件与历史条目断言,补回执竞态、持久化工具卡片、空对话首轮三条用例
2026-09-16 22:16:15 +08:00
k88936 bf8f96c115 DirectProject 回合事件补齐用户条目与终态兜底
- 新增 direct_thread_id_for_project:订阅、回合事件写入与兜底释放共用一个线程身份
- 订阅命令改用同一个身份函数,删掉命令层自己那套路径归一
- 用户消息落盘后立刻作为 item.completed 下发,前端用同一个 itemId 合并乐观气泡与历史条目
- 采集终态事件是否已经下发,缺失时按成功 / 失败补一条 turn.completed,避免前端永远停在运行中
- 取消回合的 Stale 分支补一条 turn.completed(aborted)
2026-09-16 22:15:57 +08:00
lhk229 79b153e3fa 修复Direct活动回合重试类型错误
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m53s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m5s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m26s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m51s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m49s
Project CI / AI game creator shell Rust crates (push) Successful in 2m23s
Project CI / Frontend tests (push) Failing after 4m42s
Project CI / Repository checks (push) Successful in 4m44s
Project CI / Backend tests (push) Successful in 9m27s
Project CI / Native shell tests (push) Successful in 9m17s
Project CI / AI game creator shell web tests (push) Failing after 5m2s
重试等待 Promise 显式声明为 void,修复 shell typecheck 与原生构建失败。

补充卸载后取消读取重试的回归测试。
2026-09-16 21:53:19 +08:00
lhk229 362edcc49d 修复前端测试偶发超时与异步清理
Direct 活动回合读取失败后的重试定时器随组件卸载清理,避免测试环境销毁后访问 window。

后台素材查询大量缩略图测试合并可见性触发,并补充独立超时预算。

创作首页活动图与资源卡预览调度重载用例分别补充独立超时预算。

清单快照测试补齐 Direct 活动回合 IPC mock,避免未预期命令进入重试。
2026-09-16 21:53:19 +08:00
kdletters 1e434e0cb5 文档记录 CI 宿主 CPU 上限:Jenkins 16 核 / Gitea Actions runner 12 核
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m57s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m10s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m35s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m56s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m46s
Project CI / AI game creator shell Rust crates (push) Successful in 1m47s
Project CI / Repository checks (push) Successful in 3m34s
Project CI / Frontend tests (push) Successful in 4m25s
Project CI / Native shell tests (push) Successful in 7m56s
Project CI / AI game creator shell web tests (push) Successful in 4m32s
Project CI / Backend tests (push) Successful in 10m1s
- 在【开发运维】本地开发验证与生产运维新增「CI 宿主 CPU 上限」小节,写明 jenkins.service CPUQuota=1600% 与 gitea-stack runner cpus=12.0 的生效位置、核验命令和回滚方式
- 在 shared-memory/decision-log.md 补记该资源上限决策的背景、边界与验证证据
2026-09-16 21:17:30 +08:00
k88936 3c6e084a41 DirectProject 历史切片改为从文件尾回扫并删掉聊天框只读命令
- 新增 DirectProjectHistoryReverseLines:按块从文件尾逐行回读 project.jsonl
- 幂等回扫与"读一屏"共用这一套尾部回读,不再各自从文件头读到尾
- read_direct_project_history_items_slice_at 语义不变仍返回元组,新增第四项为本屏最老的 itemId 作分页锚点
- 分页锚点只按归一身份 itemId 匹配,不再接受第二个 id
- read_direct_project_last_item_id_at 改为尾部回扫读一行,不再读整份历史
- 删除只服务聊天框回读的 read_direct_tool_calls / read_direct_turn_stream 命令与注册
- 保留 list_game_creator_direct_active_turns:它服务首页跨页面"运行中的项目",不是聊天框读路径
- 补历史切片尾部回扫与分页锚点两条用例
2026-09-16 20:17:15 +08:00
k88936 ed3369a494 文档先行:把 DirectProject 聊天真相源收敛的文档改到当前实现状态
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 5m13s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m30s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m39s
Project CI / Backend tests (pull_request) Failing after 12s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m43s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m8s
Project CI / Repository checks (pull_request) Failing after 10s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m10s
Project CI / Frontend tests (pull_request) Failing after 3m24s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m7s
Project CI / Native shell tests (pull_request) Successful in 6m8s
- 主规范把事件模型写成 ts-rs 导出的 tagged enum,说明 seq 不下发、事件不带回合身份,并补上 ts 绑定生成与 f64 时间戳约定
- ADR 补上 tagged enum 绑定、turn id 删除、正文只增不减与回合回收、前端卡片去掉 turnId、未知类型前端丢弃
- 里程碑与实施计划同步:文件改名到 direct_thread_wire.rs,新增删回合身份与生成绑定两步,验证命令加上 export_bindings
- 工具卡片技术方案在文首加修订段:数据来源层作废,表现层契约仍然有效,DirectRuntime 的 tool-calls.jsonl 写入保留
- 对话回合唯一投影里程碑改为 superseded,列出仍然有效与已作废的分界
2026-09-16 19:57:21 +08:00
lhk229 cec971c438 修复局部修改工具的缺陷和偶发锁问题 (#386)
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m49s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 4m50s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m53s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m16s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m1s
Project CI / AI game creator shell Rust crates (push) Successful in 2m14s
Project CI / Frontend tests (push) Failing after 4m6s
Project CI / Repository checks (push) Successful in 4m33s
Project CI / Native shell tests (push) Successful in 6m33s
Project CI / Backend tests (push) Successful in 8m26s
Project CI / AI game creator shell web tests (push) Successful in 3m43s
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/386
Co-authored-by: Linghong <ink29535@proton.me>
Co-committed-by: Linghong <ink29535@proton.me>
2026-09-16 19:53:23 +08:00
k88936 fdc48fe725 前端聊天投影按 ts-rs 生成类型收口,删掉 callId 与回合身份
- directThreadItemProjection.ts 直接消费生成的 DirectThreadItem,工具卡片 kind / 标题 / 摘要 / 状态与可见性判定都在这里
- directThreadChat.ts 聊天条目只留一个 itemId:去掉 callId 概念,去掉 deltaText 缓冲,增量直接追加到运行态条目正文
- 合并规则收成先到者赢、后到只补空:正文只增不减、工具状态允许从 running 升级到终态
- 回合结束把运行态条目并入历史并清空 live,条目既不消失也不重复
- directThreadEvents.ts 改为转发 ts-rs 绑定,只保留历史条目转消息的过渡函数
- ToolCallGroup 与 toolCallGroupPresentation 改用去掉回合身份的 DirectChatToolCard
- generated/index.ts 补上 DirectThread* 绑定导出
- 回退本仓库其它模块仍在改的 DirectCodexUser* 绑定重新生成(避免误改他人进行中的契约)
- 两个 vitest 用例文件按新 API 重写,11 条用例通过
2026-09-16 19:49:26 +08:00
k88936 2748468d12 DirectProject 聊天事件改用 ts-rs 导出的 tagged enum 并删掉 turn id
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 5m11s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m51s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m57s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m50s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m2s
Project CI / Repository checks (pull_request) Failing after 15s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m14s
Project CI / Native shell tests (pull_request) Failing after 2m13s
Project CI / AI game creator shell web tests (pull_request) Failing after 46s
Project CI / Frontend tests (pull_request) Failing after 3m32s
- 新增 direct_thread_wire.rs:DirectThreadItem / DirectThreadEvent / 订阅与历史切片全部改成 ts-rs 导出的 tagged enum,取代原大而全的可空结构体
- 删除 direct_thread_raw_item.rs,模块注册与直通引用改到 direct_thread_wire
- 条目身份只看一个 itemId:工具条目的第二个 id 在 Rust 边界归一,不再对外暴露
- 删除 DirectProject 聊天事件里的 turn id:生命周期用无载荷的 turn.started / turn.completed{status} 表示
- append 直接接收 DirectThreadEvent 并返回同一事件,队列内部自算 seq
- 请求事件改为携带 DirectThreadRequestKind,去掉字符串中转
- 思考增量走 ReasoningDelta 通道,与正文增量共用 item.delta
- at 用 #[ts(as = "f64")] 对齐 Tauri JSON 通道的 number
- 用 cargo test export_bindings 重新生成 project-workspace/generated 绑定
2026-09-16 19:43:57 +08:00
suzmii fca3df964c Merge branch 'master' into fix/agc-canvas-json
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m15s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m31s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m21s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m1s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m39s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m48s
Project CI / Frontend tests (pull_request) Failing after 3m36s
Project CI / Repository checks (pull_request) Failing after 3m56s
Project CI / Native shell tests (pull_request) Successful in 6m40s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m18s
Project CI / Backend tests (pull_request) Successful in 8m18s
2026-09-16 19:29:05 +08:00
lhk229 70157673b6 Merge branch 'master' into fix/ci
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m27s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m46s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m12s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m30s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m41s
Project CI / AI game creator shell Rust crates (push) Successful in 2m48s
Project CI / Frontend tests (push) Successful in 4m49s
Project CI / Repository checks (push) Successful in 3m43s
Project CI / Native shell tests (push) Successful in 6m41s
Project CI / Backend tests (push) Successful in 7m17s
Project CI / AI game creator shell web tests (push) Successful in 3m26s
2026-09-16 19:07:53 +08:00
k88936 09ad0073fe 修正 DirectProject 订阅语义:bootstrap 事件就是当前要处理的事件
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
subscribe 已在同一边界把游标钉在队尾,因此前端直接 reduce bootstrap 事件,不再补一次 consume
主规范、ADR 与实施计划同步删除"竞态窗口"说法,notify 仍是唯一唤醒来源
2026-09-16 19:06:05 +08:00
k88936 42b702d362 按 grill 结论修正 DirectProject 聊天真相源收敛计划
里程碑与实施计划改定边界:Thread Manager 只搬运脱敏原始条目,不生成卡片形状与可见性
条目身份归一为 call_id ?? id,Thread Manager 与前端不再暴露第二个 id 概念,分页锚点仍取文件里的原始 item id
合并规则收敛为"先到定形、后到补空白",删除逐字段优先级表
主规范补充条目形状三条职责边界,并说明思考正文流式下发不放宽可见范围
ADR 同步:DirectRuntime 自己的进度事件与投影文件保留,前端删除的是 DirectProject 的读路径
失败与中止说明只在运行期显示;历史切片改为从文件尾反向扫描;未知 item 类型透传并加 TODO
2026-09-16 19:05:04 +08:00
suzmii ac8a51ca79 同步master最新基线并准备画布修复PR
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
合入平台会话与主线测试修复
保持画布交互、JSON识别和对话历史分页修复范围不变
2026-09-16 18:59:32 +08:00
kdletters 492e9e63af 合入 AGC 终止链路 abort 闪退修复
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m20s
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (push) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (push) Has been cancelled
codex_app_server 新增 spawn_codex_app_server_task,统一经 tauri::async_runtime::spawn 派发
终止链路、CodexThreadLease::drop、CodexTurnGuard::drop 三处不再在同步命令线程上 tokio::spawn
新增回归用例 codex_app_server_task_dispatch_needs_no_tokio_runtime_context
补记 tokio::spawn 导致 abort 闪退、cargo test 重写 generated 绑定两条踩坑
2026-09-16 18:58:19 +08:00
lhk229 57fae7037a 修复 Agent 异步测试等待
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m13s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m24s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m52s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m12s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m38s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m42s
Project CI / Frontend tests (pull_request) Successful in 4m28s
Project CI / Repository checks (pull_request) Successful in 3m39s
Project CI / Native shell tests (pull_request) Successful in 6m59s
Project CI / Backend tests (pull_request) Successful in 7m37s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m55s
移除不稳定的项目页文案前置

保留刷新 Agent 与拆解任务按钮就绪检查
2026-09-16 10:52:25 +00:00
suzmii 1b010fb1f8 修复DirectProject对话历史分页卡页
聊天历史按有效消息分页并返回原生游标,保留默认原始切片接口
工具和推理记录不占聊天页名额,逐行过滤避免传回大段工具输出
隔离重新加载和项目切换的迟到响应,补齐单飞、重试与消息去重
补充原生和真实App回归测试,增加人工只读日志重放入口
更新B05状态、规范与PR验收记录,不提交用户原始日志
2026-09-16 18:46:47 +08:00
k88936 656c89e4b2 把 DirectProject 聊天条目的投影从前端收口,Rust 只搬运脱敏原始条目
新增 agent/direct_thread_raw_item.rs:把 Codex 原始 response item 与 app-server item 收敛成同一形状的脱敏原始条目,只做挑字段、脱敏、截断,不再生成卡片的 kind / 标题 / 折叠摘要
删除 agent/direct_chat_entry.rs:工具卡片形状不再由 Rust 生产
历史切片改为返回脱敏原始条目列表,不再在 Rust 侧合并 function_call 与 function_call_output
新增前端 directThreadItemProjection.ts:工具卡片 kind / 标题 / 摘要 / 状态与可见性判定全部在前端完成
directThreadChat reducer 改用同一投影函数处理运行态事件,新增 mergeDirectHistoryItems 走同一份投影与合并规则
DirectThreadHistorySlice 去掉 entries 与 itemTimestamps,改为 items + firstItemId
2026-09-16 18:45:13 +08:00
kdletters 2bcfa10647 修复 AGC 客户端点「终止」整体闪退:同步命令线程改走 Tauri 全局异步 runtime
- codex_app_server 新增 spawn_codex_app_server_task,统一经 tauri::async_runtime::spawn 派发中断与收尾任务
- 终止链路 maybe_interrupt、CodexThreadLease::drop、CodexTurnGuard::drop 三处改走该入口,避免同步 Tauri 命令线程上 tokio::spawn panic 后跨 IPC 回调边界 abort
- 新增回归用例 codex_app_server_task_dispatch_needs_no_tokio_runtime_context,把派发入口钉在没有 tokio 上下文的线程上
- 同步 agc-skills manifest 指纹,修复 master 指纹回退导致的 skill-pack:check 失败(本地打包前置门禁)
- 记录两条踩坑:同步命令线程 tokio::spawn 导致客户端 abort 闪退、cargo test 重写 generated/*.ts 后前端 typecheck 必红
2026-09-16 18:40:14 +08:00
kdletters e777236817 补齐 decision-log 两处标题前缺失的空行
恢复引言引用块、2026-09-16 图标图集条目之前的空行分隔,与文件既有排版一致
仅新增两行空行,不改动任何决策条目内容
2026-09-16 18:35:52 +08:00
lhk229 d11c74212d Merge pull request '修复 AGC skill 包与 Agent 测试' (#387) from fix/ci into master
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m15s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 5m16s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m38s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 6m8s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m45s
Project CI / AI game creator shell Rust crates (push) Successful in 2m28s
Project CI / Frontend tests (push) Failing after 3m36s
Project CI / Repository checks (push) Failing after 3m40s
Project CI / Native shell tests (push) Successful in 6m48s
Project CI / Backend tests (push) Successful in 7m47s
Project CI / AI game creator shell web tests (push) Failing after 3m44s
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/387
2026-09-16 18:33:52 +08:00
lhk229 82b2f853e7 修复 AGC skill 包与 Agent 测试
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
同步工作流和试玩 skill 指纹

等待项目页面与拆解任务按钮就绪
2026-09-16 10:31:57 +00:00
k88936 0ec1179bf1 移除前端 consume 轮询兜底
- 唤醒只由 notify 驱动,bootstrap 后立刻 consume 一次补齐竞态窗口
- 定时 tick 无法自举:判断活动回合本身依赖事件,唤醒丢失时定时器不会启动
- 主规范、ADR 与实施计划同步删除该条款
2026-09-16 18:17:38 +08:00
k88936 2938a49cac 固化 DirectProject 聊天真相源契约
- 主规范新增首屏锚点、生命周期锚点必进 bootstrap、事件自足与不提供单点快照四条契约
- 新增 ADR 记录单一事实源取舍、删除清单与待验证的 id 空间风险
- 新增里程碑与实施计划,CONTEXT.md 补项目对话历史/运行态事件/聊天投影词条
- 目标文档合同与文档索引同步
2026-09-16 18:05:30 +08:00
k88936 ae0f9376c9 新增 DirectProject 聊天 reducer 深模块
- directThreadChat 把运行态事件与历史切片归并成同一份聊天条目,活动回合只由 turn.started/turn.completed 判定
- item.delta 载荷补 kind,reducer 不再靠 itemId 猜条目类型
- bootstrap 原子替换运行态并保留历史窗口,历史与运行态按 callId ?? itemId 去重合并
- 新增 5 条 reducer 单测
2026-09-16 18:05:10 +08:00
kdletters 31f83a751a 三维请求自选技术栈,不再固定 Phaser
Project CI / AI game creator shell Rust shard 2/4 (push) Failing after 4m35s
Project CI / AI game creator shell Rust shard 1/4 (push) Failing after 5m18s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m32s
Project CI / AI game creator shell Rust shard 3/4 (push) Failing after 5m7s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 3m54s
Project CI / AI game creator shell Rust crates (push) Successful in 2m26s
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
- DirectProject 系统提示新增三维请求合同:三维请求不受 Phaser 4.2.1 约束,由 Codex 自选三维技术栈
- 工程合同的 Phaser 固定约束按二维/三维分层,点名引擎的不匹配澄清规则保持不变
- 新增三维意图识别、三维回合合同与首页三维提示;伪 3D、等轴与代码话题不触发
- 补定向用例与里程碑/实施计划文档,并在 decision-log 记录该决策
2026-09-16 18:04:44 +08:00
k88936 29d0cbb4df 运行态事件与历史切片共用聊天条目投影
- 新增 direct_chat_entry 深模块,把原始 response item 与 app-server item 投影成同一聊天条目
- item.started/item.completed 载荷改为完整条目,前端不再需要按 itemId 取快照
- 原始 function_call 与 function_call_output 按 callId 并成一张卡片,文本与明细统一脱敏截断
- 历史切片新增 entries 与 first_item_id,分页锚点不再依赖是否出现可显示条目
2026-09-16 18:01:50 +08:00
lhk229 a1cafde7e9 修复 AI 创作壳测试稳定性
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (push) Failing after 4m35s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m32s
Project CI / AI game creator shell Rust shard 3/4 (push) Failing after 4m48s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 4m59s
Project CI / AI game creator shell Rust shard 2/4 (push) Failing after 5m37s
Project CI / AI game creator shell Rust crates (push) Successful in 2m42s
Project CI / Native shell tests (push) Failing after 2m47s
Project CI / Frontend tests (push) Failing after 3m29s
Project CI / AI game creator shell web tests (push) Failing after 49s
Project CI / Repository checks (push) Failing after 3m16s
Project CI / Backend tests (push) Successful in 7m7s
调整 Agent 项目打开测试的异步就绪等待

延长权限策略连续命令测试超时预算

同步 taonier-art-assets skill-pack 内容指纹

补充对应实施计划中的测试约定
2026-09-16 09:57:21 +00:00
k88936 721e45f01b 统一 DirectProject 运行态条目的合并身份
- Thread Manager 事件新增 callId,条目身份统一为 callId 优先、其次 itemId
- 工具条目按 callId 归并 started/completed,不再留下永远收不到完成事件的幽灵活跃条目
- 历史锚点仍取 response item id,保证分页锚点能在 project.jsonl 中命中
- 补充跨 id 空间归并的单元测试
2026-09-16 17:45:28 +08:00
suzmii 825ea76b7b 同步master最新变更
合入当前主线的多窗口与配置更新
保留AGC画布交互和JSON识别修复
保留双方新增的项目排障记录并解决文档冲突
2026-09-16 17:45:06 +08:00
kdletters 0594a90bdd 合入平台会话身份与凭据分离
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 4m15s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m32s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m58s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m13s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 5m3s
Project CI / AI game creator shell Rust crates (push) Successful in 3m1s
Project CI / Frontend tests (push) Failing after 4m24s
Project CI / Repository checks (push) Successful in 4m1s
Project CI / Native shell tests (push) Successful in 7m45s
Project CI / AI game creator shell web tests (push) Failing after 3m4s
Project CI / Backend tests (push) Successful in 8m20s
平台会话快照拆分身份代次与写入 revision,凭据续期轮换不再中断在途生成
AGC Runner 请求参数新增 platform_auth_revision,并按 revision 做单调写入判定
解决与多窗口共享 Runner 的冲突,保留 claim adopt/publish 与界面参与锁语义
同步刷新轮换竞争、appSurface 鉴权用例与客户端 API 测试
补录平台会话身份与凭据分离的实施计划、共享记忆与决策记录
2026-09-16 17:42:00 +08:00
suzmii 910862fd06 修复AGC画布交互并识别UI设计JSON
稳定工作台与窗口标题栏状态同步,消除重复更新循环
支持画布右键平移并保留左键框选及资源拖动,完善中断清理
解耦运行不可用提示与资源选中状态
复用原生UI状态校验区分UI设计JSON和普通JSON,接入现有编辑器与代码预览
补充前端和原生回归测试、规范及待验收记录,明确对话历史分页尚未修复
2026-09-16 17:39:23 +08:00
kdletters aee862532c 删除已完成的多窗口里程碑临时文档
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 4m38s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m57s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m36s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m52s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m42s
Project CI / AI game creator shell Rust crates (push) Successful in 2m39s
Project CI / Repository checks (push) Successful in 3m58s
Project CI / Frontend tests (push) Successful in 5m53s
Project CI / Native shell tests (push) Successful in 6m28s
Project CI / Backend tests (push) Successful in 7m49s
Project CI / AI game creator shell web tests (push) Successful in 2m8s
- 按规范驱动开发工作流,里程碑与实施计划属临时产物,合并后删除
- 持久结论已回写 AGC 技术方案 2026-09-16 节、共享记忆决策记录与踩坑记录
2026-09-16 17:15:22 +08:00
kdletters 42be8ea060 发布 AGC 标准版 0.1.47
- 版本号同步到 0.1.47:package.json / package-lock.json / tauri.conf.json / Cargo.toml / Cargo.lock
- 构建脚本读取 OSS 清单(已有 0.1.46)后自动递增,本版打包产物为 陶泥儿_0.1.47_x64-setup.exe
- 本轮同时包含同 AppData 多窗口共享 Agent Runner 的修复
2026-09-16 17:15:15 +08:00
kdletters b48293fb1f 收敛平台会话 epoch 重装语义,避免原生计数与渲染层漂移
- GUI owner 重装与清除改为按 authority 快照重定基准,保持原生计数与渲染层认知一致
- 注释写明 epoch 交接的授权前提,以及写入单调性由渲染层 reserve 与 durable session revision 保证
- 同主体换凭据的重装保持身份代次,在途 operation 的冻结会话继续有效
- 补充 epoch 重装与换主体失效的回归用例,替换原先错误假设原生计数器单调的用例
2026-09-16 17:08:47 +08:00
kdletters e08171fd2e 补记平台会话身份与凭据分离的规范与记忆
- 主规范新增平台会话身份与凭据分离条款,并修正长回合保活的口径
- 共享记忆补充并发生图登录态冲突的排障口径与验证方式
- 决策记录补充身份代次、凭据轮换、刷新失败语义的长期决策
- 新增本次里程碑与实施计划,记录证据与未验证项
2026-09-16 17:08:47 +08:00
kdletters 479120d368 修复刷新轮换竞争被放大成登出
- refresh 接口的轮换失败不再下发清空 refresh cookie 的响应,避免删掉并发请求刚写入的有效 cookie
- 缺少 refresh cookie 的失败保持无副作用,cookie 失效只由吊销、过期或身份变更决定
- 网站前端在刷新返回 401 时先用当前 cookie 收敛重试一次,重试仍被拒绝才判权威失效
- 网站前端只在当前鉴权代次未变化时重试刷新,避免旧账号结论污染新代次
- 更新 api-server 与前端断言,覆盖轮换竞争与收敛重试两条路径
2026-09-16 17:08:47 +08:00
kdletters 4182979a19 平台会话身份与凭据分离,续期不再中断在途生成
- 原生会话快照拆成身份代次与写入 revision,安装与清除按 revision 排序、按身份归属判定
- 冻结平台会话校验改为只比身份,同账号 access token 轮换不再让在途生成、编辑、上传、确认和下载失败
- 同一身份代次禁止更换登录主体或服务 origin,换号、退出和 origin 变化继续失败关闭
- Runner attach 新增 platform_auth_revision,平台会话安装与校验按 revision 排序、按身份归属判定
- GUI owner 替换与清除改为计数器只增不减,同一主体重装保持身份代次,避免旧 epoch 迟到写入复活
- renderer 拆分平台原生身份代次与写入 revision,同账号续期只更新凭据,不推进身份代次
- 刷新失败结果新增权威失效判定,只有服务端明确 401 与 403 才清除本地会话,网络错误和 5xx 保留会话
- 收敛刷新判据,重复的刷新工具函数合并为一个对外判定,去掉一次性包装
- 补齐平台会话身份判据、续期与迟到写入的 Rust 与前端回归用例
2026-09-16 17:08:46 +08:00
kdletters 737a2266b9 支持同 AppData 多窗口共享 Agent Runner
- owner 独占锁改为可多窗口同时持有的界面参与锁 agent-runner.gui-participant.lock
- Runner 启动检查、attach 门禁与 watchdog 改用参与锁存活判定,最后一个窗口退出才关停 Runner
- 窗口启动只采纳现有 owner claim,登录/refresh/退出/换号才发布新 epoch claim
- 同 claim 重复 attach 改为幂等空操作,不再清空 Runner 平台登录态
- manifest 失效与 Runtime update relay 接收端改为按 token 去重的注册表并广播,失败只淘汰该接收端
- GUI 退出先释放参与锁,仍有其它窗口时保留 Runner 并记录 retained_for_other_windows
- Runner 启动失败时按最新 endpoint 复用一次,避免两窗口同时冷启动被实例锁竞争误报
- 更新 runner 定向测试、GUI 生命周期集成测试与自检用例
- 同步 AGC 技术方案、决策记录、踩坑记录与多窗口里程碑/实施计划
2026-09-16 16:56:21 +08:00
lhk229 262deaf9b7 接入做成游戏后的策划文档指令 (#383)
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 4m46s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m22s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m14s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m16s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 4m17s
Project CI / AI game creator shell Rust crates (push) Successful in 4m1s
Project CI / Frontend tests (push) Successful in 4m32s
Project CI / Backend tests (push) Successful in 7m54s
Project CI / Repository checks (push) Successful in 4m19s
Project CI / AI game creator shell web tests (push) Failing after 4m9s
Project CI / Native shell tests (push) Successful in 9m12s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m35s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m39s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m3s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 6m9s
Project CI / Backend tests (pull_request) Failing after 19s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m40s
Project CI / Repository checks (pull_request) Failing after 9s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m16s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m32s
Project CI / Frontend tests (pull_request) Successful in 6m10s
Project CI / Native shell tests (pull_request) Successful in 8m50s
## 变更说明

点击策划阶段的“做成游戏”后,切换到 GameAgent 并自动发送读取 `design_artifacts/` 文档的指令。

## 验证

- npm run typecheck
- git diff --check
- 提交钩子 ESLint / Prettier

Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/383
2026-09-16 16:51:37 +08:00
kdletters c36a5170f8 AGC 新增本地自定义 LLM 配置与展示模型勾选
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m28s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m29s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m6s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m6s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m46s
Project CI / AI game creator shell Rust crates (push) Successful in 2m51s
Project CI / Frontend tests (push) Successful in 4m44s
Project CI / Native shell tests (push) Successful in 6m31s
Project CI / Repository checks (push) Successful in 4m17s
Project CI / Backend tests (push) Successful in 7m48s
Project CI / AI game creator shell web tests (push) Successful in 3m43s
- 本地配置新增 llm.customEnabled 与 llm.visibleModels,显式开启后保留自定义连接和勾选列表,官方路由下仍清空凭据
- 配置迁移始终写出 customEnabled、visibleModels、apiKey、baseUrl、model、apiKind、reasoningEffort,便于手写自定义连接
- 新增 discover_game_creator_llm_models 命令,直连自定义端点 GET /models,限制超时与响应大小并脱敏错误
- codex_app_server 自定义模式改用配置里的地址与 Key 走本地凭据代理,不再经过平台 /api/llm,也不回退官方路由
- 模型目录按官方与自定义来源隔离缓存,自定义模式只展示勾选模型,选项失效时回退第一项
- 设置页在自定义模式展示 API 地址、API Key、协议与推理档,并提供模型读取、搜索、勾选与已勾选预览
- 补齐固定项排版与读取按钮样式,同步 AGC 模型选择规范、实施计划与共享概览
2026-09-16 16:39:15 +08:00
kdletters 9663bbf911 修复 AGC 客户端登录失败原因提示
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 6m7s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 6m13s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 6m32s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 6m38s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m38s
Project CI / AI game creator shell Rust crates (push) Successful in 2m29s
Project CI / Frontend tests (push) Successful in 4m42s
Project CI / Repository checks (push) Successful in 4m2s
Project CI / Native shell tests (push) Successful in 7m45s
Project CI / Backend tests (push) Successful in 8m39s
Project CI / AI game creator shell web tests (push) Successful in 3m0s
- clientAuth 错误响应解析兼容未带 envelope 的旧形态错误体,密码错误时显示接口返回原因而不是固定“登录失败”
- 非 JSON 与结构无法识别的响应继续使用本地化兜底,不回显内部英文和原始 JSON
- appSurface 认证用例补充 envelope 与旧形态两条回归测试
2026-09-16 16:05:59 +08:00
316 changed files with 24216 additions and 5230 deletions
@@ -32,7 +32,7 @@ Prefer `scripts/genarrative_external_api.py` for runnable REST calls. It uses on
- Use stable references such as `objectKey`, project resource ID, or asset ID where each operation permits them. Image edit/redraw is stricter: `sourceReferenceId` accepts only a registered project resource ID or asset ID; upload confirmation alone is not enough. Use `/assets/read-url` only for temporary preview/download access.
- Preserve both warning channels after completion. A general `warning` can coexist with `sliceWarning`; do not discard either.
- Do not invent missing derivatives. A source-preserved warning means the main source remains usable but requested post-processing failed. A slice warning means the complete transparent sheet is usable but individual slices are absent.
- Icon spritesheet generation accepts `sliceMode="connected-components"` (default alpha-connectivity detection) or `sliceMode="grid"`. Grid mode requires `gridX` and `gridY` (1-32); use `sliceCount` only to constrain connected-component output.
- Icon spritesheet generation requires an explicit `sliceMode` and has no default. Use `sliceMode="grid"` with the `gridX` and `gridY` the requirement actually names (1-32 each) only for equal grid cells or fixed slots; use `sliceMode="connected-components"` for free-form sheets or an open number of subjects, and constrain the count with `sliceCount` instead of inventing grid dimensions. `connected-components` must not carry `gridX`/`gridY`; an omitted, contradictory, or misapplied declaration returns 400 before billing.
- For successful `style="pixelArt"`, treat completed-result and nested resource/asset dimensions as the final logical-grid PNG dimensions. They may differ from `size`, `imageSize`, the provider image, and `canvasCompletion.placeholder`; do not rescale or reject the artifact to match those inputs.
- Keep generated artifacts in the canvas and asset library together. Character animation accepts `assetFolderId` and `assetLabel`; its completed result directly returns the final `assetKind="character-animation"` resource and asset with formal sequence fields. Do not create a duplicate first-frame record.
@@ -94,7 +94,7 @@ For image edit/redraw, confirming an upload is not sufficient: create a project
The icon-spritesheet primary `referenceId` is intentionally stricter than ordinary image references: it accepts only a current-owner project resource ID or asset ID whose authoritative `assetKind` is `icon-spec`. It does not accept an `objectKey`, URL, Data URL, or Blob URL.
`sliceMode` controls atlas splitting. Use `"connected-components"` (default) to detect independent opaque regions by alpha connectivity, or `"grid"` with positive `gridX` and `gridY` values (maximum 32 each). `sliceCount` optionally constrains the connected-component result.
`sliceMode` is required and has no default, so every request must state it. Use `"connected-components"` to detect independent opaque regions by alpha connectivity, or `"grid"` with positive `gridX` and `gridY` values (maximum 32 each) only when the requirement names equal grid cells or fixed slots; the dimensions must come from that requirement. `connected-components` must not carry `gridX`/`gridY`, and `sliceCount` constrains the connected-component result instead of expressing a grid. Omitting `sliceMode`, or contradicting the declared mode with grid dimensions, returns 400 before pricing, enqueueing, or any provider call.
## Common Values
@@ -79,9 +79,9 @@ Keep the existing autonomous-build task graph. Do not add a parallel task system
1. `art-director` generates `assets/art-spec.png` with image generation, `kind: "spec"`, then registers it as `assetKind: "icon-spec"`. This image is the authoritative visual spec; `generationInputs.artSpec` is supporting structured context.
2. `design-foundation` generates `assets/ui-prototype.png` with `kind: "ui-design"`, using the registered art-spec resource ID in `referenceImageSrcs`.
3. `art-asset-plan` generates transparent `assets/art-spritesheet.png` through icon spritesheet generation, using the same registered art-spec resource ID as `referenceId` plus concrete `iconDescriptions`. For a fixed four-category game contract it may send `sliceMode: "grid"`; for free-form assets use `sliceMode: "connected-components"` (the default).
3. `art-asset-plan` generates transparent `assets/art-spritesheet.png` through icon spritesheet generation, using the same registered art-spec resource ID as `referenceId` plus concrete `iconDescriptions`. `sliceMode` is required and has no default: send `sliceMode: "grid"` with `gridX`/`gridY` only when the requirement itself fixes the slots or names the column/row count, and otherwise send `sliceMode: "connected-components"` (with `sliceCount` when a subject count must be constrained); never invent a grid to express "kinds of assets", and never send `gridX`/`gridY` with `connected-components`.
For a playable Canvas game, do not stop at generation. Make `code-prototype` depend on `art-asset-plan` and consume the persisted `iconImageSrcs` slices for core players, blocks or targets, scene obstacles, and feedback. When using the fixed four-category contract, require response `sliceMode: "grid"` and exactly four slices before registering the local runtime sheet; both fewer and extra components fail closed. Treat `art-spec.png` as reference-only. A full-sheet `<img>`, CSS background, path-only mention, guessed equal-grid crop, or code-drawn replacement for core entities is not runtime asset use. If slicing produces `sliceWarning`, keep the complete transparent sheet as a valid editor artifact, but fail the playable game asset gate until real slice files or verified atlas coordinates exist; never invent coordinates or replace the icon-spritesheet route with ordinary image generation.
For a playable Canvas game, do not stop at generation. Make `code-prototype` depend on `art-asset-plan` and consume the persisted `iconImageSrcs` slices for core players, blocks or targets, scene obstacles, and feedback. When the requirement fixes grid slots, require the response `sliceMode` to match the declared `grid` request and exactly `gridX × gridY` slices before registering the local runtime sheet; a connected-components request is instead judged by its own `sliceCount` or by the requirement, and both fewer and extra components fail closed. Treat `art-spec.png` as reference-only. A full-sheet `<img>`, CSS background, path-only mention, guessed equal-grid crop, or code-drawn replacement for core entities is not runtime asset use. If slicing produces `sliceWarning`, keep the complete transparent sheet as a valid editor artifact, but fail the playable game asset gate until real slice files or verified atlas coordinates exist; never invent coordinates or replace the icon-spritesheet route with ordinary image generation.
Never use `assets/ui-prototype.png` as the spritesheet visual-spec reference. UI extraction is outside this canonical DAG.
@@ -617,6 +617,7 @@ class GenarrativeExternalClient:
self,
reference_id: str,
icon_descriptions: list[str],
slice_mode: str,
**fields: Any,
) -> Any:
reference_id = normalize_optional_text(reference_id)
@@ -625,6 +626,20 @@ class GenarrativeExternalClient:
descriptions = [item.strip() for item in icon_descriptions if item.strip()]
if not descriptions:
raise GenarrativeApiError("icon_descriptions must contain at least one non-empty item")
slice_mode = normalize_optional_text(slice_mode)
if slice_mode not in ("connected-components", "grid"):
raise GenarrativeApiError(
"slice_mode must be declared explicitly as 'connected-components' or 'grid'; the API has no default"
)
grid_x = fields.get("gridX")
grid_y = fields.get("gridY")
if slice_mode == "grid":
if grid_x is None or grid_y is None:
raise GenarrativeApiError("slice_mode='grid' requires both gridX and gridY")
elif grid_x is not None or grid_y is not None:
raise GenarrativeApiError(
"slice_mode='connected-components' must not carry gridX/gridY"
)
label = fields.get("assetLabel", "图标图集")
self._apply_canvas_session_fields(fields, label, 1024, 1024)
fields.setdefault("screenColor", "auto")
@@ -635,6 +650,7 @@ class GenarrativeExternalClient:
**fields,
"referenceId": reference_id,
"iconDescriptions": descriptions,
"sliceMode": slice_mode,
},
idempotency_key=idempotency_key,
)
@@ -879,9 +895,9 @@ def _self_test() -> None:
client.generate_icon_spritesheet(
"editor-resource-spec",
["蛇头向上", "蛇身直线", "转角", "尾部", "四类食物"],
"connected-components",
canvasSession=session,
assetLabel="贪吃蛇透明图集",
sliceMode="connected-components",
referenceId="must-not-override-explicit-reference",
iconDescriptions=["不得覆盖显式图标描述"],
)
+9
View File
@@ -158,6 +158,15 @@ ALIYUN_OSS_POST_EXPIRE_SECONDS="600"
ALIYUN_OSS_POST_MAX_SIZE_BYTES="20971520"
ALIYUN_OSS_SUCCESS_ACTION_STATUS="200"
# AGC 项目定时快照上传目标。对象只落在服务端私有前缀
# `agc/project-snapshots/v1/{user}/{project}/` 下,客户端直传票据不覆盖该前缀。
# bucket 与凭据可以与资源 bucket 分离;凭据未设置时回退使用 ALIYUN_OSS_ACCESS_KEY_*
# 但 bucket / endpoint 默认指向 AGC 发行 bucket,需要该凭据具备目标 bucket 的 PutObject 权限。
GENARRATIVE_AGC_PROJECT_SNAPSHOT_OSS_BUCKET="agc-dev"
GENARRATIVE_AGC_PROJECT_SNAPSHOT_OSS_ENDPOINT="oss-rg-china-mainland.aliyuncs.com"
GENARRATIVE_AGC_PROJECT_SNAPSHOT_OSS_ACCESS_KEY_ID=""
GENARRATIVE_AGC_PROJECT_SNAPSHOT_OSS_ACCESS_KEY_SECRET=""
# BgFilter 受限资源 worker。父 api-server / external-generation-worker 与唯一的
# `GENARRATIVE_PROCESS_ROLE=bgfilter-worker` 进程必须使用同一个内部 Token。
# `npm run dev` 与 `npm run dev:api-server` 都会自动带起并验活唯一 worker,不要再开第二个终端重复启动。
+4
View File
@@ -7,6 +7,10 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: project-ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
+16
View File
@@ -172,6 +172,20 @@ _Avoid_: 多步骤向导、完整规则编辑器、拖拽编辑器
Bark Battle 平台作品闭环按契约与领域规则、后端存储/API、最小前端纵切、投影体验、收口验证的顺序推进。
_Avoid_: mock 先行堆积、前后端各自发散、先做排行榜 UI
## 项目开发对话(DirectProject
**项目对话历史**:
AGC 本地项目内 Codex 原始对话条目的持久集合,是聊天展示、工具卡片和线程恢复注入的唯一持久事实源。
_Avoid_: 会话缓存、展示态历史、按 UI 需要另存的对话副本
**运行态事件**:
Thread Manager 向订阅者推送的当前回合原始事件流,只服务运行期间与短期断线恢复,不替代项目对话历史。
_Avoid_: 进度通知、快照轮询、第二套历史
**聊天投影**:
把项目对话历史条目与运行态事件转换成消息气泡和工具卡片的读取期转换;不持久化,也不构成事实源。
_Avoid_: 投影缓存文件、已脱敏卡片库、第二套 reducer
## Relationships
- 一个 **汪汪声浪大作战** 单局包含多个 **有效声浪触发**
@@ -206,3 +220,5 @@ _Avoid_: mock 先行堆积、前后端各自发散、先做排行榜 UI
- “入口闭环”曾可能只指内部 demo 或单个详情 CTA;已解析为 **正式作品入口闭环**,不新增独立专区或活动页。
- “创作编辑”曾可能指多步骤向导或完整编辑器;已解析为 **轻配置编辑流程**,使用单页表单 + 预览卡片完成保存草稿、发布和发布后跳转作品详情。
- “实施顺序”曾可能按 UI 或功能并行发散;已解析为契约/领域规则先行,再做后端存储/API,随后打通最小前端纵切,最后补投影体验与收口验证。
- “回合进度事件”曾同时指 Direct turn update 与 Thread Manager 运行态事件;已解析为 AGC 项目开发对话只保留 **运行态事件**
- “哪些消息可显示”曾可能由后端历史分页判断;已解析为可见性判断属于 **聊天投影**,后端只按原始条目分页,前端负责跳过不可显示条目并推进分页锚点。
@@ -38,6 +38,7 @@ vi.mock('../api/adminApiClient', () => ({
interface MockIntersectionObserverController {
enter: (target: Element) => void;
enterAll: (targets: Element[]) => void;
isObserved: (target: Element) => boolean;
}
@@ -106,6 +107,25 @@ function installIntersectionObserverMock(): MockIntersectionObserverController {
);
});
},
enterAll(targets) {
act(() => {
for (const target of targets) {
const record = observed.get(target);
if (!record) {
throw new Error('目标缩略图尚未进入 IntersectionObserver');
}
record.callback(
[
{
isIntersecting: true,
target,
} as IntersectionObserverEntry,
],
record.observer,
);
}
});
},
isObserved(target) {
return observed.has(target);
},
@@ -753,10 +773,10 @@ test('后台素材查询为大量同时可见的缩略图持续错峰换签', as
const thumbnails = entries.map((entry) =>
thumbnailElementForLabel(entry.label),
);
thumbnails.forEach((thumbnail) => {
for (const thumbnail of thumbnails) {
expect(observer.isObserved(thumbnail)).toBe(true);
observer.enter(thumbnail);
});
}
observer.enterAll(thumbnails);
await act(async () => {
await Promise.resolve();
});
@@ -776,7 +796,7 @@ test('后台素材查询为大量同时可见的缩略图持续错峰换签', as
await vi.advanceTimersByTimeAsync(200);
});
expect(getAdminAssetReadUrl).toHaveBeenCalledTimes(105);
});
}, 10_000);
test('后台素材查询读取更多后为新进入可视区域的素材换签', async () => {
const observer = installIntersectionObserverMock();
@@ -2,6 +2,8 @@
"schemaVersion": "game-creator-config.v2",
"agentMode": "codex_app_server",
"llm": {
"customEnabled": false,
"visibleModels": [],
"apiKey": "",
"baseUrl": "https://dev.genarrative.world/gpt/v1",
"model": "gpt-6-astra",
@@ -13,7 +15,7 @@
"autoCompactTokenLimit": 64000,
"toolOutputTokenLimit": 12000,
"requestTimeoutMs": 180000,
"maxRetries": 2,
"maxRetries": 10,
"retryBackoffMs": 500
},
"agentLlm": {}
+4 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@genarrative/ai-game-creator-shell",
"private": true,
"version": "0.1.45",
"version": "0.1.47",
"type": "module",
"scripts": {
"dev": "node scripts/start-tauri-dev.mjs",
@@ -47,6 +47,7 @@
"@tauri-apps/plugin-dialog": "^2.7.2",
"@tauri-apps/plugin-http": "^2.5.9",
"@tauri-apps/plugin-opener": "~2",
"@tauri-apps/plugin-updater": "2.11.0",
"@vitejs/plugin-react": "^5.0.4",
"focus-trap-react": "^12.0.3",
"lexical": "^0.47.0",
@@ -57,6 +58,7 @@
"react-colorful": "^5.8.0",
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"react-window": "^1.8.11",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
"vite": "^6.2.0",
@@ -70,6 +72,7 @@
"@testing-library/user-event": "^14.6.1",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/react-window": "^1.8.8",
"tailwindcss": "^4.1.14",
"typescript": "~5.8.2",
"vitest": "^0.34.6"
@@ -1,6 +1,7 @@
import { spawnSync } from 'node:child_process';
import { createHash } from 'node:crypto';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -28,14 +29,30 @@ const cargoManifestPath = path.join(appRoot, 'src-tauri', 'Cargo.toml');
const cargoLockPath = path.join(appRoot, 'src-tauri', 'Cargo.lock');
const defaultOssBaseUrl =
'https://agc-dev.oss-rg-china-mainland.aliyuncs.com/agc';
const updateManifestUrl =
process.env.VITE_AGC_UPDATE_MANIFEST_URL?.trim() ||
`${process.env.AGC_UPDATE_OSS_BASE_URL?.trim() || defaultOssBaseUrl}/latest.json`;
/**
* 发布渠道 → 目标平台。渠道名会进入 OSS 路径并烘焙进客户端端点,
* 一旦发布就不能改名(改名等于已发布客户端再也找不到更新)。
*/
const releaseChannels = {
'dev-win': 'windows',
'dev-mac': 'darwin',
};
function ossBaseUrl() {
return (
process.env.AGC_UPDATE_OSS_BASE_URL?.trim() || defaultOssBaseUrl
).replace(/\/+$/u, '');
}
function readPackageJson() {
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
}
function readReleaseNotes() {
return process.env.AGC_UPDATE_RELEASE_NOTES?.trim() || '';
}
export function compareVersions(left, right) {
const leftParts = left.split('.').map(Number);
const rightParts = right.split('.').map(Number);
@@ -66,26 +83,87 @@ export function nextPatchVersion(localVersion, remoteVersion) {
return `${major}.${minor}.${patch + 1}`;
}
async function readRemoteVersion() {
export function resolveReleasePlatform(target = releaseTarget) {
if (target.includes('windows')) return 'windows';
if (target.includes('apple-darwin')) return 'darwin';
if (target.includes('linux')) return 'linux';
throw new Error(`不支持的发布目标:${target}`);
}
export function resolveReleaseChannel(
env = process.env,
target = releaseTarget,
) {
const platform = resolveReleasePlatform(target);
const requested = env.AGC_UPDATE_CHANNEL?.trim();
if (requested) {
const channelPlatform = releaseChannels[requested];
if (!channelPlatform) {
throw new Error(
`未知发布渠道 ${requested};当前支持:${Object.keys(releaseChannels).join('、')}`,
);
}
if (channelPlatform !== platform) {
throw new Error(
`渠道 ${requested} 只能用于 ${channelPlatform} 目标,当前构建目标为 ${target}`,
);
}
return requested;
}
const defaultChannel = Object.entries(releaseChannels).find(
([, channelPlatform]) => channelPlatform === platform,
)?.[0];
if (!defaultChannel) {
throw new Error(
`目标 ${target} 没有默认发布渠道,请显式设置 AGC_UPDATE_CHANNEL`,
);
}
return defaultChannel;
}
export function updateManifestUrl(channel = resolveReleaseChannel()) {
return `${ossBaseUrl()}/${channel}/latest.json`;
}
/**
* 更新插件按运行时平台键查找清单条目:universal macOS 包同时挂
* `darwin-aarch64` 与 `darwin-x86_64`,单架构目标只挂对应键。
*/
export function resolveManifestPlatformKeys(target = releaseTarget) {
if (target === 'universal-apple-darwin') {
return ['darwin-aarch64', 'darwin-x86_64'];
}
if (target === 'aarch64-apple-darwin') return ['darwin-aarch64'];
if (target === 'x86_64-apple-darwin') return ['darwin-x86_64'];
if (target.includes('windows')) {
return [
target.startsWith('aarch64') ? 'windows-aarch64' : 'windows-x86_64',
];
}
throw new Error(`不支持的发布目标:${target}`);
}
async function readRemoteVersion(channel = resolveReleaseChannel()) {
const manifestUrl = updateManifestUrl(channel);
let response;
try {
response = await fetch(updateManifestUrl, {
response = await fetch(manifestUrl, {
headers: { Accept: 'application/json' },
});
} catch (error) {
throw new Error(`读取 OSS 版本清单失败:${error.message}`);
throw new Error(`读取 OSS 渠道清单失败:${error.message}`);
}
if (response.status === 404) return null;
if (!response.ok) {
throw new Error(`读取 OSS 版本清单失败:HTTP ${response.status}`);
throw new Error(`读取 OSS 渠道清单失败:HTTP ${response.status}`);
}
let manifest;
try {
manifest = await response.json();
} catch (error) {
throw new Error(`OSS 版本清单不是有效 JSON${error.message}`);
throw new Error(`OSS 渠道清单不是有效 JSON${error.message}`);
}
return parseVersion(manifest?.version, 'OSS版本清单 version');
return parseVersion(manifest?.version, 'OSS渠道清单 version');
}
function replaceVersionLine(source, version, pattern, label) {
@@ -94,8 +172,9 @@ function replaceVersionLine(source, version, pattern, label) {
}
export async function prepareReleaseVersion() {
const channel = resolveReleaseChannel();
const localVersion = parseVersion(readPackageJson().version, '本地版本');
const remoteVersion = await readRemoteVersion();
const remoteVersion = await readRemoteVersion(channel);
const requestedVersion = process.env.AGC_RELEASE_VERSION?.trim();
const nextVersion = requestedVersion
? parseVersion(requestedVersion, '指定版本')
@@ -158,8 +237,8 @@ export async function prepareReleaseVersion() {
console.log(
requestedVersion
? `[ai-game-creator-shell] 使用指定版本 ${nextVersion}(本地 ${localVersion} / OSS ${remoteVersion ?? '不存在'}`
: `[ai-game-creator-shell] 版本 ${localVersion} / OSS ${remoteVersion ?? '不存在'} -> ${nextVersion}`,
? `[ai-game-creator-shell] 渠道 ${channel} 使用指定版本 ${nextVersion}(本地 ${localVersion} / OSS ${remoteVersion ?? '不存在'}`
: `[ai-game-creator-shell] 渠道 ${channel} 版本 ${localVersion} / OSS ${remoteVersion ?? '不存在'} -> ${nextVersion}`,
);
return nextVersion;
}
@@ -187,18 +266,43 @@ export function buildTauriBuildArguments(
];
}
/** 渠道端点必须由构建期注入:官方更新插件的端点配置不支持运行期改渠道。 */
export function createChannelConfig(channel = resolveReleaseChannel()) {
return {
plugins: {
updater: {
endpoints: [updateManifestUrl(channel)],
},
},
};
}
function writeChannelConfigFile(channel) {
const configPath = path.join(
os.tmpdir(),
`agc-tauri-channel-${channel}.json`,
);
fs.writeFileSync(
configPath,
`${JSON.stringify(createChannelConfig(channel), null, 2)}\n`,
);
return configPath;
}
export function runTauriBuild(args = []) {
const tauriArguments = buildTauriBuildArguments(args);
if (!tauriArguments.includes('--config') && !tauriArguments.includes('-c')) {
const channel = resolveReleaseChannel();
const configPath = writeChannelConfigFile(channel);
console.log(
`[ai-game-creator-shell] 渠道 ${channel} 端点配置:${configPath}`,
);
tauriArguments.push('--config', configPath);
}
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
const result = spawnSync(
npmCommand,
[
'--prefix',
'../..',
'exec',
'tauri',
'--',
...buildTauriBuildArguments(args),
],
['--prefix', '../..', 'exec', 'tauri', '--', ...tauriArguments],
{ cwd: appRoot, stdio: 'inherit', shell: process.platform === 'win32' },
);
if (result.error) throw result.error;
@@ -216,10 +320,14 @@ function listFiles(root) {
function artifactPriority(filePath) {
const name = path.basename(filePath).toLowerCase();
if (releaseTarget.includes('windows')) return name.endsWith('.exe') ? 0 : 99;
if (process.platform === 'darwin') return name.endsWith('.dmg') ? 0 : 99;
if (name.endsWith('.appimage')) return 0;
if (name.endsWith('.deb')) return 1;
if (name.endsWith('.rpm')) return 2;
// 更新链路要的是 updater 产物(macOS 为 .app.tar.gz),dmg 只作人工分发。
if (releaseTarget.includes('apple-darwin')) {
return name.endsWith('.app.tar.gz') ? 0 : 99;
}
if (name.endsWith('.appimage.tar.gz')) return 0;
if (name.endsWith('.appimage')) return 1;
if (name.endsWith('.deb')) return 2;
if (name.endsWith('.rpm')) return 3;
return 99;
}
@@ -242,36 +350,100 @@ export function selectReleaseArtifact(files) {
);
}
export function createUpdateManifest(artifactPath) {
function readUpdaterSignature(artifactPath) {
const signaturePath = `${artifactPath}.sig`;
if (!fs.existsSync(signaturePath)) {
throw new Error(
`缺少更新包签名:${signaturePath};需要 bundle.createUpdaterArtifacts 与签名私钥(TAURI_SIGNING_PRIVATE_KEY / TAURI_SIGNING_PRIVATE_KEY_PATH`,
);
}
const signature = fs.readFileSync(signaturePath, 'utf8').trim();
if (!signature) throw new Error(`更新包签名为空:${signaturePath}`);
return signature;
}
export function createUpdateManifest(
artifactPath,
{
channel = resolveReleaseChannel(),
target = releaseTarget,
publishedAt = new Date().toISOString(),
} = {},
) {
const signature = readUpdaterSignature(artifactPath);
const version = readPackageJson().version;
const fileName = path.basename(artifactPath);
const url = `${ossBaseUrl()}/${channel}/${encodeURIComponent(version)}/${encodeURIComponent(fileName)}`;
const platforms = {};
for (const key of resolveManifestPlatformKeys(target)) {
platforms[key] = { signature, url };
}
const notes = readReleaseNotes();
return {
version,
...(notes ? { notes } : {}),
pub_date: publishedAt,
platforms,
};
}
/** 旧协议(sha256)清单:只用于把已发布客户端带到新渠道协议,一个版本周期后整条删除。 */
export function createLegacyUpdateManifest(
artifactPath,
{ channel = resolveReleaseChannel() } = {},
) {
const bytes = fs.readFileSync(artifactPath);
const version = readPackageJson().version;
const fileName = path.basename(artifactPath);
const baseUrl = (
process.env.AGC_UPDATE_OSS_BASE_URL?.trim() || defaultOssBaseUrl
).replace(/\/+$/u, '');
const encodedFileName = encodeURIComponent(fileName).replace(/%2F/giu, '/');
const notes = readReleaseNotes();
return {
version,
downloadUrl: `${baseUrl}/${encodeURIComponent(version)}/${encodedFileName}`,
downloadUrl: `${ossBaseUrl()}/${channel}/${encodeURIComponent(version)}/${encodeURIComponent(fileName)}`,
sha256: createHash('sha256').update(bytes).digest('hex'),
size: bytes.length,
...(process.env.AGC_UPDATE_RELEASE_NOTES?.trim()
? { releaseNotes: process.env.AGC_UPDATE_RELEASE_NOTES.trim() }
: {}),
...(notes ? { releaseNotes: notes } : {}),
};
}
export function generateUpdateManifest() {
const channel = resolveReleaseChannel();
const artifact = selectReleaseArtifact(listFiles(bundleRoot));
if (!artifact) {
throw new Error(`未找到可发布的 AGC 安装包:${bundleRoot}`);
}
const manifest = createUpdateManifest(artifact);
const manifest = createUpdateManifest(artifact, { channel });
const manifestPath = path.join(bundleRoot, 'latest.json');
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
console.log(`[ai-game-creator-shell] 已生成 ${manifestPath}`);
const legacyManifest =
channel === 'dev-win'
? createLegacyUpdateManifest(artifact, { channel })
: null;
const legacyManifestPath = legacyManifest
? path.join(bundleRoot, 'legacy-latest.json')
: null;
if (legacyManifest && legacyManifestPath) {
fs.writeFileSync(
legacyManifestPath,
`${JSON.stringify(legacyManifest, null, 2)}\n`,
);
}
console.log(
`[ai-game-creator-shell] 渠道 ${channel}:已生成 ${manifestPath}`,
);
console.log(`[ai-game-creator-shell] 安装包:${artifact}`);
return { artifact, manifestPath, manifest };
if (legacyManifestPath) {
console.log(
`[ai-game-creator-shell] 旧协议迁移清单:${legacyManifestPath}`,
);
}
return {
channel,
artifact,
manifest,
manifestPath,
legacyManifest,
legacyManifestPath,
};
}
if (
@@ -1,24 +1,61 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { test } from 'node:test';
import { fileURLToPath } from 'node:url';
import {
compareVersions,
createChannelConfig,
createLegacyUpdateManifest,
createUpdateManifest,
nextPatchVersion,
resolveManifestPlatformKeys,
resolveReleaseChannel,
selectReleaseArtifact,
updateManifestUrl,
} from './build-release.mjs';
test('selects an explicit release artifact when configured', () => {
const artifactPath = new URL('../package.json', import.meta.url).pathname;
const previous = process.env.AGC_UPDATE_ARTIFACT;
process.env.AGC_UPDATE_ARTIFACT = artifactPath;
try {
assert.equal(selectReleaseArtifact([]), artifactPath);
} finally {
if (previous === undefined) delete process.env.AGC_UPDATE_ARTIFACT;
else process.env.AGC_UPDATE_ARTIFACT = previous;
const windowsTarget = 'x86_64-pc-windows-msvc';
const universalTarget = 'universal-apple-darwin';
function withEnv(overrides, run) {
const previous = new Map();
for (const [key, value] of Object.entries(overrides)) {
previous.set(key, process.env[key]);
if (value === undefined) delete process.env[key];
else process.env[key] = value;
}
try {
return run();
} finally {
for (const [key, value] of previous) {
if (value === undefined) delete process.env[key];
else process.env[key] = value;
}
}
}
function withSignedArtifact(fileName, run) {
const directory = mkdtempSync(path.join(os.tmpdir(), 'agc-release-test-'));
try {
const artifact = path.join(directory, fileName);
writeFileSync(artifact, 'installation package');
writeFileSync(`${artifact}.sig`, 'signature-content\n');
return run(artifact);
} finally {
rmSync(directory, { recursive: true, force: true });
}
}
test('selects an explicit release artifact when configured', () => {
const artifactPath = fileURLToPath(
new URL('../package.json', import.meta.url),
);
withEnv({ AGC_UPDATE_ARTIFACT: artifactPath }, () => {
assert.equal(selectReleaseArtifact([]), artifactPath);
});
});
test('does not select unsupported files', () => {
@@ -28,47 +65,123 @@ test('does not select unsupported files', () => {
);
});
test('manifest contains version, download URL and integrity fields', () => {
const manifest = createUpdateManifest(
new URL('../package.json', import.meta.url).pathname,
test('resolves the channel from the target platform and rejects mismatches', () => {
assert.equal(resolveReleaseChannel({}, windowsTarget), 'dev-win');
assert.equal(resolveReleaseChannel({}, universalTarget), 'dev-mac');
assert.equal(
resolveReleaseChannel({ AGC_UPDATE_CHANNEL: 'dev-mac' }, universalTarget),
'dev-mac',
);
assert.match(manifest.version, /^\d+\.\d+\.\d+$/u);
assert.match(
manifest.downloadUrl,
new RegExp(`/agc/${manifest.version}/package\\.json$`, 'u'),
assert.throws(
() =>
resolveReleaseChannel({ AGC_UPDATE_CHANNEL: 'dev-mac' }, windowsTarget),
/只能用于 darwin 目标/u,
);
assert.throws(
() =>
resolveReleaseChannel({ AGC_UPDATE_CHANNEL: 'beta-win' }, windowsTarget),
/未知发布渠道/u,
);
assert.equal(manifest.sha256.length, 64);
assert.equal(typeof manifest.size, 'number');
});
test('manifest preserves multiline release notes', () => {
const previous = process.env.AGC_UPDATE_RELEASE_NOTES;
process.env.AGC_UPDATE_RELEASE_NOTES = '第一行\n第二行\r\n第三行';
try {
const manifest = createUpdateManifest(
new URL('../package.json', import.meta.url).pathname,
test('channel manifest URL and build-time endpoint follow the channel', () => {
withEnv({ AGC_UPDATE_OSS_BASE_URL: undefined }, () => {
assert.equal(
updateManifestUrl('dev-win'),
'https://agc-dev.oss-rg-china-mainland.aliyuncs.com/agc/dev-win/latest.json',
);
assert.deepEqual(createChannelConfig('dev-mac'), {
plugins: {
updater: {
endpoints: [
'https://agc-dev.oss-rg-china-mainland.aliyuncs.com/agc/dev-mac/latest.json',
],
},
},
});
});
});
test('universal macOS builds publish one artifact under both platform keys', () => {
assert.deepEqual(resolveManifestPlatformKeys(universalTarget), [
'darwin-aarch64',
'darwin-x86_64',
]);
assert.deepEqual(resolveManifestPlatformKeys(windowsTarget), [
'windows-x86_64',
]);
});
test('channel manifest carries version, platform keys and signature', () => {
withSignedArtifact('陶泥儿_0.1.48_x64-setup.exe', (artifact) => {
withEnv({ AGC_UPDATE_RELEASE_NOTES: '修复与改进' }, () => {
const manifest = createUpdateManifest(artifact, {
channel: 'dev-win',
target: windowsTarget,
publishedAt: '2026-09-17T00:00:00.000Z',
});
assert.match(manifest.version, /^\d+\.\d+\.\d+$/u);
assert.equal(manifest.notes, '修复与改进');
assert.equal(manifest.pub_date, '2026-09-17T00:00:00.000Z');
assert.deepEqual(Object.keys(manifest.platforms), ['windows-x86_64']);
assert.equal(
manifest.platforms['windows-x86_64'].signature,
'signature-content',
);
assert.match(
manifest.platforms['windows-x86_64'].url,
new RegExp(`/agc/dev-win/${manifest.version}/`, 'u'),
);
});
});
});
test('missing signature fails the channel manifest closed', () => {
const directory = mkdtempSync(path.join(os.tmpdir(), 'agc-release-test-'));
try {
const artifact = path.join(directory, '陶泥儿_0.1.48_x64-setup.exe');
writeFileSync(artifact, 'installation package');
assert.throws(
() =>
createUpdateManifest(artifact, {
channel: 'dev-win',
target: windowsTarget,
}),
/缺少更新包签名/u,
);
assert.equal(manifest.releaseNotes, '第一行\n第二行\r\n第三行');
} finally {
if (previous === undefined) delete process.env.AGC_UPDATE_RELEASE_NOTES;
else process.env.AGC_UPDATE_RELEASE_NOTES = previous;
rmSync(directory, { recursive: true, force: true });
}
});
test('next release version follows the higher local or OSS version', () => {
test('legacy manifest keeps the sha256 contract of published clients', () => {
withSignedArtifact('陶泥儿_0.1.48_x64-setup.exe', (artifact) => {
const legacy = createLegacyUpdateManifest(artifact, {
channel: 'dev-win',
});
assert.match(legacy.version, /^\d+\.\d+\.\d+$/u);
assert.equal(legacy.sha256.length, 64);
assert.equal(legacy.size, 'installation package'.length);
assert.match(legacy.downloadUrl, /\/agc\/dev-win\/[\d.]+\//u);
});
});
test('next release version follows the higher local or channel version', () => {
assert.equal(compareVersions('0.1.15', '0.1.12'), 1);
assert.equal(nextPatchVersion('0.1.12', '0.1.15'), '0.1.16');
assert.equal(nextPatchVersion('0.1.18', '0.1.15'), '0.1.19');
assert.equal(nextPatchVersion('0.1.12', null), '0.1.13');
});
test('release upload forces overwrite for versioned artifact and latest pointer', () => {
test('release upload forces overwrite for artifact, signature and channel pointers', () => {
const source = readFileSync(
new URL('./release-upload.mjs', import.meta.url),
'utf8',
);
assert.equal(
(source.match(/runOssutil\(\['cp', '--force'/gu) ?? []).length,
2,
(source.match(/runOssutil\(\[\s*'cp',\s*'--force'/gu) ?? []).length,
4,
);
assert.match(source, /agc\/\$\{channel\}\/latest\.json/u);
assert.match(source, /agc\/latest\.json/u);
});
@@ -121,6 +121,10 @@ const allowedUncalledTauriCommands = [
'open_game_creator_launcher_window',
'open_game_creator_workspace_window',
'read_direct_project_conversation',
// 项目定时快照上传只在 Rust 侧触发(周期定时器 / 工作区窗口关闭)与排障调用;
// 按产品口径不做客户端可见界面,因此同 `open_game_creator_*_window` 一样按 native-only 登记。
'read_local_project_snapshot_state',
'sync_local_project_snapshot',
'reset_design_agent_session',
'stop_local_game_preview_if_matches',
'start_game_creator_external_mcp',
@@ -724,6 +724,7 @@ function canvasAssetCall(agentId) {
assetKind: 'art-spritesheet',
assetLabel: '游戏首版核心美术素材',
replaceExisting: false,
sliceMode: 'connected-components',
});
}
@@ -2691,7 +2692,7 @@ function createDeterministicCanvasFixture(apiKey) {
'deterministic spritesheet fixture',
model: 'deterministic-canvas-v1',
provider: 'deterministic-loopback',
sliceLayout: 'grid-2x2',
sliceMode: 'connected-components',
spritesheetResource: {
resourceId,
projectId,
@@ -0,0 +1,20 @@
/**
* `agc` 开发启动下发给 Vite 的客户端特性开关默认值。
*
* 开发态默认关闭客户端更新检查:`npm run agc` / `agc:serve` 启动的客户端不请求 OSS
* 更新清单,也不显示更新入口。需要联调更新流程时显式传
* `VITE_AGC_ENABLE_APP_UPDATE_CHECK=1`;此处不覆盖已经显式配置的取值。
*/
const agcAppUpdateCheckEnvKey = 'VITE_AGC_ENABLE_APP_UPDATE_CHECK';
function withAgcDevFeatureFlags(env = process.env) {
if (String(env[agcAppUpdateCheckEnvKey] ?? '').trim()) {
return env;
}
return {
...env,
[agcAppUpdateCheckEnvKey]: '0',
};
}
export { agcAppUpdateCheckEnvKey, withAgcDevFeatureFlags };
@@ -0,0 +1,27 @@
/**
* 发布上传的 OSS 命令行整理:把 ossutil 参数与凭据整理成可执行或可打印的形式,
* 便于在 dry-run 下核对将要执行的上传,同时保证任何输出都不回显凭据明文。
*/
const redactedCredential = '<redacted>';
export function readReleaseDryRun(env = process.env) {
const value = env.AGC_RELEASE_DRY_RUN?.trim().toLowerCase();
return value === '1' || value === 'true';
}
function quoteArgument(value) {
return /[\s"']/u.test(value) ? JSON.stringify(value) : value;
}
export function formatOssutilCommand({ binary, args, endpoint, credentials }) {
const parts = [binary, ...args, '--endpoint', endpoint];
if (credentials) {
parts.push(
'--access-key-id',
redactedCredential,
'--access-key-secret',
redactedCredential,
);
}
return parts.map(quoteArgument).join(' ');
}
@@ -0,0 +1,44 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { test } from 'node:test';
import { formatOssutilCommand, readReleaseDryRun } from './release-oss.mjs';
test('dry run only accepts explicit truthy values', () => {
assert.equal(readReleaseDryRun({}), false);
assert.equal(readReleaseDryRun({ AGC_RELEASE_DRY_RUN: '1' }), true);
assert.equal(readReleaseDryRun({ AGC_RELEASE_DRY_RUN: ' true ' }), true);
assert.equal(readReleaseDryRun({ AGC_RELEASE_DRY_RUN: '0' }), false);
assert.equal(readReleaseDryRun({ AGC_RELEASE_DRY_RUN: '' }), false);
});
test('printed upload command keeps arguments and hides credentials', () => {
const command = formatOssutilCommand({
binary: 'ossutil',
args: [
'cp',
'--force',
'陶泥儿 0.1.48.exe',
'oss://agc-dev/agc/dev-win/x.exe',
],
endpoint: 'oss-rg-china-mainland.aliyuncs.com',
credentials: true,
});
assert.match(command, /^ossutil cp --force /u);
assert.match(command, /"陶泥儿 0\.1\.48\.exe"/u);
assert.match(command, /oss:\/\/agc-dev\/agc\/dev-win\/x\.exe/u);
assert.match(
command,
/--access-key-id <redacted> --access-key-secret <redacted>/u,
);
});
test('uploader gates every ossutil call behind the dry run switch', () => {
const source = readFileSync(
new URL('./release-upload.mjs', import.meta.url),
'utf8',
);
assert.match(source, /const dryRun = readReleaseDryRun\(\);/u);
assert.match(source, /if \(dryRun\) \{/u);
assert.match(source, /dry-run:未写入任何 OSS 对象/u);
});
@@ -1,6 +1,8 @@
import { spawnSync } from 'node:child_process';
import path from 'node:path';
import { formatOssutilCommand, readReleaseDryRun } from './release-oss.mjs';
const bucket = process.env.AGC_OSS_BUCKET?.trim() || 'agc-dev';
const endpoint =
process.env.AGC_OSS_ENDPOINT?.trim() || 'oss-rg-china-mainland.aliyuncs.com';
@@ -8,6 +10,7 @@ if (!/^[a-z0-9][a-z0-9.-]{1,62}$/u.test(bucket) || /[\r\n\0]/u.test(endpoint)) {
throw new Error('OSS bucket 或 endpoint 配置无效');
}
process.env.AGC_UPDATE_OSS_BASE_URL ||= `https://${bucket}.${endpoint}/agc`;
const dryRun = readReleaseDryRun();
const { generateUpdateManifest, prepareReleaseVersion, runTauriBuild } =
await import('./build-release.mjs');
@@ -19,6 +22,18 @@ function runOssutil(args) {
if (Boolean(accessKeyId) !== Boolean(accessKeySecret)) {
throw new Error('OSS AccessKey ID 和 Secret 必须同时提供');
}
if (dryRun) {
// 演练:只打印将要执行的上传,凭据以占位符呈现,不写入 OSS。
console.log(
`[dry-run] ${formatOssutilCommand({
binary,
args,
endpoint,
credentials: Boolean(accessKeyId),
})}`,
);
return;
}
const credentialArgs = accessKeyId
? ['--access-key-id', accessKeyId, '--access-key-secret', accessKeySecret]
: [];
@@ -38,11 +53,40 @@ function runOssutil(args) {
await prepareReleaseVersion();
runTauriBuild([]);
const { artifact, manifestPath, manifest } = generateUpdateManifest();
const artifactKey = `agc/${manifest.version}/${path.basename(artifact)}`;
const { artifact, channel, legacyManifestPath, manifest, manifestPath } =
generateUpdateManifest();
const artifactKey = `agc/${channel}/${manifest.version}/${path.basename(artifact)}`;
// Jenkins/ossutil 默认会在目标对象已存在时交互询问并按默认值跳过;
// 发布清单是固定的 latest 指针,必须显式覆盖,否则流水线会误报成功但远端仍保留旧版本。
runOssutil(['cp', '--force', artifact, `oss://${bucket}/${artifactKey}`]);
runOssutil(['cp', '--force', manifestPath, `oss://${bucket}/agc/latest.json`]);
runOssutil([
'cp',
'--force',
`${artifact}.sig`,
`oss://${bucket}/${artifactKey}.sig`,
]);
runOssutil([
'cp',
'--force',
manifestPath,
`oss://${bucket}/agc/${channel}/latest.json`,
]);
console.log(`[ai-game-creator-shell] 已上传 oss://${bucket}/${artifactKey}`);
console.log(`[ai-game-creator-shell] 已上传 oss://${bucket}/agc/latest.json`);
console.log(
`[ai-game-creator-shell] 已上传 oss://${bucket}/agc/${channel}/latest.json`,
);
if (legacyManifestPath) {
// 迁移桥:让仍走旧 sha256 清单的已发布客户端升级到新协议,一个版本周期后删除。
runOssutil([
'cp',
'--force',
legacyManifestPath,
`oss://${bucket}/agc/latest.json`,
]);
console.log(
`[ai-game-creator-shell] 已上传迁移指针 oss://${bucket}/agc/latest.json`,
);
}
if (dryRun) {
console.log('[ai-game-creator-shell] dry-run:未写入任何 OSS 对象');
}
@@ -3,6 +3,7 @@ import http from 'node:http';
import net from 'node:net';
import { fileURLToPath } from 'node:url';
import { withAgcDevFeatureFlags } from './dev-feature-flags.mjs';
import { resolveAgcDevEndpoint, withAgcDevEndpointEnv } from './dev-port.mjs';
const appRoot = fileURLToPath(new URL('..', import.meta.url));
@@ -104,7 +105,7 @@ const child = spawn(
],
{
cwd: appRoot,
env: withAgcDevEndpointEnv(endpoint),
env: withAgcDevFeatureFlags(withAgcDevEndpointEnv(endpoint)),
stdio: 'inherit',
// Node 18.20+/20+/24 on Windows rejects spawning .cmd (npm.cmd) without a shell (EINVAL).
shell: true,
@@ -11,6 +11,7 @@ import {
stopWindowsProcessTree,
stopWindowsWorktreeProcesses,
} from '../../../scripts/dev-windows-process.mjs';
import { withAgcDevFeatureFlags } from './dev-feature-flags.mjs';
import {
agcVitePortEnvKey,
readAgcDevEndpoint,
@@ -978,7 +979,10 @@ async function startVite(apiTarget, endpoint = readAgcDevEndpoint()) {
'--port',
String(endpoint.port),
],
{ cwd: appRoot, env: withAgcDevEndpointEnv(endpoint) },
{
cwd: appRoot,
env: withAgcDevFeatureFlags(withAgcDevEndpointEnv(endpoint)),
},
);
}
+240 -12
View File
@@ -814,6 +814,16 @@ dependencies = [
"url",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation"
version = "0.10.1"
@@ -837,7 +847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
dependencies = [
"bitflags 2.13.0",
"core-foundation",
"core-foundation 0.10.1",
"core-graphics-types",
"foreign-types 0.5.0",
"libc",
@@ -850,7 +860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
"bitflags 2.13.0",
"core-foundation",
"core-foundation 0.10.1",
"libc",
]
@@ -1405,6 +1415,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "filetime"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759"
dependencies = [
"cfg-if",
"libc",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
@@ -1725,7 +1745,7 @@ dependencies = [
[[package]]
name = "genarrative-ai-game-creator-shell"
version = "0.1.45"
version = "0.1.47"
dependencies = [
"agent-runtime-core",
"axum",
@@ -1747,7 +1767,6 @@ dependencies = [
"oxc_parser",
"oxc_semantic",
"oxc_span",
"percent-encoding",
"platform-agent",
"platform-llm",
"portable-pty",
@@ -1766,6 +1785,7 @@ dependencies = [
"tauri-plugin-dialog",
"tauri-plugin-http",
"tauri-plugin-opener",
"tauri-plugin-updater",
"tempfile",
"tokio",
"toml 0.8.2",
@@ -1776,7 +1796,7 @@ dependencies = [
"url",
"uuid",
"windows-sys 0.61.2",
"zip",
"zip 2.4.2",
]
[[package]]
@@ -2220,9 +2240,11 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"socket2",
"system-configuration",
"tokio",
"tower-service",
"tracing",
"windows-registry",
]
[[package]]
@@ -2506,6 +2528,36 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "jni"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
dependencies = [
"cfg-if",
"combine",
"jni-macros",
"jni-sys 0.4.1",
"log",
"simd_cesu8",
"thiserror 2.0.18",
"walkdir",
"windows-link 0.2.1",
]
[[package]]
name = "jni-macros"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"simd_cesu8",
"syn 2.0.118",
]
[[package]]
name = "jni-sys"
version = "0.3.1"
@@ -2819,6 +2871,12 @@ dependencies = [
"unicase",
]
[[package]]
name = "minisign-verify"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -3234,6 +3292,18 @@ dependencies = [
"objc2-core-foundation",
]
[[package]]
name = "objc2-osa-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0"
dependencies = [
"bitflags 2.13.0",
"objc2",
"objc2-app-kit",
"objc2-foundation",
]
[[package]]
name = "objc2-quartz-core"
version = "0.3.2"
@@ -3378,6 +3448,20 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "osakit"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
"objc2",
"objc2-foundation",
"objc2-osa-kit",
"serde",
"serde_json",
"thiserror 2.0.18",
]
[[package]]
name = "outref"
version = "0.5.2"
@@ -4360,15 +4444,20 @@ dependencies = [
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-util",
"js-sys",
"log",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
"serde",
"serde_json",
"sync_wrapper",
"tokio",
"tokio-rustls",
"tokio-util",
"tower",
"tower-http",
@@ -4482,6 +4571,33 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustls-platform-verifier"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
"jni 0.22.4",
"log",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls-platform-verifier-android"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
version = "0.103.13"
@@ -4609,7 +4725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.13.0",
"core-foundation",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
"security-framework-sys",
@@ -4952,6 +5068,22 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "simd_cesu8"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
dependencies = [
"rustc_version",
"simdutf8",
]
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "similar"
version = "2.7.0"
@@ -5175,6 +5307,27 @@ dependencies = [
"syn 2.0.118",
]
[[package]]
name = "system-configuration"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags 2.13.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@@ -5196,7 +5349,7 @@ checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9"
dependencies = [
"bitflags 2.13.0",
"block2",
"core-foundation",
"core-foundation 0.10.1",
"core-graphics",
"crossbeam-channel",
"dbus",
@@ -5206,7 +5359,7 @@ dependencies = [
"gdkwayland-sys",
"gdkx11-sys",
"gtk",
"jni",
"jni 0.21.1",
"libc",
"log",
"ndk",
@@ -5239,6 +5392,17 @@ dependencies = [
"syn 2.0.118",
]
[[package]]
name = "tar"
version = "0.4.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
@@ -5262,7 +5426,7 @@ dependencies = [
"gtk",
"heck 0.5.0",
"http",
"jni",
"jni 0.21.1",
"libc",
"log",
"mime",
@@ -5477,6 +5641,39 @@ dependencies = [
"zbus",
]
[[package]]
name = "tauri-plugin-updater"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b28d8cabdeb0564f03ae261963de4bc3d98321cd3d213e76a81b7d344e5df606"
dependencies = [
"base64 0.22.1",
"dirs",
"flate2",
"futures-util",
"http",
"infer",
"log",
"minisign-verify",
"osakit",
"percent-encoding",
"reqwest 0.13.4",
"rustls",
"semver",
"serde",
"serde_json",
"tar",
"tauri",
"tauri-plugin",
"tempfile",
"thiserror 2.0.18",
"time",
"tokio",
"url",
"windows-sys 0.60.2",
"zip 4.6.1",
]
[[package]]
name = "tauri-runtime"
version = "2.11.3"
@@ -5487,7 +5684,7 @@ dependencies = [
"dpi",
"gtk",
"http",
"jni",
"jni 0.21.1",
"objc2",
"objc2-ui-kit",
"objc2-web-kit",
@@ -5510,7 +5707,7 @@ checksum = "fe41e015bf8fc4d6477ff4926a0ef769dc64ff34c7b0038b6f7cacae892acb5c"
dependencies = [
"gtk",
"http",
"jni",
"jni 0.21.1",
"log",
"objc2",
"objc2-app-kit",
@@ -6586,6 +6783,15 @@ dependencies = [
"system-deps",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webpki-roots"
version = "1.0.9"
@@ -7192,7 +7398,7 @@ dependencies = [
"gtk",
"http",
"javascriptcore-rs",
"jni",
"jni 0.21.1",
"libc",
"ndk",
"objc2",
@@ -7256,6 +7462,16 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
[[package]]
name = "xattr"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
dependencies = [
"libc",
"rustix",
]
[[package]]
name = "yoke"
version = "0.8.3"
@@ -7437,6 +7653,18 @@ dependencies = [
"zopfli",
]
[[package]]
name = "zip"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
dependencies = [
"arbitrary",
"crc32fast",
"indexmap 2.14.0",
"memchr",
]
[[package]]
name = "zmij"
version = "1.0.21"
@@ -1,11 +1,14 @@
[package]
name = "genarrative-ai-game-creator-shell"
version = "0.1.45"
version = "0.1.47"
edition = "2021"
publish = false
[features]
default = []
# 模板库假数据注入(仅本地页面压测/演示用):只有显式开启该 feature 才会编译并在读取清单后
# 把条目循环补齐成假数据;计数由 AGC_TEMPLATE_LIBRARY_SYNTHETIC_COUNT 控制(默认 1000)。
template-library-fixtures = []
cocos-editor = ["cocos-editor-bridge/process-discovery"]
cocos-editor-execute = ["cocos-editor", "cocos-editor-bridge/windows-bootstrap"]
cocos-editor-injection = ["cocos-editor-execute", "cocos-editor-bridge/windows-injection"]
@@ -47,7 +50,6 @@ similar = "2.7"
platform-llm = { path = "../../../server-rs/crates/platform-llm" }
platform-agent = { path = "../../../server-rs/crates/platform-agent" }
portable-pty = "0.9"
percent-encoding = "2"
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart", "native-tls", "stream"] }
regex = "1"
shared-contracts = { path = "../../../server-rs/crates/shared-contracts", default-features = false }
@@ -55,6 +57,7 @@ tauri = { version = "2.11.2", features = [] }
tauri-plugin-dialog = "2.7.1"
tauri-plugin-http = { version = "2.5.9", default-features = false, features = ["charset", "cookies", "http2", "rustls-tls"] }
tauri-plugin-opener = "2"
tauri-plugin-updater = "2.11.0"
tempfile = "3"
toml = "0.8"
ttf-parser = "0.25.1"
@@ -14,13 +14,13 @@
"allow": [
{ "url": "https://dev.genarrative.world/api/*" },
{ "url": "https://www.genarrative.world/api/*" },
{ "url": "https://agc-dev.oss-rg-china-mainland.aliyuncs.com/*" },
{ "url": "https://*/api/*" },
{ "url": "http://localhost:*/*" },
{ "url": "http://127.0.0.1:*/*" }
]
},
"opener:default",
"updater:default",
"dialog:allow-open",
"dialog:allow-save"
]
@@ -2,7 +2,7 @@
{"type":"function","function":{"name":"get_workflow_status","description":"读取当前策划工作流状态,只返回阶段列表、当前阶段、已批准阶段和待审批阶段;不推进阶段、不提交审批、不修改文件。","parameters":{"type":"object","properties":{},"additionalProperties":false}}},
{"type":"function","function":{"name":"list_resources","description":"列出固定资源的逻辑目录、资源 ID、标题和简介。资源是只读的随包文档;不要猜测物理路径。","parameters":{"type":"object","properties":{},"additionalProperties":false}}},
{"type":"function","function":{"name":"read_resource","description":"读取一份固定资源文档全文。每次读取一个 resource_id;资源只读。读到未实现占位文档时由你自行判断和处理。","parameters":{"type":"object","properties":{"resource_id":{"type":"string"}},"required":["resource_id"],"additionalProperties":false}}},
{"type":"function","function":{"name":"patch_file","description":"局部修改 UTF-8 文件。使用 old_text/new_text,或使用 edits 一次进行多个独立替换;每个 old_text 必须非空且在原文件中唯一,匹配失败、重复或范围重叠时不修改文件。path 使用相对路径。","parameters":{"type":"object","properties":{"path":{"type":"string"},"old_text":{"type":"string"},"new_text":{"type":"string"},"edits":{"type":"array","items":{"type":"object","properties":{"old_text":{"type":"string"},"new_text":{"type":"string"}},"required":["old_text","new_text"],"additionalProperties":false}}},"required":["path"],"additionalProperties":false}}},
{"type":"function","function":{"name":"patch_file","description":"局部修改 UTF-8 文件。使用 old_text/new_text,或使用 edits 一次进行多个独立替换;每个 old_text 必须非空且在原文件中唯一。所有 edit 会一次性校验;任何失败都不修改文件,错误会列出各失败项及可唯一匹配的其余项。path 使用相对路径。","parameters":{"type":"object","properties":{"path":{"type":"string"},"old_text":{"type":"string"},"new_text":{"type":"string"},"edits":{"type":"array","items":{"type":"object","properties":{"old_text":{"type":"string"},"new_text":{"type":"string"}},"required":["old_text","new_text"],"additionalProperties":false}}},"required":["path"],"additionalProperties":false}}},
{"type":"function","function":{"name":"delete_path","description":"谨慎使用;永久删除工作区内的文件或目录;目录会连同全部内容递归删除,不备份。先确认目标及删除范围。path 使用相对路径,不能删除工作区根目录,也不能经过链接。","parameters":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"],"additionalProperties":false}}},
{"type":"function","function":{"name":"list_dir","description":"列出工作目录内的文件和目录。path 使用相对路径。","parameters":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"],"additionalProperties":false}}},
{"type":"function","function":{"name":"read_file","description":"读取工作目录内的 UTF-8 文本文件。path 使用相对路径。","parameters":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"],"additionalProperties":false}}},
@@ -13,8 +13,8 @@ Let the client derive projections from real disk changes and trusted tool result
2. Before using or deriving an existing registered asset, call `agc_list_registered_assets` and select its `localAssetId`. If the user points to an existing project file that is not listed, first call `agc_list_project_files`; only entries with `assetImportable=true` (recognized image, font, audio, video, document, or code files) may be passed to `agc_import_account_assets.localPaths`. Then re-read `agc_list_registered_assets`; never infer a source identity from a filename or fabricate a localAssetId.
3. Keep read scopes separate: `asset.list` is the current project manifest, `asset.library.list` is the signed-in account library, and the web project's canvas resource read model is the authoritative canvas list. The account library is not the complete canvas list.
4. Use `canvas.asset_import` for safe account/canvas asset IDs or project-relative local paths. The client rechecks ownership and validates bytes; host absolute paths require native UI file-picker authorization.
5. When the user explicitly asks to create or derive video, character animation, sound effect, or background music, call `agc_create_or_derive_resource`. Use `create` only for video/audio without a source and `derive` with a registered `sourceLocalAssetId`; character animation is always derived from an image.
6. When the user explicitly asks to remove an image background, call `agc_remove_background` with a registered image `sourceLocalAssetId` and an output name. The client requires the signed-in account, owns canvas/folder context and task identity, and returns only bounded queue state.
5. When the user explicitly asks to create or derive video, character animation, sound effect, or background music, call `agc_create_or_derive_resource`. Use `create` only for video/audio without a source and `derive` with a registered `sourceLocalAssetId`; character animation is always derived from an image. Keep `prompt` inside the per-kind limit that the client really enforces: background music at most 140 characters, sound effect at most 1900, video and character animation at most 4000. A longer prompt is rejected before submission, so write the short version first instead of retrying the same text.
6. When the user explicitly asks to remove an image background, call `agc_remove_background` with a registered image `sourceLocalAssetId` and `assetName`. Optional `backgroundMode` is `complex` (semantic foreground segmentation; default) or `flat` (solid-colour background removal). Prefer `flat` when the background is known to be solid. Only `flat` accepts optional `screenColor`: `auto`, `#RRGGBB`, or omitted for automatic detection by the service. Do not select a colour on behalf of `auto`. The client requires the signed-in account, owns canvas/folder context and task identity, and returns only bounded queue state.
7. Preserve existing relative paths when a small edit is sufficient so client resource identities remain stable.
8. Do not edit `.agent/manifest.json`, revision counters, version records, resource IDs, canvas identities, source provenance, generation ledgers, or browser receipts by hand.
9. Do not create a version when no game file changed. The client compares content fingerprints and advances revision only after an actual source change.

Some files were not shown because too many files have changed in this diff Show More