線上狀態(Presence)

OpenClaw 的「線上狀態」是一個輕量級、盡力而為的即時視圖,涵蓋:

  • Gateway 本身
  • 連線至 Gateway 的用戶端(macOS App、WebChat、CLI 等)

線上狀態主要用於 macOS App Instances 分頁的畫面呈現,以及提供快速的營運可視性。

線上狀態欄位(會顯示什麼)

線上狀態項目是結構化物件,包含以下欄位:

  • instanceId(非必填但強烈建議提供):穩定的用戶端身分識別(通常為 connect.client.instanceId
  • host:人類可讀的主機名稱
  • ip:盡力取得的 IP 位址
  • version:用戶端版本字串
  • deviceFamily / modelIdentifier:硬體提示
  • modeuiwebchatclibackendprobetestnode
  • lastInputSeconds:「距離上次使用者輸入的秒數」(若已知)
  • reasonselfconnectnode-connectedperiodic
  • ts:最後更新時間戳(毫秒,自 epoch 起算)

產生端(線上狀態從何而來)

線上狀態項目由多個來源產生,並進行合併

1) Gateway 自身項目

Gateway 在啟動時會固定填入一筆「self」項目,讓 UI 在任何用戶端連線之前就能顯示 Gateway 主機。

2) WebSocket 連線

每個 WS 用戶端都從 connect 請求開始。握手成功後,Gateway 會為該連線新增或更新一筆線上狀態項目。

為什麼一次性 CLI 指令不會出現

CLI 經常為了短暫的一次性指令而連線。為了避免 Instances 清單被灌滿,client.mode === "cli" 不會轉換為線上狀態項目。

3) system-event 信標

用戶端可透過 system-event 方法定期發送更豐富的信標。macOS App 利用此機制回報主機名稱、IP 和 lastInputSeconds

4) Node 連線(role: node)

當 Node 透過 Gateway WebSocket 以 role: node 連線時,Gateway 會為該 Node 新增或更新一筆線上狀態項目(流程與其他 WS 用戶端相同)。

合併與去重規則(為什麼 instanceId 很重要)

線上狀態項目儲存在單一的記憶體 Map 中:

  • 項目以線上狀態 Key 為索引。
  • 最理想的 Key 是穩定的 instanceId(來自 connect.client.instanceId),可以在重啟後保持不變。
  • Key 不區分大小寫。

如果用戶端在重新連線時沒有提供穩定的 instanceId,可能會出現重複列。

TTL 與容量上限

線上狀態的設計初衷就是暫時性的:

  • TTL: 超過 5 分鐘的項目會被清除
  • 最大項目數: 200(超出時先移除最舊的)

這確保清單保持即時,並避免記憶體無限增長。

遠端/通道注意事項(Loopback IP)

當用戶端透過 SSH 通道或本地連接埠轉發連線時,Gateway 可能會看到遠端位址為 127.0.0.1。為了避免覆蓋用戶端自行回報的正確 IP,Loopback 遠端位址會被忽略。

消費端

macOS Instances 分頁

macOS App 渲染 system-presence 的輸出,並根據最後更新的時間長短套用狀態指示燈(Active/Idle/Stale)。

除錯技巧

  • 要查看原始清單,對 Gateway 呼叫 system-presence
  • 如果看到重複項目:
    • 確認用戶端在握手時有送出穩定的 client.instanceId
    • 確認定期信標使用相同的 instanceId
    • 檢查連線產生的項目是否缺少 instanceId(此時重複是預期行為)