refactor: 收口前端 SSE 传输层

This commit is contained in:
2026-06-03 14:57:02 +08:00
parent 545ffa4b2c
commit 1eeb14c50f
10 changed files with 442 additions and 579 deletions

View File

@@ -0,0 +1,34 @@
# SSE 客户端传输层收口约定
更新时间:`2026-06-03`
## 背景
前端多个服务 client 需要读取 Server-Sent Events包括创作 Agent、创意互动 Agent、视觉小说运行态和微信充值订单状态。旧实现分别在各自文件里手写事件边界查找、`TextDecoder` 解码、JSON 解析和流结束 flush容易出现 CRLF / LF 边界不一致、UTF-8 多字节字符尾部丢失、错误事件处理漂移,以及长连接达到最终状态后没有及时释放的问题。
## 决策
前端 SSE 的传输层统一收口到 `src/services/sseStream.ts`
- `readSseStream` 负责读取 `Response.body`、识别 `\n\n``\r\n\r\n` 事件边界、合并多行 `data:`、flush `TextDecoder` 尾部缓冲,并支持事件处理函数返回 `false` 后取消 reader。
- `readSseJsonStream` 只在传输事件基础上解析 JSON object空 data 与异常 JSON 继续按旧口径静默跳过。
- 各业务 client 只保留领域事件归一化、最终结果聚合和中文错误文案,不再重复实现 SSE 边界扫描、reader 循环或 UTF-8 flush。
- OpenAI 兼容流、`[DONE]` 哨兵或其它非 JSON SSE 可直接使用 `readSseStream`;业务 JSON 事件优先使用 `readSseJsonStream`
## 落地范围
本次先收口以下客户端:
- `src/services/aiService.ts`
- `src/services/creation-agent/creationAgentSse.ts`
- `src/services/creative-agent/creativeAgentSse.ts`
- `src/services/visual-novel-runtime/visualNovelRuntimeSse.ts`
- `src/services/rpg-entry/rpgProfileClient.ts`
后续新增 SSE client 时不得复制 `findSseEventBoundary``parseSseEventBlock` 或手写 reader 循环;若确实需要特殊 framing应先扩展 `sseStream.ts` 的传输能力,再在业务 client 中处理领域语义。
## 验收
- `src/services/sseStream.test.ts` 覆盖 CRLF / LF 边界、UTF-8 尾部 flush、异常 JSON 跳过和提前停止取消 reader。
- 已有 OpenAI 兼容文本流、NPC 聊天流、创作 Agent、创意互动 Agent、视觉小说运行态和充值订单状态测试继续通过。
- `npm run typecheck` 不产生新的类型错误。