feat: complete M5 custom world and agent chain

This commit is contained in:
2026-04-22 14:15:27 +08:00
parent 209e924403
commit 0773a0d0ca
27 changed files with 3359 additions and 159 deletions

View File

@@ -43,6 +43,7 @@
- [SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md):冻结 `M5` Agent `message submit / operation query` 的 deterministic 最小闭环,明确同步写入 user/assistant 消息、`process_message` operation 与 session 进度推进规则。
- [SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md):冻结 `M5` Agent `/messages/stream` 的最小兼容 SSE facade明确复用 Stage 7 的同步写表逻辑,只输出当前前端真实消费的 `reply_delta / session / done / error` 事件。
- [SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md):补齐 `M5` Stage 5 遗漏的 owner-only `GET /api/runtime/custom-world-library/:profileId` 设计,冻结单条 profile detail 的 SpacetimeDB procedure、client facade、404 语义与 Axum 路由扩展方式。
- [SPACETIMEDB_CUSTOM_WORLD_WORKS_AND_AGENT_EXTENSION_STAGE9_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_WORKS_AND_AGENT_EXTENSION_STAGE9_DESIGN_2026-04-22.md):冻结 `M5` 剩余主链的 works、card detail、publish gate、supportedActions、action registry 与 AI/OSS 兼容路由边界,作为 Stage 9 到收口阶段的统一落地依据。
- [M3_BROWSE_HISTORY_AXUM_SPACETIMEDB_DESIGN_2026-04-21.md](./M3_BROWSE_HISTORY_AXUM_SPACETIMEDB_DESIGN_2026-04-21.md):冻结 `M3` 第二批 `browse history` 纵向切片的 `user_browse_history` 表、双路径 facade、宽松归一化、去重排序规则与测试策略。
- [ASSET_ENTITY_BINDING_REDUCER_DESIGN_2026-04-21.md](./ASSET_ENTITY_BINDING_REDUCER_DESIGN_2026-04-21.md):冻结已确认 `asset_object` 绑定到业务实体槽位的首版 reducer/procedure、通用 `asset_entity_binding` 表与 Axum facade。
- [FRONTEND_TO_BACKEND_MIGRATION_EXECUTION_PLAN_2026-04-21.md](./FRONTEND_TO_BACKEND_MIGRATION_EXECUTION_PLAN_2026-04-21.md)把鉴权、浏览历史、runtime story 快照、NPC 待接委托与正式生成编排继续后移到 Express 后端的实施方案与验收口径。

View File

