菜单栏
显示内容
- 我们在菜单栏图标和菜单的第一个状态行中展示当前 agent 工作状态。
- 工作活跃时隐藏健康状态;所有会话空闲后恢复显示。
- 菜单中的"Nodes"块仅列出设备(通过
node.list配对的节点),而非客户端/presence 条目。 - 当提供商使用量快照可用时,Context 下方会出现"Usage"部分。
状态模型
- 会话:事件附带
runId(每次运行)以及负载中的sessionKey。"main" 会话的键为main;如果不存在,则回退到最近更新的会话。 - 优先级:main 始终优先。如果 main 活跃,则立即显示其状态。如果 main 空闲,则显示最近活跃的非 main 会话。我们不会在活动期间来回切换;仅在当前会话变为空闲或 main 变为活跃时切换。
- 活动种类:
job:高级命令执行(state: started|streaming|done|error)tool:phase: start|result,带有toolName和meta/args
IconState 枚举(Swift)
idle— 空闲workingMain(ActivityKind)— main 会话工作中workingOther(ActivityKind)— 其他会话工作中overridden(ActivityKind)— 调试覆盖
ActivityKind → 图标
| ActivityKind | 图标 |
|---|---|
exec | 💻 |
read | 📄 |
write | ✍️ |
edit | 📝 |
attach | 📎 |
| 默认 | 🛠️ |
视觉映射
idle:正常小动物图标。workingMain:带图标的徽章,完整色调,腿部"工作"动画。workingOther:带图标的徽章,柔和色调,无快速移动。overridden:无论活动状态如何,使用选定的图标/色调。
状态行文本(菜单)
- 工作活跃时:
<会话> · <活动种类>: <标签> - 示例:
Main · exec: pnpm test、Other · read: apps/macos/Sources/OpenClaw/AppState.swift - 空闲时:回退到健康摘要。
事件处理
- 来源:控制通道
agent事件(ControlChannel.handleAgentEvent)。 - 解析字段:
stream: "job",带data.state用于启动/停止。stream: "tool",带data.phase、name、可选meta/args。
- 标签:
exec:args.command的第一行。read/write:缩短的路径。edit:路径加上从meta/diff 计数推断的更改类型。- 回退:工具名称。
调试覆盖
- 设置 → Debug → "Icon override" 选择器:
System (auto)(默认)Working: main(按工具种类)Working: other(按工具种类)Idle
- 通过
@AppStorage("iconOverride")存储;映射到IconState.overridden。
测试清单
- 触发 main 会话任务:验证图标立即切换且状态行显示 main 标签。
- 在 main 空闲时触发非 main 会话任务:图标/状态显示非 main;保持稳定直到完成。
- 在 other 活跃时启动 main:图标立即切换到 main。
- 快速工具突发:确保徽章不闪烁(工具结果的 TTL 宽限)。
- 所有会话空闲后健康行重新出现。
