This commit is contained in:
2026-04-10 15:37:02 +08:00
parent 161cd32277
commit f19e482c8f
233 changed files with 43987 additions and 5127 deletions

View File

@@ -0,0 +1,106 @@
# 编辑器与资产 API 迁移清单2026-04-08
## 1. 任务定位
对应 [EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md](../planning/EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md) 中的任务 8编辑器 API 归口与工具链隔离。
本轮目标是把编辑器写盘、资产生成、生成任务查询从旧的 Vite 本地 API 插件里收口到 `server-node`,并把前端编辑器组件改成通过统一 SDK 访问。
---
## 2. 新命名空间
编辑器写盘与读取:
- `GET /api/editor/catalog/items`
- `GET /api/editor/json/:resourceId`
- `POST /api/editor/json/:resourceId`
资产生成与任务查询:
- `POST /api/assets/character-visual/generate`
- `POST /api/assets/character-visual/publish`
- `GET /api/assets/character-visual/jobs/:taskId`
- `POST /api/assets/character-animation/generate`
- `POST /api/assets/character-animation/publish`
- `GET /api/assets/character-animation/jobs/:taskId`
- `POST /api/assets/character-animation/import-video`
- `GET /api/assets/character-animation/templates`
- `POST /api/assets/qwen-sprite/master`
- `POST /api/assets/qwen-sprite/sheet`
- `POST /api/assets/qwen-sprite/frame-repair`
- `POST /api/assets/qwen-sprite/save`
---
## 3. 前端接入
统一入口:
- `src/editor/shared/editorApiClient.ts`
已切换的编辑器链路:
- 角色预设覆盖保存
- 敌人预设覆盖保存
- 场景预设覆盖保存
- 场景角色覆盖保存
- NPC 形象覆盖与布局配置保存
- 物品目录读取与物品覆盖保存
- 状态行为覆盖保存
- 角色主形象生成、发布与任务查询
- 角色动作生成、导入、发布、模板读取与任务查询
- Qwen 精灵主图、精灵表、修帧与资产保存
---
## 4. 权限与环境边界
`server-node` 通过环境变量控制工具接口:
- `EDITOR_API_ENABLED`:控制 `/api/editor/*`
- `ASSETS_API_ENABLED`:控制 `/api/assets/*`
默认策略:
-`production` 环境默认开启。
- `production` 环境默认关闭。
- `ASSETS_API_ENABLED` 未设置时跟随 `EDITOR_API_ENABLED`
这批接口会读写 `src/data/*.json``public/generated-*`,不应作为正式运行时 API 使用。
---
## 5. 旧工具链隔离状态
`scripts/dev-server/**` 中的旧 Vite 本地插件已经不再由 `vite.config.ts` 注入,也不再作为当前开发入口使用。
旧文件保留用途:
- 作为历史迁移参考。
- 对照旧 DashScope 调用与文件写入逻辑。
新增编辑器或资产能力时,应优先写入:
- `server-node/src/modules/editor/**`
- `server-node/src/modules/assets/**`
- `src/editor/shared/editorApiClient.ts`
不要再新增旧式散落接口:
- `/api/item-overrides`
- `/api/npc-visual-overrides`
- `/api/character-overrides`
- `/api/character-visual/*`
- `/api/animation/*`
- `/api/qwen-sprite/*`
---
## 6. 当前验收状态
- `/api/editor/*``/api/assets/*` 命名空间已落地。
- 前端编辑器组件已通过统一 SDK 或资源 ID 访问编辑器 API。
- Vite 已代理 `/api/editor``/api/assets` 到 Node 后端。
- 写接口已经有环境门禁。
- 旧 Vite 本地插件不再是当前工具链入口。

View File

