perf(chat): coalesce stream events per frame and pace text release
Every NDJSON event used to commit its own React update and re-parse the whole partial answer through react-markdown, so long replies grew quadratically slower. Stream events now land in a frame buffer that flushes at most once per animation frame, releases answer and thinking text at a steady pace with a twelve-frame catch-up, and settles synchronously on completion, failure and abort. Streaming markdown is split at the last completed block so only the tail is re-parsed each frame. Applied to both the consultation hook and the rectification chat. BUG-473 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
This commit is contained in:
@@ -7266,3 +7266,19 @@
|
||||
- 相关记录:BUG-453、BUG-463
|
||||
- 复发自:BUG-463(idle 不再追问,拒答路径与 occupation blocking 仍挡住采用卡)
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-473 | 流式回答每个网络事件都全量重渲染,长回答越写越卡
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-01
|
||||
- 最近更新:2026-09-01
|
||||
- 影响面:`use-consultation-run.ts` NDJSON 回调、`rectification-agentic-chat.tsx` `send` 循环、`chat-message-content.tsx`
|
||||
- 用户现象:回答越长越卡,文字一坨一坨蹦出来而不是流出来;思考步骤更新时整条消息跟着抖。
|
||||
- 触发条件:任何一次流式咨询或校正回合,回答超过一两千字后明显。
|
||||
- 根因:服务端每个模型 text-delta 立即发一条 `answer.delta`,客户端每条事件各自 `setStreamingReply` / `setMessages`;每次提交都对整段部分回答跑 `parseAgentReply`、`applyThinkingSectionProgress`、`splitSpokenAnswerAndTechniqueAudit` 和 `react-markdown` 全量 parse,随回答长度呈平方级增长。
|
||||
- 修复:新增 `lib/stream-frame-buffer.ts`,所有流式事件先落到累加器,`requestAnimationFrame` 合并成每帧最多一次提交;正文与思考文本按 `max(2, ceil(积压/12))` 每帧匀速释放,突发积压约十二帧追平,页面隐藏时退化为 250ms 定时并一次放完,`run.completed`/失败/中止时同步冲干净。`chat-message-content.tsx` 在流式时把已完成段落(最后一个空行之前,不切进代码围栏、列表项之间或表格)交给按内容记忆的前缀组件,只有尾块每帧重 parse;结算后仍整篇一次 parse。
|
||||
- 验证:`tests/stream-frame-buffer.test.ts`(释放公式、200 token/50 帧只提交 50 次、突发 12 帧追平、隐藏退化、reset/dispose)、`tests/chat-markdown-split.test.ts`(切分规则、前缀稳定、前缀与尾块分开 parse)、`tests/home-streaming-render-split.test.ts` 新增按帧驱动的渲染次数上限。
|
||||
- 防复发:流式状态必须经 `stream-frame-buffer` 提交,不得在事件回调里直接 `setState`;流式期间的 Markdown 渲染必须走前缀/尾块切分。
|
||||
- 相关记录:BUG-474
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
Reference in New Issue
Block a user