feat: complete M5 custom world and agent chain
This commit is contained in:
@@ -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 后端的实施方案与验收口径。
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user