@@ -0,0 +1,108 @@
# Express 后端接口冻结与集成清单2026-04-09
## 1. 目的
这份文档补齐 `docs/planning/EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md` 中任务 0 缺失的仓库内产物,用来明确:
- 当前 contract 的冻结版本
- 热点文件的编辑规则
- 各类改动进入集成窗口前的最小检查清单
它不是新的重构计划,而是给当前并行改造提供一个统一落库的“不要互相踩”的边界表。
---
## 2. Contract 版本表
| 范围 | 当前版本 | 源头文件 | 说明 |
| --- | --- | --- | --- |
| 统一 API envelope | `2026-04-08 / v1` | `packages/shared/src/http.ts` | `ApiResponse`、错误结构、`meta` 字段、envelope 头约定的统一来源。 |
| auth contract | `2026-04-08` | `packages/shared/src/contracts/auth.ts` | 前后端都以 shared auth contract 识别登录、用户信息与 token 响应。 |
| runtime snapshot/settings contract | `2026-04-08` | `packages/shared/src/contracts/runtime.ts` | 存档、设置、自定义世界会话与库表相关请求/响应来源。 |
| runtime story action contract | `2026-04-08` | `packages/shared/src/contracts/story.ts` | `RuntimeStoryActionRequest/Response`、Task5/Task6 function id 与 view model 来源。 |
| Node HTTP route meta | `2026-04-08` | `server-node/src/app.ts` | `/api/auth``/api/runtime/story``/api/editor``/api/assets` 都以这一轮 route version 为当前冻结口径。 |
| editor/assets route 命名空间 | `2026-04-08` | `server-node/src/modules/editor/editorRoutes.ts``server-node/src/modules/assets/**` | 编辑器与资产接口统一走 `/api/editor/*``/api/assets/*`。 |
---
## 3. 热点文件编辑规则
以下文件继续视为高冲突入口,默认不要在多个任务里并行大改:
- `server-node/src/context.ts`
- `server-node/src/routes/runtimeRoutes.ts`
- `server-node/src/app.ts`
- `src/services/apiClient.ts`
- `src/hooks/useStoryGeneration.ts`
- `src/hooks/useGameFlow.ts`
- `src/components/GameShell.tsx`
统一规则:
- 新需求优先新增独立模块,再通过桥接或小入口接入,不要直接把逻辑堆进热点文件。
- 需要改 `server-node/src/routes/runtimeRoutes.ts` 时,先确认 shared contract 是否已落库,再补 route 接入。
- 需要改 `src/hooks/useStoryGeneration.ts` 时,优先确认是否其实应该落到 `server-node/src/modules/**``src/services/runtimeStoryService.ts``src/hooks/story/**`
- 编辑器链路与正式运行时链路不要混在同一轮提交里。
- 如果同一轮同时碰到后端 action 与前端 UI 壳层,先冻结 action/view model再接 UI。
---
## 4. 集成窗口清单
### 4.1 shared contract 变更
- 只在 `packages/shared/**` 改类型、schema、纯序列化约定。
- 同步检查 `server-node/src/**``src/**` 是否都已切到 shared contract。
- 至少跑一次 `npm run server-node:test`
- 如果前端消费层也改了,再补 `npm run typecheck`
### 4.2 runtime action / domain module 变更
- 业务规则优先写在 `server-node/src/modules/**`,不要直接写回前端 hook。
- 如果影响 `RuntimeStoryActionResponse`,同步检查 `packages/shared/src/contracts/story.ts`
- 至少覆盖对应模块测试,或补到 `server-node/src/modules/story/storyActionRoutes.test.ts`
- 合并前至少跑一次 `npm run server-node:test`
### 4.3 persistence / repository / config 变更
- 只把 PostgreSQL 视为正式基线。
- 如果改到 `server-node/src/db.ts``repositories/**`、迁移脚本,优先确认 `pg-mem` 测试仍通过。
- 合并前至少跑一次 `npm run server-node:test`
### 4.4 editor / assets 变更
- 后端入口只放在 `/api/editor/*``/api/assets/*`
- 前端统一从 `src/editor/shared/editorApiClient.ts` 或对应 persistence 层进入。
- 不要新增旧 Vite 本地插件式散落接口。
### 4.5 前端壳层接入变更
- 优先消费 `runtime story state / action response / shared contract`,不要把正式规则写回前端。
- 如果恢复流程有改动,优先以后端 runtime state 为准。
- 若影响主流程,至少补对应 hook / view model 测试并跑 `npm run typecheck`
---
## 5. 当前剩余非冻结区
以下几块仍处于“可继续收口但尚未完全冻结”的状态,改动时要额外小心:
- `server-node/src/bridges/legacyBuildRuntimeBridge.ts`
- `server-node/src/bridges/legacyInventoryRuntimeBridge.ts`
- `server-node/src/modules/ai/storyOrchestrator.ts`
- `server-node/src/modules/ai/chatOrchestrator.ts`
- `server-node/src/modules/ai/customWorldOrchestrator.ts`
它们目前仍残留一部分对 `src/**` 历史实现的复用,不建议在没有额外测试兜底时顺手混改。
---
## 6. 本轮落库结论
从 2026-04-09 起,仓库内已经具备任务 0 要求的这几类最小产物:
- contract 版本表
- 热点文件编辑规则
- 集成窗口检查清单
后续如果 shared contract、runtime action 或热点入口发生明显演进,应优先更新这份文档,而不是让口径只停留在聊天记录里。

View File

@@ -0,0 +1,109 @@
# Express 后端任务 4 AI 编排收口状态2026-04-08
## 1. 结论
`EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md` 的任务 4 定义,本轮已经把正式运行时的 `story / character chat / npc chat / custom world generation / quest intent / runtime item intent` 的主要 AI 编排入口收回到 Express 后端。
当前可以视为:
- 正式运行时主链已不再依赖浏览器端大体量 AI 实现作为兜底。
- prompt 组装、上游模型请求、SSE 转发已以后端为主。
- 前端保留的本地 AI 大模块只通过懒加载方式服务于非正式运行时遗留入口,不再作为正式运行时默认路径。
---
## 2. 已完成项
### 2.1 后端统一 orchestration 入口
- `server-node/src/modules/ai/storyOrchestrator.ts`
- `server-node/src/modules/ai/chatOrchestrator.ts`
- `server-node/src/modules/ai/customWorldOrchestrator.ts`
这些模块承接:
- story prompt 组装
- character chat prompt 组装
- npc chat / recruit prompt 组装
- custom world generation 后端入口封装
### 2.2 服务层收口
已收口到后端服务或模块的文件:
- `server-node/src/services/llmClient.ts`
- `server-node/src/services/storyService.ts`
- `server-node/src/services/chatService.ts`
- `server-node/src/services/customWorldGenerationService.ts`
- `server-node/src/services/questService.ts`
- `server-node/src/services/runtimeItemService.ts`
### 2.3 前端正式运行时 fallback 清理
`src/services/aiService.ts` 已完成以下收缩:
- story 正式路径不再 fallback 到浏览器本地 AI 编排
- character suggestions / summary / reply stream 不再 fallback 到浏览器本地 AI 编排
- npc dialogue / recruit stream 不再 fallback 到浏览器本地 AI 编排
- 移除了正式运行时对 `VITE_ENABLE_BROWSER_RUNTIME_AI_FALLBACK` 的依赖
- 移除了正式运行时对本地轻量离线文案 fallback 的默认依赖
-`./ai` 的引用改为懒加载,避免正式运行时默认把大体量 AI 模块打进主路径
- 正式运行时主流程 hook 已统一改走 `aiService`,不再直接从 `src/services/ai.ts` 获取 story/chat 主链能力
### 2.4 旧 bridge 清理
已移除:
- `server-node/src/bridges/legacyAiRuntimeBridge.ts`
---
## 3. 当前边界说明
以下项仍然存在于前端目录,但不再属于正式运行时默认 AI 执行路径:
- `src/services/ai.ts`
- `src/services/aiFallbacks.ts`
- `src/components/CustomWorldEntityEditorModal.tsx` 中的工具链直连调用
它们当前主要作为:
- 兼容性遗留实现
- 懒加载的非主路径工具能力
- 非本轮正式运行时链路的复用来源
这不再构成任务 4 的主阻塞,但后续仍应继续配合任务 1 / 任务 7 做彻底分层。
---
## 4. 非任务 4 主阻塞但需要记录的事项
### 4.1 仍属编辑器/工具链范畴的遗留调用
- `generateCustomWorldSceneImage` 仍通过懒加载复用旧实现。
原因:
- 该能力属于自定义世界工具链,不是正式运行时剧情 / 对话主链。
- 当前不会再影响“浏览器正式运行时是否依赖本地大 AI 编排”这一任务 4 验收项。
### 4.2 分层彻底闭合仍需后续任务配合
尽管任务 4 已完成主链收口,但以下更深层收敛仍建议交由后续任务继续推进:
- 继续减少 `server-node``src/**` 纯提示词/纯规则模块的历史复用
- 继续把共享 contract / schema 下沉到 `packages/shared`
- 继续把工具链与正式运行时拆分
这些属于任务 1、任务 7、任务 8 的后续工作,不再阻塞任务 4 验收。
---
## 5. 本轮建议验收口径
任务 4 可按以下口径验收:
- 浏览器正式运行时不再默认兜底到本地大体量 AI 编排
- story/chat/custom world generation 主链 prompt 组装与请求执行权在后端
- SSE 主链以后端转发为准
- upstream timeout / abort / error 统一走后端处理链

