会话气泡「执行状态」UI / 交互方案设计 · 不改代码

codex-usage-hud · Work Activity Bubble(430px 桌面气泡)· 基于 codex 0.150.1 Desktop + CLI 真实会话实测数据

0 · 硬性约束与实测结论Constraints & evidence

硬约束
不改变现有会话气泡的宽与高,不改变所有既有动画特效。具体落实:
  • 卡片宽仍 430px;正文 3 行高度预算不变(执行状态内容 只能在这 3 行内置换,不得新增行、不得让卡片变高变宽)
  • 既有动画全部保留:完成态 520ms 圆形化变形、悬停透明度、状态 shimmer —— 一律不动
  • 新增的执行指示仅用静态符号(▶ / ✓ / ✗)与既有 shimmer,不新增旋转/闪烁等新动画,不替换既有动画
折叠标题 = Reasoning.summary_text
Desktop 界面上"执行指令折叠标题"对应 rollout 的 Reasoning.summary_text(如 "Preparing patch to add hud-observe.txt"),位于每步工具调用之前。
硬约束:执行中零流式事件
24s 长命令从 custom_tool_callitem_completed 之间 rollout 无任何中间事件。Desktop 与 CLI 完全一致 → "最新活跃 3 行"无法实时流式刷新,只能展示命令 + 状态 + 上一步输出。
完成时数据完整
CommandExecution 含完整 command / cwd / stdout / stderr / exit_code;FileChange.changes 含每文件 diff。退出码 1 可判定失败。
时序(已确认)
task_started → reasoning(标题) → custom_tool_call(命令) → [执行空窗] → item_completed(CommandExecution) → custom_tool_call_output → token_count → agent_message → task_complete
真实样例(Desktop 会话 01a04b41):命令 1..4 | ForEach-Object { Write-Output ("hud-live-" + $_) ; Start-Sleep -Seconds 6 } 运行约 24s,输出 hud-live-1..4;失败命令 hud-no-such-cmd-xyz 退出码 1;apply_patch 生成 FileChange(新增 tmp/hud-observe.txt)。

1 · 基线(现状)Baseline

● 00:24
已按顺序完成:\n1. 第1步完整运行约24秒,输出 hud-live-1 至 hud-live-4。\n2. 已读取根目录 AGENTS.md 前 8 行…
✓ 已完成

当前气泡(来自 WORK_ACTIVITY_OVERLAY_DESIGN.md)· 宽 430px · 正文 3 行 · 既有动画保留

现状短板:① 左下角步骤条只显示最后一条 step 的短前缀(命令/读文件/编辑/失败/等确认),有效宽度受限看不到完整信息;② 主区只展示最近一轮 agent 输出(3 行截断),执行过程完全不可见;③ 执行细节(命令全文、输出、错误)在气泡内无入口。本方案在不改变宽高与动画的前提下补齐这些。

画布规格(两种方案共用,均不改变)

  • 卡片宽 430px,内边距 10/8,正文换行宽 ~402px
  • 主区:8px #B8C6D8最多 3 行(QTextLayout 省略号截断)——高度预算不可变
  • 状态色:工具执行 #9CCBFF / 运行 #F3D27A / 等用户 #FFB86B / 失败 #FF7B72 / 完成 #49E07D
  • 左下角步骤条:状态前缀 + workdir(≤170px) + 轮次徽标 + tokens(同一行,仅替换前缀文本)
  • 数据源:ParsedSession / ActivityStep 快照(Qt 气泡与 renderer 共用)
  • 动画:完成态 520ms 圆形化、悬停透明度、状态 shimmer —— 全部保留不动

2 · 方案 A「执行面板 · 切换式」Scheme A — Switch / Takeover(3 行内置换)

核心思路:执行时把正文 3 行预算整体置换为"执行面板"(命令 / 状态+回输出 / 最近输出),不新增行、卡片宽高不变;左下角同一位显示折叠标题。输出不永久丢失:完成后自动切回、L2 行内「回输出」随时手动切回。指示符全部静态(▶/✓/✗),不动既有动画。

执行面板(正文 3 行置换,高度不变)

  • L1 命令:工具图标 + 完整命令(等宽、单行省略,hover 见全文)
  • L2 状态:静态 ▶ + 折叠标题 + 已运行时长(本地计时),行尾内嵌「回输出」
  • L3 最近输出:上一步命令输出尾部(灰字)——无则显示等待提示
  • 左下角:折叠标题(短版)+ workdir + 轮次(同一行替换前缀)

交互(均不改宽高/动画)

  • hover L1 → 完整命令 tooltip;点击 L1 → 复制命令
  • L2 行内「回输出」→ 切回输出(不弹新行)
  • 完成:L2 → ✓ 完成·退出码 0·24s,1.5s 后自动切回输出;完成态圆形化动画不变
  • 失败:L2 → ✗ 失败·退出码 1(红),L3 显示 stderr 尾部,保持到 agent 新输出

