生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~260k tokens,输出 ~5k tokens(本节)
在多设备环境中,用户需要知道哪些设备正在连接、它们的状态如何。OpenClaw 的 System Presence(系统在线追踪)机制记录所有连接的设备信息,并实时同步到所有客户端。
30.2.1 Presence 数据结构
每个在线设备对应一条 SystemPresence 记录(src/infra/system-presence.ts):
export type SystemPresence = {
host?: string; // 主机名
ip?: string; // IP 地址
version?: string; // OpenClaw 版本
platform?: string; // 平台信息(如 "macos 15.2")
deviceFamily?: string; // 设备族(Mac / Linux / Windows)
modelIdentifier?: string; // 硬件型号(如 "Mac16,10")
lastInputSeconds?: number; // 最后输入时间(秒前)
mode?: string; // 运行模式(gateway / node / cli)
reason?: string; // 连接原因(self / heartbeat / connect)
deviceId?: string; // 设备唯一标识
roles?: string[]; // 角色列表(operator / node)
scopes?: string[]; // 权限作用域
instanceId?: string; // 实例 UUID
text: string; // 人类可读的摘要文本
ts: number; // 最后更新时间戳
};
自身 Presence 初始化
Gateway 启动时立即调用 initSelfPresence() 注册自身:
注意这里用了同步的 spawnSync("sysctl", ...)——这是因为 initSelfPresence() 在模块加载时执行(顶层调用),此时异步 API 会增加不必要的复杂性。而且 sysctl 的执行时间通常在 1 毫秒以内。
30.2.2 Presence 存储与过期
Presence 数据存储在模块级的 Map<string, SystemPresence> 中:
listSystemPresence() 在返回数据前执行两项清理:
容量限制:如果记录数超过 200,按时间戳排序删除最旧的记录(LRU 策略)
衍生解释:LRU(Least Recently Used)是一种缓存淘汰策略。当缓存满时,优先淘汰最久未被访问的数据。这里的 Presence Map 本质上就是一个 LRU 缓存——超过容量时删除 ts 最小(最久未更新)的记录。
30.2.3 Presence 更新
当客户端(CLI、macOS 应用、iOS/Android 节点)连接或发送心跳时,Gateway 调用 updateSystemPresence() 更新 Presence:
合并策略遵循"新值优先"原则:payload(最新的客户端数据) > parsed(从 text 解析的数据) > existing(已有记录)。角色和作用域列表使用集合合并(mergeStringList),避免重复项。
客户端发送的 Presence 数据包含一个人类可读的 text 字段,格式为:
parsePresence() 使用正则表达式从这个文本中提取结构化字段,这是一种兼容性设计——即使客户端只发送 text 字段而没有结构化数据,Gateway 也能解析出关键信息。
30.2.4 Presence 版本与广播
Presence 变更会触发版本号递增和实时广播:
Gateway 在以下时机广播 Presence 更新:
客户端(如 Web 控制台)收到 Presence 更新后,可以实时显示在线设备列表、打字指示器等 UI 元素。
衍生解释:打字指示器(Typing Indicator)是即时通讯中常见的功能——当对方正在输入消息时,显示"正在输入…"的提示。在 OpenClaw 中,打字指示器的含义更广泛:它不仅包括用户正在输入,还包括 Agent 正在"思考"(调用 LLM API)和正在输出流式响应。
OpenClaw 的打字指示器通过 Presence 系统实现。当 Agent 开始处理用户消息时,Gateway 会向所有客户端广播 mode 变更:
Web 控制台和原生客户端监听这些 mode 变化来显示相应的 UI 状态(如三点动画、进度指示器等)。
SystemPresence 记录每个连接设备的详细信息:主机名、IP、平台、硬件型号、运行模式、版本等。Gateway 启动时自动注册自身。
TTL + LRU 双重机制控制 Presence 数据的生命周期:5 分钟过期自动清除,超过 200 条时淘汰最旧记录。
Presence 更新采用"新值优先"的合并策略,Key 选择支持 deviceId、instanceId、host 多级回退,确保同一设备的记录不会重复。
版本号广播让客户端能以最小开销感知 Presence 变更——只需比较一个整数即可判断是否需要拉取最新数据。
打字指示器基于 Presence 的 mode 字段实现,覆盖了 idle/thinking/writing/tool 四种状态。