Ir al contenido

Viniendo de BlueBubbles

El complemento imessage incluido ahora alcanza la misma superficie de API privada que BlueBubbles (react, edit, unsend, reply, sendWithEffect, gestión de grupos, archivos adjuntos) al controlar steipete/imsg a través de JSON-RPC. Si ya ejecutas una Mac con imsg instalado, puedes dejar de usar el servidor de BlueBubbles y dejar que el complemento hable directamente con Messages.app.

Se eliminó el soporte de BlueBubbles. OpenClaw admite iMessage solo a través de imsg. Esta guía es para migrar configuraciones antiguas de channels.bluebubbles a channels.imessage; no hay otra ruta de migración admitida.

Use esta lista de verificación cuando ya conozca su configuración anterior de BlueBubbles y desee la ruta más segura y corta:

  1. Verifique imsg directamente en la Mac que ejecuta Messages.app (imsg chats, imsg history, imsg send y imsg rpc --help).
  2. Copie las claves de comportamiento de channels.bluebubbles a channels.imessage: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, includeAttachments, attachmentRoots, mediaMaxMb, textChunkLimit, coalesceSameSenderDms y actions.
  3. Elimine las claves de transporte que ya no existen: serverUrl, password, URL de webhook y la configuración del servidor BlueBubbles.
  4. Si la puerta de enlace (Gateway) no se está ejecutando en la Mac de Messages, configure channels.imessage.cliPath en un contenedor SSH y configure remoteHost para la recuperación remota de archivos adjuntos.
  5. Con la puerta de enlace detenida, habilite channels.imessage y luego ejecute openclaw channels status --probe --channel imessage.
  6. Pruebe un mensaje directo (DM), un grupo permitido, archivos adjuntos si están habilitados y cada acción de API privada que espere que use el agente.
  7. Elimine el servidor de BlueBubbles y la configuración antigua de channels.bluebubbles después de verificar la ruta de iMessage.
  • Ya estás ejecutando imsg en el mismo Mac (o uno accesible por SSH) donde Messages.app tiene la sesión iniciada.
  • Quieres tener una pieza móvil menos — ningún servidor BlueBubbles separado, ningún endpoint REST que autenticar, ninguna tubería de webhooks. Un único binario CLI en lugar de un servidor + aplicación cliente + asistente.
  • Estás en una compilación de macOS / imsg compatible donde el sondeo de la API privada informa available: true.

imsg es una CLI local de macOS para Messages. OpenClaw inicia imsg rpc como un proceso hijo y se comunica a través de JSON-RPC usando stdin/stdout. No hay servidor HTTP, URL de webhook, demonio en segundo plano, agente de lanzamiento (launch agent) o puerto que exponer.

  • Las lecturas provienen de ~/Library/Messages/chat.db usando un manejador SQLite de solo lectura.
  • Los mensajes entrantes en vivo provienen de imsg watch / watch.subscribe, que sigue los eventos del sistema de archivos chat.db con un respaldo de sondeo (polling).
  • Los envíos utilizan la automatización de Messages.app para envíos de texto normal y archivos.
  • Las acciones avanzadas usan imsg launch para inyectar el asistente imsg en Messages.app. Eso es lo que desbloquea las confirmaciones de lectura, indicadores de escritura, envíos enriquecidos, editar, no enviar, respuestas en hilos, reacciones y gestión de grupos.
  • Las compilaciones de Linux pueden inspeccionar una chat.db copiada, pero no pueden enviar, vigilar la base de datos del Mac en vivo o controlar Messages.app. Para OpenClaw iMessage, ejecuta imsg en el Mac con la sesión iniciada o a través de un envoltorio (wrapper) SSH a ese Mac.
  1. Instala imsg en el Mac que ejecuta Messages.app:

    Ventana de terminal
    brew install steipete/tap/imsg
    imsg --version
    imsg chats --limit 3

    Si imsg chats falla con unable to open database file, salida vacía o authorization denied, concede Acceso total al disco (Full Disk Access) a la terminal, editor, proceso Node, servicio Gateway o proceso padre SSH que inicia imsg, y luego vuelve a abrir ese proceso padre.

  2. Verifica las superficies de lectura, vigilancia, envío y RPC antes de cambiar la configuración de OpenClaw:

    Ventana de terminal
    imsg chats --limit 10 --json | jq -s
    imsg history --chat-id 42 --limit 10 --attachments --json | jq -s
    imsg watch --chat-id 42 --reactions --json
    imsg send --chat-id 42 --text "OpenClaw imsg test"
    imsg rpc --help

    Reemplaza 42 con un ID de chat real de imsg chats. El envío requiere permiso de Automatización para Messages.app. Si OpenClaw se ejecutará a través de SSH, ejecute estos comandos a través del mismo contenedor SSH o contexto de usuario que OpenClaw usará. Si las lecturas/sondeos funcionan pero los envíos fallan con AppleEvents -1743, verifique si Automatización se instaló en /usr/libexec/sshd-keygen-wrapper; consulte Los envíos del contenedor SSH fallan con AppleEvents -1743.

  3. Habilite el puente de API privada cuando necesite acciones avanzadas:

    Ventana de terminal
    imsg launch
    imsg status --json

    imsg launch requiere que SIP esté deshabilitado. El envío básico, el historial y la vigilancia funcionan sin imsg launch; las acciones avanzadas no.

  4. Después de agregar una configuración channels.imessage habilitada, verifique el puente a través de OpenClaw:

    Ventana de terminal
    openclaw channels status --probe

    Deseas imessage.privateApi.available: true. Si informa false, solucione eso primero; consulte Detección de capacidades. channels status --probe solo sondea cuentas configuradas y habilitadas.

  5. Haga una instantánea de su configuración:

    Ventana de terminal
    cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak

