feat(home-chat): 新增 stream 级 typing indicator 覆盖请求真空期 - #481
Merged
Conversation
- 抽取 ChatTypingIndicator 共享组件(inline / standalone 两种 variant),把
AssistantReplyBubble 与 MessageBubble 内既有的三点 bounce 占位收敛为单一
事实源;保留 data-testid="agent-waiting-placeholder" 兼容既有测试。
- ChatStream 新增 pending prop:在 displayBlocks 之外渲染 standalone 三点
动画,覆盖「用户已发送但 Assistant 气泡尚未挂载」的网络真空期;末尾
block 已是 assistant-reply 时让位给 bubble 级 placeholder,形成无缝接力。
- home-body 用既有 effectiveConnection ∈ {connecting, streaming} 直接驱动
pending,不引入新 state,不动 activeRunIdRef(PR #479 故意保持 ref 以
规避并发 race),完全外置于 buildChatDisplayBlocks / 折叠闸门 / invocationId
映射等高风险路径,零回归风险。
- 组件含 role="status" + aria-live="polite" + sr-only 文本,并对
prefers-reduced-motion 启用 motion-reduce:animate-none 静态降级。
- 新增 12 个单元测试覆盖 indicator 与 ChatStream pending 接力路径,整套
625 个测试全绿,typecheck / lint 干净。
- 通过 chrome_devtools 接入用户主 Chrome 实机验证:fiber 反查确认 pending
prop 正确绑定;timeline 完整捕获 mount → unmount 生命周期;暗色色彩对比
通过;无 console 错误。
🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
ThreeFish-AI
added a commit
that referenced
this pull request
Jul 5, 2026
…-2026-4372 处置) (#1057) * fix(deps): ts-deepmerge 补丁地板至 8.0.0 修复 GHSA-87mf-gv2c-c62c (#481); 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com> * fix(negentropy): pydantic-settings 升 2.14.2 + joserfc>=1.6.7 补丁地板修复 #482/#488; 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com> * fix(cognizes): joserfc/msgpack/python-socketio/python-engineio 补丁地板修复 #483/#486/#487/#490/#491; 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com> * docs(perceives): ISSUE-092 增补 CVE-2026-4372 威胁模型;transformers 钉 4.x + dismiss #492(marker 5.x 不兼容实测); 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
用户在首页 Home Chat 发送消息后,前端在「请求已发出 → Agent 流式内容首次显示」之间存在 100–500ms(慢网或冷启动可达数秒)的等待真空期:
AssistantReplyBubble.tsx:118-128早期已有三点 bounce 占位,但只覆盖「气泡已挂载但 segments 仍为空」的窗口;本 PR 在更上游的 ChatStream 层补一段 stream 级 indicator,与 bubble 级 placeholder 形成无缝接力。改动总览
ChatTypingIndicator(inline / standalone 两种 variant),把AssistantReplyBubble与MessageBubble内既有的三点 bounce 占位收敛为单一事实源;保留data-testid=\"agent-waiting-placeholder\"兼容既有测试。ChatStream新增pendingprop:在displayBlocks.map之外追加 standalone 三点动画,覆盖 Assistant 气泡尚未挂载的真空期;末尾 displayBlock 已是 assistant-reply 时让位给 bubble 级 placeholder,避免双 indicator。home-body直接以既有effectiveConnection ∈ {connecting, streaming}派生pending,不引入新 state、不动activeRunIdRef(PR fix(home-chat): 根治重复渲染/乱序/双气泡 — Phase 3 折叠闸门 + invocationId 映射 + sort tiebreaker #479 故意以 ref 形式保留以规避并发 race)。role=\"status\"+aria-live=\"polite\"+ sr-only 文本;动效降级:motion-reduce:animate-none响应prefers-reduced-motion。风险评估(对 PR #479)
buildChatDisplayBlocks去重/排序/Phase 3 折叠闸门displayBlocks.map之外渲染invocationId映射activeRunIdRef并发隔离conversation-tree/session-hydration/useAgentSubscription回归风险:低。
业界最佳实践对照
useChat:暴露isLoading由调用方决定 UI — 与本方案effectiveConnection派生pending概念一致。自证材料
测试
ChatTypingIndicator.test.tsx6 条 +ChatStream.pending.test.tsx6 条),覆盖 inline/standalone 两个 variant、a11y、reduced-motion、向后兼容、stream→bubble 接力路径。pnpm typecheck、pnpm lint --max-warnings=0:均通过。浏览器实机验证(chrome_devtools 接入用户主 Chrome 真实登录态)
<ChatStream>收到pendingprop(key 列表含pending);实机截图归档于
.context/typing-indicator-*.png。Test plan
🤖 Generated with Claude Code, CodeX, Gemini