Ir al contenido

Aplicación iOS

Disponibilidad: vista previa interna. La aplicación iOS aún no se distribuye públicamente.

  • Se conecta a una puerta de enlace a través de WebSocket (LAN o tailnet).
  • Expone las capacidades del nodo: Canvas, captura de pantalla, captura de cámara, ubicación, modo Talk y activación por voz.
  • Recibe comandos de node.invoke e informa eventos de estado del nodo.
  • Puerta de enlace ejecutándose en otro dispositivo (macOS, Linux o Windows a través de WSL2).
  • Ruta de red:
    • Misma LAN a través de Bonjour, o
    • Tailnet a través de unicast DNS-SD (dominio de ejemplo: openclaw.internal.), o
    • Host/puerto manual (respaldo).
  1. Inicie la puerta de enlace:
Ventana de terminal
openclaw gateway --port 18789
  1. En la aplicación iOS, abra Configuración y elija una puerta de enlace descubierta (o habilite Host manual e ingrese host/puerto).

  2. Aprobar la solicitud de emparejamiento en el host de la puerta de enlace:

Ventana de terminal
openclaw devices list
openclaw devices approve <requestId>

Si la aplicación vuelve a intentar el emparejamiento con detalles de autenticación modificados (rol/alcances/clave pública), la solicitud pendiente anterior se reemplaza y se crea un nuevo requestId. Ejecute openclaw devices list nuevamente antes de la aprobación.

Opcional: si el nodo iOS siempre se conecta desde una subred controlada estrictamente, puede optar por la aprobación automática de nodo por primera vez con CIDR explícitos o IPs exactas:

{
gateway: {
nodes: {
pairing: {
autoApproveCidrs: ["192.168.1.0/24"],
},
},
},
}

Esto está deshabilitado de forma predeterminada. Solo se aplica al emparejamiento role: node nuevo sin alcances solicitados. El emparejamiento de operador/navegador y cualquier cambio de rol, alcance, metadatos o clave pública aún requieren aprobación manual.

  1. Verificar la conexión:
Ventana de terminal
openclaw nodes status
openclaw gateway call node.list --params "{}"

Push respaldado por relay para compilaciones oficiales

Sección titulada «Push respaldado por relay para compilaciones oficiales»

Las compilaciones oficiales distribuidas de iOS utilizan el relay de push externo en lugar de publicar el token APNs sin procesar en la puerta de enlace.

Requisito del lado de la puerta de enlace:

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

Cómo funciona el flujo:

  • La aplicación de iOS se registra en el repetidor (relay) utilizando App Attest y una transacción de app JWS de StoreKit.
  • El relay devuelve un identificador de relay opaco además de una concesión de envío con ámbito de registro.
  • La aplicación iOS obtiene la identidad de la puerta de enlace emparejada y la incluye en el registro del relay, por lo que el registro respaldado por relay se delega a esa puerta de enlace específica.
  • La aplicación reenvía ese registro respaldado por relay a la puerta de enlace emparejada con push.apns.register.
  • La puerta de enlace utiliza ese identificador de relé almacenado para push.test, activaciones en segundo plano e impulsos de activación.
  • La URL base del relé de la puerta de enlace debe coincidir con la URL del relé integrada en la compilación oficial de iOS para TestFlight.
  • Si la aplicación se conecta posteriormente a una puerta de enlace diferente o a una compilación con una URL base de relé diferente, actualiza el registro de relé en lugar de reutilizar el enlace antiguo.

Lo que la puerta de enlace no necesita para esta ruta:

  • Ningún token de relé para toda la implementación.
  • Ninguna clave APNs directa para envíos respaldados por relé en las versiones oficiales/TestFlight.

Flujo de operación esperado:

  1. Instale la compilación oficial de iOS para TestFlight.
  2. Establezca gateway.push.apns.relay.baseUrl en la puerta de enlace.
  3. Empareje la aplicación con la puerta de enlace y permítale terminar de conectarse.
  4. La aplicación publica push.apns.register automáticamente después de tener un token APNs, la sesión del operador está conectada y el registro del relé tiene éxito.
  5. Después de eso, push.test, las activaciones de reconexión y los impulsos de activación pueden utilizar el registro respaldado por relé almacenado.