iMessage y BlueBubbles comparten mucha configuración a nivel de canal. Las claves que cambian son principalmente de transporte (servidor REST vs CLI local). Las claves de comportamiento (dmPolicy, groupPolicy, allowFrom, etc.) mantienen el mismo significado.

BlueBubblesiMessage incluidoNotas
channels.bluebubbles.enabledchannels.imessage.enabledMisma semántica.
channels.bluebubbles.serverUrl(eliminado)Sin servidor REST: el complemento inicia imsg rpc a través de stdio.
channels.bluebubbles.password(eliminado)No se requiere autenticación de webhook.
(implícito)channels.imessage.cliPathRuta a imsg (por defecto imsg); use un script contenedor para SSH.
(implícito)channels.imessage.dbPathInvalidación opcional de Messages.app chat.db; detectada automáticamente si se omite.
(implícito)channels.imessage.remoteHosthost o user@host — solo se necesita cuando cliPath es un contenedor SSH y desea descargas de archivos adjuntos SCP.
channels.bluebubbles.dmPolicychannels.imessage.dmPolicyMismos valores (pairing / allowlist / open / disabled).
channels.bluebubbles.allowFromchannels.imessage.allowFromLos aprobaciones de emparejamiento se transfieren por identificador, no por token.
channels.bluebubbles.groupPolicychannels.imessage.groupPolicyMismos valores (allowlist / open / disabled).
channels.bluebubbles.groupAllowFromchannels.imessage.groupAllowFromIgual.
channels.bluebubbles.groupschannels.imessage.groupsCopie esto textualmente, incluyendo cualquier entrada comodín groups: { "*": { ... } }. Los valores requireMention, tools y toolsBySender por grupo se transfieren. Con groupPolicy: "allowlist", un bloque groups vacío o ausente descarta silenciosamente cada mensaje de grupo; consulte a continuación “Trampa de registro de grupos”.
channels.bluebubbles.sendReadReceiptschannels.imessage.sendReadReceiptsPor defecto true. Con el complemento incluido, esto solo se activa cuando el sondeo de la API privada está activo.
channels.bluebubbles.includeAttachmentschannels.imessage.includeAttachmentsMisma forma, mismo desactivado por defecto. Si tenía archivos adjuntos fluyendo en BlueBubbles, debe restablecer esto explícitamente en el bloque iMessage; no se transfiere implícitamente, y las fotos/multimedios entrantes se descartarán silenciosamente sin ninguna línea de registro Inbound message hasta que lo haga.
channels.bluebubbles.attachmentRootschannels.imessage.attachmentRootsRaíces locales; mismas reglas de comodín.
(N/A)channels.imessage.remoteAttachmentRootsSolo se usa cuando remoteHost está configurado para obtenciones por SCP.
channels.bluebubbles.mediaMaxMbchannels.imessage.mediaMaxMbPredeterminado 16 MB en iMessage (el predeterminado de BlueBubbles era 8 MB). Establécelo explícitamente si deseas mantener el límite más bajo.
channels.bluebubbles.textChunkLimitchannels.imessage.textChunkLimitPredeterminado 4000 en ambos.
channels.bluebubbles.coalesceSameSenderDmschannels.imessage.coalesceSameSenderDmsMisma participación opcional. Solo MD — los chats de grupo mantienen el envío instantáneo por mensaje en ambos canales. Amplía el antirrebote de entrada predeterminado a 2500 ms cuando se habilita sin un messages.inbound.byChannel.imessage explícito. Consulte Documentación de iMessage § Coalescing split-send DMs.
channels.bluebubbles.enrichGroupParticipantsFromContacts(N/A)iMessage ya lee los nombres para mostrar del remitente de chat.db.
channels.bluebubbles.actions.*channels.imessage.actions.*Interruptores por acción: reactions, edit, unsend, reply, sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, sendAttachment.

