30 KiB
| date | type | origin |
|---|---|---|
| 2026-07-01 | feat | docs/brainstorms/2026-07-01-ui-ue-enhancement-requirements.md |
feat: AgentKit UI/UE 增强 — 聊天流式 + Sticky 头部 + 日历重设计
Summary
强化 AgentKit 聊天与日历模块的 UI/UE:让 agent 思考过程与团队/私董会结果真正流式可见,让 @team/@board 模式在对话顶部持久显式,去除常驻路由噪声,给用户消息补齐复制/删除/回填操作,并让日历回到 Notion 风格的统一设计语言。覆盖 22 个需求(R1-R22),含后端 _phase_executor.py 流式切换以打通 expert_result/team_synthesis 的流式链路。
Problem Frame
当前聊天主界面的思考展示默认折叠且为纯文本,看不到 agent 推理过程;@team/@board 模式的顶部 banner 为静态文案且不可点击,无法回答"这次任务目标是什么、由哪些专家参与";专家团与私董会的最终结果以完整事件块一次性到达前端,与 final_answer 的流式体验割裂;路由元信息 tag 常驻显示对终端用户是无意义噪声;用户消息气泡无任何悬停操作;日历模块硬编码颜色与 tokens.css 的 Notion 调色板完全脱节。
来源:docs/brainstorms/2026-07-01-ui-ue-enhancement-requirements.md(经 ce-doc-review 审查强化,含 9 个 Open Questions)。
Requirements
需求追溯
| 需求组 | R-IDs | 实施单元 |
|---|---|---|
| 思考展示 | R1-R3 | U1 |
| @team/@board 头部 | R4-R7 | U2 |
| 团队/私董会流式 | R8-R11 | U3, U4 |
| 路由标签 | R12-R13 | U5 |
| 用户消息悬停 | R14-R17 | U6 |
| 日历重设计 | R18-R22 | U7 |
完整需求清单见 origin 文档。关键决策(思考混合方案、sticky 持久条、FC+自定义外壳、流式方案待定)已由 brainstorm 确认。
成功标准
- 思考进行中时
ThinkingBlock展开并显示流式光标,完成后收起为摘要条 - @team/@board 模式进入对话后顶部渲染 sticky 持久条,专家头像可点击查看详情
expert_result与team_synthesis事件按 token/文本块流式累加渲染,与final_answer体验对齐- 路由元信息 tag 默认隐藏,悬停时淡入显示
- 用户消息气泡悬停时显示复制/删除/回填操作工具条
- 日历模块统一消费
tokens.css,无硬编码颜色值
Key Technical Decisions
-
ThinkingBlock 流式光标采用 CSS 伪元素 + watch content.length 截断展示。后端已将 thinking chunks 累积到
message.thinking(chatStream.ts:512-521),前端无需改事件流,只需在ThinkingBlock.vue内 watchcontent.length做截断展示 + 闪烁光标。完成后收起为摘要条显示 token 数。 -
StickyModeHeader 为新组件,替换
ExpertTeamView+BoardStatusView。从useTeamStore()和useChatStore().boardState读取状态,合并为单一 sticky 条(position: sticky; top: 0; z-index: var(--z-sticky))。PhaseIndicator独立保留在 sticky 头部下方,不合并。 -
expert_result/team_synthesis 流式采用
execute_stream()+ token 转发 + 前端累积式 updateMessage。后端_phase_executor.py从agent.execute()切换为agent.execute_stream(),在async for event in循环中转发token/final_answer事件到 WS。前端chatStream.ts的expert_result/team_synthesis分支从一次性appendMessage改为累积式updateMessage(复用final_answer的 526-532 模式)。 -
路由 tag 隐藏采用
v-show+ opacity transition(与 U5 Approach 对齐)。AssistantText.vue的showRoutingcomputed 增加 hover 状态依赖,CSSopacity: 0→1+transition: opacity 0.2s ease淡入淡出。v-show保留 DOM 避免首次悬停的重挂载闪烁。 -
UserBubble 回填采用 chatStore 共享状态。新增
chatStore.refillText: stringref,UserBubble的回填操作设置该值,ChatInputwatch 该值回填到inputText。删除操作新增chatStore.deleteMessage(convId, msgId)从currentMessages移除(仅前端隐藏,不删服务端副本)。 -
日历 .fc- 覆盖采用最小范围 CSS 覆盖*。仅覆盖字体、边框、表头背景、今日高亮四类样式,选择器限定为
.fc-toolbar/.fc-col-header/.fc-day-today等稳定类名,接受 FC 升级时可能需要维护的成本。
High-Level Technical Design
流式事件链路(R8-R11)
Backend: _phase_executor.py
agent.execute_stream() ← async generator yields ReActEvent
├─ event_type="token" → broadcast "expert_result_chunk" { expert_id, content }
├─ event_type="thinking" → broadcast "expert_step" { expert_id, thinking }
├─ event_type="final_answer" → broadcast "expert_result_chunk" { expert_id, content }
└─ 循环结束 → broadcast "expert_result" { expert_id, content: full, status: "completed" }
Frontend: chatStream.ts
case "expert_result_chunk":
→ updateMessage(convId, lastExpertMsg.id, { content: accumulated + chunk })
case "expert_result":
→ updateMessage(convId, lastExpertMsg.id, { status: "completed" }) ← 仅标记完成,不再 append
组件依赖关系
U1 ThinkingBlock (独立)
U2 StickyModeHeader (独立,替换两个旧组件)
U3 后端流式切换 (独立,无前端依赖)
U4 前端流式消费 (依赖 U3 联调,可 mock 开发)
U5 路由 tag 隐藏 (独立)
U6 UserBubble hover (独立,需 chatStore 新方法)
U7 CalendarGrid 重设计 (独立)
Implementation Units
U1. ThinkingBlock 流式展示重设计
Goal: 让 agent 思考过程在执行时展开流式显示,完成后收起为摘要条,切换不丢失内容。
Requirements: R1, R2, R3
Dependencies: 无
Files:
src/agentkit/server/frontend/src/components/chat/ThinkingBlock.vue(修改)src/agentkit/server/frontend/tests/unit/components/ThinkingBlock.test.ts(新建)
Approach:
- 默认展开(
expanded = ref(true)),isStreaming时显示流式光标(CSS::after伪元素闪烁动画) - watch
content.length截断展示:流式中仅显示已到达的字符,模拟 token-by-token 效果 - 完成后(
isStreaming由 true→false)自动收起为摘要条,显示思考开始时间与字符数 - 摘要条点击切换展开/收起,展开时定位到上一次滚动位置(记录
scrollTop到 ref) - 状态保持:收起时内容不丢失,
contentprop 始终持有完整文本
Patterns to follow:
ChatView.vue:47-76的 streamingSteps 渲染模式(字符数 counter)final_answer在chatStream.ts:526-532的累积模式
Test scenarios:
- 流式中展开态显示光标 + 已到达字符,完成后自动收起为摘要条
- 摘要条点击展开,显示完整思考内容
- 展开→收起→再展开,滚动位置恢复到上次位置
- 空思考内容(
content="")时不显示 ThinkingBlock isStreaming=true但content=""时显示加载占位
Verification: 思考流式中可见光标闪烁与字符累加,完成后收起为一行摘要,点击可重新展开查看完整内容。
U2. StickyModeHeader + PhaseIndicator token 化
Goal: 替换静态 banner 为 sticky 持久头部条,显示模式 badge + 任务目标 + 专家头像组;PhaseIndicator 独立保留并 token 化。
Requirements: R4, R5, R6, R7
Dependencies: 无
Files:
src/agentkit/server/frontend/src/components/chat/StickyModeHeader.vue(新建)src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue(废弃/删除引用)src/agentkit/server/frontend/src/components/chat/BoardStatusView.vue(废弃/删除引用)src/agentkit/server/frontend/src/components/chat/PhaseIndicator.vue(修改 — token 化)src/agentkit/server/frontend/src/views/ChatView.vue(修改 — 替换 banner 引用)src/agentkit/server/frontend/tests/unit/components/StickyModeHeader.test.ts(新建)
Approach:
StickyModeHeader从useTeamStore()读取isTeamMode/teamState(含task_description/experts),从useChatStore().boardState读取私董会状态。注:实际 store 暴露teamState/activeExperts/leadExpert,无currentPlan/experts顶层 ref(FYI F8 提示)— 实施时通过teamState.value?.task_description与activeExperts/teamState.value?.experts访问- 左侧:模式 badge("专家团" / "私董会"),使用
--accent-team/--accent-board - 中间:任务目标(@team 取
teamState.value?.task_description)或主题(@board 取boardState.topic) - 右侧:专家头像组(
v-for渲染activeExperts,每个显示avataremoji +color边框),溢出时显示+N - 头像点击弹出
a-popover详情面板,显示name/description/persona(现有字段,不假设 role/bio)。Popover 关闭:Esc 键 + 外击关闭;关闭时焦点回归触发头像(focus management)。移动端:viewport<768px 隐藏任务主题文本,仅显示 mode badge + avatar group;+N溢出点击打开完整专家列表 popover PhaseIndicator硬编码颜色(#722ed1/#52c41a/#cf1322)替换为 token(--accent-board/--color-success/--color-error)- ChatView.vue 中
<ExpertTeamView />+<BoardStatusView />替换为<StickyModeHeader />,<PhaseIndicator />保留在其下方
Patterns to follow:
MessageShell.vue:5-11的 custom-avatar 渲染逻辑tokens.css的--z-sticky: 1020/--accent-team/--accent-board
Test scenarios:
- @team 模式进入对话后渲染 sticky 条,显示"专家团" badge + 任务目标 + 专家头像
- @board 模式进入对话后渲染 sticky 条,显示"私董会" badge + 主题 + 专家头像
- 非 team/board 模式不渲染 sticky 条
- 专家头像点击弹出 popover 显示 name/description/persona
- Popover 通过 Esc 键关闭,关闭后焦点回归触发头像
- Popover 通过外击关闭
- 头像超过 5 个时显示
+N溢出标识,+N点击打开完整专家列表 popover - viewport<768px 时隐藏任务主题文本,仅显示 mode badge + avatar group
- PhaseIndicator 颜色使用 token 变量而非硬编码
Verification: @team/@board 模式下顶部持久显示 sticky 头部条,专家头像可点击查看详情,PhaseIndicator 颜色与 tokens.css 一致。
U3. 后端 _phase_executor.py 流式切换
Goal: 将专家阶段执行从同步 agent.execute() 切换为流式 agent.execute_stream(),转发 token/thinking/final_answer 事件到 WS。
Requirements: R8, R9(后端依赖)
Dependencies: ConfigDrivenAgent.execute_stream() 暴露 — 需先在 BaseAgent/ConfigDrivenAgent 暴露 stream dispatch(react/rewoo/plan_exec/reflexion 模式委派至底层引擎;direct/llm_generate/tool_call/custom 模式定义显式 fallback)
Files:
src/agentkit/core/config_driven.py(修改 — 暴露execute_stream()+handle_task_stream()dispatch,镜像execute()→handle_task()模式)src/agentkit/core/base.py(修改 — 在 BaseAgent 加execute_stream()抽象方法签名)src/agentkit/experts/_phase_executor.py(修改 —_run_agent_steps方法)src/agentkit/experts/_synthesizer.py(修改 —_synthesize_results注入broadcast_callback参数,保留 dict 返回类型,方法内每次 LLM chunk 调用 callback 广播team_synthesis_chunk)src/agentkit/experts/orchestrator.py(修改 —_synthesize_results调用处传入_broadcast_event的部分应用作为 callback;final_result = await self._synthesize_results(...)与final_result.get("content")消费保持不变)tests/unit/experts/test_phase_executor_streaming.py(新建)
Approach:
_run_agent_steps(line 222)从await agent.execute(task_msg)改为async for event in agent.execute_stream(task_msg, ...)循环- 循环内按
event.event_type转发(载荷在event.data: dict[str, object],无event.content/event.output属性 — 见react.py:131-137ReActEvent 定义):"token"→_broadcast_event("expert_result_chunk", { expert_id, content: event.data.get("content") })"thinking"→_broadcast_event("expert_step", { expert_id, thinking: event.data.get("content") })"final_answer"→_broadcast_event("expert_result_chunk", { expert_id, content: event.data.get("output") })"tool_call"/"tool_result"→ 可选转发(保持现有expert_step语义)
- 循环结束后广播
expert_result完整事件(content = 累积的完整结果,status: "completed") TeamOrchestrator._synthesize_results接口策略:注入broadcast_callback参数,保留dict[str, object]返回类型(对orchestrator.py:289消费者零破坏)。方法内在每次 LLM 输出 chunk 时调用broadcast_callback({"chunk": text})广播team_synthesis_chunk,最终返回完整 dict;orchestrator.py:294-301的最终team_synthesis广播路径不变- 重试 + 流式合约:
_run_agent_steps的 retry 循环(_phase_executor.py:220-241)与流式交互须遵循:(a) 重试前广播expert_result_chunk_reset事件,前端清空已累积内容;(b) 最终expert_result事件携带完整内容覆盖(前端在expert_result到达时替换而非累加);(c) 重试不广播新 chunks 直到本次流式完成 — 避免失败 attempt 1 的部分 chunks 与 attempt 2 的 chunks 在前端累积成乱码 - 异步生成器安全:遵循 AGENTS.md 约定,
async def中第一个yield前禁止return(用return; yield模式) - 异常分类:遵循
docs/solutions/conventions/any-and-except-exception-governance.md,WS 广播用except (ConnectionError, RuntimeError, asyncio.TimeoutError)
Patterns to follow:
react.py:1443的execute_stream签名与 ReActEvent 结构chatStream.ts:526-532的 final_answer 累积模式(后端镜像)docs/solutions/logic-errors/long-horizon-reliability-code-review-fixes.md的execute_stream入口self.reset()前置条件
Test scenarios:
execute_stream产出 token 事件时,_broadcast_event被调用转发expert_result_chunkexecute_stream产出 final_answer 事件时,_broadcast_event被调用转发expert_result_chunk- 循环结束后广播完整
expert_result事件 execute_stream抛出异常时,phase 状态标记为 failed 且不阻塞其他阶段execute_stream中途抛出异常时,广播expert_result事件 status="error" 携带已累积内容,前端可识别错误态并保留部分内容- 流式会话必须以
expert_result(completed)或expert_result(error)终结,不允许静默挂起 execute_stream在 2 chunks 后抛异常 → retry loop 触发 → 广播expert_result_chunk_reset→ 重试成功 → 前端消息仅含 attempt 2 内容(无 attempt 1 残留)- TeamOrchestrator 综合阶段流式广播
team_synthesis_chunk
Verification: 后端日志可见 expert_result_chunk 事件按 token 推送,最终 expert_result 完整事件作为结束标记。
U4. 前端 expert_result/team_synthesis 流式消费 + 身份标识
Goal: 前端将 expert_result/team_synthesis 从一次性 append 改为累积式 update,流式过程中显示专家身份标识。
Requirements: R8, R9, R10, R11
Dependencies: U3(联调,可 mock 开发)
Files:
src/agentkit/server/frontend/src/stores/chatStream.ts(修改 — expert_result/team_synthesis 分支)src/agentkit/server/frontend/src/components/chat/messages/MessageShell.vue(修改 — 渲染 expert_name/expert_color badge)src/agentkit/server/frontend/tests/unit/stores/chatStream.test.ts(修改 — 新增流式测试)
Approach:
- 新增
expert_result_chunk事件分支:若当前无该专家的流式消息则appendMessage创建占位(status: "streaming"),否则updateMessage累加 content(复用 final_answer 526-532 模式) expert_result事件分支改为:仅updateMessage标记status: "completed"(不再 appendMessage);status="error"时标记为错误态并保留部分内容expert_result_chunk_reset事件分支(U3 重试合约):清空已累积 content,重置 streaming 状态team_synthesis_chunk同理:首次 append 占位,后续 update 累加team_synthesis事件改为:仅 update 标记完成- 并发专家流式顺序:每个
expert_id维护独立 streaming message slot(keyed byexpert_id),同 expert 的 chunks 累积到该 expert 的消息;并发专家渲染为独立并行 streaming 消息,按 first-chunk 到达时间排序 - 流式消息渲染时显示身份标识(
expert_name+expert_colorbadge),流式结束后标识保留 - R10 身份标识为用户可见的专家 badge(区别于 R12 的内部路由 tag),通过
message.expert_name/message.expert_color在 MessageShell 中渲染
Patterns to follow:
chatStream.ts:526-532的final_answer累积模式dispatchWsEvent纯函数设计(入参ChatStreamState,无模块级状态)
Test scenarios:
expert_result_chunk首次到达时创建 streaming 占位消息expert_result_chunk后续到达时累加 content 到已有消息expert_result到达时标记消息 status 为 completedexpert_result到达时 status="error" 时,标记 streaming 消息为错误态并保留部分内容expert_result_chunk_reset到达时清空已累积 content 并重置 streaming 状态team_synthesis_chunk首次到达时创建 streaming 占位team_synthesis到达时标记完成- 流式消息显示 expert_name + expert_color badge
- 流式会话异常终止时,UI 显示错误指示器不静默挂起
- 两个专家并发流式 → 两条独立 streaming 消息,各自累积自己的 chunks,按 first-chunk 到达时间排序
Verification: 专家结果按 token 流式累加显示,完成后标记为 completed,身份标识保留在最终消息上。
U5. AssistantText 路由标签悬停显示
Goal: 路由元信息 tag 默认隐藏,悬停助手消息时淡入显示。
Requirements: R12, R13
Dependencies: 无
Files:
src/agentkit/server/frontend/src/components/chat/messages/AssistantText.vue(修改)src/agentkit/server/frontend/tests/unit/components/AssistantText.test.ts(新建)
Approach:
showRoutingcomputed 增加 hover 状态依赖:return props.message.role === 'assistant' && props.message.matched_skill && isHovered.value- 根容器加
@mouseenter/@mouseleave事件设置isHovered = ref(false) - CSS
.assistant-text__routing加transition: opacity 0.2s ease,默认opacity: 0,hover 时opacity: 1 - 采用
v-show+ opacity transition(保留 DOM 避免首次悬停的重挂载闪烁,opacity:0→1+transition:opacity 0.2s ease满足 R13 淡入要求)
Patterns to follow:
- Ant Design Vue 的
<a-tag>组件用法 tokens.css的--transition-base变量(若存在)
Test scenarios:
- 默认状态路由 tag 不可见
- 鼠标悬停助手消息时 tag 淡入显示
- 鼠标移开时 tag 淡出
- 无
matched_skill的消息悬停时也不显示 tag - 淡入淡出过渡平滑无闪烁
Verification: 路由 tag 默认不可见,悬停时淡入,移开时淡出。
U6. UserBubble 悬停操作(复制/删除/回填)
Goal: 用户消息气泡悬停时显示操作工具条,支持复制、删除(前端隐藏)、回填输入框重发。
Requirements: R14, R15, R16, R17
Dependencies: 无(chatStore 新方法独立于其他单元)
Files:
src/agentkit/server/frontend/src/components/chat/messages/UserBubble.vue(修改)src/agentkit/server/frontend/src/stores/chatStore.ts(修改 — 新增 deleteMessage / refillText)src/agentkit/server/frontend/src/components/chat/ChatInput.vue(修改 — watch refillText)src/agentkit/server/frontend/tests/unit/components/UserBubble.test.ts(新建)
Approach:
UserBubble.vue根容器加@mouseenter/@mouseleave控制showActions = ref(false)- focus-visible parity:根容器加
@focus/@blur(或:focus-within)使 Tab 聚焦时也显示工具条(键盘用户可达);Touch 设备 tap on bubble 切换显示,tap elsewhere 隐藏 - 悬停时显示工具条(
v-if="showActions"):复制按钮(CopyOutlined)、删除按钮(DeleteOutlined)、回填按钮(EditOutlined) - 复制:
navigator.clipboard.writeText(content),成功后按钮短暂变色反馈 - 删除:弹出
a-popconfirm二次确认,确认后调chatStore.deleteMessage(convId, msgId)从currentMessages移除(仅前端隐藏,不删服务端副本);若有助手回复跟随(thread order 中下一条为 assistant 消息),删除按钮 disabled 并显示 tooltip "该消息已有回复,无法删除" - 回填:调
chatStore.setRefillText(content),ChatInputwatchrefillText回填到inputText,不自动发送 - chatStore 新增:
refillText = ref('')、deleteMessage(convId, msgId)、setRefillText(text)
Patterns to follow:
chatStore.resendLastUserMessage()(chatStore.ts:449-462)的消息定位模式chatStore.deleteConversation的 pending 状态清理模式(见calendar-capability-and-ui-fixes.md学习)
Test scenarios:
- 悬停时显示三个操作按钮
- Tab 聚焦用户消息时显示工具条;Enter 触发默认动作(复制)
- Touch 设备 tap on bubble 显示工具条,tap elsewhere 隐藏
- 复制按钮点击后内容写入剪贴板,按钮变色反馈
- 删除按钮点击后弹出二次确认,确认后消息从列表消失
- 删除取消后消息不消失
- 删除有助手回复跟随的用户消息 → 删除按钮 disabled + tooltip "该消息已有回复,无法删除"
- 回填按钮点击后 ChatInput 输入框显示消息文本,不自动发送
- 离开悬停后操作工具条消失
Verification: 悬停用户消息可见三个操作,复制/删除/回填功能正常,删除有二次确认。
U7. CalendarGrid token 重设计
Goal: 日历模块统一消费 tokens.css,消除硬编码颜色,.fc-* 元素对齐 Notion 风格。
Requirements: R18, R19, R20, R21, R22
Dependencies: 无(tokens.css 已含全部变量;本期不修改 tokens.css)
Files:
src/agentkit/server/frontend/src/components/calendar/CalendarGrid.vue(修改)src/agentkit/server/frontend/src/styles/calendar-overrides.css(新建 — .fc-* 覆盖)src/agentkit/server/frontend/tests/unit/components/CalendarGrid.test.ts(新建)
Approach:
CalendarGrid.vue:38的#1677ff替换为按 event_type 映射到 token(显式映射表):event_type=team→var(--accent-team)event_type=board→var(--accent-board)event_type=task→var(--color-primary)event_type=reminder→var(--color-warning)event_type=system→var(--text-tertiary)- 默认 →
var(--color-primary) - 实施前需从
CalendarGrid.vue的事件源枚举实际event_type值
- 事件卡片
backgroundColor/borderColor改为从 token 映射函数返回 - 新建
calendar-overrides.css覆盖.fc-toolbar(按钮风格)、.fc-col-header(表头背景)、.fc-day-today(今日高亮)、.fc-event(事件卡片字体/边框) - 覆盖范围最小化:仅覆盖 4 类稳定类名,接受 FC 升级时可能需要维护的成本
- 侧栏与头部工具栏组件使用 token 重绘
Patterns to follow:
tokens.css的 Notion 调色板(--color-primary: #1a1a1a、--accent-team、--accent-board)CalendarGrid.vue现有的firstDay: 1配置(见jwt-secret-dev-mode-user-id-mismatch.md学习)
Test scenarios:
- 日历事件颜色按 event_type 映射到 token,无硬编码颜色值
.fc-toolbar按钮风格与主界面按钮一致.fc-day-today今日高亮使用 token 色- 暗色模式(
[data-theme="dark"])下日历正确显示 - FullCalendar 视图切换/日期导航/事件拖拽功能不受影响
- Calendar 零事件 → 空态 placeholder 文本使用
--text-tertiarytoken - 事件获取失败 → 错误态带 retry CTA(使用
--color-errortoken) - 事件加载中 → skeleton loader 匹配 token 间距(使用
--color-border/--color-fill-quaternary)
Verification: 日历视觉与主界面 Notion 风格一致,无硬编码颜色,FC 既有功能正常。
Scope Boundaries
Deferred for later
- 思考内容的 markdown 渲染:本期 ThinkingBlock 仍以纯文本呈现(origin 文档 Deferred)
- 日历事件的拖拽创建、resize 行为变更:仅重绘视觉外壳(origin 文档 Deferred)
- 专家头像组在线状态指示:仅展示静态头像(origin 文档 Deferred)
- 路由元信息 tag 的可配置显示规则:固定为"默认隐藏 + 悬停显示"(origin 文档 Deferred)
- 后端流式推送协议的具体方案(事件变体 vs token 分块):U3 采用
execute_stream()+ token 转发,具体事件命名(expert_result_chunk等)可在实施时调整
Outside this product's identity
- 不引入新的 UI 组件库或设计系统(继续基于 Ant Design Vue + token 覆盖)
- 不替换 FullCalendar 为自建日历组件(保留 FC 核心,仅覆盖外壳与
.fc-*样式) - 不改变
PhaseIndicator的现有阶段进度语义与展示形式(仅独立保留 + token 化)
Deferred to Follow-Up Work
- R16 服务端删除语义:本期仅前端隐藏,服务端删除留待后续迭代(origin OQ4)
- 交互状态全覆盖(错误态/空态/加载态规范):origin OQ1,本期在相关单元测试中覆盖核心场景,全面规范留待后续
- 响应式与无障碍全面策略:origin OQ2,本期在组件中遵循基本 a11y,全面策略留待后续
- @team/@board 模式可发现性引导:origin OQ9(FYI 级别)
Risks & Dependencies
| 风险 | 影响 | 缓解 |
|---|---|---|
_phase_executor.py 流式切换可能影响阶段执行稳定性 |
expert_result 流式中断或丢失;retry loop 与流式交互导致前端累积乱码 | U3 单独测试;遵循 execute_stream 入口 self.reset() 前置条件;retry+流式合约:重试前广播 expert_result_chunk_reset 让前端清空,最终 expert_result 覆盖累积(详见 U3 Approach) |
FullCalendar .fc-* 类名升级时可能破坏 |
日历样式失效 | 覆盖范围最小化(4 类稳定类名);在 calendar-overrides.css 顶部注释标注风险 |
chatStore 新增 deleteMessage 可能影响会话状态一致性 |
消息索引错乱 | 参考 deleteConversation 的 pending 清理模式;单元测试覆盖删除后消息索引 |
| U3/U4 联调依赖 | 前端流式无法独立验证 | U4 可用 mock expert_result_chunk 事件开发;U3 完成后联调 |
System-Wide Impact
- 前端:ChatView 组件树结构调整(banner 替换为 sticky header);chatStore 新增方法与状态;chatStream 事件分支改造
- 后端:
_phase_executor.py执行模式变更(execute → execute_stream);WS 事件新增expert_result_chunk/team_synthesis_chunk - 测试:新增组件测试文件(ThinkingBlock / StickyModeHeader / AssistantText / UserBubble);chatStream.test.ts 扩展流式测试
- 样式:新增
calendar-overrides.css;PhaseIndicator token 化;CalendarGrid token 化
Open Questions
来自 origin 文档的 9 个 Open Questions 处理状态:
| OQ | 状态 | 处理方式 |
|---|---|---|
| OQ1 交互状态覆盖 | Deferred | 本期测试覆盖核心场景,全面规范留待后续 |
| OQ2 响应式与无障碍 | Deferred | 本期遵循基本 a11y,全面策略留待后续 |
| OQ3 流式结构 | Resolved | U3 采用 execute_stream() + token 转发 |
| OQ4 R16 删除作用域 | Resolved | 前端隐藏,服务端删除留待后续 |
| OQ5 模式切换用户流 | Addressed | U2 Approach 中覆盖 |
| OQ6 关键交互细节 | Addressed | U2/U6 Approach 中指定(Popover/Popconfirm) |
| OQ7 .fc-* 兼容性 | Noted as Risk | Risks 表中标注 |
| OQ8 Sticky 头部替代 | Resolved | brainstorm 已确认 sticky 方案 |
| OQ9 模式可发现性 | FYI | Deferred to Follow-Up |
| OQ10 (NEW) U3 后端协议 scope 声明 | Deferred | origin 行 88 显式排除后端流式协议("不属本文档 scope"),但 U3 已纳入本计划作为实施单元。是否重新分类 U3 为 "Cross-cutting dependency unit"(与 UI/UE 单元分开)或显式标注为 scope 扩展?建议实施前确认。 |
| OQ11 (NEW) PhaseIndicator token 化 R-id 追溯 | Deferred | U2 中 PhaseIndicator 颜色 token 化(#722ed1/#52c41a/#cf1322 → --accent-board/--color-success/--color-error)无对应 R-id 追溯(origin R7 仅要求"独立保留 + token 化")。是否新增 R-id 显式覆盖此 token 化工作,或延后到独立 token 化 pass 处理其他组件同类硬编码? |
Sources & Research
- Origin:
docs/brainstorms/2026-07-01-ui-ue-enhancement-requirements.md(ce-brainstorm 产出 + ce-doc-review 审查强化) docs/solutions/logic-errors/long-horizon-reliability-code-review-fixes.md—execute_stream入口 reset 前置条件、team_synthesis 综合阶段完整内容读取docs/solutions/ui-bugs/calendar-agent-create-no-refresh.md— WS 事件链端到端追踪模式、notify_callback 注入docs/solutions/logic-errors/calendar-capability-and-ui-fixes.md— SystemMonitorPanel flex 方向、deleteConversation pending 清理docs/solutions/conventions/any-and-except-exception-governance.md— WebSocket 异常分类、CancelledError 守卫docs/solutions/integration-issues/jwt-secret-dev-mode-user-id-mismatch.md— CalendarGrid firstDay 配置- 代码库研究:
react.py:1443(execute_stream)、_phase_executor.py:222(流式缺口)、chatStream.ts:526-532(final_answer 累积模式)、tokens.css(Notion 调色板)、configs/experts/*.yaml(专家元数据字段)