Cuando iOS despierta la aplicación para una inserción silenciosa, actualización en segundo plano o un evento de ubicación significativa, la aplicación intenta una breve reconexión del nodo y luego llama a node.event con event: "node.presence.alive". La puerta de enlace registra esto como lastSeenAtMs/lastSeenReason en los metadatos del nodo/dispositivo emparejado solo después de que se conoce la identidad del dispositivo del nodo autenticado.

La aplicación considera que un despertar en segundo plano se ha registrado correctamente solo cuando la respuesta de la puerta de enlace incluye handled: true. Las puertas de enlace antiguas pueden reconocer node.event con { "ok": true }; esa respuesta es compatible pero no cuenta como una actualización duradera de la última vez visto.

Nota de compatibilidad:

  • OPENCLAW_APNS_RELAY_BASE_URL aún funciona como una anulación de entorno temporal para la puerta de enlace.

El repetidor existe para hacer cumplir dos restricciones que el APNs directo en la puerta de enlace no puede proporcionar para las compilaciones oficiales de iOS:

  • Solo las compilaciones genuinas de OpenClaw para iOS distribuidas a través de Apple pueden usar el repetidor alojado.
  • Una puerta de enlace solo puede enviar inserciones respaldadas por repetidor para dispositivos iOS que se hayan emparejado con esa puerta de enlace específica.

Salto a salto:

  1. iOS app -> gateway

    • La aplicación primero se empareja con la puerta de enlace a través del flujo de autenticación normal de la puerta de enlace.
    • Esto proporciona a la aplicación una sesión de nodo autenticada más una sesión de operador autenticada.
    • La sesión de operador se utiliza para llamar a gateway.identity.get.
  2. iOS app -> relay

    • La aplicación llama a los puntos finales de registro del repetidor a través de HTTPS.
    • El registro incluye la prueba de App Attest más una transacción de app JWS de StoreKit.
    • El repetidor valida el ID del paquete, la prueba de App Attest y la prueba de distribución de Apple, y requiere la ruta de distribución oficial/de producción.
    • Esto es lo que impide que las compilaciones locales de Xcode/desarrollo usen el repetidor alojado. Una compilación local puede estar firmada, pero no satisface la prueba de distribución oficial de Apple que el repetidor espera.
  3. gateway identity delegation

    • Antes del registro en el repetidor, la aplicación obtiene la identidad de la puerta de enlace emparejada desde gateway.identity.get.
    • La aplicación incluye esa identidad de la puerta de enlace en la carga útil de registro del repetidor.
    • El relay devuelve un identificador de relay y una concesión de envío con ámbito de registro que se delegan a esa identidad de gateway.
  4. gateway -> relay

    • El gateway almacena el identificador de relay y la concesión de envío de push.apns.register.
    • En push.test, reactivaciones de reconexión y empujes de activación, el gateway firma la solicitud de envío con su propia identidad de dispositivo.
    • El relay verifica tanto la concesión de envío almacenada como la firma del gateway frente a la identidad de gateway delegada del registro.
    • Otro gateway no puede reutilizar ese registro almacenado, incluso si de alguna manera obtiene el identificador.
  5. relay -> APNs

    • El relay posee las credenciales de producción de APNs y el token APNs sin procesar para la compilación oficial.
    • El gateway nunca almacena el token APNs sin procesar para las compilaciones oficiales respaldadas por relay.
    • El relay envía el envío final a APNs en nombre del gateway emparejado.

Por qué se creó este diseño:

  • Para mantener las credenciales de producción de APNs fuera de los gateways de los usuarios.
  • Para evitar almacenar tokens APNs sin procesar de compilaciones oficiales en el gateway.
  • Para permitir el uso del relay alojado solo para compilaciones oficiales/TestFlight de OpenClaw.
  • Para evitar que un gateway envíe envíos de activación a dispositivos iOS propiedad de un gateway diferente.

Las compilaciones locales/manuales permanecen en APNs directas. Si está probando esas compilaciones sin el relay, el gateway aún necesita credenciales APNs directas:

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