View File

@@ -0,0 +1,425 @@
# Express 后端并行任务完成度审计2026-04-09
## 1. 审计范围
本次审计以 `docs/planning/EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md` 为基准,只检查仓库内可直接验证的代码、测试、脚本和文档产物。
不能仅靠仓库静态内容确认的团队协作物,例如看板、口头冻结流程、每日集成节奏,只按“仓库内可见状态”记录,不把它们误判成完全验收。
---
## 2. 任务完成度总览
| 任务 | 状态 | 结论 |
| --- | --- | --- |
| 任务 0集成岗与接口冻结 | 基本完成 | 已补齐接口冻结与集成清单文档contract 版本表、热点文件编辑规则、集成窗口检查项都已落库;但团队执行节奏本身仍无法仅凭仓库静态确认。 |
| 任务 1共享 Contract 与目录抽离 | 部分完成 | `packages/shared` 已建立并承接 auth/runtime/story contract且 NPC Task6 bridge 与 chat prompt builder 已进一步下沉到后端本地模块;但 AI 编排主链仍残留少量 `src/**` 反向依赖,分层尚未完全闭合。 |
| 任务 2PostgreSQL 持久化基线收口 | 已完成 | `server-node/src/config.ts``db.ts``repositories/**`、迁移脚本、`pg-mem` 测试与部署文档均已到位。 |
| 任务 3HTTP 基础设施与统一响应壳层 | 已完成 | 统一错误格式、`requestId`、route meta、响应壳层、观测测试已落地。 |
| 任务 4服务端 AI 编排收口 | 基本完成 | orchestration 模块、SSE 转发和主链调用已回到后端,但仍有少量 prompt/规则模块通过 `src/**` 复用,属于后续继续收敛项。 |
| 任务 5Story / Combat / NPC | 已完成 | 后端 story action route、session 组装、combat/npc 领域服务和对应回归测试已落地。 |
| 任务 6Inventory / Quest / Build / Runtime Item | 已完成 | 对应模块、服务与回归测试已经覆盖主要正式运行时结算。 |
| 任务 7前端 SDK、鉴权、持久化瘦身 | 部分完成 | `apiClient``authService``storageService` 已统一,但前端仍保留一部分存档归一化和主流程协调职责。 |
| 任务 8编辑器 API 归口与工具链隔离 | 基本完成 | editor/assets 模块、前端 editor client、迁移文档均已出现职责边界基本清晰。 |
| 任务 9测试、观测与部署基线 | 已完成 | baseline test、smoke、proxy smoke、部署与回滚清单、日志链路均已具备。 |
| 任务 10前端主流程壳层与大 Hook 瘦身 | 部分完成 | `GameShellRuntime` / `useGameShellRuntimeViewModel` 以及新的 `storyRequestCoordinator` 已拆出,但 `useStoryGeneration.ts` 仍然过重,主流程尚未彻底退回“表现层协调器”。 |
---
## 3. 本轮补齐项
本轮先补齐了任务 0 缺失的仓库内协作产物:
- 新增 `docs/technical/EXPRESS_BACKEND_INTEGRATION_FREEZE_2026-04-09.md`
- 落库当前 contract 版本表
- 明确热点文件编辑规则
- 补齐 shared/runtime/editor/frontend 壳层各自的集成窗口清单
这让任务 0 不再只停留在规划文档里,而是有了一份可随版本一起更新的冻结口径。
随后补上了一段此前仍偏向前端快照解释的恢复链路:
- `src/hooks/story/runtimeStoryCoordinator.ts`
- 新增 `resumeServerRuntimeStory`
- 继续游戏时,若当前是正式运行时故事快照,会先请求 `/api/runtime/story/state/:sessionId`
- 让当前 `storyText` 与可用 `options` 优先以后端 runtime state 为准
- `src/hooks/useGamePersistence.ts`
- `continueSavedGame()` 现在会优先走后端 runtime story 恢复
- 如果服务端恢复失败,再回退到本地快照归一化结果
- 额外补了 `bottomTab` 归一化,避免恢复时吃到宽泛字符串
- `src/hooks/story/runtimeStoryCoordinator.test.ts`
- 新增“继续游戏时优先从后端恢复 runtime story”的测试
- 新增“非正式运行时快照不额外请求后端”的测试
这次补丁对应的是任务 7 与任务 10 之间的一段未完全闭合边界:前端在恢复流程里不应该只把远端存档当作“原始 JSON 缓存”,而应优先相信后端当前 runtime state。
此外,本轮还继续补了任务 1 的一段后端分层收口:
- 新增 `server-node/src/modules/runtime/runtimeStatePrimitives.ts`
- 后端本地承接 `addInventoryItems`
- 后端本地承接 `removeInventoryItem`
- 后端本地承接 `incrementGameRuntimeStats`
- 后端本地承接 `buildRelationState`
- 新增 `server-node/src/modules/runtime/runtimeStatePrimitives.test.ts`
- 校验背包合并、移除、运行时统计累加、关系阶段映射
- 调整桥接层:
- `server-node/src/bridges/legacyInventoryRuntimeBridge.ts`
- `server-node/src/bridges/legacyNpcTask6Bridge.ts`
- `server-node/src/modules/quest/questTask6Bridge.ts`
这意味着任务 5/6 主链里最基础的一批状态原语,已经不再依赖前端 `src/data/runtimeStats.ts``src/data/attributeResolver.ts``src/data/npcInteractions.ts` 的对应实现。
本轮又继续把 NPC Task6 bridge 里最后一批直接挂到前端 `npcInteractions.ts` 的函数下沉到了后端本地:
- 新增 `server-node/src/modules/npc/npcTask6Primitives.ts`
- 后端本地承接 `applyStoryChoiceToStanceProfile`
- 后端本地承接 `buildInitialNpcState`
- 后端本地承接 `syncNpcTradeInventory`
- 后端本地承接 `getGiftCandidates`
- 后端本地承接 `buildNpcGiftCommitActionText`
- 后端本地承接 `buildNpcGiftResultText`
- 后端本地承接 `buildNpcTradeTransactionActionText`
- 后端本地承接 `buildNpcTradeTransactionResultText`
- 新增 `server-node/src/modules/npc/npcTask6Primitives.test.ts`
- 覆盖 NPC 初始库存生成
- 覆盖交易库存刷新时保留非交易物品
- 覆盖赠礼偏好排序
- 调整桥接层:
- `server-node/src/bridges/legacyNpcTask6Bridge.ts`
这意味着 Task6 的 NPC 交易/赠礼/初始库存这条支链,已经不再直接依赖前端 `src/data/npcInteractions.ts`
同时还把叙事语言检测工具下沉到了共享层:
- 新增 `packages/shared/src/llm/narrativeLanguage.ts`
- `src/services/narrativeLanguage.ts` 改为复用共享实现
- `server-node/src/modules/ai/storyOrchestrator.ts` 改为直接依赖共享层
这部分虽然不是大块业务迁移,但它属于任务 1 最稳定的一类收口:把纯函数共识从前端目录中抽离出来。
再补充一批已经完成的后端纯原语迁移:
- 新增 `server-node/src/modules/runtime/runtimeEconomyPrimitives.ts`
- 后端本地承接 `formatCurrency`
- 后端本地承接 `getInventoryItemValue`
- 后端本地承接 `getNpcPurchasePrice`
- 后端本地承接 `getNpcBuybackPrice`
- 新增 `server-node/src/modules/runtime/runtimeTreasureTexts.ts`
- 后端本地承接 `buildTreasureResultText`
- 新增 `server-node/src/modules/runtime/runtimeEconomyPrimitives.test.ts`
- 覆盖交易定价、货币文本、宝藏奖励文本
对应桥接层:
- `server-node/src/bridges/legacyNpcTask6Bridge.ts`
- 不再依赖前端 `src/data/economy.ts`
- `server-node/src/bridges/legacyTreasureRuntimeBridge.ts`
- 不再从前端导出 `buildTreasureResultText`
这说明任务 5/6 主链中一部分交易、礼物、宝藏结算反馈文本,也已经从前端数据层抽离。
本轮又进一步补了 NPC 状态与叙事记忆的后端本地原语:
- 新增 `server-node/src/modules/runtime/runtimeNpcStatePrimitives.ts`
- 后端本地承接 `normalizeNpcPersistentState`
- 后端本地承接 `markNpcFirstMeaningfulContactResolved`
- 新增 `server-node/src/modules/runtime/runtimeNarrativeMemory.ts`
- 后端本地承接 `appendStoryEngineCarrierMemory`
- 新增 `server-node/src/modules/runtime/runtimeNpcStatePrimitives.test.ts`
- 覆盖 NPC 状态归一化、首次有效接触标记、叙事载体记忆写入
对应桥接层:
- `server-node/src/bridges/legacyNpcTask6Bridge.ts`
- 不再依赖前端 `src/services/storyEngine/echoMemory.ts`
- 不再依赖前端 `src/data/npcInteractions.ts` 中的 NPC 状态归一化与首次接触标记逻辑
这进一步缩小了后端在任务 5/6 主链上对前端 story-engine 服务目录的借用范围。
本轮还整块收口了 Quest 与 Runtime Item 两条桥接链:
- 新增 `server-node/src/modules/quest/runtimeQuestModule.ts`
- 后端本地承接 `buildQuestForEncounter`
- 后端本地承接 `evaluateQuestOpportunity`
- 后端本地承接 `buildFallbackQuestIntent`
- 后端本地承接 `compileQuestIntentToQuest`
- 后端本地承接 `buildQuestGenerationContextFromState`
- 后端本地承接 `buildQuestIntentPrompt`
- 后端本地承接 Quest 进度归一化与 signal 推进
- 更新桥接层:
- `server-node/src/bridges/legacyQuestProgressBridge.ts`
- `server-node/src/bridges/legacyQuestRuntimeBridge.ts`
这意味着 Quest 的“确定性委托构建 + AI 意图上下文 + 任务推进”已经不再依赖前端 `src/data/questFlow.ts``src/services/questDirector.ts``src/services/questPrompt.ts`
同时Runtime Item 也已经收回到后端本地:
- 新增 `server-node/src/modules/runtime-item/runtimeItemModule.ts`
- 后端本地承接 `buildRuntimeItemAiIntent`
- 后端本地承接 `buildRuntimeItemIntentPrompt`
- 后端本地承接 `buildLooseRuntimeItemGenerationContext`
- 后端本地承接 `buildQuestRuntimeItemGenerationContext`
- 后端本地承接 `buildDirectedRuntimeReward`
- 后端本地承接 `buildRuntimeInventoryStock`
- 后端本地承接 `flattenDirectedRuntimeRewardItems`
- 新增 `server-node/src/modules/runtime-item/runtimeTreasureModule.ts`
- 后端本地承接 `resolveTreasureReward`
- 更新桥接层:
- `server-node/src/bridges/legacyRuntimeItemBridge.ts`
- `server-node/src/bridges/legacyRuntimeItemResolutionBridge.ts`
- `server-node/src/bridges/legacyTreasureRuntimeBridge.ts`
这说明 Runtime Item / Treasure 相关的 AI 意图、奖励生成和库存生成,也已经从前端目录中抽离。
本轮还继续整块收口了 Build / Inventory / Forge / Equipment 规则桥接:
- 新增 `server-node/src/modules/runtime/runtimeEquipmentModule.ts`
- 后端本地承接 `getEquipmentSlotFromItem`
- 后端本地承接 `getEquipmentSlotLabel`
- 后端本地承接 `getEquipmentBonuses`
- 后端本地承接 `applyEquipmentLoadoutToState`
- 新增 `server-node/src/modules/runtime/runtimeInventoryEffectsModule.ts`
- 后端本地承接 `isInventoryItemUsable`
- 后端本地承接 `resolveInventoryItemUseEffect`
- 后端本地承接 `buildInventoryUseResultText`
- 新增 `server-node/src/modules/runtime/runtimeForgeModule.ts`
- 后端本地承接 `getForgeRecipeViews`
- 后端本地承接 `executeForgeRecipe`
- 后端本地承接 `executeDismantleItem`
- 后端本地承接 `executeReforgeItem`
- 后端本地承接 `getReforgeCostView`
- 后端本地承接 `buildForgeSuccessText`
- 新增 `server-node/src/modules/runtime/runtimeBuildModule.ts`
- 后端本地承接 `appendBuildBuffs`
- 后端本地承接 `getPlayerBuildDamageBreakdown`
- 后端本地承接 `resolvePlayerOutgoingDamageResult`
对应桥接层:
- `server-node/src/bridges/legacyBuildRuntimeBridge.ts`
- `server-node/src/bridges/legacyInventoryRuntimeBridge.ts`
这意味着 Build / Inventory / Forge / Equipment 相关的后端主链结算,已经不再依赖前端 `src/data/buildDamage.ts``src/data/equipmentEffects.ts``src/data/forgeSystem.ts``src/data/inventoryEffects.ts`
本轮又补了一段任务 1 的 AI 编排收口:
- 新增 `server-node/src/modules/ai/chatPromptBuilders.ts`
- 后端本地承接 character chat reply / suggestions / summary prompt 组装
- 后端本地承接 npc chat / recruit prompt 组装
- 调整:
- `server-node/src/modules/ai/chatOrchestrator.ts`
- `server-node/src/modules/ai/orchestrator.test.ts`
这意味着 chat orchestration 已不再依赖前端 `src/services/characterChatPrompt.ts``src/services/prompt.ts`
本轮继续把 story orchestration 主链也收回到了后端本地:
- 新增 `server-node/src/modules/ai/storyPromptBuilders.ts`
- 后端本地承接 `SYSTEM_PROMPT`
- 后端本地承接 `buildUserPrompt`
- 重写 `server-node/src/modules/ai/storyOrchestrator.ts`
- 正式生产链不再依赖前端 `src/services/prompt.ts`
- 正式生产链不再依赖前端 `src/data/stateFunctions.ts`
- 正式生产链不再依赖前端 `src/data/scenePresets.ts`
- 正式生产链不再依赖前端 `src/data/hostileNpcs.ts`
- 调整:
- `server-node/src/modules/ai/orchestrator.test.ts`
到这里,`server-node` 正式生产代码路径里Story / Chat / Quest / Runtime Item / Treasure / Build / Inventory / Forge / NPC Task6 主链都已经从前端 `src/**` 目录脱钩。
本轮也继续推进了任务 10 的主流程瘦身:
- 新增 `src/hooks/story/storyRequestCoordinator.ts`
- 抽离运行时 option source 解析
- 抽离服务端 option catalog 回退策略
- 抽离 initial / next story 请求参数协调
- 新增 `src/hooks/story/storyRequestCoordinator.test.ts`
- 覆盖服务端 option catalog 切换
- 覆盖显式 option catalog 短路
- 覆盖服务端目录加载失败时回退本地可用项
- 调整:
- `src/hooks/useStoryGeneration.ts`
这说明 `useStoryGeneration.ts` 虽然仍重,但“故事请求协调”已经不再和主流程 UI 状态、NPC/战斗/宝藏后续处理混在同一个大段里。
本轮又补了一段任务 10 的纯展示逻辑拆分:
- 新增 `src/hooks/story/storyPresentation.ts`
- 抽离 story options 去重与补齐
- 抽离对白 turn 解析
- 抽离 dialogue story moment 组装
- 抽离 typewriter delay
- 新增 `src/hooks/story/storyPresentation.test.ts`
- 覆盖对白解析与 dialogue story moment
- 覆盖选项池去重与补齐
- 调整:
- `src/hooks/useStoryGeneration.ts`
这意味着 `useStoryGeneration.ts` 又减少了一批与 React 状态本身无关的纯函数逻辑,任务 10 的主流程壳层拆分继续向前推进。
本轮还补上了任务 1 的最后一条后端反向依赖:
- 删除 `server-node/src/bridges/legacyCustomWorldAiBridge.ts`
- 重写 `server-node/src/modules/ai/customWorldOrchestrator.ts`
- 后端本地承接 custom world generation 的 deterministic 生成流程
- 后端本地承接 generation progress 汇报
这意味着 `server-node/src/**` 的正式生产代码路径已经不再反向依赖前端 `src/**` 目录。
---
## 4. 仍需继续收口的重点
### 4.1 任务 1 的剩余问题
当前从仓库内直接扫描看,`server-node/src/**` 的正式生产代码路径已经不再存在对前端 `src/**` 的反向依赖。
其中 Story / Chat / Quest / Runtime Item / Treasure / Build / Inventory / Forge / Equipment / NPC Task6 / Custom World generation 相关正式生产链都已经从这个列表中退出。
同时,`server-node/src/modules/ai/orchestrator.test.ts` 已不再直接依赖前端 `src/services/prompt.ts``src/data/stateFunctions.ts`
这说明任务 1 在“后端正式生产运行时不反向依赖前端目录”这一层面已经完成。
#### 4.1.1 当前残留依赖的真实形态
从当前状态看,任务 1 后续不再是“补洞”,而是“优化”:
- 继续提高 custom world generation 的质量与保真度
- 继续把真正通用的 prompt / JSON repair / batch helper 整理进 `packages/shared``server-node/src/modules/ai/**`
- 维持后端不再回流引用前端目录的约束
#### 4.1.2 更适合的继续收口顺序
结合当前状态,任务 1 后续更适合做的是能力优化:
1. 继续增强 custom world generation 的语义保真度与校验强度。
2. 继续把 prompt builder、JSON repair、批处理工具整理到 `packages/shared``server-node/src/modules/ai/**`
3. 持续维持“后端正式生产代码不反向依赖前端目录”的约束,避免后续重新开洞。
### 4.2 任务 7 的剩余问题
前端虽然已经大量改成 SDK 消费层,但 `src/persistence/runtimeSnapshot.ts` 里仍保留较重的存档归一化与迁移修复逻辑。
这部分后续仍建议继续向后端迁移,避免前后端双边解释快照。
#### 4.2.1 `runtimeSnapshot.ts` 当前仍承担的职责
从文件本身看,`src/persistence/runtimeSnapshot.ts` 仍不是一个单纯的“读取后端结果并转成 UI 状态”的轻薄消费层。
它当前仍直接负责:
- 存档迁移 manifest 应用
- roster 归一化
- player currency 默认值补齐
- equipment loadout 回填与属性重算
- NPC persistent state 归一化
- quest log 归一化
- runtime stats 归一化
- scene encounter preview 修复
- story engine memory 缺省补齐
这说明任务 7 的剩余问题,不只是“前端还有一点 normalize 代码”,而是:
- 前端仍在解释正式存档的结构语义
- 前端仍在决定若干正式运行时字段的缺省和修复策略
- 后端与前端之间仍存在“双边都能定义快照有效形态”的空间
#### 4.2.2 下一步更合适的迁移方向
结合本轮已经补上的“继续游戏优先以后端 runtime story state 为准”这段恢复链路,任务 7 后续更适合继续向这个方向推进:
1.`runtimeSnapshot.ts` 中的迁移、归一化、缺省补齐继续下沉到后端持久化层或专门的 runtime snapshot service。
2. 让前端拿到的远端快照尽量已经是“可直接消费的正式形态”,而不是“仍需前端补算的半成品”。
3. 把前端保留的本地 hydrate 逻辑收缩到纯 UI 恢复字段,例如当前页签、面板开合、局部显示态。
只有这样,任务 7 才算真正回到“前端只做消费层,后端才是正式状态解释者”的目标。
### 4.3 任务 10 的剩余问题
当前最大的未完成项仍然是:
- `src/hooks/useStoryGeneration.ts`
它仍承担了大量:
- 正式运行时故事编排
- 本地 fallback 组织
- NPC / 宝藏 / 战斗后续协调
- 主流程状态推进
现阶段虽然已经有:
- `src/hooks/useGameShellRuntime.ts`
- `src/components/game-shell/useGameShellRuntimeViewModel.ts`
- `src/hooks/story/runtimeStoryCoordinator.ts`
- `src/hooks/story/storyRequestCoordinator.ts`
但主流程还没有彻底完成 action/view model 化,任务 10 仍应视为“进行中”。
#### 4.3.1 `useStoryGeneration.ts` 当前仍然为什么过重
从仓库现状看,`src/hooks/useStoryGeneration.ts` 目前仍有约 1700 行,且其过重问题已经不是单纯“文件太长”,而是它还保留着大量正式业务协调职责。
当前这个 hook 里仍集中着:
- `buildStoryContextFromState` 这一整块故事上下文拼装
- AI 请求前的 option catalog / fallback 组织
- NPC / 宝藏 / 战斗 / inventory / goal / session 多条子链的集中协调
- 本地 fallback story 生成
- 一部分运行时规则与 narrative context 的最终拼装入口
这意味着即使已经拆出了:
- `runtimeStoryCoordinator`
- `storyRequestCoordinator`
- `choiceActions`
- `npcEncounterActions`
- `sessionActions`
`useStoryGeneration.ts` 仍然不是“单纯的 UI 壳层 hook”而更像前端侧的运行时总协调器。
#### 4.3.2 任务 10 后续更值得优先拆的部分
按当前文件结构看,后续最值得优先继续抽离的不是零散按钮逻辑,而是下面三类真正还握在主 hook 里的核心块:
1. `buildStoryContextFromState` 这一整块 story-engine 叙事上下文装配。
2. `buildFallbackStoryForState` / `getAvailableOptionsForState` 这类“正式规则兜底与选项来源判断”。
3. NPC / Treasure / Character Chat / Session 这些子流之间的最终总装协调。
如果只是继续把零散函数拆到 `src/hooks/story/**`,但上述三块还留在主 hook 里,那么任务 10 仍然不会真正完成。
### 4.4 建议的下一轮补齐顺序
结合任务 1、任务 7、任务 10 当前的剩余形态,后续更合适的补齐顺序建议是:
1. 先继续收任务 7 的 runtime snapshot 解释权,把正式快照的迁移、修复、归一化口径继续回收到后端。
2. 再继续收任务 10`useStoryGeneration.ts` 压回主流程协调壳层,而不是继续让它承担正式运行时总装职责。
这样排的原因是:
- 任务 1 已经完成后,新的主阻塞就变成了任务 7 和任务 10。
- 如果任务 7 不继续收,前端仍会在恢复链路里保留正式状态解释权,任务 10 也很难真正变薄。
- 等到 runtime state 与 snapshot 口径都更稳定后,再继续瘦 `useStoryGeneration.ts`,返工会更少。
---
## 5. 本轮验证
已通过:
- `npm run server-node:test`
- `npx vitest run src/hooks/story/storyRequestCoordinator.test.ts src/hooks/story/runtimeStoryCoordinator.test.ts`
- `npm run typecheck`
- `npm run check:encoding`
---
## 6. 结论
从仓库可验证结果看,任务 2、3、5、6、9 已经达到“可认为完成”的状态;任务 0、4、8 基本完成;任务 1、7、10 仍有明显后续收口空间。
当前最主要的未完成中心已经不再是后端基建,而是:
**把前端主流程和存档恢复彻底收成“以后端 runtime state 和 view model 为唯一真相源”。**

