iOS 應用程式(Node)

可用狀態:內部預覽。iOS 應用程式尚未公開發布。

功能說明

  • 透過 WebSocket 連線至 Gateway(區域網路或 tailnet)。
  • 提供節點功能:Canvas、螢幕快照、相機擷取、位置、對話模式、語音喚醒。
  • 接收 node.invoke 指令並回報節點狀態事件。

需求

  • Gateway 在另一台裝置上運行(macOS、Linux 或 Windows 透過 WSL2)。
  • 網路路徑:
    • 同一區域網路透過 Bonjour,
    • 透過 Tailnet 使用 unicast DNS-SD(範例網域:openclaw.internal.),
    • 手動指定主機/連接埠(備援方式)。

快速開始(配對 + 連線)

  1. 啟動 Gateway:
openclaw gateway --port 18789
  1. 在 iOS 應用程式中開啟設定,選擇已發現的 Gateway(或啟用 Manual Host 並輸入主機/連接埠)。

  2. 在 Gateway 主機上核准配對請求:

openclaw devices list
openclaw devices approve <requestId>
  1. 驗證連線:
openclaw nodes status
openclaw gateway call node.list --params "{}"

官方版本的 Relay 推播

官方發布的 iOS 版本使用外部推播中繼伺服器,不會將原始 APNs token 發送給 Gateway。

Gateway 端需要的設定:

{
  gateway: {
    push: {
      apns: {
        relay: {
          baseUrl: "https://relay.example.com",
        },
      },
    },
  },
}

流程運作方式:

  • iOS 應用程式使用 App Attest 和應用程式收據向中繼伺服器註冊。
  • 中繼伺服器回傳一個不透明的 relay handle 以及一個限定於該次註冊的 send grant。
  • iOS 應用程式取得已配對 Gateway 的身分識別,並在中繼註冊時一併傳入,讓註冊委派給特定的 Gateway。
  • 應用程式透過 push.apns.register 將該 relay 註冊資訊轉發給已配對的 Gateway。
  • Gateway 將儲存的 relay handle 用於 push.test、背景喚醒及喚醒推播。
  • Gateway 的 relay base URL 必須與官方/TestFlight iOS 版本中內建的 relay URL 相符。
  • 若應用程式後來連線至不同的 Gateway 或使用不同 relay base URL 的版本,會重新進行 relay 註冊,而非沿用舊的綁定。

此路徑下 Gateway 不需要

  • 部署層級的 relay token。
  • 官方/TestFlight relay 推播所需的直接 APNs 金鑰。

預期的操作流程:

  1. 安裝官方/TestFlight iOS 版本。
  2. 在 Gateway 上設定 gateway.push.apns.relay.baseUrl
  3. 將應用程式與 Gateway 配對,等待連線完成。
  4. 應用程式在取得 APNs token、操作者工作階段已連線且 relay 註冊成功後,自動發布 push.apns.register
  5. 之後 push.test、重新連線喚醒及喚醒推播即可使用儲存的 relay 註冊資訊。

相容性說明:

  • OPENCLAW_APNS_RELAY_BASE_URL 仍可作為 Gateway 的暫時環境變數覆蓋。

驗證與信任流程

中繼伺服器的存在是為了實施兩項直接在 Gateway 上處理 APNs 所無法提供的限制(針對官方 iOS 版本):

  • 只有透過 Apple 發布的正版 OpenClaw iOS 版本才能使用託管的中繼伺服器。
  • Gateway 只能對與該特定 Gateway 配對的 iOS 裝置發送 relay 推播。

