Squashes feat/tui-cache-hit-rate and feat/tui-verbose-status: the footer shows cache hit rate and the running status line reports turn phase with elapsed timing.
4.3 KiB
Agent Note: 运行状态行展示轮次阶段与已用时长
Status: implemented
English | 中文
问题
在轮次运行期间,全屏 TUI 只显示一个静态的 "Working" loader 动画。它既不表明当前步骤已耗时多久,也不表明 agent(智能体)正在做什么——等待模型、思考、流式输出回复,还是运行工具——因此运行缓慢或卡住的轮次与运行很快的轮次无从区分。
决策
- 轮次运行期间,编辑器上方的状态行显示一个派生的阶段标签及已用时长,并保留末尾的
— Enter sends steering, Esc cancels提示。四个阶段及其标签为waiting→ "Waiting for the first token"、thinking→ "Thinking"、responding→ "Responding"、executing→ "Executing tools"。 - 阶段是 TUI 从实时会话事件派生出的呈现状态,而非它自有的会话事件或 agent 状态。
step/start进入waiting;assistant/chunk的 reasoning 分片或 reasoning 块开始(block-start)进入thinking;text 分片或 text 块开始进入responding;tool/call进入executing。该事件映射可合并扩展,因此其余任何事件类型都落入默认分支,保持阶段不变。 - 标签汇报两个时钟——
<phase> <phase-elapsed> · total <step-elapsed>——但waiting只显示步骤总时长。阶段时钟在真正发生阶段切换或进入新步骤时重置;步骤时钟在step/start时重置。时长在不足一分钟时格式化为8s,达到或超过一分钟时格式化为1m05s。step/end与下一个step/start之间的工具时间计入结束步骤的总时长。 - 单一的
RunningStatus控制器——loader、阶段、两个基准时刻以及一个刷新定时器——仅在轮次运行期间存在。一个每秒触发的setInterval刷新已用时长;阶段事件则立即刷新。clearStatus清除该 interval、停止 loader 并丢弃控制器,因此任何向 idle 或 disposed 的转变都不会遗留活动定时器,与 banner 扫入动画的定时器清理保持一致。轮次进行中的调色板重建(终端颜色方案变化时setStatus会重新派生编辑器边框)会将阶段与两个基准时刻一并沿用过来,因此运行中的状态绝不会退回waiting。
曾考虑的替代方案
将阶段作为会话事件或 agent 状态发出。 已否决:阶段是 TUI 从已记录事件重建出的呈现细节。一个持久、模型可见的阶段会依据 model-visible ⟺ logged 规则要求新增一个会话事件,而对模型没有任何好处。
复用 pi-tui 的 Loader 动画定时器来刷新已用时长文本。 不可行:Loader 是 vendored 依赖,只驱动其加载动画字形,其 dist 不归我们改动。TUI 自持一个独立的每秒 interval,并在拆卸时清除。
从工具耗尽或流式组件状态推断阶段。 已否决:step/start、assistant/chunk 和 tool/call 这些生命周期事件是更干净的信号,已在同一个实时监听器中处理,且避免让状态行与其他组件耦合。
只显示已用时长,或只显示阶段。 已否决:两者都需要——按阶段的时长回答 agent 在做什么,按步骤的总时长回答该步骤已耗时多久。
后果
- 状态行例如显示
Thinking 4s · total 8s — Enter sends steering, Esc cancels,从而 agent 的当前活动与步骤时长一目了然,卡顿也随之可见。 - 阶段检测是尽力而为的呈现:未处理的未来分片或事件类型会保持上一个阶段不变,绝不抛错。
- 每个活动轮次恰好运行一个
setInterval,在每次向 idle 或 disposed 的转变以及关停时随控制器一并清除。
测试
packages/ui/tui/tests/tui.spec.ts 针对触发事件锁定每个阶段标签(step/start、reasoning 与 text 的分片及块开始、tool/call),并锁定新步骤会重新开启等待窗口、已用时长在控制器自有定时器上超过一秒后递增、超过一分钟的步骤渲染为 1m…、轮次进行中的颜色方案变化会保留阶段与已用时长,以及轮次开始前到达的实时事件不移动任何状态。已在 tmux 中实机验证。