View File

@@ -11,17 +11,18 @@
- 承接运行时鉴权
- 承接运行时持久化
- 承接运行时 AI 接口
- 承接编辑器写盘与资产生成工具接口
- 为 Vite 前端提供开发期代理目标
当前不再使用:
- Vite 本地 API 插件 `scripts/dev-server/`
- Vite 本地 API 插件 `scripts/dev-server/` 作为当前接口入口
## 2. 技术栈
- HTTP 框架:`Express`
- 语言与构建:`TypeScript` + `tsx` + `esbuild`
- 数据库:`better-sqlite3`
- 数据库:`PostgreSQL`
- JWT`jose`
- 密码哈希:`@node-rs/argon2`
- 日志:`pino` + `pino-http` + `pino-roll`
@@ -31,12 +32,13 @@
推荐命令:
```bash
npm run dev:node
npm run dev
```
相关脚本:
- 根目录联调:`npm run dev:node`
- 根目录联调:`npm run dev` / `npm run dev:node`
- 仅前端开发:`npm run dev:web`
- 单独启动后端开发模式:`npm run server-node:dev`
- 构建后端:`npm run server-node:build`
- 运行后端测试:`npm run server-node:test`
@@ -57,6 +59,9 @@ npm run dev:node
- `server-node/src/routes/authRoutes.ts`
- `server-node/src/routes/runtimeRoutes.ts`
- `server-node/src/modules/editor/editorRoutes.ts`
- `server-node/src/modules/assets/characterAssetRoutes.ts`
- `server-node/src/modules/assets/qwenSpriteRoutes.ts`
基础设施:
@@ -102,8 +107,12 @@ JWT 现状:
当前数据库:
- 默认 SQLite 文件:`server-node/data/genarrative.sqlite`
- 可通过 `SQLITE_PATH` 覆盖
- 当前运行时持久化已切换到 `PostgreSQL`
- 连接信息由后端 `DATABASE_URL` 环境变量注入
- 不再以本地 `SQLite` 文件作为正式运行时数据库
- 后端测试默认使用 `pg-mem` 作为内存级 PostgreSQL 兼容实现
- 基础表初始化通过 `schema_migrations` 基线管理
- 可通过 `npm run server-node:db:migrate` 主动校验并补齐数据库基线
当前核心表:
@@ -153,6 +162,33 @@ JWT 现状:
- `POST /api/runtime/items/runtime-intent`
- `POST /api/runtime/quests/generate`
编辑器工具:
- `GET /api/editor/catalog/items`
- `GET /api/editor/json/:resourceId`
- `POST /api/editor/json/:resourceId`
资产工具:
- `POST /api/assets/character-visual/generate`
- `POST /api/assets/character-visual/publish`
- `GET /api/assets/character-visual/jobs/:taskId`
- `POST /api/assets/character-animation/generate`
- `POST /api/assets/character-animation/publish`
- `GET /api/assets/character-animation/jobs/:taskId`
- `POST /api/assets/character-animation/import-video`
- `GET /api/assets/character-animation/templates`
- `POST /api/assets/qwen-sprite/master`
- `POST /api/assets/qwen-sprite/sheet`
- `POST /api/assets/qwen-sprite/frame-repair`
- `POST /api/assets/qwen-sprite/save`
编辑器与资产接口门禁:
- `EDITOR_API_ENABLED` 控制 `/api/editor/*`
- `ASSETS_API_ENABLED` 控制 `/api/assets/*`
- 非生产环境默认开启,生产环境默认关闭
## 8. Story 与 Custom World 现状
Story
@@ -179,6 +215,13 @@ Custom World
- `src/services/storageService.ts`
- `src/services/aiService.ts`
编辑器与资产工具层:
- `src/editor/shared/editorApiClient.ts`
- `src/editor/shared/useJsonSave.ts`
- `src/components/preset-editor/characterAssetStudioPersistence.ts`
- `src/tools/qwenSpriteSheetToolPersistence.ts`
## 10. 当前 Vite 角色
Vite 当前只负责代理,不再提供本地 API 插件。
@@ -187,8 +230,12 @@ Vite 当前只负责代理,不再提供本地 API 插件。
- `/api/auth`
- `/api/runtime`
- `/api/editor`
- `/api/assets`
- `/api/llm`
- `/api/custom-world/scene-image`
- `/api/ws`
全部转发到 Node 后端。
`scripts/dev-server/**` 文件仅保留为迁移参考,不再由 `vite.config.ts` 注入。