Las configuraciones multicuenta (channels.bluebubbles.accounts.*) se traducen uno a uno a channels.imessage.accounts.*.

El complemento iMessage integrado ejecuta dos puertas de lista de permitidos de grupos separadas una tras otra. Ambas deben pasar para que un mensaje de grupo llegue al agente:

  1. Lista blanca de remitente/destino de chat (channels.imessage.groupAllowFrom) — verificada por isAllowedIMessageSender. Coincide con los mensajes entrantes por el identificador del remitente, chat_guid, chat_identifier o chat_id. Misma forma que BlueBubbles.
  2. Registro de grupos (channels.imessage.groups) — verificado por resolveChannelGroupPolicy de inbound-processing.ts:199. Con groupPolicy: "allowlist", este filtro requiere:
    • una entrada comodín groups: { "*": { ... } } (establece allowAll = true), o
    • una entrada explícita por chat_id bajo groups.

Si se pasa la puerta 1 pero falla la puerta 2, el mensaje se descarta. El complemento emite dos señales de nivel warn para que esto ya no sea silencioso en el nivel de registro predeterminado:

  • Una warn de inicio único por cuenta cuando groupPolicy: "allowlist" está establecido pero channels.imessage.groups está vacío (sin comodín "*", sin entradas por chat_id) — se activa antes de que aterrice cualquier mensaje.
  • Una warn única por chat_id la primera vez que se descarta un grupo específico en tiempo de ejecución, nombrando el chat_id y la clave exacta para agregar a groups para permitirlo.

Los MDs siguen funcionando porque toman una ruta de código diferente.

Este es el modo de fallo de migración más común de BlueBubbles a iMessage integrado: los operadores copian groupAllowFrom y groupPolicy pero omiten el bloque groups, porque el groups: { "*": { "requireMention": true } } de BlueBubbles parece una configuración de mención no relacionada. En realidad, es fundamental para la puerta del registro.

La configuración mínima para mantener fluyendo los mensajes grupales después de groupPolicy: "allowlist":

{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."],
groups: {
"*": { requireMention: true },
},
},
},
}

requireMention: true bajo * es inofensivo cuando no se han configurado patrones de mención: el tiempo de ejecución establece canDetectMention = false y cortocircuita la caída de la mención en inbound-processing.ts:512. Con patrones de mención configurados (agents.list[].groupChat.mentionPatterns), funciona como se espera.

Si la puerta de enlace registra imessage: dropping group message from chat_id=<id> o la línea de inicio imessage: groupPolicy="allowlist" but channels.imessage.groups is empty, la puerta 2 está descartando — agregue el bloque groups.

  1. Añada un bloque iMessage junto al bloque BlueBubbles existente. Manténgalo deshabilitado mientras el Gateway siga enrutando el tráfico de BlueBubbles:

    {
    channels: {
    bluebubbles: {
    enabled: true,
    // ... existing config ...
    },
    imessage: {
    enabled: false,
    cliPath: "/opt/homebrew/bin/imsg",
    dmPolicy: "pairing",
    allowFrom: ["+15555550123"], // copy from bluebubbles.allowFrom
    groupPolicy: "allowlist",
    groupAllowFrom: [], // copy from bluebubbles.groupAllowFrom
    groups: { "*": { requireMention: true } }, // copy from bluebubbles.groups — silently drops groups if missing, see "Group registry footgun" above
    actions: {
    reactions: true,
    edit: true,
    unsend: true,
    reply: true,
    sendWithEffect: true,
    sendAttachment: true,
    },
    },
    },
    }
  2. Probar antes de que importe el tráfico — detenga el Gateway, habilite temporalmente el bloque iMessage y confirme que iMessage reporta estado saludable desde la CLI:

    Ventana de terminal
    openclaw gateway stop
    # edit config: channels.imessage.enabled = true
    openclaw channels status --probe --channel imessage # expect imessage.privateApi.available: true

    channels status --probe solo sondea cuentas configuradas y habilitadas. No reinicie la puerta de enlace con BlueBubbles e iMessage habilitados a menos que intencionalmente desee que ambos monitores de canal se estén ejecutando. Si no va a realizar el cambio de inmediato, vuelva a establecer channels.imessage.enabled en false antes de reiniciar la puerta de enlace. Use los comandos directos de imsg en Antes de comenzar para validar la Mac antes de habilitar el tráfico de OpenClaw.

  3. Realiza la transición. Una vez que la cuenta de iMessage habilitada informe que está sana, elimina la configuración de BlueBubbles y mantén iMessage habilitado:

    {
    channels: {
    imessage: { enabled: true /* ... */ },
    },
    }

    Reinicia el gateway. El tráfico entrante de iMessage ahora fluye a través del complemento incluido.

  4. Verifica los MD. Envía un mensaje directo al agente; confirma que la respuesta llegue.

  5. Verifica los grupos por separado. Los MD y los grupos toman diferentes rutas de código — el éxito de los MD no prueba que los grupos se estén enrutando. Envía un mensaje al agente en un chat de grupo vinculado y confirma que la respuesta llegue. Si el grupo se queda en silencio (sin respuesta del agente, sin error), verifica el registro de la puerta de enlace en busca de imessage: dropping group message from chat_id=<id> o la línea de imessage: groupPolicy="allowlist" but channels.imessage.groups is empty al inicio — ambos se disparan en el nivel de registro predeterminado. Si aparece alguno, tu bloque groups falta o está vacío — consulta “Peligro del registro de grupos” más arriba.

  6. Verifica la superficie de acciones — desde un MD vinculado, pide al agente que reaccione, edite, desaplique, responda, envíe una foto y (en un grupo) cambie el nombre del grupo / añada o elimine un participante. Cada acción debería aparecer de forma nativa en Messages.app. Si alguna lanza “iMessage <action> requiere el puente de la API privada de imsg”, ejecuta imsg launch de nuevo y actualiza channels status --probe.

  7. Elimina el servidor y la configuración de BlueBubbles una vez verificados los MD, grupos y acciones de iMessage. OpenClaw no usará channels.bluebubbles.