Estas son variables de entorno de tiempo de ejecución del host del gateway, no configuraciones de Fastlane. apps/ios/fastlane/.env solo almacena la autenticación de App Store Connect / TestFlight, como ASC_KEY_ID y ASC_ISSUER_ID; no configura la entrega directa de APNs para compilaciones locales de iOS.

Almacenamiento recomendado del host del gateway:

Ventana de terminal
mkdir -p ~/.openclaw/credentials/apns
chmod 700 ~/.openclaw/credentials/apns
mv /path/to/AuthKey_KEYID.p8 ~/.openclaw/credentials/apns/AuthKey_KEYID.p8
chmod 600 ~/.openclaw/credentials/apns/AuthKey_KEYID.p8
export OPENCLAW_APNS_PRIVATE_KEY_PATH="$HOME/.openclaw/credentials/apns/AuthKey_KEYID.p8"

No confirme el archivo .p8 ni lo coloque bajo la extracción del repositorio.

La aplicación iOS explora _openclaw-gw._tcp en local. y, cuando está configurado, el mismo dominio de descubrimiento DNS-SD de área amplia. Los gateways de la misma LAN aparecen automáticamente desde local.; el descubrimiento entre redes puede usar el dominio de área amplia configurado sin cambiar el tipo de baliza.

Si mDNS está bloqueado, use una zona DNS-SD unidifusión (elija un dominio; ejemplo: openclaw.internal.) y Tailscale split DNS. Vea Bonjour para el ejemplo de CoreDNS.

En Configuración, active Host manual e introduzca el host y puerto de la puerta de enlace (predeterminado 18789).

El nodo iOS renderiza un lienzo WKWebView. Use node.invoke para controlarlo:

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

Notas:

  • El host de lienzo de la puerta de enlace sirve /__openclaw__/canvas/ y /__openclaw__/a2ui/.
  • Se sirve desde el servidor HTTP de la puerta de enlace (mismo puerto que gateway.port, predeterminado 18789).
  • El nodo iOS navega automáticamente a A2UI al conectarse cuando se anuncia una URL de host de lienzo.
  • Vuelva al andamio integrado con canvas.navigate y {"url":""}.

La aplicación iOS es una superficie de nodo móvil, no un backend de Codex Computer Use. Codex Computer Use y cua-driver mcp controlan un escritorio macOS local a través de herramientas MCP; la aplicación iOS expone las capacidades del iPhone a través de comandos de nodo OpenClaw tales como canvas.*, camera.*, screen.*, location.* y talk.*.

Los agentes aún pueden operar la aplicación iOS a través de OpenClaw invocando comandos de nodo, pero esas llamadas pasan por el protocolo de nodo de puerta de enlace y siguen los límites de primer plano/fondo de iOS. Use Codex Computer Use para el control del escritorio local y esta página para las capacidades del nodo iOS.

Ventana de terminal
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\"; })()"}'
Ventana de terminal
openclaw nodes invoke --node "iOS Node" --command canvas.snapshot --params '{"maxWidth":900,"format":"jpeg"}'
  • La activación por voz y el modo de conversación están disponibles en Configuración.
  • Los nodos iOS con capacidad de conversación anuncian la capacidad talk y pueden declarar talk.ptt.start, talk.ptt.stop, talk.ptt.cancel y talk.ptt.once; la puerta de enlace permite esos comandos de pulsar para hablar de forma predeterminada para los nodos de confianza con capacidad de conversación.
  • iOS puede suspender el audio en segundo plano; trate las funciones de voz como mejor esfuerzo cuando la aplicación no está activa.
  • NODE_BACKGROUND_UNAVAILABLE: abre la aplicación de iOS en primer plano (los comandos de canvas/cámara/pantalla lo requieren).
  • A2UI_HOST_NOT_CONFIGURED: el Gateway no anunció la URL de superficie del complemento Canvas; comprueba plugins.entries.canvas.config.host en configuración del Gateway.
  • El aviso de emparejamiento nunca aparece: ejecuta openclaw devices list y apruébalo manualmente.
  • La reconexión falla después de reinstalar: el token de emparejamiento del llavero se borró; vuelve a emparejar el nodo.