Files
moltbot/extensions/bluebubbles
Roy Martin 72abd42d4c fix(bluebubbles): respect explicit target.service and never short-circuit on weaker matches
Codex review on c905b3a flagged two real issues:

1. Explicit `service: 'sms'` (e.g. `sms:+15551234567`) was still being
   routed to iMessage whenever both chats existed, because the iMessage-
   first preference was hardcoded. Make the preferred service
   parameterized off `target.service`: SMS for explicit `sms` intent,
   iMessage otherwise (covers `imessage`, `auto`, and undefined).

2. Codex also flagged on the prior commit that breaking on
   `participantIMessageMatch` could skip a higher-priority direct
   `iMessage;-;<handle>` match on a later page. Direct > participant in
   our preference order, so the early break was unsound. Remove it
   entirely \u2014 only a direct preferred-service match can short-circuit
   pagination (and that branch already `return`s immediately).

Final return preference is now:
  participantPreferredMatch
    \u2192 directHandleOtherServiceMatch
    \u2192 participantOtherServiceMatch
    \u2192 directHandleUnknownServiceMatch
    \u2192 participantUnknownServiceMatch

Adds three regression tests:
- explicit `service: 'sms'` prefers SMS direct over iMessage direct
- explicit `service: 'sms'` falls back to iMessage when no SMS exists
- later-page direct iMessage beats earlier participant iMessage
2026-04-20 04:01:43 +00:00
..

BlueBubbles extension (developer reference)

This package contains the BlueBubbles external channel plugin for OpenClaw.

If youre looking for how to use BlueBubbles as an agent/tool user, see:

  • skills/bluebubbles/SKILL.md

Layout

  • Package entry: index.ts.
  • Channel implementation: src/channel.ts.
  • Webhook handling: src/monitor.ts (register per-account route via registerPluginHttpRoute).
  • REST helpers: src/send.ts + src/probe.ts.
  • Runtime bridge: src/runtime.ts (set via api.runtime).
  • Catalog entry for setup selection: src/channels/plugins/catalog.ts.

Internal helpers (use these, not raw API calls)

  • probeBlueBubbles in src/probe.ts for health checks.
  • sendMessageBlueBubbles in src/send.ts for text delivery.
  • resolveChatGuidForTarget in src/send.ts for chat lookup.
  • sendBlueBubblesReaction in src/reactions.ts for tapbacks.
  • sendBlueBubblesTyping + markBlueBubblesChatRead in src/chat.ts.
  • downloadBlueBubblesAttachment in src/attachments.ts for inbound media.
  • buildBlueBubblesApiUrl + blueBubblesFetchWithTimeout in src/types.ts for shared REST plumbing.

Webhooks

  • BlueBubbles posts JSON to the gateway HTTP server.
  • Normalize sender/chat IDs defensively (payloads vary by version).
  • Skip messages marked as from self.
  • Route into core reply pipeline via the plugin runtime (api.runtime) and openclaw/plugin-sdk helpers.
  • For attachments/stickers, use <media:...> placeholders when text is empty and attach media paths via MediaUrl(s) in the inbound context.

Config (core)

  • channels.bluebubbles.serverUrl (base URL), channels.bluebubbles.password, channels.bluebubbles.webhookPath.
  • Action gating: channels.bluebubbles.actions.reactions (default true).

Message tool notes

  • Reactions: the react action requires a target (phone number or chat identifier) in addition to messageId. Example: action=react target=+15551234567 messageId=ABC123 emoji=❤️