Presence
OpenClaw 的 Presence 是一个轻量级、尽力而为的视图,用于显示:
- Gateway 本身
- 连接到 Gateway 的客户端(mac 应用、WebChat、CLI 等)
Presence 主要用于渲染 macOS 应用的 Instances 标签页,并提供快速的运维可见性。
Presence 字段(显示的内容)
Presence 条目是结构化对象,包含以下字段:
instanceId(可选但强烈推荐):稳定的客户端标识(通常是connect.client.instanceId)host:易读的主机名ip:尽力获取的 IP 地址version:客户端版本字符串deviceFamily/modelIdentifier:硬件信息提示mode:ui、webchat、cli、backend、probe、test、node等lastInputSeconds:距离上次用户输入的秒数(如果已知)reason:self、connect、node-connected、periodic等ts:最后更新时间戳(毫秒,从 epoch 开始)
生产者(Presence 来源)
Presence 条目由多个来源生成并合并。
1) Gateway 自身条目
Gateway 在启动时总会生成一个 “self” 条目,这样即使没有客户端连接,UI 也能显示 Gateway 主机。
2) WebSocket 连接
每个 WebSocket 客户端都以 connect 请求开始。握手成功后,Gateway 会为该连接更新或插入一个 Presence 条目。
为什么一次性 CLI 命令不会显示
CLI 经常用于执行短暂的一次性命令。为了避免刷屏 Instances 列表,client.mode === "cli" 的连接不会生成 Presence 条目。
3) system-event 信标
客户端可以通过 system-event 方法发送更丰富的周期性信标。mac 应用用它来报告主机名、IP 和 lastInputSeconds。
4) Node 连接(role: node)
当一个 node 通过 Gateway WebSocket 以 role: node 连接时,Gateway 会为该 node 更新或插入 Presence 条目(与其他 WebSocket 客户端流程相同)。
合并和去重规则(为什么 instanceId 很重要)
Presence 条目存储在单个内存映射中:
- 条目以 presence key 作为键
- 最佳键是稳定的
instanceId(来自connect.client.instanceId),它能在重启后保持不变 - 键不区分大小写
如果客户端重连时没有稳定的 instanceId,可能会显示为重复行。
TTL 和大小限制
Presence 设计为临时性的:
- TTL: 超过 5 分钟的条目会被清理
- 最大条目数: 200 条(最旧的先删除)
这样可以保持列表新鲜,避免内存无限增长。
远程/隧道注意事项(回环 IP)
当客户端通过 SSH 隧道或本地端口转发连接时,Gateway 可能会看到远程地址是 127.0.0.1。为了避免覆盖客户端报告的正确 IP,回环远程地址会被忽略。
消费者
macOS Instances 标签页
macOS 应用渲染 system-presence 的输出,并根据最后更新的时间显示一个小状态指示器(Active/Idle/Stale)。
调试技巧
- 要查看原始列表,对 Gateway 调用
system-presence - 如果看到重复项:
- 确认客户端在握手时发送了稳定的
client.instanceId - 确认周期性信标使用相同的
instanceId - 检查连接派生的条目是否缺少
instanceId(这种情况下重复是预期的)
- 确认客户端在握手时发送了稳定的