逐跳說明:

  1. iOS app -> gateway

    • 應用程式先透過標準 Gateway 驗證流程與 Gateway 配對。
    • 配對後取得已驗證的節點工作階段及操作者工作階段。
    • 操作者工作階段用於呼叫 gateway.identity.get
  2. iOS app -> relay

    • 應用程式透過 HTTPS 呼叫中繼註冊端點。
    • 註冊時包含 App Attest 證明與應用程式收據。
    • 中繼伺服器驗證 bundle ID、App Attest 證明及 Apple 收據,並要求官方/正式發布路徑。
    • 這就是為何本機 Xcode/開發版本無法使用託管中繼伺服器——本機版本可能有簽章,但無法滿足中繼伺服器所要求的 Apple 正式發布證明。
  3. gateway identity delegation

    • 在中繼註冊前,應用程式從 gateway.identity.get 取得已配對 Gateway 的身分識別。
    • 應用程式將該 Gateway 身分識別放入中繼註冊請求中。
    • 中繼伺服器回傳委派給該 Gateway 身分識別的 relay handle 和限定範圍的 send grant。
  4. gateway -> relay

    • Gateway 儲存從 push.apns.register 取得的 relay handle 和 send grant。
    • push.test、重新連線喚醒及喚醒推播時,Gateway 以自己的裝置身分簽署發送請求。
    • 中繼伺服器同時驗證儲存的 send grant 與 Gateway 簽章是否與註冊時委派的 Gateway 身分相符。
    • 即使其他 Gateway 取得了 handle,也無法重複使用該儲存的註冊資訊。
  5. relay -> APNs

    • 中繼伺服器擁有正式版的 APNs 憑證和原始 APNs token。
    • 對於 relay 方式的官方版本推播,Gateway 從不儲存原始 APNs token。
    • 中繼伺服器代表已配對的 Gateway 向 APNs 發送最終推播。

採用此設計的原因:

  • 避免將正式版 APNs 憑證放在使用者的 Gateway 上。
  • 避免在 Gateway 上儲存官方版本的原始 APNs token。
  • 只允許官方/TestFlight OpenClaw 版本使用託管的中繼伺服器。
  • 防止某個 Gateway 向不屬於它的 iOS 裝置發送喚醒推播。

本機/手動版本仍使用直接 APNs。若你在沒有中繼伺服器的情況下測試這些版本,Gateway 仍需直接提供 APNs 憑證:

export OPENCLAW_APNS_TEAM_ID="TEAMID"
export OPENCLAW_APNS_KEY_ID="KEYID"
export OPENCLAW_APNS_PRIVATE_KEY_P8="$(cat /path/to/AuthKey_KEYID.p8)"

探索路徑

Bonjour(區域網路)

Gateway 在 local. 上廣播 _openclaw-gw._tcp。iOS 應用程式會自動列出這些項目。

Tailnet(跨網路)

若 mDNS 遭到阻擋,請使用 unicast DNS-SD 區域(選擇一個網域,例如 openclaw.internal.)加上 Tailscale split DNS。 範例請參閱 Bonjour 的 CoreDNS 設定。

手動主機/連接埠

在設定中啟用 Manual Host,輸入 Gateway 主機與連接埠(預設 18789)。

Canvas + A2UI

iOS 節點使用 WKWebView 呈現 Canvas。透過 node.invoke 來驅動:

openclaw nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-host>:18789/__openclaw__/canvas/"}'

說明:

  • Gateway canvas host 提供 /__openclaw__/canvas//__openclaw__/a2ui/
  • 由 Gateway HTTP 伺服器供應(與 gateway.port 相同連接埠,預設 18789)。
  • iOS 節點在連線時若偵測到 canvas host URL,會自動導向 A2UI。
  • 使用 canvas.navigate 搭配 {"url":""} 可返回內建佈局。

Canvas eval / snapshot

openclaw nodes invoke --node "iOS Node" --command canvas.eval --params '{"javaScript":"(() => { const {ctx} = window.__openclaw; ctx.clearRect(0,0,innerWidth,innerHeight); ctx.lineWidth=6; ctx.strokeStyle=\"#ff2d55\"; ctx.beginPath(); ctx.moveTo(40,40); ctx.lineTo(innerWidth-40, innerHeight-40); ctx.stroke(); return \"ok\"; })()"}'
openclaw nodes invoke --node "iOS Node" --command canvas.snapshot --params '{"maxWidth":900,"format":"jpeg"}'

語音喚醒 + 對話模式

  • 語音喚醒與對話模式可在設定中啟用。
  • iOS 可能會暫停背景音訊;應用程式不在前景時,語音功能請視為盡力而為。

常見錯誤

  • NODE_BACKGROUND_UNAVAILABLE:將 iOS 應用程式帶到前景(canvas/相機/螢幕指令需要在前景執行)。
  • A2UI_HOST_NOT_CONFIGURED:Gateway 未廣播 canvas host URL;請檢查 Gateway 設定 中的 canvasHost
  • 配對提示始終不出現:執行 openclaw devices list 並手動核准。
  • 重新安裝後無法重新連線:Keychain 中的配對 token 已清除,需重新配對節點。

相關文件