@@ -0,0 +1,404 @@
# `M5` custom world works / agent extension Stage 9 设计
日期:`2026-04-22`
## 1. 文档目的
这份文档冻结 `M5` 剩余主链的最小可交付边界,目标是在已经完成的:
1. library / gallery
2. agent session create / snapshot
3. message submit / operation query
4. message stream
5. publish world compile / publish 最小链
基础上,继续补齐当前前端真正依赖的剩余能力:
1. `GET /api/runtime/custom-world/works`
2. `GET /api/runtime/custom-world/agent/sessions/:sessionId/cards/:cardId`
3. session snapshot 的真实 `supportedActions`
4. session snapshot / works 共用的 `publish gate`
5. session snapshot 的最小 `resultPreview`
6. `draft_foundation / update_draft_card / sync_result_profile / revert_checkpoint / publish_world`
7. `entity / scene-npc / scene-image / cover-image / cover-upload` 兼容路由
本轮保持一个原则:
1. 先把 deterministic 主链和 contract 补全
2. LLM / 图片 / OSS 只补最小可用编排,不把 Node 的整套内部服务原样搬进 Rust
## 2. 当前问题
当前 Rust 后端虽然已经能:
1. 创建 Agent session
2. 提交消息
3. 拉取 session snapshot
4. 兼容作品库与世界广场
但前端主链仍然缺失以下关键读写能力:
1. 作品列表 `works` 还没有 Rust 输出
2. 草稿卡详情 `card detail` 还没有 Rust 输出
3. `supportedActions` 还是临时三项伪造值
4. `resultPreview / blockers / publishReady / canEnterWorld` 还没有稳定真相源
5. `draft_foundation / update_draft_card / sync_result_profile / revert_checkpoint / publish_world` 还没有统一 action 执行口径
6. 旧前端仍会调用 `entity / scene-npc / scene-image / cover-image / cover-upload`
如果这些能力缺失,即使 session / message 已迁到 SpacetimeDB前端 RPG 创作主链仍然不能视为完成。
## 3. 设计目标
### 3.1 works
`GET /api/runtime/custom-world/works` 返回两类 item
1. `agent_session` 草稿作品
2. `published_profile` 已发布作品
排序规则保持旧 Node 语义:
1. `updatedAt` 倒序
2. `sourceType=agent_session` 优先于 `published_profile`
3. 最后按 `workId` 稳定排序
### 3.2 card detail
`GET /api/runtime/custom-world/agent/sessions/:sessionId/cards/:cardId` 返回:
```json
{
"card": {
"...": "detail payload"
}
}
```
当前 Rust 不复制 Node 里整套复杂卡片编译器,只走已存在真相表:
1. `custom_world_draft_card.detail_payload_json` 有值时直接透出
2. 无值时由 summary 字段拼最小 detail fallback
### 3.3 publish gate
统一引入最小 publish gate 摘要,供三处复用:
1. works 草稿 item
2. session snapshot.resultPreview
3. `publish_world` action 前置校验
固定字段:
1. `profileId`
2. `blockers`
3. `blockerCount`
4. `publishReady`
5. `canEnterWorld`
### 3.4 supportedActions
session snapshot 的 `supportedActions` 不再用伪造最小值,而是按当前 session 真相态计算以下动作:
1. `draft_foundation`
2. `update_draft_card`
3. `sync_result_profile`
4. `generate_characters`
5. `generate_landmarks`
6. `generate_role_assets`
7. `sync_role_assets`
8. `generate_scene_assets`
9. `sync_scene_assets`
10. `expand_long_tail`
11. `publish_world`
12. `revert_checkpoint`
启用规则沿用旧 Node 的最小语义:
1. `draft_foundation` 需要 `progressPercent >= 100`
2. refine 类动作只在 `object_refining / visual_refining`
3. `expand_long_tail``publish_world` 允许 `object_refining / visual_refining / long_tail_review / ready_to_publish`
4. `publish_world` 还要求 publish gate 无 blocker
5. `revert_checkpoint` 还要求存在可恢复 checkpoint
### 3.5 resultPreview
session snapshot 中的 `resultPreview` 固定输出:
```json
{
"preview": { "...": "compiled preview profile" },
"source": "session_preview",
"generatedAt": "2026-04-22T00:00:00Z",
"qualityFindings": [],
"blockers": [],
"publishReady": false,
"canEnterWorld": false
}
```
当前最小策略:
1. `draft_profile_json` 为空则返回 `null`
2.`draft_profile_json` 时直接把它作为 `preview`
3. 附带 publish gate 摘要
4. `source` 固定为 `session_preview`
## 4. works contract
### 4.1 路由
`GET /api/runtime/custom-world/works`
### 4.2 响应
```json
{
"items": [
{
"workId": "draft:custom-world-agent-session-001",
"sourceType": "agent_session",
"status": "draft",
"title": "未命名草稿",
"subtitle": "准备发布",
"summary": "当前世界草稿摘要",
"coverImageSrc": null,
"updatedAt": "2026-04-22T00:00:00Z",
"publishedAt": null,
"stage": "ready_to_publish",
"stageLabel": "准备发布",
"playableNpcCount": 0,
"landmarkCount": 0,
"sessionId": "custom-world-agent-session-001",
"profileId": null,
"canResume": true,
"canEnterWorld": false,
"blockerCount": 2,
"publishReady": false
}
]
}
```
### 4.3 草稿 works 最小取值规则
1. `title` 优先取 `draft_profile_json.name`
2. 否则退回 `draft_profile_json.title`
3. 仍为空则退回 `seed_text`
4. 最终兜底 `未命名草稿`
5. `summary` 优先取 `draft_profile_json.summary`
6. 仍为空则退回 `seed_text`
7. 最终兜底 `还在收集你的世界锚点。`
8. `subtitle` 先取 `draft_profile_json.subtitle`
9. 否则用 `stageLabel`
### 4.4 已发布 works 最小取值规则
直接复用 `custom_world_profile`
1. `title=world_name`
2. `subtitle=subtitle`
3. `summary=summary_text`
4. `publishedAt=published_at`
5. `canEnterWorld=true`
6. `publishReady=true`
7. `blockerCount=0`
## 5. card detail contract
### 5.1 路由
`GET /api/runtime/custom-world/agent/sessions/:sessionId/cards/:cardId`
### 5.2 详情结构
详情最小 contract 固定为:
1. `id`
2. `kind`
3. `title`
4. `sections`
5. `linkedIds`
6. `locked`
7. `editable`
8. `editableSectionIds`
9. `warningMessages`
10. `assetStatus`
11. `assetStatusLabel`
### 5.3 detail fallback 规则
如果 `detail_payload_json` 缺失,则按 summary 字段回填:
1. `sections` 至少包含 `title / subtitle / summary`
2. `editable=false`
3. `editableSectionIds=[]`
4. `warningMessages=[]`
5. `linkedIds``linked_ids_json`
## 6. action 主链
### 6.1 action 统一入口
继续沿用:
`POST /api/runtime/custom-world/agent/sessions/:sessionId/actions`
本轮明确不新增独立 `card update` REST。
### 6.2 action 最小落地范围
#### `draft_foundation`
1. 把 session 推进到 `object_refining`
2. 生成最小 `draft_profile_json`
3. 写入世界卡 `world-foundation`
4. 追加 assistant `action_result` 消息
5. 记录可恢复 checkpoint
#### `update_draft_card`
1. 定位卡片
2. 把 sections 写回 `detail_payload_json`
3. 同步更新 summary/title/subtitle
4. 如存在 `draft_profile_json`,最小同步回常见字段
5. 追加 assistant `action_result` 消息
#### `sync_result_profile`
1. 用传入 `profile` 覆盖 session `draft_profile_json`
2. 重建最小 preview
3. 追加 assistant `action_result` 消息
4. 记录 checkpoint
#### `revert_checkpoint`
1. 校验 checkpoint 存在且可恢复
2. 把 checkpoint 快照写回 session
3. 追加 assistant `action_result` 消息
#### `publish_world`
1. 优先从 session 里的 `draft_profile_json` 取草稿
2. 如请求体显式传入 `draftProfile / settingText / legacyResultProfile`,允许覆盖
3. 先走 publish gate
4. 再执行 Stage 4 已有 `publish_custom_world_world`
5. 成功后返回 `completed` operation
### 6.3 非 deterministic action 的本轮策略
以下动作先给出最小兼容 operation不阻塞前端按钮
1. `generate_characters`
2. `generate_landmarks`
3. `generate_role_assets`
4. `sync_role_assets`
5. `generate_scene_assets`
6. `sync_scene_assets`
7. `expand_long_tail`
其中:
1. `sync_role_assets / sync_scene_assets` 允许直接同步回 `draft_profile_json`
2. 其余生成类先走最小 LLM / 资产编排
## 7. LLM / OSS 兼容路由边界
### 7.1 允许复用的 Rust 基座
1. `api-server/llm.rs`
2. `platform-llm`
3. `api-server/assets.rs`
4. `platform-oss`
5. `spacetime-client``asset_object / asset_entity_binding`
### 7.2 本轮新增兼容路由
1. `POST /api/custom-world/entity`
2. `POST /api/runtime/custom-world/entity`
3. `POST /api/custom-world/scene-npc`
4. `POST /api/runtime/custom-world/scene-npc`
5. `POST /api/custom-world/scene-image`
6. `POST /api/custom-world/cover-image`
7. `POST /api/custom-world/cover-upload`
### 7.3 最小实现策略
#### `entity / scene-npc`
1. 使用 `platform-llm` 调用文本模型
2. 返回 JSON object
3. 当前不把生成结果自动写回 session
#### `scene-image / cover-image`
1. 当前不直接生成真实图片
2. 返回明确 `NOT_IMPLEMENTED` 或最小占位错误会导致前端主链中断
3. 因此前端兼容需要的最小可用策略是:创建上传票据或返回可继续上传的对象位置信息
#### `cover-upload`
1. 复用 `/api/assets/direct-upload-tickets`
2. 生成 OSS 上传票据
3. 返回兼容旧前端所需的上传字段
## 8. crate 级改动范围
### 8.1 `module-custom-world`
新增:
1. works / card detail / publish gate / preview DTO
2. action request / action procedure result DTO
3. 最小 gate 与 supported action 领域辅助函数
### 8.2 `spacetime-module`
新增:
1. `list_custom_world_works`
2. `get_custom_world_agent_card_detail`
3. `execute_custom_world_agent_action`
4. session snapshot 内真实 `supportedActions`
5. publish gate / result preview 组装辅助
### 8.3 `spacetime-client`
新增:
1. works 查询 facade
2. card detail 查询 facade
3. action 执行 facade
4. 新 DTO mapper
### 8.4 `api-server`
新增:
1. `GET /api/runtime/custom-world/works`
2. `GET /api/runtime/custom-world/agent/sessions/:sessionId/cards/:cardId`
3. action 路由切到真实 registry
4. custom world AI/OSS 兼容路由
## 9. 验收口径
当以下条件满足时Stage 9 视为完成:
1. `works` 可列出草稿与已发布作品
2. `card detail` 可返回 detail 或 fallback detail
3. session snapshot 的 `supportedActions` 为真实能力矩阵
4. `resultPreview` 附带 `blockers / publishReady / canEnterWorld`
5. `draft_foundation / update_draft_card / sync_result_profile / revert_checkpoint / publish_world` 可走通
6. `entity / scene-npc / scene-image / cover-image / cover-upload` 已由 Rust 接口承接
7. `backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md``M5` 相关项全部勾完
8. 重新生成 Rust bindings
9. `cargo check -p api-server`
10. 定向编码检查通过
## 10. 相关文档
1. [../../backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md](../../backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md)
2. [./SPACETIMEDB_CUSTOM_WORLD_AXUM_FACADE_STAGE5_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AXUM_FACADE_STAGE5_DESIGN_2026-04-22.md)
3. [./SPACETIMEDB_CUSTOM_WORLD_AGENT_SESSION_STAGE6_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_SESSION_STAGE6_DESIGN_2026-04-22.md)
4. [./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md)
5. [./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md)
6. [./SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md)