Skip to content

fix: 流式渲染器在首 token 到达前启动(消除开头字号突变与首字延迟) - #272

Merged
taekchef merged 2 commits into
mainfrom
codex/fix-streaming-start
Aug 20, 2026
Merged

fix: 流式渲染器在首 token 到达前启动(消除开头字号突变与首字延迟)#272
taekchef merged 2 commits into
mainfrom
codex/fix-streaming-start

Conversation

@taekchef

@taekchef taekchef commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

问题

回答开头的体验断裂:

  1. 最开始的几个字不随流式出现,过一会儿才整段冒出来;
  2. 开头有一次明显的字号突变。

根因

流式 WebView 等到首个 token 到达才挂载,冷启动(HTML 加载 + Milkdown 初始化)被串行排在了等内容之后:

  • 冷启动期间 JS 收不到推送,且 editorReady 的 else 分支不补推已累计文本(也不消费 pendingStreamingCompletion),开头要等下一个 33ms tick 才进入渲染器——首字延迟。
  • 同族边界 bug:回答极短、ready 前已完成时,最终全文永远推不进 JS,画面停在第一个 chunk。
  • 字号断链:AgentThinkingIndicator(14.5pt SF)→ WebView 载入占位(14px)→ 正文(compact 14px / chat-wide 16px),三档在开头几百毫秒内接力。

改动

  • NotesAgentView.swift:generating 行一出现即挂载 AgentMessageMarkdownText,thinking 指示器改为覆盖层(chat 窗格 + 选区浮窗),冷启动与等首 token 并行;视图身份跨「等首 token → 流式」保持不变(与 fix: 会话回答完成瞬间气泡闪烁(视图身份跨完成时刻保持稳定) #271 同一原则)。
  • RichMarkdownEditorView.swifteditorReady else 分支补推——streaming 中补 updateStreamingMarkdown,有 pending completion 补 finishStreamingMarkdown(修掉极短回答卡死)。
  • index.html:compact chat 预览隐藏 WebView 内 14px 载入占位文本(错误状态保留),等待期由 thinking 覆盖层承担。

共享核心文件占用

无(NotesAgentView / RichMarkdownEditorView / index.html 均不在共享核心面)。

验证

  • swift build ✅ / WeiBeiSelfCheck ✅ / WeiBeiWebEditorCheck
  • 真实 App 冒烟(待验收):提问后观察开头——「正在思考」停留期间渲染器已在背后就绪,第一个字应直接以正文字号出现、随后匀速流出,无字号跳变、无开头整段延迟冒出。极短回答(一两句话)也试一条。

未做

  • AgentThinkingIndicator 与宽排正文的 14.5pt/16px 残差:不断链,暂不动。
  • 流式顺滑优化(匀速打字机泵 + 增量推送):独立分支跟进。

后续提交(Kimi 配额中断后由 ZCode 接续)

  • a0cd79d chore: 补提 index.html 重建后的资源清单——1b06643 漏提 build:editor 重新生成的 editor-resources.json,导致 CI 构建可复现门禁(git diff --exit-code)失败。已本地复跑 npm run build:editor 确认产物一致后提交。

验证(更新)

  • CI 快速编译与核心自检 ✅(pass,4m37s,run 32400916763)
  • 本地构建可复现门禁 git diff --exit-code -- Sources/WeiBei/Resources/Editor
  • 验收候选包:dist/魏碑.appWeiBeiGitCommit=a0cd79dproduction_hygiene=clean,已按最终提交重建
  • 真实 App 冒烟:待用户在候选包上验收(观察回答开头:首字应以正文字号即时出现、匀速流出、无字号跳变与开头整段延迟;另试一条极短回答)

The streaming WebView mounted only when the first token landed, so its
cold start (HTML load + Milkdown init) serialized after the wait for
content: the opening characters appeared late and in a burst, and the
row visibly hopped between the thinking indicator, a 14px loading
placeholder, and the body type size.

- Mount AgentMessageMarkdownText as soon as the generating row exists
  and keep the thinking indicator as an overlay (chat pane and
  floating panel), so the renderer warms up in parallel with the
  request.
- Replay accumulated text on editorReady: the else branch neither
  re-pushed the streaming snapshot nor consumed a pending completion,
  which also froze ultra-short answers (finished before ready) on
  their first chunk forever.
- Hide the in-WebView loading line in compact chat previews; the
  thinking overlay owns the waiting state now. Error status stays.
1b06643 更新了 index.html 但漏提交 build:editor 重新生成的
editor-resources.json,CI 的构建可复现门禁 (git diff --exit-code)
因此失败。
@taekchef
taekchef marked this pull request as ready for review August 20, 2026 18:11
@taekchef
taekchef merged commit 3204fd8 into main Aug 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant