OpenClaw Presence 机制全解析:Gateway 在线设备名单的生成、合并与展示

发布时间:2026/9/15 22:13:53
OpenClaw Presence 机制全解析:Gateway 在线设备名单的生成、合并与展示 OpenClaw Presence 机制全解析Gateway 在线设备名单的生成、合并与展示【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclawPresence 是 OpenClaw 中一套轻量级、尽力而为best-effort的在线状态视图用来呈现Gateway 自身以及所有连接到 Gateway 的用户可见客户端macOS 应用、WebChat、node 节点等的实时连接元数据。本文以 docs/concepts/presence.md 为骨架结合 system-presence.ts、client-presence.ts 等源码实现系统讲解 Presence 条目的字段结构、生产来源、合并去重规则、权限边界、TTL 清理与消费端渲染。读完本文你将能够读懂 Devices 页面与 macOS Instances 标签页背后的数据流排查重复/过期实例行在需要改动 Gateway WebSocket 连接握手或system-event信标时理解其影响面并正确设计instanceId等标识。Presence 是什么Presence 是 OpenClaw 对谁在线、用什么设备、状态如何的实时视图。它不追求强一致而是以心跳和握手信息为基础在 Control UI 的Devices页面Settings → Devices以及 macOS 应用的Instances标签页中渲染实时连接元数据。从数据流上看Presence 由四个主要环节构成产生ProducersGateway 自身、WebSocket 连接握手、system-event周期信标、node 节点连接都会写入 Presence 条目存储与合并Merge所有条目存放在一个单进程内的内存 Map 中按大小写不敏感的键合并具备 TTL 与容量上限投影与广播ProjectionGateway 按接收者权限对条目做过滤投影通过presence事件和system-presenceRPC 分发消费ConsumersControl UI Devices 页面、macOS Instances 标签页读取并渲染。本文覆盖的是Gateway 客户端名册client roster。若要检测你最近使用的 Mac 并把节点告警路由到那里参见 Active computer presence。Presence 字段一条记录包含什么Presence 条目是结构化对象核心字段如下表字段含义instanceId可选的稳定客户端身份标识通常取自connect.client.instanceId强烈建议提供host人类友好的主机名clientId来自已接受连接的客户端类型与显示名相互独立people card 用它区分Terminal与原生Appip尽力而为的 IP 地址geolocation 插件 会将其解析为粗略城市信息version客户端版本字符串deviceFamily/modelIdentifier硬件提示如Mac、Windows、Linux与机型标识timeZone客户端自报的 IANA 时区如Europe/Vienna。浏览器在连接时上报当连接 IP 是 loopback、隧道或 CGNAT 时依然有用modeui、webchat、cli、backend、node、probe、test之一lastInputSeconds距上次用户输入的秒数若已知reason客户端自由填写的字符串Gateway 自身只发射self、connect、disconnectdeviceId、roles、scopes来自连接握手的设备身份与角色/作用域提示ts最后一次 presence 更新的时间戳毫秒时间戳包括心跳更新这不是用户活动时间戳onlineSince已认证人员当前连续在线时段的开始时间跨重叠连接共享lastActivityAt该在线时段内最近一次被观测到的已接受交互在观测到活动之前该字段不存在watchedSessions客户端显式声明正在查看的会话键列表按接收者过滤后返回这些字段在协议层有正式的类型定义PresenceEntrySchema位于 snapshot.ts其中onlineSince、lastActivityAt均为非负整数毫秒时间戳watchedSessions为非空字符串数组。从源码实现看SystemPresence类型定义于 system-presence.ts服务端持有的时序字段onlineSince/lastActivityAt与心跳新鲜度ts是相互独立的ts只代表这条记录最后被更新/刷新的时刻而onlineSince与lastActivityAt属于人的在线与活动时序由 Gateway 侧维护。谁能看到 PresencePresence 名册仅对拥有operator.read访问权限的操作者开放operator.write与operator.admin同样隐含读取权限。可以读到其他人在线时间、活动时序以及自报的timeZone——包括那些没有在观看任何会话的人。而 node 连接、仅配对的 operator 以及其他无读取权限的连接在连接快照中收到的是空 presence 名册也收不到任何presence事件。system-presenceRPC 同样要求 operator 读取权限。watchedSessions引用会针对每个接收者单独过滤采用与sessions.list相同的可见性规则隐藏或缺失的会话被整体省略不显示计数或占位符该过滤同时作用于连接快照、system-presence响应和 presence 事件被查看者本人并不因此向接收者授予其会话的访问权草稿drafts、隐身会话incognito sessions以及 operator 角色限制遵循同样的列表规则缺失或已删除的引用即使对 admin 也省略键保留其 agent 作用域包括 agent 限定的global与unknown引用非 admin 读者在等待认证 profile 校验期间能拿到 person 元数据但没有 watched 引用已建立的 admin 授权保留 admin 列表可见性没有任何可见引用时watchedSessions字段直接省略仅订阅消息message subscriptions不会声明查看者 presence。需要强调该策略并不改变读者之间共享哪些 IP 地址也不隔离全部 Gateway 元数据。若要求读者之间互相看不到彼此的 presence 或其他共享元数据应使用独立的 Gateway 信任边界。ProducersPresence 从哪来Presence 条目由多个来源产生并合并merged对应源码中upsertPresence/updateSystemPresence两个写入口。1) Gateway 自身条目self entryGateway 在启动时总会种入一条self条目这样即使还没有任何客户端连接UI 也能立刻看到 gateway 主机。实现见initSelfPresencesystem-presence.ts它读取os.hostname()、尽力而为的主 LAN IPv4pickBestEffortPrimaryLanIPv4、运行版本、机型标识与平台信息构造一条mode: gateway、reason: self的记录并用独立的SELF_KEY存放——这条记录不受 TTL 清理和容量淘汰影响listSystemPresence在遍历时显式跳过SELF_KEY。pickGatewaySelfPresencegateway-presence.ts负责从 presence 载荷中提取这条 self 记录供 CLI 等消费端使用并兼容旧版只有一行text的载荷格式。2) WebSocket connect 握手每个 WS 客户端都从connect请求开始。握手成功后Gateway 为该连接 upsert 一条 presence 条目。这里有一个值得注意的设计为什么短暂的 control-plane 连接不会出现在名单里CLI 命令、后端 RPC 客户端、探针probe往往只连接很短时间。为了避免这些连接带来的频繁 churn 占满整个 presence TTL处于cli、backend、probe模式的客户端不会被转化为 presence 条目。而test模式客户端仍会被跟踪因为测试套件把它们当作真实客户端的替身。3)system-event信标客户端可以通过system-event方法发送更丰富的周期性信标。macOS 应用用它上报主机名、IP、版本和存活元数据。几点关键语义物理输入活动不属于这个通用信标它由 Active computer presence 中描述的原生 node 事件专门负责Mac 会给信标打上system-presence-clear-last-input标记当前 Gateway 利用这个向后兼容的标记清除从旧版本应用继承下来的输入 recency信标同时携带一个固定 30 天的值使忽略该标记的旧 Gateway 用精确 recency覆盖而不是保留旧值该兼容值不会采样新的活动。在源码层system-event信标走updateSystemPresencesystem-presence.ts它会先用正则解析载荷text行如Node: host (ip) · app vX · last input Ns ago · mode M · reason R再按优先级选取合并键——deviceId→instanceId→ 解析出的instanceId→ 解析出的host→ip→ 截断后的text→ 本机 hostname。合并时对roles、scopes做去重并集并返回本次发生了变化的键host/ip/version/mode/reason供事件系统做变更广播。4) Node 连接role: node当节点以role: node通过 Gateway WebSocket 连接时Gateway 会为它 upsert 一条 presence 条目与普通 WS 客户端走同一流程。node 身份相关的协议定义可参考 gateway-protocol 的 node-presence.ts。连接行与信标去重Presence 条目存储在一个单一的内存 Map中键大小写不敏感用户 WebSocket 客户端每个连接一行因此两个标签页即使观看不同会话也不会互相覆盖Node 连接优先用设备 id其次connect.client.instanceId最后是连接 id。system-event信标在提供 device id 或 instance id 时按它们合并否则按解析出的 host 或其他信标元数据合并。稳定的instanceId能帮助消费端把多行关联到同一客户端但它不会合并不同的用户 WebSocket 连接。短暂连接的 control-plane 客户端则完全被排除在跟踪之外。Control UI 在展示 people 时会按记录的限定身份命名空间分组连接行具有相同限定 profile 身份的连接归为同一个人具有相同 raw ID 但未限定的连接另成一组raw ID 与某个 profile ID 恰好相同也不会合并它们的 watched sessions、连接事实或查看者计数Gateway 对在线/活动时序与协作输入计数使用同一命名空间边界——重叠的标签页只在各自命名空间内共享时序事实raw 标签页若后来获得 profile 限定此后的活动保持分离自我排除self exclusion遵循已认证用户记录的限定身份仅在该用户不可用时使用当前连接。refreshClientPresenceclient-presence.ts展示了这一逻辑的落地它依据presenceIdentity优先取authenticatedUserProfile.profileId构造限定键否则退化为裸authenticatedUserId聚合同命名空间的存活连接取所有 peer 中最早的onlineSince与最晚的lastActivityAt作为共享时序再逐个 upsert。测试用例 client-presence.test.ts 验证了这些时序合并规则例如同名 namespace 内活动时间取最大值、不同 namespaceraw 与 profile时序互不干扰等。people card参见 multi-user 中的 people cards 一节会把在线时长和观测到的活动与每条条目的心跳新鲜度分开呈现。只有具有精确限定 profile 身份的展示所有者才会从会话的实时查看者中被去重。会话查看者 presence 的相关实现见 session-viewer-presence.ts。TTL 与容量上限Presence 是有意为之的临时数据TTL超过5 分钟未更新的条目会被清理TTL_MS 5 * 60 * 1000见 system-presence.ts最大条目数200条超出时最先过期的先被丢弃MAX_ENTRIES 200。这样既保证名单常新又避免内存无限增长。listSystemPresencesystem-presence.ts在每次读取时执行清理与容量裁剪遍历删除超过 TTL 的条目跳过 self若仍超出上限则按 freshness 升序淘汰最旧的。需要留意清理与容量淘汰共用同一条 freshness 顺序即使公开时间戳发生回拨也能保持一致。另外Gateway 使用uptime 连续性计算 freshnesscontinuousTimeNow在系统挂起/休眠或时钟回拨场景下依然能推进过期判断。远程/隧道注意点loopback IP当客户端通过 SSH 隧道或本地端口转发连接时Gateway 可能看到远端地址是127.0.0.1。为了避免把隧道地址记成客户端 IPconnect 处理对检测为本地loopback的客户端直接省略ip字段而不是把 loopback 地址写进条目。这样在 geolocation 插件 解析时不会把隧道出口误判为客户端所在城市。Consumers谁在消费 PresenceControl UI Devices 页面Devices 页面把system-presence与持久的配对记录和 node 记录做 join它把 Gateway self 信标固定置顶并使用匹配的 device 或 instance id 来展示实时平台、版本、机型与输入 recency 元数据。macOS Instances 标签页macOS 应用渲染system-presence的输出并根据最后一次更新的时间差应用一个小型状态指示器Active / Idle / Stale。在协议侧presence 快照通过presence事件广播broadcastPresenceSnapshotpresence-events.ts把listSystemPresence()的结果连同presence/health的状态版本号一起广播并对慢速消费者使用dropIfSlow: true丢弃策略避免拖慢 Gateway。调试技巧想查看投影给你的名单直接对 Gateway 调用system-presence。如果看到重复行依次排查确认客户端在握手中发送了稳定的client.instanceId确认周期信标使用同一个instanceId检查是否有多个标签页或反复重连——不同的用户连接各自独立成行旧行在 TTL 到期后自然过期。相关主题Active computer presence物理 Mac 输入如何选择活跃节点并路由连接告警Typing indicators打字指示何时发送、如何调优Streaming and chunking出站流式、分块与按渠道格式化Gateway architectureGateway 组件与驱动 presence 更新的 WebSocket 协议Gateway protocolconnect、system-event、system-presence的线上协议细节Geolocation pluginpresence 中 IP 地址的城市级解析。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询