View File

@@ -0,0 +1,226 @@
# Node 后端测试、观测与部署基线
日期:`2026-04-08`
## 1. 文档目标
这份文档用于落实 `EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md` 中的任务 9
- 给 Node 后端补最小自动回归
- 给请求链路补最小可追踪基线
- 给部署、回滚、迁移补最小操作清单
当前目标不是一次性把监控平台、CI/CD、容器编排全部做完而是先确保
- 后端改动后有脚本能快速验证主链路
- 线上或联调失败时能快速定位到具体请求
- 发布前后有统一检查口径
## 2. 当前基线命令
推荐在仓库根目录执行:
```bash
npm run server-node:db:migrate
npm run server-node:test:baseline
npm run server-node:smoke
npm run server-node:smoke:proxy
```
说明:
- `npm run server-node:db:migrate`
- 用当前 `DATABASE_URL` 主动校验 PostgreSQL 基线是否可连接、可初始化
- 会确保 `schema_migrations` 和运行时基础表已补齐
- `npm run server-node:test:baseline`
- 当前先固定为任务 9 自己维护的观测基线测试
- 已覆盖 `requestId` 回传、访问日志字段、错误日志链路
- `npm run server-node:smoke`
- 启动一套基于 `pg-mem` 的临时 Express 服务
- 不依赖本地 PostgreSQL
- 走真实 HTTP 调用验证 `healthz -> auth -> runtime save/settings -> logout`
- `npm run server-node:smoke:proxy`
- 基于已构建的 `dist + server-node/dist`
- 自动拉起 `server-node + 同域反向代理 harness`
-`pg-mem` 跑同域反向代理链路 smoke
- 验证 `web -> reverse proxy -> /api/* -> server-node` 主链路
如果要一口气跑完整发布前基线,可执行:
```bash
npm run server-node:check:deploy
```
补充说明:
- `npm run server-node:test` 仍然可以继续作为更大范围的后端接口套件入口
- 但它会跟随其他并行任务一起变化,不应替代任务 9 自己的稳定基线
## 2.1 任务 9 对照清单
当前按并行任务规划中的任务 9 逐项对照:
- 后端接口测试:`npm run server-node:test`
- 关键主链路 smoke`npm run server-node:smoke`
- request/response 日志校验:`npm run server-node:test:baseline`
- 同域部署基线:本文第 6 节与 `npm run server-node:smoke:proxy`
- 反向代理 smoke 测试脚本:`scripts/smoke-same-origin-stack.ts`
- 回滚、备份、迁移检查清单:本文第 8 节与 `npm run server-node:db:migrate`
- 发布前一键检查:`npm run server-node:check:deploy`
## 3. 当前 smoke 覆盖范围
当前 smoke 脚本验证以下链路:
- `GET /healthz`
- `POST /api/auth/entry`
- `GET /api/auth/me`
- `PUT /api/runtime/save/snapshot`
- `GET /api/runtime/save/snapshot`
- `PUT /api/runtime/settings`
- `GET /api/runtime/settings`
- `DELETE /api/runtime/save/snapshot`
- `POST /api/auth/logout`
当前代理 smoke 额外验证:
- `GET /`
- `GET /healthz`(本地反向代理健康探针)
- `POST /api/auth/entry` 经反代可用
- `GET /api/auth/me` 经反代可用
- `PUT /api/runtime/save/snapshot` 经反代可用
- `GET /api/runtime/save/snapshot` 经反代可用
- `X-Request-Id` 能穿过反向代理返回给调用方
当前 smoke 的定位是:
- 优先覆盖后端化后最容易断的基础链路
- 优先覆盖前端最依赖的鉴权和持久化能力
- 不把 AI 上游依赖拉进最小回归集,避免把第三方波动误判成主链路回归
## 4. 当前观测基线
当前请求链路至少要满足以下约束:
- 支持读取外部传入的 `X-Request-Id`
- 如果调用方没有传 `X-Request-Id`,后端自动生成
- 响应头回写 `x-request-id`
- 访问日志至少包含:
- `request_id`
- `user_id`
- `method`
- `path`
- `status`
- `latency_ms`
- 错误日志至少包含:
- `request_id`
- `user_id`
- `err`
当前目的很明确:
- 浏览器、反向代理、Node 后端至少有一个共同可追踪的请求标识
- 接口失败后,能从日志里快速找到对应请求
## 5. 部署前检查清单
发布前至少执行一次:
- `npm run check:encoding`
- `npm run server-node:db:migrate`
- `npm run server-node:test:baseline`
- `npm run server-node:smoke`
- `npm run server-node:build`
- `npm run build`
- `npm run server-node:smoke:proxy`
环境变量至少确认:
- `DATABASE_URL`
- `JWT_SECRET`
- `NODE_SERVER_ADDR`
- `LOG_LEVEL`
- `LLM_API_KEY``ARK_API_KEY`
- `DASHSCOPE_API_KEY`
部署前数据库检查:
- 确认目标 PostgreSQL 可连接
- 确认发布账号具备建表或执行初始化所需权限
- 确认已执行 `npm run server-node:db:migrate` 或等效迁移步骤
- 确认现网数据已完成备份
## 6. 同域部署基线
当前推荐仍然是同域部署:
- Web 静态资源:`https://game.example.com/`
- Node API`https://game.example.com/api/*`
最小拓扑:
```text
Browser
-> Nginx / Caddy
-> dist
-> server-node
```
反向代理至少要保留这些头:
- `Host`
- `X-Forwarded-For`
- `X-Forwarded-Proto`
- `X-Request-Id`
流式接口还要确保:
- `proxy_buffering off`
- `X-Accel-Buffering: no`
## 7. 发布后 smoke 清单
发布完成后至少人工或脚本确认一次:
1. `GET /healthz` 返回 `200`
2. 响应头里能看到 `x-request-id`
3. `POST /api/auth/entry` 可正常注册或恢复账号
4. `GET /api/auth/me` 可正常识别 token
5. `PUT /api/runtime/save/snapshot``GET /api/runtime/save/snapshot` 正常
6. 日志中能用同一个 `request_id` 串起访问记录
如果线上使用反向代理生成请求 ID还要额外确认
- 代理传入的 `X-Request-Id` 没有在 Node 层丢失
- 同域入口 `/``/api/*` 可以通过同一个站点域名访问
## 8. 回滚与备份清单
回滚前先确认:
- 当前发布包版本号或 commit 可定位
- 当前数据库备份可恢复
- 当前 `.env` 或 secret 版本可回退
需要回滚时按顺序执行:
1. 停止新版本 Node 进程
2. 切回上一个稳定前端静态包和 Node 构建产物
3. 恢复上一个稳定环境变量版本
4. 如果本次发布包含数据库结构变更,先确认是否需要回滚数据
5. 回滚后重新执行 `healthz + auth + runtime save` 最小 smoke
如果本次发布已经写入了不兼容数据结构:
- 不要只回滚代码不验证数据兼容性
- 必须先确认旧版本代码是否还能读取当前数据
## 9. 后续扩展方向
任务 9 的下一轮可以继续补:
- 把 smoke 纳入 CI
- 为关键 API 增加结构化 contract 测试
- 给上游 AI 调用补 vendor/model/errorCode 维度日志
- 增加数据库迁移前后的自动检查脚本
- 增加反向代理与正式环境的联调 smoke