3 · 方案 B「状态条 · 并置式」Scheme B — Coexist / Strip(占第 1 行 + 覆盖式浮层)

核心思路:主区以输出为主。执行时正文 第 1 行替换为一行"状态条"(静态 ▶ + 折叠标题 + 时长),输出占剩余 2 行——3 行预算不变、高度不变、不遮盖输出;点击状态条展开覆盖式浮层看最新活跃 3 行(命令/输出/状态,浮层不占高度、可关闭)。无执行时恢复纯输出 3 行。可点「展开浮层」试玩。

状态条(占正文第 1 行)+ 浮层

  • 状态条:[▶] 折叠标题 · 24s,替换正文第 1 行;输出在第 2-3 行
  • 浮层(点开):命令全文 / 输出或错误 3 行 / 状态+退出码;绝对定位覆盖、不改变气泡高度,可关闭
  • 左下角:折叠标题(短版)+ workdir + 轮次(同一行)

交互(均不改宽高/动画)

  • 状态条 hover → 完整命令 tooltip;点击 → 展开/收起浮层
  • 完成:状态条 → ✓ 完成·24s,2s 后淡出(输出恢复 3 行);完成态圆形化动画不变
  • 失败:状态条 → ✗ 失败·退出码 1(红,常驻),点击看错误 3 行
  • 浮层点外 / ✕ 收起;不阻塞点按输出区

4 · 数据映射(每个 UI 元素 ← 真实事件字段)Data mapping

UI 元素数据来源(真实事件)解析现状
折叠标题(左下角/状态条)event_msg item_completed(item.type=Reasoning).summary_text[] 或 response_item reasoning.summary[].text(去 markdown)已有 reasoning_text() 可提取,但未接入 ActivityStep(当前仅显示"正在思考")→ 需接线
命令(L1)response_item custom_tool_call.input(cmd/shell/workdir)或 item_completed CommandExecution.command[]已有 step.detail(command_execution_text,compact 140)→ 可放宽长度
执行状态 / 时长custom_tool_call.timestamp → item_completed.timestamp 本地计时;rollout 无执行中事件(硬约束)需新增(现有 elapsed 计时可复用)
最近输出 3 行(L3)item_completed CommandExecution.stdout/stderr;完成前可用上一步输出占位已有 aggregated_output(compact 220)→ 可放宽/尾部截取
失败 / 退出码item_completed CommandExecution.status=failed / exit_code已有"命令失败"前缀 → 需带出 exit_code 与错误行
文件编辑(apply_patch)item_completed item.type=FileChange.changes{path:{type,content/diff}}未解析(parser 跳过非 CommandExecution item)→ 可新增

5 · 对比与推荐 Comparison & recommendation

方案 A · 切换式(3 行置换)

  • 执行细节可见性:默认可见(3 行全给执行细节)
  • 输出优先:执行时临时让位,L2「回输出」+ 完成自动回归兜底
  • 宽高/动画:3 行内置换,不变;静态指示符,不动既有动画
  • 实现改动:主区 3 行换渲染 + footer 同一位换文本;中等
  • 风险:执行时输出暂不可见(有回切兜底)

方案 B · 并置式(占第 1 行)

  • 执行细节可见性:标题行常驻,3 行细节需展开浮层
  • 输出优先:输出占 2 行、不被遮盖,符合"输出为主"
  • 宽高/动画:3 行预算内换第 1 行 + 覆盖式浮层,不变;静态指示符,不动既有动画
  • 实现改动:新增状态行 + 浮层,输出 3→2 行适配;较小
  • 风险:执行细节多一步点击;输出从 3 行减为 2 行
推荐
默认采用 方案 B(并置式):主区保持"输出"为主且不被遮盖,最贴合你的产品主张;且 3 行预算内换第 1 行、浮层覆盖不占高度,宽高与动画完全不变。折叠标题在左下角 + 状态条始终可见,点开即得 3 行细节。方案 A(切换式)作为"专注执行"的可选模式保留(设置里切换),同样 3 行内置换、不动宽高与动画。建议落地下一步:解析 reasoning.summary_textCommandExecution.exit_code/stdout/stderr 进 ActivityStep → 双端(气泡 + renderer)按本方案渲染。
数据来源:ZCode 会话 sess_a0a6d314-6aa9-4c9f-aa70-5cd6017e8f16 实测 —— codex Desktop 会话 01a04b41 与 CLI 慢命令会话(rollout JSONL)。本页为 UI 方案示意,未修改任何代码;两方案均不改变现有气泡宽高与动画特效。