1
This commit is contained in:
@@ -16,22 +16,23 @@
|
||||
|
||||
## 页面路径表
|
||||
|
||||
| 页面阶段 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `platform` | `/` | 平台首页、广场、我的、创作中心等主入口 |
|
||||
| `detail` | `/worlds/detail` | RPG 世界详情页,依赖当前已选作品 |
|
||||
| `agent-workspace` | `/creation/rpg/agent` | RPG Agent 共创工作区 |
|
||||
| `custom-world-generating` | `/creation/rpg/generating` | RPG 世界草稿生成进度页 |
|
||||
| `custom-world-result` | `/creation/rpg/result` | RPG 世界结果页与编辑页 |
|
||||
| `big-fish-agent-workspace` | `/creation/big-fish/agent` | 大鱼吃小鱼 Agent 共创工作区 |
|
||||
| `big-fish-result` | `/creation/big-fish/result` | 大鱼吃小鱼草稿结果页 |
|
||||
| `big-fish-runtime` | `/runtime/big-fish` | 正式链路中的大鱼吃小鱼运行页 |
|
||||
| `puzzle-agent-workspace` | `/creation/puzzle/agent` | 拼图 Agent 共创工作区 |
|
||||
| `puzzle-result` | `/creation/puzzle/result` | 拼图草稿结果页 |
|
||||
| `puzzle-gallery-detail` | `/gallery/puzzle/detail` | 拼图作品详情页,依赖当前已选作品 |
|
||||
| `puzzle-runtime` | `/runtime/puzzle` | 正式链路中的拼图运行页 |
|
||||
| RPG 选角页 | `/runtime/rpg/characters` | 进入世界后、确认角色前的选角阶段 |
|
||||
| RPG 冒险页 | `/runtime/rpg/adventure` | 已确认角色后的 RPG 主运行态 |
|
||||
| 页面阶段 | 路径 | 说明 |
|
||||
| -------------------------- | --------------------------- | ------------------------------------------------------ |
|
||||
| `platform` | `/` | 平台首页、广场、我的、创作中心等主入口 |
|
||||
| `work-detail` | `/works/detail` | 统一公开作品详情页,承接 RPG、拼图、大鱼吃小鱼公开作品 |
|
||||
| `detail` | `/worlds/detail` | RPG 世界详情页,依赖当前已选作品 |
|
||||
| `agent-workspace` | `/creation/rpg/agent` | RPG Agent 共创工作区 |
|
||||
| `custom-world-generating` | `/creation/rpg/generating` | RPG 世界草稿生成进度页 |
|
||||
| `custom-world-result` | `/creation/rpg/result` | RPG 世界结果页与编辑页 |
|
||||
| `big-fish-agent-workspace` | `/creation/big-fish/agent` | 大鱼吃小鱼 Agent 共创工作区 |
|
||||
| `big-fish-result` | `/creation/big-fish/result` | 大鱼吃小鱼草稿结果页 |
|
||||
| `big-fish-runtime` | `/runtime/big-fish` | 正式链路中的大鱼吃小鱼运行页 |
|
||||
| `puzzle-agent-workspace` | `/creation/puzzle/agent` | 拼图 Agent 共创工作区 |
|
||||
| `puzzle-result` | `/creation/puzzle/result` | 拼图草稿结果页 |
|
||||
| `puzzle-gallery-detail` | `/gallery/puzzle/detail` | 拼图作品详情页,依赖当前已选作品 |
|
||||
| `puzzle-runtime` | `/runtime/puzzle` | 正式链路中的拼图运行页 |
|
||||
| RPG 选角页 | `/runtime/rpg/characters` | 进入世界后、确认角色前的选角阶段 |
|
||||
| RPG 冒险页 | `/runtime/rpg/adventure` | 已确认角色后的 RPG 主运行态 |
|
||||
|
||||
## 落地边界
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
## 作品分享路由补充
|
||||
|
||||
1. 公开作品入口路由统一使用当前作品页面路径加 `work=作品号`:RPG 为 `/worlds/detail?work=CW-00000001`,拼图为 `/gallery/puzzle/detail?work=PZ-00000001`,大鱼玩法为 `/runtime/big-fish?work=BF-00000001`。
|
||||
1. 公开作品入口路由统一使用 `/works/detail?work=作品号`,三类作品在该页先展示统一公开详情,再由“启动”进入对应运行态;旧 `/worlds/detail` 与 `/gallery/puzzle/detail` 只保留给既有创作/编辑链路。
|
||||
2. 从公开广场、最近浏览、创作中心打开已发布作品详情或玩法时,若当前作品有公开作品号,地址栏必须同步追加 `work=作品号`;没有作品号的草稿详情仍保持无查询参数路径。
|
||||
3. 首次进入主应用时若 URL 带 `work` 查询参数,平台入口自动复用现有公开编号搜索逻辑打开对应作品详情,不新增独立详情系统。
|
||||
4. 详情页必须保留“复制作品号”和“分享作品”两个独立动作:
|
||||
@@ -34,5 +34,5 @@
|
||||
5. 桌面右侧趋势列表只显示排序和作品类型,不再显示 `1777110165.990127Z` 这类原始时间字符串,也不直接显示作品号。
|
||||
6. 在内嵌浏览器 Clipboard API 拒绝写入时,详情页与创作中心作品号复制仍能通过降级路径完成,并显示 `已复制` 或 `复制失败`。
|
||||
7. 打开拼图详情后点击返回,不再固定跳到创作中心,而是回到打开详情前的平台 Tab。
|
||||
8. 打开 `/?work=CW-00000001`、`/worlds/detail?work=CW-00000001`、`/gallery/puzzle/detail?work=PZ-00000001` 或 `/runtime/big-fish?work=BF-00000001` 后能自动进入对应公开作品详情或玩法。
|
||||
8. 打开 `/?work=CW-00000001` 或 `/works/detail?work=CW-00000001` 后能自动进入对应公开作品详情;拼图、大鱼吃小鱼作品号同样进入统一公开详情后再启动玩法。
|
||||
9. 点击详情页“分享作品”后,剪切板内容包含邀请文本、作品号和当前站点下带 `work=作品号` 的完整网址。
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# RPG NPC 聊天禁存快照会话修复(2026-04-28)
|
||||
|
||||
## 背景
|
||||
|
||||
复测 NPC 对话时,前端请求:
|
||||
|
||||
```text
|
||||
POST /api/runtime/chat/npc/turn/stream
|
||||
```
|
||||
|
||||
返回 `409 Conflict`,错误为:
|
||||
|
||||
```text
|
||||
请求的运行时会话与服务端快照不一致,请重新进入游戏
|
||||
```
|
||||
|
||||
当前 story action 主链已经支持 `runtimePersistenceDisabled = true` 的运行态:这类请求会携带临时 `snapshot`,后端只构造本次响应,不写入 `runtime_snapshot`。但 NPC 聊天接口在带 `sessionId` 时只从正式 `runtime_snapshot` 读取上下文。若当前运行态是作品测试、幕预览或其他禁存 run,服务端正式快照仍可能是上一局正式存档,导致 `sessionId` 与 `snapshotSessionId` 不一致。
|
||||
|
||||
## 修复原则
|
||||
|
||||
1. 正式 `play` 且允许持久化的运行态,聊天请求继续只提交 `sessionId` 与聊天输入,保持后端快照为唯一来源。
|
||||
2. `runtimePersistenceDisabled = true` 或历史 `runtimeMode = preview/test` 的运行态,聊天请求必须携带临时 `snapshot`。
|
||||
3. 后端聊天接口收到临时 `snapshot` 时,只用它投影本轮 prompt context、NPC state、history、encounter,不写入 `runtime_snapshot`。
|
||||
4. 临时 `snapshot.gameState.runtimeSessionId` 必须与请求 `sessionId` 一致;不一致仍返回 `409`。
|
||||
5. 前端不得把完整快照默认用于正式游玩聊天,避免重新扩大浏览器对正式真相链的写入权。
|
||||
|
||||
## 工程落点
|
||||
|
||||
1. `packages/shared/src/contracts/rpgRuntimeChat.ts`
|
||||
- 给角色聊天、NPC 对话、NPC 单轮、招募对话请求补可选 `snapshot` 字段。
|
||||
2. `src/services/aiService.ts`
|
||||
- 增加禁存运行态 snapshot 构造。
|
||||
- 仅在 `context.runtimeSnapshot` 存在时,随聊天请求提交 `snapshot`。
|
||||
3. `src/services/aiTypes.ts`
|
||||
- `StoryGenerationContext` 增加可选 `runtimeSnapshot`。
|
||||
4. `src/hooks/rpg-runtime-story/storyContextBuilder.ts`
|
||||
- 禁存运行态把当前 `GameState` 作为临时 snapshot 注入 context。
|
||||
5. `server-rs/crates/api-server/src/runtime_chat.rs`
|
||||
- `NpcChatTurnRequest` 接收 `snapshot`。
|
||||
- 优先使用请求 snapshot 校验并投影上下文。
|
||||
6. `server-rs/crates/api-server/src/runtime_chat_plain.rs`
|
||||
- 角色聊天、NPC 开场、招募同样支持临时 snapshot。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 禁存运行态 NPC 聊天请求体携带 `snapshot`,正式运行态不携带。
|
||||
2. 后端 NPC 聊天在请求 snapshot 与正式存档 session 不一致时,仍按请求 snapshot 成功投影,不读取旧正式存档。
|
||||
3. snapshot 内部 `runtimeSessionId` 与请求 `sessionId` 不一致时返回 `409`。
|
||||
4. 相关前端单测、后端 `runtime_chat` 单测、编码检查通过。
|
||||
Reference in New Issue
Block a user