文档:AGC 模型目录初始值改为上游同步的规范与运维口径

- 主规范补充目录初始化来源、失败关闭与重试口径,并记录本变更不改变目录格式与客户端契约
- 后端数据契约补充缺行语义与启动期同步
- 运维文档新增「AGC 模型目录上游同步」小节(来源、恢复路径、同批发布约束)
- decision-log 记录本次决策、真实上游实测结论与残留项
- 新增里程碑《AGC 模型目录初始值改为上游同步》与对应实施计划
This commit is contained in:
2026-09-24 16:14:19 +08:00
parent ec3a187dd7
commit 6c92e5d673
6 changed files with 126 additions and 2 deletions
@@ -9335,3 +9335,17 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 影响面:`server-rs/crates/api-server/src/{config.rs,modules/game_distribution.rs}`、`server-rs/crates/shared-contracts/src/game_distribution.rs`、`packages/shared/src/contracts/gameDistribution.ts`、`src/components/game-distribution/gameDistributionGuards.ts`(含新增测试)、`deploy/{nginx,container,env}`、`scripts/check-game-distribution-media-e2e.mjs`、`package.json`、平台与运维主规范。
- 边界:SpacetimeDB 表结构与公开契约字段不变(`entryUrl` 仍是 string),只是取值从绝对 URL 变为相对路径;历史版本已冻结的绝对值不改写,admin 页与详情页展示口径不变。线上 dev / release 的 nginx 已按同源路径改动并 reload,`/etc/genarrative/api-server.env` 已删除模板变量;api-server 未重启,新写入要等下次重启。
- 验证:`cargo check -p api-server --tests`、`cargo test -p api-server game_distribution`(27 passed)、`cargo fmt --all --check`、`npx vitest run src/components/game-distribution`(57 passed)、`npm run check:nginx-spa-routes`、`npm run check:encoding`(5060 文件)、`npm run check:doc-index`、`git diff --check` 全部通过;三份 nginx 模板渲染后 `nginx -t` 语法通过;dev 线上实测 `/games/game_2dcd…4955/` 与 `./assets/index-2Ws3zHlS.js` 均 200。
## 2026-09-24 AGC 模型目录初始值改为上游同步:不再回退写死的 gpt-6-astra/gpt-5.6-luna
- 背景:`agc_model_catalog` 缺行时 procedure 兜底返回内置目录(`quality → gpt-6-astra`、`fast → gpt-5.6-luna`),两个模型都已从上游移除;从未配置过目录的环境(新库、清库、本地调试)会把不存在的模型下发给客户端,选中后上游 `model_not_found`。
- 决策(范围):本次只改目录初始值的来源,保持既有格式与契约不变 —— 目录字段仍是 `id`/`alias`/`modelId`/`defaultModelId`,后台页面与 admin DTO、`GET /api/llm/models` 形状、客户端 `select_game_creator_model` 的标识校验都不动,因此没有不兼容变更。
- 决策(初始化):api-server(API/All 角色)启动时目录缺失、结构与当前定义不符或校验不通过即视为未初始化;此时请求上游 Router 控制面的分组定价列表 `GET {控制面}/api/pricing?group=taonier`(公开只读、不带凭据),按 `data[].model_name` 排序生成目录:`modelId` 与 `alias` 用上游原名(不再填“高质量/快速”),`id` 用模型名 slug(小写字母/数字/`-`/`_`,同名冲突追加 `-2`,因此客户端标识校验无需放宽),全部 enabled,默认项取排序后第一项,并按存量 revision 写回自增。
- 决策(来源选择,2026-09-24 实测后确定):不用管理面模型注册表 `/api/models/`(会带出已下线、没有路由绑定的 `gpt-6-astra`/`gpt-6-luna`),也不用 `/v1/models`(要求 Router 用户 Key,用管理 token 实测 401)。当日 `group=taonier` 在售 6 个:`deepseek-flash`、`deepseek-v4-pro`、`glm-5.3`、`glm-5.3-flash`、`qwen-image-3.0`、`qwen3.8-flash`。
- 决策(失败关闭与重试):拉取失败、空列表、响应超 1 MiB、缺可解析 revision 或写回失败都只记录 error,不写替代目录;未初始化期间 `GET /api/llm/models`、`/api/llm/responses`、`/api/llm/chat/completions` 与后台 `GET/PUT /admin/api/agc-models` 返回 `503`“模型目录未初始化”;只在启动期尝试一次,下一次启动重试,直到目录里有数据。启动本身不因同步失败而失败,避免 Router 短时不可用放大成 api-server 起不来。
- 决策(幂等与并发):目录只取决于模型集合(排序后生成),重复同步结果一致;多实例并发启动只有一个写入成功,冲突方重读并校验既有目录可用性。目录只在未初始化时重建,上游变化不自动跟随。
- 决策(存量目录):结构合法的目录不会被自动重建,包括旧版写死的 `quality/fast` —— 需要 owner 在后台改掉,或清空该行后重启重新同步。
- 影响范围:`module-runtime`(`from_upstream_models` + slug 生成,删除写死的 `Default`)、`spacetime-module`(缺行返回 `AGC_MODEL_CATALOG_NOT_INITIALIZED`)、`api-server`(启动期同步、上游请求硬化、只校验地址的目标校验、后台 PUT 未初始化门禁)、AGC 客户端(默认模型占位改为 `platform-default`)、AGC 模型弹层 CSS、主规范/后端契约/运维文档。
- 验证:`cargo test -p module-runtime --lib agc_models::`(4 passed)、`cargo test -p api-server --bin api-server agc` 与 `llm::`、AGC 客户端 `configuration::`、admin-web 页面定向 Vitest 与 typecheck、两套 workspace 的 `cargo fmt -- --check`、`check:encoding`/`check:doc-index`/`check:spacetime-schema`/`git diff --check`。
- 验证(真实上游 smoke,本地 dev DB):清空 `agc_model_catalog` 后启动 api-server → 日志 `已按上游模型列表初始化 AGC 模型目录 revision=1 model_count=6`;登录后 `GET /api/llm/models` 返回同一批模型、`displayName` 即上游原名、默认项为排序后第一项;上游不可达/非 2xx 时启动只记录 error、AGC 接口 `503` 且目录保持未初始化;目录已存在时重启不重写。
- 边界(未验证/残留):上游在售模型超过 32 条时同步会失败(目录项上限未改);`qwen-image-3.0` 这类图像模型会一起进入目录,是否对 AGC 隐藏由 owner 在后台停用;混合版本期间未升级的 api-server 会把自己的 AGC 接口打到 `503`,module 与 api-server 必须同批发布/回滚。