View File

@@ -5,6 +5,9 @@
## 文档列表
- [NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md](./NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md):当前 Node 运行时后端的技术栈、入口、鉴权、存储与接口知识图谱。
- [EXPRESS_BACKEND_INTEGRATION_FREEZE_2026-04-09.md](./EXPRESS_BACKEND_INTEGRATION_FREEZE_2026-04-09.md)Express 后端当前 contract 冻结版本、热点文件编辑规则与集成窗口清单。
- [EXPRESS_BACKEND_WORKSTREAM_AUDIT_2026-04-09.md](./EXPRESS_BACKEND_WORKSTREAM_AUDIT_2026-04-09.md):按并行工作流文档逐项核对后的完成度审计与剩余收口点。
- [EDITOR_ASSET_API_MIGRATION_2026-04-08.md](./EDITOR_ASSET_API_MIGRATION_2026-04-08.md):编辑器写盘、资产生成、任务查询从 Vite 本地插件迁到 Node 后端的接口与工具链清单。
- [GO_SERVER_RUNTIME_INTEGRATION_2026-04-07.md](./GO_SERVER_RUNTIME_INTEGRATION_2026-04-07.md)Go 服务端接入、运行时持久化迁移与当前进展记录。
- [GO_SERVER_TASKLIST_2026-04-08.md](./GO_SERVER_TASKLIST_2026-04-08.md)Go 服务端已完成与未完成事项的执行清单。
- [AI_CHARACTER_ANIMATION_TECHNICAL_SOLUTION_2026-04-04.md](./AI_CHARACTER_ANIMATION_TECHNICAL_SOLUTION_2026-04-04.md)AI 生成角色形象与角色动画的技术路线。