AcciónBlueBubbles heredadoiMessage incluido
Enviar texto / respaldo SMS
Enviar multimedia (foto, video, archivo, voz)
Respuesta en hilo (reply_to_guid)✅ (cierra #51892)
Tapback (react)
Editar / anular envío (destinatarios macOS 13+)
Enviar con efecto de pantalla✅ (cierra parte de #9394)
Texto enriquecido negrita / cursiva / subrayado / tachado✅ (formato typed-run vía attributedBody)
Cambiar nombre de grupo / establecer icono de grupo
Añadir / eliminar participante, salir del grupo
Confirmaciones de lectura e indicador de escritura✅ (condicionado a la sonda de API privada)
Agrupación de MD del mismo remitente✅ (solo MD; activación opcional mediante channels.imessage.coalesceSameSenderDms)
Puesta al día de mensajes entrantes recibidos mientras la puerta de enlace está caída✅ (repetición de webhook + obtención de historial)✅ (activación opcional mediante channels.imessage.catchup.enabled; cierra #78649)

La puesta al día de iMessage ya está disponible como función opcional en el complemento incluido. Al iniciar la puerta de enlace, si channels.imessage.catchup.enabled es true, la puerta de enlace ejecuta una pasada chats.list + messages.history por chat contra el mismo cliente JSON-RPC que usa imsg watch, reproduce cada fila entrante perdida a través de la ruta de envío en vivo (listas de permitidos, política de grupos, antirrebote, caché de eco) y persiste un cursor por cuenta para que los inicios posteriores continúen donde se quedaron. Consulta Ponerse al día después del tiempo de inactividad de la puerta de enlace para ajustes.

  • Las aprobaciones de emparejamiento se transfieren por identificador. No necesitas volver a aprobar a los remitentes conocidos: channels.imessage.allowFrom reconoce las mismas cadenas +15555550123 / [email protected] que usaba BlueBubbles.
  • Las sesiones permanecen limitadas por agente + chat. Los MDs se colapsan en la sesión principal del agente bajo el session.dmScope=main predeterminado; las sesiones de grupo permanecen aisladas por chat_id. Las claves de sesión difieren (agent:<id>:imessage:group:<chat_id> frente al equivalente de BlueBubbles); el historial de conversación antiguo bajo las claves de sesión de BlueBubbles no se traslada a las sesiones de iMessage.
  • Los enlaces ACP que hacen referencia a match.channel: "bluebubbles" deben actualizarse a "imessage". Las formas match.peer.id (chat_id:, chat_guid:, chat_identifier:, identificador simple) son idénticas.

No hay un tiempo de ejecución de BlueBubbles compatible al que volver a cambiar. Si falla la verificación de iMessage, establece channels.imessage.enabled: false, reinicia el Gateway, soluciona el bloqueador de imsg y vuelve a intentar la transición.

La caché de respuestas reside en el estado del complemento SQLite. openclaw doctor --fix importa y archiva el sidecar antiguo de imessage/reply-cache.jsonl cuando está presente.