聊天轮次视觉规范

执行时间线(去外框、图标竖线串联、行样式统一)+ 手动函数运行 + 右缘消息导航。全部可交互——点开试。本文件是聊天轮次视觉的唯一权威;实现在 web/components/chat/messages/execution-strip.tsx / runtime-block.tsxapp/styles/chat/execution-strip.css

1默认(收起):一轮 = 一行淡文字 + 回复

执行过程不再有框。收起态是一行 GPT"已思考 19s ›"式的纯文字摘要——无按钮底色、与正文左对齐,hover 只提亮文字。摘要只分三类:思考 / 函数 / 子代理。点击展开时间线。
你能开一个agent,帮我去看看今天天气吗,我在北京亚洲金融大厦
思考 ×2 · 函数 ×1 · 子代理: 查询北京天气
思考 需要先核对当前日期,再决定查询口径…
用户在北京亚洲金融大厦,要今天的天气。我先用 bash 核对系统日期,确认"今天"是哪一天,然后开一个子代理去做实时查询,最后汇总成简短建议。
函数调用 bash · date '+%Y-%m-%d %H:%M %Z' → 2026-07-10 16:32 CST
子代理: 查询北京天气 已完成
思考 子代理结果可信,整理成出行建议…
数据来自中国天气网 + Open-Meteo,两源一致。整理成三行:现况、区间、建议。
北京今天小雨转暴雨,现在 25.8°C、湿度 89%;全天 24~28°C,降水概率约 98%。建议带伞,尽量减少非必要外出。
规则:外层无框无底色;收起行 = 纯文字摘要 + ›(无按钮底色,与正文列左对齐);回复文本永远直接可见。
展开只向下:高度过渡用 grid 0fr↔1fr(0.18s),展开把下方内容推开、收起平滑抽走;视口不许跳——聊天区关掉原生 scroll anchoring(overflow-anchor:none),且用户点击后的 600ms 内暂停贴底吸附,展开/收起时开关行在屏幕上纹丝不动。收起动画结束后卸载子树,折叠状态不付渲染成本。流式进行中同样折叠(用户裁决 2026-07-13):摘要小字加 shimmer 扫光表示进行中,点击才展开;展开后的列表向下拼接新步骤(淡入下滑 0.22s),当前运行中的行图标位用呼吸点,思考行的 note 显示最新一行。落定后 shimmer 停止,其余不变——流式与落定共用同一条时间线渲染路径(伪 blocks 由实时字段合成,finalize 后由真 blocks 接管)。

2时间线行:图标 + 标题 + 一行摘要 + 悬停动作

所有行同一副面孔:左列圆形图标压在竖线上,中间是标题 + 灰色单行摘要,右侧动作 hover 才出现。图标按类配色:思考紫 / 函数橙 / LLM 青 / 子代理绿。点击语义分两半:标题文字 = 超链接(点了进右栏 Executions 详情),行空白 / 图标 = 展开开关(有子树切子树,思考行切内联全文,叶子行也进右栏)。
思考 ×1 · 函数 ×2(进行中)
思考 点开的行长这样——内容与标题条同宽对齐
展开的内容块只有一层浅底色,没有边框、没有自己的头部——头就是上面那行。内容块左缘与标题条对齐(不再额外缩进)。再点一次行收回去。只有思考行内联展开;函数/子代理的详情在右栏。
函数调用 research_agent · 内部还有子调用 → 展开是缩进一层的子时间线
web_search "北京 朝阳区 今日天气" → 12 results
LLM 两源数据一致,取中国天气网为准…
read_page weather.com.cn/101010300.shtml
函数调用 deep_lookup · 子树折叠时行尾出提示 → ⋯ 3 步
函数调用 web_fetch · weather.com.cn(运行中)
函数调用 bash · 退出码 1 — 失败的行图标换红 ✗
状态就画在图标位:运行中 = 呼吸点(青),失败 = 红 ✗,正常 = 类型图标(按类配色)。行高、字号、图标列宽全部统一。
几何:主层 tl-body 左内边距 38px,20px 图标落在 4..24(圆心 14),1.5px 竖线压在 13.25px;子层左内边距 34px,17px 图标(圆心 12.5),竖线 11.75px、透明度 0.6。图标带 3px 不透明底色圈(box-shadow 0 0 0 3px bg-primary)把穿过的竖线挡出空隙;可展开行 head 悬停时圈换成图标自身色的淡化环(color-mix currentColor 22% + bg-primary——混不透明底色而非 transparent,才压得住竖线)。
悬停动作只出现在鼠标压着的那一行::hover 必须挂在 step-head 而非整个 step——嵌套树里子行悬停会同时命中所有祖先 step,一排复制按钮全冒出来。子树折叠时行尾淡字"⋯ N 步"提示。
嵌套层级:函数内部还有子调用时(@agentic_function 的执行树、工具的多层 call-tree),展开就是缩进一层的子时间线——同一套行样式递归下去,层数不限。

3手动函数运行:同一条时间线 + 消息式 footer

表单(fn-form)或 //run 手动发起的函数调用不再有独立卡片样式——就是上面同一条无框时间线,根行子树默认展开(过程即内容)。操作不挂在行尾,而是收进树下方一条消息式 footer:时间戳 + 复制 / 重试 / 修改 + 版本切换,悬停显现,左缘对齐树的图标列。把鼠标移进下面区域试。
weather_report {"city": "北京"} · 3.2s → 今天小雨转暴雨,24~28°C…
web_search "北京 今日天气" → 12 results
LLM 汇总两源数据 · 1.1s
footer 与聊天消息的 footer 同款(同一套图标按钮 + 时间戳,悬停显现),justify-content:flex-start、左缘对齐树最左的图标列;版本切换复用聊天的 .message-nav 组件(◀ N/M ▶),不另造样式。footer 的复制复制根调用的实际结果(error ?? output),不是参数 JSON。
分支语义:重试 = 参数不变的兄弟分支;修改(Edit)= 把上一次的参数预填回表单、提交后作为可改参数的兄弟分支运行(fork_of_node → 锚到原调用的前驱)。两者都在原位替换显示、旧运行经 ◀ N/M ▶ 仍可回看——绝不在会话尾部追加新调用。运行中占位 = 单条呼吸点行;嵌套在别的消息里(nested)时不渲染 footer。

4右缘消息导航:横线即消息,悬停展开列表

聊天列右缘一列小横线,一条横线 = 你发过的一条消息(当前可视的那条加亮加长)。悬停整列 → 展开消息列表面板,点击跳到那条消息。把鼠标移到右边那几条横线上试试。
你好
你好!有什么我可以帮你的吗?
你能开一个agent,帮我去看看今天天气吗
北京今天小雨转暴雨,现在 25.8°C……建议带伞。
那明天呢?
明天多云转晴,26~31°C,无降水……
你好
你能开一个agent,帮我去看看今天天气吗
那明天呢?
横线只数用户消息(回复不占位);整列贴右缘——紧靠右侧栏分割线(right: calc((100% - 100cqw)/2 + 8px),chat-area 是 inline-size 容器),不悬在正文中间。面板行单行截断;点击 = 平滑滚到那条消息并闪一下。面板出现时横线隐去,二者不叠。列表滚动时高亮跟随当前可视消息。