feat(web): chat 过程展示两层化 —— Adaptive Title 分层 + composer 常驻运行条 - #1145
Conversation
组头(运行中)从「只滚动最新一次调用」改为两层:上层=段级现在时动词 (Exploring/探索中,shimmer)+ 实时 bucket 计数,下层=now 行滚动当前调用 (复用 live-peek-line;展开组体时隐藏,避免一个状态两处渲染)。沉淀后组头 恢复最终聚合并追加段级 diff 汇总(+N/-N)。 composer dock 新增 runtime line:streaming 且未阻塞于审批/ask_user 时显示 工作中 + 已耗时 + 步数;跟随 composer 不随消息流滚走,回答「还活着吗」。 token 用量流里还没有,耗时+步数是诚实的客户端代理信号。 i18n 三语同改:新增 chat.process.phase.* 与 chat.runtime.working。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e841e25673
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const start = props.startedAt ?? selfStart | ||
| if (!start) return '' | ||
| const seconds = Math.max(0, Math.floor((now.value - start) / 1000)) |
There was a problem hiding this comment.
Use one clock for elapsed time
When the browser clock differs from the server clock, this produces a misleading duration because startedAt originates from the server's run.started_at, while now is taken from the client's Date.now(). A client clock that is five minutes ahead immediately displays 5m, while one that is behind remains at 0s; measure from a client-side receipt time or compensate for the server/client offset.
Useful? React with 👍 / 👎.
| <div | ||
| class="flex items-center gap-1.5 px-1.5 pb-1.5 text-xs text-muted-foreground select-none" | ||
| role="status" |
There was a problem hiding this comment.
Keep the ticking clock outside the live status region
For screen-reader users, role="status" creates a polite live region, and the elapsed label inside it changes every second. That can cause the runtime status to be announced repeatedly for the entire turn; keep the stable working announcement in the status region while hiding the visual clock from assistive technology or placing it outside the live region.
Useful? React with 👍 / 👎.
第一轮实现没有照着第 17 页 demo 做,是自我想象的改写,已纠正: - 撤掉 composer runtime 条(自创元素,demo 里没有;且英文有 1 steps 单复数 bug)。composer-dock / chat-pane 恢复原状。 - 组头改两色分层:muted 段动词(ing/done 时态,只有它带 shimmer)+ 深色 裸计数 details(12 files, 4 searches, 3 commands)。计数从 bucket 动词短语 改为按 fragment 种类的裸名词,files/searches 拆分(browse 桶混算会导致 「8 次搜索读成 8 个文件」)。 - 单工具段保持原有具体 label,不叠段动词(避免 Running Run ls 式结巴)。 - now 行从 live-peek-line 换成 demo 的滚动行:同正文大小、cop-title 色、 translateY roll 动画;工具输入未流完时显示 pending 文案(与组内行一致)。 - i18n:phase 重构为 ing/done 对,新增 frag.* 与 fragmentSeparator,删 runtime。
背景
chat view 运行中的过程展示有两个问题(对照演讲稿第 17 页 demo / Cursor / Claude Code 的设计语言):
改动(对齐演讲 demo 的设计)
两层 Adaptive Title(
tool-call-group.vue)Exploring/探索中,只有动词带 shimmer)+ 深色裸计数 details(3 files, 1 search, 2 commands,随调用增长);其下 now 行滚动当前那一次调用(正文同大同色,translateY roll 动画;工具输入未流完时显示 pending 文案,与组内行措辞一致)。Explored/已探索),计数定格,追加段级 diff 汇总(+284 −96,从每行自己的 display 数学累加)。Run echo done),不叠段动词——否则 "Running Run ls" 式结巴,且与 now 行重复。i18n:三语同改。
chat.process.phase.*(9 段动词 × ing/done)、chat.process.frag.*(裸计数)+fragmentSeparator。未做(原计划在演进的):composer 常驻 runtime 条(Working+耗时+步数)——demo 里没有这个元素,第一版做了已被撤掉;token 用量需 stream 携带,留作后端后续项。
验证状态(如实)
src/pages/home+src/store/chat区域 431 全过;全仓pnpm lint干净。Test plan