chore(sync): mirror docs from openclaw/openclaw@7f4c0b3192
This commit is contained in:
parent
11ea266d46
commit
32c3912307
@ -1,5 +1,5 @@
|
||||
{
|
||||
"repository": "openclaw/openclaw",
|
||||
"sha": "484a289be34e6d744d158c72cef95bba5061dd94",
|
||||
"syncedAt": "2026-05-07T19:20:00.786Z"
|
||||
"sha": "7f4c0b319262c0c3c1935b43786312a5483bf8b1",
|
||||
"syncedAt": "2026-05-07T19:56:37.151Z"
|
||||
}
|
||||
|
||||
@ -76,7 +76,6 @@
|
||||
{
|
||||
"group": "消息平台",
|
||||
"pages": [
|
||||
"zh-CN/channels/bluebubbles",
|
||||
"zh-CN/channels/discord",
|
||||
"zh-CN/channels/feishu",
|
||||
"zh-CN/channels/grammy",
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- إعداد قناة BlueBubbles
|
||||
- استكشاف أخطاء اقتران Webhook وإصلاحها
|
||||
- إعداد iMessage على macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: دعم iMessage القديم عبر خادم BlueBubbles على macOS (إرسال/استقبال عبر REST، الكتابة، التفاعلات، الإقران، الإجراءات المتقدمة).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:57Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
الحالة: Plugin قديم مضمّن يتواصل مع خادم BlueBubbles على macOS عبر HTTP. تستمر إعدادات BlueBubbles الحالية في العمل، لكن عمليات نشر OpenClaw iMessage الجديدة يجب أن تفضّل Plugin [iMessage](/ar/channels/imessage) الأصلي عندما تناسب متطلباته مضيفك.
|
||||
|
||||
<Warning>
|
||||
تم إهمال BlueBubbles لإعدادات OpenClaw الجديدة.
|
||||
|
||||
لا يزال نظام BlueBubbles العلوي نشطًا، لكن OpenClaw يعتمد على واجهة API لخادم BlueBubbles على macOS. اعتبارًا من 6 مايو 2026، كان آخر تغيير على فرع التطوير الرسمي لـ [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) في [22 يناير 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037)، ونُشر أحدث إصدار للخادم ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) في 16 مايو 2025. توجد نشاطات أحدث في تطبيق العميل ومستودعات المساعدة، لذلك فهذا ليس ادعاءً بالتخلي؛ يتعلق الإهمال بتقليل اعتماد OpenClaw على خادم HTTP خارجي، وwebhooks، وسطح توافق واجهات API الخاصة عندما يحافظ مسار `imsg` الأصلي على التكامل ضمن عقد stdio محلي.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
تتضمن إصدارات OpenClaw الحالية BlueBubbles، لذلك لا تحتاج الحزم المبنية العادية إلى خطوة `openclaw plugins install` منفصلة.
|
||||
</Note>
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
- يعمل على macOS عبر تطبيق BlueBubbles المساعد ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- بديل قديم للمنشآت التي تعتمد بالفعل على معرّفات قناة BlueBubbles، أو حالة Webhook، أو أهداف المجموعات، أو تسليم cron، أو توجيه مساحة العمل.
|
||||
- موصى به/مختبر: macOS Sequoia (15). يعمل macOS Tahoe (26)؛ التحرير معطّل حاليًا على Tahoe، وقد تُبلغ تحديثات أيقونة المجموعة عن النجاح لكنها لا تتزامن.
|
||||
- يتواصل OpenClaw معه عبر REST API الخاصة به (`GET /api/v1/ping`، `POST /message/text`، `POST /chat/:id/*`).
|
||||
- تصل الرسائل الواردة عبر webhooks؛ أما الردود الصادرة، ومؤشرات الكتابة، وإيصالات القراءة، وtapbacks فهي استدعاءات REST.
|
||||
- تُستوعب المرفقات والملصقات كوسائط واردة (وتُعرض للوكيل عند الإمكان).
|
||||
- تُسلَّم ردود Auto-TTS التي تُنشئ صوت MP3 أو CAF كفقاعات مذكرة صوتية في iMessage بدلًا من مرفقات ملفات عادية.
|
||||
- تعمل الاقتران/قائمة السماح بالطريقة نفسها مثل القنوات الأخرى (`/channels/pairing` وما إلى ذلك) مع `channels.bluebubbles.allowFrom` + رموز الاقتران.
|
||||
- تُعرض التفاعلات كأحداث نظام تمامًا مثل Slack/Telegram حتى يتمكن الوكلاء من "ذكرها" قبل الرد.
|
||||
- الميزات المتقدمة: التحرير، إلغاء الإرسال، ترابط الردود، تأثيرات الرسائل، إدارة المجموعات.
|
||||
|
||||
## البدء السريع
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
ثبّت خادم BlueBubbles على جهاز Mac الخاص بك (اتبع التعليمات في [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
في إعدادات BlueBubbles، فعّل web API واضبط كلمة مرور.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
شغّل `openclaw onboard` وحدد BlueBubbles، أو اضبطه يدويًا:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
وجّه webhooks الخاصة بـ BlueBubbles إلى Gateway لديك (مثال: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
ابدأ Gateway؛ سيسجّل معالج Webhook ويبدأ الاقتران.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**الأمان**
|
||||
|
||||
- اضبط دائمًا كلمة مرور Webhook.
|
||||
- مصادقة Webhook مطلوبة دائمًا. يرفض OpenClaw طلبات Webhook من BlueBubbles ما لم تتضمن كلمة مرور/guid تطابق `channels.bluebubbles.password` (مثلًا `?password=<password>` أو `x-password`)، بغض النظر عن طوبولوجيا local loopback/الوكيل.
|
||||
- تُفحص مصادقة كلمة المرور قبل قراءة/تحليل أجسام Webhook الكاملة.
|
||||
|
||||
</Warning>
|
||||
|
||||
## إبقاء Messages.app نشطًا (إعدادات VM / بلا واجهة)
|
||||
|
||||
قد تنتهي بعض إعدادات macOS VM / الدائمة التشغيل إلى دخول Messages.app في حالة "خمول" (تتوقف الأحداث الواردة حتى يُفتح التطبيق/يُجلب إلى المقدمة). الحل البسيط هو **تنبيه Messages كل 5 دقائق** باستخدام AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
احفظ هذا باسم `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
احفظ هذا باسم `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
يعمل هذا **كل 300 ثانية** و**عند تسجيل الدخول**. قد يؤدي التشغيل الأول إلى ظهور مطالبات **Automation** في macOS (`osascript` → Messages). وافق عليها في جلسة المستخدم نفسها التي تشغّل LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## الإعداد الأولي
|
||||
|
||||
يتوفر BlueBubbles في الإعداد الأولي التفاعلي:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
يطالبك المعالج بما يلي:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
عنوان خادم BlueBubbles (مثل `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
كلمة مرور API من إعدادات خادم BlueBubbles.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
مسار نقطة نهاية Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`، أو `allowlist`، أو `open`، أو `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
أرقام الهواتف، أو عناوين البريد الإلكتروني، أو أهداف الدردشة.
|
||||
</ParamField>
|
||||
|
||||
يمكنك أيضًا إضافة BlueBubbles عبر CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## التحكم في الوصول (الرسائل المباشرة + المجموعات)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- الافتراضي: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- يتلقى المرسلون غير المعروفين رمز اقتران؛ ويتم تجاهل الرسائل حتى الموافقة (تنتهي صلاحية الرموز بعد ساعة واحدة).
|
||||
- الموافقة عبر:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- الاقتران هو تبادل الرمز الافتراضي. التفاصيل: [الاقتران](/ar/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (الافتراضي: `allowlist`).
|
||||
- يتحكم `channels.bluebubbles.groupAllowFrom` في من يمكنه التحفيز داخل المجموعات عند ضبط `allowlist`.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### إثراء أسماء جهات الاتصال (macOS، اختياري)
|
||||
|
||||
غالبًا ما تتضمن webhooks الخاصة بمجموعات BlueBubbles عناوين المشاركين الخام فقط. إذا كنت تريد أن يعرض سياق `GroupMembers` أسماء جهات الاتصال المحلية بدلًا من ذلك، فيمكنك الاشتراك في إثراء جهات الاتصال المحلية على macOS:
|
||||
|
||||
- يفعّل `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` البحث. الافتراضي: `false`.
|
||||
- لا تعمل عمليات البحث إلا بعد أن تسمح صلاحية الوصول إلى المجموعة، وتفويض الأوامر، وبوابة الذكر بمرور الرسالة.
|
||||
- يُثري المشاركون ذوو أرقام الهاتف غير المسماة فقط.
|
||||
- تبقى أرقام الهاتف الخام كبديل احتياطي عند عدم العثور على تطابق محلي.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### بوابة الذكر (المجموعات)
|
||||
|
||||
يدعم BlueBubbles بوابة الذكر لدردشات المجموعات، بما يطابق سلوك iMessage/WhatsApp:
|
||||
|
||||
- يستخدم `agents.list[].groupChat.mentionPatterns` (أو `messages.groupChat.mentionPatterns`) لاكتشاف الإشارات.
|
||||
- عند تفعيل `requireMention` لمجموعة، لا يرد الوكيل إلا عند ذكره.
|
||||
- تتجاوز أوامر التحكم من المرسلين المصرح لهم بوابة الذكر.
|
||||
|
||||
إعداد كل مجموعة:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### بوابة الأوامر
|
||||
|
||||
- تتطلب أوامر التحكم (مثل `/config` و`/model`) تفويضًا.
|
||||
- يستخدم `allowFrom` و`groupAllowFrom` لتحديد تفويض الأوامر.
|
||||
- يمكن للمرسلين المصرح لهم تشغيل أوامر التحكم حتى من دون ذكر في المجموعات.
|
||||
|
||||
### موجّه النظام لكل مجموعة
|
||||
|
||||
يقبل كل إدخال ضمن `channels.bluebubbles.groups.*` سلسلة `systemPrompt` اختيارية. تُحقن القيمة في موجّه نظام الوكيل في كل دورة تتعامل مع رسالة في تلك المجموعة، بحيث يمكنك ضبط شخصية أو قواعد سلوكية لكل مجموعة من دون تعديل موجّهات الوكيل:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
يطابق المفتاح ما يبلّغ عنه BlueBubbles كـ `chatGuid` / `chatIdentifier` / `chatId` رقمي للمجموعة، ويوفر إدخال حرف البدل `"*"` إعدادًا افتراضيًا لكل مجموعة من دون تطابق دقيق (النمط نفسه المستخدم بواسطة `requireMention` وسياسات الأدوات لكل مجموعة). تنتصر المطابقات الدقيقة دائمًا على حرف البدل. تتجاهل الرسائل المباشرة هذا الحقل؛ استخدم تخصيص الموجّه على مستوى الوكيل أو الحساب بدلًا من ذلك.
|
||||
|
||||
#### مثال عملي: الردود المترابطة وتفاعلات tapback (API خاصة)
|
||||
|
||||
مع تفعيل API الخاصة في BlueBubbles، تصل الرسائل الواردة مع معرّفات رسائل قصيرة (مثل `[[reply_to:5]]`) ويمكن للوكيل استدعاء `action=reply` للترابط مع رسالة محددة أو `action=react` لإسقاط tapback. تُعد `systemPrompt` لكل مجموعة طريقة موثوقة لإبقاء الوكيل يختار الأداة الصحيحة:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
تتطلب كل من تفاعلات tapback والردود المترابطة API الخاصة في BlueBubbles؛ راجع [الإجراءات المتقدمة](#advanced-actions) و[معرّفات الرسائل](#message-ids-short-vs-full) للآليات الأساسية.
|
||||
|
||||
## ارتباطات محادثات ACP
|
||||
|
||||
يمكن تحويل دردشات BlueBubbles إلى مساحات عمل ACP مستمرة من دون تغيير طبقة النقل.
|
||||
|
||||
تدفق المشغّل السريع:
|
||||
|
||||
- شغّل `/acp spawn codex --bind here` داخل الرسالة المباشرة أو دردشة المجموعة المسموح بها.
|
||||
- تُوجّه الرسائل المستقبلية في محادثة BlueBubbles نفسها إلى جلسة ACP المنشأة.
|
||||
- يعيد `/new` و`/reset` ضبط جلسة ACP المرتبطة نفسها في مكانها.
|
||||
- يغلق `/acp close` جلسة ACP ويزيل الارتباط.
|
||||
|
||||
تُدعم أيضًا الارتباطات المستمرة المضبوطة عبر إدخالات `bindings[]` في المستوى الأعلى مع `type: "acp"` و`match.channel: "bluebubbles"`.
|
||||
|
||||
يمكن لـ `match.peer.id` استخدام أي صيغة هدف BlueBubbles مدعومة:
|
||||
|
||||
- معرّف DM مُطبّع مثل `+15555550123` أو `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
لربط المجموعات بشكل مستقر، فضّل `chat_id:*` أو `chat_identifier:*`.
|
||||
|
||||
مثال:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
راجع [وكلاء ACP](/ar/tools/acp-agents) لمعرفة سلوك ربط ACP المشترك.
|
||||
|
||||
## مؤشرات الكتابة + إيصالات القراءة
|
||||
|
||||
- **مؤشرات الكتابة**: تُرسل تلقائيًا قبل إنشاء الرد وأثناءه.
|
||||
- **إيصالات القراءة**: يتحكم بها `channels.bluebubbles.sendReadReceipts` (الافتراضي: `true`).
|
||||
- **مؤشرات الكتابة**: يرسل OpenClaw أحداث بدء الكتابة؛ ويمسح BlueBubbles حالة الكتابة تلقائيًا عند الإرسال أو انتهاء المهلة (الإيقاف اليدوي عبر DELETE غير موثوق).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## إجراءات متقدمة
|
||||
|
||||
يدعم BlueBubbles إجراءات رسائل متقدمة عند تفعيلها في الإعدادات:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**: إضافة/إزالة تفاعلات tapback (`messageId`، `emoji`، `remove`). مجموعة tapback الأصلية في iMessage هي `love` و`like` و`dislike` و`laugh` و`emphasize` و`question`. عندما يختار الوكيل رمزًا تعبيريًا خارج تلك المجموعة (مثل `👀`)، تعود أداة التفاعل إلى `love` بحيث يظل tapback يظهر بدلًا من فشل الطلب بالكامل. تظل تفاعلات الإقرار المكوّنة تتحقق بصرامة وتُرجع خطأ عند القيم غير المعروفة.
|
||||
- **edit**: تحرير رسالة مُرسلة (`messageId`، `text`).
|
||||
- **unsend**: إلغاء إرسال رسالة (`messageId`).
|
||||
- **reply**: الرد على رسالة محددة (`messageId`، `text`، `to`).
|
||||
- **sendWithEffect**: الإرسال مع تأثير iMessage (`text`، `to`، `effectId`).
|
||||
- **renameGroup**: إعادة تسمية دردشة جماعية (`chatGuid`، `displayName`).
|
||||
- **setGroupIcon**: تعيين أيقونة/صورة دردشة جماعية (`chatGuid`، `media`) - غير مستقر على macOS 26 Tahoe (قد تُرجع API نجاحًا لكن الأيقونة لا تتزامن).
|
||||
- **addParticipant**: إضافة شخص إلى مجموعة (`chatGuid`، `address`).
|
||||
- **removeParticipant**: إزالة شخص من مجموعة (`chatGuid`، `address`).
|
||||
- **leaveGroup**: مغادرة دردشة جماعية (`chatGuid`).
|
||||
- **upload-file**: إرسال وسائط/ملفات (`to`، `buffer`، `filename`، `asVoice`).
|
||||
- المذكرات الصوتية: عيّن `asVoice: true` مع صوت **MP3** أو **CAF** للإرسال كرسالة صوتية في iMessage. يحوّل BlueBubbles MP3 → CAF عند إرسال المذكرات الصوتية.
|
||||
- الاسم المستعار القديم: لا يزال `sendAttachment` يعمل، لكن `upload-file` هو اسم الإجراء القياسي.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### معرّفات الرسائل (قصيرة مقابل كاملة)
|
||||
|
||||
قد يعرض OpenClaw معرّفات رسائل _قصيرة_ (مثل `1` و`2`) لتوفير الرموز.
|
||||
|
||||
- يمكن أن تكون `MessageSid` / `ReplyToId` معرّفات قصيرة.
|
||||
- تحتوي `MessageSidFull` / `ReplyToIdFull` على المعرّفات الكاملة للمزوّد.
|
||||
- المعرّفات القصيرة موجودة في الذاكرة؛ وقد تنتهي صلاحيتها عند إعادة التشغيل أو إخلاء ذاكرة التخزين المؤقت.
|
||||
- تقبل الإجراءات `messageId` قصيرًا أو كاملًا، لكن المعرّفات القصيرة ستُرجع خطأ إذا لم تعد متاحة.
|
||||
|
||||
استخدم المعرّفات الكاملة للأتمتة والتخزين الدائمين:
|
||||
|
||||
- القوالب: `{{MessageSidFull}}`، `{{ReplyToIdFull}}`
|
||||
- السياق: `MessageSidFull` / `ReplyToIdFull` في الحمولات الواردة
|
||||
|
||||
راجع [الإعدادات](/ar/gateway/configuration) لمتغيرات القوالب.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## دمج رسائل DM ذات الإرسال المقسّم (أمر + URL في إنشاء واحد)
|
||||
|
||||
عندما يكتب مستخدم أمرًا وURL معًا في iMessage - مثل `Dump https://example.com/article` - تقسم Apple الإرسال إلى **تسليمين منفصلين عبر Webhook**:
|
||||
|
||||
1. رسالة نصية (`"Dump"`).
|
||||
2. فقاعة معاينة URL (`"https://..."`) مع صور معاينة OG كمرفقات.
|
||||
|
||||
يصل Webhookان إلى OpenClaw بفاصل يقارب 0.8-2.0 ثانية في معظم الإعدادات. بدون الدمج، يتلقى الوكيل الأمر وحده في الدور 1، ويرد (غالبًا "أرسل لي URL")، ولا يرى URL إلا في الدور 2 - وعندها يكون سياق الأمر قد فُقد بالفعل.
|
||||
|
||||
يُدخل `channels.bluebubbles.coalesceSameSenderDms` رسالة DM في دمج Webhooks المتتالية من المرسل نفسه في دور وكيل واحد. تستمر الدردشات الجماعية في استخدام مفتاح لكل رسالة للحفاظ على بنية الأدوار متعددة المستخدمين.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
فعّل عندما:
|
||||
|
||||
- ترسل Skills تتوقع `command + payload` في رسالة واحدة (dump، paste، save، queue، إلخ).
|
||||
- يلصق مستخدموك عناوين URL أو صورًا أو محتوى طويلًا بجانب الأوامر.
|
||||
- يمكنك قبول زمن انتقال دور DM الإضافي (انظر أدناه).
|
||||
|
||||
اتركه معطلًا عندما:
|
||||
|
||||
- تحتاج إلى أقل زمن انتقال للأوامر لمحفزات DM ذات الكلمة الواحدة.
|
||||
- تكون كل تدفقاتك أوامر لمرة واحدة بدون متابعات حمولة.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
عند تشغيل العلامة وعدم وجود `messages.inbound.byChannel.bluebubbles` صريح، تتسع نافذة إزالة الاهتزاز إلى **2500 ms** (الافتراضي لعدم الدمج هو 500 ms). النافذة الأوسع مطلوبة - إيقاع الإرسال المقسّم من Apple البالغ 0.8-2.0 ثانية لا يناسب الافتراضي الأضيق.
|
||||
|
||||
لضبط النافذة بنفسك:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **زمن انتقال إضافي لأوامر التحكم في DM.** عند تشغيل العلامة، تنتظر رسائل أوامر التحكم في DM (مثل `Dump` و`Save` وما إلى ذلك) الآن حتى نافذة إزالة الاهتزاز قبل الإرسال، لاحتمال وصول Webhook حمولة. تحافظ أوامر الدردشة الجماعية على الإرسال الفوري.
|
||||
- **المخرجات المدمجة محدودة** - يُحدد النص المدمج عند 4000 حرف مع علامة `…[truncated]` صريحة؛ وتُحدد المرفقات عند 20؛ وتُحدد إدخالات المصدر عند 10 (مع الاحتفاظ بالأول والأحدث بعد ذلك). لا يزال كل `messageId` مصدر يصل إلى إزالة التكرار الوارد، لذا يُتعرّف على إعادة تشغيل لاحقة من MessagePoller لأي حدث فردي كتكرار.
|
||||
- **اختياري، لكل قناة.** القنوات الأخرى (Telegram وWhatsApp وSlack و…) غير متأثرة.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### السيناريوهات وما يراه الوكيل
|
||||
|
||||
| ما ينشئه المستخدم | ما تسلّمه Apple | العلامة معطلة (افتراضي) | العلامة مفعلة + نافذة 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (إرسال واحد) | 2 Webhooks بفاصل ~1 s | دوران للوكيل: "Dump" وحده، ثم URL | دور واحد: نص مدمج `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (مرفق + نص) | 2 Webhooks | دوران | دور واحد: نص + صورة |
|
||||
| `/status` (أمر مستقل) | 1 Webhook | إرسال فوري | **انتظار حتى النافذة، ثم إرسال** |
|
||||
| URL ملصق وحده | 1 Webhook | إرسال فوري | إرسال فوري (إدخال واحد فقط في الحاوية) |
|
||||
| نص + URL مُرسلان كرسالتين منفصلتين متعمدتين، بينهما دقائق | 2 Webhooks خارج النافذة | دوران | دوران (تنتهي النافذة بينهما) |
|
||||
| تدفق سريع (>10 رسائل DM صغيرة داخل النافذة) | N Webhooks | N أدوار | دور واحد، مخرجات محدودة (الأول + الأحدث، مع تطبيق حدود النص/المرفقات) |
|
||||
|
||||
### استكشاف أخطاء دمج الإرسال المقسّم وإصلاحها
|
||||
|
||||
إذا كانت العلامة مفعلة وما زالت الإرسالات المقسّمة تصل كدورين، فتحقق من كل طبقة:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
ثم `openclaw gateway restart` - تُقرأ العلامة عند إنشاء سجل مزيل الاهتزاز.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
انظر إلى سجل خادم BlueBubbles ضمن `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
قِس الفجوة بين إرسال النص بأسلوب `"Dump"` وإرسال `"https://..."; Attachments:` الذي يليه. ارفع `messages.inbound.byChannel.bluebubbles` ليغطي تلك الفجوة بشكل مريح.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
تعكس طوابع أحداث الجلسة الزمنية (`~/.openclaw/agents/<id>/sessions/*.jsonl`) وقت تسليم Gateway للرسالة إلى الوكيل، **وليس** وقت وصول Webhook. تعني الرسالة الثانية الموضوعة في قائمة الانتظار والموسومة `[Queued messages while agent was busy]` أن الدور الأول كان لا يزال قيد التشغيل عندما وصل Webhook الثاني - وكانت حاوية الدمج قد أُفرغت بالفعل. اضبط النافذة وفق سجل خادم BB، وليس سجل الجلسة.
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
على الأجهزة الأصغر (8 GB)، قد تستغرق أدوار الوكيل وقتًا طويلًا بما يكفي لتُفرغ حاوية الدمج قبل اكتمال الرد، ويصل URL كدور ثانٍ في قائمة الانتظار. تحقق من `memory_pressure` و`ps -o rss -p $(pgrep openclaw-gateway)`؛ إذا كان Gateway يتجاوز ~500 MB RSS وكان الضاغط نشطًا، فأغلق العمليات الثقيلة الأخرى أو انتقل إلى مضيف أكبر.
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
إذا نقر المستخدم على `Dump` كـ **رد** على فقاعة URL موجودة (يعرض iMessage شارة "1 Reply" على فقاعة Dump)، فإن URL موجود في `replyToBody`، وليس في Webhook ثانٍ. لا ينطبق الدمج - فهذا شأن Skill/المطالبة، وليس شأن مزيل الاهتزاز.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## بث الكتل
|
||||
|
||||
تحكم فيما إذا كانت الردود تُرسل كرسالة واحدة أو تُبث في كتل:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## الوسائط + الحدود
|
||||
|
||||
- تُنزّل المرفقات الواردة وتُخزن في ذاكرة التخزين المؤقت للوسائط.
|
||||
- حد الوسائط عبر `channels.bluebubbles.mediaMaxMb` للوسائط الواردة والصادرة (الافتراضي: 8 MB).
|
||||
- يُقسّم النص الصادر إلى `channels.bluebubbles.textChunkLimit` (الافتراضي: 4000 حرف).
|
||||
|
||||
## مرجع الإعدادات
|
||||
|
||||
الإعدادات الكاملة: [الإعدادات](/ar/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="الاتصال وWebhook">
|
||||
- `channels.bluebubbles.enabled`: تفعيل/تعطيل القناة.
|
||||
- `channels.bluebubbles.serverUrl`: عنوان URL الأساسي لواجهة BlueBubbles REST API.
|
||||
- `channels.bluebubbles.password`: كلمة مرور API.
|
||||
- `channels.bluebubbles.webhookPath`: مسار نقطة نهاية Webhook (الافتراضي: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="سياسة الوصول">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (الافتراضي: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: قائمة سماح للرسائل المباشرة (المعرّفات، رسائل البريد الإلكتروني، أرقام E.164، و`chat_id:*`، و`chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (الافتراضي: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: قائمة سماح لمرسلي المجموعات.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: على macOS، يمكنك اختيارياً إثراء المشاركين غير المسمّين في المجموعة من جهات الاتصال المحلية بعد اجتياز التحقق. الافتراضي: `false`.
|
||||
- `channels.bluebubbles.groups`: إعداد لكل مجموعة (`requireMention`، إلخ).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="التسليم والتقسيم">
|
||||
- `channels.bluebubbles.sendReadReceipts`: إرسال إيصالات القراءة (الافتراضي: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: تفعيل بث الكتل (الافتراضي: `false`؛ مطلوب للردود المتدفقة).
|
||||
- `channels.bluebubbles.textChunkLimit`: حجم المقطع الصادر بعدد الأحرف (الافتراضي: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: مهلة كل طلب بالمللي ثانية لإرسال النصوص الصادرة عبر `/api/v1/message/text` (الافتراضي: 30000). ارفعها على إعدادات macOS 26 التي قد تتوقف فيها عمليات إرسال iMessage عبر Private API لمدة تتجاوز 60 ثانية داخل إطار عمل iMessage؛ على سبيل المثال `45000` أو `60000`. تبقي المجسّات، وعمليات البحث عن الدردشات، والتفاعلات، والتعديلات، وفحوصات الصحة حالياً على الافتراضي الأقصر البالغ 10 ثوانٍ؛ ومن المخطط توسيع التغطية لتشمل التفاعلات والتعديلات كمتابعة لاحقة. تجاوز لكل حساب: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (الافتراضي) يقسّم فقط عند تجاوز `textChunkLimit`؛ أما `newline` فيقسّم عند الأسطر الفارغة (حدود الفقرات) قبل التقسيم حسب الطول.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="الوسائط والسجل">
|
||||
- `channels.bluebubbles.mediaMaxMb`: حد الوسائط الواردة/الصادرة بالميغابايت (الافتراضي: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: قائمة سماح صريحة للأدلة المحلية المطلقة المسموح بها لمسارات الوسائط المحلية الصادرة. يتم رفض إرسال المسارات المحلية افتراضياً ما لم يتم تكوين هذا. تجاوز لكل حساب: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: دمج Webhook الرسائل المباشرة المتتالية من المرسل نفسه في دورة وكيل واحدة حتى يصل إرسال Apple المقسّم للنص+URL كرسالة واحدة (الافتراضي: `false`). راجع [دمج الرسائل المباشرة المقسّمة](#coalescing-split-send-dms-command--url-in-one-composition) للاطلاع على السيناريوهات وضبط النافذة والمفاضلات. يوسّع نافذة إزالة الارتداد الافتراضية للوارد من 500 مللي ثانية إلى 2500 مللي ثانية عند تفعيله بدون `messages.inbound.byChannel.bluebubbles` صريح.
|
||||
- `channels.bluebubbles.historyLimit`: الحد الأقصى لرسائل المجموعة للسياق (0 يعطّلها).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: حد سجل الرسائل المباشرة.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: عندما يصل رد وارد بدون `replyToBody`/`replyToSender` وتفشل ذاكرة التخزين المؤقت لسياق الرد داخل الذاكرة، اجلب الرسالة الأصلية من BlueBubbles HTTP API كخيار احتياطي بأفضل جهد (الافتراضي: `false`). مفيد لعمليات النشر متعددة النسخ التي تشترك في حساب BlueBubbles واحد، أو بعد إعادة تشغيل العملية، أو بعد إخلاء ذاكرة التخزين المؤقت طويلة العمر TTL/LRU. يخضع الجلب لحماية SSRF بالسياسة نفسها المطبقة على كل طلب عميل BlueBubbles آخر، ولا يرمي أخطاء أبداً، ويملأ ذاكرة التخزين المؤقت حتى تُستهلك الردود اللاحقة بكلفة موزعة. تجاوز لكل حساب: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. ينتشر إعداد مستوى القناة إلى الحسابات التي تحذف العلامة.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="الإجراءات والحسابات">
|
||||
- `channels.bluebubbles.actions`: تفعيل/تعطيل إجراءات محددة.
|
||||
- `channels.bluebubbles.accounts`: تكوين متعدد الحسابات.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
الخيارات العامة ذات الصلة:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (أو `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## العنونة / أهداف التسليم
|
||||
|
||||
فضّل `chat_guid` للتوجيه المستقر:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (مفضل للمجموعات)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- المعرّفات المباشرة: `+15555550123`، `user@example.com`
|
||||
- إذا لم يكن لدى المعرّف المباشر دردشة رسائل مباشرة موجودة، فسينشئ OpenClaw واحدة عبر `POST /api/v1/chat/new`. يتطلب هذا تفعيل BlueBubbles Private API.
|
||||
|
||||
### توجيه iMessage مقابل SMS
|
||||
|
||||
عندما يكون للمعرّف نفسه دردشة iMessage ودردشة SMS على Mac (على سبيل المثال رقم هاتف مسجّل في iMessage لكنه تلقى أيضاً بدائل الفقاعة الخضراء)، يفضّل OpenClaw دردشة iMessage ولا يخفّض أبداً إلى SMS بصمت. لفرض دردشة SMS، استخدم بادئة هدف صريحة `sms:` (على سبيل المثال `sms:+15555550123`). تستمر المعرّفات التي لا تملك دردشة iMessage مطابقة في الإرسال عبر أي دردشة يبلّغ عنها BlueBubbles.
|
||||
|
||||
## الأمان
|
||||
|
||||
- تتم مصادقة طلبات Webhook بمقارنة معاملات الاستعلام أو الرؤوس `guid`/`password` مع `channels.bluebubbles.password`.
|
||||
- أبقِ كلمة مرور API ونقطة نهاية Webhook سرّيتين (تعامل معهما كبيانات اعتماد).
|
||||
- لا يوجد تجاوز للمضيف المحلي لمصادقة BlueBubbles Webhook. إذا كنت تمرّر حركة Webhook عبر وكيل، فأبقِ كلمة مرور BlueBubbles على الطلب من طرف إلى طرف. لا يحل `gateway.trustedProxies` محل `channels.bluebubbles.password` هنا. راجع [أمان Gateway](/ar/gateway/security#reverse-proxy-configuration).
|
||||
- فعّل HTTPS + قواعد جدار الحماية على خادم BlueBubbles إذا كنت تعرضه خارج شبكتك المحلية.
|
||||
|
||||
## استكشاف الأخطاء وإصلاحها
|
||||
|
||||
- إذا توقفت أحداث الكتابة/القراءة عن العمل، فتحقق من سجلات BlueBubbles Webhook وتأكد من أن مسار Gateway يطابق `channels.bluebubbles.webhookPath`.
|
||||
- تنتهي صلاحية رموز الاقتران بعد ساعة واحدة؛ استخدم `openclaw pairing list bluebubbles` و`openclaw pairing approve bluebubbles <code>`.
|
||||
- تتطلب التفاعلات BlueBubbles private API (`POST /api/v1/message/react`)؛ تأكد من أن إصدار الخادم يوفّرها.
|
||||
- يتطلب التعديل/إلغاء الإرسال macOS 13+ وإصدار خادم BlueBubbles متوافقاً. على macOS 26 (Tahoe)، التعديل معطل حالياً بسبب تغييرات private API.
|
||||
- قد تكون تحديثات أيقونة المجموعة غير مستقرة على macOS 26 (Tahoe): قد تعيد API نجاحاً لكن الأيقونة الجديدة لا تتم مزامنتها.
|
||||
- يخفي OpenClaw تلقائياً الإجراءات المعروفة بأنها معطلة بناءً على إصدار macOS في خادم BlueBubbles. إذا ظل التعديل ظاهراً على macOS 26 (Tahoe)، فعطّله يدوياً باستخدام `channels.bluebubbles.actions.edit=false`.
|
||||
- تم تفعيل `coalesceSameSenderDms` لكن الإرسالات المقسّمة (مثل `Dump` + URL) ما زالت تصل كدورتين: راجع قائمة تحقق [استكشاف أخطاء دمج الإرسال المقسّم وإصلاحها](#split-send-coalescing-troubleshooting) - الأسباب الشائعة هي نافذة إزالة ارتداد ضيقة جداً، أو إساءة قراءة الطوابع الزمنية لسجل الجلسة كوقت وصول Webhook، أو إرسال اقتباس رد (الذي يستخدم `replyToBody`، وليس Webhook ثانياً).
|
||||
- لمعلومات الحالة/الصحة: `openclaw status --all` أو `openclaw status --deep`.
|
||||
|
||||
للاطلاع على مرجع عام لسير عمل القنوات، راجع [القنوات](/ar/channels) ودليل [Plugins](/ar/tools/plugin).
|
||||
|
||||
## ذات صلة
|
||||
|
||||
- [توجيه القنوات](/ar/channels/channel-routing) - توجيه الجلسات للرسائل
|
||||
- [نظرة عامة على القنوات](/ar/channels) - جميع القنوات المدعومة
|
||||
- [المجموعات](/ar/channels/groups) - سلوك دردشة المجموعة والتحقق من الإشارات
|
||||
- [الاقتران](/ar/channels/pairing) - مصادقة الرسائل المباشرة وتدفق الاقتران
|
||||
- [الأمان](/ar/gateway/security) - نموذج الوصول والتقوية
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- أنت تقوم بتثبيت Plugin bluebubbles أو تهيئته أو تدقيقه
|
||||
summary: يضيف واجهة قناة BlueBubbles لإرسال رسائل OpenClaw وتلقيها.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T07:35:39Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
يضيف واجهة قناة BlueBubbles لإرسال رسائل OpenClaw واستلامها.
|
||||
|
||||
## التوزيع
|
||||
|
||||
- الحزمة: `@openclaw/bluebubbles`
|
||||
- مسار التثبيت: npm؛ ClawHub
|
||||
|
||||
## الواجهة
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## المستندات ذات الصلة
|
||||
|
||||
- [bluebubbles](/ar/channels/bluebubbles)
|
||||
@ -90,7 +90,7 @@ openclaw cron add \
|
||||
--tz America/New_York \
|
||||
--timeout-seconds 300 \
|
||||
--announce \
|
||||
--channel bluebubbles \
|
||||
--channel imessage \
|
||||
--to "+1XXXXXXXXXX" \
|
||||
--message "Execute daily inbox triage per standing orders. Check mail for new alerts. Parse, categorize, and persist each item. Report summary to owner. Escalate unknowns."
|
||||
```
|
||||
|
||||
@ -1,638 +0,0 @@
|
||||
---
|
||||
summary: "Legacy iMessage support via the BlueBubbles macOS server (REST send/receive, typing, reactions, pairing, advanced actions)."
|
||||
read_when:
|
||||
- Setting up BlueBubbles channel
|
||||
- Troubleshooting webhook pairing
|
||||
- Configuring iMessage on macOS
|
||||
title: "BlueBubbles"
|
||||
sidebarTitle: "BlueBubbles"
|
||||
---
|
||||
|
||||
Status: bundled legacy plugin that talks to the BlueBubbles macOS server over HTTP. Existing BlueBubbles setups continue to work, but new OpenClaw iMessage deployments should prefer the native [iMessage](/channels/imessage) plugin when its requirements fit your host.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles is deprecated for new OpenClaw setups.
|
||||
|
||||
The upstream BlueBubbles ecosystem is still active, but OpenClaw depends on the BlueBubbles macOS server API. As of May 6, 2026, the official [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) development branch last changed on [January 22, 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), and the latest server release ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) was published on May 16, 2025. The client app and helper repositories have newer activity, so this is not an abandonment claim; the deprecation is about reducing OpenClaw's dependency on an external HTTP server, webhooks, and private-API compatibility surface when the native `imsg` path keeps the integration on a local stdio contract.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Current OpenClaw releases bundle BlueBubbles, so normal packaged builds do not need a separate `openclaw plugins install` step.
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
- Runs on macOS via the BlueBubbles helper app ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Legacy fallback for installations that already rely on BlueBubbles channel IDs, webhook state, group targets, cron delivery, or workspace routing.
|
||||
- Recommended/tested: macOS Sequoia (15). macOS Tahoe (26) works; edit is currently broken on Tahoe, and group icon updates may report success but not sync.
|
||||
- OpenClaw talks to it through its REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Incoming messages arrive via webhooks; outgoing replies, typing indicators, read receipts, and tapbacks are REST calls.
|
||||
- Attachments and stickers are ingested as inbound media (and surfaced to the agent when possible).
|
||||
- Auto-TTS replies that synthesize MP3 or CAF audio are delivered as iMessage voice memo bubbles instead of plain file attachments.
|
||||
- Pairing/allowlist works the same way as other channels (`/channels/pairing` etc) with `channels.bluebubbles.allowFrom` + pairing codes.
|
||||
- Reactions are surfaced as system events just like Slack/Telegram so agents can "mention" them before replying.
|
||||
- Advanced features: edit, unsend, reply threading, message effects, group management.
|
||||
|
||||
## Quick start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
Install the BlueBubbles server on your Mac (follow the instructions at [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
In the BlueBubbles config, enable the web API and set a password.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
Run `openclaw onboard` and select BlueBubbles, or configure manually:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
Point BlueBubbles webhooks to your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Start the gateway; it will register the webhook handler and start pairing.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Security**
|
||||
|
||||
- Always set a webhook password.
|
||||
- Webhook authentication is always required. OpenClaw rejects BlueBubbles webhook requests unless they include a password/guid that matches `channels.bluebubbles.password` (for example `?password=<password>` or `x-password`), regardless of loopback/proxy topology.
|
||||
- Password authentication is checked before reading/parsing full webhook bodies.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Keeping Messages.app alive (VM / headless setups)
|
||||
|
||||
Some macOS VM / always-on setups can end up with Messages.app going "idle" (incoming events stop until the app is opened/foregrounded). A simple workaround is to **poke Messages every 5 minutes** using an AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Save this as `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Save this as `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
This runs **every 300 seconds** and **on login**. The first run may trigger macOS **Automation** prompts (`osascript` → Messages). Approve them in the same user session that runs the LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles is available in interactive onboarding:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
The wizard prompts for:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles server address (e.g., `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
API password from BlueBubbles Server settings.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook endpoint path.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open`, or `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Phone numbers, emails, or chat targets.
|
||||
</ParamField>
|
||||
|
||||
You can also add BlueBubbles via CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Access control (DMs + groups)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Default: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour).
|
||||
- Approve via:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Pairing is the default token exchange. Details: [Pairing](/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (default: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` controls who can trigger in groups when `allowlist` is set.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Contact name enrichment (macOS, optional)
|
||||
|
||||
BlueBubbles group webhooks often only include raw participant addresses. If you want `GroupMembers` context to show local contact names instead, you can opt in to local Contacts enrichment on macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` enables the lookup. Default: `false`.
|
||||
- Lookups run only after group access, command authorization, and mention gating have allowed the message through.
|
||||
- Only unnamed phone participants are enriched.
|
||||
- Raw phone numbers remain as the fallback when no local match is found.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Mention gating (groups)
|
||||
|
||||
BlueBubbles supports mention gating for group chats, matching iMessage/WhatsApp behavior:
|
||||
|
||||
- Uses `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) to detect mentions.
|
||||
- When `requireMention` is enabled for a group, the agent only responds when mentioned.
|
||||
- Control commands from authorized senders bypass mention gating.
|
||||
|
||||
Per-group configuration:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Command gating
|
||||
|
||||
- Control commands (e.g., `/config`, `/model`) require authorization.
|
||||
- Uses `allowFrom` and `groupAllowFrom` to determine command authorization.
|
||||
- Authorized senders can run control commands even without mentioning in groups.
|
||||
|
||||
### Per-group system prompt
|
||||
|
||||
Each entry under `channels.bluebubbles.groups.*` accepts an optional `systemPrompt` string. The value is injected into the agent's system prompt on every turn that handles a message in that group, so you can set per-group persona or behavioral rules without editing agent prompts:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The key matches whatever BlueBubbles reports as `chatGuid` / `chatIdentifier` / numeric `chatId` for the group, and a `"*"` wildcard entry provides a default for every group without an exact match (same pattern used by `requireMention` and per-group tool policies). Exact matches always win over the wildcard. DMs ignore this field; use agent-level or account-level prompt customization instead.
|
||||
|
||||
#### Worked example: threaded replies and tapback reactions (Private API)
|
||||
|
||||
With the BlueBubbles Private API enabled, inbound messages arrive with short message IDs (for example `[[reply_to:5]]`) and the agent can call `action=reply` to thread into a specific message or `action=react` to drop a tapback. A per-group `systemPrompt` is a reliable way to keep the agent choosing the right tool:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback reactions and threaded replies both require the BlueBubbles Private API; see [Advanced actions](#advanced-actions) and [Message IDs](#message-ids-short-vs-full) for the underlying mechanics.
|
||||
|
||||
## ACP conversation bindings
|
||||
|
||||
BlueBubbles chats can be turned into durable ACP workspaces without changing the transport layer.
|
||||
|
||||
Fast operator flow:
|
||||
|
||||
- Run `/acp spawn codex --bind here` inside the DM or allowed group chat.
|
||||
- Future messages in that same BlueBubbles conversation route to the spawned ACP session.
|
||||
- `/new` and `/reset` reset the same bound ACP session in place.
|
||||
- `/acp close` closes the ACP session and removes the binding.
|
||||
|
||||
Configured persistent bindings are also supported through top-level `bindings[]` entries with `type: "acp"` and `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` can use any supported BlueBubbles target form:
|
||||
|
||||
- normalized DM handle such as `+15555550123` or `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
For stable group bindings, prefer `chat_id:*` or `chat_identifier:*`.
|
||||
|
||||
Example:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
See [ACP Agents](/tools/acp-agents) for shared ACP binding behavior.
|
||||
|
||||
## Typing + read receipts
|
||||
|
||||
- **Typing indicators**: Sent automatically before and during response generation.
|
||||
- **Read receipts**: Controlled by `channels.bluebubbles.sendReadReceipts` (default: `true`).
|
||||
- **Typing indicators**: OpenClaw sends typing start events; BlueBubbles clears typing automatically on send or timeout (manual stop via DELETE is unreliable).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced actions
|
||||
|
||||
BlueBubbles supports advanced message actions when enabled in config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**: Add/remove tapback reactions (`messageId`, `emoji`, `remove`). iMessage's native tapback set is `love`, `like`, `dislike`, `laugh`, `emphasize`, and `question`. When an agent picks an emoji outside that set (for example `👀`), the reaction tool falls back to `love` so the tapback still renders instead of failing the whole request. Configured ack reactions still validate strictly and error on unknown values.
|
||||
- **edit**: Edit a sent message (`messageId`, `text`).
|
||||
- **unsend**: Unsend a message (`messageId`).
|
||||
- **reply**: Reply to a specific message (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Send with iMessage effect (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Rename a group chat (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Set a group chat's icon/photo (`chatGuid`, `media`) - flaky on macOS 26 Tahoe (API may return success but the icon does not sync).
|
||||
- **addParticipant**: Add someone to a group (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Remove someone from a group (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Leave a group chat (`chatGuid`).
|
||||
- **upload-file**: Send media/files (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Voice memos: set `asVoice: true` with **MP3** or **CAF** audio to send as an iMessage voice message. BlueBubbles converts MP3 → CAF when sending voice memos.
|
||||
- Legacy alias: `sendAttachment` still works, but `upload-file` is the canonical action name.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Message IDs (short vs full)
|
||||
|
||||
OpenClaw may surface _short_ message IDs (e.g., `1`, `2`) to save tokens.
|
||||
|
||||
- `MessageSid` / `ReplyToId` can be short IDs.
|
||||
- `MessageSidFull` / `ReplyToIdFull` contain the provider full IDs.
|
||||
- Short IDs are in-memory; they can expire on restart or cache eviction.
|
||||
- Actions accept short or full `messageId`, but short IDs will error if no longer available.
|
||||
|
||||
Use full IDs for durable automations and storage:
|
||||
|
||||
- Templates: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Context: `MessageSidFull` / `ReplyToIdFull` in inbound payloads
|
||||
|
||||
See [Configuration](/gateway/configuration) for template variables.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Coalescing split-send DMs (command + URL in one composition)
|
||||
|
||||
When a user types a command and a URL together in iMessage - e.g. `Dump https://example.com/article` - Apple splits the send into **two separate webhook deliveries**:
|
||||
|
||||
1. A text message (`"Dump"`).
|
||||
2. A URL-preview balloon (`"https://..."`) with OG-preview images as attachments.
|
||||
|
||||
The two webhooks arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coalescing, the agent receives the command alone on turn 1, replies (often "send me the URL"), and only sees the URL on turn 2 - at which point the command context is already lost.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` opts a DM into merging consecutive same-sender webhooks into a single agent turn. Group chats continue to key per-message so multi-user turn structure is preserved.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
Enable when:
|
||||
|
||||
- You ship skills that expect `command + payload` in one message (dump, paste, save, queue, etc.).
|
||||
- Your users paste URLs, images, or long content alongside commands.
|
||||
- You can accept the added DM turn latency (see below).
|
||||
|
||||
Leave disabled when:
|
||||
|
||||
- You need minimum command latency for single-word DM triggers.
|
||||
- All your flows are one-shot commands without payload follow-ups.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
With the flag on and no explicit `messages.inbound.byChannel.bluebubbles`, the debounce window widens to **2500 ms** (the default for non-coalescing is 500 ms). The wider window is required - Apple's split-send cadence of 0.8-2.0 s does not fit in the tighter default.
|
||||
|
||||
To tune the window yourself:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **Added latency for DM control commands.** With the flag on, DM control-command messages (like `Dump`, `Save`, etc.) now wait up to the debounce window before dispatching, in case a payload webhook is coming. Group-chat commands keep instant dispatch.
|
||||
- **Merged output is bounded** - merged text caps at 4000 chars with an explicit `…[truncated]` marker; attachments cap at 20; source entries cap at 10 (first-plus-latest retained beyond that). Every source `messageId` still reaches inbound-dedupe so a later MessagePoller replay of any individual event is recognized as a duplicate.
|
||||
- **Opt-in, per-channel.** Other channels (Telegram, WhatsApp, Slack, …) are unaffected.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Scenarios and what the agent sees
|
||||
|
||||
| User composes | Apple delivers | Flag off (default) | Flag on + 2500 ms window |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (one send) | 2 webhooks ~1 s apart | Two agent turns: "Dump" alone, then URL | One turn: merged text `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (attachment + text) | 2 webhooks | Two turns | One turn: text + image |
|
||||
| `/status` (standalone command) | 1 webhook | Instant dispatch | **Wait up to window, then dispatch** |
|
||||
| URL pasted alone | 1 webhook | Instant dispatch | Instant dispatch (only one entry in bucket) |
|
||||
| Text + URL sent as two deliberate separate messages, minutes apart | 2 webhooks outside window | Two turns | Two turns (window expires between them) |
|
||||
| Rapid flood (>10 small DMs inside window) | N webhooks | N turns | One turn, bounded output (first + latest, text/attachment caps applied) |
|
||||
|
||||
### Split-send coalescing troubleshooting
|
||||
|
||||
If the flag is on and split-sends still arrive as two turns, check each layer:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Then `openclaw gateway restart` - the flag is read at debouncer-registry creation.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
Look at the BlueBubbles server log under `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Measure the gap between the `"Dump"`-style text dispatch and the `"https://..."; Attachments:` dispatch that follows. Raise `messages.inbound.byChannel.bluebubbles` to comfortably cover that gap.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
Session event timestamps (`~/.openclaw/agents/<id>/sessions/*.jsonl`) reflect when the gateway hands a message to the agent, **not** when the webhook arrived. A queued-second message tagged `[Queued messages while agent was busy]` means the first turn was still running when the second webhook arrived - the coalesce bucket had already flushed. Tune the window against the BB server log, not the session log.
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
On smaller machines (8 GB), agent turns can take long enough that the coalesce bucket flushes before the reply completes, and the URL lands as a queued second turn. Check `memory_pressure` and `ps -o rss -p $(pgrep openclaw-gateway)`; if the gateway is over ~500 MB RSS and the compressor is active, close other heavy processes or bump to a larger host.
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
If the user tapped `Dump` as a **reply** to an existing URL-balloon (iMessage shows a "1 Reply" badge on the Dump bubble), the URL lives in `replyToBody`, not in a second webhook. Coalescing does not apply - that's a skill/prompt concern, not a debouncer concern.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Block streaming
|
||||
|
||||
Control whether responses are sent as a single message or streamed in blocks:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Media + limits
|
||||
|
||||
- Inbound attachments are downloaded and stored in the media cache.
|
||||
- Media cap via `channels.bluebubbles.mediaMaxMb` for inbound and outbound media (default: 8 MB).
|
||||
- Outbound text is chunked to `channels.bluebubbles.textChunkLimit` (default: 4000 chars).
|
||||
|
||||
## Configuration reference
|
||||
|
||||
Full configuration: [Configuration](/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Connection and webhook">
|
||||
- `channels.bluebubbles.enabled`: Enable/disable the channel.
|
||||
- `channels.bluebubbles.serverUrl`: BlueBubbles REST API base URL.
|
||||
- `channels.bluebubbles.password`: API password.
|
||||
- `channels.bluebubbles.webhookPath`: Webhook endpoint path (default: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Access policy">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (default: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: DM allowlist (handles, emails, E.164 numbers, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (default: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Group sender allowlist.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: On macOS, optionally enrich unnamed group participants from local Contacts after gating passes. Default: `false`.
|
||||
- `channels.bluebubbles.groups`: Per-group config (`requireMention`, etc.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Delivery and chunking">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Send read receipts (default: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Enable block streaming (default: `false`; required for streaming replies).
|
||||
- `channels.bluebubbles.textChunkLimit`: Outbound chunk size in chars (default: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Per-request timeout in ms for outbound text sends via `/api/v1/message/text` (default: 30000). Raise on macOS 26 setups where Private API iMessage sends can stall for 60+ seconds inside the iMessage framework; for example `45000` or `60000`. Probes, chat lookups, reactions, edits, and health checks currently keep the shorter 10s default; broadening coverage to reactions and edits is planned as a follow-up. Per-account override: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (default) splits only when exceeding `textChunkLimit`; `newline` splits on blank lines (paragraph boundaries) before length chunking.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Media and history">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Inbound/outbound media cap in MB (default: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Explicit allowlist of absolute local directories permitted for outbound local media paths. Local path sends are denied by default unless this is configured. Per-account override: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Merge consecutive same-sender DM webhooks into one agent turn so Apple's text+URL split-send arrives as a single message (default: `false`). See [Coalescing split-send DMs](#coalescing-split-send-dms-command--url-in-one-composition) for scenarios, window tuning, and trade-offs. Widens the default inbound debounce window from 500 ms to 2500 ms when enabled without an explicit `messages.inbound.byChannel.bluebubbles`.
|
||||
- `channels.bluebubbles.historyLimit`: Max group messages for context (0 disables).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM history limit.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: When an inbound reply lands without `replyToBody`/`replyToSender` and the in-memory reply-context cache misses, fetch the original message from the BlueBubbles HTTP API as a best-effort fallback (default: `false`). Useful for multi-instance deployments sharing one BlueBubbles account, after process restarts, or after long-lived TTL/LRU cache eviction. The fetch is SSRF-guarded by the same policy as every other BlueBubbles client request, never throws, and populates the cache so subsequent replies amortize. Per-account override: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. A channel-level setting propagates to accounts that omit the flag.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Actions and accounts">
|
||||
- `channels.bluebubbles.actions`: Enable/disable specific actions.
|
||||
- `channels.bluebubbles.accounts`: Multi-account configuration.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Related global options:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Addressing / delivery targets
|
||||
|
||||
Prefer `chat_guid` for stable routing:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (preferred for groups)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Direct handles: `+15555550123`, `user@example.com`
|
||||
- If a direct handle does not have an existing DM chat, OpenClaw will create one via `POST /api/v1/chat/new`. This requires the BlueBubbles Private API to be enabled.
|
||||
|
||||
### iMessage vs SMS routing
|
||||
|
||||
When the same handle has both an iMessage and an SMS chat on the Mac (for example a phone number that is iMessage-registered but has also received green-bubble fallbacks), OpenClaw prefers the iMessage chat and never silently downgrades to SMS. To force the SMS chat, use an explicit `sms:` target prefix (for example `sms:+15555550123`). Handles without a matching iMessage chat still send through whatever chat BlueBubbles reports.
|
||||
|
||||
## Security
|
||||
|
||||
- Webhook requests are authenticated by comparing `guid`/`password` query params or headers against `channels.bluebubbles.password`.
|
||||
- Keep the API password and webhook endpoint secret (treat them like credentials).
|
||||
- There is no localhost bypass for BlueBubbles webhook auth. If you proxy webhook traffic, keep the BlueBubbles password on the request end-to-end. `gateway.trustedProxies` does not replace `channels.bluebubbles.password` here. See [Gateway security](/gateway/security#reverse-proxy-configuration).
|
||||
- Enable HTTPS + firewall rules on the BlueBubbles server if exposing it outside your LAN.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- If typing/read events stop working, check the BlueBubbles webhook logs and verify the gateway path matches `channels.bluebubbles.webhookPath`.
|
||||
- Pairing codes expire after one hour; use `openclaw pairing list bluebubbles` and `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reactions require the BlueBubbles private API (`POST /api/v1/message/react`); ensure the server version exposes it.
|
||||
- Edit/unsend require macOS 13+ and a compatible BlueBubbles server version. On macOS 26 (Tahoe), edit is currently broken due to private API changes.
|
||||
- Group icon updates can be flaky on macOS 26 (Tahoe): the API may return success but the new icon does not sync.
|
||||
- OpenClaw auto-hides known-broken actions based on the BlueBubbles server's macOS version. If edit still appears on macOS 26 (Tahoe), disable it manually with `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` enabled but split-sends (e.g. `Dump` + URL) still arrive as two turns: see the [split-send coalescing troubleshooting](#split-send-coalescing-troubleshooting) checklist - common causes are too-tight debounce window, session-log timestamps misread as webhook arrival, or a reply-quote send (which uses `replyToBody`, not a second webhook).
|
||||
- For status/health info: `openclaw status --all` or `openclaw status --deep`.
|
||||
|
||||
For general channel workflow reference, see [Channels](/channels) and the [Plugins](/tools/plugin) guide.
|
||||
|
||||
## Related
|
||||
|
||||
- [Channel Routing](/channels/channel-routing) - session routing for messages
|
||||
- [Channels Overview](/channels) - all supported channels
|
||||
- [Groups](/channels/groups) - group chat behavior and mention gating
|
||||
- [Pairing](/channels/pairing) - DM authentication and pairing flow
|
||||
- [Security](/gateway/security) - access model and hardening
|
||||
@ -482,10 +482,6 @@ Group inbound payloads set:
|
||||
- `WasMentioned` (mention gating result)
|
||||
- Telegram forum topics also include `MessageThreadId` and `IsForum`.
|
||||
|
||||
Channel-specific notes:
|
||||
|
||||
- BlueBubbles can optionally enrich unnamed macOS group participants from the local Contacts database before populating `GroupMembers`. This is off by default and only runs after normal group gating passes.
|
||||
|
||||
The agent system prompt includes a group intro on the first turn of a new group session. It reminds the model to respond like a human, avoid Markdown tables, minimize empty lines and follow normal chat spacing, and avoid typing literal `\n` sequences. Channel-sourced group names and participant labels are rendered as fenced untrusted metadata, not inline system instructions.
|
||||
|
||||
## iMessage specifics
|
||||
|
||||
@ -7,18 +7,18 @@ title: "iMessage"
|
||||
---
|
||||
|
||||
<Note>
|
||||
For new OpenClaw iMessage deployments, start here when you can run `imsg` on a signed-in macOS Messages host. BlueBubbles remains available as a legacy fallback for existing setups that depend on its HTTP server, webhooks, or richer private-API actions.
|
||||
For OpenClaw iMessage deployments, use `imsg` on a signed-in macOS Messages host. If your Gateway runs on Linux or Windows, point `channels.imessage.cliPath` at an SSH wrapper that runs `imsg` on the Mac.
|
||||
</Note>
|
||||
|
||||
Status: native external CLI integration. Gateway spawns `imsg rpc` and communicates over JSON-RPC on stdio (no separate daemon/port).
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="BlueBubbles (legacy fallback)" icon="message-circle" href="/channels/bluebubbles">
|
||||
Keep using it for existing BlueBubbles-backed routing; avoid it for new setups when imsg fits.
|
||||
</Card>
|
||||
<Card title="Pairing" icon="link" href="/channels/pairing">
|
||||
iMessage DMs default to pairing mode.
|
||||
</Card>
|
||||
<Card title="Remote Mac" icon="terminal" href="#remote-mac-over-ssh">
|
||||
Use an SSH wrapper when the Gateway is not running on the Messages Mac.
|
||||
</Card>
|
||||
<Card title="Configuration reference" icon="settings" href="/gateway/config-channels#imessage">
|
||||
Full iMessage field reference.
|
||||
</Card>
|
||||
@ -362,7 +362,23 @@ imsg rpc --help
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
If probe reports RPC unsupported, update `imsg`.
|
||||
If probe reports RPC unsupported, update `imsg`. If the Gateway is not running on macOS, use the Remote Mac over SSH setup above instead of the default local `imsg` path.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gateway is not running on macOS">
|
||||
The default `cliPath: "imsg"` must run on the Mac signed into Messages. On Linux or Windows, set `channels.imessage.cliPath` to a wrapper script that SSHes to that Mac and runs `imsg "$@"`.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
exec ssh -T messages-mac imsg "$@"
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
openclaw channels status --probe --channel imessage
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -414,7 +430,6 @@ imsg send <handle> "test"
|
||||
- [Configuration reference - iMessage](/gateway/config-channels#imessage)
|
||||
- [Gateway configuration](/gateway/configuration)
|
||||
- [Pairing](/channels/pairing)
|
||||
- [BlueBubbles](/channels/bluebubbles)
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
@ -21,11 +21,10 @@ Text is supported everywhere; media and reactions vary by channel.
|
||||
|
||||
## Supported channels
|
||||
|
||||
- [BlueBubbles](/channels/bluebubbles) - Legacy iMessage bridge via the BlueBubbles macOS server REST API; deprecated for new OpenClaw setups but still supported for existing configs and richer private-API actions.
|
||||
- [Discord](/channels/discord) - Discord Bot API + Gateway; supports servers, channels, and DMs.
|
||||
- [Feishu](/channels/feishu) - Feishu/Lark bot via WebSocket (bundled plugin).
|
||||
- [Google Chat](/channels/googlechat) - Google Chat API app via HTTP webhook (downloadable plugin).
|
||||
- [iMessage](/channels/imessage) - Native macOS integration via the imsg CLI; preferred for new OpenClaw iMessage setups when host permissions and Messages access fit.
|
||||
- [iMessage](/channels/imessage) - Native macOS integration via the `imsg` CLI on a signed-in Mac; use an SSH wrapper when the Gateway runs elsewhere.
|
||||
- [IRC](/channels/irc) - Classic IRC servers; channels + DMs with pairing/allowlist controls.
|
||||
- [LINE](/channels/line) - LINE Messaging API bot (downloadable plugin).
|
||||
- [Matrix](/channels/matrix) - Matrix protocol (downloadable plugin).
|
||||
|
||||
@ -45,7 +45,7 @@ That gives first-time setups an explicit owner for privileged commands and exec
|
||||
approval prompts. After an owner exists, later pairing approvals only grant DM
|
||||
access; they do not add more owners.
|
||||
|
||||
Supported channels: `bluebubbles`, `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `openclaw-weixin`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`.
|
||||
Supported channels: `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `openclaw-weixin`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`.
|
||||
|
||||
### Reusable sender groups
|
||||
|
||||
@ -209,6 +209,5 @@ Stored under `~/.openclaw/devices/`:
|
||||
- WhatsApp: [WhatsApp](/channels/whatsapp)
|
||||
- Signal: [Signal](/channels/signal)
|
||||
- iMessage: [iMessage](/channels/imessage)
|
||||
- BlueBubbles (legacy iMessage bridge): [BlueBubbles](/channels/bluebubbles)
|
||||
- Discord: [Discord](/channels/discord)
|
||||
- Slack: [Slack](/channels/slack)
|
||||
|
||||
@ -82,20 +82,19 @@ Full troubleshooting: [Discord troubleshooting](/channels/discord#troubleshootin
|
||||
|
||||
Full troubleshooting: [Slack troubleshooting](/channels/slack#troubleshooting)
|
||||
|
||||
## iMessage and BlueBubbles
|
||||
## iMessage
|
||||
|
||||
### iMessage and BlueBubbles failure signatures
|
||||
### iMessage failure signatures
|
||||
|
||||
| Symptom | Fastest check | Fix |
|
||||
| -------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| No inbound events | Verify webhook/server reachability and app permissions | Fix webhook URL or BlueBubbles server state. |
|
||||
| Can send but no receive on macOS | Check macOS privacy permissions for Messages automation | Re-grant TCC permissions and restart channel process. |
|
||||
| DM sender blocked | `openclaw pairing list imessage` or `openclaw pairing list bluebubbles` | Approve pairing or update allowlist. |
|
||||
| Symptom | Fastest check | Fix |
|
||||
| ------------------------------------ | ------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| `imsg` missing or fails on non-macOS | `openclaw channels status --probe --channel imessage` | Run OpenClaw on the Messages Mac or use an SSH wrapper for `cliPath`. |
|
||||
| Can send but no receive on macOS | Check macOS privacy permissions for Messages automation | Re-grant TCC permissions and restart channel process. |
|
||||
| DM sender blocked | `openclaw pairing list imessage` | Approve pairing or update allowlist. |
|
||||
|
||||
Full troubleshooting:
|
||||
|
||||
- [iMessage troubleshooting](/channels/imessage#troubleshooting)
|
||||
- [BlueBubbles troubleshooting](/channels/bluebubbles#troubleshooting)
|
||||
|
||||
## Signal
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ title: "Features"
|
||||
**Channels:**
|
||||
|
||||
- Built-in channels include Discord, Google Chat, iMessage, IRC, Signal, Slack, Telegram, WebChat, and WhatsApp
|
||||
- Bundled plugin channels include BlueBubbles as a legacy iMessage bridge, Feishu, LINE, Matrix, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQ Bot, Synology Chat, Tlon, Twitch, Zalo, and Zalo Personal
|
||||
- Bundled plugin channels include Feishu, LINE, Matrix, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQ Bot, Synology Chat, Tlon, Twitch, Zalo, and Zalo Personal
|
||||
- Optional separately installed channel plugins include Voice Call and third-party packages such as WeChat
|
||||
- Third-party channel plugins can extend the Gateway further, such as WeChat
|
||||
- Group chat support with mention-based activation
|
||||
|
||||
@ -763,7 +763,7 @@ Concrete migration hazards to preserve:
|
||||
- Telegram silent fallback delivery must deliver the full projected payload
|
||||
array. A single-payload shortcut can drop additional fallback payloads after
|
||||
projection.
|
||||
- LINE, BlueBubbles, Zalo, Nostr, and other existing assembled/helper paths may
|
||||
- LINE, Zalo, Nostr, and other existing assembled/helper paths may
|
||||
have reply-token handling, media proxying, sent-message caches, loading/status
|
||||
cleanup, or callback-only targets. They stay on channel-owned delivery until
|
||||
those semantics are represented by the send adapter and verified by tests.
|
||||
@ -854,30 +854,30 @@ Core policy:
|
||||
|
||||
## Channel mapping
|
||||
|
||||
| Channel | Target migration |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Telegram | Receive ack policy plus durable final sends. Live adapter owns send plus edit preview, stale preview final send, topics, quote-reply preview skip, media fallback, and retry-after handling. |
|
||||
| Discord | Send adapter wraps existing durable payload delivery. Live adapter owns draft edit, progress draft, media/error preview cancel, reply target preservation, and message id receipts. Audit bot-authored gateway-failure echoes in shared rooms; use an outbound registry or other native equivalent if Discord cannot carry origin metadata on normal messages. |
|
||||
| Slack | Send adapter handles normal chat posts. Live adapter chooses native stream when thread shape supports it, otherwise draft preview. Receipts preserve thread timestamps. Origin adapter maps OpenClaw gateway failures to Slack `chat.postMessage.metadata` and drops tagged bot-room echoes before `allowBots` authorization. |
|
||||
| WhatsApp | Send adapter owns text/media send with durable final intents. Receive adapter handles group mention and sender identity. Live can stay absent until WhatsApp has an editable transport. |
|
||||
| Matrix | Live adapter owns draft event edits, finalization, redaction, encrypted media constraints, and reply-target mismatch fallback. Receive adapter owns encrypted event hydration and dedupe. Origin adapter should encode OpenClaw gateway-failure origin into Matrix event content and drop configured-bot room echoes before `allowBots` handling. |
|
||||
| Mattermost | Live adapter owns one draft post, progress/tool folding, finalization in place, and fresh-send fallback. |
|
||||
| Microsoft Teams | Live adapter owns native progress and block stream behavior. Send adapter owns activities and attachment/card receipts. |
|
||||
| Feishu | Render adapter owns text/card/raw rendering. Live adapter owns streaming cards and duplicate final suppression. Send adapter owns comments, topic sessions, media, and voice suppression. |
|
||||
| QQ Bot | Live adapter owns C2C streaming, accumulator timeout, and fallback final send. Render adapter owns media tags and text-as-voice. |
|
||||
| Signal | Simple receive plus send adapter. No live adapter unless signal-cli adds reliable edit support. |
|
||||
| iMessage and BlueBubbles | Simple receive plus send adapter. iMessage send must preserve monitor echo-cache population before durable finals can bypass monitor delivery. BlueBubbles-specific typing, reactions, and attachments remain adapter capabilities. |
|
||||
| Google Chat | Simple receive plus send adapter with thread relation mapped to spaces and thread ids. Audit `allowBots=true` room behavior for tagged OpenClaw gateway-failure echoes. |
|
||||
| LINE | Simple receive plus send adapter with reply-token constraints modeled as target/relation capability. |
|
||||
| Nextcloud Talk | SDK receive bridge plus send adapter. |
|
||||
| IRC | Simple receive plus send adapter, no durable edit receipts. |
|
||||
| Nostr | Receive plus send adapter for encrypted DMs; receipts are event ids. |
|
||||
| QA Channel | Contract-test adapter for receive, send, live, retry, and recovery behavior. |
|
||||
| Synology Chat | Simple receive plus send adapter. |
|
||||
| Tlon | Send adapter must preserve model-signature rendering and participated-thread tracking before generic durable final delivery is enabled. |
|
||||
| Twitch | Simple receive plus send adapter with rate-limit classification. |
|
||||
| Zalo | Simple receive plus send adapter. |
|
||||
| Zalo Personal | Simple receive plus send adapter. |
|
||||
| Channel | Target migration |
|
||||
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Telegram | Receive ack policy plus durable final sends. Live adapter owns send plus edit preview, stale preview final send, topics, quote-reply preview skip, media fallback, and retry-after handling. |
|
||||
| Discord | Send adapter wraps existing durable payload delivery. Live adapter owns draft edit, progress draft, media/error preview cancel, reply target preservation, and message id receipts. Audit bot-authored gateway-failure echoes in shared rooms; use an outbound registry or other native equivalent if Discord cannot carry origin metadata on normal messages. |
|
||||
| Slack | Send adapter handles normal chat posts. Live adapter chooses native stream when thread shape supports it, otherwise draft preview. Receipts preserve thread timestamps. Origin adapter maps OpenClaw gateway failures to Slack `chat.postMessage.metadata` and drops tagged bot-room echoes before `allowBots` authorization. |
|
||||
| WhatsApp | Send adapter owns text/media send with durable final intents. Receive adapter handles group mention and sender identity. Live can stay absent until WhatsApp has an editable transport. |
|
||||
| Matrix | Live adapter owns draft event edits, finalization, redaction, encrypted media constraints, and reply-target mismatch fallback. Receive adapter owns encrypted event hydration and dedupe. Origin adapter should encode OpenClaw gateway-failure origin into Matrix event content and drop configured-bot room echoes before `allowBots` handling. |
|
||||
| Mattermost | Live adapter owns one draft post, progress/tool folding, finalization in place, and fresh-send fallback. |
|
||||
| Microsoft Teams | Live adapter owns native progress and block stream behavior. Send adapter owns activities and attachment/card receipts. |
|
||||
| Feishu | Render adapter owns text/card/raw rendering. Live adapter owns streaming cards and duplicate final suppression. Send adapter owns comments, topic sessions, media, and voice suppression. |
|
||||
| QQ Bot | Live adapter owns C2C streaming, accumulator timeout, and fallback final send. Render adapter owns media tags and text-as-voice. |
|
||||
| Signal | Simple receive plus send adapter. No live adapter unless signal-cli adds reliable edit support. |
|
||||
| iMessage | Simple receive plus send adapter. iMessage send must preserve monitor echo-cache population before durable finals can bypass monitor delivery. |
|
||||
| Google Chat | Simple receive plus send adapter with thread relation mapped to spaces and thread ids. Audit `allowBots=true` room behavior for tagged OpenClaw gateway-failure echoes. |
|
||||
| LINE | Simple receive plus send adapter with reply-token constraints modeled as target/relation capability. |
|
||||
| Nextcloud Talk | SDK receive bridge plus send adapter. |
|
||||
| IRC | Simple receive plus send adapter, no durable edit receipts. |
|
||||
| Nostr | Receive plus send adapter for encrypted DMs; receipts are event ids. |
|
||||
| QA Channel | Contract-test adapter for receive, send, live, retry, and recovery behavior. |
|
||||
| Synology Chat | Simple receive plus send adapter. |
|
||||
| Tlon | Send adapter must preserve model-signature rendering and participated-thread tracking before generic durable final delivery is enabled. |
|
||||
| Twitch | Simple receive plus send adapter with rate-limit classification. |
|
||||
| Zalo | Simple receive plus send adapter. |
|
||||
| Zalo Personal | Simple receive plus send adapter. |
|
||||
|
||||
## Migration plan
|
||||
|
||||
@ -1035,7 +1035,7 @@ Channel tests:
|
||||
- Discord prepared dispatcher finals route through the send context before docs
|
||||
or changelog claim Discord final-reply durability.
|
||||
- iMessage durable final sends populate the monitor sent-message echo cache.
|
||||
- LINE, BlueBubbles, Zalo, and Nostr legacy delivery paths are not bypassed by
|
||||
- LINE, Zalo, and Nostr legacy delivery paths are not bypassed by
|
||||
generic durable send until their adapter parity tests exist.
|
||||
- Direct-DM/Nostr callback delivery remains authoritative unless explicitly
|
||||
migrated to a complete message target and replay-safe send adapter.
|
||||
|
||||
@ -59,7 +59,7 @@ Config (global default + per-channel overrides):
|
||||
Notes:
|
||||
|
||||
- Debounce applies to **text-only** messages; media/attachments flush immediately.
|
||||
- Control commands bypass debouncing so they remain standalone — **except** when a channel explicitly opts in to same-sender DM coalescing (e.g. [BlueBubbles `coalesceSameSenderDms`](/channels/bluebubbles#coalescing-split-send-dms-command--url-in-one-composition)), where DM commands wait inside the debounce window so a split-send payload can join the same agent turn.
|
||||
- Control commands bypass debouncing so they remain standalone. Channels that explicitly opt in to same-sender DM coalescing can keep DM commands inside the debounce window so a split-send payload can join the same agent turn.
|
||||
|
||||
## Sessions and devices
|
||||
|
||||
|
||||
@ -262,7 +262,7 @@ Common channels supporting this pattern include:
|
||||
|
||||
- `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`
|
||||
- `irc`, `line`, `googlechat`, `mattermost`, `matrix`, `nextcloud-talk`
|
||||
- `bluebubbles`, `zalo`, `zalouser`, `nostr`, `feishu`
|
||||
- `zalo`, `zalouser`, `nostr`, `feishu`
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles-Kanal einrichten
|
||||
- Fehlerbehebung bei der Webhook-Kopplung
|
||||
- iMessage unter macOS konfigurieren
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Legacy-Unterstützung für iMessage über den BlueBubbles-macOS-Server (REST-Senden/-Empfangen, Schreibstatus, Reaktionen, Kopplung, erweiterte Aktionen).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:55Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: gebündeltes Legacy-Plugin, das über HTTP mit dem BlueBubbles-macOS-Server kommuniziert. Bestehende BlueBubbles-Setups funktionieren weiterhin, neue OpenClaw-iMessage-Bereitstellungen sollten jedoch das native [iMessage](/de/channels/imessage)-Plugin bevorzugen, wenn dessen Anforderungen zu Ihrem Host passen.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles ist für neue OpenClaw-Setups veraltet.
|
||||
|
||||
Das Upstream-BlueBubbles-Ökosystem ist weiterhin aktiv, aber OpenClaw hängt von der BlueBubbles-macOS-Server-API ab. Mit Stand vom 6. Mai 2026 wurde der offizielle Entwicklungs-Branch von [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) zuletzt am [22. Januar 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037) geändert, und die neueste Server-Version ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) wurde am 16. Mai 2025 veröffentlicht. Die Client-App und Helper-Repositories weisen neuere Aktivität auf; dies ist also keine Behauptung, dass das Projekt aufgegeben wurde. Die Deprecation dient dazu, die Abhängigkeit von OpenClaw von einem externen HTTP-Server, Webhooks und einer Private-API-Kompatibilitätsfläche zu reduzieren, wenn der native `imsg`-Pfad die Integration auf einem lokalen stdio-Vertrag hält.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Aktuelle OpenClaw-Versionen bündeln BlueBubbles, daher benötigen normale paketierte Builds keinen separaten Schritt `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Überblick
|
||||
|
||||
- Läuft unter macOS über die BlueBubbles-Helper-App ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Legacy-Fallback für Installationen, die bereits auf BlueBubbles-Kanal-IDs, Webhook-Status, Gruppenziele, Cron-Zustellung oder Workspace-Routing angewiesen sind.
|
||||
- Empfohlen/getestet: macOS Sequoia (15). macOS Tahoe (26) funktioniert; Bearbeiten ist unter Tahoe derzeit defekt, und Aktualisierungen von Gruppensymbolen melden eventuell Erfolg, synchronisieren aber nicht.
|
||||
- OpenClaw kommuniziert damit über die REST-API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Eingehende Nachrichten treffen über Webhooks ein; ausgehende Antworten, Tippindikatoren, Lesebestätigungen und Tapbacks sind REST-Aufrufe.
|
||||
- Anhänge und Sticker werden als eingehende Medien aufgenommen und, wenn möglich, dem Agenten bereitgestellt.
|
||||
- Auto-TTS-Antworten, die MP3- oder CAF-Audio synthetisieren, werden als iMessage-Sprachmemo-Blasen statt als einfache Dateianhänge zugestellt.
|
||||
- Pairing/Allowlist funktioniert wie bei anderen Kanälen (`/channels/pairing` usw.) mit `channels.bluebubbles.allowFrom` + Pairing-Codes.
|
||||
- Reaktionen werden genau wie bei Slack/Telegram als Systemereignisse bereitgestellt, sodass Agenten sie vor dem Antworten „erwähnen“ können.
|
||||
- Erweiterte Funktionen: Bearbeiten, Senden rückgängig machen, Antwort-Threads, Nachrichteneffekte, Gruppenverwaltung.
|
||||
|
||||
## Schnellstart
|
||||
|
||||
<Steps>
|
||||
<Step title="BlueBubbles installieren">
|
||||
Installieren Sie den BlueBubbles-Server auf Ihrem Mac (folgen Sie den Anweisungen unter [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Web-API aktivieren">
|
||||
Aktivieren Sie in der BlueBubbles-Konfiguration die Web-API und legen Sie ein Passwort fest.
|
||||
</Step>
|
||||
<Step title="OpenClaw konfigurieren">
|
||||
Führen Sie `openclaw onboard` aus und wählen Sie BlueBubbles aus, oder konfigurieren Sie manuell:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Webhooks auf das Gateway richten">
|
||||
Richten Sie BlueBubbles-Webhooks auf Ihr Gateway (Beispiel: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Gateway starten">
|
||||
Starten Sie das Gateway; es registriert den Webhook-Handler und startet das Pairing.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Sicherheit**
|
||||
|
||||
- Legen Sie immer ein Webhook-Passwort fest.
|
||||
- Webhook-Authentifizierung ist immer erforderlich. OpenClaw lehnt BlueBubbles-Webhook-Anfragen ab, sofern sie kein Passwort/guid enthalten, das mit `channels.bluebubbles.password` übereinstimmt (zum Beispiel `?password=<password>` oder `x-password`), unabhängig von loopback-/Proxy-Topologie.
|
||||
- Passwortauthentifizierung wird geprüft, bevor vollständige Webhook-Bodys gelesen/geparst werden.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Messages.app aktiv halten (VM-/Headless-Setups)
|
||||
|
||||
Einige macOS-VM- oder Always-on-Setups können dazu führen, dass Messages.app „idle“ wird (eingehende Ereignisse stoppen, bis die App geöffnet/in den Vordergrund gebracht wird). Ein einfacher Workaround besteht darin, **Messages alle 5 Minuten anzustoßen**, mit einem AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="AppleScript speichern">
|
||||
Speichern Sie dies als `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="LaunchAgent installieren">
|
||||
Speichern Sie dies als `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Dies läuft **alle 300 Sekunden** und **beim Anmelden**. Der erste Lauf kann macOS-**Automation**-Aufforderungen auslösen (`osascript` → Messages). Genehmigen Sie diese in derselben Benutzersitzung, in der der LaunchAgent läuft.
|
||||
|
||||
</Step>
|
||||
<Step title="Laden">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles ist im interaktiven Onboarding verfügbar:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Der Assistent fragt nach:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles-Serveradresse (z. B. `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
API-Passwort aus den BlueBubbles-Servereinstellungen.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook-Endpunktpfad.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` oder `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Telefonnummern, E-Mails oder Chat-Ziele.
|
||||
</ParamField>
|
||||
|
||||
Sie können BlueBubbles auch per CLI hinzufügen:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Zugriffskontrolle (DMs + Gruppen)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Standard: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Unbekannte Absender erhalten einen Pairing-Code; Nachrichten werden ignoriert, bis sie genehmigt wurden (Codes laufen nach 1 Stunde ab).
|
||||
- Genehmigen über:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Pairing ist der standardmäßige Token-Austausch. Details: [Pairing](/de/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Gruppen">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (Standard: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` steuert, wer in Gruppen auslösen kann, wenn `allowlist` gesetzt ist.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Kontaktnamen-Anreicherung (macOS, optional)
|
||||
|
||||
BlueBubbles-Gruppen-Webhooks enthalten häufig nur rohe Teilnehmeradressen. Wenn Sie möchten, dass der `GroupMembers`-Kontext stattdessen lokale Kontaktnamen anzeigt, können Sie unter macOS lokale Kontakte-Anreicherung aktivieren:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` aktiviert die Suche. Standard: `false`.
|
||||
- Suchvorgänge laufen erst, nachdem Gruppenzugriff, Befehlsautorisierung und Mention-Gating die Nachricht zugelassen haben.
|
||||
- Nur unbenannte Telefonnummern-Teilnehmer werden angereichert.
|
||||
- Rohe Telefonnummern bleiben der Fallback, wenn keine lokale Übereinstimmung gefunden wird.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Mention-Gating (Gruppen)
|
||||
|
||||
BlueBubbles unterstützt Mention-Gating für Gruppenchats und entspricht damit dem Verhalten von iMessage/WhatsApp:
|
||||
|
||||
- Verwendet `agents.list[].groupChat.mentionPatterns` (oder `messages.groupChat.mentionPatterns`), um Mentions zu erkennen.
|
||||
- Wenn `requireMention` für eine Gruppe aktiviert ist, antwortet der Agent nur, wenn er erwähnt wird.
|
||||
- Steuerbefehle von autorisierten Absendern umgehen Mention-Gating.
|
||||
|
||||
Konfiguration pro Gruppe:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Befehls-Gating
|
||||
|
||||
- Steuerbefehle (z. B. `/config`, `/model`) erfordern Autorisierung.
|
||||
- Verwendet `allowFrom` und `groupAllowFrom`, um die Befehlsautorisierung zu bestimmen.
|
||||
- Autorisierte Absender können Steuerbefehle auch ohne Erwähnung in Gruppen ausführen.
|
||||
|
||||
### System-Prompt pro Gruppe
|
||||
|
||||
Jeder Eintrag unter `channels.bluebubbles.groups.*` akzeptiert einen optionalen `systemPrompt`-String. Der Wert wird bei jedem Turn, der eine Nachricht in dieser Gruppe verarbeitet, in den System-Prompt des Agenten eingefügt, sodass Sie gruppenspezifische Persona- oder Verhaltensregeln festlegen können, ohne Agenten-Prompts zu bearbeiten:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Der Schlüssel entspricht dem, was BlueBubbles für die Gruppe als `chatGuid` / `chatIdentifier` / numerische `chatId` meldet, und ein `"*"`-Wildcard-Eintrag stellt einen Standard für jede Gruppe ohne genaue Übereinstimmung bereit (dasselbe Muster wie bei `requireMention` und Tool-Richtlinien pro Gruppe). Genaue Übereinstimmungen haben immer Vorrang vor der Wildcard. DMs ignorieren dieses Feld; verwenden Sie stattdessen Prompt-Anpassung auf Agenten- oder Kontoebene.
|
||||
|
||||
#### Ausgearbeitetes Beispiel: Thread-Antworten und Tapback-Reaktionen (Private API)
|
||||
|
||||
Wenn die BlueBubbles Private API aktiviert ist, treffen eingehende Nachrichten mit kurzen Nachrichten-IDs ein (zum Beispiel `[[reply_to:5]]`), und der Agent kann `action=reply` aufrufen, um in eine bestimmte Nachricht einzufädeln, oder `action=react`, um einen Tapback zu setzen. Ein `systemPrompt` pro Gruppe ist eine zuverlässige Möglichkeit, den Agenten dazu zu bringen, das richtige Tool auszuwählen:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback-Reaktionen und Thread-Antworten erfordern beide die BlueBubbles Private API; siehe [Erweiterte Aktionen](#advanced-actions) und [Nachrichten-IDs](#message-ids-short-vs-full) für die zugrunde liegenden Mechanismen.
|
||||
|
||||
## ACP-Konversationsbindungen
|
||||
|
||||
BlueBubbles-Chats können in dauerhafte ACP-Workspaces umgewandelt werden, ohne die Transportschicht zu ändern.
|
||||
|
||||
Schneller Operator-Ablauf:
|
||||
|
||||
- Führen Sie `/acp spawn codex --bind here` innerhalb der DM oder des erlaubten Gruppenchats aus.
|
||||
- Zukünftige Nachrichten in derselben BlueBubbles-Konversation werden an die gestartete ACP-Sitzung geroutet.
|
||||
- `/new` und `/reset` setzen dieselbe gebundene ACP-Sitzung direkt zurück.
|
||||
- `/acp close` schließt die ACP-Sitzung und entfernt die Bindung.
|
||||
|
||||
Konfigurierte persistente Bindungen werden auch über Top-Level-`bindings[]`-Einträge mit `type: "acp"` und `match.channel: "bluebubbles"` unterstützt.
|
||||
|
||||
`match.peer.id` kann jede unterstützte BlueBubbles-Zielform verwenden:
|
||||
|
||||
- normalisiertes DM-Handle wie `+15555550123` oder `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Für stabile Gruppenbindungen bevorzugen Sie `chat_id:*` oder `chat_identifier:*`.
|
||||
|
||||
Beispiel:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Siehe [ACP-Agenten](/de/tools/acp-agents) für gemeinsames ACP-Bindungsverhalten.
|
||||
|
||||
## Tippanzeige + Lesebestätigungen
|
||||
|
||||
- **Tippanzeigen**: Werden vor und während der Antwortgenerierung automatisch gesendet.
|
||||
- **Lesebestätigungen**: Gesteuert über `channels.bluebubbles.sendReadReceipts` (Standard: `true`).
|
||||
- **Tippanzeigen**: OpenClaw sendet Ereignisse für den Tippbeginn; BlueBubbles löscht die Tippanzeige automatisch beim Senden oder nach einem Timeout (manuelles Stoppen per DELETE ist unzuverlässig).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Erweiterte Aktionen
|
||||
|
||||
BlueBubbles unterstützt erweiterte Nachrichtenaktionen, wenn sie in der Konfiguration aktiviert sind:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Verfügbare Aktionen">
|
||||
- **react**: Tapback-Reaktionen hinzufügen/entfernen (`messageId`, `emoji`, `remove`). iMessages native Tapback-Auswahl ist `love`, `like`, `dislike`, `laugh`, `emphasize` und `question`. Wenn ein Agent ein Emoji außerhalb dieser Auswahl wählt (zum Beispiel `👀`), fällt das Reaktionswerkzeug auf `love` zurück, damit der Tapback weiterhin dargestellt wird, statt die gesamte Anfrage fehlschlagen zu lassen. Konfigurierte Bestätigungsreaktionen werden weiterhin strikt validiert und geben bei unbekannten Werten einen Fehler aus.
|
||||
- **edit**: Eine gesendete Nachricht bearbeiten (`messageId`, `text`).
|
||||
- **unsend**: Eine Nachricht zurücknehmen (`messageId`).
|
||||
- **reply**: Auf eine bestimmte Nachricht antworten (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Mit iMessage-Effekt senden (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Einen Gruppenchat umbenennen (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Symbol/Foto eines Gruppenchats festlegen (`chatGuid`, `media`) - unter macOS 26 Tahoe unzuverlässig (API kann Erfolg zurückgeben, aber das Symbol wird nicht synchronisiert).
|
||||
- **addParticipant**: Jemanden zu einer Gruppe hinzufügen (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Jemanden aus einer Gruppe entfernen (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Einen Gruppenchat verlassen (`chatGuid`).
|
||||
- **upload-file**: Medien/Dateien senden (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Sprachmemos: Setzen Sie `asVoice: true` mit **MP3**- oder **CAF**-Audio, um als iMessage-Sprachnachricht zu senden. BlueBubbles konvertiert MP3 → CAF beim Senden von Sprachmemos.
|
||||
- Legacy-Alias: `sendAttachment` funktioniert weiterhin, aber `upload-file` ist der kanonische Aktionsname.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Nachrichten-IDs (kurz vs. vollständig)
|
||||
|
||||
OpenClaw kann _kurze_ Nachrichten-IDs (z. B. `1`, `2`) anzeigen, um Token zu sparen.
|
||||
|
||||
- `MessageSid` / `ReplyToId` können kurze IDs sein.
|
||||
- `MessageSidFull` / `ReplyToIdFull` enthalten die vollständigen Provider-IDs.
|
||||
- Kurze IDs liegen im Speicher; sie können nach einem Neustart oder Cache-Verdrängung ablaufen.
|
||||
- Aktionen akzeptieren kurze oder vollständige `messageId`, aber kurze IDs geben einen Fehler aus, wenn sie nicht mehr verfügbar sind.
|
||||
|
||||
Verwenden Sie vollständige IDs für dauerhafte Automatisierungen und Speicherung:
|
||||
|
||||
- Vorlagen: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Kontext: `MessageSidFull` / `ReplyToIdFull` in eingehenden Payloads
|
||||
|
||||
Siehe [Konfiguration](/de/gateway/configuration) für Vorlagenvariablen.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Zusammenführen aufgeteilter DM-Sendungen (Befehl + URL in einer Komposition)
|
||||
|
||||
Wenn ein Benutzer in iMessage einen Befehl und eine URL zusammen eingibt - z. B. `Dump https://example.com/article` -, teilt Apple den Versand in **zwei separate Webhook-Zustellungen** auf:
|
||||
|
||||
1. Eine Textnachricht (`"Dump"`).
|
||||
2. Eine URL-Vorschaublase (`"https://..."`) mit OG-Vorschaubildern als Anhängen.
|
||||
|
||||
Die beiden Webhooks treffen bei den meisten Setups im Abstand von ca. 0,8-2,0 s bei OpenClaw ein. Ohne Zusammenführung erhält der Agent in Runde 1 nur den Befehl, antwortet (oft „send me the URL“) und sieht die URL erst in Runde 2 - dann ist der Befehlskontext bereits verloren.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` aktiviert für eine DM das Zusammenführen aufeinanderfolgender Webhooks desselben Absenders zu einer einzelnen Agentenrunde. Gruppenchats bleiben nach Nachricht geschlüsselt, sodass die Rundenstruktur mit mehreren Benutzern erhalten bleibt.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Wann aktivieren">
|
||||
Aktivieren Sie dies, wenn:
|
||||
|
||||
- Sie Skills bereitstellen, die `command + payload` in einer Nachricht erwarten (dump, paste, save, queue usw.).
|
||||
- Ihre Benutzer URLs, Bilder oder lange Inhalte zusammen mit Befehlen einfügen.
|
||||
- Sie die zusätzliche DM-Rundenlatenz akzeptieren können (siehe unten).
|
||||
|
||||
Deaktiviert lassen, wenn:
|
||||
|
||||
- Sie minimale Befehlslatenz für DM-Auslöser mit einem einzelnen Wort benötigen.
|
||||
- Alle Ihre Abläufe einmalige Befehle ohne nachfolgende Payloads sind.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Aktivieren">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Bei aktivem Flag und ohne explizites `messages.inbound.byChannel.bluebubbles` wird das Debounce-Fenster auf **2500 ms** erweitert (Standard ohne Zusammenführung ist 500 ms). Das breitere Fenster ist erforderlich - Apples Taktung aufgeteilter Sendungen von 0,8-2,0 s passt nicht in den engeren Standardwert.
|
||||
|
||||
So passen Sie das Fenster selbst an:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Abwägungen">
|
||||
- **Zusätzliche Latenz für DM-Steuerbefehle.** Bei aktivem Flag warten DM-Steuerbefehlsnachrichten (wie `Dump`, `Save` usw.) jetzt bis zum Debounce-Fenster, bevor sie weitergeleitet werden, falls ein Payload-Webhook eintrifft. Gruppenchat-Befehle werden weiterhin sofort weitergeleitet.
|
||||
- **Die zusammengeführte Ausgabe ist begrenzt** - zusammengeführter Text ist auf 4000 Zeichen mit einem expliziten Marker `…[truncated]` begrenzt; Anhänge sind auf 20 begrenzt; Quelleneinträge auf 10 (erster-plus-neuester darüber hinaus beibehalten). Jede Quell-`messageId` erreicht weiterhin die eingehende Deduplizierung, sodass eine spätere MessagePoller-Wiederholung eines einzelnen Ereignisses als Duplikat erkannt wird.
|
||||
- **Opt-in, pro Kanal.** Andere Kanäle (Telegram, WhatsApp, Slack, …) sind nicht betroffen.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Szenarien und was der Agent sieht
|
||||
|
||||
| Benutzer verfasst | Apple liefert | Flag aus (Standard) | Flag an + 2500-ms-Fenster |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (ein Versand) | 2 Webhooks ~1 s Abstand | Zwei Agentenrunden: nur „Dump“, dann URL | Eine Runde: zusammengeführter Text `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (Anhang + Text) | 2 Webhooks | Zwei Runden | Eine Runde: Text + Bild |
|
||||
| `/status` (eigenständiger Befehl) | 1 Webhook | Sofortige Weiterleitung | **Bis zum Fenster warten, dann weiterleiten** |
|
||||
| URL allein eingefügt | 1 Webhook | Sofortige Weiterleitung | Sofortige Weiterleitung (nur ein Eintrag im Bucket) |
|
||||
| Text + URL als zwei bewusst separate Nachrichten, Minuten auseinander | 2 Webhooks außerhalb des Fensters | Zwei Runden | Zwei Runden (Fenster läuft zwischen ihnen ab) |
|
||||
| Schnelle Flut (>10 kleine DMs im Fenster) | N Webhooks | N Runden | Eine Runde, begrenzte Ausgabe (erster + neuester, Text-/Anhanglimits angewendet) |
|
||||
|
||||
### Fehlerbehebung für Zusammenführung aufgeteilter Sendungen
|
||||
|
||||
Wenn das Flag aktiviert ist und aufgeteilte Sendungen weiterhin als zwei Runden ankommen, prüfen Sie jede Ebene:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Konfiguration tatsächlich geladen">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Dann `openclaw gateway restart` - das Flag wird bei der Erstellung der Debouncer-Registry gelesen.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce-Fenster breit genug für Ihr Setup">
|
||||
Sehen Sie im BlueBubbles-Serverprotokoll unter `~/Library/Logs/bluebubbles-server/main.log` nach:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Messen Sie den Abstand zwischen der Textweiterleitung im `"Dump"`-Stil und der folgenden Weiterleitung `"https://..."; Attachments:`. Erhöhen Sie `messages.inbound.byChannel.bluebubbles`, sodass diese Lücke komfortabel abgedeckt ist.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session-JSONL-Zeitstempel ≠ Webhook-Eingang">
|
||||
Session-Ereigniszeitstempel (`~/.openclaw/agents/<id>/sessions/*.jsonl`) geben wieder, wann das Gateway eine Nachricht an den Agenten übergibt, **nicht**, wann der Webhook eingetroffen ist. Eine zweite Nachricht in der Warteschlange mit dem Tag `[Queued messages while agent was busy]` bedeutet, dass die erste Runde noch lief, als der zweite Webhook eintraf - der Zusammenführungs-Bucket war bereits geleert. Stimmen Sie das Fenster anhand des BB-Serverprotokolls ab, nicht anhand des Session-Protokolls.
|
||||
</Accordion>
|
||||
<Accordion title="Speicherdruck verlangsamt Antwortweiterleitung">
|
||||
Auf kleineren Maschinen (8 GB) können Agentenrunden so lange dauern, dass der Zusammenführungs-Bucket geleert wird, bevor die Antwort abgeschlossen ist, und die URL als zweite Runde in der Warteschlange landet. Prüfen Sie `memory_pressure` und `ps -o rss -p $(pgrep openclaw-gateway)`; wenn das Gateway über ~500 MB RSS liegt und der Kompressor aktiv ist, schließen Sie andere schwere Prozesse oder wechseln Sie auf einen größeren Host.
|
||||
</Accordion>
|
||||
<Accordion title="Reply-Quote-Sendungen sind ein anderer Pfad">
|
||||
Wenn der Benutzer `Dump` als **Antwort** auf eine vorhandene URL-Blase angetippt hat (iMessage zeigt ein „1 Reply“-Badge auf der Dump-Blase), befindet sich die URL in `replyToBody`, nicht in einem zweiten Webhook. Zusammenführung greift hier nicht - das ist ein Skill-/Prompt-Thema, kein Debouncer-Thema.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Block-Streaming
|
||||
|
||||
Steuern Sie, ob Antworten als einzelne Nachricht gesendet oder in Blöcken gestreamt werden:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Medien + Limits
|
||||
|
||||
- Eingehende Anhänge werden heruntergeladen und im Mediencache gespeichert.
|
||||
- Medienlimit über `channels.bluebubbles.mediaMaxMb` für eingehende und ausgehende Medien (Standard: 8 MB).
|
||||
- Ausgehender Text wird auf `channels.bluebubbles.textChunkLimit` aufgeteilt (Standard: 4000 Zeichen).
|
||||
|
||||
## Konfigurationsreferenz
|
||||
|
||||
Vollständige Konfiguration: [Konfiguration](/de/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Verbindung und Webhook">
|
||||
- `channels.bluebubbles.enabled`: Kanal aktivieren/deaktivieren.
|
||||
- `channels.bluebubbles.serverUrl`: Basis-URL der BlueBubbles REST API.
|
||||
- `channels.bluebubbles.password`: API-Passwort.
|
||||
- `channels.bluebubbles.webhookPath`: Pfad des Webhook-Endpunkts (Standard: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Zugriffsrichtlinie">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (Standard: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: DM-Zulassungsliste (Handles, E-Mails, E.164-Nummern, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (Standard: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Zulassungsliste für Gruppensender.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Unter macOS optional unbenannte Gruppenteilnehmer nach erfolgreichem Gating aus lokalen Kontakten anreichern. Standard: `false`.
|
||||
- `channels.bluebubbles.groups`: Konfiguration pro Gruppe (`requireMention` usw.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Zustellung und Chunking">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Lesebestätigungen senden (Standard: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Block-Streaming aktivieren (Standard: `false`; für Streaming-Antworten erforderlich).
|
||||
- `channels.bluebubbles.textChunkLimit`: Größe ausgehender Chunks in Zeichen (Standard: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Timeout pro Anfrage in ms für ausgehende Textsendungen über `/api/v1/message/text` (Standard: 30000). Erhöhen Sie den Wert bei macOS-26-Setups, bei denen Private-API-iMessage-Sendungen innerhalb des iMessage-Frameworks für 60+ Sekunden hängen bleiben können, zum Beispiel `45000` oder `60000`. Probes, Chat-Lookups, Reaktionen, Bearbeitungen und Health Checks behalten derzeit den kürzeren 10-s-Standard bei; eine Ausweitung auf Reaktionen und Bearbeitungen ist als Folgearbeit geplant. Überschreibung pro Konto: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (Standard) teilt nur bei Überschreitung von `textChunkLimit`; `newline` teilt vor dem längenbasierten Chunking an Leerzeilen (Absatzgrenzen).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Medien und Verlauf">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Obergrenze für eingehende/ausgehende Medien in MB (Standard: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Explizite Zulassungsliste absoluter lokaler Verzeichnisse, die für ausgehende lokale Medienpfade erlaubt sind. Sendungen über lokale Pfade werden standardmäßig verweigert, sofern dies nicht konfiguriert ist. Überschreibung pro Konto: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Aufeinanderfolgende DM-Webhooks desselben Absenders zu einem Agent-Turn zusammenführen, sodass Apples Text+URL-Split-Send als einzelne Nachricht ankommt (Standard: `false`). Siehe [Split-Send-DMs zusammenführen](#coalescing-split-send-dms-command--url-in-one-composition) für Szenarien, Fenster-Tuning und Kompromisse. Erweitert bei Aktivierung ohne explizites `messages.inbound.byChannel.bluebubbles` das standardmäßige eingehende Debounce-Fenster von 500 ms auf 2500 ms.
|
||||
- `channels.bluebubbles.historyLimit`: Maximale Anzahl von Gruppennachrichten für Kontext (0 deaktiviert).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM-Verlaufslimit.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Wenn eine eingehende Antwort ohne `replyToBody`/`replyToSender` ankommt und der In-Memory-Reply-Context-Cache nicht trifft, die ursprüngliche Nachricht als Best-Effort-Fallback aus der BlueBubbles HTTP API abrufen (Standard: `false`). Nützlich für Multi-Instanz-Deployments, die ein BlueBubbles-Konto gemeinsam nutzen, nach Prozessneustarts oder nach Eviction aus langlebigen TTL/LRU-Caches. Der Abruf ist durch dieselbe Richtlinie wie jede andere BlueBubbles-Client-Anfrage gegen SSRF geschützt, wirft nie eine Ausnahme und befüllt den Cache, sodass sich nachfolgende Antworten amortisieren. Überschreibung pro Konto: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Eine Einstellung auf Kanalebene wird an Konten weitergegeben, die das Flag auslassen.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Aktionen und Konten">
|
||||
- `channels.bluebubbles.actions`: Bestimmte Aktionen aktivieren/deaktivieren.
|
||||
- `channels.bluebubbles.accounts`: Multi-Konto-Konfiguration.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Zugehörige globale Optionen:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (oder `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Adressierung / Zustellziele
|
||||
|
||||
Bevorzugen Sie `chat_guid` für stabiles Routing:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (für Gruppen bevorzugt)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Direkte Handles: `+15555550123`, `user@example.com`
|
||||
- Wenn ein direkter Handle keinen bestehenden DM-Chat hat, erstellt OpenClaw über `POST /api/v1/chat/new` einen. Dafür muss die BlueBubbles Private API aktiviert sein.
|
||||
|
||||
### iMessage- vs. SMS-Routing
|
||||
|
||||
Wenn derselbe Handle auf dem Mac sowohl einen iMessage- als auch einen SMS-Chat hat (zum Beispiel eine Telefonnummer, die für iMessage registriert ist, aber auch Fallbacks mit grüner Sprechblase empfangen hat), bevorzugt OpenClaw den iMessage-Chat und stuft niemals stillschweigend auf SMS zurück. Um den SMS-Chat zu erzwingen, verwenden Sie ein explizites `sms:`-Zielpräfix (zum Beispiel `sms:+15555550123`). Handles ohne passenden iMessage-Chat senden weiterhin über den Chat, den BlueBubbles meldet.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- Webhook-Anfragen werden authentifiziert, indem `guid`/`password`-Query-Parameter oder -Header mit `channels.bluebubbles.password` verglichen werden.
|
||||
- Halten Sie das API-Passwort und den Webhook-Endpunkt geheim (behandeln Sie sie wie Zugangsdaten).
|
||||
- Für die BlueBubbles-Webhook-Authentifizierung gibt es keine localhost-Umgehung. Wenn Sie Webhook-Datenverkehr proxien, behalten Sie das BlueBubbles-Passwort End-to-End in der Anfrage. `gateway.trustedProxies` ersetzt hier nicht `channels.bluebubbles.password`. Siehe [Gateway-Sicherheit](/de/gateway/security#reverse-proxy-configuration).
|
||||
- Aktivieren Sie HTTPS + Firewall-Regeln auf dem BlueBubbles-Server, wenn Sie ihn außerhalb Ihres LAN bereitstellen.
|
||||
|
||||
## Fehlerbehebung
|
||||
|
||||
- Wenn Tipp-/Leseereignisse nicht mehr funktionieren, prüfen Sie die BlueBubbles-Webhook-Protokolle und verifizieren Sie, dass der Gateway-Pfad `channels.bluebubbles.webhookPath` entspricht.
|
||||
- Pairing-Codes laufen nach einer Stunde ab; verwenden Sie `openclaw pairing list bluebubbles` und `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reaktionen erfordern die BlueBubbles Private API (`POST /api/v1/message/react`); stellen Sie sicher, dass die Serverversion sie bereitstellt.
|
||||
- Bearbeiten/Zurückrufen erfordert macOS 13+ und eine kompatible BlueBubbles-Serverversion. Unter macOS 26 (Tahoe) ist Bearbeiten derzeit aufgrund von Änderungen an der Private API defekt.
|
||||
- Aktualisierungen von Gruppensymbolen können unter macOS 26 (Tahoe) unzuverlässig sein: Die API kann Erfolg zurückgeben, aber das neue Symbol wird nicht synchronisiert.
|
||||
- OpenClaw blendet bekannte defekte Aktionen basierend auf der macOS-Version des BlueBubbles-Servers automatisch aus. Wenn Bearbeiten unter macOS 26 (Tahoe) weiterhin erscheint, deaktivieren Sie es manuell mit `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` ist aktiviert, aber Split-Sends (z. B. `Dump` + URL) kommen weiterhin als zwei Turns an: siehe die [Fehlerbehebungs-Checkliste zur Split-Send-Zusammenführung](#split-send-coalescing-troubleshooting) - häufige Ursachen sind ein zu enges Debounce-Fenster, Session-Log-Zeitstempel, die fälschlich als Webhook-Ankunft gelesen werden, oder ein Senden mit Antwortzitat (das `replyToBody` verwendet, nicht einen zweiten Webhook).
|
||||
- Für Status-/Health-Informationen: `openclaw status --all` oder `openclaw status --deep`.
|
||||
|
||||
Eine allgemeine Referenz zum Kanal-Workflow finden Sie unter [Kanäle](/de/channels) und im Leitfaden [Plugins](/de/tools/plugin).
|
||||
|
||||
## Zugehörig
|
||||
|
||||
- [Kanal-Routing](/de/channels/channel-routing) - Session-Routing für Nachrichten
|
||||
- [Kanäle: Übersicht](/de/channels) - alle unterstützten Kanäle
|
||||
- [Gruppen](/de/channels/groups) - Gruppenchatverhalten und Mention-Gating
|
||||
- [Pairing](/de/channels/pairing) - DM-Authentifizierung und Pairing-Ablauf
|
||||
- [Sicherheit](/de/gateway/security) - Zugriffsmodell und Härtung
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Sie installieren, konfigurieren oder prüfen das bluebubbles-Plugin
|
||||
summary: Fügt die BlueBubbles-Kanaloberfläche zum Senden und Empfangen von OpenClaw-Nachrichten hinzu.
|
||||
title: BlueBubbles-Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T06:40:39Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles-Plugin
|
||||
|
||||
Fügt die BlueBubbles-Kanaloberfläche zum Senden und Empfangen von OpenClaw-Nachrichten hinzu.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Paket: `@openclaw/bluebubbles`
|
||||
- Installationsweg: npm; ClawHub
|
||||
|
||||
## Oberfläche
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Zugehörige Dokumentation
|
||||
|
||||
- [bluebubbles](/de/channels/bluebubbles)
|
||||
@ -1072,7 +1072,6 @@
|
||||
"channels/msteams",
|
||||
"channels/googlechat",
|
||||
"channels/imessage",
|
||||
"channels/bluebubbles",
|
||||
"channels/matrix",
|
||||
"channels/matrix-migration",
|
||||
"channels/matrix-push-rules"
|
||||
@ -1931,7 +1930,6 @@
|
||||
{
|
||||
"group": "消息平台",
|
||||
"pages": [
|
||||
"zh-CN/channels/bluebubbles",
|
||||
"zh-CN/channels/discord",
|
||||
"zh-CN/channels/feishu",
|
||||
"zh-CN/channels/grammy",
|
||||
@ -2566,7 +2564,6 @@
|
||||
"zh-TW/channels/msteams",
|
||||
"zh-TW/channels/googlechat",
|
||||
"zh-TW/channels/imessage",
|
||||
"zh-TW/channels/bluebubbles",
|
||||
"zh-TW/channels/matrix",
|
||||
"zh-TW/channels/matrix-migration",
|
||||
"zh-TW/channels/matrix-push-rules"
|
||||
@ -3445,7 +3442,6 @@
|
||||
"ja-JP/channels/msteams",
|
||||
"ja-JP/channels/googlechat",
|
||||
"ja-JP/channels/imessage",
|
||||
"ja-JP/channels/bluebubbles",
|
||||
"ja-JP/channels/matrix",
|
||||
"ja-JP/channels/matrix-migration",
|
||||
"ja-JP/channels/matrix-push-rules"
|
||||
@ -4324,7 +4320,6 @@
|
||||
"es/channels/msteams",
|
||||
"es/channels/googlechat",
|
||||
"es/channels/imessage",
|
||||
"es/channels/bluebubbles",
|
||||
"es/channels/matrix",
|
||||
"es/channels/matrix-migration",
|
||||
"es/channels/matrix-push-rules"
|
||||
@ -5203,7 +5198,6 @@
|
||||
"pt-BR/channels/msteams",
|
||||
"pt-BR/channels/googlechat",
|
||||
"pt-BR/channels/imessage",
|
||||
"pt-BR/channels/bluebubbles",
|
||||
"pt-BR/channels/matrix",
|
||||
"pt-BR/channels/matrix-migration",
|
||||
"pt-BR/channels/matrix-push-rules"
|
||||
@ -6082,7 +6076,6 @@
|
||||
"ko/channels/msteams",
|
||||
"ko/channels/googlechat",
|
||||
"ko/channels/imessage",
|
||||
"ko/channels/bluebubbles",
|
||||
"ko/channels/matrix",
|
||||
"ko/channels/matrix-migration",
|
||||
"ko/channels/matrix-push-rules"
|
||||
@ -6961,7 +6954,6 @@
|
||||
"de/channels/msteams",
|
||||
"de/channels/googlechat",
|
||||
"de/channels/imessage",
|
||||
"de/channels/bluebubbles",
|
||||
"de/channels/matrix",
|
||||
"de/channels/matrix-migration",
|
||||
"de/channels/matrix-push-rules"
|
||||
@ -7840,7 +7832,6 @@
|
||||
"fr/channels/msteams",
|
||||
"fr/channels/googlechat",
|
||||
"fr/channels/imessage",
|
||||
"fr/channels/bluebubbles",
|
||||
"fr/channels/matrix",
|
||||
"fr/channels/matrix-migration",
|
||||
"fr/channels/matrix-push-rules"
|
||||
@ -8719,7 +8710,6 @@
|
||||
"ar/channels/msteams",
|
||||
"ar/channels/googlechat",
|
||||
"ar/channels/imessage",
|
||||
"ar/channels/bluebubbles",
|
||||
"ar/channels/matrix",
|
||||
"ar/channels/matrix-migration",
|
||||
"ar/channels/matrix-push-rules"
|
||||
@ -9598,7 +9588,6 @@
|
||||
"it/channels/msteams",
|
||||
"it/channels/googlechat",
|
||||
"it/channels/imessage",
|
||||
"it/channels/bluebubbles",
|
||||
"it/channels/matrix",
|
||||
"it/channels/matrix-migration",
|
||||
"it/channels/matrix-push-rules"
|
||||
@ -10477,7 +10466,6 @@
|
||||
"vi/channels/msteams",
|
||||
"vi/channels/googlechat",
|
||||
"vi/channels/imessage",
|
||||
"vi/channels/bluebubbles",
|
||||
"vi/channels/matrix",
|
||||
"vi/channels/matrix-migration",
|
||||
"vi/channels/matrix-push-rules"
|
||||
@ -11356,7 +11344,6 @@
|
||||
"nl/channels/msteams",
|
||||
"nl/channels/googlechat",
|
||||
"nl/channels/imessage",
|
||||
"nl/channels/bluebubbles",
|
||||
"nl/channels/matrix",
|
||||
"nl/channels/matrix-migration",
|
||||
"nl/channels/matrix-push-rules"
|
||||
@ -12235,7 +12222,6 @@
|
||||
"tr/channels/msteams",
|
||||
"tr/channels/googlechat",
|
||||
"tr/channels/imessage",
|
||||
"tr/channels/bluebubbles",
|
||||
"tr/channels/matrix",
|
||||
"tr/channels/matrix-migration",
|
||||
"tr/channels/matrix-push-rules"
|
||||
@ -13114,7 +13100,6 @@
|
||||
"uk/channels/msteams",
|
||||
"uk/channels/googlechat",
|
||||
"uk/channels/imessage",
|
||||
"uk/channels/bluebubbles",
|
||||
"uk/channels/matrix",
|
||||
"uk/channels/matrix-migration",
|
||||
"uk/channels/matrix-push-rules"
|
||||
@ -13993,7 +13978,6 @@
|
||||
"id/channels/msteams",
|
||||
"id/channels/googlechat",
|
||||
"id/channels/imessage",
|
||||
"id/channels/bluebubbles",
|
||||
"id/channels/matrix",
|
||||
"id/channels/matrix-migration",
|
||||
"id/channels/matrix-push-rules"
|
||||
@ -14872,7 +14856,6 @@
|
||||
"pl/channels/msteams",
|
||||
"pl/channels/googlechat",
|
||||
"pl/channels/imessage",
|
||||
"pl/channels/bluebubbles",
|
||||
"pl/channels/matrix",
|
||||
"pl/channels/matrix-migration",
|
||||
"pl/channels/matrix-push-rules"
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Configuración del canal de BlueBubbles
|
||||
- Solución de problemas del emparejamiento de Webhook
|
||||
- Configuración de iMessage en macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Compatibilidad heredada con iMessage mediante el servidor de macOS BlueBubbles (envío/recepción REST, escritura, reacciones, emparejamiento, acciones avanzadas).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:49Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Estado: Plugin heredado incluido que se comunica con el servidor macOS de BlueBubbles por HTTP. Las configuraciones existentes de BlueBubbles siguen funcionando, pero las nuevas implementaciones de OpenClaw iMessage deberían preferir el Plugin nativo [iMessage](/es/channels/imessage) cuando sus requisitos encajen con tu host.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles está obsoleto para nuevas configuraciones de OpenClaw.
|
||||
|
||||
El ecosistema upstream de BlueBubbles sigue activo, pero OpenClaw depende de la API del servidor macOS de BlueBubbles. Al 6 de mayo de 2026, la rama de desarrollo oficial de [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) cambió por última vez el [22 de enero de 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), y la versión más reciente del servidor ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) se publicó el 16 de mayo de 2025. La aplicación cliente y los repositorios auxiliares tienen actividad más reciente, así que esto no es una afirmación de abandono; la obsolescencia trata de reducir la dependencia de OpenClaw de un servidor HTTP externo, webhooks y la superficie de compatibilidad de APIs privadas cuando la ruta nativa `imsg` mantiene la integración en un contrato stdio local.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Las versiones actuales de OpenClaw incluyen BlueBubbles, así que las compilaciones empaquetadas normales no necesitan un paso separado de `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Descripción general
|
||||
|
||||
- Se ejecuta en macOS mediante la aplicación auxiliar de BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Recurso heredado para instalaciones que ya dependen de IDs de canal de BlueBubbles, estado de Webhook, destinos de grupo, entrega con Cron o enrutamiento de espacios de trabajo.
|
||||
- Recomendado/probado: macOS Sequoia (15). macOS Tahoe (26) funciona; la edición está rota actualmente en Tahoe, y las actualizaciones de iconos de grupo pueden informar éxito pero no sincronizarse.
|
||||
- OpenClaw se comunica con él mediante su API REST (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Los mensajes entrantes llegan mediante webhooks; las respuestas salientes, indicadores de escritura, confirmaciones de lectura y tapbacks son llamadas REST.
|
||||
- Los adjuntos y stickers se ingieren como medios entrantes (y se exponen al agente cuando es posible).
|
||||
- Las respuestas Auto-TTS que sintetizan audio MP3 o CAF se entregan como burbujas de nota de voz de iMessage en lugar de adjuntos de archivo normales.
|
||||
- El emparejamiento/lista de permitidos funciona igual que en otros canales (`/channels/pairing` etc.) con `channels.bluebubbles.allowFrom` + códigos de emparejamiento.
|
||||
- Las reacciones se exponen como eventos del sistema igual que en Slack/Telegram para que los agentes puedan "mencionarlas" antes de responder.
|
||||
- Funciones avanzadas: editar, anular envío, respuestas en hilos, efectos de mensaje, gestión de grupos.
|
||||
|
||||
## Inicio rápido
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
Instala el servidor BlueBubbles en tu Mac (sigue las instrucciones en [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
En la configuración de BlueBubbles, habilita la API web y establece una contraseña.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
Ejecuta `openclaw onboard` y selecciona BlueBubbles, o configúralo manualmente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
Apunta los webhooks de BlueBubbles a tu Gateway (ejemplo: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Inicia el Gateway; registrará el manejador de Webhook y comenzará el emparejamiento.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Seguridad**
|
||||
|
||||
- Establece siempre una contraseña de Webhook.
|
||||
- La autenticación de Webhook siempre es obligatoria. OpenClaw rechaza las solicitudes de Webhook de BlueBubbles a menos que incluyan una contraseña/guid que coincida con `channels.bluebubbles.password` (por ejemplo, `?password=<password>` o `x-password`), independientemente de la topología de local loopback/proxy.
|
||||
- La autenticación por contraseña se verifica antes de leer/analizar los cuerpos completos de Webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Mantener Messages.app activo (configuraciones con VM / sin interfaz gráfica)
|
||||
|
||||
Algunas configuraciones de VM de macOS / siempre activas pueden terminar con Messages.app en estado "inactivo" (los eventos entrantes se detienen hasta que la app se abre/pasa a primer plano). Una solución sencilla es **estimular Messages cada 5 minutos** usando un AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Guarda esto como `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Guarda esto como `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Esto se ejecuta **cada 300 segundos** y **al iniciar sesión**. La primera ejecución puede activar solicitudes de **Automatización** de macOS (`osascript` → Messages). Apruébalas en la misma sesión de usuario que ejecuta el LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles está disponible en el onboarding interactivo:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
El asistente solicita:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Dirección del servidor BlueBubbles (p. ej., `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Contraseña de API desde la configuración de BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Ruta del endpoint de Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` o `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Números de teléfono, correos electrónicos o destinos de chat.
|
||||
</ParamField>
|
||||
|
||||
También puedes agregar BlueBubbles mediante la CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Control de acceso (DMs + grupos)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Predeterminado: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Los remitentes desconocidos reciben un código de emparejamiento; los mensajes se ignoran hasta que se aprueban (los códigos vencen después de 1 hora).
|
||||
- Aprueba mediante:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- El emparejamiento es el intercambio de token predeterminado. Detalles: [Emparejamiento](/es/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (predeterminado: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` controla quién puede activar en grupos cuando `allowlist` está establecido.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Enriquecimiento de nombres de contacto (macOS, opcional)
|
||||
|
||||
Los webhooks de grupo de BlueBubbles a menudo solo incluyen direcciones sin procesar de participantes. Si quieres que el contexto `GroupMembers` muestre nombres de contactos locales en su lugar, puedes habilitar el enriquecimiento local de Contactos en macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` habilita la búsqueda. Predeterminado: `false`.
|
||||
- Las búsquedas se ejecutan solo después de que el acceso al grupo, la autorización de comandos y la compuerta de menciones hayan permitido pasar el mensaje.
|
||||
- Solo se enriquecen los participantes telefónicos sin nombre.
|
||||
- Los números de teléfono sin procesar permanecen como respaldo cuando no se encuentra ninguna coincidencia local.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Compuerta de menciones (grupos)
|
||||
|
||||
BlueBubbles admite compuerta de menciones para chats de grupo, coincidiendo con el comportamiento de iMessage/WhatsApp:
|
||||
|
||||
- Usa `agents.list[].groupChat.mentionPatterns` (o `messages.groupChat.mentionPatterns`) para detectar menciones.
|
||||
- Cuando `requireMention` está habilitado para un grupo, el agente solo responde cuando se lo menciona.
|
||||
- Los comandos de control de remitentes autorizados omiten la compuerta de menciones.
|
||||
|
||||
Configuración por grupo:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Compuerta de comandos
|
||||
|
||||
- Los comandos de control (p. ej., `/config`, `/model`) requieren autorización.
|
||||
- Usa `allowFrom` y `groupAllowFrom` para determinar la autorización de comandos.
|
||||
- Los remitentes autorizados pueden ejecutar comandos de control incluso sin mencionar en grupos.
|
||||
|
||||
### Prompt de sistema por grupo
|
||||
|
||||
Cada entrada bajo `channels.bluebubbles.groups.*` acepta una cadena `systemPrompt` opcional. El valor se inyecta en el prompt de sistema del agente en cada turno que maneja un mensaje en ese grupo, para que puedas establecer reglas de personalidad o comportamiento por grupo sin editar los prompts del agente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
La clave coincide con lo que BlueBubbles informe como `chatGuid` / `chatIdentifier` / `chatId` numérico para el grupo, y una entrada comodín `"*"` proporciona un valor predeterminado para cada grupo sin una coincidencia exacta (el mismo patrón usado por `requireMention` y las políticas de herramientas por grupo). Las coincidencias exactas siempre prevalecen sobre el comodín. Los DMs ignoran este campo; usa personalización de prompts a nivel de agente o de cuenta en su lugar.
|
||||
|
||||
#### Ejemplo trabajado: respuestas en hilos y reacciones tapback (API privada)
|
||||
|
||||
Con la API privada de BlueBubbles habilitada, los mensajes entrantes llegan con IDs de mensaje cortos (por ejemplo `[[reply_to:5]]`) y el agente puede llamar a `action=reply` para responder en hilo a un mensaje específico o `action=react` para dejar un tapback. Un `systemPrompt` por grupo es una forma fiable de mantener al agente eligiendo la herramienta correcta:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tanto las reacciones tapback como las respuestas en hilos requieren la API privada de BlueBubbles; consulta [Acciones avanzadas](#advanced-actions) e [IDs de mensaje](#message-ids-short-vs-full) para ver la mecánica subyacente.
|
||||
|
||||
## Enlaces de conversación ACP
|
||||
|
||||
Los chats de BlueBubbles pueden convertirse en espacios de trabajo ACP duraderos sin cambiar la capa de transporte.
|
||||
|
||||
Flujo rápido para operadores:
|
||||
|
||||
- Ejecuta `/acp spawn codex --bind here` dentro del DM o chat de grupo permitido.
|
||||
- Los mensajes futuros en esa misma conversación de BlueBubbles se enrutan a la sesión ACP creada.
|
||||
- `/new` y `/reset` restablecen la misma sesión ACP vinculada en el lugar.
|
||||
- `/acp close` cierra la sesión ACP y elimina el enlace.
|
||||
|
||||
También se admiten enlaces persistentes configurados mediante entradas de nivel superior `bindings[]` con `type: "acp"` y `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` puede usar cualquier forma de destino admitida de BlueBubbles:
|
||||
|
||||
- identificador de DM normalizado, como `+15555550123` o `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Para enlaces de grupo estables, prefiere `chat_id:*` o `chat_identifier:*`.
|
||||
|
||||
Ejemplo:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Consulta [agentes ACP](/es/tools/acp-agents) para ver el comportamiento compartido de enlaces ACP.
|
||||
|
||||
## Indicadores de escritura + confirmaciones de lectura
|
||||
|
||||
- **Indicadores de escritura**: Se envían automáticamente antes y durante la generación de la respuesta.
|
||||
- **Confirmaciones de lectura**: Controladas por `channels.bluebubbles.sendReadReceipts` (valor predeterminado: `true`).
|
||||
- **Indicadores de escritura**: OpenClaw envía eventos de inicio de escritura; BlueBubbles borra la escritura automáticamente al enviar o al agotar el tiempo de espera (la detención manual mediante DELETE no es fiable).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Acciones avanzadas
|
||||
|
||||
BlueBubbles admite acciones avanzadas de mensajes cuando están habilitadas en la configuración:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**: Añade o elimina reacciones tapback (`messageId`, `emoji`, `remove`). El conjunto de tapbacks nativo de iMessage es `love`, `like`, `dislike`, `laugh`, `emphasize` y `question`. Cuando un agente elige un emoji fuera de ese conjunto (por ejemplo, `👀`), la herramienta de reacción recurre a `love` para que el tapback se renderice de todos modos en lugar de hacer fallar toda la solicitud. Las reacciones de confirmación configuradas siguen validándose estrictamente y dan error con valores desconocidos.
|
||||
- **edit**: Edita un mensaje enviado (`messageId`, `text`).
|
||||
- **unsend**: Anula el envío de un mensaje (`messageId`).
|
||||
- **reply**: Responde a un mensaje específico (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Envía con efecto de iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Cambia el nombre de un chat de grupo (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Establece el icono/foto de un chat de grupo (`chatGuid`, `media`): inestable en macOS 26 Tahoe (la API puede devolver éxito, pero el icono no se sincroniza).
|
||||
- **addParticipant**: Añade a alguien a un grupo (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Elimina a alguien de un grupo (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Sale de un chat de grupo (`chatGuid`).
|
||||
- **upload-file**: Envía medios/archivos (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Notas de voz: establece `asVoice: true` con audio **MP3** o **CAF** para enviar como mensaje de voz de iMessage. BlueBubbles convierte MP3 → CAF al enviar notas de voz.
|
||||
- Alias heredado: `sendAttachment` sigue funcionando, pero `upload-file` es el nombre de acción canónico.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID de mensaje (corto frente a completo)
|
||||
|
||||
OpenClaw puede mostrar ID de mensaje _cortos_ (por ejemplo, `1`, `2`) para ahorrar tokens.
|
||||
|
||||
- `MessageSid` / `ReplyToId` pueden ser ID cortos.
|
||||
- `MessageSidFull` / `ReplyToIdFull` contienen los ID completos del proveedor.
|
||||
- Los ID cortos están en memoria; pueden caducar al reiniciar o al expulsarse de la caché.
|
||||
- Las acciones aceptan `messageId` corto o completo, pero los ID cortos darán error si ya no están disponibles.
|
||||
|
||||
Usa ID completos para automatizaciones y almacenamiento duraderos:
|
||||
|
||||
- Plantillas: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Contexto: `MessageSidFull` / `ReplyToIdFull` en cargas entrantes
|
||||
|
||||
Consulta [configuración](/es/gateway/configuration) para ver las variables de plantilla.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Fusión de DM de envío dividido (comando + URL en una sola composición)
|
||||
|
||||
Cuando un usuario escribe un comando y una URL juntos en iMessage, por ejemplo `Dump https://example.com/article`, Apple divide el envío en **dos entregas de webhook separadas**:
|
||||
|
||||
1. Un mensaje de texto (`"Dump"`).
|
||||
2. Un globo de vista previa de URL (`"https://..."`) con imágenes de vista previa OG como adjuntos.
|
||||
|
||||
Los dos webhooks llegan a OpenClaw con una diferencia de ~0,8-2,0 s en la mayoría de las configuraciones. Sin fusión, el agente recibe solo el comando en el turno 1, responde (a menudo "envíame la URL") y solo ve la URL en el turno 2, momento en el que el contexto del comando ya se perdió.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` opta por fusionar webhooks consecutivos del mismo remitente en un DM en un único turno del agente. Los chats de grupo siguen indexándose por mensaje, de modo que se preserva la estructura de turnos de varios usuarios.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
Habilita cuando:
|
||||
|
||||
- Envías skills que esperan `command + payload` en un solo mensaje (dump, paste, save, queue, etc.).
|
||||
- Tus usuarios pegan URL, imágenes o contenido largo junto con comandos.
|
||||
- Puedes aceptar la latencia añadida en el turno de DM (ver abajo).
|
||||
|
||||
Deja deshabilitado cuando:
|
||||
|
||||
- Necesitas latencia mínima de comando para activadores de DM de una sola palabra.
|
||||
- Todos tus flujos son comandos de una sola ejecución sin seguimientos de carga útil.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Con la marca activada y sin `messages.inbound.byChannel.bluebubbles` explícito, la ventana de debounce se amplía a **2500 ms** (el valor predeterminado sin fusión es 500 ms). La ventana más amplia es necesaria: la cadencia de envío dividido de Apple de 0,8-2,0 s no cabe en el valor predeterminado más ajustado.
|
||||
|
||||
Para ajustar la ventana tú mismo:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **Latencia añadida para comandos de control por DM.** Con la marca activada, los mensajes de comandos de control por DM (como `Dump`, `Save`, etc.) ahora esperan hasta la ventana de debounce antes de despacharse, por si llega un webhook de carga útil. Los comandos de chat de grupo mantienen el despacho instantáneo.
|
||||
- **La salida fusionada está acotada**: el texto fusionado se limita a 4000 caracteres con un marcador explícito `…[truncated]`; los adjuntos se limitan a 20; las entradas de origen se limitan a 10 (se conserva la primera más la más reciente más allá de eso). Cada `messageId` de origen sigue llegando a la deduplicación de entrada, de modo que una repetición posterior de MessagePoller de cualquier evento individual se reconoce como duplicado.
|
||||
- **Opt-in, por canal.** Otros canales (Telegram, WhatsApp, Slack, …) no se ven afectados.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Escenarios y lo que ve el agente
|
||||
|
||||
| El usuario compone | Apple entrega | Marca desactivada (predeterminado) | Marca activada + ventana de 2500 ms |
|
||||
| ------------------------------------------------------------------ | ----------------------------- | -------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (un envío) | 2 webhooks separados ~1 s | Dos turnos del agente: solo "Dump", luego URL | Un turno: texto fusionado `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (adjunto + texto) | 2 webhooks | Dos turnos | Un turno: texto + imagen |
|
||||
| `/status` (comando independiente) | 1 webhook | Despacho instantáneo | **Espera hasta la ventana y luego despacha** |
|
||||
| URL pegada sola | 1 webhook | Despacho instantáneo | Despacho instantáneo (solo una entrada en el bucket) |
|
||||
| Texto + URL enviados como dos mensajes separados deliberados, con minutos de diferencia | 2 webhooks fuera de la ventana | Dos turnos | Dos turnos (la ventana caduca entre ellos) |
|
||||
| Ráfaga rápida (>10 DM pequeños dentro de la ventana) | N webhooks | N turnos | Un turno, salida acotada (primero + último, límites de texto/adjuntos aplicados) |
|
||||
|
||||
### Solución de problemas de fusión de envío dividido
|
||||
|
||||
Si la marca está activada y los envíos divididos siguen llegando como dos turnos, revisa cada capa:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Luego `openclaw gateway restart`: la marca se lee al crear el registro de debouncers.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
Mira el registro del servidor BlueBubbles en `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Mide la separación entre el despacho de texto estilo `"Dump"` y el despacho siguiente de `"https://..."; Attachments:`. Aumenta `messages.inbound.byChannel.bluebubbles` para cubrir cómodamente esa separación.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
Las marcas de tiempo de eventos de sesión (`~/.openclaw/agents/<id>/sessions/*.jsonl`) reflejan cuándo el Gateway entrega un mensaje al agente, **no** cuándo llegó el webhook. Un segundo mensaje en cola etiquetado como `[Queued messages while agent was busy]` significa que el primer turno seguía ejecutándose cuando llegó el segundo webhook: el bucket de fusión ya se había vaciado. Ajusta la ventana contra el registro del servidor BB, no contra el registro de sesión.
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
En máquinas más pequeñas (8 GB), los turnos del agente pueden tardar lo suficiente como para que el bucket de fusión se vacíe antes de que la respuesta termine, y la URL llegue como un segundo turno en cola. Revisa `memory_pressure` y `ps -o rss -p $(pgrep openclaw-gateway)`; si el Gateway supera ~500 MB RSS y el compresor está activo, cierra otros procesos pesados o cambia a un host más grande.
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
Si el usuario tocó `Dump` como **respuesta** a un globo de URL existente (iMessage muestra una insignia "1 Reply" en el globo de Dump), la URL vive en `replyToBody`, no en un segundo webhook. La fusión no aplica: eso es asunto de skill/prompt, no del debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Streaming por bloques
|
||||
|
||||
Controla si las respuestas se envían como un solo mensaje o se transmiten en bloques:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Medios + límites
|
||||
|
||||
- Los adjuntos entrantes se descargan y se almacenan en la caché de medios.
|
||||
- Límite de medios mediante `channels.bluebubbles.mediaMaxMb` para medios entrantes y salientes (valor predeterminado: 8 MB).
|
||||
- El texto saliente se divide en fragmentos hasta `channels.bluebubbles.textChunkLimit` (valor predeterminado: 4000 caracteres).
|
||||
|
||||
## Referencia de configuración
|
||||
|
||||
Configuración completa: [configuración](/es/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Conexión y Webhook">
|
||||
- `channels.bluebubbles.enabled`: Habilita/deshabilita el canal.
|
||||
- `channels.bluebubbles.serverUrl`: URL base de la API REST de BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Contraseña de la API.
|
||||
- `channels.bluebubbles.webhookPath`: Ruta del endpoint de Webhook (predeterminado: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Política de acceso">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (predeterminado: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Lista de permitidos de DM (identificadores, correos electrónicos, números E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (predeterminado: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Lista de permitidos de remitentes de grupo.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: En macOS, opcionalmente enriquece los participantes de grupo sin nombre desde Contactos locales después de pasar el control de acceso. Predeterminado: `false`.
|
||||
- `channels.bluebubbles.groups`: Configuración por grupo (`requireMention`, etc.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Entrega y fragmentación">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Envía confirmaciones de lectura (predeterminado: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Habilita el streaming de bloques (predeterminado: `false`; requerido para respuestas en streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Tamaño de fragmento saliente en caracteres (predeterminado: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Tiempo de espera por solicitud en ms para envíos de texto salientes mediante `/api/v1/message/text` (predeterminado: 30000). Auméntalo en configuraciones de macOS 26 donde los envíos de iMessage con Private API pueden quedarse bloqueados durante más de 60 segundos dentro del framework de iMessage; por ejemplo `45000` o `60000`. Las sondas, búsquedas de chats, reacciones, ediciones y comprobaciones de salud actualmente conservan el valor predeterminado más corto de 10 s; ampliar la cobertura a reacciones y ediciones está previsto como seguimiento. Anulación por cuenta: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (predeterminado) divide solo cuando se supera `textChunkLimit`; `newline` divide en líneas en blanco (límites de párrafo) antes de la fragmentación por longitud.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Medios e historial">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Límite de medios entrantes/salientes en MB (predeterminado: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Lista de permitidos explícita de directorios locales absolutos permitidos para rutas de medios locales salientes. Los envíos de rutas locales se deniegan de forma predeterminada salvo que esto esté configurado. Anulación por cuenta: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Fusiona Webhooks de DM consecutivos del mismo remitente en un solo turno del agente para que el envío dividido de texto+URL de Apple llegue como un único mensaje (predeterminado: `false`). Consulta [Fusión de DM de envío dividido](#coalescing-split-send-dms-command--url-in-one-composition) para ver escenarios, ajuste de ventana y compensaciones. Amplía la ventana de debounce entrante predeterminada de 500 ms a 2500 ms cuando se habilita sin un `messages.inbound.byChannel.bluebubbles` explícito.
|
||||
- `channels.bluebubbles.historyLimit`: Máximo de mensajes de grupo para contexto (0 deshabilita).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Límite de historial de DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Cuando una respuesta entrante llega sin `replyToBody`/`replyToSender` y falla la caché en memoria de contexto de respuesta, obtiene el mensaje original desde la API HTTP de BlueBubbles como alternativa de mejor esfuerzo (predeterminado: `false`). Útil para despliegues de varias instancias que comparten una cuenta de BlueBubbles, después de reinicios de proceso o después de la expulsión de caché TTL/LRU de larga duración. La obtención está protegida contra SSRF por la misma política que cualquier otra solicitud del cliente de BlueBubbles, nunca lanza errores y rellena la caché para que las respuestas posteriores se amorticen. Anulación por cuenta: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Un ajuste a nivel de canal se propaga a las cuentas que omiten la marca.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Acciones y cuentas">
|
||||
- `channels.bluebubbles.actions`: Habilita/deshabilita acciones específicas.
|
||||
- `channels.bluebubbles.accounts`: Configuración multicuenta.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Opciones globales relacionadas:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (o `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Direccionamiento / destinos de entrega
|
||||
|
||||
Prefiere `chat_guid` para un enrutamiento estable:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (preferido para grupos)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Identificadores directos: `+15555550123`, `user@example.com`
|
||||
- Si un identificador directo no tiene un chat de DM existente, OpenClaw creará uno mediante `POST /api/v1/chat/new`. Esto requiere que la Private API de BlueBubbles esté habilitada.
|
||||
|
||||
### Enrutamiento de iMessage frente a SMS
|
||||
|
||||
Cuando el mismo identificador tiene tanto un chat de iMessage como uno de SMS en la Mac (por ejemplo, un número de teléfono que está registrado en iMessage pero también ha recibido alternativas de burbuja verde), OpenClaw prefiere el chat de iMessage y nunca degrada silenciosamente a SMS. Para forzar el chat de SMS, usa un prefijo de destino `sms:` explícito (por ejemplo `sms:+15555550123`). Los identificadores sin un chat de iMessage coincidente siguen enviándose mediante cualquier chat que BlueBubbles informe.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- Las solicitudes de Webhook se autentican comparando los parámetros de consulta o encabezados `guid`/`password` con `channels.bluebubbles.password`.
|
||||
- Mantén en secreto la contraseña de la API y el endpoint de Webhook (trátalos como credenciales).
|
||||
- No hay omisión de localhost para la autenticación de Webhook de BlueBubbles. Si proxyas tráfico de Webhook, conserva la contraseña de BlueBubbles en la solicitud de extremo a extremo. `gateway.trustedProxies` no sustituye a `channels.bluebubbles.password` aquí. Consulta [Seguridad del Gateway](/es/gateway/security#reverse-proxy-configuration).
|
||||
- Habilita HTTPS y reglas de firewall en el servidor de BlueBubbles si lo expones fuera de tu LAN.
|
||||
|
||||
## Solución de problemas
|
||||
|
||||
- Si los eventos de escritura/lectura dejan de funcionar, revisa los logs de Webhook de BlueBubbles y verifica que la ruta del Gateway coincida con `channels.bluebubbles.webhookPath`.
|
||||
- Los códigos de emparejamiento caducan después de una hora; usa `openclaw pairing list bluebubbles` y `openclaw pairing approve bluebubbles <code>`.
|
||||
- Las reacciones requieren la API privada de BlueBubbles (`POST /api/v1/message/react`); asegúrate de que la versión del servidor la exponga.
|
||||
- Editar/deshacer envío requiere macOS 13+ y una versión compatible del servidor de BlueBubbles. En macOS 26 (Tahoe), la edición actualmente no funciona debido a cambios en la API privada.
|
||||
- Las actualizaciones de iconos de grupo pueden ser inestables en macOS 26 (Tahoe): la API puede devolver éxito, pero el nuevo icono no se sincroniza.
|
||||
- OpenClaw oculta automáticamente acciones conocidas como rotas según la versión de macOS del servidor de BlueBubbles. Si la edición aún aparece en macOS 26 (Tahoe), deshabilítala manualmente con `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` habilitado, pero los envíos divididos (p. ej., `Dump` + URL) aún llegan como dos turnos: consulta la lista de comprobación de [solución de problemas de fusión de envío dividido](#split-send-coalescing-troubleshooting); las causas comunes son una ventana de debounce demasiado ajustada, marcas de tiempo del log de sesión mal interpretadas como llegada del Webhook o un envío con cita de respuesta (que usa `replyToBody`, no un segundo Webhook).
|
||||
- Para información de estado/salud: `openclaw status --all` o `openclaw status --deep`.
|
||||
|
||||
Para una referencia general del flujo de trabajo de canales, consulta [Canales](/es/channels) y la guía de [Plugins](/es/tools/plugin).
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Enrutamiento de canales](/es/channels/channel-routing) - enrutamiento de sesiones para mensajes
|
||||
- [Resumen de canales](/es/channels) - todos los canales compatibles
|
||||
- [Grupos](/es/channels/groups) - comportamiento de chat de grupo y control de menciones
|
||||
- [Emparejamiento](/es/channels/pairing) - autenticación de DM y flujo de emparejamiento
|
||||
- [Seguridad](/es/gateway/security) - modelo de acceso y refuerzo
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Está instalando, configurando o auditando el Plugin bluebubbles
|
||||
summary: Añade la superficie de canal BlueBubbles para enviar y recibir mensajes de OpenClaw.
|
||||
title: Plugin de BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T05:30:19Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin de BlueBubbles
|
||||
|
||||
Agrega la superficie del canal BlueBubbles para enviar y recibir mensajes de OpenClaw.
|
||||
|
||||
## Distribución
|
||||
|
||||
- Paquete: `@openclaw/bluebubbles`
|
||||
- Ruta de instalación: npm; ClawHub
|
||||
|
||||
## Superficie
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Documentación relacionada
|
||||
|
||||
- [bluebubbles](/es/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- راهاندازی کانال BlueBubbles
|
||||
- عیبیابی جفتسازی Webhook
|
||||
- پیکربندی iMessage در macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: پشتیبانی قدیمی از iMessage از طریق سرور macOS BlueBubbles (ارسال/دریافت REST، تایپ، واکنشها، جفتسازی، کنشهای پیشرفته).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:57Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: Plugin قدیمیِ همراهشده که از طریق HTTP با سرور BlueBubbles در macOS صحبت میکند. راهاندازیهای موجود BlueBubbles همچنان کار میکنند، اما استقرارهای جدید OpenClaw iMessage باید وقتی الزامات Plugin بومی [iMessage](/fa/channels/imessage) با میزبان شما سازگار است، آن را ترجیح دهند.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles برای راهاندازیهای جدید OpenClaw منسوخ شده است.
|
||||
|
||||
اکوسیستم بالادستی BlueBubbles همچنان فعال است، اما OpenClaw به API سرور BlueBubbles در macOS وابسته است. تا ۶ مه ۲۰۲۶، آخرین تغییر شاخه توسعه رسمی [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) در [۲۲ ژانویه ۲۰۲۶](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037) بوده، و آخرین انتشار سرور ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) در ۱۶ مه ۲۰۲۵ منتشر شده است. اپلیکیشن کلاینت و مخازن کمکی فعالیت جدیدتری دارند، بنابراین این ادعای رهاشدگی نیست؛ این منسوخسازی درباره کاهش وابستگی OpenClaw به یک سرور HTTP خارجی، Webhookها، و سطح سازگاری API خصوصی است، وقتی مسیر بومی `imsg` یکپارچهسازی را روی یک قرارداد stdio محلی نگه میدارد.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
انتشارهای فعلی OpenClaw شامل BlueBubbles هستند، بنابراین بیلدهای بستهبندیشده معمولی به مرحله جداگانه `openclaw plugins install` نیاز ندارند.
|
||||
</Note>
|
||||
|
||||
## نمای کلی
|
||||
|
||||
- از طریق اپلیکیشن کمکی BlueBubbles روی macOS اجرا میشود ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- جایگزین قدیمی برای نصبهایی که از قبل به شناسههای کانال BlueBubbles، وضعیت Webhook، اهداف گروهی، تحویل Cron، یا مسیریابی workspace متکی هستند.
|
||||
- توصیهشده/آزمایششده: macOS Sequoia (15). macOS Tahoe (26) کار میکند؛ ویرایش در حال حاضر روی Tahoe خراب است، و بهروزرسانیهای آیکن گروه ممکن است موفقیت گزارش کنند اما همگامسازی نشوند.
|
||||
- OpenClaw از طریق REST API آن با آن صحبت میکند (`GET /api/v1/ping`، `POST /message/text`، `POST /chat/:id/*`).
|
||||
- پیامهای ورودی از طریق Webhookها میرسند؛ پاسخهای خروجی، نشانگرهای تایپ، رسیدهای خواندن، و tapbackها فراخوانیهای REST هستند.
|
||||
- پیوستها و برچسبها بهعنوان رسانه ورودی دریافت میشوند (و هرجا ممکن باشد به agent نمایش داده میشوند).
|
||||
- پاسخهای Auto-TTS که صدای MP3 یا CAF تولید میکنند، بهجای پیوست فایل ساده، بهصورت حبابهای یادداشت صوتی iMessage تحویل داده میشوند.
|
||||
- جفتسازی/allowlist مانند کانالهای دیگر کار میکند (`/channels/pairing` و غیره) با `channels.bluebubbles.allowFrom` + کدهای جفتسازی.
|
||||
- واکنشها درست مانند Slack/Telegram بهعنوان رویدادهای سیستمی نمایش داده میشوند تا agentها بتوانند پیش از پاسخ دادن به آنها «اشاره» کنند.
|
||||
- قابلیتهای پیشرفته: ویرایش، لغو ارسال، thread کردن پاسخ، افکتهای پیام، مدیریت گروه.
|
||||
|
||||
## شروع سریع
|
||||
|
||||
<Steps>
|
||||
<Step title="نصب BlueBubbles">
|
||||
سرور BlueBubbles را روی Mac خود نصب کنید (دستورالعملهای [bluebubbles.app/install](https://bluebubbles.app/install) را دنبال کنید).
|
||||
</Step>
|
||||
<Step title="فعال کردن web API">
|
||||
در پیکربندی BlueBubbles، web API را فعال کنید و یک رمز عبور تنظیم کنید.
|
||||
</Step>
|
||||
<Step title="پیکربندی OpenClaw">
|
||||
`openclaw onboard` را اجرا کنید و BlueBubbles را انتخاب کنید، یا بهصورت دستی پیکربندی کنید:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="هدایت Webhookها به Gateway">
|
||||
Webhookهای BlueBubbles را به Gateway خود هدایت کنید (مثال: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="شروع Gateway">
|
||||
Gateway را شروع کنید؛ handler مربوط به Webhook را ثبت میکند و جفتسازی را آغاز میکند.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**امنیت**
|
||||
|
||||
- همیشه یک رمز عبور Webhook تنظیم کنید.
|
||||
- احراز هویت Webhook همیشه لازم است. OpenClaw درخواستهای Webhook مربوط به BlueBubbles را رد میکند مگر اینکه شامل یک password/guid مطابق با `channels.bluebubbles.password` باشند (برای مثال `?password=<password>` یا `x-password`)، مستقل از توپولوژی loopback/proxy.
|
||||
- احراز هویت با رمز عبور پیش از خواندن/تجزیه کامل بدنههای Webhook بررسی میشود.
|
||||
|
||||
</Warning>
|
||||
|
||||
## زنده نگه داشتن Messages.app (راهاندازیهای VM / بدون نمایشگر)
|
||||
|
||||
برخی راهاندازیهای macOS VM / همیشه روشن ممکن است باعث شوند Messages.app «idle» شود (رویدادهای ورودی تا زمان باز شدن/foreground شدن اپلیکیشن متوقف میشوند). یک راهحل ساده این است که با استفاده از AppleScript + LaunchAgent هر ۵ دقیقه یکبار **Messages را poke کنید**.
|
||||
|
||||
<Steps>
|
||||
<Step title="ذخیره AppleScript">
|
||||
این را با نام `~/Scripts/poke-messages.scpt` ذخیره کنید:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="نصب یک LaunchAgent">
|
||||
این را با نام `~/Library/LaunchAgents/com.user.poke-messages.plist` ذخیره کنید:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
این **هر ۳۰۰ ثانیه** و **هنگام ورود** اجرا میشود. اجرای نخست ممکن است promptهای **Automation** در macOS را فعال کند (`osascript` → Messages). آنها را در همان نشست کاربری که LaunchAgent را اجرا میکند تأیید کنید.
|
||||
|
||||
</Step>
|
||||
<Step title="بارگذاری آن">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## راهاندازی اولیه
|
||||
|
||||
BlueBubbles در راهاندازی تعاملی موجود است:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
wizard موارد زیر را درخواست میکند:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
نشانی سرور BlueBubbles (مثلاً `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
رمز عبور API از تنظیمات BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
مسیر endpoint مربوط به Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`، `allowlist`، `open`، یا `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
شمارههای تلفن، ایمیلها، یا اهداف چت.
|
||||
</ParamField>
|
||||
|
||||
همچنین میتوانید BlueBubbles را از طریق CLI اضافه کنید:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## کنترل دسترسی (DMها + گروهها)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMها">
|
||||
- پیشفرض: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- فرستندگان ناشناس یک کد جفتسازی دریافت میکنند؛ پیامها تا زمان تأیید نادیده گرفته میشوند (کدها پس از ۱ ساعت منقضی میشوند).
|
||||
- تأیید از طریق:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- جفتسازی تبادل token پیشفرض است. جزئیات: [جفتسازی](/fa/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="گروهها">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (پیشفرض: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` کنترل میکند وقتی `allowlist` تنظیم شده است چه کسی میتواند در گروهها trigger کند.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### غنیسازی نام مخاطب (macOS، اختیاری)
|
||||
|
||||
Webhookهای گروهی BlueBubbles اغلب فقط نشانیهای خام شرکتکنندگان را شامل میشوند. اگر میخواهید context مربوط به `GroupMembers` بهجای آن نامهای مخاطبان محلی را نشان دهد، میتوانید در macOS غنیسازی از Contacts محلی را فعال کنید:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` lookup را فعال میکند. پیشفرض: `false`.
|
||||
- lookupها فقط پس از آن اجرا میشوند که دسترسی گروه، مجوز فرمان، و mention gating اجازه عبور پیام را داده باشند.
|
||||
- فقط شرکتکنندگان تلفنی بدون نام غنیسازی میشوند.
|
||||
- وقتی تطابق محلی پیدا نشود، شمارههای تلفن خام بهعنوان fallback باقی میمانند.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Mention gating (گروهها)
|
||||
|
||||
BlueBubbles از mention gating برای چتهای گروهی پشتیبانی میکند و با رفتار iMessage/WhatsApp همخوان است:
|
||||
|
||||
- از `agents.list[].groupChat.mentionPatterns` (یا `messages.groupChat.mentionPatterns`) برای تشخیص mentionها استفاده میکند.
|
||||
- وقتی `requireMention` برای یک گروه فعال باشد، agent فقط هنگام mention شدن پاسخ میدهد.
|
||||
- فرمانهای کنترلی از فرستندگان مجاز mention gating را دور میزنند.
|
||||
|
||||
پیکربندی برای هر گروه:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Command gating
|
||||
|
||||
- فرمانهای کنترلی (مثلاً `/config`، `/model`) به مجوز نیاز دارند.
|
||||
- از `allowFrom` و `groupAllowFrom` برای تعیین مجوز فرمان استفاده میکند.
|
||||
- فرستندگان مجاز میتوانند فرمانهای کنترلی را حتی بدون mention کردن در گروهها اجرا کنند.
|
||||
|
||||
### system prompt برای هر گروه
|
||||
|
||||
هر ورودی زیر `channels.bluebubbles.groups.*` یک رشته اختیاری `systemPrompt` میپذیرد. مقدار آن در هر turn که پیامی را در آن گروه پردازش میکند، به system prompt مربوط به agent تزریق میشود، بنابراین میتوانید بدون ویرایش promptهای agent، persona یا قواعد رفتاری مخصوص هر گروه را تنظیم کنید:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
کلید با هر چیزی که BlueBubbles بهعنوان `chatGuid` / `chatIdentifier` / `chatId` عددی برای گروه گزارش میکند مطابقت دارد، و یک ورودی wildcard با `"*"` پیشفرضی برای هر گروه بدون تطابق دقیق فراهم میکند (همان الگویی که توسط `requireMention` و سیاستهای ابزار برای هر گروه استفاده میشود). تطابقهای دقیق همیشه بر wildcard اولویت دارند. DMها این فیلد را نادیده میگیرند؛ بهجای آن از سفارشیسازی prompt در سطح agent یا حساب استفاده کنید.
|
||||
|
||||
#### مثال عملی: پاسخهای thread شده و واکنشهای tapback (API خصوصی)
|
||||
|
||||
با فعال بودن API خصوصی BlueBubbles، پیامهای ورودی با شناسههای کوتاه پیام میرسند (برای مثال `[[reply_to:5]]`) و agent میتواند `action=reply` را فراخوانی کند تا وارد thread یک پیام مشخص شود یا `action=react` را برای گذاشتن یک tapback فراخوانی کند. یک `systemPrompt` برای هر گروه راهی قابل اعتماد برای نگه داشتن agent روی انتخاب ابزار درست است:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
واکنشهای tapback و پاسخهای thread شده هر دو به API خصوصی BlueBubbles نیاز دارند؛ برای سازوکارهای زیرین، [اقدامهای پیشرفته](#advanced-actions) و [شناسههای پیام](#message-ids-short-vs-full) را ببینید.
|
||||
|
||||
## اتصالهای گفتوگوی ACP
|
||||
|
||||
چتهای BlueBubbles میتوانند بدون تغییر لایه انتقال به workspaceهای پایدار ACP تبدیل شوند.
|
||||
|
||||
جریان سریع operator:
|
||||
|
||||
- داخل DM یا چت گروهی مجاز، `/acp spawn codex --bind here` را اجرا کنید.
|
||||
- پیامهای آینده در همان گفتوگوی BlueBubbles به نشست ACP ایجادشده route میشوند.
|
||||
- `/new` و `/reset` همان نشست ACP متصل را درجا reset میکنند.
|
||||
- `/acp close` نشست ACP را میبندد و اتصال را حذف میکند.
|
||||
|
||||
اتصالهای پایدار پیکربندیشده نیز از طریق ورودیهای سطح بالای `bindings[]` با `type: "acp"` و `match.channel: "bluebubbles"` پشتیبانی میشوند.
|
||||
|
||||
`match.peer.id` میتواند از هر فرم هدف پشتیبانیشده BlueBubbles استفاده کند:
|
||||
|
||||
- شناسهٔ عادیشدهٔ DM مانند `+15555550123` یا `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
برای اتصالهای پایدار گروهی، `chat_id:*` یا `chat_identifier:*` را ترجیح دهید.
|
||||
|
||||
مثال:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
برای رفتار مشترک اتصال ACP، [عاملهای ACP](/fa/tools/acp-agents) را ببینید.
|
||||
|
||||
## نشانگرهای تایپ + رسیدهای خواندن
|
||||
|
||||
- **نشانگرهای تایپ**: پیش از تولید پاسخ و هنگام آن بهصورت خودکار ارسال میشوند.
|
||||
- **رسیدهای خواندن**: با `channels.bluebubbles.sendReadReceipts` کنترل میشود (پیشفرض: `true`).
|
||||
- **نشانگرهای تایپ**: OpenClaw رویدادهای شروع تایپ را ارسال میکند؛ BlueBubbles هنگام ارسال یا پایان مهلت، تایپ را بهصورت خودکار پاک میکند (توقف دستی از طریق DELETE قابل اتکا نیست).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## کنشهای پیشرفته
|
||||
|
||||
BlueBubbles وقتی در پیکربندی فعال شده باشد، از کنشهای پیشرفتهٔ پیام پشتیبانی میکند:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="کنشهای موجود">
|
||||
- **react**: واکنشهای tapback را اضافه/حذف کنید (`messageId`, `emoji`, `remove`). مجموعهٔ tapback بومی iMessage شامل `love`، `like`، `dislike`، `laugh`، `emphasize` و `question` است. وقتی یک عامل ایموجیای خارج از آن مجموعه انتخاب میکند (برای مثال `👀`)، ابزار واکنش به `love` برمیگردد تا tapback همچنان نمایش داده شود، نه اینکه کل درخواست شکست بخورد. واکنشهای تأیید پیکربندیشده همچنان با سختگیری اعتبارسنجی میشوند و برای مقادیر ناشناخته خطا میدهند.
|
||||
- **edit**: یک پیام ارسالشده را ویرایش کنید (`messageId`, `text`).
|
||||
- **unsend**: ارسال یک پیام را لغو کنید (`messageId`).
|
||||
- **reply**: به یک پیام مشخص پاسخ دهید (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: با جلوهٔ iMessage ارسال کنید (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: نام یک گفتوگوی گروهی را تغییر دهید (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: آیکن/عکس یک گفتوگوی گروهی را تنظیم کنید (`chatGuid`, `media`) - در macOS 26 Tahoe ناپایدار است (ممکن است API موفقیت برگرداند اما آیکن همگامسازی نشود).
|
||||
- **addParticipant**: فردی را به یک گروه اضافه کنید (`chatGuid`, `address`).
|
||||
- **removeParticipant**: فردی را از یک گروه حذف کنید (`chatGuid`, `address`).
|
||||
- **leaveGroup**: یک گفتوگوی گروهی را ترک کنید (`chatGuid`).
|
||||
- **upload-file**: رسانه/فایلها را ارسال کنید (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- یادداشتهای صوتی: برای ارسال بهعنوان پیام صوتی iMessage، `asVoice: true` را با صدای **MP3** یا **CAF** تنظیم کنید. BlueBubbles هنگام ارسال یادداشتهای صوتی، MP3 → CAF را تبدیل میکند.
|
||||
- نام مستعار قدیمی: `sendAttachment` همچنان کار میکند، اما `upload-file` نام کنش رسمی است.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### شناسههای پیام (کوتاه در برابر کامل)
|
||||
|
||||
OpenClaw ممکن است برای صرفهجویی در توکنها، شناسههای پیام _کوتاه_ (مثلاً `1`، `2`) را نمایش دهد.
|
||||
|
||||
- `MessageSid` / `ReplyToId` میتوانند شناسههای کوتاه باشند.
|
||||
- `MessageSidFull` / `ReplyToIdFull` شامل شناسههای کامل ارائهدهنده هستند.
|
||||
- شناسههای کوتاه در حافظه نگهداری میشوند؛ ممکن است هنگام راهاندازی مجدد یا حذف از کش منقضی شوند.
|
||||
- کنشها `messageId` کوتاه یا کامل را میپذیرند، اما اگر شناسههای کوتاه دیگر در دسترس نباشند خطا میدهند.
|
||||
|
||||
برای خودکارسازیها و ذخیرهسازی ماندگار، از شناسههای کامل استفاده کنید:
|
||||
|
||||
- الگوها: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- زمینه: `MessageSidFull` / `ReplyToIdFull` در payloadهای ورودی
|
||||
|
||||
برای متغیرهای الگو، [پیکربندی](/fa/gateway/configuration) را ببینید.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## ادغام DMهای split-send (فرمان + URL در یک ترکیب)
|
||||
|
||||
وقتی کاربر در iMessage یک فرمان و یک URL را با هم تایپ میکند - مثلاً `Dump https://example.com/article` - Apple ارسال را به **دو تحویل Webhook جداگانه** تقسیم میکند:
|
||||
|
||||
1. یک پیام متنی (`"Dump"`).
|
||||
2. یک حباب پیشنمایش URL (`"https://..."`) با تصاویر پیشنمایش OG بهعنوان پیوست.
|
||||
|
||||
در بیشتر راهاندازیها، دو Webhook با فاصلهٔ حدود 0.8 تا 2.0 ثانیه به OpenClaw میرسند. بدون ادغام، عامل در نوبت 1 فقط فرمان را دریافت میکند، پاسخ میدهد (اغلب «URL را برایم بفرست»)، و URL را فقط در نوبت 2 میبیند - در آن نقطه زمینهٔ فرمان از قبل از دست رفته است.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` یک DM را وارد ادغام Webhookهای متوالی از همان فرستنده در یک نوبت عامل میکند. گفتوگوهای گروهی همچنان بر اساس هر پیام کلیدگذاری میشوند تا ساختار نوبت چندکاربره حفظ شود.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="زمان فعالسازی">
|
||||
زمانی فعال کنید که:
|
||||
|
||||
- Skillsای منتشر میکنید که انتظار `command + payload` را در یک پیام دارند (dump، paste، save، queue و غیره).
|
||||
- کاربران شما URLها، تصاویر یا محتوای طولانی را کنار فرمانها paste میکنند.
|
||||
- میتوانید تأخیر اضافهشده به نوبت DM را بپذیرید (پایینتر را ببینید).
|
||||
|
||||
غیرفعال بگذارید وقتی که:
|
||||
|
||||
- برای triggerهای DM تککلمهای به کمینهٔ تأخیر فرمان نیاز دارید.
|
||||
- همهٔ جریانهای شما فرمانهای یکمرحلهای بدون پیگیری payload هستند.
|
||||
|
||||
</Tab>
|
||||
<Tab title="فعالسازی">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
وقتی این پرچم روشن باشد و `messages.inbound.byChannel.bluebubbles` صریحی وجود نداشته باشد، پنجرهٔ debounce به **2500 ms** گسترش مییابد (پیشفرض برای حالت بدون ادغام 500 ms است). پنجرهٔ گستردهتر لازم است - cadence ارسال split-send اپل با فاصلهٔ 0.8 تا 2.0 ثانیه در پیشفرض تنگتر جا نمیشود.
|
||||
|
||||
برای تنظیم دستی پنجره:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="مصالحهها">
|
||||
- **تأخیر اضافه برای فرمانهای کنترلی DM.** وقتی پرچم روشن باشد، پیامهای فرمان کنترلی DM (مانند `Dump`، `Save` و غیره) اکنون پیش از dispatch تا سقف پنجرهٔ debounce منتظر میمانند، برای زمانی که Webhook مربوط به payload در راه است. فرمانهای گفتوگوی گروهی همچنان dispatch فوری دارند.
|
||||
- **خروجی ادغامشده محدود است** - متن ادغامشده با نشانگر صریح `…[truncated]` حداکثر 4000 نویسه دارد؛ پیوستها حداکثر 20 هستند؛ ورودیهای منبع حداکثر 10 هستند (فراتر از آن، اولین و آخرین نگه داشته میشوند). هر `messageId` منبع همچنان به حذف تکراری ورودی میرسد، بنابراین replay بعدی MessagePoller از هر رویداد منفرد بهعنوان تکراری شناسایی میشود.
|
||||
- **اختیاری، برای هر کانال.** کانالهای دیگر (Telegram، WhatsApp، Slack، …) تحت تأثیر قرار نمیگیرند.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### سناریوها و آنچه عامل میبیند
|
||||
|
||||
| کاربر مینویسد | Apple تحویل میدهد | پرچم خاموش (پیشفرض) | پرچم روشن + پنجرهٔ 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (یک ارسال) | 2 Webhook با فاصلهٔ حدود 1 s | دو نوبت عامل: فقط "Dump"، سپس URL | یک نوبت: متن ادغامشدهٔ `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (پیوست + متن) | 2 Webhook | دو نوبت | یک نوبت: متن + تصویر |
|
||||
| `/status` (فرمان مستقل) | 1 Webhook | dispatch فوری | **تا سقف پنجره منتظر بمان، سپس dispatch کن** |
|
||||
| URL بهتنهایی paste شده | 1 Webhook | dispatch فوری | dispatch فوری (فقط یک ورودی در bucket) |
|
||||
| متن + URL که عمداً بهصورت دو پیام جداگانه و با فاصلهٔ چند دقیقه ارسال شدهاند | 2 Webhook بیرون از پنجره | دو نوبت | دو نوبت (پنجره میان آنها منقضی میشود) |
|
||||
| سیل سریع (>10 DM کوچک داخل پنجره) | N Webhook | N نوبت | یک نوبت، خروجی محدودشده (اولین + آخرین، سقفهای متن/پیوست اعمال شدهاند) |
|
||||
|
||||
### عیبیابی ادغام split-send
|
||||
|
||||
اگر پرچم روشن است و split-sendها همچنان بهصورت دو نوبت میرسند، هر لایه را بررسی کنید:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="پیکربندی واقعاً بارگذاری شده است">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
سپس `openclaw gateway restart` - پرچم هنگام ایجاد debouncer-registry خوانده میشود.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="پنجرهٔ debounce برای راهاندازی شما بهاندازهٔ کافی گسترده است">
|
||||
به گزارش سرور BlueBubbles در `~/Library/Logs/bluebubbles-server/main.log` نگاه کنید:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
فاصلهٔ بین dispatch متن به سبک `"Dump"` و dispatch بعدی `"https://..."; Attachments:` را اندازه بگیرید. `messages.inbound.byChannel.bluebubbles` را آنقدر افزایش دهید که با خیال راحت آن فاصله را پوشش دهد.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="مهرهای زمانی JSONL نشست ≠ رسیدن Webhook">
|
||||
مهرهای زمانی رویداد نشست (`~/.openclaw/agents/<id>/sessions/*.jsonl`) نشان میدهند Gateway چه زمانی پیام را به عامل تحویل میدهد، **نه** اینکه Webhook چه زمانی رسیده است. پیام دومِ صفشده با برچسب `[Queued messages while agent was busy]` یعنی نوبت اول هنگام رسیدن Webhook دوم هنوز در حال اجرا بوده است - bucket ادغام از قبل flush شده بود. پنجره را بر اساس گزارش سرور BB تنظیم کنید، نه گزارش نشست.
|
||||
</Accordion>
|
||||
<Accordion title="فشار حافظه dispatch پاسخ را کند میکند">
|
||||
روی ماشینهای کوچکتر (8 GB)، نوبتهای عامل ممکن است آنقدر طول بکشند که bucket ادغام پیش از کاملشدن پاسخ flush شود و URL بهعنوان نوبت دوم صفشده وارد شود. `memory_pressure` و `ps -o rss -p $(pgrep openclaw-gateway)` را بررسی کنید؛ اگر Gateway بیش از حدود 500 MB RSS مصرف میکند و compressor فعال است، فرایندهای سنگین دیگر را ببندید یا به میزبان بزرگتری ارتقا دهید.
|
||||
</Accordion>
|
||||
<Accordion title="ارسالهای reply-quote مسیر متفاوتی هستند">
|
||||
اگر کاربر `Dump` را بهعنوان **پاسخ** به یک حباب URL موجود لمس کرده باشد (iMessage نشان «1 Reply» را روی حباب Dump نشان میدهد)، URL در `replyToBody` قرار دارد، نه در Webhook دوم. ادغام اعمال نمیشود - این مسئله به skill/prompt مربوط است، نه به debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## استریم بلوکی
|
||||
|
||||
کنترل کنید پاسخها بهصورت یک پیام واحد ارسال شوند یا بهشکل بلوکها استریم شوند:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## رسانه + محدودیتها
|
||||
|
||||
- پیوستهای ورودی دانلود میشوند و در کش رسانه ذخیره میشوند.
|
||||
- سقف رسانه از طریق `channels.bluebubbles.mediaMaxMb` برای رسانهٔ ورودی و خروجی (پیشفرض: 8 MB).
|
||||
- متن خروجی به `channels.bluebubbles.textChunkLimit` بخشبندی میشود (پیشفرض: 4000 نویسه).
|
||||
|
||||
## مرجع پیکربندی
|
||||
|
||||
پیکربندی کامل: [پیکربندی](/fa/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="اتصال و Webhook">
|
||||
- `channels.bluebubbles.enabled`: فعال/غیرفعال کردن کانال.
|
||||
- `channels.bluebubbles.serverUrl`: نشانی پایه API از نوع REST برای BlueBubbles.
|
||||
- `channels.bluebubbles.password`: گذرواژه API.
|
||||
- `channels.bluebubbles.webhookPath`: مسیر نقطه پایانی Webhook (پیشفرض: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="سیاست دسترسی">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (پیشفرض: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: فهرست مجاز پیام مستقیم (شناسهها، ایمیلها، شمارههای E.164، `chat_id:*`، `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (پیشفرض: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: فهرست مجاز فرستندگان گروه.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: در macOS، پس از عبور از دروازهگذاری، در صورت نیاز شرکتکنندگان بینام گروه را از مخاطبان محلی کامل میکند. پیشفرض: `false`.
|
||||
- `channels.bluebubbles.groups`: پیکربندی برای هر گروه (`requireMention` و غیره).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="تحویل و بخشبندی">
|
||||
- `channels.bluebubbles.sendReadReceipts`: ارسال رسیدهای خواندهشدن (پیشفرض: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: فعال کردن پخش جریانی بلوکی (پیشفرض: `false`؛ برای پاسخهای جریانی الزامی است).
|
||||
- `channels.bluebubbles.textChunkLimit`: اندازه بخش خروجی بر حسب نویسه (پیشفرض: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: مهلت زمانی هر درخواست بر حسب میلیثانیه برای ارسال متن خروجی از طریق `/api/v1/message/text` (پیشفرض: 30000). در راهاندازیهای macOS 26 که ارسالهای iMessage با Private API میتوانند درون چارچوب iMessage بیش از ۶۰ ثانیه متوقف بمانند، آن را افزایش دهید؛ برای مثال `45000` یا `60000`. کاوشها، جستوجوهای چت، واکنشها، ویرایشها و بررسیهای سلامت فعلا همان پیشفرض کوتاهتر ۱۰ ثانیهای را نگه میدارند؛ گسترش پوشش به واکنشها و ویرایشها بهعنوان پیگیری بعدی برنامهریزی شده است. بازنویسی برای هر حساب: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (پیشفرض) فقط هنگام عبور از `textChunkLimit` جدا میکند؛ `newline` پیش از بخشبندی بر اساس طول، روی خطهای خالی (مرزهای پاراگراف) جدا میکند.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="رسانه و تاریخچه">
|
||||
- `channels.bluebubbles.mediaMaxMb`: سقف رسانه ورودی/خروجی بر حسب MB (پیشفرض: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: فهرست مجاز صریح از دایرکتوریهای محلی مطلق که برای مسیرهای رسانه محلی خروجی مجاز هستند. ارسال مسیر محلی بهطور پیشفرض رد میشود مگر اینکه این گزینه پیکربندی شده باشد. بازنویسی برای هر حساب: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Webhookهای پیام مستقیم پیاپی از همان فرستنده را در یک نوبت عامل ادغام میکند تا ارسال جداشده متن+URL از Apple بهصورت یک پیام واحد برسد (پیشفرض: `false`). برای سناریوها، تنظیم پنجره و بدهبستانها، [ادغام پیامهای مستقیم ارسالشده بهصورت جداشده](#coalescing-split-send-dms-command--url-in-one-composition) را ببینید. وقتی بدون `messages.inbound.byChannel.bluebubbles` صریح فعال شود، پنجره پیشفرض تأخیرزدایی ورودی را از 500 ms به 2500 ms افزایش میدهد.
|
||||
- `channels.bluebubbles.historyLimit`: حداکثر پیامهای گروه برای زمینه (0 غیرفعال میکند).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: محدودیت تاریخچه پیام مستقیم.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: وقتی یک پاسخ ورودی بدون `replyToBody`/`replyToSender` میرسد و کش درونحافظهای زمینه پاسخ پیدا نمیشود، پیام اصلی را از API HTTP BlueBubbles بهعنوان جایگزین در حد بهترین تلاش دریافت میکند (پیشفرض: `false`). برای استقرارهای چندنمونهای که یک حساب BlueBubbles را به اشتراک میگذارند، پس از راهاندازی مجدد فرایند، یا پس از تخلیه کش TTL/LRU بلندمدت مفید است. دریافت با همان سیاستی که برای هر درخواست دیگر کلاینت BlueBubbles استفاده میشود در برابر SSRF محافظت میشود، هرگز خطا پرتاب نمیکند، و کش را پر میکند تا پاسخهای بعدی سرشکن شوند. بازنویسی برای هر حساب: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. تنظیم در سطح کانال به حسابهایی که این پرچم را حذف کردهاند منتقل میشود.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="کنشها و حسابها">
|
||||
- `channels.bluebubbles.actions`: فعال/غیرفعال کردن کنشهای مشخص.
|
||||
- `channels.bluebubbles.accounts`: پیکربندی چندحسابی.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
گزینههای سراسری مرتبط:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (یا `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## نشانیدهی / اهداف تحویل
|
||||
|
||||
برای مسیریابی پایدار، `chat_guid` را ترجیح دهید:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (ترجیحی برای گروهها)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- شناسههای مستقیم: `+15555550123`، `user@example.com`
|
||||
- اگر یک شناسه مستقیم چت پیام مستقیم موجود نداشته باشد، OpenClaw از طریق `POST /api/v1/chat/new` یکی ایجاد میکند. این کار نیازمند فعال بودن BlueBubbles Private API است.
|
||||
|
||||
### مسیریابی iMessage در برابر SMS
|
||||
|
||||
وقتی همان شناسه روی Mac هم چت iMessage و هم چت SMS داشته باشد (برای مثال شماره تلفنی که در iMessage ثبت شده اما پیامهای جایگزین حباب سبز را هم دریافت کرده است)، OpenClaw چت iMessage را ترجیح میدهد و هرگز بیصدا به SMS تنزل نمیدهد. برای اجبار به استفاده از چت SMS، از پیشوند هدف صریح `sms:` استفاده کنید (برای مثال `sms:+15555550123`). شناسههایی که چت iMessage منطبق ندارند همچنان از طریق هر چتی که BlueBubbles گزارش میکند ارسال میشوند.
|
||||
|
||||
## امنیت
|
||||
|
||||
- درخواستهای Webhook با مقایسه پارامترهای پرسوجوی `guid`/`password` یا سرآیندها با `channels.bluebubbles.password` احراز هویت میشوند.
|
||||
- گذرواژه API و نقطه پایانی Webhook را محرمانه نگه دارید (با آنها مانند اعتبارنامه برخورد کنید).
|
||||
- برای احراز هویت Webhook در BlueBubbles هیچ میانبری برای localhost وجود ندارد. اگر ترافیک Webhook را پراکسی میکنید، گذرواژه BlueBubbles را از ابتدا تا انتهای درخواست نگه دارید. `gateway.trustedProxies` در اینجا جایگزین `channels.bluebubbles.password` نمیشود. [امنیت Gateway](/fa/gateway/security#reverse-proxy-configuration) را ببینید.
|
||||
- اگر سرور BlueBubbles را بیرون از LAN خود در معرض دسترس قرار میدهید، HTTPS و قوانین دیواره آتش را فعال کنید.
|
||||
|
||||
## عیبیابی
|
||||
|
||||
- اگر رویدادهای تایپ/خواندن از کار افتادند، لاگهای Webhook در BlueBubbles را بررسی کنید و مطمئن شوید مسیر Gateway با `channels.bluebubbles.webhookPath` منطبق است.
|
||||
- کدهای جفتسازی پس از یک ساعت منقضی میشوند؛ از `openclaw pairing list bluebubbles` و `openclaw pairing approve bluebubbles <code>` استفاده کنید.
|
||||
- واکنشها به API خصوصی BlueBubbles (`POST /api/v1/message/react`) نیاز دارند؛ مطمئن شوید نسخه سرور آن را ارائه میکند.
|
||||
- ویرایش/لغو ارسال به macOS 13+ و نسخه سازگار سرور BlueBubbles نیاز دارد. در macOS 26 (Tahoe)، ویرایش فعلا بهدلیل تغییرات API خصوصی خراب است.
|
||||
- بهروزرسانی آیکون گروه در macOS 26 (Tahoe) میتواند ناپایدار باشد: API ممکن است موفقیت برگرداند اما آیکون جدید همگام نشود.
|
||||
- OpenClaw کنشهای شناختهشده خراب را بر اساس نسخه macOS سرور BlueBubbles بهطور خودکار پنهان میکند. اگر ویرایش همچنان در macOS 26 (Tahoe) ظاهر میشود، آن را بهصورت دستی با `channels.bluebubbles.actions.edit=false` غیرفعال کنید.
|
||||
- `coalesceSameSenderDms` فعال است اما ارسالهای جداشده (مثلا `Dump` + URL) همچنان بهصورت دو نوبت میرسند: چکلیست [عیبیابی ادغام ارسال جداشده](#split-send-coalescing-troubleshooting) را ببینید - علتهای رایج شامل پنجره تأخیرزدایی بیش از حد تنگ، برداشت نادرست مهرهای زمانی لاگ نشست بهعنوان زمان رسیدن Webhook، یا ارسال نقلقول پاسخ (که از `replyToBody` استفاده میکند، نه Webhook دوم) هستند.
|
||||
- برای اطلاعات وضعیت/سلامت: `openclaw status --all` یا `openclaw status --deep`.
|
||||
|
||||
برای مرجع کلی گردشکار کانال، راهنمای [کانالها](/fa/channels) و [Plugins](/fa/tools/plugin) را ببینید.
|
||||
|
||||
## مرتبط
|
||||
|
||||
- [مسیریابی کانال](/fa/channels/channel-routing) - مسیریابی نشست برای پیامها
|
||||
- [نمای کلی کانالها](/fa/channels) - همه کانالهای پشتیبانیشده
|
||||
- [گروهها](/fa/channels/groups) - رفتار چت گروهی و دروازهگذاری ذکر نام
|
||||
- [جفتسازی](/fa/channels/pairing) - احراز هویت پیام مستقیم و جریان جفتسازی
|
||||
- [امنیت](/fa/gateway/security) - مدل دسترسی و مقاومسازی
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- شما در حال نصب، پیکربندی یا ممیزی Plugin bluebubbles هستید
|
||||
summary: سطح کانال BlueBubbles را برای ارسال و دریافت پیامهای OpenClaw اضافه میکند.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T11:40:58Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
سطح کانال BlueBubbles را برای ارسال و دریافت پیامهای OpenClaw اضافه میکند.
|
||||
|
||||
## توزیع
|
||||
|
||||
- بسته: `@openclaw/bluebubbles`
|
||||
- مسیر نصب: npm؛ ClawHub
|
||||
|
||||
## سطح
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## مستندات مرتبط
|
||||
|
||||
- [bluebubbles](/fa/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Configuration du canal BlueBubbles
|
||||
- Dépannage de l'appairage Webhook
|
||||
- Configuration d’iMessage sur macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Prise en charge héritée d’iMessage via le serveur macOS BlueBubbles (envoi/réception REST, saisie, réactions, appairage, actions avancées).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:49Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Statut : plugin hérité groupé qui communique avec le serveur macOS BlueBubbles via HTTP. Les configurations BlueBubbles existantes continuent de fonctionner, mais les nouveaux déploiements OpenClaw iMessage doivent privilégier le plugin natif [iMessage](/fr/channels/imessage) lorsque ses exigences conviennent à votre hôte.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles est obsolète pour les nouvelles configurations OpenClaw.
|
||||
|
||||
L’écosystème BlueBubbles amont est toujours actif, mais OpenClaw dépend de l’API du serveur macOS BlueBubbles. Au 6 mai 2026, la branche de développement officielle [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) a été modifiée pour la dernière fois le [22 janvier 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), et la dernière version du serveur ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) a été publiée le 16 mai 2025. L’application cliente et les dépôts d’assistance ont une activité plus récente ; il ne s’agit donc pas d’affirmer un abandon. La dépréciation vise à réduire la dépendance d’OpenClaw à un serveur HTTP externe, aux webhooks et à une surface de compatibilité avec des API privées lorsque le chemin natif `imsg` maintient l’intégration sur un contrat stdio local.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Les versions actuelles d’OpenClaw incluent BlueBubbles ; les builds empaquetés normaux n’ont donc pas besoin d’une étape `openclaw plugins install` séparée.
|
||||
</Note>
|
||||
|
||||
## Vue d’ensemble
|
||||
|
||||
- Fonctionne sur macOS via l’application d’assistance BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Solution de repli héritée pour les installations qui s’appuient déjà sur les ID de canal BlueBubbles, l’état des webhooks, les cibles de groupe, la livraison cron ou le routage d’espace de travail.
|
||||
- Recommandé/testé : macOS Sequoia (15). macOS Tahoe (26) fonctionne ; la modification est actuellement cassée sur Tahoe, et les mises à jour d’icône de groupe peuvent signaler une réussite sans se synchroniser.
|
||||
- OpenClaw communique avec lui via son API REST (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Les messages entrants arrivent via des webhooks ; les réponses sortantes, indicateurs de saisie, accusés de lecture et tapbacks sont des appels REST.
|
||||
- Les pièces jointes et stickers sont ingérés comme médias entrants (et exposés à l’agent lorsque c’est possible).
|
||||
- Les réponses TTS automatiques qui synthétisent de l’audio MP3 ou CAF sont livrées comme bulles de mémo vocal iMessage plutôt que comme simples pièces jointes.
|
||||
- L’association/liste d’autorisation fonctionne de la même manière que les autres canaux (`/channels/pairing`, etc.) avec `channels.bluebubbles.allowFrom` + codes d’association.
|
||||
- Les réactions sont exposées comme événements système, comme dans Slack/Telegram, afin que les agents puissent les « mentionner » avant de répondre.
|
||||
- Fonctionnalités avancées : modification, annulation d’envoi, fils de réponse, effets de message, gestion des groupes.
|
||||
|
||||
## Démarrage rapide
|
||||
|
||||
<Steps>
|
||||
<Step title="Installer BlueBubbles">
|
||||
Installez le serveur BlueBubbles sur votre Mac (suivez les instructions sur [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Activer l’API web">
|
||||
Dans la configuration BlueBubbles, activez l’API web et définissez un mot de passe.
|
||||
</Step>
|
||||
<Step title="Configurer OpenClaw">
|
||||
Exécutez `openclaw onboard` et sélectionnez BlueBubbles, ou configurez manuellement :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Pointer les webhooks vers le Gateway">
|
||||
Pointez les webhooks BlueBubbles vers votre Gateway (exemple : `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Démarrer le Gateway">
|
||||
Démarrez le Gateway ; il enregistrera le gestionnaire de webhook et lancera l’association.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Sécurité**
|
||||
|
||||
- Définissez toujours un mot de passe de webhook.
|
||||
- L’authentification du webhook est toujours requise. OpenClaw rejette les requêtes de webhook BlueBubbles sauf si elles incluent un mot de passe/guid qui correspond à `channels.bluebubbles.password` (par exemple `?password=<password>` ou `x-password`), quelle que soit la topologie local loopback/proxy.
|
||||
- L’authentification par mot de passe est vérifiée avant la lecture/l’analyse complète des corps de webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Maintenir Messages.app actif (VM / configurations sans interface)
|
||||
|
||||
Certaines VM macOS / configurations toujours actives peuvent voir Messages.app passer en « veille » (les événements entrants s’arrêtent jusqu’à ce que l’application soit ouverte/ramenée au premier plan). Une solution simple consiste à **stimuler Messages toutes les 5 minutes** avec un AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Enregistrer l’AppleScript">
|
||||
Enregistrez ceci sous `~/Scripts/poke-messages.scpt` :
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Installer un LaunchAgent">
|
||||
Enregistrez ceci sous `~/Library/LaunchAgents/com.user.poke-messages.plist` :
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Cela s’exécute **toutes les 300 secondes** et **à la connexion**. La première exécution peut déclencher des invites **Automatisation** macOS (`osascript` → Messages). Approuvez-les dans la même session utilisateur que celle qui exécute le LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Le charger">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles est disponible dans l’onboarding interactif :
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
L’assistant demande :
|
||||
|
||||
<ParamField path="URL du serveur" type="string" required>
|
||||
Adresse du serveur BlueBubbles (par ex., `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Mot de passe" type="string" required>
|
||||
Mot de passe d’API depuis les paramètres du serveur BlueBubbles.
|
||||
</ParamField>
|
||||
<ParamField path="Chemin du webhook" type="string" default="/bluebubbles-webhook">
|
||||
Chemin du point de terminaison Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="Politique de DM" type="string">
|
||||
`pairing`, `allowlist`, `open` ou `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Liste d’autorisation" type="string[]">
|
||||
Numéros de téléphone, e-mails ou cibles de chat.
|
||||
</ParamField>
|
||||
|
||||
Vous pouvez aussi ajouter BlueBubbles via la CLI :
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Contrôle d’accès (DM + groupes)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- Par défaut : `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Les expéditeurs inconnus reçoivent un code d’association ; les messages sont ignorés jusqu’à approbation (les codes expirent après 1 heure).
|
||||
- Approuver via :
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- L’association est l’échange de jeton par défaut. Détails : [Association](/fr/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groupes">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (par défaut : `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` contrôle qui peut déclencher dans les groupes lorsque `allowlist` est défini.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Enrichissement du nom de contact (macOS, facultatif)
|
||||
|
||||
Les webhooks de groupe BlueBubbles n’incluent souvent que les adresses brutes des participants. Si vous voulez que le contexte `GroupMembers` affiche plutôt les noms de contacts locaux, vous pouvez activer l’enrichissement local depuis Contacts sur macOS :
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` active la recherche. Par défaut : `false`.
|
||||
- Les recherches ne s’exécutent qu’après que l’accès au groupe, l’autorisation de commande et le filtrage par mention ont autorisé le message.
|
||||
- Seuls les participants téléphoniques sans nom sont enrichis.
|
||||
- Les numéros de téléphone bruts restent la solution de repli lorsqu’aucune correspondance locale n’est trouvée.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Filtrage par mention (groupes)
|
||||
|
||||
BlueBubbles prend en charge le filtrage par mention pour les discussions de groupe, avec le même comportement que iMessage/WhatsApp :
|
||||
|
||||
- Utilise `agents.list[].groupChat.mentionPatterns` (ou `messages.groupChat.mentionPatterns`) pour détecter les mentions.
|
||||
- Lorsque `requireMention` est activé pour un groupe, l’agent ne répond que lorsqu’il est mentionné.
|
||||
- Les commandes de contrôle provenant d’expéditeurs autorisés contournent le filtrage par mention.
|
||||
|
||||
Configuration par groupe :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Filtrage des commandes
|
||||
|
||||
- Les commandes de contrôle (par ex., `/config`, `/model`) nécessitent une autorisation.
|
||||
- Utilise `allowFrom` et `groupAllowFrom` pour déterminer l’autorisation de commande.
|
||||
- Les expéditeurs autorisés peuvent exécuter des commandes de contrôle même sans mention dans les groupes.
|
||||
|
||||
### Prompt système par groupe
|
||||
|
||||
Chaque entrée sous `channels.bluebubbles.groups.*` accepte une chaîne `systemPrompt` facultative. La valeur est injectée dans le prompt système de l’agent à chaque tour qui traite un message dans ce groupe, ce qui vous permet de définir une persona ou des règles comportementales par groupe sans modifier les prompts de l’agent :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
La clé correspond à ce que BlueBubbles signale comme `chatGuid` / `chatIdentifier` / `chatId` numérique pour le groupe, et une entrée joker `"*"` fournit une valeur par défaut pour chaque groupe sans correspondance exacte (même modèle utilisé par `requireMention` et les politiques d’outils par groupe). Les correspondances exactes l’emportent toujours sur le joker. Les DM ignorent ce champ ; utilisez plutôt la personnalisation de prompt au niveau de l’agent ou du compte.
|
||||
|
||||
#### Exemple détaillé : réponses en fil et réactions tapback (API privée)
|
||||
|
||||
Lorsque l’API privée BlueBubbles est activée, les messages entrants arrivent avec des ID de message courts (par exemple `[[reply_to:5]]`) et l’agent peut appeler `action=reply` pour répondre dans un fil à un message précis, ou `action=react` pour déposer un tapback. Un `systemPrompt` par groupe est une manière fiable de garder l’agent orienté vers le bon outil :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Les réactions tapback et les réponses en fil nécessitent toutes deux l’API privée BlueBubbles ; consultez [Actions avancées](#advanced-actions) et [ID de message](#message-ids-short-vs-full) pour les mécanismes sous-jacents.
|
||||
|
||||
## Liaisons de conversation ACP
|
||||
|
||||
Les chats BlueBubbles peuvent être transformés en espaces de travail ACP durables sans changer la couche de transport.
|
||||
|
||||
Flux opérateur rapide :
|
||||
|
||||
- Exécutez `/acp spawn codex --bind here` dans le DM ou la discussion de groupe autorisée.
|
||||
- Les futurs messages de cette même conversation BlueBubbles sont routés vers la session ACP créée.
|
||||
- `/new` et `/reset` réinitialisent la même session ACP liée sur place.
|
||||
- `/acp close` ferme la session ACP et supprime la liaison.
|
||||
|
||||
Les liaisons persistantes configurées sont également prises en charge via des entrées `bindings[]` de niveau supérieur avec `type: "acp"` et `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` peut utiliser n’importe quelle forme de cible BlueBubbles prise en charge :
|
||||
|
||||
- identifiant de message direct normalisé tel que `+15555550123` ou `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Pour des liaisons de groupe stables, préférez `chat_id:*` ou `chat_identifier:*`.
|
||||
|
||||
Exemple :
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Consultez [Agents ACP](/fr/tools/acp-agents) pour le comportement partagé des liaisons ACP.
|
||||
|
||||
## Indicateurs de saisie + accusés de lecture
|
||||
|
||||
- **Indicateurs de saisie** : envoyés automatiquement avant et pendant la génération de la réponse.
|
||||
- **Accusés de lecture** : contrôlés par `channels.bluebubbles.sendReadReceipts` (par défaut : `true`).
|
||||
- **Indicateurs de saisie** : OpenClaw envoie des événements de début de saisie ; BlueBubbles efface automatiquement la saisie lors de l’envoi ou après expiration du délai (l’arrêt manuel via DELETE n’est pas fiable).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Actions avancées
|
||||
|
||||
BlueBubbles prend en charge des actions avancées sur les messages lorsqu’elles sont activées dans la configuration :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Actions disponibles">
|
||||
- **react** : ajouter/supprimer des réactions Tapback (`messageId`, `emoji`, `remove`). L’ensemble Tapback natif d’iMessage est `love`, `like`, `dislike`, `laugh`, `emphasize` et `question`. Lorsqu’un agent choisit un émoji hors de cet ensemble (par exemple `👀`), l’outil de réaction se rabat sur `love` afin que le Tapback s’affiche quand même au lieu de faire échouer toute la requête. Les réactions d’accusé configurées restent strictement validées et produisent une erreur pour les valeurs inconnues.
|
||||
- **edit** : modifier un message envoyé (`messageId`, `text`).
|
||||
- **unsend** : annuler l’envoi d’un message (`messageId`).
|
||||
- **reply** : répondre à un message précis (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect** : envoyer avec un effet iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup** : renommer une conversation de groupe (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon** : définir l’icône/photo d’une conversation de groupe (`chatGuid`, `media`) - peu fiable sur macOS 26 Tahoe (l’API peut renvoyer un succès sans que l’icône se synchronise).
|
||||
- **addParticipant** : ajouter quelqu’un à un groupe (`chatGuid`, `address`).
|
||||
- **removeParticipant** : retirer quelqu’un d’un groupe (`chatGuid`, `address`).
|
||||
- **leaveGroup** : quitter une conversation de groupe (`chatGuid`).
|
||||
- **upload-file** : envoyer des médias/fichiers (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Mémos vocaux : définissez `asVoice: true` avec de l’audio **MP3** ou **CAF** pour l’envoyer comme message vocal iMessage. BlueBubbles convertit MP3 → CAF lors de l’envoi de mémos vocaux.
|
||||
- Alias hérité : `sendAttachment` fonctionne toujours, mais `upload-file` est le nom d’action canonique.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID de message (courts ou complets)
|
||||
|
||||
OpenClaw peut exposer des ID de message _courts_ (par ex. `1`, `2`) afin d’économiser des jetons.
|
||||
|
||||
- `MessageSid` / `ReplyToId` peuvent être des ID courts.
|
||||
- `MessageSidFull` / `ReplyToIdFull` contiennent les ID complets du fournisseur.
|
||||
- Les ID courts sont en mémoire ; ils peuvent expirer au redémarrage ou lors de l’éviction du cache.
|
||||
- Les actions acceptent un `messageId` court ou complet, mais les ID courts renverront une erreur s’ils ne sont plus disponibles.
|
||||
|
||||
Utilisez les ID complets pour les automatisations et le stockage durables :
|
||||
|
||||
- Modèles : `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Contexte : `MessageSidFull` / `ReplyToIdFull` dans les charges utiles entrantes
|
||||
|
||||
Consultez [Configuration](/fr/gateway/configuration) pour les variables de modèle.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Regroupement des messages directs à envoi fractionné (commande + URL dans une seule composition)
|
||||
|
||||
Lorsqu’un utilisateur saisit une commande et une URL ensemble dans iMessage - par ex. `Dump https://example.com/article` - Apple fractionne l’envoi en **deux livraisons Webhook distinctes** :
|
||||
|
||||
1. Un message texte (`"Dump"`).
|
||||
2. Une bulle d’aperçu d’URL (`"https://..."`) avec des images d’aperçu OG en pièces jointes.
|
||||
|
||||
Les deux Webhooks arrivent dans OpenClaw à environ 0,8 à 2,0 s d’intervalle sur la plupart des configurations. Sans regroupement, l’agent reçoit la commande seule au tour 1, répond (souvent « envoyez-moi l’URL »), et ne voit l’URL qu’au tour 2 - moment où le contexte de la commande est déjà perdu.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` active, pour les messages directs, la fusion des Webhooks consécutifs du même expéditeur en un seul tour d’agent. Les conversations de groupe continuent d’être indexées par message afin de préserver la structure des tours multi-utilisateurs.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Quand activer">
|
||||
Activez lorsque :
|
||||
|
||||
- Vous fournissez des Skills qui attendent `command + payload` dans un seul message (extraire, coller, enregistrer, mettre en file d’attente, etc.).
|
||||
- Vos utilisateurs collent des URL, des images ou du contenu long avec les commandes.
|
||||
- Vous pouvez accepter la latence ajoutée aux tours de message direct (voir ci-dessous).
|
||||
|
||||
Laissez désactivé lorsque :
|
||||
|
||||
- Vous avez besoin d’une latence minimale de commande pour les déclencheurs de message direct à un seul mot.
|
||||
- Tous vos flux sont des commandes ponctuelles sans suivis de charge utile.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Activation">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Lorsque l’option est activée et qu’aucun `messages.inbound.byChannel.bluebubbles` explicite n’est défini, la fenêtre d’anti-rebond s’élargit à **2500 ms** (la valeur par défaut sans regroupement est 500 ms). La fenêtre plus large est nécessaire - la cadence d’envoi fractionné d’Apple, de 0,8 à 2,0 s, ne tient pas dans la valeur par défaut plus stricte.
|
||||
|
||||
Pour régler vous-même la fenêtre :
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Compromis">
|
||||
- **Latence ajoutée pour les commandes de contrôle en message direct.** Lorsque l’option est activée, les messages de commande de contrôle en message direct (comme `Dump`, `Save`, etc.) attendent désormais jusqu’à la fenêtre d’anti-rebond avant d’être distribués, au cas où un Webhook de charge utile arriverait. Les commandes de conversation de groupe conservent une distribution instantanée.
|
||||
- **La sortie fusionnée est bornée** - le texte fusionné est limité à 4000 caractères avec un marqueur explicite `…[truncated]` ; les pièces jointes sont limitées à 20 ; les entrées source sont limitées à 10 (la première et les plus récentes sont conservées au-delà). Chaque `messageId` source atteint toujours la déduplication entrante afin qu’une relecture ultérieure par MessagePoller de n’importe quel événement individuel soit reconnue comme doublon.
|
||||
- **Activation explicite, par canal.** Les autres canaux (Telegram, WhatsApp, Slack, …) ne sont pas affectés.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Scénarios et ce que voit l’agent
|
||||
|
||||
| L’utilisateur compose | Apple livre | Option désactivée (par défaut) | Option activée + fenêtre de 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------ | --------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (un seul envoi) | 2 Webhooks espacés d’environ 1 s | Deux tours d’agent : « Dump » seul, puis l’URL | Un seul tour : texte fusionné `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (pièce jointe + texte) | 2 Webhooks | Deux tours | Un seul tour : texte + image |
|
||||
| `/status` (commande autonome) | 1 Webhook | Distribution instantanée | **Attend jusqu’à la fenêtre, puis distribue** |
|
||||
| URL collée seule | 1 Webhook | Distribution instantanée | Distribution instantanée (une seule entrée dans le compartiment) |
|
||||
| Texte + URL envoyés en deux messages séparés intentionnels, à plusieurs minutes d’intervalle | 2 Webhooks hors fenêtre | Deux tours | Deux tours (la fenêtre expire entre eux) |
|
||||
| Afflux rapide (>10 petits messages directs dans la fenêtre) | N Webhooks | N tours | Un seul tour, sortie bornée (premier + plus récents, limites texte/pièces jointes appliquées) |
|
||||
|
||||
### Dépannage du regroupement des envois fractionnés
|
||||
|
||||
Si l’option est activée et que les envois fractionnés arrivent toujours sous forme de deux tours, vérifiez chaque couche :
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Configuration effectivement chargée">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Puis `openclaw gateway restart` - l’option est lue lors de la création du registre d’anti-rebond.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Fenêtre d’anti-rebond assez large pour votre configuration">
|
||||
Consultez le journal du serveur BlueBubbles sous `~/Library/Logs/bluebubbles-server/main.log` :
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Mesurez l’écart entre la distribution de texte de style `"Dump"` et la distribution `"https://..."; Attachments:` qui suit. Augmentez `messages.inbound.byChannel.bluebubbles` pour couvrir confortablement cet écart.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Horodatages JSONL de session ≠ arrivée du Webhook">
|
||||
Les horodatages d’événements de session (`~/.openclaw/agents/<id>/sessions/*.jsonl`) reflètent le moment où le Gateway transmet un message à l’agent, **pas** celui où le Webhook est arrivé. Un deuxième message en file d’attente étiqueté `[Queued messages while agent was busy]` signifie que le premier tour était encore en cours lorsque le deuxième Webhook est arrivé - le compartiment de regroupement avait déjà été vidé. Réglez la fenêtre à partir du journal du serveur BB, pas du journal de session.
|
||||
</Accordion>
|
||||
<Accordion title="Pression mémoire ralentissant la distribution des réponses">
|
||||
Sur les machines plus petites (8 Go), les tours d’agent peuvent durer assez longtemps pour que le compartiment de regroupement soit vidé avant la fin de la réponse, et l’URL arrive alors comme deuxième tour en file d’attente. Vérifiez `memory_pressure` et `ps -o rss -p $(pgrep openclaw-gateway)` ; si le Gateway dépasse environ 500 Mo de RSS et que le compresseur est actif, fermez d’autres processus lourds ou passez à un hôte plus grand.
|
||||
</Accordion>
|
||||
<Accordion title="Les envois par citation de réponse suivent un chemin différent">
|
||||
Si l’utilisateur a touché `Dump` comme **réponse** à une bulle d’URL existante (iMessage affiche un badge « 1 réponse » sur la bulle Dump), l’URL se trouve dans `replyToBody`, pas dans un second Webhook. Le regroupement ne s’applique pas - c’est une question de Skill/invite, pas d’anti-rebond.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Diffusion par blocs
|
||||
|
||||
Contrôlez si les réponses sont envoyées sous forme d’un seul message ou diffusées par blocs :
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Médias + limites
|
||||
|
||||
- Les pièces jointes entrantes sont téléchargées et stockées dans le cache média.
|
||||
- Limite des médias via `channels.bluebubbles.mediaMaxMb` pour les médias entrants et sortants (par défaut : 8 Mo).
|
||||
- Le texte sortant est découpé selon `channels.bluebubbles.textChunkLimit` (par défaut : 4000 caractères).
|
||||
|
||||
## Référence de configuration
|
||||
|
||||
Configuration complète : [Configuration](/fr/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Connexion et webhook">
|
||||
- `channels.bluebubbles.enabled`: Activer/désactiver le canal.
|
||||
- `channels.bluebubbles.serverUrl`: URL de base de l’API REST BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Mot de passe de l’API.
|
||||
- `channels.bluebubbles.webhookPath`: Chemin du point de terminaison Webhook (par défaut : `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Politique d’accès">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (par défaut : `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Liste d’autorisation des MP (identifiants, e-mails, numéros E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (par défaut : `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Liste d’autorisation des expéditeurs de groupe.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Sur macOS, enrichit éventuellement les participants de groupe sans nom à partir des Contacts locaux une fois le contrôle d’accès réussi. Par défaut : `false`.
|
||||
- `channels.bluebubbles.groups`: Configuration par groupe (`requireMention`, etc.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Livraison et découpage">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Envoyer des accusés de lecture (par défaut : `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Activer le streaming par blocs (par défaut : `false` ; requis pour les réponses en streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Taille des fragments sortants en caractères (par défaut : 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Délai d’expiration par requête en ms pour les envois de texte sortants via `/api/v1/message/text` (par défaut : 30000). Augmentez-le sur les configurations macOS 26 où les envois iMessage via l’API privée peuvent rester bloqués pendant plus de 60 secondes dans le framework iMessage ; par exemple `45000` ou `60000`. Les sondes, recherches de discussions, réactions, modifications et vérifications d’état conservent actuellement la valeur par défaut plus courte de 10 s ; l’extension de la couverture aux réactions et aux modifications est prévue ultérieurement. Remplacement par compte : `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (par défaut) découpe uniquement en cas de dépassement de `textChunkLimit` ; `newline` découpe sur les lignes vides (limites de paragraphes) avant le découpage par longueur.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Médias et historique">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Limite des médias entrants/sortants en Mo (par défaut : 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Liste d’autorisation explicite des répertoires locaux absolus autorisés pour les chemins de médias locaux sortants. Les envois par chemin local sont refusés par défaut sauf si ceci est configuré. Remplacement par compte : `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Fusionner les Webhooks de MP consécutifs d’un même expéditeur en un seul tour d’agent afin que l’envoi scindé texte+URL d’Apple arrive comme un seul message (par défaut : `false`). Voir [Fusion des MP envoyés en plusieurs parties](#coalescing-split-send-dms-command--url-in-one-composition) pour les scénarios, l’ajustement de la fenêtre et les compromis. Élargit la fenêtre anti-rebond entrante par défaut de 500 ms à 2500 ms lorsqu’elle est activée sans `messages.inbound.byChannel.bluebubbles` explicite.
|
||||
- `channels.bluebubbles.historyLimit`: Nombre maximal de messages de groupe pour le contexte (0 désactive).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Limite d’historique des MP.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Lorsqu’une réponse entrante arrive sans `replyToBody`/`replyToSender` et que le cache en mémoire du contexte de réponse ne contient pas l’entrée, récupère le message d’origine depuis l’API HTTP BlueBubbles comme solution de secours au mieux (par défaut : `false`). Utile pour les déploiements multi-instances partageant un seul compte BlueBubbles, après des redémarrages de processus ou après l’éviction d’un cache TTL/LRU de longue durée. La récupération est protégée contre les SSRF par la même politique que toute autre requête du client BlueBubbles, ne lève jamais d’exception et alimente le cache afin que les réponses suivantes soient amorties. Remplacement par compte : `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Un paramètre au niveau du canal se propage aux comptes qui omettent l’indicateur.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Actions et comptes">
|
||||
- `channels.bluebubbles.actions`: Activer/désactiver des actions spécifiques.
|
||||
- `channels.bluebubbles.accounts`: Configuration multi-comptes.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Options globales associées :
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (ou `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Adressage / cibles de livraison
|
||||
|
||||
Préférez `chat_guid` pour un routage stable :
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (préféré pour les groupes)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Identifiants directs : `+15555550123`, `user@example.com`
|
||||
- Si un identifiant direct n’a pas de discussion MP existante, OpenClaw en créera une via `POST /api/v1/chat/new`. Cela nécessite l’activation de l’API privée BlueBubbles.
|
||||
|
||||
### Routage iMessage vs SMS
|
||||
|
||||
Lorsque le même identifiant possède à la fois une discussion iMessage et une discussion SMS sur le Mac (par exemple un numéro de téléphone enregistré auprès d’iMessage mais ayant aussi reçu des solutions de repli en bulles vertes), OpenClaw privilégie la discussion iMessage et ne rétrograde jamais silencieusement vers SMS. Pour forcer la discussion SMS, utilisez un préfixe de cible `sms:` explicite (par exemple `sms:+15555550123`). Les identifiants sans discussion iMessage correspondante sont toujours envoyés via la discussion signalée par BlueBubbles.
|
||||
|
||||
## Sécurité
|
||||
|
||||
- Les requêtes Webhook sont authentifiées en comparant les paramètres de requête ou en-têtes `guid`/`password` à `channels.bluebubbles.password`.
|
||||
- Gardez le mot de passe de l’API et le point de terminaison Webhook secrets (traitez-les comme des identifiants).
|
||||
- Il n’y a pas de contournement localhost pour l’authentification Webhook de BlueBubbles. Si vous proxifiez le trafic Webhook, conservez le mot de passe BlueBubbles sur la requête de bout en bout. `gateway.trustedProxies` ne remplace pas `channels.bluebubbles.password` ici. Voir [Sécurité du Gateway](/fr/gateway/security#reverse-proxy-configuration).
|
||||
- Activez HTTPS et des règles de pare-feu sur le serveur BlueBubbles si vous l’exposez en dehors de votre réseau local.
|
||||
|
||||
## Dépannage
|
||||
|
||||
- Si les événements de saisie/lecture cessent de fonctionner, vérifiez les journaux Webhook de BlueBubbles et confirmez que le chemin du Gateway correspond à `channels.bluebubbles.webhookPath`.
|
||||
- Les codes d’appairage expirent après une heure ; utilisez `openclaw pairing list bluebubbles` et `openclaw pairing approve bluebubbles <code>`.
|
||||
- Les réactions nécessitent l’API privée BlueBubbles (`POST /api/v1/message/react`) ; assurez-vous que la version du serveur l’expose.
|
||||
- Modifier/annuler l’envoi nécessite macOS 13+ et une version compatible du serveur BlueBubbles. Sur macOS 26 (Tahoe), la modification est actuellement cassée en raison de changements de l’API privée.
|
||||
- Les mises à jour d’icône de groupe peuvent être peu fiables sur macOS 26 (Tahoe) : l’API peut renvoyer un succès alors que la nouvelle icône ne se synchronise pas.
|
||||
- OpenClaw masque automatiquement les actions connues comme cassées en fonction de la version macOS du serveur BlueBubbles. Si la modification apparaît encore sur macOS 26 (Tahoe), désactivez-la manuellement avec `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` est activé mais les envois scindés (par ex. `Dump` + URL) arrivent toujours en deux tours : consultez la liste de vérification du [dépannage de la fusion des envois scindés](#split-send-coalescing-troubleshooting) - les causes courantes sont une fenêtre anti-rebond trop courte, des horodatages de journal de session interprétés à tort comme l’arrivée du Webhook, ou un envoi de citation de réponse (qui utilise `replyToBody`, pas un second Webhook).
|
||||
- Pour les informations d’état/santé : `openclaw status --all` ou `openclaw status --deep`.
|
||||
|
||||
Pour une référence générale du workflow de canal, consultez [Canaux](/fr/channels) et le guide [Plugins](/fr/tools/plugin).
|
||||
|
||||
## Associés
|
||||
|
||||
- [Routage des canaux](/fr/channels/channel-routing) - routage de session pour les messages
|
||||
- [Vue d’ensemble des canaux](/fr/channels) - tous les canaux pris en charge
|
||||
- [Groupes](/fr/channels/groups) - comportement des discussions de groupe et contrôle des mentions
|
||||
- [Appairage](/fr/channels/pairing) - authentification des MP et flux d’appairage
|
||||
- [Sécurité](/fr/gateway/security) - modèle d’accès et renforcement
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Vous installez, configurez ou auditez le Plugin bluebubbles
|
||||
summary: Ajoute la surface de canal BlueBubbles pour l’envoi et la réception de messages OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T07:12:17Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Ajoute la surface de canal BlueBubbles pour l’envoi et la réception de messages OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Paquet : `@openclaw/bluebubbles`
|
||||
- Mode d’installation : npm ; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Documentation connexe
|
||||
|
||||
- [bluebubbles](/fr/channels/bluebubbles)
|
||||
@ -1290,7 +1290,7 @@ Variables are case-insensitive. `{think}` is an alias for `{thinkingLevel}`.
|
||||
- Per-channel overrides: `channels.<channel>.ackReaction`, `channels.<channel>.accounts.<id>.ackReaction`.
|
||||
- Resolution order: account → channel → `messages.ackReaction` → identity fallback.
|
||||
- Scope: `group-mentions` (default), `group-all`, `direct`, `all`.
|
||||
- `removeAckAfterReply`: removes ack after reply on reaction-capable channels such as Slack, Discord, Telegram, WhatsApp, and BlueBubbles.
|
||||
- `removeAckAfterReply`: removes ack after reply on reaction-capable channels such as Slack, Discord, Telegram, WhatsApp, and iMessage.
|
||||
- `messages.statusReactions.enabled`: enables lifecycle status reactions on Slack, Discord, and Telegram.
|
||||
On Slack and Discord, unset keeps status reactions enabled when ack reactions are active.
|
||||
On Telegram, set it explicitly to `true` to enable lifecycle status reactions.
|
||||
|
||||
@ -581,32 +581,12 @@ When Mattermost native commands are enabled:
|
||||
- `channels.signal.configWrites`: allow or deny Signal-initiated config writes.
|
||||
- Optional `channels.signal.defaultAccount` overrides default account selection when it matches a configured account id.
|
||||
|
||||
### BlueBubbles
|
||||
|
||||
BlueBubbles is the legacy iMessage bridge (plugin-backed, configured under `channels.bluebubbles`). Existing setups remain supported, but new OpenClaw iMessage deployments should prefer `channels.imessage` when `imsg` can run on the Messages host.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
dmPolicy: "pairing",
|
||||
// serverUrl, password, webhookPath, group controls, and advanced actions:
|
||||
// see /channels/bluebubbles
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- Core key paths covered here: `channels.bluebubbles`, `channels.bluebubbles.dmPolicy`.
|
||||
- Optional `channels.bluebubbles.defaultAccount` overrides default account selection when it matches a configured account id.
|
||||
- Top-level `bindings[]` entries with `type: "acp"` can bind BlueBubbles conversations to persistent ACP sessions. Use a BlueBubbles handle or target string (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`) in `match.peer.id`. Shared field semantics: [ACP Agents](/tools/acp-agents#persistent-channel-bindings).
|
||||
- Full BlueBubbles channel configuration and deprecation rationale are documented in [BlueBubbles](/channels/bluebubbles).
|
||||
|
||||
### iMessage
|
||||
|
||||
OpenClaw spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required. This is the preferred path for new OpenClaw iMessage setups when the host can grant Messages database and Automation permissions.
|
||||
|
||||
If the Gateway is not running on the signed-in Messages Mac, keep `channels.imessage.enabled=true` and set `channels.imessage.cliPath` to an SSH wrapper that runs `imsg "$@"` on that Mac. The default local `imsg` path is macOS-only.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
|
||||
@ -102,7 +102,7 @@ Outside heartbeats, stray `HEARTBEAT_OK` at the start/end of a message is stripp
|
||||
lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
|
||||
isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history)
|
||||
skipWhenBusy: false, // default: false; true also waits for subagent/nested lanes
|
||||
target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "bluebubbles")
|
||||
target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "imessage")
|
||||
to: "+15551234567", // optional channel-specific override
|
||||
accountId: "ops-bot", // optional multi-account channel id
|
||||
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
|
||||
|
||||
@ -670,22 +670,22 @@ and troubleshooting see the main [FAQ](/help/faq).
|
||||
No. OpenClaw runs on macOS or Linux (Windows via WSL2). A Mac mini is optional - some people
|
||||
buy one as an always-on host, but a small VPS, home server, or Raspberry Pi-class box works too.
|
||||
|
||||
You only need a Mac **for macOS-only tools**. For iMessage, use [BlueBubbles](/channels/bluebubbles) (recommended) - the BlueBubbles server runs on any Mac, and the Gateway can run on Linux or elsewhere. If you want other macOS-only tools, run the Gateway on a Mac or pair a macOS node.
|
||||
You only need a Mac **for macOS-only tools**. For iMessage, use [iMessage](/channels/imessage) with `imsg` on any Mac signed into Messages. If the Gateway runs on Linux or elsewhere, set `channels.imessage.cliPath` to an SSH wrapper that runs `imsg` on that Mac. If you want other macOS-only tools, run the Gateway on a Mac or pair a macOS node.
|
||||
|
||||
Docs: [BlueBubbles](/channels/bluebubbles), [Nodes](/nodes), [Mac remote mode](/platforms/mac/remote).
|
||||
Docs: [iMessage](/channels/imessage), [Nodes](/nodes), [Mac remote mode](/platforms/mac/remote).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Do I need a Mac mini for iMessage support?">
|
||||
You need **some macOS device** signed into Messages. It does **not** have to be a Mac mini -
|
||||
any Mac works. **Use [BlueBubbles](/channels/bluebubbles)** (recommended) for iMessage - the BlueBubbles server runs on macOS, while the Gateway can run on Linux or elsewhere.
|
||||
any Mac works. **Use [iMessage](/channels/imessage)** with `imsg`; the Gateway can run on that Mac, or it can run elsewhere with an SSH wrapper `cliPath`.
|
||||
|
||||
Common setups:
|
||||
|
||||
- Run the Gateway on Linux/VPS, and run the BlueBubbles server on any Mac signed into Messages.
|
||||
- Run the Gateway on Linux/VPS, and set `channels.imessage.cliPath` to an SSH wrapper that runs `imsg` on a Mac signed into Messages.
|
||||
- Run everything on the Mac if you want the simplest single-machine setup.
|
||||
|
||||
Docs: [BlueBubbles](/channels/bluebubbles), [Nodes](/nodes),
|
||||
Docs: [iMessage](/channels/imessage), [Nodes](/nodes),
|
||||
[Mac remote mode](/platforms/mac/remote).
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Menyiapkan saluran BlueBubbles
|
||||
- Pemecahan masalah pemasangan Webhook
|
||||
- Mengonfigurasi iMessage di macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Dukungan iMessage lama melalui server macOS BlueBubbles (kirim/terima REST, mengetik, reaksi, pemasangan, tindakan lanjutan).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:53Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: Plugin warisan bawaan yang berkomunikasi dengan server macOS BlueBubbles melalui HTTP. Setup BlueBubbles yang sudah ada tetap berfungsi, tetapi deployment OpenClaw iMessage baru sebaiknya memilih Plugin [iMessage](/id/channels/imessage) native ketika persyaratannya sesuai dengan host Anda.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles tidak digunakan lagi untuk setup OpenClaw baru.
|
||||
|
||||
Ekosistem upstream BlueBubbles masih aktif, tetapi OpenClaw bergantung pada API server macOS BlueBubbles. Per 6 Mei 2026, cabang pengembangan resmi [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) terakhir berubah pada [22 Januari 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), dan rilis server terbaru ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) diterbitkan pada 16 Mei 2025. Aplikasi klien dan repositori helper memiliki aktivitas yang lebih baru, jadi ini bukan klaim bahwa proyek ditinggalkan; penghentian ini bertujuan mengurangi ketergantungan OpenClaw pada server HTTP eksternal, webhook, dan permukaan kompatibilitas private-API ketika jalur native `imsg` menjaga integrasi tetap pada kontrak stdio lokal.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Rilis OpenClaw saat ini menyertakan BlueBubbles, sehingga build paket normal tidak memerlukan langkah `openclaw plugins install` terpisah.
|
||||
</Note>
|
||||
|
||||
## Gambaran umum
|
||||
|
||||
- Berjalan di macOS melalui aplikasi helper BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Fallback warisan untuk instalasi yang sudah bergantung pada ID channel BlueBubbles, status webhook, target grup, pengiriman cron, atau perutean workspace.
|
||||
- Direkomendasikan/diuji: macOS Sequoia (15). macOS Tahoe (26) berfungsi; edit saat ini rusak di Tahoe, dan pembaruan ikon grup mungkin melaporkan sukses tetapi tidak tersinkron.
|
||||
- OpenClaw berkomunikasi dengannya melalui REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Pesan masuk tiba melalui webhook; balasan keluar, indikator mengetik, tanda dibaca, dan tapback adalah panggilan REST.
|
||||
- Lampiran dan stiker diserap sebagai media masuk (dan ditampilkan ke agent bila memungkinkan).
|
||||
- Balasan Auto-TTS yang mensintesis audio MP3 atau CAF dikirim sebagai gelembung voice memo iMessage, bukan lampiran file biasa.
|
||||
- Pairing/allowlist bekerja dengan cara yang sama seperti channel lain (`/channels/pairing` dll.) dengan `channels.bluebubbles.allowFrom` + kode pairing.
|
||||
- Reaksi ditampilkan sebagai event sistem seperti Slack/Telegram sehingga agent dapat "menyebutnya" sebelum membalas.
|
||||
- Fitur lanjutan: edit, unsend, reply threading, efek pesan, manajemen grup.
|
||||
|
||||
## Mulai cepat
|
||||
|
||||
<Steps>
|
||||
<Step title="Instal BlueBubbles">
|
||||
Instal server BlueBubbles di Mac Anda (ikuti instruksi di [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Aktifkan web API">
|
||||
Di konfigurasi BlueBubbles, aktifkan web API dan tetapkan kata sandi.
|
||||
</Step>
|
||||
<Step title="Konfigurasi OpenClaw">
|
||||
Jalankan `openclaw onboard` dan pilih BlueBubbles, atau konfigurasikan secara manual:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Arahkan webhook ke gateway">
|
||||
Arahkan webhook BlueBubbles ke gateway Anda (contoh: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Mulai gateway">
|
||||
Mulai gateway; gateway akan mendaftarkan handler webhook dan memulai pairing.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Keamanan**
|
||||
|
||||
- Selalu tetapkan kata sandi webhook.
|
||||
- Autentikasi webhook selalu diperlukan. OpenClaw menolak permintaan webhook BlueBubbles kecuali menyertakan password/guid yang cocok dengan `channels.bluebubbles.password` (misalnya `?password=<password>` atau `x-password`), terlepas dari topologi loopback/proxy.
|
||||
- Autentikasi kata sandi diperiksa sebelum membaca/mengurai body webhook penuh.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Menjaga Messages.app tetap aktif (setup VM / headless)
|
||||
|
||||
Beberapa setup VM macOS / selalu aktif dapat membuat Messages.app menjadi "idle" (event masuk berhenti hingga aplikasi dibuka/dibawa ke depan). Solusi sederhana adalah **menyentuh Messages setiap 5 menit** menggunakan AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Simpan AppleScript">
|
||||
Simpan ini sebagai `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Instal LaunchAgent">
|
||||
Simpan ini sebagai `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Ini berjalan **setiap 300 detik** dan **saat login**. Jalankan pertama mungkin memicu prompt **Automation** macOS (`osascript` → Messages). Setujui prompt tersebut dalam sesi pengguna yang sama yang menjalankan LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Muat">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles tersedia dalam onboarding interaktif:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Wizard meminta:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Alamat server BlueBubbles (misalnya, `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Kata sandi API dari pengaturan BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Path endpoint webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open`, atau `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Nomor telepon, email, atau target chat.
|
||||
</ParamField>
|
||||
|
||||
Anda juga dapat menambahkan BlueBubbles melalui CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Kontrol akses (DM + grup)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- Default: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Pengirim tidak dikenal menerima kode pairing; pesan diabaikan hingga disetujui (kode kedaluwarsa setelah 1 jam).
|
||||
- Setujui melalui:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Pairing adalah pertukaran token default. Detail: [Pairing](/id/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Grup">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (default: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` mengontrol siapa yang dapat memicu di grup saat `allowlist` diatur.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Pengayaan nama kontak (macOS, opsional)
|
||||
|
||||
Webhook grup BlueBubbles sering kali hanya menyertakan alamat peserta mentah. Jika Anda ingin konteks `GroupMembers` menampilkan nama kontak lokal, Anda dapat mengaktifkan pengayaan Contacts lokal di macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` mengaktifkan pencarian. Default: `false`.
|
||||
- Pencarian hanya berjalan setelah akses grup, otorisasi perintah, dan mention gating mengizinkan pesan lewat.
|
||||
- Hanya peserta telepon tanpa nama yang diperkaya.
|
||||
- Nomor telepon mentah tetap menjadi fallback ketika tidak ada kecocokan lokal yang ditemukan.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Mention gating (grup)
|
||||
|
||||
BlueBubbles mendukung mention gating untuk chat grup, sesuai perilaku iMessage/WhatsApp:
|
||||
|
||||
- Menggunakan `agents.list[].groupChat.mentionPatterns` (atau `messages.groupChat.mentionPatterns`) untuk mendeteksi mention.
|
||||
- Ketika `requireMention` diaktifkan untuk sebuah grup, agent hanya merespons saat disebut.
|
||||
- Perintah kontrol dari pengirim berwenang melewati mention gating.
|
||||
|
||||
Konfigurasi per grup:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Command gating
|
||||
|
||||
- Perintah kontrol (misalnya, `/config`, `/model`) memerlukan otorisasi.
|
||||
- Menggunakan `allowFrom` dan `groupAllowFrom` untuk menentukan otorisasi perintah.
|
||||
- Pengirim berwenang dapat menjalankan perintah kontrol bahkan tanpa mention di grup.
|
||||
|
||||
### System prompt per grup
|
||||
|
||||
Setiap entri di bawah `channels.bluebubbles.groups.*` menerima string `systemPrompt` opsional. Nilai tersebut disuntikkan ke system prompt agent pada setiap turn yang menangani pesan di grup tersebut, sehingga Anda dapat menetapkan persona atau aturan perilaku per grup tanpa mengedit prompt agent:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Kunci cocok dengan apa pun yang dilaporkan BlueBubbles sebagai `chatGuid` / `chatIdentifier` / `chatId` numerik untuk grup tersebut, dan entri wildcard `"*"` menyediakan default untuk setiap grup tanpa kecocokan persis (pola yang sama digunakan oleh `requireMention` dan kebijakan tool per grup). Kecocokan persis selalu menang atas wildcard. DM mengabaikan field ini; gunakan kustomisasi prompt tingkat agent atau tingkat akun sebagai gantinya.
|
||||
|
||||
#### Contoh lengkap: balasan berutas dan reaksi tapback (Private API)
|
||||
|
||||
Dengan BlueBubbles Private API diaktifkan, pesan masuk tiba dengan ID pesan pendek (misalnya `[[reply_to:5]]`) dan agent dapat memanggil `action=reply` untuk membuat thread ke pesan tertentu atau `action=react` untuk mengirim tapback. `systemPrompt` per grup adalah cara yang andal agar agent memilih tool yang tepat:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Reaksi tapback dan balasan berutas sama-sama memerlukan BlueBubbles Private API; lihat [Tindakan lanjutan](#advanced-actions) dan [ID pesan](#message-ids-short-vs-full) untuk mekanisme dasarnya.
|
||||
|
||||
## Binding percakapan ACP
|
||||
|
||||
Chat BlueBubbles dapat diubah menjadi workspace ACP yang tahan lama tanpa mengubah lapisan transport.
|
||||
|
||||
Alur operator cepat:
|
||||
|
||||
- Jalankan `/acp spawn codex --bind here` di dalam DM atau chat grup yang diizinkan.
|
||||
- Pesan berikutnya dalam percakapan BlueBubbles yang sama dirutekan ke sesi ACP yang dibuat.
|
||||
- `/new` dan `/reset` mereset sesi ACP terikat yang sama di tempat.
|
||||
- `/acp close` menutup sesi ACP dan menghapus binding.
|
||||
|
||||
Binding persisten terkonfigurasi juga didukung melalui entri `bindings[]` tingkat atas dengan `type: "acp"` dan `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` dapat menggunakan bentuk target BlueBubbles apa pun yang didukung:
|
||||
|
||||
- handle DM ternormalisasi seperti `+15555550123` atau `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Untuk binding grup yang stabil, utamakan `chat_id:*` atau `chat_identifier:*`.
|
||||
|
||||
Contoh:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Lihat [Agen ACP](/id/tools/acp-agents) untuk perilaku binding ACP bersama.
|
||||
|
||||
## Pengetikan + tanda terima dibaca
|
||||
|
||||
- **Indikator pengetikan**: Dikirim otomatis sebelum dan selama pembuatan respons.
|
||||
- **Tanda terima dibaca**: Dikontrol oleh `channels.bluebubbles.sendReadReceipts` (default: `true`).
|
||||
- **Indikator pengetikan**: OpenClaw mengirim peristiwa mulai mengetik; BlueBubbles menghapus status mengetik secara otomatis saat pesan dikirim atau waktu habis (penghentian manual lewat DELETE tidak andal).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Tindakan lanjutan
|
||||
|
||||
BlueBubbles mendukung tindakan pesan lanjutan saat diaktifkan dalam config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Tindakan yang tersedia">
|
||||
- **react**: Tambahkan/hapus reaksi tapback (`messageId`, `emoji`, `remove`). Set tapback native iMessage adalah `love`, `like`, `dislike`, `laugh`, `emphasize`, dan `question`. Saat agen memilih emoji di luar set itu (misalnya `👀`), alat reaksi akan fallback ke `love` agar tapback tetap dirender alih-alih menggagalkan seluruh permintaan. Reaksi ack yang dikonfigurasi tetap divalidasi secara ketat dan menghasilkan error pada nilai yang tidak dikenal.
|
||||
- **edit**: Edit pesan yang sudah dikirim (`messageId`, `text`).
|
||||
- **unsend**: Batalkan pengiriman pesan (`messageId`).
|
||||
- **reply**: Balas pesan tertentu (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Kirim dengan efek iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Ganti nama chat grup (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Tetapkan ikon/foto chat grup (`chatGuid`, `media`) - tidak stabil di macOS 26 Tahoe (API dapat mengembalikan sukses tetapi ikon tidak disinkronkan).
|
||||
- **addParticipant**: Tambahkan seseorang ke grup (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Hapus seseorang dari grup (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Keluar dari chat grup (`chatGuid`).
|
||||
- **upload-file**: Kirim media/file (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Memo suara: tetapkan `asVoice: true` dengan audio **MP3** atau **CAF** untuk mengirim sebagai pesan suara iMessage. BlueBubbles mengonversi MP3 → CAF saat mengirim memo suara.
|
||||
- Alias lama: `sendAttachment` masih berfungsi, tetapi `upload-file` adalah nama tindakan kanonis.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID pesan (pendek vs lengkap)
|
||||
|
||||
OpenClaw dapat menampilkan ID pesan _pendek_ (misalnya, `1`, `2`) untuk menghemat token.
|
||||
|
||||
- `MessageSid` / `ReplyToId` dapat berupa ID pendek.
|
||||
- `MessageSidFull` / `ReplyToIdFull` berisi ID lengkap provider.
|
||||
- ID pendek berada dalam memori; ID tersebut dapat kedaluwarsa saat restart atau eviksi cache.
|
||||
- Tindakan menerima `messageId` pendek atau lengkap, tetapi ID pendek akan error jika sudah tidak tersedia.
|
||||
|
||||
Gunakan ID lengkap untuk otomatisasi dan penyimpanan yang tahan lama:
|
||||
|
||||
- Template: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Konteks: `MessageSidFull` / `ReplyToIdFull` dalam payload masuk
|
||||
|
||||
Lihat [Konfigurasi](/id/gateway/configuration) untuk variabel template.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Menggabungkan DM split-send (perintah + URL dalam satu komposisi)
|
||||
|
||||
Saat pengguna mengetik perintah dan URL bersama di iMessage - misalnya `Dump https://example.com/article` - Apple membagi pengiriman menjadi **dua pengiriman webhook terpisah**:
|
||||
|
||||
1. Pesan teks (`"Dump"`).
|
||||
2. Balon pratinjau URL (`"https://..."`) dengan gambar pratinjau OG sebagai lampiran.
|
||||
|
||||
Kedua webhook tiba di OpenClaw dengan jeda ~0,8-2,0 dtk pada sebagian besar setup. Tanpa penggabungan, agen menerima perintah saja pada giliran 1, membalas (sering kali "kirimkan URL-nya"), dan baru melihat URL pada giliran 2 - ketika konteks perintah sudah hilang.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` memilih DM untuk menggabungkan webhook berurutan dari pengirim yang sama ke dalam satu giliran agen. Chat grup tetap dikunci per pesan sehingga struktur giliran multi-pengguna dipertahankan.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Kapan mengaktifkan">
|
||||
Aktifkan saat:
|
||||
|
||||
- Anda mengirim Skills yang mengharapkan `command + payload` dalam satu pesan (dump, paste, save, queue, dll.).
|
||||
- Pengguna Anda menempelkan URL, gambar, atau konten panjang bersama perintah.
|
||||
- Anda dapat menerima latensi giliran DM tambahan (lihat di bawah).
|
||||
|
||||
Biarkan nonaktif saat:
|
||||
|
||||
- Anda memerlukan latensi perintah minimum untuk pemicu DM satu kata.
|
||||
- Semua alur Anda adalah perintah sekali jalan tanpa tindak lanjut payload.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Mengaktifkan">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Dengan flag aktif dan tanpa `messages.inbound.byChannel.bluebubbles` eksplisit, jendela debounce melebar menjadi **2500 md** (default untuk non-penggabungan adalah 500 md). Jendela yang lebih lebar diperlukan - irama split-send Apple sebesar 0,8-2,0 dtk tidak muat dalam default yang lebih sempit.
|
||||
|
||||
Untuk menyesuaikan jendela sendiri:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-off">
|
||||
- **Latensi tambahan untuk perintah kontrol DM.** Dengan flag aktif, pesan perintah kontrol DM (seperti `Dump`, `Save`, dll.) kini menunggu hingga jendela debounce sebelum didispatch, untuk berjaga-jaga jika webhook payload akan datang. Perintah chat grup tetap didispatch instan.
|
||||
- **Output gabungan dibatasi** - teks gabungan dibatasi 4000 karakter dengan penanda `…[truncated]` eksplisit; lampiran dibatasi 20; entri sumber dibatasi 10 (pertama-plus-terbaru dipertahankan setelah itu). Setiap `messageId` sumber tetap mencapai dedupe masuk sehingga replay MessagePoller berikutnya dari peristiwa individual apa pun dikenali sebagai duplikat.
|
||||
- **Opt-in, per-channel.** Channel lain (Telegram, WhatsApp, Slack, …) tidak terpengaruh.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Skenario dan apa yang dilihat agen
|
||||
|
||||
| Pengguna menyusun | Apple mengirim | Flag nonaktif (default) | Flag aktif + jendela 2500 md |
|
||||
| ----------------------------------------------------------------- | ------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (satu pengiriman) | 2 webhook berjarak ~1 dtk | Dua giliran agen: "Dump" saja, lalu URL | Satu giliran: teks gabungan `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (lampiran + teks) | 2 webhook | Dua giliran | Satu giliran: teks + gambar |
|
||||
| `/status` (perintah mandiri) | 1 webhook | Dispatch instan | **Tunggu hingga jendela, lalu dispatch** |
|
||||
| URL ditempel sendiri | 1 webhook | Dispatch instan | Dispatch instan (hanya satu entri dalam bucket) |
|
||||
| Teks + URL dikirim sebagai dua pesan terpisah yang disengaja, berselang menit | 2 webhook di luar jendela | Dua giliran | Dua giliran (jendela kedaluwarsa di antara keduanya) |
|
||||
| Flood cepat (>10 DM kecil di dalam jendela) | N webhook | N giliran | Satu giliran, output dibatasi (pertama + terbaru, batas teks/lampiran diterapkan) |
|
||||
|
||||
### Pemecahan masalah penggabungan split-send
|
||||
|
||||
Jika flag aktif dan split-send masih tiba sebagai dua giliran, periksa tiap lapisan:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config benar-benar dimuat">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Lalu `openclaw gateway restart` - flag dibaca saat pembuatan debouncer-registry.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Jendela debounce cukup lebar untuk setup Anda">
|
||||
Lihat log server BlueBubbles di `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Ukur jarak antara dispatch teks bergaya `"Dump"` dan dispatch `"https://..."; Attachments:` yang mengikutinya. Naikkan `messages.inbound.byChannel.bluebubbles` agar cukup nyaman menutup celah tersebut.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Timestamp JSONL sesi ≠ kedatangan webhook">
|
||||
Timestamp peristiwa sesi (`~/.openclaw/agents/<id>/sessions/*.jsonl`) mencerminkan kapan gateway menyerahkan pesan ke agen, **bukan** kapan webhook tiba. Pesan kedua yang diantrekan dengan tag `[Queued messages while agent was busy]` berarti giliran pertama masih berjalan saat webhook kedua tiba - bucket penggabungan sudah di-flush. Sesuaikan jendela berdasarkan log server BB, bukan log sesi.
|
||||
</Accordion>
|
||||
<Accordion title="Tekanan memori memperlambat dispatch balasan">
|
||||
Pada mesin yang lebih kecil (8 GB), giliran agen dapat memakan waktu cukup lama sehingga bucket penggabungan di-flush sebelum balasan selesai, dan URL masuk sebagai giliran kedua yang diantrekan. Periksa `memory_pressure` dan `ps -o rss -p $(pgrep openclaw-gateway)`; jika gateway melebihi ~500 MB RSS dan kompresor aktif, tutup proses berat lainnya atau pindah ke host yang lebih besar.
|
||||
</Accordion>
|
||||
<Accordion title="Pengiriman kutipan balasan adalah jalur berbeda">
|
||||
Jika pengguna mengetuk `Dump` sebagai **balasan** ke balon URL yang sudah ada (iMessage menampilkan badge "1 Reply" pada balon Dump), URL berada di `replyToBody`, bukan di webhook kedua. Penggabungan tidak berlaku - itu urusan skill/prompt, bukan urusan debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Streaming blok
|
||||
|
||||
Kontrol apakah respons dikirim sebagai satu pesan atau distream dalam blok:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Media + batas
|
||||
|
||||
- Lampiran masuk diunduh dan disimpan di cache media.
|
||||
- Batas media melalui `channels.bluebubbles.mediaMaxMb` untuk media masuk dan keluar (default: 8 MB).
|
||||
- Teks keluar dipecah menjadi chunk ke `channels.bluebubbles.textChunkLimit` (default: 4000 karakter).
|
||||
|
||||
## Referensi konfigurasi
|
||||
|
||||
Konfigurasi lengkap: [Konfigurasi](/id/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Connection and webhook">
|
||||
- `channels.bluebubbles.enabled`: Aktifkan/nonaktifkan channel.
|
||||
- `channels.bluebubbles.serverUrl`: URL dasar REST API BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Kata sandi API.
|
||||
- `channels.bluebubbles.webhookPath`: Path endpoint Webhook (default: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Access policy">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (default: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Allowlist DM (handle, email, nomor E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (default: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Allowlist pengirim grup.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Di macOS, secara opsional perkaya peserta grup tanpa nama dari Kontak lokal setelah gating lolos. Default: `false`.
|
||||
- `channels.bluebubbles.groups`: Konfigurasi per grup (`requireMention`, dll.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Delivery and chunking">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Kirim tanda terima dibaca (default: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Aktifkan streaming blok (default: `false`; diperlukan untuk balasan streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Ukuran chunk keluar dalam karakter (default: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Timeout per permintaan dalam ms untuk pengiriman teks keluar melalui `/api/v1/message/text` (default: 30000). Naikkan pada setup macOS 26 tempat pengiriman Private API iMessage dapat macet selama 60+ detik di dalam framework iMessage; misalnya `45000` atau `60000`. Probe, pencarian chat, reaksi, edit, dan pemeriksaan kesehatan saat ini tetap memakai default 10 detik yang lebih pendek; perluasan cakupan ke reaksi dan edit direncanakan sebagai tindak lanjut. Override per akun: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (default) hanya memecah saat melebihi `textChunkLimit`; `newline` memecah pada baris kosong (batas paragraf) sebelum chunking berdasarkan panjang.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Media and history">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Batas media masuk/keluar dalam MB (default: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Allowlist eksplisit direktori lokal absolut yang diizinkan untuk path media lokal keluar. Pengiriman path lokal ditolak secara default kecuali ini dikonfigurasi. Override per akun: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Gabungkan Webhook DM berurutan dari pengirim yang sama menjadi satu giliran agen sehingga split-send teks+URL Apple tiba sebagai satu pesan (default: `false`). Lihat [Menggabungkan DM split-send](#coalescing-split-send-dms-command--url-in-one-composition) untuk skenario, penyetelan window, dan trade-off. Memperlebar window debounce masuk default dari 500 ms menjadi 2500 ms saat diaktifkan tanpa `messages.inbound.byChannel.bluebubbles` eksplisit.
|
||||
- `channels.bluebubbles.historyLimit`: Jumlah maksimum pesan grup untuk konteks (0 menonaktifkan).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Batas riwayat DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Saat balasan masuk tiba tanpa `replyToBody`/`replyToSender` dan cache konteks balasan dalam memori meleset, ambil pesan asli dari HTTP API BlueBubbles sebagai fallback best-effort (default: `false`). Berguna untuk deployment multi-instance yang berbagi satu akun BlueBubbles, setelah proses dimulai ulang, atau setelah penggusuran cache TTL/LRU berumur panjang. Pengambilan dilindungi SSRF oleh kebijakan yang sama seperti setiap permintaan klien BlueBubbles lainnya, tidak pernah melempar error, dan mengisi cache sehingga balasan berikutnya teramortisasi. Override per akun: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Pengaturan tingkat channel dipropagasikan ke akun yang menghilangkan flag tersebut.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Actions and accounts">
|
||||
- `channels.bluebubbles.actions`: Aktifkan/nonaktifkan tindakan tertentu.
|
||||
- `channels.bluebubbles.accounts`: Konfigurasi multi-akun.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Opsi global terkait:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (atau `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Pengalamatan / target pengiriman
|
||||
|
||||
Utamakan `chat_guid` untuk perutean yang stabil:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (diutamakan untuk grup)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Handle langsung: `+15555550123`, `user@example.com`
|
||||
- Jika handle langsung tidak memiliki chat DM yang sudah ada, OpenClaw akan membuatnya melalui `POST /api/v1/chat/new`. Ini memerlukan BlueBubbles Private API diaktifkan.
|
||||
|
||||
### Perutean iMessage vs SMS
|
||||
|
||||
Saat handle yang sama memiliki chat iMessage dan SMS di Mac (misalnya nomor telepon yang terdaftar di iMessage tetapi juga pernah menerima fallback gelembung hijau), OpenClaw mengutamakan chat iMessage dan tidak pernah diam-diam menurunkan ke SMS. Untuk memaksa chat SMS, gunakan prefiks target `sms:` eksplisit (misalnya `sms:+15555550123`). Handle tanpa chat iMessage yang cocok tetap dikirim melalui chat apa pun yang dilaporkan BlueBubbles.
|
||||
|
||||
## Keamanan
|
||||
|
||||
- Permintaan Webhook diautentikasi dengan membandingkan parameter query atau header `guid`/`password` terhadap `channels.bluebubbles.password`.
|
||||
- Jaga kata sandi API dan endpoint Webhook tetap rahasia (perlakukan seperti kredensial).
|
||||
- Tidak ada bypass localhost untuk autentikasi Webhook BlueBubbles. Jika Anda mem-proxy traffic Webhook, pertahankan kata sandi BlueBubbles pada permintaan dari ujung ke ujung. `gateway.trustedProxies` tidak menggantikan `channels.bluebubbles.password` di sini. Lihat [Keamanan Gateway](/id/gateway/security#reverse-proxy-configuration).
|
||||
- Aktifkan aturan HTTPS + firewall pada server BlueBubbles jika mengeksposnya di luar LAN Anda.
|
||||
|
||||
## Pemecahan masalah
|
||||
|
||||
- Jika event mengetik/dibaca berhenti berfungsi, periksa log Webhook BlueBubbles dan verifikasi path Gateway cocok dengan `channels.bluebubbles.webhookPath`.
|
||||
- Kode pairing kedaluwarsa setelah satu jam; gunakan `openclaw pairing list bluebubbles` dan `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reaksi memerlukan private API BlueBubbles (`POST /api/v1/message/react`); pastikan versi server mengeksposnya.
|
||||
- Edit/unsend memerlukan macOS 13+ dan versi server BlueBubbles yang kompatibel. Di macOS 26 (Tahoe), edit saat ini rusak karena perubahan private API.
|
||||
- Pembaruan ikon grup bisa tidak stabil di macOS 26 (Tahoe): API dapat mengembalikan sukses tetapi ikon baru tidak disinkronkan.
|
||||
- OpenClaw otomatis menyembunyikan tindakan yang diketahui rusak berdasarkan versi macOS server BlueBubbles. Jika edit masih muncul di macOS 26 (Tahoe), nonaktifkan secara manual dengan `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` diaktifkan tetapi split-send (mis. `Dump` + URL) masih tiba sebagai dua giliran: lihat checklist [pemecahan masalah penggabungan split-send](#split-send-coalescing-troubleshooting) - penyebab umum adalah window debounce terlalu ketat, timestamp log sesi disalahartikan sebagai kedatangan Webhook, atau pengiriman kutipan balasan (yang menggunakan `replyToBody`, bukan Webhook kedua).
|
||||
- Untuk info status/kesehatan: `openclaw status --all` atau `openclaw status --deep`.
|
||||
|
||||
Untuk referensi alur kerja channel umum, lihat [Channel](/id/channels) dan panduan [Plugins](/id/tools/plugin).
|
||||
|
||||
## Terkait
|
||||
|
||||
- [Perutean Channel](/id/channels/channel-routing) - perutean sesi untuk pesan
|
||||
- [Ikhtisar Channel](/id/channels) - semua channel yang didukung
|
||||
- [Grup](/id/channels/groups) - perilaku chat grup dan gating mention
|
||||
- [Pairing](/id/channels/pairing) - autentikasi DM dan alur pairing
|
||||
- [Keamanan](/id/gateway/security) - model akses dan hardening
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Anda sedang menginstal, mengonfigurasi, atau mengaudit plugin bluebubbles
|
||||
summary: Menambahkan permukaan saluran BlueBubbles untuk mengirim dan menerima pesan OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T09:19:08Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Menambahkan permukaan saluran BlueBubbles untuk mengirim dan menerima pesan OpenClaw.
|
||||
|
||||
## Distribusi
|
||||
|
||||
- Paket: `@openclaw/bluebubbles`
|
||||
- Rute pemasangan: npm; ClawHub
|
||||
|
||||
## Permukaan
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Dokumentasi terkait
|
||||
|
||||
- [bluebubbles](/id/channels/bluebubbles)
|
||||
@ -2,7 +2,7 @@
|
||||
summary: "Run OpenClaw in a sandboxed macOS VM (local or hosted) when you need isolation or iMessage"
|
||||
read_when:
|
||||
- You want OpenClaw isolated from your main macOS environment
|
||||
- You want iMessage integration (BlueBubbles) in a sandbox
|
||||
- You want iMessage integration in a sandbox
|
||||
- You want a resettable macOS environment you can clone
|
||||
- You want to compare local vs hosted macOS VM options
|
||||
title: "macOS VMs"
|
||||
@ -14,7 +14,7 @@ title: "macOS VMs"
|
||||
- **Dedicated hardware** (Mac mini or Linux box) if you want full control and a **residential IP** for browser automation. Many sites block data center IPs, so local browsing often works better.
|
||||
- **Hybrid:** keep the Gateway on a cheap VPS, and connect your Mac as a **node** when you need browser/UI automation. See [Nodes](/nodes) and [Gateway remote](/gateway/remote).
|
||||
|
||||
Use a macOS VM when you specifically need macOS-only capabilities (iMessage/BlueBubbles) or want strict isolation from your daily Mac.
|
||||
Use a macOS VM when you specifically need macOS-only capabilities such as iMessage or want strict isolation from your daily Mac.
|
||||
|
||||
## macOS VM options
|
||||
|
||||
@ -25,7 +25,7 @@ Run OpenClaw in a sandboxed macOS VM on your existing Apple Silicon Mac using [L
|
||||
This gives you:
|
||||
|
||||
- Full macOS environment in isolation (your host stays clean)
|
||||
- iMessage support via BlueBubbles (impossible on Linux/Windows)
|
||||
- iMessage support via `imsg` (the default local path is impossible on Linux/Windows)
|
||||
- Instant reset by cloning VMs
|
||||
- No extra hardware or cloud costs
|
||||
|
||||
@ -198,24 +198,24 @@ ssh youruser@192.168.64.X "openclaw status"
|
||||
|
||||
## Bonus: iMessage integration
|
||||
|
||||
This is the killer feature of running on macOS. Use [BlueBubbles](https://bluebubbles.app) to add iMessage to OpenClaw.
|
||||
This is the killer feature of running on macOS. Use [iMessage](/channels/imessage) with `imsg` to add Messages to OpenClaw.
|
||||
|
||||
Inside the VM:
|
||||
|
||||
1. Download BlueBubbles from bluebubbles.app
|
||||
2. Sign in with your Apple ID
|
||||
3. Enable the Web API and set a password
|
||||
4. Point BlueBubbles webhooks at your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)
|
||||
1. Sign in to Messages.
|
||||
2. Install `imsg`.
|
||||
3. Grant Full Disk Access and Automation permission for the process running OpenClaw/`imsg`.
|
||||
4. Verify RPC support with `imsg rpc --help`.
|
||||
|
||||
Add to your OpenClaw config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
serverUrl: "http://localhost:1234",
|
||||
password: "your-api-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
imessage: {
|
||||
enabled: true,
|
||||
cliPath: "imsg",
|
||||
dbPath: "~/Library/Messages/chat.db",
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -223,7 +223,7 @@ Add to your OpenClaw config:
|
||||
|
||||
Restart the gateway. Now your agent can send and receive iMessages.
|
||||
|
||||
Full setup details: [BlueBubbles channel](/channels/bluebubbles)
|
||||
Full setup details: [iMessage channel](/channels/imessage)
|
||||
|
||||
---
|
||||
|
||||
@ -274,7 +274,7 @@ For true always-on, consider a dedicated Mac mini or a small VPS. See [VPS hosti
|
||||
- [VPS hosting](/vps)
|
||||
- [Nodes](/nodes)
|
||||
- [Gateway remote](/gateway/remote)
|
||||
- [BlueBubbles channel](/channels/bluebubbles)
|
||||
- [iMessage channel](/channels/imessage)
|
||||
- [Lume Quickstart](https://cua.ai/docs/lume/guide/getting-started/quickstart)
|
||||
- [Lume CLI Reference](https://cua.ai/docs/lume/reference/cli-reference)
|
||||
- [Unattended VM Setup](https://cua.ai/docs/lume/guide/fundamentals/unattended-setup) (advanced)
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Configurazione del canale BlueBubbles
|
||||
- Risoluzione dei problemi di associazione Webhook
|
||||
- Configurare iMessage su macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Supporto iMessage legacy tramite il server macOS BlueBubbles (invio/ricezione REST, digitazione, reazioni, abbinamento, azioni avanzate).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:51:00Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Stato: Plugin legacy incluso che comunica con il server macOS BlueBubbles tramite HTTP. Le configurazioni BlueBubbles esistenti continuano a funzionare, ma le nuove distribuzioni OpenClaw iMessage dovrebbero preferire il Plugin nativo [iMessage](/it/channels/imessage) quando i suoi requisiti sono adatti al tuo host.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles è deprecato per le nuove configurazioni OpenClaw.
|
||||
|
||||
L'ecosistema upstream di BlueBubbles è ancora attivo, ma OpenClaw dipende dall'API del server macOS BlueBubbles. Al 6 maggio 2026, il ramo di sviluppo ufficiale di [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) è stato modificato l'ultima volta il [22 gennaio 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), e l'ultima versione del server ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) è stata pubblicata il 16 maggio 2025. L'app client e i repository di supporto hanno attività più recente, quindi questa non è un'affermazione di abbandono; la deprecazione riguarda la riduzione della dipendenza di OpenClaw da un server HTTP esterno, Webhook e una superficie di compatibilità con API private, quando il percorso nativo `imsg` mantiene l'integrazione su un contratto stdio locale.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Le versioni attuali di OpenClaw includono BlueBubbles, quindi le normali build pacchettizzate non richiedono un passaggio separato `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Panoramica
|
||||
|
||||
- Funziona su macOS tramite l'app helper BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Fallback legacy per installazioni che dipendono già dagli ID canale BlueBubbles, dallo stato dei Webhook, dalle destinazioni di gruppo, dalla consegna Cron o dal routing dello workspace.
|
||||
- Consigliato/testato: macOS Sequoia (15). macOS Tahoe (26) funziona; la modifica è attualmente non funzionante su Tahoe e gli aggiornamenti dell'icona di gruppo possono indicare successo senza sincronizzarsi.
|
||||
- OpenClaw comunica con esso tramite la sua API REST (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- I messaggi in arrivo arrivano tramite Webhook; le risposte in uscita, gli indicatori di digitazione, le conferme di lettura e i tapback sono chiamate REST.
|
||||
- Allegati e sticker vengono importati come contenuti multimediali in ingresso (e mostrati all'agente quando possibile).
|
||||
- Le risposte Auto-TTS che sintetizzano audio MP3 o CAF vengono recapitate come bolle di memo vocale iMessage invece che come semplici allegati file.
|
||||
- Abbinamento/allowlist funziona allo stesso modo degli altri canali (`/channels/pairing` ecc.) con `channels.bluebubbles.allowFrom` + codici di abbinamento.
|
||||
- Le reazioni vengono mostrate come eventi di sistema proprio come Slack/Telegram, così gli agenti possono "menzionarle" prima di rispondere.
|
||||
- Funzionalità avanzate: modifica, annullamento invio, threading delle risposte, effetti dei messaggi, gestione dei gruppi.
|
||||
|
||||
## Avvio rapido
|
||||
|
||||
<Steps>
|
||||
<Step title="Installa BlueBubbles">
|
||||
Installa il server BlueBubbles sul tuo Mac (segui le istruzioni su [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Abilita l'API web">
|
||||
Nella configurazione BlueBubbles, abilita l'API web e imposta una password.
|
||||
</Step>
|
||||
<Step title="Configura OpenClaw">
|
||||
Esegui `openclaw onboard` e seleziona BlueBubbles, oppure configura manualmente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Punta i Webhook al Gateway">
|
||||
Punta i Webhook BlueBubbles al tuo Gateway (esempio: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Avvia il Gateway">
|
||||
Avvia il Gateway; registrerà il gestore Webhook e inizierà l'abbinamento.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Sicurezza**
|
||||
|
||||
- Imposta sempre una password per il Webhook.
|
||||
- L'autenticazione Webhook è sempre obbligatoria. OpenClaw rifiuta le richieste Webhook BlueBubbles a meno che includano una password/guid che corrisponda a `channels.bluebubbles.password` (per esempio `?password=<password>` o `x-password`), indipendentemente dalla topologia loopback/proxy.
|
||||
- L'autenticazione tramite password viene verificata prima della lettura/analisi completa dei corpi Webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Mantenere Messages.app attiva (configurazioni VM / headless)
|
||||
|
||||
Alcune configurazioni VM macOS / sempre attive possono finire con Messages.app in stato "inattivo" (gli eventi in arrivo si interrompono finché l'app non viene aperta/portata in primo piano). Una soluzione semplice è **sollecitare Messages ogni 5 minuti** usando AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Salva l'AppleScript">
|
||||
Salva questo come `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Installa un LaunchAgent">
|
||||
Salva questo come `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Questo viene eseguito **ogni 300 secondi** e **all'accesso**. La prima esecuzione potrebbe attivare prompt macOS **Automazione** (`osascript` → Messages). Approvalli nella stessa sessione utente che esegue il LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Caricalo">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles è disponibile nell'onboarding interattivo:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
La procedura guidata richiede:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Indirizzo del server BlueBubbles (ad es. `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Password API dalle impostazioni di BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Percorso dell'endpoint Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` o `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Numeri di telefono, email o destinazioni chat.
|
||||
</ParamField>
|
||||
|
||||
Puoi anche aggiungere BlueBubbles tramite CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Controllo degli accessi (DM + gruppi)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- Predefinito: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- I mittenti sconosciuti ricevono un codice di abbinamento; i messaggi vengono ignorati finché non sono approvati (i codici scadono dopo 1 ora).
|
||||
- Approva tramite:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- L'abbinamento è lo scambio di token predefinito. Dettagli: [Abbinamento](/it/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Gruppi">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (predefinito: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` controlla chi può attivare nei gruppi quando `allowlist` è impostato.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Arricchimento dei nomi dei contatti (macOS, facoltativo)
|
||||
|
||||
I Webhook di gruppo BlueBubbles spesso includono solo indirizzi grezzi dei partecipanti. Se vuoi che il contesto `GroupMembers` mostri invece i nomi dei contatti locali, puoi attivare l'arricchimento locale tramite Contatti su macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` abilita la ricerca. Predefinito: `false`.
|
||||
- Le ricerche vengono eseguite solo dopo che accesso al gruppo, autorizzazione dei comandi e gating delle menzioni hanno consentito il passaggio del messaggio.
|
||||
- Vengono arricchiti solo i partecipanti telefonici senza nome.
|
||||
- I numeri di telefono grezzi restano il fallback quando non viene trovata alcuna corrispondenza locale.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Gating delle menzioni (gruppi)
|
||||
|
||||
BlueBubbles supporta il gating delle menzioni per le chat di gruppo, corrispondente al comportamento iMessage/WhatsApp:
|
||||
|
||||
- Usa `agents.list[].groupChat.mentionPatterns` (o `messages.groupChat.mentionPatterns`) per rilevare le menzioni.
|
||||
- Quando `requireMention` è abilitato per un gruppo, l'agente risponde solo quando viene menzionato.
|
||||
- I comandi di controllo da mittenti autorizzati bypassano il gating delle menzioni.
|
||||
|
||||
Configurazione per gruppo:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Gating dei comandi
|
||||
|
||||
- I comandi di controllo (ad es. `/config`, `/model`) richiedono autorizzazione.
|
||||
- Usa `allowFrom` e `groupAllowFrom` per determinare l'autorizzazione dei comandi.
|
||||
- I mittenti autorizzati possono eseguire comandi di controllo anche senza menzionare nei gruppi.
|
||||
|
||||
### Prompt di sistema per gruppo
|
||||
|
||||
Ogni voce sotto `channels.bluebubbles.groups.*` accetta una stringa facoltativa `systemPrompt`. Il valore viene inserito nel prompt di sistema dell'agente a ogni turno che gestisce un messaggio in quel gruppo, così puoi impostare regole di persona o di comportamento per gruppo senza modificare i prompt dell'agente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
La chiave corrisponde a ciò che BlueBubbles segnala come `chatGuid` / `chatIdentifier` / `chatId` numerico per il gruppo, e una voce wildcard `"*"` fornisce un valore predefinito per ogni gruppo senza una corrispondenza esatta (lo stesso schema usato da `requireMention` e dalle policy degli strumenti per gruppo). Le corrispondenze esatte prevalgono sempre sulla wildcard. I DM ignorano questo campo; usa invece la personalizzazione del prompt a livello di agente o di account.
|
||||
|
||||
#### Esempio pratico: risposte in thread e reazioni tapback (API privata)
|
||||
|
||||
Con l'API privata BlueBubbles abilitata, i messaggi in ingresso arrivano con ID messaggio brevi (per esempio `[[reply_to:5]]`) e l'agente può chiamare `action=reply` per inserirsi in un messaggio specifico o `action=react` per lasciare un tapback. Un `systemPrompt` per gruppo è un modo affidabile per far scegliere all'agente lo strumento giusto:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Le reazioni tapback e le risposte in thread richiedono entrambe l'API privata BlueBubbles; vedi [Azioni avanzate](#advanced-actions) e [ID messaggio](#message-ids-short-vs-full) per i meccanismi sottostanti.
|
||||
|
||||
## Binding conversazione ACP
|
||||
|
||||
Le chat BlueBubbles possono essere trasformate in workspace ACP duraturi senza modificare il livello di trasporto.
|
||||
|
||||
Flusso rapido per operatore:
|
||||
|
||||
- Esegui `/acp spawn codex --bind here` nel DM o nella chat di gruppo consentita.
|
||||
- I messaggi futuri nella stessa conversazione BlueBubbles verranno instradati alla sessione ACP generata.
|
||||
- `/new` e `/reset` reimpostano sul posto la stessa sessione ACP associata.
|
||||
- `/acp close` chiude la sessione ACP e rimuove il binding.
|
||||
|
||||
Sono supportati anche binding persistenti configurati tramite voci di primo livello `bindings[]` con `type: "acp"` e `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` può usare qualsiasi formato di destinazione BlueBubbles supportato:
|
||||
|
||||
- handle DM normalizzato come `+15555550123` o `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Per associazioni di gruppo stabili, preferisci `chat_id:*` o `chat_identifier:*`.
|
||||
|
||||
Esempio:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Vedi [Agenti ACP](/it/tools/acp-agents) per il comportamento condiviso delle associazioni ACP.
|
||||
|
||||
## Indicatori di digitazione + conferme di lettura
|
||||
|
||||
- **Indicatori di digitazione**: inviati automaticamente prima e durante la generazione della risposta.
|
||||
- **Conferme di lettura**: controllate da `channels.bluebubbles.sendReadReceipts` (predefinito: `true`).
|
||||
- **Indicatori di digitazione**: OpenClaw invia eventi di inizio digitazione; BlueBubbles cancella automaticamente la digitazione all'invio o al timeout (l'arresto manuale tramite DELETE non è affidabile).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Azioni avanzate
|
||||
|
||||
BlueBubbles supporta azioni avanzate sui messaggi quando abilitate nella configurazione:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Azioni disponibili">
|
||||
- **react**: aggiungi/rimuovi reazioni tapback (`messageId`, `emoji`, `remove`). Il set tapback nativo di iMessage è `love`, `like`, `dislike`, `laugh`, `emphasize` e `question`. Quando un agente sceglie un'emoji fuori da quel set (per esempio `👀`), lo strumento di reazione ripiega su `love`, così il tapback viene comunque renderizzato invece di far fallire l'intera richiesta. Le reazioni di ack configurate sono comunque validate in modo rigoroso e generano errore su valori sconosciuti.
|
||||
- **edit**: modifica un messaggio inviato (`messageId`, `text`).
|
||||
- **unsend**: annulla l'invio di un messaggio (`messageId`).
|
||||
- **reply**: rispondi a un messaggio specifico (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: invia con effetto iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: rinomina una chat di gruppo (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: imposta l'icona/foto di una chat di gruppo (`chatGuid`, `media`) - instabile su macOS 26 Tahoe (l'API può restituire successo ma l'icona non viene sincronizzata).
|
||||
- **addParticipant**: aggiungi qualcuno a un gruppo (`chatGuid`, `address`).
|
||||
- **removeParticipant**: rimuovi qualcuno da un gruppo (`chatGuid`, `address`).
|
||||
- **leaveGroup**: lascia una chat di gruppo (`chatGuid`).
|
||||
- **upload-file**: invia media/file (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Memo vocali: imposta `asVoice: true` con audio **MP3** o **CAF** per inviare come messaggio vocale iMessage. BlueBubbles converte MP3 → CAF quando invia memo vocali.
|
||||
- Alias legacy: `sendAttachment` funziona ancora, ma `upload-file` è il nome canonico dell'azione.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID dei messaggi (brevi vs completi)
|
||||
|
||||
OpenClaw può esporre ID messaggio _brevi_ (ad es. `1`, `2`) per risparmiare token.
|
||||
|
||||
- `MessageSid` / `ReplyToId` possono essere ID brevi.
|
||||
- `MessageSidFull` / `ReplyToIdFull` contengono gli ID completi del provider.
|
||||
- Gli ID brevi sono in memoria; possono scadere al riavvio o all'espulsione dalla cache.
|
||||
- Le azioni accettano `messageId` breve o completo, ma gli ID brevi generano errore se non sono più disponibili.
|
||||
|
||||
Usa gli ID completi per automazioni e archiviazione durature:
|
||||
|
||||
- Template: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Contesto: `MessageSidFull` / `ReplyToIdFull` nei payload in ingresso
|
||||
|
||||
Vedi [Configurazione](/it/gateway/configuration) per le variabili di template.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Coalescenza dei DM con invio diviso (comando + URL in un'unica composizione)
|
||||
|
||||
Quando un utente digita insieme un comando e un URL in iMessage - ad es. `Dump https://example.com/article` - Apple divide l'invio in **due consegne Webhook separate**:
|
||||
|
||||
1. Un messaggio di testo (`"Dump"`).
|
||||
2. Un fumetto di anteprima URL (`"https://..."`) con immagini di anteprima OG come allegati.
|
||||
|
||||
I due Webhook arrivano a OpenClaw a circa 0,8-2,0 s di distanza nella maggior parte delle configurazioni. Senza coalescenza, l'agente riceve solo il comando al turno 1, risponde (spesso "inviami l'URL") e vede l'URL solo al turno 2, momento in cui il contesto del comando è già perso.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` abilita per un DM l'unione di Webhook consecutivi dello stesso mittente in un unico turno agente. Le chat di gruppo continuano a usare una chiave per messaggio, così la struttura dei turni multiutente viene preservata.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Quando abilitare">
|
||||
Abilita quando:
|
||||
|
||||
- Distribuisci Skills che si aspettano `command + payload` in un unico messaggio (dump, paste, save, queue, ecc.).
|
||||
- I tuoi utenti incollano URL, immagini o contenuti lunghi insieme ai comandi.
|
||||
- Puoi accettare la latenza aggiunta ai turni DM (vedi sotto).
|
||||
|
||||
Lascia disabilitato quando:
|
||||
|
||||
- Ti serve la latenza minima dei comandi per trigger DM di una sola parola.
|
||||
- Tutti i tuoi flussi sono comandi one-shot senza follow-up di payload.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Abilitazione">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Con il flag attivo e senza `messages.inbound.byChannel.bluebubbles` esplicito, la finestra di debounce si amplia a **2500 ms** (il valore predefinito senza coalescenza è 500 ms). La finestra più ampia è necessaria: la cadenza di invio diviso di Apple, pari a 0,8-2,0 s, non rientra nel valore predefinito più stretto.
|
||||
|
||||
Per regolare tu stesso la finestra:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Compromessi">
|
||||
- **Latenza aggiunta per i comandi di controllo DM.** Con il flag attivo, i messaggi di comando di controllo DM (come `Dump`, `Save`, ecc.) ora attendono fino alla finestra di debounce prima dell'invio, nel caso stia arrivando un Webhook di payload. I comandi nelle chat di gruppo mantengono l'invio istantaneo.
|
||||
- **L'output unito è limitato** - il testo unito è limitato a 4000 caratteri con un marcatore esplicito `…[truncated]`; gli allegati sono limitati a 20; le voci sorgente sono limitate a 10 (oltre tale limite vengono mantenute la prima e le più recenti). Ogni `messageId` sorgente raggiunge comunque la deduplica in ingresso, così una successiva riproduzione di MessagePoller di qualsiasi evento individuale viene riconosciuta come duplicato.
|
||||
- **Opt-in, per canale.** Gli altri canali (Telegram, WhatsApp, Slack, …) non sono interessati.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Scenari e cosa vede l'agente
|
||||
|
||||
| L'utente compone | Apple consegna | Flag disattivato (predefinito) | Flag attivo + finestra da 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (un invio) | 2 Webhook a ~1 s di distanza | Due turni agente: solo "Dump", poi URL | Un turno: testo unito `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (allegato + testo) | 2 Webhook | Due turni | Un turno: testo + immagine |
|
||||
| `/status` (comando autonomo) | 1 Webhook | Invio istantaneo | **Attesa fino alla finestra, poi invio** |
|
||||
| URL incollato da solo | 1 Webhook | Invio istantaneo | Invio istantaneo (solo una voce nel bucket) |
|
||||
| Testo + URL inviati come due messaggi separati deliberati, a minuti di distanza | 2 Webhook fuori dalla finestra | Due turni | Due turni (la finestra scade tra i due) |
|
||||
| Raffica rapida (>10 piccoli DM nella finestra) | N Webhook | N turni | Un turno, output limitato (prima + più recenti, limiti di testo/allegati applicati) |
|
||||
|
||||
### Risoluzione dei problemi della coalescenza degli invii divisi
|
||||
|
||||
Se il flag è attivo e gli invii divisi arrivano ancora come due turni, controlla ogni livello:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Configurazione effettivamente caricata">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Poi `openclaw gateway restart` - il flag viene letto alla creazione del registro dei debouncer.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Finestra di debounce abbastanza ampia per la tua configurazione">
|
||||
Guarda il log del server BlueBubbles in `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Misura l'intervallo tra l'invio del testo stile `"Dump"` e il successivo invio `"https://..."; Attachments:`. Aumenta `messages.inbound.byChannel.bluebubbles` fino a coprire comodamente quell'intervallo.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Timestamp JSONL di sessione ≠ arrivo del Webhook">
|
||||
I timestamp degli eventi di sessione (`~/.openclaw/agents/<id>/sessions/*.jsonl`) riflettono quando il gateway passa un messaggio all'agente, **non** quando è arrivato il Webhook. Un secondo messaggio in coda marcato `[Queued messages while agent was busy]` significa che il primo turno era ancora in esecuzione quando è arrivato il secondo Webhook: il bucket di coalescenza era già stato svuotato. Regola la finestra in base al log del server BB, non al log di sessione.
|
||||
</Accordion>
|
||||
<Accordion title="Pressione di memoria che rallenta l'invio della risposta">
|
||||
Su macchine più piccole (8 GB), i turni agente possono richiedere abbastanza tempo da far svuotare il bucket di coalescenza prima del completamento della risposta, e l'URL arriva come secondo turno in coda. Controlla `memory_pressure` e `ps -o rss -p $(pgrep openclaw-gateway)`; se il Gateway supera ~500 MB RSS e il compressore è attivo, chiudi altri processi pesanti o passa a un host più grande.
|
||||
</Accordion>
|
||||
<Accordion title="Gli invii con citazione di risposta seguono un percorso diverso">
|
||||
Se l'utente ha toccato `Dump` come **risposta** a un fumetto URL esistente (iMessage mostra un badge "1 risposta" sul fumetto Dump), l'URL si trova in `replyToBody`, non in un secondo Webhook. La coalescenza non si applica: è una questione di skill/prompt, non di debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Streaming a blocchi
|
||||
|
||||
Controlla se le risposte vengono inviate come messaggio singolo o in streaming a blocchi:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Media + limiti
|
||||
|
||||
- Gli allegati in ingresso vengono scaricati e archiviati nella cache media.
|
||||
- Limite media tramite `channels.bluebubbles.mediaMaxMb` per media in ingresso e in uscita (predefinito: 8 MB).
|
||||
- Il testo in uscita viene suddiviso in blocchi secondo `channels.bluebubbles.textChunkLimit` (predefinito: 4000 caratteri).
|
||||
|
||||
## Riferimento di configurazione
|
||||
|
||||
Configurazione completa: [Configurazione](/it/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Connessione e Webhook">
|
||||
- `channels.bluebubbles.enabled`: Abilita/disabilita il canale.
|
||||
- `channels.bluebubbles.serverUrl`: URL di base dell'API REST di BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Password API.
|
||||
- `channels.bluebubbles.webhookPath`: Percorso dell'endpoint Webhook (predefinito: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Criterio di accesso">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (predefinito: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Elenco consentiti dei DM (handle, email, numeri E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (predefinito: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Elenco consentiti dei mittenti del gruppo.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Su macOS, opzionalmente arricchisce i partecipanti al gruppo senza nome dai Contatti locali dopo il superamento dei controlli di accesso. Predefinito: `false`.
|
||||
- `channels.bluebubbles.groups`: Configurazione per gruppo (`requireMention`, ecc.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Consegna e suddivisione in blocchi">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Invia conferme di lettura (predefinito: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Abilita lo streaming a blocchi (predefinito: `false`; richiesto per le risposte in streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Dimensione dei blocchi in uscita in caratteri (predefinito: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Timeout per richiesta in ms per gli invii di testo in uscita tramite `/api/v1/message/text` (predefinito: 30000). Aumentalo nelle configurazioni macOS 26 in cui gli invii iMessage tramite Private API possono bloccarsi per oltre 60 secondi all'interno del framework iMessage; per esempio `45000` o `60000`. Probe, ricerche delle chat, reazioni, modifiche e controlli di integrità mantengono attualmente il valore predefinito più breve di 10 s; l'estensione della copertura a reazioni e modifiche è pianificata come follow-up. Override per account: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (predefinito) divide solo quando supera `textChunkLimit`; `newline` divide sulle righe vuote (confini dei paragrafi) prima della suddivisione per lunghezza.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Media e cronologia">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Limite per i media in entrata/uscita in MB (predefinito: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Elenco consentiti esplicito di directory locali assolute consentite per i percorsi dei media locali in uscita. Gli invii da percorso locale sono negati per impostazione predefinita a meno che questa opzione sia configurata. Override per account: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Unisce Webhook DM consecutivi dello stesso mittente in un unico turno dell'agente, così l'invio separato testo+URL di Apple arriva come un solo messaggio (predefinito: `false`). Vedi [Coalescenza dei DM inviati separatamente](#coalescing-split-send-dms-command--url-in-one-composition) per scenari, regolazione della finestra e compromessi. Quando abilitato senza un `messages.inbound.byChannel.bluebubbles` esplicito, amplia la finestra di debounce in entrata predefinita da 500 ms a 2500 ms.
|
||||
- `channels.bluebubbles.historyLimit`: Numero massimo di messaggi di gruppo per il contesto (0 disabilita).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Limite della cronologia dei DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Quando una risposta in entrata arriva senza `replyToBody`/`replyToSender` e la cache in memoria del contesto della risposta non trova una corrispondenza, recupera il messaggio originale dall'API HTTP di BlueBubbles come fallback best-effort (predefinito: `false`). Utile per distribuzioni multi-istanza che condividono un account BlueBubbles, dopo riavvii del processo o dopo l'espulsione da una cache TTL/LRU a lunga durata. Il recupero è protetto da SSRF con lo stesso criterio di ogni altra richiesta client BlueBubbles, non genera mai eccezioni e popola la cache così le risposte successive ammortizzano il costo. Override per account: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Un'impostazione a livello di canale si propaga agli account che omettono il flag.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Azioni e account">
|
||||
- `channels.bluebubbles.actions`: Abilita/disabilita azioni specifiche.
|
||||
- `channels.bluebubbles.accounts`: Configurazione multi-account.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Opzioni globali correlate:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (o `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Indirizzamento / destinazioni di consegna
|
||||
|
||||
Preferisci `chat_guid` per un instradamento stabile:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (preferito per i gruppi)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Handle diretti: `+15555550123`, `user@example.com`
|
||||
- Se un handle diretto non ha una chat DM esistente, OpenClaw ne creerà una tramite `POST /api/v1/chat/new`. Questo richiede che la Private API di BlueBubbles sia abilitata.
|
||||
|
||||
### Instradamento iMessage rispetto a SMS
|
||||
|
||||
Quando lo stesso handle ha sia una chat iMessage sia una chat SMS sul Mac (per esempio un numero di telefono registrato a iMessage che ha anche ricevuto fallback con bolle verdi), OpenClaw preferisce la chat iMessage e non effettua mai un downgrade silenzioso a SMS. Per forzare la chat SMS, usa un prefisso di destinazione `sms:` esplicito (per esempio `sms:+15555550123`). Gli handle senza una chat iMessage corrispondente continuano a inviare tramite qualunque chat segnalata da BlueBubbles.
|
||||
|
||||
## Sicurezza
|
||||
|
||||
- Le richieste Webhook sono autenticate confrontando parametri query o intestazioni `guid`/`password` con `channels.bluebubbles.password`.
|
||||
- Mantieni segreti la password API e l'endpoint Webhook (trattali come credenziali).
|
||||
- Non esiste alcun bypass localhost per l'autenticazione Webhook di BlueBubbles. Se usi un proxy per il traffico Webhook, mantieni la password BlueBubbles nella richiesta end-to-end. `gateway.trustedProxies` non sostituisce `channels.bluebubbles.password` qui. Vedi [Sicurezza del Gateway](/it/gateway/security#reverse-proxy-configuration).
|
||||
- Abilita HTTPS e regole firewall sul server BlueBubbles se lo esponi al di fuori della tua LAN.
|
||||
|
||||
## Risoluzione dei problemi
|
||||
|
||||
- Se gli eventi di digitazione/lettura smettono di funzionare, controlla i log Webhook di BlueBubbles e verifica che il percorso del Gateway corrisponda a `channels.bluebubbles.webhookPath`.
|
||||
- I codici di abbinamento scadono dopo un'ora; usa `openclaw pairing list bluebubbles` e `openclaw pairing approve bluebubbles <code>`.
|
||||
- Le reazioni richiedono la Private API di BlueBubbles (`POST /api/v1/message/react`); assicurati che la versione del server la esponga.
|
||||
- Modifica/annullamento dell'invio richiedono macOS 13+ e una versione compatibile del server BlueBubbles. Su macOS 26 (Tahoe), la modifica è attualmente non funzionante a causa di modifiche alla Private API.
|
||||
- Gli aggiornamenti dell'icona del gruppo possono essere instabili su macOS 26 (Tahoe): l'API può restituire successo ma la nuova icona non viene sincronizzata.
|
||||
- OpenClaw nasconde automaticamente le azioni note come non funzionanti in base alla versione macOS del server BlueBubbles. Se la modifica appare ancora su macOS 26 (Tahoe), disabilitala manualmente con `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` abilitato ma gli invii separati (ad es. `Dump` + URL) arrivano ancora come due turni: vedi la checklist per la [risoluzione dei problemi della coalescenza degli invii separati](#split-send-coalescing-troubleshooting) - le cause comuni sono una finestra di debounce troppo stretta, timestamp del log di sessione interpretati erroneamente come arrivo del Webhook, o un invio con citazione di risposta (che usa `replyToBody`, non un secondo Webhook).
|
||||
- Per informazioni su stato/integrità: `openclaw status --all` o `openclaw status --deep`.
|
||||
|
||||
Per il riferimento generale sul flusso di lavoro dei canali, vedi [Canali](/it/channels) e la guida [Plugin](/it/tools/plugin).
|
||||
|
||||
## Correlati
|
||||
|
||||
- [Instradamento dei canali](/it/channels/channel-routing) - instradamento delle sessioni per i messaggi
|
||||
- [Panoramica dei canali](/it/channels) - tutti i canali supportati
|
||||
- [Gruppi](/it/channels/groups) - comportamento delle chat di gruppo e controllo delle menzioni
|
||||
- [Abbinamento](/it/channels/pairing) - autenticazione DM e flusso di abbinamento
|
||||
- [Sicurezza](/it/gateway/security) - modello di accesso e hardening
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Stai installando, configurando o eseguendo un audit del Plugin bluebubbles
|
||||
summary: Aggiunge l'interfaccia del canale BlueBubbles per inviare e ricevere messaggi OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:40:02Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Aggiunge la superficie del canale BlueBubbles per inviare e ricevere messaggi OpenClaw.
|
||||
|
||||
## Distribuzione
|
||||
|
||||
- Pacchetto: `@openclaw/bluebubbles`
|
||||
- Percorso di installazione: npm; ClawHub
|
||||
|
||||
## Superficie
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Documentazione correlata
|
||||
|
||||
- [bluebubbles](/it/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles チャンネルの設定
|
||||
- Webhook ペアリングのトラブルシューティング
|
||||
- macOSでiMessageを設定する
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: BlueBubbles macOS サーバー経由のレガシー iMessage サポート(REST の送受信、入力中表示、リアクション、ペアリング、高度なアクション)。
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:46Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
ステータス: BlueBubbles macOS サーバーと HTTP 経由で通信するバンドル済みレガシー Plugin。既存の BlueBubbles セットアップは引き続き動作しますが、新しい OpenClaw iMessage デプロイでは、ホストの要件に合う場合はネイティブの [iMessage](/ja-JP/channels/imessage) Plugin を優先してください。
|
||||
|
||||
<Warning>
|
||||
BlueBubbles は新しい OpenClaw セットアップでは非推奨です。
|
||||
|
||||
アップストリームの BlueBubbles エコシステムは現在も活動していますが、OpenClaw は BlueBubbles macOS サーバー API に依存しています。2026年5月6日時点で、公式の [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) 開発ブランチの最終変更は [2026年1月22日](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037)で、最新のサーバーリリース([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9))は2025年5月16日に公開されました。クライアントアプリとヘルパーリポジトリにはより新しい活動があるため、これは放棄の主張ではありません。この非推奨化は、ネイティブの `imsg` パスが統合をローカルの stdio 契約上に保つ場合に、外部 HTTP サーバー、webhooks、Private API 互換性面への OpenClaw の依存を減らすためのものです。
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
現在の OpenClaw リリースには BlueBubbles がバンドルされているため、通常のパッケージビルドでは別途 `openclaw plugins install` 手順は不要です。
|
||||
</Note>
|
||||
|
||||
## 概要
|
||||
|
||||
- BlueBubbles ヘルパーアプリ([bluebubbles.app](https://bluebubbles.app))を介して macOS 上で動作します。
|
||||
- BlueBubbles チャネル ID、webhook 状態、グループターゲット、cron 配信、またはワークスペースルーティングにすでに依存しているインストール向けのレガシーフォールバックです。
|
||||
- 推奨/テスト済み: macOS Sequoia (15)。macOS Tahoe (26) でも動作します。Tahoe では現在編集が壊れており、グループアイコンの更新は成功と報告されても同期されない場合があります。
|
||||
- OpenClaw は REST API(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)を通じて通信します。
|
||||
- 受信メッセージは webhooks 経由で届きます。送信返信、入力インジケーター、既読通知、tapback は REST 呼び出しです。
|
||||
- 添付ファイルとステッカーは受信メディアとして取り込まれます(可能な場合はエージェントにも提示されます)。
|
||||
- MP3 または CAF 音声を合成する自動 TTS 返信は、通常のファイル添付ではなく iMessage のボイスメモバブルとして配信されます。
|
||||
- ペアリング/許可リストは、`channels.bluebubbles.allowFrom` + ペアリングコードを使い、他のチャネル(`/channels/pairing` など)と同じ方法で動作します。
|
||||
- リアクションは Slack/Telegram と同様にシステムイベントとして提示されるため、エージェントは返信前にそれらに「メンション」できます。
|
||||
- 高度な機能: 編集、送信取り消し、返信スレッド、メッセージエフェクト、グループ管理。
|
||||
|
||||
## クイックスタート
|
||||
|
||||
<Steps>
|
||||
<Step title="BlueBubbles をインストール">
|
||||
Mac に BlueBubbles サーバーをインストールします([bluebubbles.app/install](https://bluebubbles.app/install) の手順に従ってください)。
|
||||
</Step>
|
||||
<Step title="Web API を有効化">
|
||||
BlueBubbles 設定で Web API を有効にし、パスワードを設定します。
|
||||
</Step>
|
||||
<Step title="OpenClaw を設定">
|
||||
`openclaw onboard` を実行して BlueBubbles を選択するか、手動で設定します。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="webhooks を Gateway に向ける">
|
||||
BlueBubbles webhooks を Gateway に向けます(例: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
|
||||
</Step>
|
||||
<Step title="Gateway を起動">
|
||||
Gateway を起動します。webhook ハンドラーを登録し、ペアリングを開始します。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**セキュリティ**
|
||||
|
||||
- 常に webhook パスワードを設定してください。
|
||||
- Webhook 認証は常に必須です。OpenClaw は、local loopback/プロキシトポロジーにかかわらず、`channels.bluebubbles.password` と一致する password/guid(たとえば `?password=<password>` または `x-password`)を含まない BlueBubbles webhook リクエストを拒否します。
|
||||
- パスワード認証は、webhook 本文全体を読み取り/解析する前に確認されます。
|
||||
|
||||
</Warning>
|
||||
|
||||
## Messages.app を稼働状態に保つ(VM / ヘッドレスセットアップ)
|
||||
|
||||
一部の macOS VM / 常時稼働セットアップでは、Messages.app が「アイドル」状態になることがあります(アプリを開く/前面に出すまで受信イベントが停止します)。簡単な回避策は、AppleScript + LaunchAgent を使って **5分ごとに Messages を刺激する** ことです。
|
||||
|
||||
<Steps>
|
||||
<Step title="AppleScript を保存">
|
||||
これを `~/Scripts/poke-messages.scpt` として保存します。
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="LaunchAgent をインストール">
|
||||
これを `~/Library/LaunchAgents/com.user.poke-messages.plist` として保存します。
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
これは **300秒ごと** および **ログイン時** に実行されます。初回実行時に macOS の **Automation** プロンプト(`osascript` → Messages)が表示される場合があります。LaunchAgent を実行する同じユーザーセッションで承認してください。
|
||||
|
||||
</Step>
|
||||
<Step title="読み込む">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## オンボーディング
|
||||
|
||||
BlueBubbles は対話型オンボーディングで利用できます。
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
ウィザードは次の項目を求めます。
|
||||
|
||||
<ParamField path="サーバー URL" type="string" required>
|
||||
BlueBubbles サーバーのアドレス(例: `http://192.168.1.100:1234`)。
|
||||
</ParamField>
|
||||
<ParamField path="パスワード" type="string" required>
|
||||
BlueBubbles Server 設定の API パスワード。
|
||||
</ParamField>
|
||||
<ParamField path="Webhook パス" type="string" default="/bluebubbles-webhook">
|
||||
Webhook エンドポイントのパス。
|
||||
</ParamField>
|
||||
<ParamField path="DM ポリシー" type="string">
|
||||
`pairing`、`allowlist`、`open`、または `disabled`。
|
||||
</ParamField>
|
||||
<ParamField path="許可リスト" type="string[]">
|
||||
電話番号、メールアドレス、またはチャットターゲット。
|
||||
</ParamField>
|
||||
|
||||
CLI から BlueBubbles を追加することもできます。
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## アクセス制御(DM + グループ)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- デフォルト: `channels.bluebubbles.dmPolicy = "pairing"`。
|
||||
- 不明な送信者にはペアリングコードが送られます。承認されるまでメッセージは無視されます(コードは1時間後に期限切れになります)。
|
||||
- 次で承認します。
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- ペアリングはデフォルトのトークン交換です。詳細: [ペアリング](/ja-JP/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="グループ">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(デフォルト: `allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom` は、`allowlist` が設定されている場合にグループ内で誰がトリガーできるかを制御します。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 連絡先名の補完(macOS、任意)
|
||||
|
||||
BlueBubbles のグループ webhooks には、多くの場合、生の参加者アドレスだけが含まれます。代わりに `GroupMembers` コンテキストにローカル連絡先名を表示したい場合は、macOS 上のローカル連絡先補完を有効にできます。
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` でルックアップを有効にします。デフォルト: `false`。
|
||||
- ルックアップは、グループアクセス、コマンド認可、メンションゲートがメッセージの通過を許可した後にのみ実行されます。
|
||||
- 名前のない電話参加者のみ補完されます。
|
||||
- ローカル一致が見つからない場合、生の電話番号がフォールバックとして残ります。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### メンションゲート(グループ)
|
||||
|
||||
BlueBubbles は、iMessage/WhatsApp の動作に合わせてグループチャットのメンションゲートをサポートします。
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(または `messages.groupChat.mentionPatterns`)を使ってメンションを検出します。
|
||||
- グループで `requireMention` が有効な場合、エージェントはメンションされたときだけ応答します。
|
||||
- 認可済み送信者からの制御コマンドは、メンションゲートをバイパスします。
|
||||
|
||||
グループごとの設定:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### コマンドゲート
|
||||
|
||||
- 制御コマンド(例: `/config`、`/model`)には認可が必要です。
|
||||
- `allowFrom` と `groupAllowFrom` を使ってコマンド認可を判定します。
|
||||
- 認可済み送信者は、グループでメンションしなくても制御コマンドを実行できます。
|
||||
|
||||
### グループごとのシステムプロンプト
|
||||
|
||||
`channels.bluebubbles.groups.*` 配下の各エントリは、任意の `systemPrompt` 文字列を受け付けます。この値は、そのグループ内のメッセージを処理するすべてのターンでエージェントのシステムプロンプトに注入されるため、エージェントプロンプトを編集せずにグループごとのペルソナや動作ルールを設定できます。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
キーは、BlueBubbles がグループに対して報告する `chatGuid` / `chatIdentifier` / 数値 `chatId` のいずれかと一致します。また、`"*"` ワイルドカードエントリは、完全一致がないすべてのグループにデフォルトを提供します(`requireMention` とグループごとのツールポリシーで使われるものと同じパターンです)。完全一致は常にワイルドカードより優先されます。DM はこのフィールドを無視します。代わりにエージェントレベルまたはアカウントレベルのプロンプトカスタマイズを使用してください。
|
||||
|
||||
#### 実例: スレッド返信と tapback リアクション(Private API)
|
||||
|
||||
BlueBubbles Private API が有効な場合、受信メッセージには短いメッセージ ID(例: `[[reply_to:5]]`)が付与され、エージェントは `action=reply` を呼び出して特定のメッセージにスレッド返信したり、`action=react` で tapback を付けたりできます。グループごとの `systemPrompt` は、エージェントに適切なツールを選ばせ続ける信頼性の高い方法です。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback リアクションとスレッド返信はいずれも BlueBubbles Private API が必要です。基礎となる仕組みについては、[高度なアクション](#advanced-actions) と [メッセージ ID](#message-ids-short-vs-full) を参照してください。
|
||||
|
||||
## ACP 会話バインディング
|
||||
|
||||
BlueBubbles チャットは、トランスポート層を変更せずに永続的な ACP ワークスペースへ変換できます。
|
||||
|
||||
高速なオペレーターフロー:
|
||||
|
||||
- DM または許可されたグループチャット内で `/acp spawn codex --bind here` を実行します。
|
||||
- 以後、その同じ BlueBubbles 会話内のメッセージは、生成された ACP セッションにルーティングされます。
|
||||
- `/new` と `/reset` は、同じバインド済み ACP セッションをその場でリセットします。
|
||||
- `/acp close` は ACP セッションを閉じ、バインディングを削除します。
|
||||
|
||||
設定済みの永続バインディングも、`type: "acp"` と `match.channel: "bluebubbles"` を持つトップレベルの `bindings[]` エントリを通じてサポートされます。
|
||||
|
||||
`match.peer.id` には、サポートされている任意の BlueBubbles ターゲット形式を使用できます。
|
||||
|
||||
- 正規化された DM ハンドル(`+15555550123` や `user@example.com` など)
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
安定したグループバインディングには、`chat_id:*` または `chat_identifier:*` を優先してください。
|
||||
|
||||
例:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
共有 ACP バインディングの動作については、[ACPエージェント](/ja-JP/tools/acp-agents)を参照してください。
|
||||
|
||||
## 入力中 + 既読通知
|
||||
|
||||
- **入力インジケーター**: 応答生成の前および生成中に自動送信されます。
|
||||
- **既読通知**: `channels.bluebubbles.sendReadReceipts` で制御します(デフォルト: `true`)。
|
||||
- **入力インジケーター**: OpenClaw は入力開始イベントを送信します。BlueBubbles は送信時またはタイムアウト時に入力中状態を自動的に解除します(DELETE による手動停止は信頼できません)。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 高度なアクション
|
||||
|
||||
BlueBubbles は、設定で有効化されている場合に高度なメッセージアクションをサポートします。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**: tapback リアクションを追加または削除します(`messageId`、`emoji`、`remove`)。iMessage のネイティブ tapback セットは `love`、`like`、`dislike`、`laugh`、`emphasize`、`question` です。エージェントがそのセット外の絵文字(例: `👀`)を選んだ場合、リアクションツールは `love` にフォールバックするため、リクエスト全体を失敗させるのではなく tapback は引き続き表示されます。設定済みの ack リアクションは引き続き厳密に検証され、不明な値ではエラーになります。
|
||||
- **edit**: 送信済みメッセージを編集します(`messageId`、`text`)。
|
||||
- **unsend**: メッセージの送信を取り消します(`messageId`)。
|
||||
- **reply**: 特定のメッセージに返信します(`messageId`、`text`、`to`)。
|
||||
- **sendWithEffect**: iMessage エフェクト付きで送信します(`text`、`to`、`effectId`)。
|
||||
- **renameGroup**: グループチャット名を変更します(`chatGuid`、`displayName`)。
|
||||
- **setGroupIcon**: グループチャットのアイコンまたは写真を設定します(`chatGuid`、`media`)- macOS 26 Tahoe では不安定です(API が成功を返してもアイコンが同期されない場合があります)。
|
||||
- **addParticipant**: グループに誰かを追加します(`chatGuid`、`address`)。
|
||||
- **removeParticipant**: グループから誰かを削除します(`chatGuid`、`address`)。
|
||||
- **leaveGroup**: グループチャットから退出します(`chatGuid`)。
|
||||
- **upload-file**: メディアまたはファイルを送信します(`to`、`buffer`、`filename`、`asVoice`)。
|
||||
- ボイスメモ: iMessage の音声メッセージとして送信するには、**MP3** または **CAF** 音声で `asVoice: true` を設定します。BlueBubbles はボイスメモ送信時に MP3 → CAF に変換します。
|
||||
- レガシーエイリアス: `sendAttachment` は引き続き動作しますが、正規のアクション名は `upload-file` です。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### メッセージ ID(短縮形式と完全形式)
|
||||
|
||||
OpenClaw は、トークンを節約するために_短い_メッセージ ID(例: `1`、`2`)を表示する場合があります。
|
||||
|
||||
- `MessageSid` / `ReplyToId` には短い ID を指定できます。
|
||||
- `MessageSidFull` / `ReplyToIdFull` にはプロバイダーの完全な ID が含まれます。
|
||||
- 短い ID はメモリ内にあります。再起動またはキャッシュ削除で期限切れになる場合があります。
|
||||
- アクションは短縮または完全な `messageId` を受け付けますが、短い ID が利用できなくなっている場合はエラーになります。
|
||||
|
||||
永続的な自動化と保存には完全な ID を使用してください。
|
||||
|
||||
- テンプレート: `{{MessageSidFull}}`、`{{ReplyToIdFull}}`
|
||||
- コンテキスト: 受信ペイロード内の `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
テンプレート変数については、[設定](/ja-JP/gateway/configuration)を参照してください。
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## 分割送信 DM の結合(1 回の入力にコマンド + URL)
|
||||
|
||||
ユーザーが iMessage でコマンドと URL を一緒に入力した場合(例: `Dump https://example.com/article`)、Apple は送信を**2 つの別個の Webhook 配信**に分割します。
|
||||
|
||||
1. テキストメッセージ(`"Dump"`)。
|
||||
2. OG プレビュー画像を添付した URL プレビューバルーン(`"https://..."`)。
|
||||
|
||||
ほとんどの環境では、2 つの Webhook は OpenClaw に約 0.8〜2.0 秒間隔で到着します。結合しない場合、エージェントは 1 ターン目でコマンドだけを受け取り、返信し(多くの場合「URL を送ってください」)、2 ターン目で初めて URL を見ます。この時点ではコマンドのコンテキストはすでに失われています。
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` は、DM で連続する同一送信者の Webhook を 1 回のエージェントターンに統合するようにします。グループチャットはメッセージごとのキーを引き続き使用するため、複数ユーザーのターン構造は保持されます。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
次の場合に有効化してください。
|
||||
|
||||
- 1 つのメッセージに `command + payload` が含まれることを期待する Skills(dump、paste、save、queue など)を提供している。
|
||||
- ユーザーが URL、画像、長いコンテンツをコマンドと一緒に貼り付ける。
|
||||
- 追加される DM ターンのレイテンシを許容できる(下記参照)。
|
||||
|
||||
次の場合は無効のままにしてください。
|
||||
|
||||
- 1 語の DM トリガーで最小のコマンドレイテンシが必要。
|
||||
- すべてのフローが、後続のペイロードを伴わない単発コマンドである。
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
フラグがオンで、明示的な `messages.inbound.byChannel.bluebubbles` がない場合、デバウンスウィンドウは **2500 ms** に広がります(結合しない場合のデフォルトは 500 ms)。Apple の分割送信の間隔は 0.8〜2.0 秒で、より短いデフォルトには収まらないため、広いウィンドウが必要です。
|
||||
|
||||
ウィンドウを自分で調整するには:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **DM 制御コマンドのレイテンシが増加します。** フラグがオンの場合、DM 制御コマンドメッセージ(`Dump`、`Save` など)は、ペイロード Webhook が来る可能性に備えて、ディスパッチ前に最大でデバウンスウィンドウ分待機するようになります。グループチャットのコマンドは即時ディスパッチのままです。
|
||||
- **統合された出力には上限があります** - 統合テキストは明示的な `…[truncated]` マーカー付きで 4000 文字まで、添付ファイルは 20 個まで、ソースエントリは 10 個までです(それを超える分は最初と最新が保持されます)。各ソースの `messageId` は引き続き受信重複排除に到達するため、後で MessagePoller が個別イベントをリプレイしても重複として認識されます。
|
||||
- **オプトインで、チャンネルごとです。** 他のチャンネル(Telegram、WhatsApp、Slack、…)には影響しません。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### シナリオとエージェントに見える内容
|
||||
|
||||
| ユーザーの入力内容 | Apple の配信内容 | フラグオフ(デフォルト) | フラグオン + 2500 ms ウィンドウ |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(1 回の送信) | 約 1 秒間隔の 2 Webhook | 2 つのエージェントターン: "Dump" のみ、その後 URL | 1 ターン: 統合テキスト `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(添付ファイル + テキスト) | 2 Webhook | 2 ターン | 1 ターン: テキスト + 画像 |
|
||||
| `/status`(単独コマンド) | 1 Webhook | 即時ディスパッチ | **ウィンドウまで待機してからディスパッチ** |
|
||||
| URL のみを貼り付け | 1 Webhook | 即時ディスパッチ | 即時ディスパッチ(バケット内のエントリが 1 つのみ) |
|
||||
| テキスト + URL を意図的に別々のメッセージとして数分空けて送信 | ウィンドウ外の 2 Webhook | 2 ターン | 2 ターン(その間にウィンドウが期限切れ) |
|
||||
| 急速な連投(ウィンドウ内に 10 件超の小さな DM) | N Webhook | N ターン | 1 ターン、上限付き出力(最初 + 最新、テキスト/添付ファイル上限を適用) |
|
||||
|
||||
### 分割送信の結合に関するトラブルシューティング
|
||||
|
||||
フラグがオンでも分割送信がまだ 2 ターンとして到着する場合は、各レイヤーを確認してください。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
その後 `openclaw gateway restart` を実行してください。このフラグは debouncer-registry の作成時に読み取られます。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
`~/Library/Logs/bluebubbles-server/main.log` にある BlueBubbles サーバーログを確認します。
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
`"Dump"` のようなテキストディスパッチと、その後に続く `"https://..."; Attachments:` ディスパッチの間隔を測定してください。その間隔を十分にカバーするように `messages.inbound.byChannel.bluebubbles` を引き上げます。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
セッションイベントのタイムスタンプ(`~/.openclaw/agents/<id>/sessions/*.jsonl`)は、Gateway がメッセージをエージェントに渡した時刻を示し、Webhook が到着した時刻では**ありません**。`[Queued messages while agent was busy]` とタグ付けされた 2 件目のキュー内メッセージは、2 件目の Webhook が到着した時点で 1 ターン目がまだ実行中だったことを意味します。つまり、結合バケットはすでにフラッシュ済みでした。セッションログではなく、BB サーバーログを基準にウィンドウを調整してください。
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
小さめのマシン(8 GB)では、エージェントターンに十分な時間がかかり、返信完了前に結合バケットがフラッシュされて、URL がキュー内の 2 ターン目として到着する場合があります。`memory_pressure` と `ps -o rss -p $(pgrep openclaw-gateway)` を確認してください。Gateway が約 500 MB RSS を超えていて compressor が有効な場合は、他の重いプロセスを閉じるか、より大きなホストに増強してください。
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
ユーザーが既存の URL バルーンへの**返信**として `Dump` をタップした場合(iMessage では Dump バブルに「1 Reply」バッジが表示されます)、URL は 2 件目の Webhook ではなく `replyToBody` に存在します。結合は適用されません。これは debouncer の問題ではなく、Skill またはプロンプトの問題です。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## ブロックストリーミング
|
||||
|
||||
応答を 1 つのメッセージとして送信するか、ブロック単位でストリーミングするかを制御します。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## メディア + 上限
|
||||
|
||||
- 受信した添付ファイルはダウンロードされ、メディアキャッシュに保存されます。
|
||||
- 受信および送信メディアのメディア上限は `channels.bluebubbles.mediaMaxMb` で指定します(デフォルト: 8 MB)。
|
||||
- 送信テキストは `channels.bluebubbles.textChunkLimit` に従って分割されます(デフォルト: 4000 文字)。
|
||||
|
||||
## 設定リファレンス
|
||||
|
||||
完全な設定: [設定](/ja-JP/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="接続と Webhook">
|
||||
- `channels.bluebubbles.enabled`: チャンネルを有効化/無効化します。
|
||||
- `channels.bluebubbles.serverUrl`: BlueBubbles REST API のベース URL。
|
||||
- `channels.bluebubbles.password`: API パスワード。
|
||||
- `channels.bluebubbles.webhookPath`: Webhook エンドポイントパス (デフォルト: `/bluebubbles-webhook`)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="アクセスポリシー">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (デフォルト: `pairing`)。
|
||||
- `channels.bluebubbles.allowFrom`: DM 許可リスト (ハンドル、メール、E.164 番号、`chat_id:*`、`chat_guid:*`)。
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (デフォルト: `allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom`: グループ送信者の許可リスト。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: macOS では、ゲートを通過した後に、名前のないグループ参加者をローカルの連絡先から任意で補完します。デフォルト: `false`。
|
||||
- `channels.bluebubbles.groups`: グループごとの設定 (`requireMention` など)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="配信とチャンク化">
|
||||
- `channels.bluebubbles.sendReadReceipts`: 既読通知を送信します (デフォルト: `true`)。
|
||||
- `channels.bluebubbles.blockStreaming`: ブロックストリーミングを有効にします (デフォルト: `false`; ストリーミング返信に必要)。
|
||||
- `channels.bluebubbles.textChunkLimit`: 送信チャンクサイズを文字数で指定します (デフォルト: 4000)。
|
||||
- `channels.bluebubbles.sendTimeoutMs`: `/api/v1/message/text` 経由の送信テキスト送信について、リクエストごとのタイムアウトをミリ秒で指定します (デフォルト: 30000)。Private API の iMessage 送信が iMessage フレームワーク内で 60 秒以上停止することがある macOS 26 環境では、たとえば `45000` または `60000` に引き上げてください。プローブ、チャット検索、リアクション、編集、ヘルスチェックは現在、より短い 10 秒のデフォルトを維持します。リアクションと編集への対象拡大はフォローアップとして計画されています。アカウントごとのオーバーライド: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`。
|
||||
- `channels.bluebubbles.chunkMode`: `length` (デフォルト) は `textChunkLimit` を超える場合にのみ分割します。`newline` は長さによるチャンク化の前に空行 (段落境界) で分割します。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="メディアと履歴">
|
||||
- `channels.bluebubbles.mediaMaxMb`: 受信/送信メディアの上限を MB で指定します (デフォルト: 8)。
|
||||
- `channels.bluebubbles.mediaLocalRoots`: 送信用のローカルメディアパスとして許可する絶対ローカルディレクトリの明示的な許可リスト。これが設定されていない限り、ローカルパス送信はデフォルトで拒否されます。アカウントごとのオーバーライド: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`。
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: 同じ送信者から連続する DM Webhook を 1 つのエージェントターンに統合し、Apple のテキスト+URL 分割送信を単一メッセージとして受信できるようにします (デフォルト: `false`)。シナリオ、ウィンドウ調整、トレードオフについては、[分割送信 DM の統合](#coalescing-split-send-dms-command--url-in-one-composition) を参照してください。明示的な `messages.inbound.byChannel.bluebubbles` なしで有効にした場合、デフォルトの受信デバウンスウィンドウを 500 ms から 2500 ms に広げます。
|
||||
- `channels.bluebubbles.historyLimit`: コンテキスト用の最大グループメッセージ数 (0 で無効化)。
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM 履歴の上限。
|
||||
- `channels.bluebubbles.replyContextApiFallback`: 受信返信に `replyToBody`/`replyToSender` がなく、メモリ内の返信コンテキストキャッシュもミスした場合、ベストエフォートのフォールバックとして BlueBubbles HTTP API から元のメッセージを取得します (デフォルト: `false`)。1 つの BlueBubbles アカウントを共有する複数インスタンスのデプロイ、プロセス再起動後、または長期間有効な TTL/LRU キャッシュの退避後に便利です。この取得は、他のすべての BlueBubbles クライアントリクエストと同じポリシーで SSRF ガードされ、例外をスローせず、キャッシュに投入されるため、後続の返信でコストがならされます。アカウントごとのオーバーライド: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`。チャンネルレベルの設定は、このフラグを省略したアカウントに伝播します。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="アクションとアカウント">
|
||||
- `channels.bluebubbles.actions`: 特定のアクションを有効化/無効化します。
|
||||
- `channels.bluebubbles.accounts`: マルチアカウント設定。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
関連するグローバルオプション:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (または `messages.groupChat.mentionPatterns`)。
|
||||
- `messages.responsePrefix`。
|
||||
|
||||
## アドレス指定 / 配信先
|
||||
|
||||
安定したルーティングには `chat_guid` を優先してください:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (グループに推奨)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 直接ハンドル: `+15555550123`、`user@example.com`
|
||||
- 直接ハンドルに既存の DM チャットがない場合、OpenClaw は `POST /api/v1/chat/new` 経由で作成します。これには BlueBubbles Private API が有効である必要があります。
|
||||
|
||||
### iMessage と SMS のルーティング
|
||||
|
||||
同じハンドルに Mac 上で iMessage チャットと SMS チャットの両方がある場合 (たとえば、iMessage に登録済みだが、緑色の吹き出しのフォールバックも受信したことがある電話番号)、OpenClaw は iMessage チャットを優先し、暗黙に SMS へダウングレードすることはありません。SMS チャットを強制するには、明示的な `sms:` ターゲットプレフィックスを使用してください (例: `sms:+15555550123`)。一致する iMessage チャットがないハンドルは、BlueBubbles が報告する任意のチャットを通じて送信されます。
|
||||
|
||||
## セキュリティ
|
||||
|
||||
- Webhook リクエストは、`guid`/`password` クエリパラメーターまたはヘッダーを `channels.bluebubbles.password` と比較して認証されます。
|
||||
- API パスワードと Webhook エンドポイントは秘密にしてください (資格情報として扱ってください)。
|
||||
- BlueBubbles Webhook 認証に localhost バイパスはありません。Webhook トラフィックをプロキシする場合は、リクエストのエンドツーエンドで BlueBubbles パスワードを保持してください。ここでは `gateway.trustedProxies` は `channels.bluebubbles.password` の代わりにはなりません。[Gateway セキュリティ](/ja-JP/gateway/security#reverse-proxy-configuration)を参照してください。
|
||||
- LAN の外部に公開する場合は、BlueBubbles サーバーで HTTPS とファイアウォールルールを有効にしてください。
|
||||
|
||||
## トラブルシューティング
|
||||
|
||||
- タイピング/既読イベントが動作しなくなった場合は、BlueBubbles Webhook ログを確認し、Gateway パスが `channels.bluebubbles.webhookPath` と一致することを検証してください。
|
||||
- ペアリングコードは 1 時間後に期限切れになります。`openclaw pairing list bluebubbles` と `openclaw pairing approve bluebubbles <code>` を使用してください。
|
||||
- リアクションには BlueBubbles private API (`POST /api/v1/message/react`) が必要です。サーバーバージョンがそれを公開していることを確認してください。
|
||||
- 編集/送信取り消しには macOS 13+ と互換性のある BlueBubbles サーバーバージョンが必要です。macOS 26 (Tahoe) では、private API の変更により編集は現在壊れています。
|
||||
- グループアイコンの更新は macOS 26 (Tahoe) で不安定な場合があります。API が成功を返しても、新しいアイコンが同期されないことがあります。
|
||||
- OpenClaw は、BlueBubbles サーバーの macOS バージョンに基づいて、既知の壊れているアクションを自動的に非表示にします。macOS 26 (Tahoe) で編集がまだ表示される場合は、`channels.bluebubbles.actions.edit=false` で手動で無効化してください。
|
||||
- `coalesceSameSenderDms` が有効でも分割送信 (例: `Dump` + URL) がまだ 2 つのターンとして届く場合は、[分割送信統合のトラブルシューティング](#split-send-coalescing-troubleshooting) チェックリストを参照してください - 一般的な原因は、デバウンスウィンドウが短すぎる、セッションログのタイムスタンプを Webhook 到着時刻と誤読している、または返信引用送信 (`replyToBody` を使用し、2 つ目の Webhook ではない) です。
|
||||
- ステータス/ヘルス情報: `openclaw status --all` または `openclaw status --deep`。
|
||||
|
||||
一般的なチャンネルワークフローのリファレンスについては、[チャンネル](/ja-JP/channels) と [Plugins](/ja-JP/tools/plugin) ガイドを参照してください。
|
||||
|
||||
## 関連
|
||||
|
||||
- [チャンネルルーティング](/ja-JP/channels/channel-routing) - メッセージのセッションルーティング
|
||||
- [チャンネル概要](/ja-JP/channels) - サポートされているすべてのチャンネル
|
||||
- [グループ](/ja-JP/channels/groups) - グループチャットの動作とメンションゲート
|
||||
- [ペアリング](/ja-JP/channels/pairing) - DM 認証とペアリングフロー
|
||||
- [セキュリティ](/ja-JP/gateway/security) - アクセスモデルと強化
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- bluebubbles Pluginをインストール、設定、または監査している
|
||||
summary: OpenClaw メッセージの送受信用の BlueBubbles チャネルサーフェスを追加します。
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T05:01:46Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles Plugin
|
||||
|
||||
OpenClaw メッセージを送受信するための BlueBubbles チャネルサーフェスを追加します。
|
||||
|
||||
## 配布
|
||||
|
||||
- パッケージ: `@openclaw/bluebubbles`
|
||||
- インストール経路: npm; ClawHub
|
||||
|
||||
## サーフェス
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## 関連ドキュメント
|
||||
|
||||
- [bluebubbles](/ja-JP/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles 채널 설정하기
|
||||
- Webhook 페어링 문제 해결
|
||||
- macOS에서 iMessage 설정하기
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: BlueBubbles macOS 서버를 통한 레거시 iMessage 지원(REST 보내기/받기, 입력 중 표시, 반응, 페어링, 고급 작업).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:55Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
상태: HTTP를 통해 BlueBubbles macOS 서버와 통신하는 번들 레거시 Plugin입니다. 기존 BlueBubbles 설정은 계속 작동하지만, 새 OpenClaw iMessage 배포에서는 호스트에 요구 사항이 맞는 경우 네이티브 [iMessage](/ko/channels/imessage) Plugin을 우선 사용해야 합니다.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles는 새 OpenClaw 설정에서 더 이상 권장되지 않습니다.
|
||||
|
||||
업스트림 BlueBubbles 생태계는 여전히 활발하지만, OpenClaw는 BlueBubbles macOS 서버 API에 의존합니다. 2026년 5월 6일 기준, 공식 [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) 개발 브랜치는 [2026년 1월 22일](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037)에 마지막으로 변경되었고, 최신 서버 릴리스([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9))는 2025년 5월 16일에 게시되었습니다. 클라이언트 앱과 헬퍼 저장소에는 더 새로운 활동이 있으므로, 이는 프로젝트 중단 주장이라기보다 네이티브 `imsg` 경로가 통합을 로컬 stdio 계약 위에 유지할 수 있을 때 OpenClaw가 외부 HTTP 서버, Webhook, 비공개 API 호환성 표면에 의존하는 부분을 줄이기 위한 사용 중단입니다.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
현재 OpenClaw 릴리스는 BlueBubbles를 번들로 포함하므로, 일반 패키지 빌드에서는 별도의 `openclaw plugins install` 단계가 필요하지 않습니다.
|
||||
</Note>
|
||||
|
||||
## 개요
|
||||
|
||||
- BlueBubbles 헬퍼 앱([bluebubbles.app](https://bluebubbles.app))을 통해 macOS에서 실행됩니다.
|
||||
- 이미 BlueBubbles 채널 ID, Webhook 상태, 그룹 대상, Cron 전달 또는 워크스페이스 라우팅에 의존하는 설치를 위한 레거시 대체 경로입니다.
|
||||
- 권장/테스트됨: macOS Sequoia (15). macOS Tahoe (26)도 작동하지만, 현재 Tahoe에서는 편집이 깨져 있으며 그룹 아이콘 업데이트가 성공으로 보고되더라도 동기화되지 않을 수 있습니다.
|
||||
- OpenClaw는 REST API(`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`)를 통해 통신합니다.
|
||||
- 수신 메시지는 Webhook으로 도착하며, 발신 답장, 입력 표시, 읽음 확인, tapback은 REST 호출입니다.
|
||||
- 첨부 파일과 스티커는 인바운드 미디어로 수집됩니다(가능한 경우 에이전트에 노출됨).
|
||||
- MP3 또는 CAF 오디오를 합성하는 자동 TTS 답장은 일반 파일 첨부 대신 iMessage 음성 메모 말풍선으로 전달됩니다.
|
||||
- 페어링/허용 목록은 다른 채널(`/channels/pairing` 등)과 같은 방식으로 `channels.bluebubbles.allowFrom` + 페어링 코드를 사용합니다.
|
||||
- 반응은 Slack/Telegram과 마찬가지로 시스템 이벤트로 노출되어 에이전트가 답장 전에 이를 "언급"할 수 있습니다.
|
||||
- 고급 기능: 편집, 보내기 취소, 답글 스레딩, 메시지 효과, 그룹 관리.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
<Steps>
|
||||
<Step title="BlueBubbles 설치">
|
||||
Mac에 BlueBubbles 서버를 설치합니다([bluebubbles.app/install](https://bluebubbles.app/install)의 지침을 따르세요).
|
||||
</Step>
|
||||
<Step title="웹 API 활성화">
|
||||
BlueBubbles 구성에서 웹 API를 활성화하고 비밀번호를 설정합니다.
|
||||
</Step>
|
||||
<Step title="OpenClaw 구성">
|
||||
`openclaw onboard`를 실행하고 BlueBubbles를 선택하거나, 수동으로 구성합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Webhook을 Gateway로 지정">
|
||||
BlueBubbles Webhook이 Gateway를 가리키도록 설정합니다(예: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Gateway 시작">
|
||||
Gateway를 시작합니다. Webhook 핸들러가 등록되고 페어링이 시작됩니다.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**보안**
|
||||
|
||||
- 항상 Webhook 비밀번호를 설정하세요.
|
||||
- Webhook 인증은 항상 필요합니다. OpenClaw는 local loopback/프록시 토폴로지와 관계없이, `channels.bluebubbles.password`와 일치하는 비밀번호/guid를 포함하지 않는 BlueBubbles Webhook 요청을 거부합니다(예: `?password=<password>` 또는 `x-password`).
|
||||
- 비밀번호 인증은 전체 Webhook 본문을 읽거나 파싱하기 전에 확인됩니다.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Messages.app을 계속 실행 상태로 유지하기(VM / 헤드리스 설정)
|
||||
|
||||
일부 macOS VM / 상시 실행 설정에서는 Messages.app이 "유휴" 상태가 될 수 있습니다(앱을 열거나 포그라운드로 가져오기 전까지 수신 이벤트가 멈춤). 간단한 우회 방법은 AppleScript + LaunchAgent를 사용해 **5분마다 Messages를 건드리는 것**입니다.
|
||||
|
||||
<Steps>
|
||||
<Step title="AppleScript 저장">
|
||||
다음을 `~/Scripts/poke-messages.scpt`로 저장합니다.
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="LaunchAgent 설치">
|
||||
다음을 `~/Library/LaunchAgents/com.user.poke-messages.plist`로 저장합니다.
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
이는 **300초마다** 그리고 **로그인 시** 실행됩니다. 첫 실행 시 macOS **Automation** 프롬프트(`osascript` → Messages)가 표시될 수 있습니다. LaunchAgent를 실행하는 동일한 사용자 세션에서 승인하세요.
|
||||
|
||||
</Step>
|
||||
<Step title="로드">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 온보딩
|
||||
|
||||
BlueBubbles는 대화형 온보딩에서 사용할 수 있습니다.
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
마법사가 다음 항목을 요청합니다.
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles 서버 주소(예: `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
BlueBubbles Server 설정의 API 비밀번호.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook 엔드포인트 경로.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` 또는 `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
전화번호, 이메일 또는 채팅 대상.
|
||||
</ParamField>
|
||||
|
||||
CLI를 통해 BlueBubbles를 추가할 수도 있습니다.
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## 접근 제어(DM + 그룹)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- 기본값: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- 알 수 없는 발신자는 페어링 코드를 받으며, 승인될 때까지 메시지는 무시됩니다(코드는 1시간 후 만료).
|
||||
- 승인 방법:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- 페어링은 기본 토큰 교환 방식입니다. 자세한 내용: [페어링](/ko/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="그룹">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(기본값: `allowlist`).
|
||||
- `allowlist`가 설정된 경우 `channels.bluebubbles.groupAllowFrom`은 그룹에서 누가 트리거할 수 있는지 제어합니다.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 연락처 이름 보강(macOS, 선택 사항)
|
||||
|
||||
BlueBubbles 그룹 Webhook에는 원시 참가자 주소만 포함되는 경우가 많습니다. `GroupMembers` 컨텍스트에 로컬 연락처 이름을 대신 표시하려면 macOS에서 로컬 연락처 보강을 선택적으로 활성화할 수 있습니다.
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true`는 조회를 활성화합니다. 기본값: `false`.
|
||||
- 조회는 그룹 접근, 명령 권한 부여, 멘션 게이팅이 메시지 통과를 허용한 후에만 실행됩니다.
|
||||
- 이름이 없는 전화번호 참가자만 보강됩니다.
|
||||
- 로컬 일치 항목을 찾지 못하면 원시 전화번호가 대체값으로 유지됩니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 멘션 게이팅(그룹)
|
||||
|
||||
BlueBubbles는 iMessage/WhatsApp 동작과 일치하는 그룹 채팅 멘션 게이팅을 지원합니다.
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(또는 `messages.groupChat.mentionPatterns`)를 사용해 멘션을 감지합니다.
|
||||
- 그룹에 `requireMention`이 활성화된 경우, 에이전트는 멘션된 경우에만 응답합니다.
|
||||
- 권한이 있는 발신자의 제어 명령은 멘션 게이팅을 우회합니다.
|
||||
|
||||
그룹별 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 명령 게이팅
|
||||
|
||||
- 제어 명령(예: `/config`, `/model`)에는 권한 부여가 필요합니다.
|
||||
- 명령 권한 부여 여부를 결정하는 데 `allowFrom` 및 `groupAllowFrom`을 사용합니다.
|
||||
- 권한이 있는 발신자는 그룹에서 멘션하지 않아도 제어 명령을 실행할 수 있습니다.
|
||||
|
||||
### 그룹별 시스템 프롬프트
|
||||
|
||||
`channels.bluebubbles.groups.*` 아래의 각 항목은 선택적 `systemPrompt` 문자열을 허용합니다. 이 값은 해당 그룹의 메시지를 처리하는 모든 턴에서 에이전트의 시스템 프롬프트에 주입되므로, 에이전트 프롬프트를 편집하지 않고도 그룹별 페르소나 또는 동작 규칙을 설정할 수 있습니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
키는 BlueBubbles가 그룹에 대해 보고하는 `chatGuid` / `chatIdentifier` / 숫자 `chatId`와 일치하며, `"*"` 와일드카드 항목은 정확히 일치하는 항목이 없는 모든 그룹에 대한 기본값을 제공합니다(`requireMention` 및 그룹별 도구 정책에서 사용하는 것과 동일한 패턴). 정확히 일치하는 항목은 항상 와일드카드보다 우선합니다. DM은 이 필드를 무시합니다. 대신 에이전트 수준 또는 계정 수준 프롬프트 사용자 지정을 사용하세요.
|
||||
|
||||
#### 실제 예: 스레드 답글과 tapback 반응(비공개 API)
|
||||
|
||||
BlueBubbles 비공개 API가 활성화되면, 인바운드 메시지는 짧은 메시지 ID(예: `[[reply_to:5]]`)와 함께 도착하며, 에이전트는 `action=reply`를 호출해 특정 메시지 아래에 스레드로 답장하거나 `action=react`를 호출해 tapback을 남길 수 있습니다. 그룹별 `systemPrompt`는 에이전트가 올바른 도구를 선택하도록 유지하는 신뢰할 수 있는 방법입니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback 반응과 스레드 답글은 모두 BlueBubbles 비공개 API가 필요합니다. 기본 동작은 [고급 작업](#advanced-actions) 및 [메시지 ID](#message-ids-short-vs-full)를 참고하세요.
|
||||
|
||||
## ACP 대화 바인딩
|
||||
|
||||
BlueBubbles 채팅은 전송 계층을 변경하지 않고도 지속 ACP 워크스페이스로 전환할 수 있습니다.
|
||||
|
||||
빠른 운영자 흐름:
|
||||
|
||||
- DM 또는 허용된 그룹 채팅 안에서 `/acp spawn codex --bind here`를 실행합니다.
|
||||
- 이후 동일한 BlueBubbles 대화의 메시지는 생성된 ACP 세션으로 라우팅됩니다.
|
||||
- `/new` 및 `/reset`은 같은 바인딩된 ACP 세션을 제자리에서 재설정합니다.
|
||||
- `/acp close`는 ACP 세션을 닫고 바인딩을 제거합니다.
|
||||
|
||||
구성된 영구 바인딩도 최상위 `bindings[]` 항목에서 `type: "acp"` 및 `match.channel: "bluebubbles"`를 사용해 지원됩니다.
|
||||
|
||||
`match.peer.id`는 지원되는 모든 BlueBubbles 대상 형식을 사용할 수 있습니다:
|
||||
|
||||
- `+15555550123` 또는 `user@example.com` 같은 정규화된 DM 핸들
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
안정적인 그룹 바인딩에는 `chat_id:*` 또는 `chat_identifier:*`를 권장합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
공유 ACP 바인딩 동작은 [ACP 에이전트](/ko/tools/acp-agents)를 참조하세요.
|
||||
|
||||
## 입력 표시 + 읽음 확인
|
||||
|
||||
- **입력 표시기**: 응답 생성 전과 중에 자동으로 전송됩니다.
|
||||
- **읽음 확인**: `channels.bluebubbles.sendReadReceipts`로 제어됩니다(기본값: `true`).
|
||||
- **입력 표시기**: OpenClaw는 입력 시작 이벤트를 보냅니다. BlueBubbles는 전송 또는 시간 초과 시 입력 상태를 자동으로 지웁니다(DELETE를 통한 수동 중지는 신뢰할 수 없습니다).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 고급 작업
|
||||
|
||||
BlueBubbles는 설정에서 활성화된 경우 고급 메시지 작업을 지원합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="사용 가능한 작업">
|
||||
- **react**: 탭백 반응을 추가/제거합니다(`messageId`, `emoji`, `remove`). iMessage의 기본 탭백 세트는 `love`, `like`, `dislike`, `laugh`, `emphasize`, `question`입니다. 에이전트가 해당 세트 밖의 이모지(예: `👀`)를 선택하면, 반응 도구는 전체 요청을 실패시키는 대신 탭백이 계속 렌더링되도록 `love`로 폴백합니다. 설정된 확인 반응은 여전히 엄격하게 검증되며 알 수 없는 값에서는 오류가 발생합니다.
|
||||
- **edit**: 보낸 메시지를 편집합니다(`messageId`, `text`).
|
||||
- **unsend**: 메시지 전송을 취소합니다(`messageId`).
|
||||
- **reply**: 특정 메시지에 답장합니다(`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: iMessage 효과와 함께 전송합니다(`text`, `to`, `effectId`).
|
||||
- **renameGroup**: 그룹 채팅 이름을 변경합니다(`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: 그룹 채팅의 아이콘/사진을 설정합니다(`chatGuid`, `media`) - macOS 26 Tahoe에서 불안정합니다(API가 성공을 반환해도 아이콘이 동기화되지 않을 수 있음).
|
||||
- **addParticipant**: 그룹에 사람을 추가합니다(`chatGuid`, `address`).
|
||||
- **removeParticipant**: 그룹에서 사람을 제거합니다(`chatGuid`, `address`).
|
||||
- **leaveGroup**: 그룹 채팅에서 나갑니다(`chatGuid`).
|
||||
- **upload-file**: 미디어/파일을 보냅니다(`to`, `buffer`, `filename`, `asVoice`).
|
||||
- 음성 메모: iMessage 음성 메시지로 보내려면 **MP3** 또는 **CAF** 오디오와 함께 `asVoice: true`를 설정하세요. BlueBubbles는 음성 메모를 보낼 때 MP3 → CAF로 변환합니다.
|
||||
- 레거시 별칭: `sendAttachment`는 여전히 작동하지만, 정식 작업 이름은 `upload-file`입니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 메시지 ID(짧은 형식 vs 전체 형식)
|
||||
|
||||
OpenClaw는 토큰을 절약하기 위해 _짧은_ 메시지 ID(예: `1`, `2`)를 표시할 수 있습니다.
|
||||
|
||||
- `MessageSid` / `ReplyToId`는 짧은 ID일 수 있습니다.
|
||||
- `MessageSidFull` / `ReplyToIdFull`에는 제공자 전체 ID가 포함됩니다.
|
||||
- 짧은 ID는 메모리 내에만 있으며, 재시작 또는 캐시 축출 시 만료될 수 있습니다.
|
||||
- 작업은 짧은 `messageId` 또는 전체 `messageId`를 받지만, 짧은 ID를 더 이상 사용할 수 없으면 오류가 발생합니다.
|
||||
|
||||
내구성 있는 자동화와 저장에는 전체 ID를 사용하세요.
|
||||
|
||||
- 템플릿: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- 컨텍스트: 인바운드 페이로드의 `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
템플릿 변수는 [설정](/ko/gateway/configuration)을 참조하세요.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## 분할 전송 DM 병합(하나의 작성 내용에 명령 + URL)
|
||||
|
||||
사용자가 iMessage에서 명령과 URL을 함께 입력하면(예: `Dump https://example.com/article`) Apple은 전송을 **두 개의 별도 Webhook 전달**로 분할합니다.
|
||||
|
||||
1. 텍스트 메시지(`"Dump"`).
|
||||
2. OG 미리보기 이미지가 첨부된 URL 미리보기 말풍선(`"https://..."`).
|
||||
|
||||
대부분의 설정에서 두 Webhook은 약 0.8-2.0초 간격으로 OpenClaw에 도착합니다. 병합이 없으면 에이전트는 1번째 턴에서 명령만 받고 응답하며(흔히 "URL을 보내 주세요"), 2번째 턴에서야 URL을 보게 됩니다. 이 시점에는 이미 명령 컨텍스트가 사라진 뒤입니다.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms`는 DM에서 같은 발신자의 연속 Webhook을 하나의 에이전트 턴으로 병합하도록 선택합니다. 그룹 채팅은 다중 사용자 턴 구조가 유지되도록 계속 메시지별로 키를 사용합니다.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="활성화 시점">
|
||||
다음 경우 활성화하세요.
|
||||
|
||||
- 하나의 메시지에서 `command + payload`를 기대하는 Skills를 제공하는 경우(dump, paste, save, queue 등).
|
||||
- 사용자가 명령과 함께 URL, 이미지 또는 긴 콘텐츠를 붙여 넣는 경우.
|
||||
- 추가되는 DM 턴 지연 시간을 허용할 수 있는 경우(아래 참조).
|
||||
|
||||
다음 경우 비활성화 상태로 두세요.
|
||||
|
||||
- 한 단어 DM 트리거의 명령 지연 시간을 최소화해야 하는 경우.
|
||||
- 모든 흐름이 페이로드 후속 입력 없는 일회성 명령인 경우.
|
||||
|
||||
</Tab>
|
||||
<Tab title="활성화">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
플래그가 켜져 있고 명시적인 `messages.inbound.byChannel.bluebubbles`가 없으면 디바운스 창이 **2500 ms**로 넓어집니다(병합하지 않을 때의 기본값은 500 ms). 더 넓은 창이 필요합니다. Apple의 0.8-2.0초 분할 전송 간격은 더 좁은 기본값에 맞지 않습니다.
|
||||
|
||||
창을 직접 조정하려면:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="트레이드오프">
|
||||
- **DM 제어 명령에 추가 지연 시간이 생깁니다.** 플래그가 켜져 있으면 DM 제어 명령 메시지(예: `Dump`, `Save` 등)는 페이로드 Webhook이 올 수 있으므로 디스패치 전에 디바운스 창까지 대기합니다. 그룹 채팅 명령은 즉시 디스패치를 유지합니다.
|
||||
- **병합된 출력에는 한계가 있습니다** - 병합된 텍스트는 명시적인 `…[truncated]` 표시와 함께 4000자로 제한됩니다. 첨부 파일은 20개로 제한됩니다. 소스 항목은 10개로 제한됩니다(그 이후는 첫 항목과 최신 항목을 유지). 모든 소스 `messageId`는 여전히 인바운드 중복 제거에 도달하므로, 나중에 MessagePoller가 개별 이벤트를 재생해도 중복으로 인식됩니다.
|
||||
- **채널별 선택 사항입니다.** 다른 채널(Telegram, WhatsApp, Slack, …)에는 영향을 주지 않습니다.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 시나리오와 에이전트가 보는 내용
|
||||
|
||||
| 사용자가 작성한 내용 | Apple 전달 방식 | 플래그 꺼짐(기본값) | 플래그 켜짐 + 2500 ms 창 |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(한 번 전송) | 약 1초 간격의 Webhook 2개 | 두 에이전트 턴: "Dump"만, 그다음 URL | 한 턴: 병합된 텍스트 `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(첨부 파일 + 텍스트) | Webhook 2개 | 두 턴 | 한 턴: 텍스트 + 이미지 |
|
||||
| `/status`(독립 실행 명령) | Webhook 1개 | 즉시 디스패치 | **창까지 대기한 다음 디스패치** |
|
||||
| URL만 붙여넣음 | Webhook 1개 | 즉시 디스패치 | 즉시 디스패치(버킷에 항목이 하나뿐임) |
|
||||
| 텍스트 + URL을 몇 분 간격의 의도적인 별도 메시지 두 개로 보냄 | 창 밖의 Webhook 2개 | 두 턴 | 두 턴(그 사이 창 만료) |
|
||||
| 빠른 폭주(창 안에서 작은 DM 10개 초과) | Webhook N개 | N턴 | 한 턴, 제한된 출력(첫 항목 + 최신 항목, 텍스트/첨부 파일 제한 적용) |
|
||||
|
||||
### 분할 전송 병합 문제 해결
|
||||
|
||||
플래그가 켜져 있는데도 분할 전송이 여전히 두 턴으로 도착한다면 각 계층을 확인하세요.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="설정이 실제로 로드됨">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
그런 다음 `openclaw gateway restart`를 실행하세요. 플래그는 디바운서 레지스트리 생성 시 읽힙니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="설정에 충분히 넓은 디바운스 창">
|
||||
`~/Library/Logs/bluebubbles-server/main.log` 아래의 BlueBubbles 서버 로그를 확인하세요.
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
`"Dump"` 스타일 텍스트 디스패치와 뒤따르는 `"https://..."; Attachments:` 디스패치 사이의 간격을 측정하세요. `messages.inbound.byChannel.bluebubbles`를 그 간격을 충분히 감쌀 수 있게 높이세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="세션 JSONL 타임스탬프 ≠ Webhook 도착">
|
||||
세션 이벤트 타임스탬프(`~/.openclaw/agents/<id>/sessions/*.jsonl`)는 Gateway가 에이전트에 메시지를 전달한 시점을 반영하며, Webhook이 도착한 시점이 **아닙니다**. `[Queued messages while agent was busy]`로 태그된 대기 중인 두 번째 메시지는 두 번째 Webhook이 도착했을 때 첫 번째 턴이 아직 실행 중이었다는 뜻입니다. 병합 버킷은 이미 플러시된 상태였습니다. 세션 로그가 아니라 BB 서버 로그에 맞춰 창을 조정하세요.
|
||||
</Accordion>
|
||||
<Accordion title="메모리 압박으로 느려지는 답장 디스패치">
|
||||
더 작은 머신(8 GB)에서는 에이전트 턴이 충분히 오래 걸려 답장이 완료되기 전에 병합 버킷이 플러시되고, URL이 대기 중인 두 번째 턴으로 들어갈 수 있습니다. `memory_pressure`와 `ps -o rss -p $(pgrep openclaw-gateway)`를 확인하세요. Gateway가 약 500 MB RSS를 넘고 압축기가 활성화되어 있다면 다른 무거운 프로세스를 닫거나 더 큰 호스트로 올리세요.
|
||||
</Accordion>
|
||||
<Accordion title="답장 인용 전송은 다른 경로">
|
||||
사용자가 기존 URL 말풍선에 대한 **답장**으로 `Dump`를 탭했다면(iMessage에서 Dump 말풍선에 "1 Reply" 배지가 표시됨), URL은 두 번째 Webhook이 아니라 `replyToBody`에 있습니다. 병합은 적용되지 않습니다. 이는 디바운서 문제가 아니라 Skill/프롬프트 문제입니다.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 블록 스트리밍
|
||||
|
||||
응답을 단일 메시지로 보낼지 블록 단위로 스트리밍할지 제어합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 미디어 + 제한
|
||||
|
||||
- 인바운드 첨부 파일은 다운로드되어 미디어 캐시에 저장됩니다.
|
||||
- 인바운드 및 아웃바운드 미디어의 미디어 한도는 `channels.bluebubbles.mediaMaxMb`를 통해 설정합니다(기본값: 8 MB).
|
||||
- 아웃바운드 텍스트는 `channels.bluebubbles.textChunkLimit`에 맞게 청크로 나뉩니다(기본값: 4000자).
|
||||
|
||||
## 설정 참조
|
||||
|
||||
전체 설정: [설정](/ko/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="연결 및 Webhook">
|
||||
- `channels.bluebubbles.enabled`: 채널을 활성화/비활성화합니다.
|
||||
- `channels.bluebubbles.serverUrl`: BlueBubbles REST API 기본 URL입니다.
|
||||
- `channels.bluebubbles.password`: API 비밀번호입니다.
|
||||
- `channels.bluebubbles.webhookPath`: Webhook 엔드포인트 경로입니다(기본값: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="액세스 정책">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled`(기본값: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: DM 허용 목록입니다(핸들, 이메일, E.164 번호, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled`(기본값: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: 그룹 발신자 허용 목록입니다.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: macOS에서 게이팅을 통과한 뒤 이름이 없는 그룹 참여자를 로컬 연락처에서 선택적으로 보강합니다. 기본값: `false`.
|
||||
- `channels.bluebubbles.groups`: 그룹별 구성입니다(`requireMention` 등).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="전송 및 청킹">
|
||||
- `channels.bluebubbles.sendReadReceipts`: 읽음 확인을 보냅니다(기본값: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: 블록 스트리밍을 활성화합니다(기본값: `false`, 스트리밍 답장에 필요).
|
||||
- `channels.bluebubbles.textChunkLimit`: 문자 단위 아웃바운드 청크 크기입니다(기본값: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: `/api/v1/message/text`를 통한 아웃바운드 텍스트 전송의 요청별 제한 시간(ms)입니다(기본값: 30000). Private API iMessage 전송이 iMessage 프레임워크 안에서 60초 이상 멈출 수 있는 macOS 26 설정에서는 이 값을 높이세요. 예: `45000` 또는 `60000`. 프로브, 채팅 조회, 반응, 편집, 상태 확인은 현재 더 짧은 10초 기본값을 유지합니다. 반응 및 편집까지 범위를 넓히는 작업은 후속 작업으로 계획되어 있습니다. 계정별 재정의: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length`(기본값)는 `textChunkLimit`를 초과할 때만 분할합니다. `newline`은 길이 기준 청킹 전에 빈 줄(단락 경계)을 기준으로 분할합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="미디어 및 기록">
|
||||
- `channels.bluebubbles.mediaMaxMb`: 인바운드/아웃바운드 미디어 제한(MB)입니다(기본값: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: 아웃바운드 로컬 미디어 경로에 허용되는 절대 로컬 디렉터리의 명시적 허용 목록입니다. 이 설정이 구성되지 않으면 로컬 경로 전송은 기본적으로 거부됩니다. 계정별 재정의: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: 같은 발신자의 연속 DM Webhook을 하나의 에이전트 턴으로 병합하여 Apple의 텍스트+URL 분할 전송이 단일 메시지로 도착하게 합니다(기본값: `false`). 시나리오, 윈도우 조정, 트레이드오프는 [분할 전송 DM 병합](#coalescing-split-send-dms-command--url-in-one-composition)을 참고하세요. 명시적인 `messages.inbound.byChannel.bluebubbles` 없이 활성화하면 기본 인바운드 디바운스 윈도우가 500 ms에서 2500 ms로 넓어집니다.
|
||||
- `channels.bluebubbles.historyLimit`: 컨텍스트에 사용할 최대 그룹 메시지 수입니다(0이면 비활성화).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM 기록 제한입니다.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: 인바운드 답장이 `replyToBody`/`replyToSender` 없이 도착하고 메모리 내 답장 컨텍스트 캐시도 누락된 경우, 최선의 대체 수단으로 BlueBubbles HTTP API에서 원본 메시지를 가져옵니다(기본값: `false`). 하나의 BlueBubbles 계정을 공유하는 다중 인스턴스 배포, 프로세스 재시작 이후, 또는 오래 유지된 TTL/LRU 캐시 축출 이후에 유용합니다. 이 가져오기는 다른 모든 BlueBubbles 클라이언트 요청과 같은 정책으로 SSRF 보호되며, 예외를 던지지 않고, 이후 답장이 비용을 분산할 수 있도록 캐시를 채웁니다. 계정별 재정의: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. 채널 수준 설정은 해당 플래그를 생략한 계정으로 전파됩니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="작업 및 계정">
|
||||
- `channels.bluebubbles.actions`: 특정 작업을 활성화/비활성화합니다.
|
||||
- `channels.bluebubbles.accounts`: 다중 계정 구성입니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
관련 전역 옵션:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(또는 `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## 주소 지정 / 전송 대상
|
||||
|
||||
안정적인 라우팅에는 `chat_guid`를 권장합니다.
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123`(그룹에 권장)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 직접 핸들: `+15555550123`, `user@example.com`
|
||||
- 직접 핸들에 기존 DM 채팅이 없으면 OpenClaw가 `POST /api/v1/chat/new`를 통해 새로 만듭니다. 이 작업에는 BlueBubbles Private API가 활성화되어 있어야 합니다.
|
||||
|
||||
### iMessage와 SMS 라우팅 비교
|
||||
|
||||
같은 핸들이 Mac에서 iMessage 채팅과 SMS 채팅을 모두 가지고 있는 경우(예: iMessage에 등록되어 있지만 초록 말풍선 대체 메시지도 받은 전화번호), OpenClaw는 iMessage 채팅을 우선 사용하며 SMS로 조용히 다운그레이드하지 않습니다. SMS 채팅을 강제로 사용하려면 명시적인 `sms:` 대상 접두사를 사용하세요(예: `sms:+15555550123`). 일치하는 iMessage 채팅이 없는 핸들은 BlueBubbles가 보고하는 채팅을 통해 그대로 전송됩니다.
|
||||
|
||||
## 보안
|
||||
|
||||
- Webhook 요청은 `guid`/`password` 쿼리 매개변수 또는 헤더를 `channels.bluebubbles.password`와 비교하여 인증됩니다.
|
||||
- API 비밀번호와 Webhook 엔드포인트는 비밀로 유지하세요(자격 증명처럼 취급하세요).
|
||||
- BlueBubbles Webhook 인증에는 localhost 우회가 없습니다. Webhook 트래픽을 프록시하는 경우 요청의 처음부터 끝까지 BlueBubbles 비밀번호를 유지하세요. 여기서 `gateway.trustedProxies`는 `channels.bluebubbles.password`를 대체하지 않습니다. [Gateway 보안](/ko/gateway/security#reverse-proxy-configuration)을 참고하세요.
|
||||
- LAN 외부에 노출하는 경우 BlueBubbles 서버에서 HTTPS와 방화벽 규칙을 활성화하세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- 입력/읽음 이벤트가 작동하지 않으면 BlueBubbles Webhook 로그를 확인하고 Gateway 경로가 `channels.bluebubbles.webhookPath`와 일치하는지 확인하세요.
|
||||
- 페어링 코드는 한 시간 후 만료됩니다. `openclaw pairing list bluebubbles` 및 `openclaw pairing approve bluebubbles <code>`를 사용하세요.
|
||||
- 반응에는 BlueBubbles Private API(`POST /api/v1/message/react`)가 필요합니다. 서버 버전이 이를 노출하는지 확인하세요.
|
||||
- 편집/보내기 취소에는 macOS 13 이상과 호환되는 BlueBubbles 서버 버전이 필요합니다. macOS 26(Tahoe)에서는 Private API 변경으로 인해 현재 편집이 작동하지 않습니다.
|
||||
- 그룹 아이콘 업데이트는 macOS 26(Tahoe)에서 불안정할 수 있습니다. API가 성공을 반환하더라도 새 아이콘이 동기화되지 않을 수 있습니다.
|
||||
- OpenClaw는 BlueBubbles 서버의 macOS 버전에 따라 작동하지 않는 것으로 알려진 작업을 자동으로 숨깁니다. macOS 26(Tahoe)에서 편집이 여전히 표시되면 `channels.bluebubbles.actions.edit=false`로 수동 비활성화하세요.
|
||||
- `coalesceSameSenderDms`가 활성화되어 있지만 분할 전송(예: `Dump` + URL)이 여전히 두 턴으로 도착하는 경우: [분할 전송 병합 문제 해결](#split-send-coalescing-troubleshooting) 체크리스트를 참고하세요. 일반적인 원인은 너무 짧은 디바운스 윈도우, Webhook 도착 시각으로 잘못 읽은 세션 로그 타임스탬프, 또는 답장 인용 전송(`replyToBody`를 사용하며 두 번째 Webhook이 아님)입니다.
|
||||
- 상태/상태 확인 정보: `openclaw status --all` 또는 `openclaw status --deep`.
|
||||
|
||||
일반적인 채널 워크플로 참고 자료는 [채널](/ko/channels) 및 [Plugins](/ko/tools/plugin) 가이드를 참고하세요.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 라우팅](/ko/channels/channel-routing) - 메시지의 세션 라우팅
|
||||
- [채널 개요](/ko/channels) - 지원되는 모든 채널
|
||||
- [그룹](/ko/channels/groups) - 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [페어링](/ko/channels/pairing) - DM 인증 및 페어링 흐름
|
||||
- [보안](/ko/gateway/security) - 액세스 모델 및 강화
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- bluebubbles Plugin을 설치, 구성 또는 감사하는 중입니다
|
||||
summary: OpenClaw 메시지를 보내고 받을 수 있는 BlueBubbles 채널 인터페이스를 추가합니다.
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T06:19:51Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles Plugin
|
||||
|
||||
OpenClaw 메시지를 보내고 받기 위한 BlueBubbles 채널 표면을 추가합니다.
|
||||
|
||||
## 배포
|
||||
|
||||
- 패키지: `@openclaw/bluebubbles`
|
||||
- 설치 경로: npm; ClawHub
|
||||
|
||||
## 표면
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [bluebubbles](/ko/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles-kanaal instellen
|
||||
- Problemen met Webhook-koppeling oplossen
|
||||
- iMessage configureren op macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Legacy-ondersteuning voor iMessage via de BlueBubbles macOS-server (REST-verzenden/ontvangen, typen, reacties, koppelen, geavanceerde acties).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:47Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: gebundelde legacy-plugin die via HTTP met de BlueBubbles macOS-server praat. Bestaande BlueBubbles-setups blijven werken, maar nieuwe OpenClaw iMessage-implementaties zouden de native [iMessage](/nl/channels/imessage)-plugin moeten verkiezen wanneer de vereisten bij je host passen.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles is verouderd voor nieuwe OpenClaw-setups.
|
||||
|
||||
Het upstream BlueBubbles-ecosysteem is nog steeds actief, maar OpenClaw is afhankelijk van de BlueBubbles macOS-server-API. Vanaf 6 mei 2026 is de officiële ontwikkeltak van [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) voor het laatst gewijzigd op [22 januari 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), en de nieuwste serverrelease ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) is gepubliceerd op 16 mei 2025. De client-app en helper-repositories hebben recentere activiteit, dus dit is geen bewering dat het project is verlaten; de deprecatie gaat over het verminderen van OpenClaw's afhankelijkheid van een externe HTTP-server, webhooks en compatibiliteitsoppervlak met private API's wanneer het native `imsg`-pad de integratie op een lokaal stdio-contract houdt.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Huidige OpenClaw-releases bundelen BlueBubbles, dus normale verpakte builds hebben geen aparte stap `openclaw plugins install` nodig.
|
||||
</Note>
|
||||
|
||||
## Overzicht
|
||||
|
||||
- Draait op macOS via de BlueBubbles-helper-app ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Legacy-terugval voor installaties die al afhankelijk zijn van BlueBubbles-kanaal-ID's, webhookstatus, groepsdoelen, cronbezorging of werkruimte-routering.
|
||||
- Aanbevolen/getest: macOS Sequoia (15). macOS Tahoe (26) werkt; bewerken is momenteel kapot op Tahoe, en updates van groepspictogrammen kunnen succes melden maar niet synchroniseren.
|
||||
- OpenClaw praat ermee via de REST-API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Inkomende berichten komen binnen via webhooks; uitgaande antwoorden, typindicatoren, leesbevestigingen en tapbacks zijn REST-aanroepen.
|
||||
- Bijlagen en stickers worden opgenomen als inkomende media (en waar mogelijk aan de agent aangeboden).
|
||||
- Auto-TTS-antwoorden die MP3- of CAF-audio synthetiseren, worden bezorgd als iMessage-spraakmemobubbels in plaats van gewone bestandsbijlagen.
|
||||
- Koppelen/toestaanlijst werkt op dezelfde manier als andere kanalen (`/channels/pairing` enz.) met `channels.bluebubbles.allowFrom` + koppelcodes.
|
||||
- Reacties worden als systeemgebeurtenissen aangeboden, net als bij Slack/Telegram, zodat agents ze kunnen "vermelden" voordat ze antwoorden.
|
||||
- Geavanceerde functies: bewerken, verzenden ongedaan maken, antwoordthreads, berichteffecten, groepsbeheer.
|
||||
|
||||
## Snel starten
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
Installeer de BlueBubbles-server op je Mac (volg de instructies op [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
Schakel in de BlueBubbles-configuratie de web-API in en stel een wachtwoord in.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
Voer `openclaw onboard` uit en selecteer BlueBubbles, of configureer handmatig:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
Richt BlueBubbles-webhooks op je gateway (voorbeeld: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Start de gateway; die registreert de webhook-handler en begint met koppelen.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Beveiliging**
|
||||
|
||||
- Stel altijd een webhookwachtwoord in.
|
||||
- Webhook-authenticatie is altijd vereist. OpenClaw weigert BlueBubbles-webhookverzoeken tenzij ze een wachtwoord/guid bevatten dat overeenkomt met `channels.bluebubbles.password` (bijvoorbeeld `?password=<password>` of `x-password`), ongeacht de loopback-/proxytopologie.
|
||||
- Wachtwoordauthenticatie wordt gecontroleerd voordat volledige webhook-bodies worden gelezen/geparset.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Messages.app actief houden (VM / headless setups)
|
||||
|
||||
Sommige macOS-VM- / altijd-aan-setups kunnen eindigen met Messages.app die "idle" wordt (inkomende gebeurtenissen stoppen totdat de app wordt geopend/naar de voorgrond wordt gehaald). Een eenvoudige workaround is om **Messages elke 5 minuten aan te tikken** met een AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Sla dit op als `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Sla dit op als `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Dit draait **elke 300 seconden** en **bij inloggen**. De eerste uitvoering kan macOS-**Automation**-prompts activeren (`osascript` → Messages). Keur ze goed in dezelfde gebruikerssessie die de LaunchAgent uitvoert.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles is beschikbaar in interactieve onboarding:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
De wizard vraagt om:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles-serveradres (bijv. `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
API-wachtwoord uit de BlueBubbles Server-instellingen.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook-eindpuntpad.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open`, of `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Telefoonnummers, e-mails of chatdoelen.
|
||||
</ParamField>
|
||||
|
||||
Je kunt BlueBubbles ook toevoegen via de CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Toegangscontrole (DM's + groepen)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Standaard: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Onbekende afzenders ontvangen een koppelcode; berichten worden genegeerd totdat ze zijn goedgekeurd (codes verlopen na 1 uur).
|
||||
- Goedkeuren via:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Koppelen is de standaard tokenuitwisseling. Details: [Koppelen](/nl/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (standaard: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` bepaalt wie in groepen kan activeren wanneer `allowlist` is ingesteld.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Verrijking van contactnamen (macOS, optioneel)
|
||||
|
||||
BlueBubbles-groepswebhooks bevatten vaak alleen ruwe deelnemersadressen. Als je wilt dat de `GroupMembers`-context in plaats daarvan lokale contactnamen toont, kun je je aanmelden voor lokale Contacts-verrijking op macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` schakelt de lookup in. Standaard: `false`.
|
||||
- Lookups worden alleen uitgevoerd nadat groepstoegang, commandoautorisatie en vermeldingsgating het bericht hebben doorgelaten.
|
||||
- Alleen naamloze telefoondeelnemers worden verrijkt.
|
||||
- Ruwe telefoonnummers blijven de fallback wanneer er geen lokale match wordt gevonden.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Vermeldingsgating (groepen)
|
||||
|
||||
BlueBubbles ondersteunt vermeldingsgating voor groepschats, passend bij iMessage-/WhatsApp-gedrag:
|
||||
|
||||
- Gebruikt `agents.list[].groupChat.mentionPatterns` (of `messages.groupChat.mentionPatterns`) om vermeldingen te detecteren.
|
||||
- Wanneer `requireMention` is ingeschakeld voor een groep, antwoordt de agent alleen wanneer die wordt vermeld.
|
||||
- Controlecommando's van geautoriseerde afzenders omzeilen vermeldingsgating.
|
||||
|
||||
Configuratie per groep:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Commandogating
|
||||
|
||||
- Controlecommando's (bijv. `/config`, `/model`) vereisen autorisatie.
|
||||
- Gebruikt `allowFrom` en `groupAllowFrom` om commandoautorisatie te bepalen.
|
||||
- Geautoriseerde afzenders kunnen controlecommando's uitvoeren, zelfs zonder vermelding in groepen.
|
||||
|
||||
### Systeemprompt per groep
|
||||
|
||||
Elke vermelding onder `channels.bluebubbles.groups.*` accepteert een optionele `systemPrompt`-string. De waarde wordt geïnjecteerd in de systeemprompt van de agent bij elke beurt die een bericht in die groep behandelt, zodat je per groep persona- of gedragsregels kunt instellen zonder agentprompts te bewerken:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
De sleutel komt overeen met wat BlueBubbles meldt als `chatGuid` / `chatIdentifier` / numerieke `chatId` voor de groep, en een `"*"`-wildcardvermelding biedt een standaard voor elke groep zonder exacte match (hetzelfde patroon dat wordt gebruikt door `requireMention` en toolbeleid per groep). Exacte matches winnen altijd van de wildcard. DM's negeren dit veld; gebruik in plaats daarvan promptaanpassing op agent- of accountniveau.
|
||||
|
||||
#### Uitgewerkt voorbeeld: gethreadde antwoorden en tapback-reacties (private API)
|
||||
|
||||
Met de BlueBubbles private API ingeschakeld komen inkomende berichten binnen met korte bericht-ID's (bijvoorbeeld `[[reply_to:5]]`) en kan de agent `action=reply` aanroepen om in een specifiek bericht te threaden of `action=react` om een tapback te plaatsen. Een `systemPrompt` per groep is een betrouwbare manier om de agent de juiste tool te laten kiezen:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback-reacties en gethreadde antwoorden vereisen beide de BlueBubbles private API; zie [Geavanceerde acties](#advanced-actions) en [Bericht-ID's](#message-ids-short-vs-full) voor de onderliggende mechanismen.
|
||||
|
||||
## ACP-gespreksbindingen
|
||||
|
||||
BlueBubbles-chats kunnen worden omgezet in duurzame ACP-werkruimten zonder de transportlaag te wijzigen.
|
||||
|
||||
Snelle operatorflow:
|
||||
|
||||
- Voer `/acp spawn codex --bind here` uit in de DM of toegestane groepschat.
|
||||
- Toekomstige berichten in datzelfde BlueBubbles-gesprek worden naar de gespawnde ACP-sessie gerouteerd.
|
||||
- `/new` en `/reset` resetten dezelfde gebonden ACP-sessie ter plekke.
|
||||
- `/acp close` sluit de ACP-sessie en verwijdert de binding.
|
||||
|
||||
Geconfigureerde persistente bindingen worden ook ondersteund via top-level `bindings[]`-vermeldingen met `type: "acp"` en `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` kan elke ondersteunde BlueBubbles-doelvorm gebruiken:
|
||||
|
||||
- genormaliseerde DM-handle zoals `+15555550123` of `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Voor stabiele groepskoppelingen geef je de voorkeur aan `chat_id:*` of `chat_identifier:*`.
|
||||
|
||||
Voorbeeld:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Zie [ACP-agenten](/nl/tools/acp-agents) voor gedeeld gedrag van ACP-koppelingen.
|
||||
|
||||
## Typen + leesbevestigingen
|
||||
|
||||
- **Typindicatoren**: Worden automatisch verzonden vóór en tijdens het genereren van antwoorden.
|
||||
- **Leesbevestigingen**: Beheerd door `channels.bluebubbles.sendReadReceipts` (standaard: `true`).
|
||||
- **Typindicatoren**: OpenClaw verzendt gebeurtenissen voor starten met typen; BlueBubbles wist typen automatisch bij verzenden of timeout (handmatig stoppen via DELETE is onbetrouwbaar).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Geavanceerde acties
|
||||
|
||||
BlueBubbles ondersteunt geavanceerde berichtacties wanneer deze zijn ingeschakeld in de configuratie:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Beschikbare acties">
|
||||
- **react**: Voeg tapback-reacties toe of verwijder ze (`messageId`, `emoji`, `remove`). De native tapback-set van iMessage is `love`, `like`, `dislike`, `laugh`, `emphasize` en `question`. Wanneer een agent een emoji buiten die set kiest (bijvoorbeeld `👀`), valt de reactietool terug op `love`, zodat de tapback nog steeds wordt weergegeven in plaats van dat het hele verzoek mislukt. Geconfigureerde ack-reacties worden nog steeds strikt gevalideerd en geven een fout bij onbekende waarden.
|
||||
- **edit**: Bewerk een verzonden bericht (`messageId`, `text`).
|
||||
- **unsend**: Trek een bericht in (`messageId`).
|
||||
- **reply**: Antwoord op een specifiek bericht (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Verstuur met iMessage-effect (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Wijzig de naam van een groepschat (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Stel het pictogram/de foto van een groepschat in (`chatGuid`, `media`) - instabiel op macOS 26 Tahoe (API kan succes retourneren, maar het pictogram wordt niet gesynchroniseerd).
|
||||
- **addParticipant**: Voeg iemand toe aan een groep (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Verwijder iemand uit een groep (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Verlaat een groepschat (`chatGuid`).
|
||||
- **upload-file**: Verstuur media/bestanden (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Spraakmemo's: stel `asVoice: true` in met **MP3**- of **CAF**-audio om als een iMessage-spraakbericht te verzenden. BlueBubbles converteert MP3 → CAF bij het verzenden van spraakmemo's.
|
||||
- Verouderde alias: `sendAttachment` werkt nog steeds, maar `upload-file` is de canonieke actienaam.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Bericht-ID's (kort versus volledig)
|
||||
|
||||
OpenClaw kan _korte_ bericht-ID's (bijv. `1`, `2`) tonen om tokens te besparen.
|
||||
|
||||
- `MessageSid` / `ReplyToId` kunnen korte ID's zijn.
|
||||
- `MessageSidFull` / `ReplyToIdFull` bevatten de volledige ID's van de provider.
|
||||
- Korte ID's bevinden zich in het geheugen; ze kunnen verlopen bij een herstart of cacheverwijdering.
|
||||
- Acties accepteren korte of volledige `messageId`, maar korte ID's geven een fout als ze niet langer beschikbaar zijn.
|
||||
|
||||
Gebruik volledige ID's voor duurzame automatiseringen en opslag:
|
||||
|
||||
- Sjablonen: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Context: `MessageSidFull` / `ReplyToIdFull` in inkomende payloads
|
||||
|
||||
Zie [Configuratie](/nl/gateway/configuration) voor sjabloonvariabelen.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Gesplitst verzonden DM's samenvoegen (opdracht + URL in één compositie)
|
||||
|
||||
Wanneer een gebruiker in iMessage een opdracht en een URL samen typt - bijvoorbeeld `Dump https://example.com/article` - splitst Apple de verzending in **twee afzonderlijke Webhook-leveringen**:
|
||||
|
||||
1. Een tekstbericht (`"Dump"`).
|
||||
2. Een URL-voorbeeldballon (`"https://..."`) met OG-voorbeeldafbeeldingen als bijlagen.
|
||||
|
||||
De twee Webhooks komen bij de meeste configuraties ~0,8-2,0 s na elkaar binnen bij OpenClaw. Zonder samenvoeging ontvangt de agent alleen de opdracht in beurt 1, antwoordt deze (vaak "stuur me de URL") en ziet hij de URL pas in beurt 2 - waarna de opdrachtcontext al verloren is.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` laat een DM opeenvolgende Webhooks van dezelfde afzender samenvoegen tot één agentbeurt. Groepschats blijven per bericht sleutel gebruiken, zodat de beurtstructuur met meerdere gebruikers behouden blijft.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Wanneer inschakelen">
|
||||
Schakel dit in wanneer:
|
||||
|
||||
- Je Skills levert die `command + payload` in één bericht verwachten (dump, paste, save, queue, enz.).
|
||||
- Je gebruikers URL's, afbeeldingen of lange inhoud naast opdrachten plakken.
|
||||
- Je de extra DM-beurtlatentie kunt accepteren (zie hieronder).
|
||||
|
||||
Laat dit uitgeschakeld wanneer:
|
||||
|
||||
- Je minimale opdrachtlatentie nodig hebt voor DM-triggers van één woord.
|
||||
- Al je flows eenmalige opdrachten zonder payload-opvolgingen zijn.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Inschakelen">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Met de vlag aan en zonder expliciete `messages.inbound.byChannel.bluebubbles` wordt het debounce-venster verbreed naar **2500 ms** (de standaard voor niet-samenvoegen is 500 ms). Het bredere venster is vereist - Apple's gesplitste verzendcadans van 0,8-2,0 s past niet binnen de strakkere standaardwaarde.
|
||||
|
||||
Om het venster zelf af te stemmen:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Afwegingen">
|
||||
- **Extra latentie voor DM-besturingsopdrachten.** Met de vlag aan wachten DM-berichten met besturingsopdrachten (zoals `Dump`, `Save`, enz.) nu tot maximaal het debounce-venster voordat ze worden verzonden, voor het geval er een payload-Webhook aankomt. Groepschatopdrachten blijven direct verzenden.
|
||||
- **Samengevoegde uitvoer is begrensd** - samengevoegde tekst is beperkt tot 4000 tekens met een expliciete markering `…[truncated]`; bijlagen zijn beperkt tot 20; bronvermeldingen zijn beperkt tot 10 (eerste-plus-laatste blijven daarna behouden). Elke bron-`messageId` bereikt nog steeds inkomende deduplicatie, zodat een latere MessagePoller-herhaling van een individuele gebeurtenis als duplicaat wordt herkend.
|
||||
- **Opt-in, per kanaal.** Andere kanalen (Telegram, WhatsApp, Slack, …) worden niet beïnvloed.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Scenario's en wat de agent ziet
|
||||
|
||||
| Gebruiker stelt op | Apple levert | Vlag uit (standaard) | Vlag aan + venster van 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (één verzending) | 2 Webhooks ~1 s uit elkaar | Twee agentbeurten: alleen "Dump", daarna URL | Eén beurt: samengevoegde tekst `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (bijlage + tekst) | 2 Webhooks | Twee beurten | Eén beurt: tekst + afbeelding |
|
||||
| `/status` (zelfstandige opdracht) | 1 Webhook | Directe verzending | **Wacht tot maximaal het venster en verzend dan** |
|
||||
| URL alleen geplakt | 1 Webhook | Directe verzending | Directe verzending (slechts één item in bucket) |
|
||||
| Tekst + URL verzonden als twee bewust afzonderlijke berichten, minuten uit elkaar | 2 Webhooks buiten venster | Twee beurten | Twee beurten (venster verloopt ertussen) |
|
||||
| Snelle stroom (>10 kleine DM's binnen venster) | N Webhooks | N beurten | Eén beurt, begrensde uitvoer (eerste + laatste, tekst-/bijlagelimieten toegepast) |
|
||||
|
||||
### Probleemoplossing voor samenvoeging van gesplitste verzendingen
|
||||
|
||||
Als de vlag aan staat en gesplitste verzendingen nog steeds als twee beurten binnenkomen, controleer dan elke laag:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Configuratie daadwerkelijk geladen">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Daarna `openclaw gateway restart` - de vlag wordt gelezen bij het maken van de debouncer-registry.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce-venster breed genoeg voor je configuratie">
|
||||
Kijk naar het BlueBubbles-serverlog onder `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Meet de kloof tussen de tekstverzending in `"Dump"`-stijl en de daaropvolgende `"https://..."; Attachments:`-verzending. Verhoog `messages.inbound.byChannel.bluebubbles` zodat die kloof ruim wordt afgedekt.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL-tijdstempels ≠ aankomst van Webhook">
|
||||
Tijdstempels van sessiegebeurtenissen (`~/.openclaw/agents/<id>/sessions/*.jsonl`) geven weer wanneer de gateway een bericht aan de agent doorgeeft, **niet** wanneer de Webhook is aangekomen. Een tweede bericht in de wachtrij met tag `[Queued messages while agent was busy]` betekent dat de eerste beurt nog liep toen de tweede Webhook aankwam - de samenvoegbucket was al geleegd. Stem het venster af op het BB-serverlog, niet op het sessielog.
|
||||
</Accordion>
|
||||
<Accordion title="Geheugendruk vertraagt antwoordverzending">
|
||||
Op kleinere machines (8 GB) kunnen agentbeurten lang genoeg duren dat de samenvoegbucket wordt geleegd voordat het antwoord is voltooid, en de URL als tweede beurt in de wachtrij belandt. Controleer `memory_pressure` en `ps -o rss -p $(pgrep openclaw-gateway)`; als de Gateway boven ~500 MB RSS zit en de compressor actief is, sluit dan andere zware processen of stap over op een grotere host.
|
||||
</Accordion>
|
||||
<Accordion title="Verzendingen met antwoordcitaat volgen een ander pad">
|
||||
Als de gebruiker op `Dump` tikte als **antwoord** op een bestaande URL-ballon (iMessage toont een badge "1 Reply" op de Dump-ballon), staat de URL in `replyToBody`, niet in een tweede Webhook. Samenvoeging is niet van toepassing - dat is een Skills-/prompt-aandachtspunt, geen debouncer-aandachtspunt.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Blokstreaming
|
||||
|
||||
Bepaal of antwoorden als één bericht worden verzonden of in blokken worden gestreamd:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Media + limieten
|
||||
|
||||
- Inkomende bijlagen worden gedownload en opgeslagen in de mediacache.
|
||||
- Medialimiet via `channels.bluebubbles.mediaMaxMb` voor inkomende en uitgaande media (standaard: 8 MB).
|
||||
- Uitgaande tekst wordt opgesplitst volgens `channels.bluebubbles.textChunkLimit` (standaard: 4000 tekens).
|
||||
|
||||
## Configuratiereferentie
|
||||
|
||||
Volledige configuratie: [Configuratie](/nl/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Connection and webhook">
|
||||
- `channels.bluebubbles.enabled`: Schakel het kanaal in/uit.
|
||||
- `channels.bluebubbles.serverUrl`: Basis-URL van de BlueBubbles REST-API.
|
||||
- `channels.bluebubbles.password`: API-wachtwoord.
|
||||
- `channels.bluebubbles.webhookPath`: Pad voor het Webhook-eindpunt (standaard: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Access policy">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (standaard: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Allowlist voor DM's (handles, e-mails, E.164-nummers, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (standaard: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Allowlist voor groepsafzenders.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Op macOS optioneel naamloze groepsdeelnemers verrijken vanuit lokale Contacten nadat gating is geslaagd. Standaard: `false`.
|
||||
- `channels.bluebubbles.groups`: Configuratie per groep (`requireMention`, enz.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Delivery and chunking">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Verstuur leesbevestigingen (standaard: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Schakel blockstreaming in (standaard: `false`; vereist voor streamingantwoorden).
|
||||
- `channels.bluebubbles.textChunkLimit`: Grootte van uitgaande chunks in tekens (standaard: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Time-out per aanvraag in ms voor uitgaande tekstverzendingen via `/api/v1/message/text` (standaard: 30000). Verhoog dit op macOS 26-installaties waarbij iMessage-verzendingen via de Private API 60+ seconden kunnen vastlopen binnen het iMessage-framework; bijvoorbeeld `45000` of `60000`. Probes, chatopzoekingen, reacties, bewerkingen en gezondheidscontroles behouden momenteel de kortere standaard van 10 s; uitbreiding van de dekking naar reacties en bewerkingen is gepland als vervolg. Overschrijving per account: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (standaard) splitst alleen wanneer `textChunkLimit` wordt overschreden; `newline` splitst op lege regels (alineagrenzen) vóór chunking op lengte.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Media and history">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Limiet voor inkomende/uitgaande media in MB (standaard: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Expliciete allowlist van absolute lokale mappen die zijn toegestaan voor uitgaande lokale mediapaden. Verzendingen via lokale paden worden standaard geweigerd tenzij dit is geconfigureerd. Overschrijving per account: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Voeg opeenvolgende DM-Webhooks van dezelfde afzender samen tot één agentbeurt, zodat Apple's gesplitste verzending van tekst+URL als één bericht aankomt (standaard: `false`). Zie [Gesplitst verzonden DM's samenvoegen](#coalescing-split-send-dms-command--url-in-one-composition) voor scenario's, vensterafstemming en afwegingen. Vergroot het standaard debouncevenster voor inkomende berichten van 500 ms naar 2500 ms wanneer dit is ingeschakeld zonder expliciete `messages.inbound.byChannel.bluebubbles`.
|
||||
- `channels.bluebubbles.historyLimit`: Maximumaantal groepsberichten voor context (0 schakelt uit).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Geschiedenisl limiet voor DM's.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Wanneer een inkomend antwoord binnenkomt zonder `replyToBody`/`replyToSender` en de in-memory reply-contextcache mist, haal dan het oorspronkelijke bericht op via de BlueBubbles HTTP-API als best-effort fallback (standaard: `false`). Nuttig voor implementaties met meerdere instanties die één BlueBubbles-account delen, na procesherstarts of na het verwijderen uit een langlevende TTL/LRU-cache. De fetch wordt beschermd tegen SSRF door hetzelfde beleid als elke andere BlueBubbles-clientaanvraag, gooit nooit een fout en vult de cache zodat volgende antwoorden worden geamortiseerd. Overschrijving per account: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Een instelling op kanaalniveau wordt doorgegeven aan accounts die de vlag weglaten.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Actions and accounts">
|
||||
- `channels.bluebubbles.actions`: Schakel specifieke acties in/uit.
|
||||
- `channels.bluebubbles.accounts`: Configuratie voor meerdere accounts.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Gerelateerde globale opties:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (of `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Adressering / afleveringsdoelen
|
||||
|
||||
Geef de voorkeur aan `chat_guid` voor stabiele routering:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (aanbevolen voor groepen)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Directe handles: `+15555550123`, `user@example.com`
|
||||
- Als een directe handle geen bestaande DM-chat heeft, maakt OpenClaw er een via `POST /api/v1/chat/new`. Hiervoor moet de BlueBubbles Private API zijn ingeschakeld.
|
||||
|
||||
### Routering via iMessage versus SMS
|
||||
|
||||
Wanneer dezelfde handle zowel een iMessage- als een SMS-chat op de Mac heeft (bijvoorbeeld een telefoonnummer dat voor iMessage is geregistreerd maar ook green-bubble fallbacks heeft ontvangen), geeft OpenClaw de voorkeur aan de iMessage-chat en degradeert het nooit stilzwijgend naar SMS. Gebruik een expliciet `sms:`-doelprefix om de SMS-chat te forceren (bijvoorbeeld `sms:+15555550123`). Handles zonder overeenkomende iMessage-chat worden nog steeds verzonden via de chat die BlueBubbles rapporteert.
|
||||
|
||||
## Beveiliging
|
||||
|
||||
- Webhook-aanvragen worden geauthenticeerd door `guid`/`password`-queryparameters of headers te vergelijken met `channels.bluebubbles.password`.
|
||||
- Houd het API-wachtwoord en het Webhook-eindpunt geheim (behandel ze als referenties).
|
||||
- Er is geen localhost-bypass voor BlueBubbles Webhook-authenticatie. Als je Webhook-verkeer proxyt, houd dan het BlueBubbles-wachtwoord end-to-end op de aanvraag. `gateway.trustedProxies` vervangt hier `channels.bluebubbles.password` niet. Zie [Gateway-beveiliging](/nl/gateway/security#reverse-proxy-configuration).
|
||||
- Schakel HTTPS + firewallregels in op de BlueBubbles-server als je deze buiten je LAN beschikbaar maakt.
|
||||
|
||||
## Probleemoplossing
|
||||
|
||||
- Als typ-/leesgebeurtenissen niet meer werken, controleer dan de BlueBubbles Webhook-logs en verifieer dat het Gateway-pad overeenkomt met `channels.bluebubbles.webhookPath`.
|
||||
- Koppelingscodes verlopen na één uur; gebruik `openclaw pairing list bluebubbles` en `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reacties vereisen de BlueBubbles private API (`POST /api/v1/message/react`); zorg ervoor dat de serverversie deze beschikbaar stelt.
|
||||
- Bewerken/verzenden ongedaan maken vereist macOS 13+ en een compatibele BlueBubbles-serverversie. Op macOS 26 (Tahoe) werkt bewerken momenteel niet door wijzigingen in de private API.
|
||||
- Updates van groepspictogrammen kunnen onbetrouwbaar zijn op macOS 26 (Tahoe): de API kan succes retourneren terwijl het nieuwe pictogram niet synchroniseert.
|
||||
- OpenClaw verbergt automatisch bekende defecte acties op basis van de macOS-versie van de BlueBubbles-server. Als bewerken nog steeds verschijnt op macOS 26 (Tahoe), schakel het dan handmatig uit met `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` ingeschakeld maar gesplitste verzendingen (bijv. `Dump` + URL) komen nog steeds als twee beurten binnen: zie de controlelijst voor [probleemoplossing voor samenvoegen van gesplitste verzendingen](#split-send-coalescing-troubleshooting) - veelvoorkomende oorzaken zijn een te krap debouncevenster, sessielogtijdstempels die worden verward met Webhook-aankomst, of een verzending met antwoordcitaat (die `replyToBody` gebruikt, geen tweede Webhook).
|
||||
- Voor status-/gezondheidsinformatie: `openclaw status --all` of `openclaw status --deep`.
|
||||
|
||||
Zie voor algemene referentie over kanaalworkflows [Kanalen](/nl/channels) en de gids [Plugins](/nl/tools/plugin).
|
||||
|
||||
## Gerelateerd
|
||||
|
||||
- [Kanaalroutering](/nl/channels/channel-routing) - sessieroutering voor berichten
|
||||
- [Overzicht van kanalen](/nl/channels) - alle ondersteunde kanalen
|
||||
- [Groepen](/nl/channels/groups) - gedrag van groepschats en mention-gating
|
||||
- [Koppeling](/nl/channels/pairing) - DM-authenticatie en koppelingsflow
|
||||
- [Beveiliging](/nl/gateway/security) - toegangsmodel en verharding
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- U installeert, configureert of controleert de bluebubbles Plugin
|
||||
summary: Voegt het BlueBubbles-kanaaloppervlak toe voor het verzenden en ontvangen van OpenClaw-berichten.
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T11:13:29Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles-Plugin
|
||||
|
||||
Voegt het BlueBubbles-kanaaloppervlak toe voor het verzenden en ontvangen van OpenClaw-berichten.
|
||||
|
||||
## Distributie
|
||||
|
||||
- Pakket: `@openclaw/bluebubbles`
|
||||
- Installatieroute: npm; ClawHub
|
||||
|
||||
## Oppervlak
|
||||
|
||||
kanalen: bluebubbles
|
||||
|
||||
## Gerelateerde docs
|
||||
|
||||
- [bluebubbles](/nl/channels/bluebubbles)
|
||||
@ -1,639 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Konfigurowanie kanału BlueBubbles
|
||||
- Rozwiązywanie problemów z parowaniem Webhook
|
||||
- Konfigurowanie iMessage w systemie macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Starsza obsługa iMessage za pośrednictwem serwera BlueBubbles dla macOS (wysyłanie/odbieranie przez REST, wskaźniki pisania, reakcje, parowanie, zaawansowane działania).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:51:06Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: dołączony starszy Plugin, który komunikuje się z serwerem BlueBubbles dla macOS przez HTTP. Istniejące konfiguracje BlueBubbles nadal działają, ale nowe wdrożenia OpenClaw iMessage powinny preferować natywny Plugin [iMessage](/pl/channels/imessage), gdy jego wymagania pasują do Twojego hosta.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles jest przestarzały dla nowych konfiguracji OpenClaw.
|
||||
|
||||
Nadrzędny ekosystem BlueBubbles jest nadal aktywny, ale OpenClaw zależy od API serwera BlueBubbles dla macOS. Na dzień 6 maja 2026 r. oficjalna gałąź rozwojowa [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) ostatnio zmieniła się [22 stycznia 2026 r.](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), a najnowsze wydanie serwera ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) opublikowano 16 maja 2025 r. Aplikacja kliencka i repozytoria pomocnicze mają nowszą aktywność, więc nie jest to twierdzenie o porzuceniu projektu; deprecjacja dotyczy ograniczenia zależności OpenClaw od zewnętrznego serwera HTTP, webhooków i powierzchni zgodności prywatnego API, gdy natywna ścieżka `imsg` utrzymuje integrację na lokalnym kontrakcie stdio.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Bieżące wydania OpenClaw zawierają BlueBubbles, więc zwykłe spakowane kompilacje nie wymagają osobnego kroku `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Omówienie
|
||||
|
||||
- Działa na macOS przez aplikację pomocniczą BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Starsza opcja awaryjna dla instalacji, które już polegają na identyfikatorach kanałów BlueBubbles, stanie webhooków, celach grupowych, dostarczaniu cron lub routingu obszarów roboczych.
|
||||
- Zalecane/przetestowane: macOS Sequoia (15). macOS Tahoe (26) działa; edycja jest obecnie zepsuta na Tahoe, a aktualizacje ikon grup mogą zgłaszać powodzenie, ale się nie synchronizować.
|
||||
- OpenClaw komunikuje się z nim przez jego REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Wiadomości przychodzące docierają przez webhooki; odpowiedzi wychodzące, wskaźniki pisania, potwierdzenia odczytu i tapbacki są wywołaniami REST.
|
||||
- Załączniki i naklejki są przetwarzane jako media przychodzące (i gdy to możliwe, udostępniane agentowi).
|
||||
- Odpowiedzi Auto-TTS, które syntetyzują dźwięk MP3 lub CAF, są dostarczane jako dymki notatek głosowych iMessage zamiast zwykłych załączników plików.
|
||||
- Parowanie/lista dozwolonych działa tak samo jak w innych kanałach (`/channels/pairing` itd.) z `channels.bluebubbles.allowFrom` + kodami parowania.
|
||||
- Reakcje są udostępniane jako zdarzenia systemowe, tak jak w Slack/Telegram, aby agenci mogli o nich „wspomnieć” przed odpowiedzią.
|
||||
- Funkcje zaawansowane: edycja, cofanie wysłania, wątki odpowiedzi, efekty wiadomości, zarządzanie grupami.
|
||||
|
||||
## Szybki start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
Zainstaluj serwer BlueBubbles na Macu (postępuj zgodnie z instrukcjami na [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
W konfiguracji BlueBubbles włącz web API i ustaw hasło.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
Uruchom `openclaw onboard` i wybierz BlueBubbles albo skonfiguruj ręcznie:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
Skieruj webhooki BlueBubbles do swojego Gateway (przykład: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Uruchom Gateway; zarejestruje obsługę webhooka i rozpocznie parowanie.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Bezpieczeństwo**
|
||||
|
||||
- Zawsze ustaw hasło webhooka.
|
||||
- Uwierzytelnianie Webhook jest zawsze wymagane. OpenClaw odrzuca żądania webhooków BlueBubbles, chyba że zawierają hasło/guid zgodne z `channels.bluebubbles.password` (na przykład `?password=<password>` lub `x-password`), niezależnie od topologii loopback/proxy.
|
||||
- Uwierzytelnianie hasłem jest sprawdzane przed odczytaniem/przeanalizowaniem pełnych treści webhooków.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Utrzymywanie Messages.app przy życiu (konfiguracje VM / headless)
|
||||
|
||||
Niektóre konfiguracje macOS VM / zawsze włączone mogą doprowadzić do przejścia Messages.app w stan „bezczynności” (zdarzenia przychodzące zatrzymują się, dopóki aplikacja nie zostanie otwarta/przeniesiona na pierwszy plan). Prostym obejściem jest **wybudzanie Messages co 5 minut** za pomocą AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Zapisz to jako `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Zapisz to jako `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Uruchamia się to **co 300 sekund** i **przy logowaniu**. Pierwsze uruchomienie może wywołać monity macOS **Automation** (`osascript` → Messages). Zatwierdź je w tej samej sesji użytkownika, która uruchamia LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Wprowadzanie
|
||||
|
||||
BlueBubbles jest dostępny w interaktywnym wprowadzaniu:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Kreator pyta o:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Adres serwera BlueBubbles (np. `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Hasło API z ustawień BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Ścieżka punktu końcowego Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` lub `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Numery telefonów, adresy e-mail lub cele czatów.
|
||||
</ParamField>
|
||||
|
||||
Możesz też dodać BlueBubbles przez CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Kontrola dostępu (DM-y + grupy)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Domyślnie: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Nieznani nadawcy otrzymują kod parowania; wiadomości są ignorowane do czasu zatwierdzenia (kody wygasają po 1 godzinie).
|
||||
- Zatwierdź przez:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Parowanie jest domyślną wymianą tokenów. Szczegóły: [Parowanie](/pl/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (domyślnie: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` kontroluje, kto może wyzwalać w grupach, gdy ustawiono `allowlist`.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Wzbogacanie nazw kontaktów (macOS, opcjonalnie)
|
||||
|
||||
Webhooki grup BlueBubbles często zawierają tylko surowe adresy uczestników. Jeśli chcesz, aby kontekst `GroupMembers` pokazywał zamiast tego lokalne nazwy kontaktów, możesz włączyć lokalne wzbogacanie z Kontaktów na macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` włącza wyszukiwanie. Domyślnie: `false`.
|
||||
- Wyszukiwania są uruchamiane dopiero po tym, jak dostęp do grupy, autoryzacja poleceń i bramkowanie wzmianek przepuszczą wiadomość.
|
||||
- Wzbogacani są tylko nienazwani uczestnicy telefoniczni.
|
||||
- Surowe numery telefonów pozostają opcją awaryjną, gdy nie znaleziono lokalnego dopasowania.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Bramkowanie wzmianek (grupy)
|
||||
|
||||
BlueBubbles obsługuje bramkowanie wzmianek dla czatów grupowych, zgodnie z zachowaniem iMessage/WhatsApp:
|
||||
|
||||
- Używa `agents.list[].groupChat.mentionPatterns` (lub `messages.groupChat.mentionPatterns`) do wykrywania wzmianek.
|
||||
- Gdy `requireMention` jest włączone dla grupy, agent odpowiada tylko po wzmiance.
|
||||
- Polecenia kontrolne od autoryzowanych nadawców omijają bramkowanie wzmianek.
|
||||
|
||||
Konfiguracja dla grupy:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Prompt systemowy dla grupy
|
||||
|
||||
Każdy wpis pod `channels.bluebubbles.groups.*` akceptuje opcjonalny ciąg `systemPrompt`. Wartość jest wstrzykiwana do promptu systemowego agenta przy każdej turze obsługującej wiadomość w tej grupie, dzięki czemu możesz ustawić personę lub reguły zachowania dla grupy bez edytowania promptów agenta:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Klucz odpowiada temu, co BlueBubbles zgłasza jako `chatGuid` / `chatIdentifier` / numeryczne `chatId` dla grupy, a wpis wieloznaczny `"*"` zapewnia ustawienie domyślne dla każdej grupy bez dokładnego dopasowania (ten sam wzorzec używany przez `requireMention` i zasady narzędzi dla grup). Dokładne dopasowania zawsze wygrywają z symbolem wieloznacznym. DM-y ignorują to pole; zamiast tego użyj dostosowania promptu na poziomie agenta lub konta.
|
||||
|
||||
#### Przykład praktyczny: odpowiedzi w wątkach i reakcje tapback (Private API)
|
||||
|
||||
Przy włączonym BlueBubbles Private API wiadomości przychodzące docierają z krótkimi identyfikatorami wiadomości (na przykład `[[reply_to:5]]`), a agent może wywołać `action=reply`, aby wejść w wątek konkretnej wiadomości, albo `action=react`, aby dodać tapback. `systemPrompt` dla grupy to niezawodny sposób na utrzymanie wyboru właściwego narzędzia przez agenta:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Reakcje tapback i odpowiedzi w wątkach wymagają BlueBubbles Private API; zobacz [Zaawansowane akcje](#advanced-actions) i [Identyfikatory wiadomości](#message-ids-short-vs-full), aby poznać mechanikę leżącą u podstaw.
|
||||
|
||||
## Powiązania konwersacji ACP
|
||||
|
||||
Czaty BlueBubbles można przekształcić w trwałe obszary robocze ACP bez zmiany warstwy transportu.
|
||||
|
||||
Szybki przepływ operatora:
|
||||
|
||||
- Uruchom `/acp spawn codex --bind here` w DM-ie lub dozwolonym czacie grupowym.
|
||||
- Przyszłe wiadomości w tej samej konwersacji BlueBubbles są kierowane do utworzonej sesji ACP.
|
||||
- `/new` i `/reset` resetują tę samą powiązaną sesję ACP w miejscu.
|
||||
- `/acp close` zamyka sesję ACP i usuwa powiązanie.
|
||||
|
||||
Obsługiwane są też skonfigurowane trwałe powiązania przez wpisy najwyższego poziomu `bindings[]` z `type: "acp"` i `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` może używać dowolnej obsługiwanej formy celu BlueBubbles:
|
||||
|
||||
- znormalizowany uchwyt DM, taki jak `+15555550123` lub `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Dla stabilnych powiązań grupowych preferuj `chat_id:*` lub `chat_identifier:*`.
|
||||
|
||||
Przykład:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Zobacz [Agenci ACP](/pl/tools/acp-agents), aby poznać wspólne zachowanie powiązań ACP.
|
||||
|
||||
## Wskaźniki pisania + potwierdzenia odczytu
|
||||
|
||||
- **Wskaźniki pisania**: Wysyłane automatycznie przed generowaniem odpowiedzi i w jego trakcie.
|
||||
- **Potwierdzenia odczytu**: Kontrolowane przez `channels.bluebubbles.sendReadReceipts` (domyślnie: `true`).
|
||||
- **Wskaźniki pisania**: OpenClaw wysyła zdarzenia rozpoczęcia pisania; BlueBubbles automatycznie czyści stan pisania przy wysłaniu lub po przekroczeniu limitu czasu (ręczne zatrzymanie przez DELETE jest zawodne).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Zaawansowane akcje
|
||||
|
||||
BlueBubbles obsługuje zaawansowane akcje wiadomości, gdy są włączone w konfiguracji:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**: Dodaj/usuń reakcje tapback (`messageId`, `emoji`, `remove`). Natywny zestaw tapback iMessage to `love`, `like`, `dislike`, `laugh`, `emphasize` i `question`. Gdy agent wybierze emoji spoza tego zestawu (na przykład `👀`), narzędzie reakcji użyje zastępczo `love`, aby tapback nadal się wyświetlił zamiast powodować niepowodzenie całego żądania. Skonfigurowane reakcje potwierdzające nadal są walidowane ściśle i zwracają błąd przy nieznanych wartościach.
|
||||
- **edit**: Edytuj wysłaną wiadomość (`messageId`, `text`).
|
||||
- **unsend**: Cofnij wysłanie wiadomości (`messageId`).
|
||||
- **reply**: Odpowiedz na konkretną wiadomość (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Wyślij z efektem iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Zmień nazwę czatu grupowego (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Ustaw ikonę/zdjęcie czatu grupowego (`chatGuid`, `media`) - zawodne w macOS 26 Tahoe (API może zwrócić sukces, ale ikona się nie zsynchronizuje).
|
||||
- **addParticipant**: Dodaj kogoś do grupy (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Usuń kogoś z grupy (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Opuść czat grupowy (`chatGuid`).
|
||||
- **upload-file**: Wyślij multimedia/pliki (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Notatki głosowe: ustaw `asVoice: true` z dźwiękiem **MP3** lub **CAF**, aby wysłać wiadomość głosową iMessage. BlueBubbles konwertuje MP3 → CAF podczas wysyłania notatek głosowych.
|
||||
- Starszy alias: `sendAttachment` nadal działa, ale `upload-file` jest kanoniczną nazwą akcji.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Identyfikatory wiadomości (krótkie i pełne)
|
||||
|
||||
OpenClaw może pokazywać _krótkie_ identyfikatory wiadomości (np. `1`, `2`), aby oszczędzać tokeny.
|
||||
|
||||
- `MessageSid` / `ReplyToId` mogą być krótkimi identyfikatorami.
|
||||
- `MessageSidFull` / `ReplyToIdFull` zawierają pełne identyfikatory dostawcy.
|
||||
- Krótkie identyfikatory są przechowywane w pamięci; mogą wygasnąć po restarcie lub usunięciu z pamięci podręcznej.
|
||||
- Akcje akceptują krótki lub pełny `messageId`, ale krótkie identyfikatory zwrócą błąd, jeśli nie będą już dostępne.
|
||||
|
||||
Używaj pełnych identyfikatorów dla trwałych automatyzacji i przechowywania:
|
||||
|
||||
- Szablony: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Kontekst: `MessageSidFull` / `ReplyToIdFull` w przychodzących ładunkach
|
||||
|
||||
Zobacz [Konfiguracja](/pl/gateway/configuration), aby poznać zmienne szablonów.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Scalanie podzielonych wysyłek DM (polecenie + URL w jednej kompozycji)
|
||||
|
||||
Gdy użytkownik wpisze w iMessage polecenie razem z adresem URL - np. `Dump https://example.com/article` - Apple dzieli wysyłkę na **dwa osobne dostarczenia webhooka**:
|
||||
|
||||
1. Wiadomość tekstowa (`"Dump"`).
|
||||
2. Dymek podglądu URL (`"https://..."`) z obrazami podglądu OG jako załącznikami.
|
||||
|
||||
Dwa webhooki docierają do OpenClaw w odstępie około 0,8-2,0 s w większości konfiguracji. Bez scalania agent otrzymuje samo polecenie w turze 1, odpowiada (często „wyślij mi URL”) i widzi URL dopiero w turze 2 - kiedy kontekst polecenia jest już utracony.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` włącza dla DM scalanie kolejnych webhooków od tego samego nadawcy w jedną turę agenta. Czaty grupowe nadal są kluczowane według wiadomości, dzięki czemu struktura tur wielu użytkowników pozostaje zachowana.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
Włącz, gdy:
|
||||
|
||||
- Dostarczasz Skills, które oczekują `command + payload` w jednej wiadomości (dump, paste, save, queue itd.).
|
||||
- Twoi użytkownicy wklejają adresy URL, obrazy lub długą treść razem z poleceniami.
|
||||
- Możesz zaakceptować dodatkowe opóźnienie tury DM (patrz niżej).
|
||||
|
||||
Pozostaw wyłączone, gdy:
|
||||
|
||||
- Potrzebujesz minimalnego opóźnienia poleceń dla jednowyrazowych wyzwalaczy DM.
|
||||
- Wszystkie Twoje przepływy to jednorazowe polecenia bez następujących po nich ładunków.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Po włączeniu flagi i bez jawnego `messages.inbound.byChannel.bluebubbles` okno debounce rozszerza się do **2500 ms** (domyślnie dla trybu bez scalania to 500 ms). Szersze okno jest wymagane - kadencja podzielonej wysyłki Apple wynosząca 0,8-2,0 s nie mieści się w ciaśniejszej wartości domyślnej.
|
||||
|
||||
Aby samodzielnie dostroić okno:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **Dodatkowe opóźnienie dla poleceń sterujących DM.** Po włączeniu flagi wiadomości poleceń sterujących DM (takie jak `Dump`, `Save` itd.) czekają teraz do końca okna debounce przed wysłaniem, na wypadek gdyby nadchodził webhook z ładunkiem. Polecenia czatu grupowego zachowują natychmiastową wysyłkę.
|
||||
- **Scalone wyjście jest ograniczone** - scalony tekst ma limit 4000 znaków z jawnym znacznikiem `…[truncated]`; załączniki mają limit 20; wpisy źródłowe mają limit 10 (poza nim zachowywany jest pierwszy i najnowszy). Każde źródłowe `messageId` nadal trafia do deduplikacji przychodzącej, więc późniejsze odtworzenie dowolnego pojedynczego zdarzenia przez MessagePoller zostanie rozpoznane jako duplikat.
|
||||
- **Opcjonalne, dla kanału.** Inne kanały (Telegram, WhatsApp, Slack, …) pozostają bez zmian.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Scenariusze i to, co widzi agent
|
||||
|
||||
| Kompozycja użytkownika | Dostarczenie przez Apple | Flaga wyłączona (domyślnie) | Flaga włączona + okno 2500 ms |
|
||||
| ------------------------------------------------------------------ | -------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (jedna wysyłka) | 2 webhooki w odstępie ~1 s | Dwie tury agenta: samo „Dump”, potem URL | Jedna tura: scalony tekst `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (załącznik + tekst) | 2 webhooki | Dwie tury | Jedna tura: tekst + obraz |
|
||||
| `/status` (samodzielne polecenie) | 1 webhook | Natychmiastowa wysyłka | **Czekaj do końca okna, potem wyślij** |
|
||||
| Sam URL wklejony osobno | 1 webhook | Natychmiastowa wysyłka | Natychmiastowa wysyłka (tylko jeden wpis w koszyku) |
|
||||
| Tekst + URL wysłane jako dwie celowo osobne wiadomości w odstępie minut | 2 webhooki poza oknem | Dwie tury | Dwie tury (okno wygasa między nimi) |
|
||||
| Szybka seria (>10 małych DM w oknie) | N webhooków | N tur | Jedna tura, ograniczone wyjście (pierwsze + najnowsze, zastosowane limity tekstu/załączników) |
|
||||
|
||||
### Rozwiązywanie problemów ze scalaniem podzielonych wysyłek
|
||||
|
||||
Jeśli flaga jest włączona, a podzielone wysyłki nadal docierają jako dwie tury, sprawdź każdą warstwę:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Następnie `openclaw gateway restart` - flaga jest odczytywana podczas tworzenia rejestru debouncerów.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
Sprawdź dziennik serwera BlueBubbles w `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Zmierz odstęp między wysyłką tekstu w stylu `"Dump"` a następującą po niej wysyłką `"https://..."; Attachments:`. Podnieś `messages.inbound.byChannel.bluebubbles`, aby wygodnie pokryć ten odstęp.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
Znaczniki czasu zdarzeń sesji (`~/.openclaw/agents/<id>/sessions/*.jsonl`) odzwierciedlają moment, w którym Gateway przekazuje wiadomość agentowi, **a nie** moment nadejścia webhooka. Druga wiadomość w kolejce oznaczona `[Queued messages while agent was busy]` oznacza, że pierwsza tura nadal trwała, gdy dotarł drugi webhook - koszyk scalania został już opróżniony. Dostrajaj okno względem dziennika serwera BB, a nie dziennika sesji.
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
Na mniejszych maszynach (8 GB) tury agenta mogą trwać wystarczająco długo, aby koszyk scalania opróżnił się przed zakończeniem odpowiedzi, a URL trafił jako druga tura w kolejce. Sprawdź `memory_pressure` i `ps -o rss -p $(pgrep openclaw-gateway)`; jeśli Gateway przekracza ~500 MB RSS i kompresor jest aktywny, zamknij inne ciężkie procesy albo przenieś się na większy host.
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
Jeśli użytkownik stuknął `Dump` jako **odpowiedź** na istniejący dymek URL (iMessage pokazuje plakietkę „1 odpowiedź” na dymku Dump), URL znajduje się w `replyToBody`, a nie w drugim webhooku. Scalanie nie ma tu zastosowania - to kwestia umiejętności/promptu, a nie debouncera.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Przesyłanie blokowe
|
||||
|
||||
Kontroluj, czy odpowiedzi są wysyłane jako jedna wiadomość, czy strumieniowane w blokach:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Multimedia + limity
|
||||
|
||||
- Załączniki przychodzące są pobierane i przechowywane w pamięci podręcznej multimediów.
|
||||
- Limit multimediów przez `channels.bluebubbles.mediaMaxMb` dla multimediów przychodzących i wychodzących (domyślnie: 8 MB).
|
||||
- Tekst wychodzący jest dzielony na fragmenty zgodnie z `channels.bluebubbles.textChunkLimit` (domyślnie: 4000 znaków).
|
||||
|
||||
## Odwołanie do konfiguracji
|
||||
|
||||
Pełna konfiguracja: [Konfiguracja](/pl/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Połączenie i Webhook">
|
||||
- `channels.bluebubbles.enabled`: Włącz/wyłącz kanał.
|
||||
- `channels.bluebubbles.serverUrl`: Bazowy URL REST API BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Hasło API.
|
||||
- `channels.bluebubbles.webhookPath`: Ścieżka punktu końcowego Webhook (domyślnie: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Zasady dostępu">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (domyślnie: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Lista dozwolonych DM (uchwyty, e-maile, numery E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (domyślnie: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Lista dozwolonych nadawców grupowych.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: W systemie macOS opcjonalnie uzupełnia nienazwanych uczestników grupy na podstawie lokalnych Kontaktów po przejściu kontroli dostępu. Domyślnie: `false`.
|
||||
- `channels.bluebubbles.groups`: Konfiguracja dla poszczególnych grup (`requireMention` itd.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Dostarczanie i dzielenie na części">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Wysyłaj potwierdzenia odczytu (domyślnie: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Włącz strumieniowanie blokowe (domyślnie: `false`; wymagane dla odpowiedzi strumieniowych).
|
||||
- `channels.bluebubbles.textChunkLimit`: Rozmiar wychodzącej części w znakach (domyślnie: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Limit czasu na żądanie w ms dla wysyłania tekstu wychodzącego przez `/api/v1/message/text` (domyślnie: 30000). Zwiększ w konfiguracjach macOS 26, w których wysyłanie iMessage przez Private API może zawiesić się na ponad 60 sekund wewnątrz frameworka iMessage; na przykład `45000` lub `60000`. Próby, wyszukiwania czatów, reakcje, edycje i kontrole kondycji obecnie zachowują krótszą domyślną wartość 10 s; rozszerzenie zakresu na reakcje i edycje jest planowane jako kolejne usprawnienie. Nadpisanie dla konta: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (domyślnie) dzieli tylko po przekroczeniu `textChunkLimit`; `newline` dzieli na pustych wierszach (granicach akapitów) przed dzieleniem według długości.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Media i historia">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Limit mediów przychodzących/wychodzących w MB (domyślnie: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Jawna lista dozwolonych bezwzględnych katalogów lokalnych dopuszczonych dla wychodzących lokalnych ścieżek mediów. Wysyłanie ścieżek lokalnych jest domyślnie odmawiane, chyba że ta opcja jest skonfigurowana. Nadpisanie dla konta: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Scal kolejne Webhooki DM od tego samego nadawcy w jedną turę agenta, tak aby rozdzielone wysyłanie tekstu i URL przez Apple dotarło jako jedna wiadomość (domyślnie: `false`). Zobacz [Scalanie rozdzielonych DM](#coalescing-split-send-dms-command--url-in-one-composition), aby poznać scenariusze, strojenie okna i kompromisy. Po włączeniu bez jawnego `messages.inbound.byChannel.bluebubbles` rozszerza domyślne okno debounce dla wiadomości przychodzących z 500 ms do 2500 ms.
|
||||
- `channels.bluebubbles.historyLimit`: Maksymalna liczba wiadomości grupowych dla kontekstu (0 wyłącza).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Limit historii DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Gdy odpowiedź przychodząca dotrze bez `replyToBody`/`replyToSender`, a pamięciowa pamięć podręczna kontekstu odpowiedzi nie trafi, pobierz oryginalną wiadomość z HTTP API BlueBubbles jako awaryjne rozwiązanie best-effort (domyślnie: `false`). Przydatne w wdrożeniach z wieloma instancjami współdzielącymi jedno konto BlueBubbles, po restartach procesu albo po eksmisji długowiecznej pamięci podręcznej TTL/LRU. Pobieranie jest chronione przed SSRF tymi samymi zasadami co każde inne żądanie klienta BlueBubbles, nigdy nie zgłasza wyjątku i wypełnia pamięć podręczną, aby kolejne odpowiedzi amortyzowały koszt. Nadpisanie dla konta: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Ustawienie na poziomie kanału propaguje się do kont, które pomijają tę flagę.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Akcje i konta">
|
||||
- `channels.bluebubbles.actions`: Włącz/wyłącz określone akcje.
|
||||
- `channels.bluebubbles.accounts`: Konfiguracja wielu kont.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Powiązane opcje globalne:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (lub `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Adresowanie / cele dostarczania
|
||||
|
||||
Preferuj `chat_guid` dla stabilnego routingu:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (preferowane dla grup)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Bezpośrednie uchwyty: `+15555550123`, `user@example.com`
|
||||
- Jeśli bezpośredni uchwyt nie ma istniejącego czatu DM, OpenClaw utworzy go przez `POST /api/v1/chat/new`. Wymaga to włączenia BlueBubbles Private API.
|
||||
|
||||
### Routing iMessage a SMS
|
||||
|
||||
Gdy ten sam uchwyt ma na Macu zarówno czat iMessage, jak i SMS (na przykład numer telefonu zarejestrowany w iMessage, który otrzymywał także awaryjne wiadomości z zielonym dymkiem), OpenClaw preferuje czat iMessage i nigdy po cichu nie obniża trasy do SMS. Aby wymusić czat SMS, użyj jawnego prefiksu celu `sms:` (na przykład `sms:+15555550123`). Uchwyty bez pasującego czatu iMessage nadal wysyłają przez dowolny czat zgłoszony przez BlueBubbles.
|
||||
|
||||
## Bezpieczeństwo
|
||||
|
||||
- Żądania Webhook są uwierzytelniane przez porównanie parametrów zapytania lub nagłówków `guid`/`password` z `channels.bluebubbles.password`.
|
||||
- Zachowaj hasło API i punkt końcowy Webhook w tajemnicy (traktuj je jak dane uwierzytelniające).
|
||||
- Nie ma obejścia localhost dla uwierzytelniania Webhook BlueBubbles. Jeśli pośredniczysz w ruchu Webhook, zachowaj hasło BlueBubbles w żądaniu end-to-end. `gateway.trustedProxies` nie zastępuje tutaj `channels.bluebubbles.password`. Zobacz [Bezpieczeństwo Gateway](/pl/gateway/security#reverse-proxy-configuration).
|
||||
- Włącz HTTPS i reguły zapory na serwerze BlueBubbles, jeśli wystawiasz go poza swoją sieć LAN.
|
||||
|
||||
## Rozwiązywanie problemów
|
||||
|
||||
- Jeśli zdarzenia pisania/odczytu przestaną działać, sprawdź logi Webhook BlueBubbles i zweryfikuj, czy ścieżka Gateway odpowiada `channels.bluebubbles.webhookPath`.
|
||||
- Kody parowania wygasają po godzinie; użyj `openclaw pairing list bluebubbles` i `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reakcje wymagają prywatnego API BlueBubbles (`POST /api/v1/message/react`); upewnij się, że wersja serwera je udostępnia.
|
||||
- Edycja/cofnięcie wysłania wymaga macOS 13+ i zgodnej wersji serwera BlueBubbles. W macOS 26 (Tahoe) edycja obecnie nie działa z powodu zmian w private API.
|
||||
- Aktualizacje ikon grup mogą być zawodne w macOS 26 (Tahoe): API może zwrócić sukces, ale nowa ikona się nie zsynchronizuje.
|
||||
- OpenClaw automatycznie ukrywa znane niedziałające akcje na podstawie wersji macOS serwera BlueBubbles. Jeśli edycja nadal pojawia się w macOS 26 (Tahoe), wyłącz ją ręcznie za pomocą `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` jest włączone, ale rozdzielone wysyłki (np. `Dump` + URL) nadal docierają jako dwie tury: zobacz listę kontrolną [rozwiązywania problemów ze scalaniem rozdzielonych wysyłek](#split-send-coalescing-troubleshooting) - typowe przyczyny to zbyt krótkie okno debounce, znaczniki czasu logu sesji błędnie odczytane jako czas dotarcia Webhook albo wysłanie cytatu odpowiedzi (które używa `replyToBody`, a nie drugiego Webhooka).
|
||||
- Informacje o statusie/kondycji: `openclaw status --all` lub `openclaw status --deep`.
|
||||
|
||||
Ogólne informacje o przepływie pracy kanałów znajdziesz w przewodniku [Kanały](/pl/channels) oraz [Plugins](/pl/tools/plugin).
|
||||
|
||||
## Powiązane
|
||||
|
||||
- [Routing kanałów](/pl/channels/channel-routing) - routing sesji dla wiadomości
|
||||
- [Przegląd kanałów](/pl/channels) - wszystkie obsługiwane kanały
|
||||
- [Grupy](/pl/channels/groups) - zachowanie czatu grupowego i kontrola wzmianek
|
||||
- [Parowanie](/pl/channels/pairing) - uwierzytelnianie DM i przepływ parowania
|
||||
- [Bezpieczeństwo](/pl/gateway/security) - model dostępu i utwardzanie
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Instalujesz, konfigurujesz lub audytujesz plugin bluebubbles
|
||||
summary: Dodaje interfejs kanału BlueBubbles do wysyłania i odbierania wiadomości OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T09:50:31Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Dodaje powierzchnię kanału BlueBubbles do wysyłania i odbierania wiadomości OpenClaw.
|
||||
|
||||
## Dystrybucja
|
||||
|
||||
- Pakiet: `@openclaw/bluebubbles`
|
||||
- Ścieżka instalacji: npm; ClawHub
|
||||
|
||||
## Powierzchnia
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Powiązana dokumentacja
|
||||
|
||||
- [bluebubbles](/pl/channels/bluebubbles)
|
||||
@ -144,7 +144,6 @@ uninstall, and publishing commands.
|
||||
| Plugin | Description | Distribution | Surface |
|
||||
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
|
||||
| [acpx](/plugins/reference/acpx) | Embedded ACP runtime backend with plugin-owned session and transport management. | `@openclaw/acpx`<br />npm; ClawHub | skills |
|
||||
| [bluebubbles](/plugins/reference/bluebubbles) | Adds the BlueBubbles channel surface for sending and receiving OpenClaw messages. | `@openclaw/bluebubbles`<br />npm; ClawHub | channels: bluebubbles |
|
||||
| [brave](/plugins/reference/brave) | Adds web search provider support. | `@openclaw/brave-plugin`<br />npm; ClawHub | contracts: webSearchProviders |
|
||||
| [codex](/plugins/reference/codex) | Codex app-server harness and Codex-managed GPT model catalog. | `@openclaw/codex`<br />npm; ClawHub | providers: codex; contracts: mediaUnderstandingProviders, migrationProviders |
|
||||
| [diagnostics-otel](/plugins/reference/diagnostics-otel) | OpenClaw diagnostics OpenTelemetry exporter. | `@openclaw/diagnostics-otel`<br />npm; ClawHub: `clawhub:@openclaw/diagnostics-otel` | plugin |
|
||||
|
||||
@ -25,7 +25,6 @@ pnpm plugins:inventory:gen
|
||||
| [anthropic-vertex](/plugins/reference/anthropic-vertex) | Adds Anthropic Vertex model provider support to OpenClaw. | `@openclaw/anthropic-vertex-provider`<br />included in OpenClaw | providers: anthropic-vertex |
|
||||
| [arcee](/plugins/reference/arcee) | Adds Arcee model provider support to OpenClaw. | `@openclaw/arcee-provider`<br />included in OpenClaw | providers: arcee |
|
||||
| [azure-speech](/plugins/reference/azure-speech) | Azure AI Speech text-to-speech (MP3, native Ogg/Opus voice notes, PCM telephony). | `@openclaw/azure-speech`<br />included in OpenClaw | contracts: speechProviders |
|
||||
| [bluebubbles](/plugins/reference/bluebubbles) | Adds the BlueBubbles channel surface for sending and receiving OpenClaw messages. | `@openclaw/bluebubbles`<br />npm; ClawHub | channels: bluebubbles |
|
||||
| [bonjour](/plugins/reference/bonjour) | Advertise the local OpenClaw gateway over Bonjour/mDNS. | `@openclaw/bonjour`<br />included in OpenClaw | plugin |
|
||||
| [brave](/plugins/reference/brave) | Adds web search provider support. | `@openclaw/brave-plugin`<br />npm; ClawHub | contracts: webSearchProviders |
|
||||
| [browser](/plugins/reference/browser) | Adds agent-callable tools. | `@openclaw/browser-plugin`<br />included in OpenClaw | contracts: tools; skills |
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
summary: "Adds the BlueBubbles channel surface for sending and receiving OpenClaw messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the bluebubbles plugin
|
||||
title: "BlueBubbles plugin"
|
||||
---
|
||||
|
||||
# BlueBubbles plugin
|
||||
|
||||
Adds the BlueBubbles channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/bluebubbles`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Related docs
|
||||
|
||||
- [bluebubbles](/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Configurando o canal BlueBubbles
|
||||
- Solução de problemas do emparelhamento de Webhook
|
||||
- Configurando o iMessage no macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Suporte legado ao iMessage via servidor macOS BlueBubbles (envio/recebimento por REST, digitação, reações, pareamento, ações avançadas).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:52Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: Plugin legado incluído que se comunica com o servidor macOS do BlueBubbles por HTTP. Configurações existentes do BlueBubbles continuam funcionando, mas novas implantações do OpenClaw iMessage devem preferir o Plugin nativo [iMessage](/pt-BR/channels/imessage) quando seus requisitos forem adequados ao seu host.
|
||||
|
||||
<Warning>
|
||||
O BlueBubbles está obsoleto para novas configurações do OpenClaw.
|
||||
|
||||
O ecossistema upstream do BlueBubbles ainda está ativo, mas o OpenClaw depende da API do servidor macOS do BlueBubbles. Em 6 de maio de 2026, a branch de desenvolvimento oficial do [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) foi alterada pela última vez em [22 de janeiro de 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), e a versão mais recente do servidor ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) foi publicada em 16 de maio de 2025. O aplicativo cliente e os repositórios auxiliares têm atividade mais recente, então isso não é uma alegação de abandono; a descontinuação trata de reduzir a dependência do OpenClaw em relação a um servidor HTTP externo, Webhooks e superfície de compatibilidade com APIs privadas quando o caminho nativo `imsg` mantém a integração em um contrato stdio local.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
As versões atuais do OpenClaw incluem o BlueBubbles, portanto builds empacotados normais não precisam de uma etapa separada `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Visão geral
|
||||
|
||||
- Executa no macOS por meio do aplicativo auxiliar BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Fallback legado para instalações que já dependem de IDs de canal do BlueBubbles, estado de Webhook, destinos de grupo, entrega por Cron ou roteamento de workspace.
|
||||
- Recomendado/testado: macOS Sequoia (15). macOS Tahoe (26) funciona; a edição está atualmente quebrada no Tahoe, e atualizações de ícone de grupo podem relatar sucesso, mas não sincronizar.
|
||||
- O OpenClaw se comunica com ele por meio de sua API REST (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Mensagens recebidas chegam por Webhooks; respostas enviadas, indicadores de digitação, confirmações de leitura e tapbacks são chamadas REST.
|
||||
- Anexos e stickers são ingeridos como mídia de entrada (e expostos ao agente quando possível).
|
||||
- Respostas Auto-TTS que sintetizam áudio MP3 ou CAF são entregues como balões de memorando de voz do iMessage em vez de anexos de arquivo comuns.
|
||||
- O pareamento/lista de permissão funciona da mesma forma que outros canais (`/channels/pairing` etc.) com `channels.bluebubbles.allowFrom` + códigos de pareamento.
|
||||
- Reações são expostas como eventos de sistema, assim como Slack/Telegram, para que agentes possam "mencioná-las" antes de responder.
|
||||
- Recursos avançados: editar, cancelar envio, encadeamento de respostas, efeitos de mensagem, gerenciamento de grupos.
|
||||
|
||||
## Início rápido
|
||||
|
||||
<Steps>
|
||||
<Step title="Instale o BlueBubbles">
|
||||
Instale o servidor BlueBubbles no seu Mac (siga as instruções em [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Habilite a API web">
|
||||
Na configuração do BlueBubbles, habilite a API web e defina uma senha.
|
||||
</Step>
|
||||
<Step title="Configure o OpenClaw">
|
||||
Execute `openclaw onboard` e selecione BlueBubbles, ou configure manualmente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Aponte os Webhooks para o Gateway">
|
||||
Aponte os Webhooks do BlueBubbles para seu Gateway (exemplo: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Inicie o Gateway">
|
||||
Inicie o Gateway; ele registrará o manipulador de Webhook e iniciará o pareamento.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Segurança**
|
||||
|
||||
- Sempre defina uma senha de Webhook.
|
||||
- A autenticação de Webhook é sempre obrigatória. O OpenClaw rejeita solicitações de Webhook do BlueBubbles a menos que elas incluam uma senha/guid que corresponda a `channels.bluebubbles.password` (por exemplo, `?password=<password>` ou `x-password`), independentemente da topologia de loopback/proxy.
|
||||
- A autenticação por senha é verificada antes de ler/analisar corpos completos de Webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Mantendo o Messages.app ativo (configurações de VM / headless)
|
||||
|
||||
Algumas configurações de VM macOS / sempre ativas podem acabar com o Messages.app ficando "ocioso" (eventos recebidos param até que o app seja aberto/colocado em primeiro plano). Uma solução alternativa simples é **tocar o Messages a cada 5 minutos** usando um AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Salve o AppleScript">
|
||||
Salve isto como `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Instale um LaunchAgent">
|
||||
Salve isto como `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Isso executa **a cada 300 segundos** e **no login**. A primeira execução pode acionar prompts de **Automation** do macOS (`osascript` → Messages). Aprove-os na mesma sessão de usuário que executa o LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Carregue-o">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
O BlueBubbles está disponível no onboarding interativo:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
O assistente solicita:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Endereço do servidor BlueBubbles (por exemplo, `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Senha da API das configurações do BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Caminho do endpoint de Webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` ou `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Números de telefone, emails ou destinos de chat.
|
||||
</ParamField>
|
||||
|
||||
Você também pode adicionar o BlueBubbles via CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Controle de acesso (DMs + grupos)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Padrão: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Remetentes desconhecidos recebem um código de pareamento; mensagens são ignoradas até serem aprovadas (códigos expiram após 1 hora).
|
||||
- Aprove via:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Pareamento é a troca de token padrão. Detalhes: [Pareamento](/pt-BR/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Grupos">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (padrão: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` controla quem pode acionar em grupos quando `allowlist` está definido.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Enriquecimento de nome de contato (macOS, opcional)
|
||||
|
||||
Webhooks de grupo do BlueBubbles frequentemente incluem apenas endereços brutos dos participantes. Se você quiser que o contexto `GroupMembers` mostre nomes de contatos locais em vez disso, pode optar por enriquecimento local de Contatos no macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` habilita a consulta. Padrão: `false`.
|
||||
- As consultas são executadas somente depois que acesso ao grupo, autorização de comando e gating de menção permitiram a passagem da mensagem.
|
||||
- Somente participantes por telefone sem nome são enriquecidos.
|
||||
- Números de telefone brutos permanecem como fallback quando nenhuma correspondência local é encontrada.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Gating de menção (grupos)
|
||||
|
||||
O BlueBubbles oferece suporte a gating de menção para chats em grupo, correspondendo ao comportamento do iMessage/WhatsApp:
|
||||
|
||||
- Usa `agents.list[].groupChat.mentionPatterns` (ou `messages.groupChat.mentionPatterns`) para detectar menções.
|
||||
- Quando `requireMention` está habilitado para um grupo, o agente responde somente quando mencionado.
|
||||
- Comandos de controle de remetentes autorizados ignoram o gating de menção.
|
||||
|
||||
Configuração por grupo:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Gating de comandos
|
||||
|
||||
- Comandos de controle (por exemplo, `/config`, `/model`) exigem autorização.
|
||||
- Usa `allowFrom` e `groupAllowFrom` para determinar a autorização de comando.
|
||||
- Remetentes autorizados podem executar comandos de controle mesmo sem mencionar em grupos.
|
||||
|
||||
### Prompt de sistema por grupo
|
||||
|
||||
Cada entrada em `channels.bluebubbles.groups.*` aceita uma string `systemPrompt` opcional. O valor é injetado no prompt de sistema do agente em cada turno que processa uma mensagem nesse grupo, para que você possa definir persona ou regras comportamentais por grupo sem editar prompts de agente:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
A chave corresponde ao que o BlueBubbles relata como `chatGuid` / `chatIdentifier` / `chatId` numérico para o grupo, e uma entrada curinga `"*"` fornece um padrão para cada grupo sem correspondência exata (o mesmo padrão usado por `requireMention` e políticas de ferramenta por grupo). Correspondências exatas sempre vencem o curinga. DMs ignoram este campo; use personalização de prompt no nível do agente ou da conta em vez disso.
|
||||
|
||||
#### Exemplo prático: respostas encadeadas e reações tapback (API privada)
|
||||
|
||||
Com a API privada do BlueBubbles habilitada, mensagens recebidas chegam com IDs curtos de mensagem (por exemplo, `[[reply_to:5]]`) e o agente pode chamar `action=reply` para encadear em uma mensagem específica ou `action=react` para adicionar um tapback. Um `systemPrompt` por grupo é uma forma confiável de manter o agente escolhendo a ferramenta certa:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Reações tapback e respostas encadeadas exigem a API privada do BlueBubbles; consulte [Ações avançadas](#advanced-actions) e [IDs de mensagem](#message-ids-short-vs-full) para a mecânica subjacente.
|
||||
|
||||
## Bindings de conversa ACP
|
||||
|
||||
Chats do BlueBubbles podem ser transformados em workspaces ACP duráveis sem alterar a camada de transporte.
|
||||
|
||||
Fluxo rápido de operador:
|
||||
|
||||
- Execute `/acp spawn codex --bind here` dentro da DM ou do chat em grupo permitido.
|
||||
- Mensagens futuras nessa mesma conversa do BlueBubbles são roteadas para a sessão ACP gerada.
|
||||
- `/new` e `/reset` redefinem a mesma sessão ACP vinculada no lugar.
|
||||
- `/acp close` fecha a sessão ACP e remove o binding.
|
||||
|
||||
Bindings persistentes configurados também são compatíveis por meio de entradas de nível superior `bindings[]` com `type: "acp"` e `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` pode usar qualquer forma de destino compatível do BlueBubbles:
|
||||
|
||||
- identificador de DM normalizado, como `+15555550123` ou `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Para vínculos de grupo estáveis, prefira `chat_id:*` ou `chat_identifier:*`.
|
||||
|
||||
Exemplo:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Consulte [Agentes ACP](/pt-BR/tools/acp-agents) para o comportamento compartilhado de vínculo ACP.
|
||||
|
||||
## Digitação + confirmações de leitura
|
||||
|
||||
- **Indicadores de digitação**: Enviados automaticamente antes e durante a geração da resposta.
|
||||
- **Confirmações de leitura**: Controladas por `channels.bluebubbles.sendReadReceipts` (padrão: `true`).
|
||||
- **Indicadores de digitação**: O OpenClaw envia eventos de início de digitação; o BlueBubbles limpa a digitação automaticamente ao enviar ou após tempo limite (a parada manual via DELETE não é confiável).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // desativar confirmações de leitura
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Ações avançadas
|
||||
|
||||
O BlueBubbles oferece suporte a ações avançadas de mensagem quando habilitadas na configuração:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (padrão: true)
|
||||
edit: true, // editar mensagens enviadas (macOS 13+, quebrado no macOS 26 Tahoe)
|
||||
unsend: true, // desfazer envio de mensagens (macOS 13+)
|
||||
reply: true, // encadeamento de respostas por GUID da mensagem
|
||||
sendWithEffect: true, // efeitos de mensagem (slam, loud etc.)
|
||||
renameGroup: true, // renomear conversas em grupo
|
||||
setGroupIcon: true, // definir ícone/foto da conversa em grupo (instável no macOS 26 Tahoe)
|
||||
addParticipant: true, // adicionar participantes a grupos
|
||||
removeParticipant: true, // remover participantes de grupos
|
||||
leaveGroup: true, // sair de conversas em grupo
|
||||
sendAttachment: true, // enviar anexos/mídia
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ações disponíveis">
|
||||
- **react**: Adicionar/remover reações de tapback (`messageId`, `emoji`, `remove`). O conjunto nativo de tapbacks do iMessage é `love`, `like`, `dislike`, `laugh`, `emphasize` e `question`. Quando um agente escolhe um emoji fora desse conjunto (por exemplo, `👀`), a ferramenta de reação recorre a `love` para que o tapback ainda seja renderizado em vez de falhar a solicitação inteira. Reações de confirmação configuradas ainda validam de forma estrita e geram erro em valores desconhecidos.
|
||||
- **edit**: Editar uma mensagem enviada (`messageId`, `text`).
|
||||
- **unsend**: Desfazer o envio de uma mensagem (`messageId`).
|
||||
- **reply**: Responder a uma mensagem específica (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Enviar com efeito do iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Renomear uma conversa em grupo (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Definir o ícone/foto de uma conversa em grupo (`chatGuid`, `media`) - instável no macOS 26 Tahoe (a API pode retornar sucesso, mas o ícone não sincroniza).
|
||||
- **addParticipant**: Adicionar alguém a um grupo (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Remover alguém de um grupo (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Sair de uma conversa em grupo (`chatGuid`).
|
||||
- **upload-file**: Enviar mídia/arquivos (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Recados de voz: defina `asVoice: true` com áudio **MP3** ou **CAF** para enviar como mensagem de voz do iMessage. O BlueBubbles converte MP3 → CAF ao enviar recados de voz.
|
||||
- Alias legado: `sendAttachment` ainda funciona, mas `upload-file` é o nome de ação canônico.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### IDs de mensagem (curtos vs. completos)
|
||||
|
||||
O OpenClaw pode expor IDs de mensagem _curtos_ (por exemplo, `1`, `2`) para economizar tokens.
|
||||
|
||||
- `MessageSid` / `ReplyToId` podem ser IDs curtos.
|
||||
- `MessageSidFull` / `ReplyToIdFull` contêm os IDs completos do provedor.
|
||||
- IDs curtos ficam em memória; eles podem expirar ao reiniciar ou por remoção do cache.
|
||||
- As ações aceitam `messageId` curto ou completo, mas IDs curtos gerarão erro se não estiverem mais disponíveis.
|
||||
|
||||
Use IDs completos para automações e armazenamento duráveis:
|
||||
|
||||
- Modelos: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Contexto: `MessageSidFull` / `ReplyToIdFull` em payloads de entrada
|
||||
|
||||
Consulte [Configuração](/pt-BR/gateway/configuration) para variáveis de modelo.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Agrupamento de DMs de envio dividido (comando + URL em uma composição)
|
||||
|
||||
Quando um usuário digita um comando e uma URL juntos no iMessage - por exemplo, `Dump https://example.com/article` - a Apple divide o envio em **duas entregas de Webhook separadas**:
|
||||
|
||||
1. Uma mensagem de texto (`"Dump"`).
|
||||
2. Um balão de prévia de URL (`"https://..."`) com imagens de prévia OG como anexos.
|
||||
|
||||
Os dois webhooks chegam ao OpenClaw com ~0,8-2,0 s de diferença na maioria das configurações. Sem agrupamento, o agente recebe apenas o comando no turno 1, responde (geralmente "envie a URL") e só vê a URL no turno 2 - momento em que o contexto do comando já foi perdido.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` opta uma DM por mesclar webhooks consecutivos do mesmo remetente em um único turno do agente. Conversas em grupo continuam a usar a chave por mensagem para preservar a estrutura de turnos com vários usuários.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Quando habilitar">
|
||||
Habilite quando:
|
||||
|
||||
- Você entrega Skills que esperam `command + payload` em uma única mensagem (dump, paste, save, queue etc.).
|
||||
- Seus usuários colam URLs, imagens ou conteúdo longo junto com comandos.
|
||||
- Você pode aceitar a latência adicional do turno de DM (veja abaixo).
|
||||
|
||||
Deixe desabilitado quando:
|
||||
|
||||
- Você precisa de latência mínima de comando para gatilhos de DM de uma só palavra.
|
||||
- Todos os seus fluxos são comandos de disparo único sem payloads posteriores.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Habilitando">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // optar por habilitar (padrão: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Com a flag ativada e sem `messages.inbound.byChannel.bluebubbles` explícito, a janela de debounce aumenta para **2500 ms** (o padrão para sem agrupamento é 500 ms). A janela mais ampla é necessária - a cadência de envio dividido da Apple de 0,8-2,0 s não cabe no padrão mais estreito.
|
||||
|
||||
Para ajustar a janela você mesmo:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms funciona para a maioria das configurações; aumente para 4000 ms se o seu Mac estiver lento
|
||||
// ou sob pressão de memória (a lacuna observada pode passar de 2 s nesses casos).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **Latência adicional para comandos de controle por DM.** Com a flag ativada, mensagens de comando de controle por DM (como `Dump`, `Save` etc.) agora aguardam até a janela de debounce antes do despacho, caso um Webhook de payload esteja chegando. Comandos de conversa em grupo mantêm despacho instantâneo.
|
||||
- **A saída mesclada é limitada** - o texto mesclado é limitado a 4000 caracteres com um marcador explícito `…[truncated]`; anexos são limitados a 20; entradas de origem são limitadas a 10 (a primeira e a mais recente são mantidas além disso). Todo `messageId` de origem ainda chega à deduplicação de entrada, então uma repetição posterior do MessagePoller de qualquer evento individual é reconhecida como duplicata.
|
||||
- **Opt-in, por canal.** Outros canais (Telegram, WhatsApp, Slack, …) não são afetados.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Cenários e o que o agente vê
|
||||
|
||||
| Usuário compõe | Apple entrega | Flag desativada (padrão) | Flag ativada + janela de 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| `Dump https://example.com` (um envio) | 2 webhooks com ~1 s de intervalo | Dois turnos do agente: apenas "Dump", depois URL | Um turno: texto mesclado `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (anexo + texto) | 2 webhooks | Dois turnos | Um turno: texto + imagem |
|
||||
| `/status` (comando isolado) | 1 Webhook | Despacho instantâneo | **Aguarda até a janela e então despacha** |
|
||||
| URL colada sozinha | 1 Webhook | Despacho instantâneo | Despacho instantâneo (apenas uma entrada no bucket) |
|
||||
| Texto + URL enviados como duas mensagens separadas deliberadas, com minutos de intervalo | 2 webhooks fora da janela | Dois turnos | Dois turnos (a janela expira entre eles) |
|
||||
| Enxurrada rápida (>10 DMs pequenas dentro da janela) | N webhooks | N turnos | Um turno, saída limitada (primeira + mais recente, limites de texto/anexo aplicados) |
|
||||
|
||||
### Solução de problemas de agrupamento de envio dividido
|
||||
|
||||
Se a flag estiver ativada e envios divididos ainda chegarem como dois turnos, verifique cada camada:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Configuração realmente carregada">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Em seguida, `openclaw gateway restart` - a flag é lida na criação do debouncer-registry.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Janela de debounce ampla o suficiente para sua configuração">
|
||||
Veja o log do servidor BlueBubbles em `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Meça a lacuna entre o despacho de texto no estilo `"Dump"` e o despacho `"https://..."; Attachments:` que vem em seguida. Aumente `messages.inbound.byChannel.bluebubbles` para cobrir essa lacuna com folga.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Timestamps de JSONL de sessão ≠ chegada do Webhook">
|
||||
Timestamps de eventos de sessão (`~/.openclaw/agents/<id>/sessions/*.jsonl`) refletem quando o Gateway entrega uma mensagem ao agente, **não** quando o Webhook chegou. Uma segunda mensagem na fila marcada com `[Queued messages while agent was busy]` significa que o primeiro turno ainda estava em execução quando o segundo Webhook chegou - o bucket de agrupamento já tinha sido liberado. Ajuste a janela com base no log do servidor BB, não no log da sessão.
|
||||
</Accordion>
|
||||
<Accordion title="Pressão de memória retardando o despacho de resposta">
|
||||
Em máquinas menores (8 GB), turnos de agente podem demorar o suficiente para que o bucket de agrupamento seja liberado antes de a resposta ser concluída, e a URL entre como um segundo turno na fila. Verifique `memory_pressure` e `ps -o rss -p $(pgrep openclaw-gateway)`; se o Gateway estiver acima de ~500 MB RSS e o compressor estiver ativo, feche outros processos pesados ou mude para um host maior.
|
||||
</Accordion>
|
||||
<Accordion title="Envios de citação de resposta seguem outro caminho">
|
||||
Se o usuário tocou em `Dump` como uma **resposta** a um balão de URL existente (o iMessage mostra um selo "1 Reply" no balão de Dump), a URL fica em `replyToBody`, não em um segundo Webhook. O agrupamento não se aplica - isso é uma questão de skill/prompt, não uma questão de debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Streaming em blocos
|
||||
|
||||
Controle se as respostas são enviadas como uma única mensagem ou transmitidas em blocos:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // habilitar streaming em blocos (desativado por padrão)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Mídia + limites
|
||||
|
||||
- Anexos de entrada são baixados e armazenados no cache de mídia.
|
||||
- Limite de mídia via `channels.bluebubbles.mediaMaxMb` para mídia de entrada e saída (padrão: 8 MB).
|
||||
- O texto de saída é dividido em blocos conforme `channels.bluebubbles.textChunkLimit` (padrão: 4000 caracteres).
|
||||
|
||||
## Referência de configuração
|
||||
|
||||
Configuração completa: [Configuração](/pt-BR/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Conexão e Webhook">
|
||||
- `channels.bluebubbles.enabled`: Habilita/desabilita o canal.
|
||||
- `channels.bluebubbles.serverUrl`: URL base da API REST do BlueBubbles.
|
||||
- `channels.bluebubbles.password`: Senha da API.
|
||||
- `channels.bluebubbles.webhookPath`: Caminho do endpoint de Webhook (padrão: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Política de acesso">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (padrão: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Lista de permissões de DM (identificadores, e-mails, números E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (padrão: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Lista de permissões de remetentes de grupo.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: No macOS, opcionalmente enriquece participantes de grupo sem nome a partir dos Contatos locais depois que a filtragem passa. Padrão: `false`.
|
||||
- `channels.bluebubbles.groups`: Configuração por grupo (`requireMention` etc.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Entrega e fragmentação">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Envia confirmações de leitura (padrão: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Habilita streaming em bloco (padrão: `false`; obrigatório para respostas em streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Tamanho do fragmento de saída em caracteres (padrão: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Tempo limite por solicitação em ms para envios de texto de saída via `/api/v1/message/text` (padrão: 30000). Aumente em configurações do macOS 26 nas quais envios do iMessage pela Private API podem travar por mais de 60 segundos dentro do framework do iMessage; por exemplo, `45000` ou `60000`. Sondagens, buscas de chats, reações, edições e verificações de integridade atualmente mantêm o padrão mais curto de 10s; ampliar a cobertura para reações e edições está planejado como acompanhamento. Substituição por conta: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (padrão) divide somente ao exceder `textChunkLimit`; `newline` divide em linhas em branco (limites de parágrafo) antes da fragmentação por comprimento.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Mídia e histórico">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Limite de mídia de entrada/saída em MB (padrão: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Lista de permissões explícita de diretórios locais absolutos permitidos para caminhos de mídia local de saída. Envios de caminhos locais são negados por padrão, a menos que isto esteja configurado. Substituição por conta: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Mescla Webhooks consecutivos de DM do mesmo remetente em uma única vez do agente, para que o envio dividido de texto+URL da Apple chegue como uma única mensagem (padrão: `false`). Consulte [Combinar DMs de envio dividido](#coalescing-split-send-dms-command--url-in-one-composition) para cenários, ajuste de janela e compensações. Amplia a janela padrão de debounce de entrada de 500 ms para 2500 ms quando habilitado sem um `messages.inbound.byChannel.bluebubbles` explícito.
|
||||
- `channels.bluebubbles.historyLimit`: Máximo de mensagens de grupo para contexto (0 desabilita).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Limite de histórico de DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Quando uma resposta de entrada chega sem `replyToBody`/`replyToSender` e o cache em memória de contexto de resposta não acerta, busca a mensagem original na API HTTP do BlueBubbles como fallback de melhor esforço (padrão: `false`). Útil para implantações multi-instância que compartilham uma conta do BlueBubbles, após reinicializações do processo ou após despejo de cache TTL/LRU de longa duração. A busca é protegida contra SSRF pela mesma política de todas as outras solicitações do cliente BlueBubbles, nunca lança erro e preenche o cache para amortizar respostas subsequentes. Substituição por conta: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Uma configuração no nível do canal se propaga para contas que omitem a flag.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Ações e contas">
|
||||
- `channels.bluebubbles.actions`: Habilita/desabilita ações específicas.
|
||||
- `channels.bluebubbles.accounts`: Configuração de várias contas.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Opções globais relacionadas:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (ou `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Endereçamento / destinos de entrega
|
||||
|
||||
Prefira `chat_guid` para roteamento estável:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (preferido para grupos)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Identificadores diretos: `+15555550123`, `user@example.com`
|
||||
- Se um identificador direto não tiver um chat de DM existente, o OpenClaw criará um via `POST /api/v1/chat/new`. Isto exige que a Private API do BlueBubbles esteja habilitada.
|
||||
|
||||
### Roteamento iMessage vs SMS
|
||||
|
||||
Quando o mesmo identificador tem tanto um chat do iMessage quanto um chat SMS no Mac (por exemplo, um número de telefone registrado no iMessage que também recebeu fallbacks de balão verde), o OpenClaw prefere o chat do iMessage e nunca rebaixa silenciosamente para SMS. Para forçar o chat SMS, use um prefixo de destino `sms:` explícito (por exemplo, `sms:+15555550123`). Identificadores sem um chat do iMessage correspondente ainda enviam por qualquer chat que o BlueBubbles informar.
|
||||
|
||||
## Segurança
|
||||
|
||||
- Solicitações de Webhook são autenticadas comparando parâmetros de consulta ou cabeçalhos `guid`/`password` com `channels.bluebubbles.password`.
|
||||
- Mantenha a senha da API e o endpoint de Webhook em segredo (trate-os como credenciais).
|
||||
- Não há bypass de localhost para autenticação de Webhook do BlueBubbles. Se você encaminhar tráfego de Webhook por proxy, mantenha a senha do BlueBubbles na solicitação de ponta a ponta. `gateway.trustedProxies` não substitui `channels.bluebubbles.password` aqui. Consulte [Segurança do Gateway](/pt-BR/gateway/security#reverse-proxy-configuration).
|
||||
- Habilite HTTPS + regras de firewall no servidor BlueBubbles se o expuser fora da sua LAN.
|
||||
|
||||
## Solução de problemas
|
||||
|
||||
- Se eventos de digitação/leitura pararem de funcionar, verifique os logs de Webhook do BlueBubbles e confirme se o caminho do Gateway corresponde a `channels.bluebubbles.webhookPath`.
|
||||
- Códigos de pareamento expiram após uma hora; use `openclaw pairing list bluebubbles` e `openclaw pairing approve bluebubbles <code>`.
|
||||
- Reações exigem a API privada do BlueBubbles (`POST /api/v1/message/react`); certifique-se de que a versão do servidor a exponha.
|
||||
- Editar/desfazer envio exige macOS 13+ e uma versão compatível do servidor BlueBubbles. No macOS 26 (Tahoe), a edição está atualmente quebrada devido a mudanças na API privada.
|
||||
- Atualizações de ícone de grupo podem ser instáveis no macOS 26 (Tahoe): a API pode retornar sucesso, mas o novo ícone não sincroniza.
|
||||
- O OpenClaw oculta automaticamente ações conhecidamente quebradas com base na versão de macOS do servidor BlueBubbles. Se a edição ainda aparecer no macOS 26 (Tahoe), desabilite-a manualmente com `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` habilitado, mas envios divididos (por exemplo, `Dump` + URL) ainda chegam como duas vezes: consulte a lista de verificação de [solução de problemas de combinação de envios divididos](#split-send-coalescing-troubleshooting) - causas comuns são uma janela de debounce curta demais, timestamps do log de sessão interpretados incorretamente como chegada de Webhook ou um envio com citação de resposta (que usa `replyToBody`, não um segundo Webhook).
|
||||
- Para informações de status/integridade: `openclaw status --all` ou `openclaw status --deep`.
|
||||
|
||||
Para referência geral do fluxo de trabalho de canais, consulte [Canais](/pt-BR/channels) e o guia de [Plugins](/pt-BR/tools/plugin).
|
||||
|
||||
## Relacionados
|
||||
|
||||
- [Roteamento de canais](/pt-BR/channels/channel-routing) - roteamento de sessão para mensagens
|
||||
- [Visão geral dos canais](/pt-BR/channels) - todos os canais compatíveis
|
||||
- [Grupos](/pt-BR/channels/groups) - comportamento de chat em grupo e filtragem por menção
|
||||
- [Pareamento](/pt-BR/channels/pairing) - autenticação de DM e fluxo de pareamento
|
||||
- [Segurança](/pt-BR/gateway/security) - modelo de acesso e reforço de segurança
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Você está instalando, configurando ou auditando o Plugin bluebubbles
|
||||
summary: Adiciona a superfície de canal BlueBubbles para enviar e receber mensagens do OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T05:51:32Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Adiciona a superfície de canal BlueBubbles para enviar e receber mensagens do OpenClaw.
|
||||
|
||||
## Distribuição
|
||||
|
||||
- Pacote: `@openclaw/bluebubbles`
|
||||
- Rota de instalação: npm; ClawHub
|
||||
|
||||
## Superfície
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Documentação relacionada
|
||||
|
||||
- [bluebubbles](/pt-BR/channels/bluebubbles)
|
||||
@ -17,11 +17,9 @@ OpenClaw integrates external CLIs via JSON-RPC. Two patterns are used today.
|
||||
|
||||
See [Signal](/channels/signal) for setup and endpoints.
|
||||
|
||||
## Pattern B: stdio child process (legacy: imsg)
|
||||
## Pattern B: stdio child process (imsg)
|
||||
|
||||
> **Note:** For new iMessage setups, use [BlueBubbles](/channels/bluebubbles) instead.
|
||||
|
||||
- OpenClaw spawns `imsg rpc` as a child process (legacy iMessage integration).
|
||||
- OpenClaw spawns `imsg rpc` as a child process for [iMessage](/channels/imessage).
|
||||
- JSON-RPC is line-delimited over stdin/stdout (one JSON object per line).
|
||||
- No TCP port, no daemon required.
|
||||
|
||||
|
||||
@ -82,8 +82,6 @@ Scope intent:
|
||||
- `channels.irc.nickserv.password`
|
||||
- `channels.irc.accounts.*.password`
|
||||
- `channels.irc.accounts.*.nickserv.password`
|
||||
- `channels.bluebubbles.password`
|
||||
- `channels.bluebubbles.accounts.*.password`
|
||||
- `channels.feishu.appSecret`
|
||||
- `channels.feishu.encryptKey`
|
||||
- `channels.feishu.verificationToken`
|
||||
|
||||
@ -60,20 +60,6 @@
|
||||
"optIn": true,
|
||||
"notes": "Compatibility exception: sibling ref field remains canonical."
|
||||
},
|
||||
{
|
||||
"id": "channels.bluebubbles.accounts.*.password",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "channels.bluebubbles.accounts.*.password",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "channels.bluebubbles.password",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "channels.bluebubbles.password",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "channels.discord.accounts.*.pluralkit.token",
|
||||
"configFile": "openclaw.json",
|
||||
|
||||
@ -102,8 +102,7 @@ For a high-level overview, see [Onboarding (CLI)](/start/wizard).
|
||||
- [Google Chat](/channels/googlechat): service account JSON + webhook audience.
|
||||
- [Mattermost](/channels/mattermost) (plugin): bot token + base URL.
|
||||
- [Signal](/channels/signal): optional `signal-cli` install + account config.
|
||||
- [BlueBubbles](/channels/bluebubbles): **recommended for iMessage**; server URL + password + webhook.
|
||||
- [iMessage](/channels/imessage): legacy `imsg` CLI path + DB access.
|
||||
- [iMessage](/channels/imessage): `imsg` CLI path + Messages DB access; use an SSH wrapper when the Gateway runs off-Mac.
|
||||
- DM security: default is pairing. First DM sends a code; approve via `openclaw pairing approve <channel> <code>` or use allowlists.
|
||||
|
||||
</Step>
|
||||
@ -249,5 +248,5 @@ will prompt to install it (npm or a local path) before it can be configured.
|
||||
- Onboarding overview: [Onboarding (CLI)](/start/wizard)
|
||||
- macOS app onboarding: [Onboarding](/start/onboarding)
|
||||
- Config reference: [Gateway configuration](/gateway/configuration)
|
||||
- Providers: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord), [Google Chat](/channels/googlechat), [Signal](/channels/signal), [BlueBubbles](/channels/bluebubbles) (iMessage), [iMessage](/channels/imessage) (legacy)
|
||||
- Providers: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord), [Google Chat](/channels/googlechat), [Signal](/channels/signal), [iMessage](/channels/imessage)
|
||||
- Skills: [Skills](/tools/skills), [Skills config](/tools/skills-config)
|
||||
|
||||
@ -39,7 +39,6 @@ For a complete map of the docs, see [Docs hubs](/start/hubs).
|
||||
- [Telegram](/channels/telegram)
|
||||
- [Discord](/channels/discord)
|
||||
- [Mattermost](/channels/mattermost)
|
||||
- [BlueBubbles (legacy iMessage bridge)](/channels/bluebubbles)
|
||||
- [QQ Bot](/channels/qqbot)
|
||||
- [iMessage](/channels/imessage)
|
||||
- [Groups](/channels/groups)
|
||||
|
||||
@ -73,7 +73,6 @@ Use these hubs to discover every page, including deep dives and reference docs t
|
||||
- [Discord](/channels/discord)
|
||||
- [Mattermost](/channels/mattermost)
|
||||
- [Signal](/channels/signal)
|
||||
- [BlueBubbles (legacy iMessage bridge)](/channels/bluebubbles)
|
||||
- [QQ Bot](/channels/qqbot)
|
||||
- [iMessage](/channels/imessage)
|
||||
- [Location parsing](/channels/location)
|
||||
|
||||
@ -31,7 +31,7 @@ Regardless of which path you choose, onboarding sets up:
|
||||
2. **Workspace** — directory for agent files, bootstrap templates, and memory
|
||||
3. **Gateway** — port, bind address, auth mode
|
||||
4. **Channels** (optional) — built-in and bundled chat channels such as
|
||||
BlueBubbles, Discord, Feishu, Google Chat, Mattermost, Microsoft Teams,
|
||||
iMessage, Discord, Feishu, Google Chat, Mattermost, Microsoft Teams,
|
||||
Telegram, WhatsApp, and more
|
||||
5. **Daemon** (optional) — background service so the Gateway starts automatically
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ Local mode (default) walks you through:
|
||||
- Model and auth setup (OpenAI Code subscription OAuth, Anthropic Claude CLI or API key, plus MiniMax, GLM, Ollama, Moonshot, StepFun, and AI Gateway options)
|
||||
- Workspace location and bootstrap files
|
||||
- Gateway settings (port, bind, auth, tailscale)
|
||||
- Channels and providers (Telegram, WhatsApp, Discord, Google Chat, Mattermost, Signal, BlueBubbles, and other bundled channel plugins)
|
||||
- Channels and providers (Telegram, WhatsApp, Discord, Google Chat, Mattermost, Signal, iMessage, and other bundled channel plugins)
|
||||
- Daemon install (LaunchAgent, systemd user unit, or native Windows Scheduled Task with Startup-folder fallback)
|
||||
- Health check
|
||||
- Skills setup
|
||||
@ -70,8 +70,7 @@ It does not install or modify anything on the remote host.
|
||||
- [Google Chat](/channels/googlechat): service account JSON + webhook audience
|
||||
- [Mattermost](/channels/mattermost): bot token + base URL
|
||||
- [Signal](/channels/signal): optional `signal-cli` install + account config
|
||||
- [BlueBubbles](/channels/bluebubbles): recommended for iMessage; server URL + password + webhook
|
||||
- [iMessage](/channels/imessage): legacy `imsg` CLI path + DB access
|
||||
- [iMessage](/channels/imessage): `imsg` CLI path + Messages DB access; use an SSH wrapper when the Gateway runs off-Mac
|
||||
- DM security: default is pairing. First DM sends a code; approve via
|
||||
`openclaw pairing approve <channel> <code>` or use allowlists.
|
||||
</Step>
|
||||
|
||||
@ -77,7 +77,7 @@ Onboarding starts with **QuickStart** (defaults) vs **Advanced** (full control).
|
||||
3. **Gateway** — Port, bind address, auth mode, Tailscale exposure.
|
||||
In interactive token mode, choose default plaintext token storage or opt into SecretRef.
|
||||
Non-interactive token SecretRef path: `--gateway-token-ref-env <ENV_VAR>`.
|
||||
4. **Channels** — built-in and bundled chat channels such as BlueBubbles, Discord, Feishu, Google Chat, Mattermost, Microsoft Teams, QQ Bot, Signal, Slack, Telegram, WhatsApp, and more.
|
||||
4. **Channels** — built-in and bundled chat channels such as iMessage, Discord, Feishu, Google Chat, Mattermost, Microsoft Teams, QQ Bot, Signal, Slack, Telegram, WhatsApp, and more.
|
||||
5. **Daemon** — Installs a LaunchAgent (macOS), systemd user unit (Linux/WSL2), or native Windows Scheduled Task with per-user Startup-folder fallback.
|
||||
If token auth requires a token and `gateway.auth.token` is SecretRef-managed, daemon install validates it but does not persist the resolved token into supervisor service environment metadata.
|
||||
If token auth requires a token and the configured token SecretRef is unresolved, daemon install is blocked with actionable guidance.
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- การตั้งค่าช่องทาง BlueBubbles
|
||||
- การแก้ไขปัญหาการจับคู่ Webhook
|
||||
- การกำหนดค่า iMessage บน macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: การรองรับ iMessage แบบเดิมผ่านเซิร์ฟเวอร์ macOS ของ BlueBubbles (การส่ง/รับผ่าน REST, การแสดงสถานะกำลังพิมพ์, รีแอ็กชัน, การจับคู่, การดำเนินการขั้นสูง).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:48Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
สถานะ: Plugin แบบเดิมที่บันเดิลมาด้วย ซึ่งสื่อสารกับเซิร์ฟเวอร์ BlueBubbles บน macOS ผ่าน HTTP การตั้งค่า BlueBubbles ที่มีอยู่ยังคงใช้งานได้ต่อไป แต่การปรับใช้ OpenClaw iMessage ใหม่ควรเลือกใช้ Plugin [iMessage](/th/channels/imessage) แบบเนทีฟเมื่อข้อกำหนดของมันเหมาะกับโฮสต์ของคุณ
|
||||
|
||||
<Warning>
|
||||
BlueBubbles เลิกแนะนำสำหรับการตั้งค่า OpenClaw ใหม่แล้ว
|
||||
|
||||
ระบบนิเวศ BlueBubbles ต้นน้ำยังคงมีการพัฒนาอยู่ แต่ OpenClaw พึ่งพา API ของเซิร์ฟเวอร์ BlueBubbles บน macOS ณ วันที่ 6 พฤษภาคม 2026 สาขาพัฒนาของ [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) อย่างเป็นทางการเปลี่ยนแปลงล่าสุดเมื่อ [22 มกราคม 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037) และรุ่นเซิร์ฟเวอร์ล่าสุด ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) เผยแพร่เมื่อ 16 พฤษภาคม 2025 แอปไคลเอนต์และรีโพซิทอรีตัวช่วยมีกิจกรรมใหม่กว่า ดังนั้นนี่ไม่ใช่การอ้างว่าโปรเจ็กต์ถูกละทิ้ง การเลิกแนะนำนี้เกี่ยวกับการลดการพึ่งพาของ OpenClaw ต่อเซิร์ฟเวอร์ HTTP ภายนอก, webhooks และพื้นผิวความเข้ากันได้กับ private API เมื่อเส้นทาง `imsg` แบบเนทีฟทำให้การผสานรวมอยู่บนสัญญา stdio ภายในเครื่อง
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
รุ่น OpenClaw ปัจจุบันบันเดิล BlueBubbles มาให้ ดังนั้นบิลด์แบบแพ็กเกจปกติไม่ต้องมีขั้นตอน `openclaw plugins install` แยกต่างหาก
|
||||
</Note>
|
||||
|
||||
## ภาพรวม
|
||||
|
||||
- ทำงานบน macOS ผ่านแอปตัวช่วย BlueBubbles ([bluebubbles.app](https://bluebubbles.app))
|
||||
- ทางเลือกสำรองแบบเดิมสำหรับการติดตั้งที่พึ่งพา ID ช่องทาง BlueBubbles, สถานะ webhook, เป้าหมายกลุ่ม, การส่ง Cron หรือการกำหนดเส้นทางเวิร์กสเปซอยู่แล้ว
|
||||
- แนะนำ/ทดสอบแล้ว: macOS Sequoia (15) macOS Tahoe (26) ใช้งานได้ แต่ปัจจุบันการแก้ไขยังเสียบน Tahoe และการอัปเดตไอคอนกลุ่มอาจรายงานว่าสำเร็จแต่ไม่ซิงก์
|
||||
- OpenClaw สื่อสารกับมันผ่าน REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`)
|
||||
- ข้อความขาเข้ามาถึงผ่าน webhooks; การตอบกลับขาออก, ตัวบ่งชี้การพิมพ์, ใบตอบรับการอ่าน และ tapbacks เป็นการเรียก REST
|
||||
- ไฟล์แนบและสติกเกอร์จะถูกนำเข้าเป็นสื่อขาเข้า (และแสดงให้ agent เห็นเมื่อเป็นไปได้)
|
||||
- การตอบกลับ Auto-TTS ที่สังเคราะห์เสียง MP3 หรือ CAF จะถูกส่งเป็นบับเบิลบันทึกเสียงของ iMessage แทนไฟล์แนบธรรมดา
|
||||
- การจับคู่/allowlist ทำงานแบบเดียวกับช่องทางอื่น (`/channels/pairing` เป็นต้น) ด้วย `channels.bluebubbles.allowFrom` + โค้ดจับคู่
|
||||
- ปฏิกิริยาจะถูกแสดงเป็นเหตุการณ์ระบบเหมือน Slack/Telegram เพื่อให้ agents สามารถ "กล่าวถึง" ก่อนตอบกลับได้
|
||||
- ฟีเจอร์ขั้นสูง: แก้ไข, ยกเลิกการส่ง, เธรดการตอบกลับ, เอฟเฟกต์ข้อความ, การจัดการกลุ่ม
|
||||
|
||||
## เริ่มต้นอย่างรวดเร็ว
|
||||
|
||||
<Steps>
|
||||
<Step title="ติดตั้ง BlueBubbles">
|
||||
ติดตั้งเซิร์ฟเวอร์ BlueBubbles บน Mac ของคุณ (ทำตามคำแนะนำที่ [bluebubbles.app/install](https://bluebubbles.app/install))
|
||||
</Step>
|
||||
<Step title="เปิดใช้งาน web API">
|
||||
ในการตั้งค่า BlueBubbles ให้เปิดใช้งาน web API และตั้งรหัสผ่าน
|
||||
</Step>
|
||||
<Step title="กำหนดค่า OpenClaw">
|
||||
เรียกใช้ `openclaw onboard` แล้วเลือก BlueBubbles หรือกำหนดค่าด้วยตนเอง:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="ชี้ webhooks ไปที่ gateway">
|
||||
ชี้ webhooks ของ BlueBubbles ไปที่ gateway ของคุณ (ตัวอย่าง: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)
|
||||
</Step>
|
||||
<Step title="เริ่ม gateway">
|
||||
เริ่ม gateway; มันจะลงทะเบียนตัวจัดการ webhook และเริ่มการจับคู่
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**ความปลอดภัย**
|
||||
|
||||
- ตั้งรหัสผ่าน webhook เสมอ
|
||||
- ต้องมีการยืนยันตัวตนของ Webhook เสมอ OpenClaw จะปฏิเสธคำขอ webhook ของ BlueBubbles เว้นแต่คำขอนั้นมี password/guid ที่ตรงกับ `channels.bluebubbles.password` (เช่น `?password=<password>` หรือ `x-password`) ไม่ว่าโทโพโลยี loopback/proxy จะเป็นแบบใด
|
||||
- การยืนยันตัวตนด้วยรหัสผ่านจะถูกตรวจสอบก่อนอ่าน/แยกวิเคราะห์เนื้อหา webhook แบบเต็ม
|
||||
|
||||
</Warning>
|
||||
|
||||
## ทำให้ Messages.app ยังทำงานอยู่ (การตั้งค่า VM / แบบไม่มีหน้าจอ)
|
||||
|
||||
การตั้งค่า macOS VM / เปิดตลอดบางแบบอาจทำให้ Messages.app เข้าสถานะ "idle" (เหตุการณ์ขาเข้าหยุดจนกว่าแอปจะถูกเปิด/นำมาอยู่เบื้องหน้า) วิธีเลี่ยงแบบง่ายคือ **กระตุ้น Messages ทุก 5 นาที** ด้วย AppleScript + LaunchAgent
|
||||
|
||||
<Steps>
|
||||
<Step title="บันทึก AppleScript">
|
||||
บันทึกสิ่งนี้เป็น `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="ติดตั้ง LaunchAgent">
|
||||
บันทึกสิ่งนี้เป็น `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
สิ่งนี้จะทำงาน **ทุก 300 วินาที** และ **เมื่อเข้าสู่ระบบ** การเรียกใช้ครั้งแรกอาจเรียกพรอมป์ **Automation** ของ macOS (`osascript` → Messages) อนุมัติพรอมป์เหล่านั้นในเซสชันผู้ใช้เดียวกับที่เรียกใช้ LaunchAgent
|
||||
|
||||
</Step>
|
||||
<Step title="โหลด">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## การเริ่มต้นใช้งาน
|
||||
|
||||
BlueBubbles พร้อมใช้งานในการเริ่มต้นใช้งานแบบโต้ตอบ:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
วิซาร์ดจะขอข้อมูล:
|
||||
|
||||
<ParamField path="URL เซิร์ฟเวอร์" type="string" required>
|
||||
ที่อยู่เซิร์ฟเวอร์ BlueBubbles (เช่น `http://192.168.1.100:1234`)
|
||||
</ParamField>
|
||||
<ParamField path="รหัสผ่าน" type="string" required>
|
||||
รหัสผ่าน API จากการตั้งค่า BlueBubbles Server
|
||||
</ParamField>
|
||||
<ParamField path="พาธ Webhook" type="string" default="/bluebubbles-webhook">
|
||||
พาธเอนด์พอยต์ Webhook
|
||||
</ParamField>
|
||||
<ParamField path="นโยบาย DM" type="string">
|
||||
`pairing`, `allowlist`, `open` หรือ `disabled`
|
||||
</ParamField>
|
||||
<ParamField path="รายการอนุญาต" type="string[]">
|
||||
หมายเลขโทรศัพท์, อีเมล หรือเป้าหมายแชต
|
||||
</ParamField>
|
||||
|
||||
คุณยังสามารถเพิ่ม BlueBubbles ผ่าน CLI ได้:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## การควบคุมการเข้าถึง (DMs + กลุ่ม)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- ค่าเริ่มต้น: `channels.bluebubbles.dmPolicy = "pairing"`
|
||||
- ผู้ส่งที่ไม่รู้จักจะได้รับโค้ดจับคู่; ข้อความจะถูกละเว้นจนกว่าจะอนุมัติ (โค้ดหมดอายุหลัง 1 ชั่วโมง)
|
||||
- อนุมัติผ่าน:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- การจับคู่คือการแลกเปลี่ยนโทเคนเริ่มต้น รายละเอียด: [การจับคู่](/th/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="กลุ่ม">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (ค่าเริ่มต้น: `allowlist`)
|
||||
- `channels.bluebubbles.groupAllowFrom` ควบคุมว่าใครสามารถทริกเกอร์ในกลุ่มเมื่อกำหนด `allowlist`
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### การเติมเต็มชื่อผู้ติดต่อ (macOS, ไม่บังคับ)
|
||||
|
||||
webhooks กลุ่มของ BlueBubbles มักมีเพียงที่อยู่ผู้เข้าร่วมแบบดิบ หากคุณต้องการให้บริบท `GroupMembers` แสดงชื่อผู้ติดต่อภายในเครื่องแทน คุณสามารถเลือกใช้การเติมเต็มจาก Contacts ภายในเครื่องบน macOS ได้:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` เปิดใช้งานการค้นหา ค่าเริ่มต้น: `false`
|
||||
- การค้นหาจะทำงานหลังจากการเข้าถึงกลุ่ม, การอนุญาตคำสั่ง และการกั้นการกล่าวถึงอนุญาตให้ข้อความผ่านแล้วเท่านั้น
|
||||
- เฉพาะผู้เข้าร่วมที่เป็นหมายเลขโทรศัพท์และยังไม่มีชื่อเท่านั้นที่จะถูกเติมเต็ม
|
||||
- หมายเลขโทรศัพท์ดิบยังคงเป็นทางเลือกสำรองเมื่อไม่พบรายการที่ตรงกันภายในเครื่อง
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### การกั้นการกล่าวถึง (กลุ่ม)
|
||||
|
||||
BlueBubbles รองรับการกั้นการกล่าวถึงสำหรับแชตกลุ่ม โดยสอดคล้องกับพฤติกรรมของ iMessage/WhatsApp:
|
||||
|
||||
- ใช้ `agents.list[].groupChat.mentionPatterns` (หรือ `messages.groupChat.mentionPatterns`) เพื่อตรวจจับการกล่าวถึง
|
||||
- เมื่อเปิดใช้งาน `requireMention` สำหรับกลุ่ม agent จะตอบกลับเฉพาะเมื่อถูกกล่าวถึงเท่านั้น
|
||||
- คำสั่งควบคุมจากผู้ส่งที่ได้รับอนุญาตจะข้ามการกั้นการกล่าวถึง
|
||||
|
||||
การกำหนดค่าต่อกลุ่ม:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### การกั้นคำสั่ง
|
||||
|
||||
- คำสั่งควบคุม (เช่น `/config`, `/model`) ต้องได้รับอนุญาต
|
||||
- ใช้ `allowFrom` และ `groupAllowFrom` เพื่อกำหนดการอนุญาตคำสั่ง
|
||||
- ผู้ส่งที่ได้รับอนุญาตสามารถเรียกใช้คำสั่งควบคุมได้แม้ไม่ได้กล่าวถึงในกลุ่ม
|
||||
|
||||
### system prompt ต่อกลุ่ม
|
||||
|
||||
แต่ละรายการภายใต้ `channels.bluebubbles.groups.*` รับสตริง `systemPrompt` แบบไม่บังคับ ค่านี้จะถูกฉีดเข้าไปใน system prompt ของ agent ในทุกเทิร์นที่จัดการข้อความในกลุ่มนั้น เพื่อให้คุณตั้งบุคลิกหรือกฎพฤติกรรมต่อกลุ่มได้โดยไม่ต้องแก้ไขพรอมป์ของ agent:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
คีย์ตรงกับสิ่งที่ BlueBubbles รายงานเป็น `chatGuid` / `chatIdentifier` / `chatId` แบบตัวเลขสำหรับกลุ่ม และรายการ wildcard `"*"` ให้ค่าเริ่มต้นสำหรับทุกกลุ่มที่ไม่มีรายการตรงแบบเป๊ะ (รูปแบบเดียวกับที่ใช้โดย `requireMention` และนโยบายเครื่องมือต่อกลุ่ม) รายการที่ตรงแบบเป๊ะชนะ wildcard เสมอ DMs จะละเว้นฟิลด์นี้; ให้ใช้การปรับแต่งพรอมป์ระดับ agent หรือระดับบัญชีแทน
|
||||
|
||||
#### ตัวอย่างที่ใช้งานจริง: การตอบกลับแบบเธรดและปฏิกิริยา tapback (Private API)
|
||||
|
||||
เมื่อเปิดใช้งาน BlueBubbles Private API ข้อความขาเข้าจะมาพร้อม ID ข้อความแบบสั้น (เช่น `[[reply_to:5]]`) และ agent สามารถเรียก `action=reply` เพื่อเธรดเข้าไปยังข้อความเฉพาะ หรือ `action=react` เพื่อวาง tapback ได้ `systemPrompt` ต่อกลุ่มเป็นวิธีที่เชื่อถือได้ในการทำให้ agent เลือกเครื่องมือที่ถูกต้อง:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
ทั้งปฏิกิริยา tapback และการตอบกลับแบบเธรดต้องใช้ BlueBubbles Private API; ดู [การดำเนินการขั้นสูง](#advanced-actions) และ [ID ข้อความ](#message-ids-short-vs-full) สำหรับกลไกพื้นฐาน
|
||||
|
||||
## การผูกการสนทนา ACP
|
||||
|
||||
แชต BlueBubbles สามารถเปลี่ยนเป็นเวิร์กสเปซ ACP ที่คงทนได้โดยไม่ต้องเปลี่ยนเลเยอร์การขนส่ง
|
||||
|
||||
ขั้นตอนเร็วสำหรับผู้ปฏิบัติงาน:
|
||||
|
||||
- เรียกใช้ `/acp spawn codex --bind here` ภายใน DM หรือแชตกลุ่มที่ได้รับอนุญาต
|
||||
- ข้อความในอนาคตในบทสนทนา BlueBubbles เดียวกันนั้นจะถูกกำหนดเส้นทางไปยังเซสชัน ACP ที่สร้างขึ้น
|
||||
- `/new` และ `/reset` รีเซ็ตเซสชัน ACP ที่ผูกไว้เดิม ณ จุดเดิม
|
||||
- `/acp close` ปิดเซสชัน ACP และลบการผูก
|
||||
|
||||
ยังรองรับการผูกถาวรที่กำหนดค่าไว้ผ่านรายการ `bindings[]` ระดับบนสุดด้วย `type: "acp"` และ `match.channel: "bluebubbles"`
|
||||
|
||||
`match.peer.id` สามารถใช้รูปแบบเป้าหมาย BlueBubbles ที่รองรับใดก็ได้:
|
||||
|
||||
- แฮนด์เดิล DM ที่ปรับให้เป็นมาตรฐานแล้ว เช่น `+15555550123` หรือ `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
สำหรับการผูกกลุ่มที่เสถียร ให้เลือกใช้ `chat_id:*` หรือ `chat_identifier:*`
|
||||
|
||||
ตัวอย่าง:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
ดู [เอเจนต์ ACP](/th/tools/acp-agents) สำหรับพฤติกรรมการผูก ACP ที่ใช้ร่วมกัน
|
||||
|
||||
## การกำลังพิมพ์ + ใบตอบรับการอ่าน
|
||||
|
||||
- **ตัวบ่งชี้การกำลังพิมพ์**: ส่งโดยอัตโนมัติก่อนและระหว่างการสร้างคำตอบ
|
||||
- **ใบตอบรับการอ่าน**: ควบคุมโดย `channels.bluebubbles.sendReadReceipts` (ค่าเริ่มต้น: `true`)
|
||||
- **ตัวบ่งชี้การกำลังพิมพ์**: OpenClaw ส่งเหตุการณ์เริ่มพิมพ์ BlueBubbles จะล้างสถานะกำลังพิมพ์โดยอัตโนมัติเมื่อส่งหรือหมดเวลา (การหยุดด้วยตนเองผ่าน DELETE ไม่น่าเชื่อถือ)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## การทำงานขั้นสูง
|
||||
|
||||
BlueBubbles รองรับการทำงานกับข้อความขั้นสูงเมื่อเปิดใช้ใน config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="การทำงานที่มีให้ใช้">
|
||||
- **react**: เพิ่ม/ลบรีแอ็กชัน tapback (`messageId`, `emoji`, `remove`) ชุด tapback ดั้งเดิมของ iMessage คือ `love`, `like`, `dislike`, `laugh`, `emphasize` และ `question` เมื่อเอเจนต์เลือกอีโมจินอกชุดนั้น (เช่น `👀`) เครื่องมือรีแอ็กชันจะถอยกลับไปใช้ `love` เพื่อให้ tapback ยังคงแสดงผลแทนที่จะทำให้คำขอทั้งหมดล้มเหลว รีแอ็กชัน ack ที่กำหนดค่าไว้ยังคงตรวจสอบอย่างเข้มงวดและจะแจ้งข้อผิดพลาดเมื่อพบค่าที่ไม่รู้จัก
|
||||
- **edit**: แก้ไขข้อความที่ส่งแล้ว (`messageId`, `text`)
|
||||
- **unsend**: ยกเลิกการส่งข้อความ (`messageId`)
|
||||
- **reply**: ตอบกลับข้อความที่ระบุ (`messageId`, `text`, `to`)
|
||||
- **sendWithEffect**: ส่งพร้อมเอฟเฟกต์ iMessage (`text`, `to`, `effectId`)
|
||||
- **renameGroup**: เปลี่ยนชื่อแชตกลุ่ม (`chatGuid`, `displayName`)
|
||||
- **setGroupIcon**: ตั้งค่าไอคอน/รูปภาพของแชตกลุ่ม (`chatGuid`, `media`) - ไม่เสถียรบน macOS 26 Tahoe (API อาจส่งผลว่าสำเร็จ แต่ไอคอนไม่ซิงค์)
|
||||
- **addParticipant**: เพิ่มบุคคลในกลุ่ม (`chatGuid`, `address`)
|
||||
- **removeParticipant**: นำบุคคลออกจากกลุ่ม (`chatGuid`, `address`)
|
||||
- **leaveGroup**: ออกจากแชตกลุ่ม (`chatGuid`)
|
||||
- **upload-file**: ส่งสื่อ/ไฟล์ (`to`, `buffer`, `filename`, `asVoice`)
|
||||
- บันทึกเสียง: ตั้งค่า `asVoice: true` พร้อมเสียง **MP3** หรือ **CAF** เพื่อส่งเป็นข้อความเสียง iMessage BlueBubbles จะแปลง MP3 → CAF เมื่อส่งบันทึกเสียง
|
||||
- ชื่อแทนแบบเดิม: `sendAttachment` ยังใช้งานได้ แต่ `upload-file` คือชื่อการทำงานมาตรฐาน
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID ข้อความ (แบบสั้นกับแบบเต็ม)
|
||||
|
||||
OpenClaw อาจแสดง ID ข้อความแบบ _สั้น_ (เช่น `1`, `2`) เพื่อประหยัดโทเค็น
|
||||
|
||||
- `MessageSid` / `ReplyToId` อาจเป็น ID แบบสั้น
|
||||
- `MessageSidFull` / `ReplyToIdFull` มี ID เต็มของผู้ให้บริการ
|
||||
- ID แบบสั้นอยู่ในหน่วยความจำ และอาจหมดอายุเมื่อรีสตาร์ทหรือเมื่อแคชถูกขับออก
|
||||
- การทำงานต่าง ๆ รับ `messageId` แบบสั้นหรือแบบเต็ม แต่ ID แบบสั้นจะแจ้งข้อผิดพลาดหากไม่มีให้ใช้แล้ว
|
||||
|
||||
ใช้ ID แบบเต็มสำหรับการทำงานอัตโนมัติและพื้นที่เก็บข้อมูลที่ต้องคงทน:
|
||||
|
||||
- เทมเพลต: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- บริบท: `MessageSidFull` / `ReplyToIdFull` ในเพย์โหลดขาเข้า
|
||||
|
||||
ดู [การกำหนดค่า](/th/gateway/configuration) สำหรับตัวแปรเทมเพลต
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## การรวม DM ที่ถูกแยกส่ง (คำสั่ง + URL ในการเขียนครั้งเดียว)
|
||||
|
||||
เมื่อผู้ใช้พิมพ์คำสั่งและ URL พร้อมกันใน iMessage - เช่น `Dump https://example.com/article` - Apple จะแยกการส่งออกเป็น **การส่งมอบ Webhook สองรายการแยกกัน**:
|
||||
|
||||
1. ข้อความตัวอักษร (`"Dump"`)
|
||||
2. บอลลูนพรีวิว URL (`"https://..."`) พร้อมรูปภาพ OG-preview เป็นไฟล์แนบ
|
||||
|
||||
Webhook ทั้งสองมาถึง OpenClaw ห่างกันประมาณ 0.8-2.0 วินาทีในสภาพแวดล้อมส่วนใหญ่ หากไม่มีการรวม เอเจนต์จะได้รับเฉพาะคำสั่งในรอบที่ 1 ตอบกลับ (มักเป็น "ส่ง URL มาให้ฉัน") และเพิ่งเห็น URL ในรอบที่ 2 ซึ่ง ณ ตอนนั้นบริบทของคำสั่งก็หายไปแล้ว
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` เลือกให้ DM รวม Webhook ที่ติดต่อกันจากผู้ส่งเดียวกันเป็นรอบเอเจนต์เดียว แชตกลุ่มยังคงจัดคีย์แยกตามข้อความเพื่อรักษาโครงสร้างรอบของผู้ใช้หลายคนไว้
|
||||
|
||||
<Tabs>
|
||||
<Tab title="ควรเปิดใช้เมื่อใด">
|
||||
เปิดใช้เมื่อ:
|
||||
|
||||
- คุณส่ง Skills ที่คาดหวัง `command + payload` ในข้อความเดียว (dump, paste, save, queue เป็นต้น)
|
||||
- ผู้ใช้ของคุณวาง URL, รูปภาพ หรือเนื้อหายาวพร้อมกับคำสั่ง
|
||||
- คุณยอมรับเวลาแฝงของรอบ DM ที่เพิ่มขึ้นได้ (ดูด้านล่าง)
|
||||
|
||||
ปล่อยให้ปิดใช้เมื่อ:
|
||||
|
||||
- คุณต้องการเวลาแฝงขั้นต่ำสำหรับทริกเกอร์ DM แบบคำเดียว
|
||||
- โฟลว์ทั้งหมดของคุณเป็นคำสั่งครั้งเดียวจบโดยไม่มีเพย์โหลดตามมา
|
||||
|
||||
</Tab>
|
||||
<Tab title="การเปิดใช้">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
เมื่อเปิดแฟล็กและไม่มี `messages.inbound.byChannel.bluebubbles` ที่ระบุชัดเจน หน้าต่าง debounce จะขยายเป็น **2500 ms** (ค่าเริ่มต้นสำหรับการไม่รวมคือ 500 ms) จำเป็นต้องใช้หน้าต่างที่กว้างขึ้น เพราะจังหวะ split-send ของ Apple ที่ 0.8-2.0 วินาทีไม่พอดีกับค่าเริ่มต้นที่แคบกว่า
|
||||
|
||||
หากต้องการปรับหน้าต่างเอง:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="ข้อแลกเปลี่ยน">
|
||||
- **เวลาแฝงที่เพิ่มขึ้นสำหรับคำสั่งควบคุม DM** เมื่อเปิดแฟล็ก ข้อความคำสั่งควบคุม DM (เช่น `Dump`, `Save` เป็นต้น) จะรอสูงสุดเท่ากับหน้าต่าง debounce ก่อนส่งต่อ เผื่อมี Webhook เพย์โหลดตามมา คำสั่งในแชตกลุ่มยังคงส่งต่อทันที
|
||||
- **ผลลัพธ์ที่รวมแล้วมีขอบเขต** - ข้อความที่รวมแล้วจำกัดที่ 4000 อักขระพร้อมมาร์กเกอร์ `…[truncated]` ที่ชัดเจน ไฟล์แนบจำกัดที่ 20 รายการ รายการแหล่งที่มาจำกัดที่ 10 รายการ (คงรายการแรกบวกรายการล่าสุดไว้เมื่อเกินกว่านั้น) `messageId` ของทุกแหล่งที่มายังคงไปถึงการขจัดข้อมูลซ้ำขาเข้า ดังนั้นการเล่นซ้ำ MessagePoller ภายหลังของเหตุการณ์รายรายการใด ๆ จะถูกจดจำว่าเป็นรายการซ้ำ
|
||||
- **เลือกใช้ได้ตามแต่ละช่องทาง** ช่องทางอื่น (Telegram, WhatsApp, Slack, …) ไม่ได้รับผลกระทบ
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### สถานการณ์และสิ่งที่เอเจนต์เห็น
|
||||
|
||||
| ผู้ใช้เขียน | Apple ส่งมอบ | ปิดแฟล็ก (ค่าเริ่มต้น) | เปิดแฟล็ก + หน้าต่าง 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | ---------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (ส่งครั้งเดียว) | 2 Webhook ห่างกัน ~1 วินาที | เอเจนต์สองรอบ: มีแค่ "Dump" แล้วตามด้วย URL | หนึ่งรอบ: ข้อความที่รวมแล้ว `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (ไฟล์แนบ + ข้อความ) | 2 Webhook | สองรอบ | หนึ่งรอบ: ข้อความ + รูปภาพ |
|
||||
| `/status` (คำสั่งเดี่ยว) | 1 Webhook | ส่งต่อทันที | **รอสูงสุดเท่าหน้าต่าง แล้วจึงส่งต่อ** |
|
||||
| วาง URL อย่างเดียว | 1 Webhook | ส่งต่อทันที | ส่งต่อทันที (มีเพียงรายการเดียวใน bucket) |
|
||||
| ข้อความ + URL ที่ตั้งใจส่งเป็นข้อความแยกกันสองรายการ ห่างกันหลายนาที | 2 Webhook นอกหน้าต่าง | สองรอบ | สองรอบ (หน้าต่างหมดอายุระหว่างกัน) |
|
||||
| ส่ง DM สั้น ๆ จำนวนมากอย่างรวดเร็ว (>10 รายการภายในหน้าต่าง) | N Webhook | N รอบ | หนึ่งรอบ ผลลัพธ์มีขอบเขต (แรก + ล่าสุด ใช้ขีดจำกัดข้อความ/ไฟล์แนบแล้ว) |
|
||||
|
||||
### การแก้ปัญหาการรวม split-send
|
||||
|
||||
หากเปิดแฟล็กแล้ว แต่ split-send ยังมาถึงเป็นสองรอบ ให้ตรวจสอบแต่ละชั้น:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="โหลด config จริงแล้ว">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
จากนั้น `openclaw gateway restart` - แฟล็กถูกอ่านตอนสร้าง debouncer-registry
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="หน้าต่าง debounce กว้างพอสำหรับสภาพแวดล้อมของคุณ">
|
||||
ดู log ของเซิร์ฟเวอร์ BlueBubbles ใต้ `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
วัดช่วงห่างระหว่างการส่งต่อข้อความแบบ `"Dump"` กับการส่งต่อ `"https://..."; Attachments:` ที่ตามมา เพิ่ม `messages.inbound.byChannel.bluebubbles` ให้ครอบคลุมช่วงห่างนั้นอย่างสบาย
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="ไทม์สแตมป์ JSONL ของเซสชัน ≠ การมาถึงของ Webhook">
|
||||
ไทม์สแตมป์เหตุการณ์ของเซสชัน (`~/.openclaw/agents/<id>/sessions/*.jsonl`) สะท้อนเวลาที่ Gateway ส่งข้อความให้เอเจนต์ **ไม่ใช่** เวลาที่ Webhook มาถึง ข้อความที่สองในคิวซึ่งติดแท็ก `[Queued messages while agent was busy]` หมายความว่ารอบแรกยังทำงานอยู่เมื่อ Webhook ที่สองมาถึง - bucket การรวมถูก flush ไปแล้ว ปรับหน้าต่างเทียบกับ log เซิร์ฟเวอร์ BB ไม่ใช่ log เซสชัน
|
||||
</Accordion>
|
||||
<Accordion title="แรงกดดันหน่วยความจำทำให้การส่งคำตอบช้าลง">
|
||||
บนเครื่องขนาดเล็กกว่า (8 GB) รอบเอเจนต์อาจใช้เวลานานพอที่ bucket การรวมจะ flush ก่อนที่การตอบกลับเสร็จ และ URL จะเข้ามาเป็นรอบที่สองในคิว ตรวจสอบ `memory_pressure` และ `ps -o rss -p $(pgrep openclaw-gateway)`; หาก Gateway ใช้ RSS เกินประมาณ 500 MB และ compressor ทำงานอยู่ ให้ปิดกระบวนการหนักอื่น ๆ หรือย้ายไปโฮสต์ที่ใหญ่ขึ้น
|
||||
</Accordion>
|
||||
<Accordion title="การส่งแบบอ้างอิงตอบกลับเป็นเส้นทางคนละแบบ">
|
||||
หากผู้ใช้แตะ `Dump` เป็น **การตอบกลับ** บอลลูน URL ที่มีอยู่ (iMessage แสดงป้าย "1 Reply" บนบับเบิล Dump) URL จะอยู่ใน `replyToBody` ไม่ใช่ใน Webhook ที่สอง การรวมไม่เกี่ยวข้อง - นั่นเป็นเรื่องของ skill/prompt ไม่ใช่เรื่องของ debouncer
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## การสตรีมแบบบล็อก
|
||||
|
||||
ควบคุมว่าจะส่งคำตอบเป็นข้อความเดียวหรือสตรีมเป็นบล็อก:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## สื่อ + ขีดจำกัด
|
||||
|
||||
- ไฟล์แนบขาเข้าจะถูกดาวน์โหลดและเก็บไว้ในแคชสื่อ
|
||||
- ขีดจำกัดสื่อผ่าน `channels.bluebubbles.mediaMaxMb` สำหรับสื่อขาเข้าและขาออก (ค่าเริ่มต้น: 8 MB)
|
||||
- ข้อความขาออกถูกแบ่งเป็นชิ้นตาม `channels.bluebubbles.textChunkLimit` (ค่าเริ่มต้น: 4000 อักขระ)
|
||||
|
||||
## ข้อมูลอ้างอิงการกำหนดค่า
|
||||
|
||||
การกำหนดค่าแบบเต็ม: [การกำหนดค่า](/th/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="การเชื่อมต่อและ Webhook">
|
||||
- `channels.bluebubbles.enabled`: เปิด/ปิดแชนเนล
|
||||
- `channels.bluebubbles.serverUrl`: URL ฐานของ REST API สำหรับ BlueBubbles
|
||||
- `channels.bluebubbles.password`: รหัสผ่าน API
|
||||
- `channels.bluebubbles.webhookPath`: พาธ endpoint ของ Webhook (ค่าเริ่มต้น: `/bluebubbles-webhook`)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="นโยบายการเข้าถึง">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (ค่าเริ่มต้น: `pairing`)
|
||||
- `channels.bluebubbles.allowFrom`: รายการที่อนุญาตสำหรับ DM (handles, อีเมล, หมายเลข E.164, `chat_id:*`, `chat_guid:*`)
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (ค่าเริ่มต้น: `allowlist`)
|
||||
- `channels.bluebubbles.groupAllowFrom`: รายการที่อนุญาตสำหรับผู้ส่งในกลุ่ม
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: บน macOS เลือกเติมข้อมูลผู้เข้าร่วมกลุ่มที่ไม่มีชื่อจาก Contacts ภายในเครื่องหลังผ่านการคัดกรองแล้ว ค่าเริ่มต้น: `false`
|
||||
- `channels.bluebubbles.groups`: การกำหนดค่าต่อกลุ่ม (`requireMention` ฯลฯ)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การจัดส่งและการแบ่งข้อความ">
|
||||
- `channels.bluebubbles.sendReadReceipts`: ส่งใบตอบรับว่าอ่านแล้ว (ค่าเริ่มต้น: `true`)
|
||||
- `channels.bluebubbles.blockStreaming`: เปิดใช้ block streaming (ค่าเริ่มต้น: `false`; จำเป็นสำหรับการตอบกลับแบบสตรีม)
|
||||
- `channels.bluebubbles.textChunkLimit`: ขนาดส่วนข้อความขาออกเป็นอักขระ (ค่าเริ่มต้น: 4000)
|
||||
- `channels.bluebubbles.sendTimeoutMs`: ระยะหมดเวลาต่อคำขอเป็น ms สำหรับการส่งข้อความขาออกผ่าน `/api/v1/message/text` (ค่าเริ่มต้น: 30000) เพิ่มค่านี้บนชุดติดตั้ง macOS 26 ที่การส่งผ่าน Private API ของ iMessage อาจค้างได้นานกว่า 60 วินาทีภายในเฟรมเวิร์ก iMessage; เช่น `45000` หรือ `60000` ปัจจุบัน probes, การค้นหาแชท, reactions, edits และ health checks ยังคงใช้ค่าเริ่มต้นที่สั้นกว่า 10 วินาที; มีแผนขยายการครอบคลุมไปยัง reactions และ edits เป็นงานถัดไป การแทนที่ค่าต่อบัญชี: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`
|
||||
- `channels.bluebubbles.chunkMode`: `length` (ค่าเริ่มต้น) จะแบ่งเฉพาะเมื่อเกิน `textChunkLimit`; `newline` จะแบ่งตามบรรทัดว่าง (ขอบเขตย่อหน้า) ก่อนแบ่งตามความยาว
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="สื่อและประวัติ">
|
||||
- `channels.bluebubbles.mediaMaxMb`: ขีดจำกัดสื่อขาเข้า/ขาออกเป็น MB (ค่าเริ่มต้น: 8)
|
||||
- `channels.bluebubbles.mediaLocalRoots`: รายการที่อนุญาตอย่างชัดเจนของไดเรกทอรีภายในเครื่องแบบ absolute ที่อนุญาตให้ใช้กับพาธสื่อภายในเครื่องขาออก การส่งพาธภายในเครื่องจะถูกปฏิเสธโดยค่าเริ่มต้น เว้นแต่จะกำหนดค่านี้ไว้ การแทนที่ค่าต่อบัญชี: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: รวม Webhook ของ DM จากผู้ส่งเดียวกันที่มาต่อเนื่องกันให้เป็นหนึ่งรอบของ agent เพื่อให้การส่งแยกข้อความ+URL ของ Apple มาถึงเป็นข้อความเดียว (ค่าเริ่มต้น: `false`) ดู [การรวม DM ที่ถูกส่งแยก](#coalescing-split-send-dms-command--url-in-one-composition) สำหรับสถานการณ์ การปรับหน้าต่างเวลา และข้อแลกเปลี่ยน เมื่อเปิดใช้โดยไม่มี `messages.inbound.byChannel.bluebubbles` ที่ระบุไว้ชัดเจน จะขยายหน้าต่าง debounce ขาเข้าเริ่มต้นจาก 500 ms เป็น 2500 ms
|
||||
- `channels.bluebubbles.historyLimit`: จำนวนข้อความกลุ่มสูงสุดสำหรับบริบท (0 หมายถึงปิดใช้)
|
||||
- `channels.bluebubbles.dmHistoryLimit`: ขีดจำกัดประวัติ DM
|
||||
- `channels.bluebubbles.replyContextApiFallback`: เมื่อ reply ขาเข้ามาถึงโดยไม่มี `replyToBody`/`replyToSender` และแคช reply-context ในหน่วยความจำไม่พบรายการ ให้ดึงข้อความต้นฉบับจาก BlueBubbles HTTP API เป็น fallback แบบ best-effort (ค่าเริ่มต้น: `false`) มีประโยชน์สำหรับการติดตั้งหลายอินสแตนซ์ที่ใช้บัญชี BlueBubbles เดียวกันร่วมกัน หลังรีสตาร์ทโปรเซส หรือหลังการไล่ออกจากแคช TTL/LRU ที่มีอายุยาวนาน การดึงข้อมูลมีการป้องกัน SSRF ด้วยนโยบายเดียวกับคำขอไคลเอนต์ BlueBubbles อื่นทั้งหมด ไม่ throw และเติมแคชเพื่อให้ reply ถัดไปใช้ต้นทุนร่วมกันได้ การแทนที่ค่าต่อบัญชี: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback` การตั้งค่าระดับแชนเนลจะส่งต่อไปยังบัญชีที่ละเว้น flag นี้
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="การกระทำและบัญชี">
|
||||
- `channels.bluebubbles.actions`: เปิด/ปิดการกระทำเฉพาะรายการ
|
||||
- `channels.bluebubbles.accounts`: การกำหนดค่าหลายบัญชี
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
ตัวเลือกระดับ global ที่เกี่ยวข้อง:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (หรือ `messages.groupChat.mentionPatterns`)
|
||||
- `messages.responsePrefix`
|
||||
|
||||
## การระบุที่อยู่ / เป้าหมายการจัดส่ง
|
||||
|
||||
ควรใช้ `chat_guid` เพื่อการกำหนดเส้นทางที่เสถียร:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (แนะนำสำหรับกลุ่ม)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- handles โดยตรง: `+15555550123`, `user@example.com`
|
||||
- หาก handle โดยตรงไม่มีแชท DM ที่มีอยู่ OpenClaw จะสร้างให้ผ่าน `POST /api/v1/chat/new` ซึ่งต้องเปิดใช้ BlueBubbles Private API
|
||||
|
||||
### การกำหนดเส้นทาง iMessage เทียบกับ SMS
|
||||
|
||||
เมื่อ handle เดียวกันมีทั้งแชท iMessage และ SMS บน Mac (เช่น หมายเลขโทรศัพท์ที่ลงทะเบียน iMessage แล้ว แต่เคยได้รับ fallback แบบ green-bubble ด้วย) OpenClaw จะเลือกแชท iMessage และจะไม่ลดระดับเป็น SMS แบบเงียบ ๆ หากต้องการบังคับใช้แชท SMS ให้ใช้ prefix เป้าหมาย `sms:` อย่างชัดเจน (เช่น `sms:+15555550123`) Handles ที่ไม่มีแชท iMessage ตรงกันจะยังส่งผ่านแชทใดก็ตามที่ BlueBubbles รายงาน
|
||||
|
||||
## ความปลอดภัย
|
||||
|
||||
- คำขอ Webhook จะได้รับการยืนยันตัวตนโดยเปรียบเทียบ query params หรือ headers ของ `guid`/`password` กับ `channels.bluebubbles.password`
|
||||
- เก็บรหัสผ่าน API และ endpoint ของ Webhook เป็นความลับ (ปฏิบัติกับสิ่งเหล่านี้เหมือน credentials)
|
||||
- ไม่มีการข้ามการยืนยันตัวตน Webhook ของ BlueBubbles สำหรับ localhost หากคุณ proxy ทราฟฟิก Webhook ให้คงรหัสผ่าน BlueBubbles ไว้ในคำขอแบบ end-to-end `gateway.trustedProxies` ไม่ได้แทนที่ `channels.bluebubbles.password` ที่นี่ ดู [ความปลอดภัยของ Gateway](/th/gateway/security#reverse-proxy-configuration)
|
||||
- เปิดใช้ HTTPS + กฎ firewall บนเซิร์ฟเวอร์ BlueBubbles หากเปิดเผยออกนอก LAN ของคุณ
|
||||
|
||||
## การแก้ปัญหา
|
||||
|
||||
- หากเหตุการณ์ typing/read หยุดทำงาน ให้ตรวจสอบบันทึก Webhook ของ BlueBubbles และยืนยันว่าพาธ Gateway ตรงกับ `channels.bluebubbles.webhookPath`
|
||||
- โค้ด pairing หมดอายุหลังหนึ่งชั่วโมง; ใช้ `openclaw pairing list bluebubbles` และ `openclaw pairing approve bluebubbles <code>`
|
||||
- Reactions ต้องใช้ private API ของ BlueBubbles (`POST /api/v1/message/react`); ตรวจสอบให้แน่ใจว่าเวอร์ชันเซิร์ฟเวอร์เปิดเผย API นี้
|
||||
- Edit/unsend ต้องใช้ macOS 13+ และเวอร์ชันเซิร์ฟเวอร์ BlueBubbles ที่เข้ากันได้ บน macOS 26 (Tahoe) ขณะนี้ edit ใช้งานไม่ได้เนื่องจากการเปลี่ยนแปลง private API
|
||||
- การอัปเดตไอคอนกลุ่มอาจไม่เสถียรบน macOS 26 (Tahoe): API อาจส่งคืนว่าสำเร็จ แต่ไอคอนใหม่ไม่ sync
|
||||
- OpenClaw จะซ่อนการกระทำที่ทราบว่าเสียโดยอัตโนมัติตามเวอร์ชัน macOS ของเซิร์ฟเวอร์ BlueBubbles หาก edit ยังคงปรากฏบน macOS 26 (Tahoe) ให้ปิดด้วยตนเองโดยใช้ `channels.bluebubbles.actions.edit=false`
|
||||
- เปิดใช้ `coalesceSameSenderDms` แล้ว แต่ split-sends (เช่น `Dump` + URL) ยังมาถึงเป็นสองรอบ: ดู checklist [การแก้ปัญหาการรวม split-send](#split-send-coalescing-troubleshooting) - สาเหตุทั่วไปคือหน้าต่าง debounce แคบเกินไป, อ่าน timestamp ของ session-log ผิดเป็นเวลาที่ Webhook มาถึง, หรือการส่งแบบ reply-quote (ซึ่งใช้ `replyToBody` ไม่ใช่ Webhook ที่สอง)
|
||||
- สำหรับข้อมูลสถานะ/สุขภาพ: `openclaw status --all` หรือ `openclaw status --deep`
|
||||
|
||||
สำหรับอ้างอิง workflow ของแชนเนลทั่วไป โปรดดู [แชนเนล](/th/channels) และคู่มือ [Plugins](/th/tools/plugin)
|
||||
|
||||
## ที่เกี่ยวข้อง
|
||||
|
||||
- [การกำหนดเส้นทางแชนเนล](/th/channels/channel-routing) - การกำหนดเส้นทาง session สำหรับข้อความ
|
||||
- [ภาพรวมแชนเนล](/th/channels) - แชนเนลที่รองรับทั้งหมด
|
||||
- [กลุ่ม](/th/channels/groups) - พฤติกรรมแชทกลุ่มและการคัดกรองด้วย mention
|
||||
- [Pairing](/th/channels/pairing) - การยืนยันตัวตน DM และ flow การ pairing
|
||||
- [ความปลอดภัย](/th/gateway/security) - โมเดลการเข้าถึงและการเสริมความแข็งแกร่ง
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- คุณกำลังติดตั้ง กำหนดค่า หรือตรวจสอบ Plugin bluebubbles
|
||||
summary: เพิ่มอินเทอร์เฟซช่องทาง BlueBubbles สำหรับการส่งและรับข้อความ OpenClaw.
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T10:15:28Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles Plugin
|
||||
|
||||
เพิ่มพื้นผิวช่องทาง BlueBubbles สำหรับส่งและรับข้อความ OpenClaw
|
||||
|
||||
## การเผยแพร่
|
||||
|
||||
- แพ็กเกจ: `@openclaw/bluebubbles`
|
||||
- ช่องทางการติดตั้ง: npm; ClawHub
|
||||
|
||||
## พื้นผิว
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## เอกสารที่เกี่ยวข้อง
|
||||
|
||||
- [bluebubbles](/th/channels/bluebubbles)
|
||||
@ -336,7 +336,6 @@ top-level `bindings[]` entries.
|
||||
|
||||
- **Discord channel/thread:** `match.channel="discord"` + `match.peer.id="<channelOrThreadId>"`
|
||||
- **Telegram forum topic:** `match.channel="telegram"` + `match.peer.id="<chatId>:topic:<topicId>"`
|
||||
- **BlueBubbles DM/group:** `match.channel="bluebubbles"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`. Prefer `chat_id:*` or `chat_identifier:*` for stable group bindings.
|
||||
- **iMessage DM/group:** `match.channel="imessage"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`. Prefer `chat_id:*` for stable group bindings.
|
||||
|
||||
</ParamField>
|
||||
|
||||
@ -235,7 +235,6 @@ current OpenClaw or a local checkout until a newer npm package is published.
|
||||
|
||||
| Plugin | Package | Docs |
|
||||
| --------------- | -------------------------- | ------------------------------------------ |
|
||||
| BlueBubbles | `@openclaw/bluebubbles` | [BlueBubbles](/channels/bluebubbles) |
|
||||
| Discord | `@openclaw/discord` | [Discord](/channels/discord) |
|
||||
| Feishu | `@openclaw/feishu` | [Feishu](/channels/feishu) |
|
||||
| Matrix | `@openclaw/matrix` | [Matrix](/channels/matrix) |
|
||||
|
||||
@ -709,8 +709,6 @@ delivery.
|
||||
`audio/ogg; codecs=opus`. If conversion fails, Feishu receives the original
|
||||
file as an attachment; WhatsApp send fails rather than posting an incompatible
|
||||
PTT payload.
|
||||
- **BlueBubbles**: keeps provider synthesis on the normal audio-file path; MP3
|
||||
and CAF outputs are marked for iMessage voice memo delivery.
|
||||
- **Other channels**: MP3 (`mp3_44100_128` from ElevenLabs, `mp3` from OpenAI).
|
||||
- 44.1kHz / 128kbps is the default balance for speech clarity.
|
||||
- **MiniMax**: MP3 (`speech-2.8-hd` model, 32kHz sample rate) for normal audio attachments. For channel-advertised voice-note targets, OpenClaw transcodes the MiniMax MP3 to 48kHz Opus with `ffmpeg` before delivery when the channel advertises transcoding.
|
||||
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles kanalını ayarlama
|
||||
- Webhook eşleştirme sorunlarını giderme
|
||||
- macOS'ta iMessage'ı yapılandırma
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: BlueBubbles macOS sunucusu üzerinden eski iMessage desteği (REST gönderme/alma, yazıyor göstergesi, tepkiler, eşleştirme, gelişmiş eylemler).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:51:02Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Durum: HTTP üzerinden BlueBubbles macOS sunucusuyla konuşan paketli eski Plugin. Mevcut BlueBubbles kurulumları çalışmaya devam eder, ancak yeni OpenClaw iMessage dağıtımları, gereksinimleri ana makinenize uyduğunda yerel [iMessage](/tr/channels/imessage) Plugin'ini tercih etmelidir.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles, yeni OpenClaw kurulumları için kullanımdan kaldırılmıştır.
|
||||
|
||||
Yukarı akış BlueBubbles ekosistemi hâlâ aktiftir, ancak OpenClaw, BlueBubbles macOS sunucu API'sine bağlıdır. 6 Mayıs 2026 itibarıyla, resmi [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) geliştirme dalı en son [22 Ocak 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037) tarihinde değişti ve en son sunucu sürümü ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) 16 Mayıs 2025'te yayımlandı. İstemci uygulaması ve yardımcı depolarda daha yeni etkinlik vardır; bu nedenle bu bir terk edilme iddiası değildir. Kullanımdan kaldırma, yerel `imsg` yolu entegrasyonu yerel bir stdio sözleşmesinde tuttuğunda OpenClaw'ın harici bir HTTP sunucusuna, webhooks'a ve özel API uyumluluk yüzeyine bağımlılığını azaltmakla ilgilidir.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Geçerli OpenClaw sürümleri BlueBubbles'ı paketler, bu yüzden normal paketli derlemeler ayrı bir `openclaw plugins install` adımı gerektirmez.
|
||||
</Note>
|
||||
|
||||
## Genel bakış
|
||||
|
||||
- BlueBubbles yardımcı uygulaması ([bluebubbles.app](https://bluebubbles.app)) üzerinden macOS'ta çalışır.
|
||||
- Zaten BlueBubbles kanal kimliklerine, webhook durumuna, grup hedeflerine, cron teslimine veya çalışma alanı yönlendirmesine dayanan kurulumlar için eski yedek.
|
||||
- Önerilen/test edilen: macOS Sequoia (15). macOS Tahoe (26) çalışır; düzenleme şu anda Tahoe'da bozuk ve grup simgesi güncellemeleri başarılı görünebilir ancak eşitlenmeyebilir.
|
||||
- OpenClaw onunla REST API'si üzerinden konuşur (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Gelen mesajlar webhooks üzerinden gelir; giden yanıtlar, yazıyor göstergeleri, okundu bilgileri ve tapback'ler REST çağrılarıdır.
|
||||
- Ekler ve çıkartmalar gelen medya olarak alınır (ve mümkün olduğunda ajana gösterilir).
|
||||
- MP3 veya CAF ses sentezleyen otomatik TTS yanıtları, düz dosya ekleri yerine iMessage sesli not baloncukları olarak teslim edilir.
|
||||
- Eşleştirme/izin listesi diğer kanallarla aynı şekilde çalışır (`/channels/pairing` vb.) ve `channels.bluebubbles.allowFrom` + eşleştirme kodlarını kullanır.
|
||||
- Tepkiler Slack/Telegram'da olduğu gibi sistem olayları olarak gösterilir, böylece ajanlar yanıtlamadan önce bunlardan "bahsedebilir".
|
||||
- Gelişmiş özellikler: düzenleme, göndermeyi geri alma, yanıt iş parçacıkları, mesaj efektleri, grup yönetimi.
|
||||
|
||||
## Hızlı başlangıç
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
BlueBubbles sunucusunu Mac'inize kurun ([bluebubbles.app/install](https://bluebubbles.app/install) adresindeki yönergeleri izleyin).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
BlueBubbles yapılandırmasında web API'sini etkinleştirin ve bir parola belirleyin.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
`openclaw onboard` komutunu çalıştırıp BlueBubbles'ı seçin veya elle yapılandırın:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
BlueBubbles webhooks'unu gateway'inize yönlendirin (örnek: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Gateway'i başlatın; webhook işleyicisini kaydeder ve eşleştirmeyi başlatır.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Güvenlik**
|
||||
|
||||
- Her zaman bir webhook parolası belirleyin.
|
||||
- Webhook kimlik doğrulaması her zaman gereklidir. OpenClaw, local loopback/proxy topolojisinden bağımsız olarak, `channels.bluebubbles.password` ile eşleşen bir password/guid içermedikçe BlueBubbles webhook isteklerini reddeder (örneğin `?password=<password>` veya `x-password`).
|
||||
- Parola kimlik doğrulaması, tam webhook gövdeleri okunmadan/ayrıştırılmadan önce denetlenir.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Messages.app'i canlı tutma (VM / başsız kurulumlar)
|
||||
|
||||
Bazı macOS VM / her zaman açık kurulumlarda Messages.app "boşta" kalabilir (uygulama açılana/ön plana alınana kadar gelen olaylar durur). Basit bir geçici çözüm, AppleScript + LaunchAgent kullanarak **her 5 dakikada bir Messages'ı dürtmektir**.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Bunu `~/Scripts/poke-messages.scpt` olarak kaydedin:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Bunu `~/Library/LaunchAgents/com.user.poke-messages.plist` olarak kaydedin:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Bu **her 300 saniyede bir** ve **oturum açıldığında** çalışır. İlk çalıştırma macOS **Automation** istemlerini tetikleyebilir (`osascript` → Messages). Bunları LaunchAgent'ı çalıştıran aynı kullanıcı oturumunda onaylayın.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## İlk kurulum
|
||||
|
||||
BlueBubbles etkileşimli ilk kurulumda kullanılabilir:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Sihirbaz şunları ister:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles sunucu adresi (örn. `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
BlueBubbles Server ayarlarından API parolası.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook uç nokta yolu.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` veya `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Telefon numaraları, e-postalar veya sohbet hedefleri.
|
||||
</ParamField>
|
||||
|
||||
BlueBubbles'ı CLI ile de ekleyebilirsiniz:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Erişim denetimi (DM'ler + gruplar)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Varsayılan: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Bilinmeyen gönderenler bir eşleştirme kodu alır; onaylanana kadar mesajlar yok sayılır (kodların süresi 1 saat sonra dolar).
|
||||
- Şununla onaylayın:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Eşleştirme varsayılan token değişimidir. Ayrıntılar: [Eşleştirme](/tr/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (varsayılan: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`, `allowlist` ayarlandığında gruplarda kimin tetikleyebileceğini denetler.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Kişi adı zenginleştirme (macOS, isteğe bağlı)
|
||||
|
||||
BlueBubbles grup webhooks'u genellikle yalnızca ham katılımcı adreslerini içerir. `GroupMembers` bağlamının bunun yerine yerel kişi adlarını göstermesini istiyorsanız macOS'ta yerel Kişiler zenginleştirmesine katılabilirsiniz:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` aramayı etkinleştirir. Varsayılan: `false`.
|
||||
- Aramalar yalnızca grup erişimi, komut yetkilendirmesi ve bahsetme kapısı mesajın geçmesine izin verdikten sonra çalışır.
|
||||
- Yalnızca adı olmayan telefon katılımcıları zenginleştirilir.
|
||||
- Yerel eşleşme bulunmadığında ham telefon numaraları yedek olarak kalır.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Bahsetme kapısı (gruplar)
|
||||
|
||||
BlueBubbles, iMessage/WhatsApp davranışıyla eşleşen grup sohbetleri için bahsetme kapısını destekler:
|
||||
|
||||
- Bahsetmeleri algılamak için `agents.list[].groupChat.mentionPatterns` (veya `messages.groupChat.mentionPatterns`) kullanır.
|
||||
- Bir grup için `requireMention` etkinleştirildiğinde, ajan yalnızca kendisinden bahsedildiğinde yanıt verir.
|
||||
- Yetkili gönderenlerden gelen denetim komutları bahsetme kapısını atlar.
|
||||
|
||||
Grup başına yapılandırma:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Komut kapısı
|
||||
|
||||
- Denetim komutları (örn. `/config`, `/model`) yetkilendirme gerektirir.
|
||||
- Komut yetkilendirmesini belirlemek için `allowFrom` ve `groupAllowFrom` kullanır.
|
||||
- Yetkili gönderenler, gruplarda bahsetmeden bile denetim komutlarını çalıştırabilir.
|
||||
|
||||
### Grup başına sistem istemi
|
||||
|
||||
`channels.bluebubbles.groups.*` altındaki her giriş isteğe bağlı bir `systemPrompt` dizesi kabul eder. Değer, o gruptaki bir mesajı işleyen her turda ajanın sistem istemine enjekte edilir; böylece ajan istemlerini düzenlemeden grup başına persona veya davranış kuralları ayarlayabilirsiniz:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Anahtar, BlueBubbles'ın grup için `chatGuid` / `chatIdentifier` / sayısal `chatId` olarak bildirdiği değerle eşleşir ve `"*"` joker karakter girişi, tam eşleşmesi olmayan her grup için varsayılan sağlar (`requireMention` ve grup başına araç politikaları tarafından kullanılan aynı kalıp). Tam eşleşmeler her zaman joker karaktere üstün gelir. DM'ler bu alanı yok sayar; bunun yerine ajan düzeyinde veya hesap düzeyinde istem özelleştirmesi kullanın.
|
||||
|
||||
#### Çalışılmış örnek: iş parçacıklı yanıtlar ve tapback tepkileri (Private API)
|
||||
|
||||
BlueBubbles Private API etkinleştirildiğinde, gelen mesajlar kısa mesaj kimlikleriyle gelir (örneğin `[[reply_to:5]]`) ve ajan belirli bir mesaja iş parçacığı oluşturmak için `action=reply` veya bir tapback bırakmak için `action=react` çağırabilir. Grup başına bir `systemPrompt`, ajanın doğru aracı seçmesini sağlamanın güvenilir bir yoludur:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback tepkileri ve iş parçacıklı yanıtların ikisi de BlueBubbles Private API gerektirir; temel mekanikler için [Gelişmiş eylemler](#advanced-actions) ve [Mesaj kimlikleri](#message-ids-short-vs-full) bölümlerine bakın.
|
||||
|
||||
## ACP konuşma bağlamaları
|
||||
|
||||
BlueBubbles sohbetleri, taşıma katmanı değiştirilmeden dayanıklı ACP çalışma alanlarına dönüştürülebilir.
|
||||
|
||||
Hızlı operatör akışı:
|
||||
|
||||
- DM veya izin verilen grup sohbetinin içinde `/acp spawn codex --bind here` çalıştırın.
|
||||
- Aynı BlueBubbles konuşmasındaki gelecekteki mesajlar, oluşturulan ACP oturumuna yönlendirilir.
|
||||
- `/new` ve `/reset`, aynı bağlı ACP oturumunu yerinde sıfırlar.
|
||||
- `/acp close`, ACP oturumunu kapatır ve bağlamayı kaldırır.
|
||||
|
||||
Yapılandırılmış kalıcı bağlamalar da `type: "acp"` ve `match.channel: "bluebubbles"` ile üst düzey `bindings[]` girişleri üzerinden desteklenir.
|
||||
|
||||
`match.peer.id` desteklenen herhangi bir BlueBubbles hedef biçimini kullanabilir:
|
||||
|
||||
- `+15555550123` veya `user@example.com` gibi normalize edilmiş DM tanıtıcısı
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Kararlı grup bağlamaları için `chat_id:*` veya `chat_identifier:*` tercih edin.
|
||||
|
||||
Örnek:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Paylaşılan ACP bağlama davranışı için [ACP aracıları](/tr/tools/acp-agents) bölümüne bakın.
|
||||
|
||||
## Yazıyor göstergeleri + okundu bilgileri
|
||||
|
||||
- **Yazıyor göstergeleri**: Yanıt üretiminden önce ve üretim sırasında otomatik olarak gönderilir.
|
||||
- **Okundu bilgileri**: `channels.bluebubbles.sendReadReceipts` tarafından denetlenir (varsayılan: `true`).
|
||||
- **Yazıyor göstergeleri**: OpenClaw yazıyor başlangıç olayları gönderir; BlueBubbles gönderimde veya zaman aşımında yazıyor durumunu otomatik olarak temizler (DELETE ile elle durdurma güvenilir değildir).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Gelişmiş eylemler
|
||||
|
||||
BlueBubbles, yapılandırmada etkinleştirildiğinde gelişmiş ileti eylemlerini destekler:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Kullanılabilir eylemler">
|
||||
- **react**: Tapback tepkileri ekleyin/kaldırın (`messageId`, `emoji`, `remove`). iMessage'ın yerel tapback kümesi `love`, `like`, `dislike`, `laugh`, `emphasize` ve `question` değerleridir. Bir aracı bu kümenin dışında bir emoji seçtiğinde (örneğin `👀`), tepki aracı `love` değerine geri döner; böylece tüm istek başarısız olmak yerine tapback yine işlenir. Yapılandırılmış onay tepkileri yine de katı biçimde doğrulanır ve bilinmeyen değerlerde hata verir.
|
||||
- **edit**: Gönderilmiş bir iletiyi düzenleyin (`messageId`, `text`).
|
||||
- **unsend**: Bir iletiyi geri alın (`messageId`).
|
||||
- **reply**: Belirli bir iletiye yanıt verin (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: iMessage efektiyle gönderin (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Bir grup sohbetini yeniden adlandırın (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Bir grup sohbetinin simgesini/fotoğrafını ayarlayın (`chatGuid`, `media`) - macOS 26 Tahoe'da kararsızdır (API başarı döndürebilir ancak simge eşitlenmez).
|
||||
- **addParticipant**: Bir gruba birini ekleyin (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Bir gruptan birini kaldırın (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Bir grup sohbetinden ayrılın (`chatGuid`).
|
||||
- **upload-file**: Medya/dosya gönderin (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Sesli notlar: iMessage sesli iletisi olarak göndermek için **MP3** veya **CAF** sesle `asVoice: true` ayarlayın. BlueBubbles sesli not gönderirken MP3 → CAF dönüştürür.
|
||||
- Eski takma ad: `sendAttachment` çalışmaya devam eder, ancak kanonik eylem adı `upload-file` değeridir.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### İleti kimlikleri (kısa ve tam)
|
||||
|
||||
OpenClaw, token tasarrufu için _kısa_ ileti kimlikleri (ör. `1`, `2`) gösterebilir.
|
||||
|
||||
- `MessageSid` / `ReplyToId` kısa kimlikler olabilir.
|
||||
- `MessageSidFull` / `ReplyToIdFull` sağlayıcı tam kimliklerini içerir.
|
||||
- Kısa kimlikler bellek içindedir; yeniden başlatmada veya önbellek çıkarımında süreleri dolabilir.
|
||||
- Eylemler kısa veya tam `messageId` kabul eder, ancak kısa kimlikler artık kullanılamıyorsa hata verir.
|
||||
|
||||
Kalıcı otomasyonlar ve depolama için tam kimlikleri kullanın:
|
||||
|
||||
- Şablonlar: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Bağlam: gelen yüklerde `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
Şablon değişkenleri için [Yapılandırma](/tr/gateway/configuration) bölümüne bakın.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Bölünmüş gönderimli DM'leri birleştirme (tek kompozisyonda komut + URL)
|
||||
|
||||
Bir kullanıcı iMessage içinde bir komutu ve URL'yi birlikte yazdığında - ör. `Dump https://example.com/article` - Apple gönderimi **iki ayrı Webhook teslimatına** böler:
|
||||
|
||||
1. Bir metin iletisi (`"Dump"`).
|
||||
2. Ek olarak OG önizleme görselleriyle bir URL önizleme balonu (`"https://..."`).
|
||||
|
||||
İki Webhook çoğu kurulumda OpenClaw'a yaklaşık 0,8-2,0 sn arayla ulaşır. Birleştirme olmadan aracı 1. turda yalnızca komutu alır, yanıt verir (çoğunlukla "bana URL'yi gönder") ve URL'yi yalnızca 2. turda görür; o noktada komut bağlamı zaten kaybolmuştur.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms`, bir DM'yi aynı gönderenin ardışık Webhook'larını tek bir aracı turunda birleştirecek şekilde etkinleştirir. Grup sohbetleri, çok kullanıcılı tur yapısı korunsun diye ileti başına anahtarlanmaya devam eder.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Ne zaman etkinleştirilmeli">
|
||||
Şu durumlarda etkinleştirin:
|
||||
|
||||
- Tek iletide `command + payload` bekleyen Skills gönderiyorsanız (dump, paste, save, queue vb.).
|
||||
- Kullanıcılarınız komutların yanına URL'ler, görseller veya uzun içerikler yapıştırıyorsa.
|
||||
- Eklenen DM tur gecikmesini kabul edebiliyorsanız (aşağıya bakın).
|
||||
|
||||
Şu durumlarda devre dışı bırakın:
|
||||
|
||||
- Tek sözcüklü DM tetikleyicileri için minimum komut gecikmesine ihtiyacınız varsa.
|
||||
- Tüm akışlarınız, yük devamı olmayan tek seferlik komutlarsa.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Etkinleştirme">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Bayrak açıkken ve açık bir `messages.inbound.byChannel.bluebubbles` yokken, debounce penceresi **2500 ms** değerine genişler (birleştirme olmayan varsayılan 500 ms'dir). Daha geniş pencere gereklidir; Apple'ın 0,8-2,0 sn'lik bölünmüş gönderim temposu daha dar varsayılana sığmaz.
|
||||
|
||||
Pencereyi kendiniz ayarlamak için:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Ödünleşimler">
|
||||
- **DM denetim komutları için ek gecikme.** Bayrak açıkken DM denetim komutu iletileri (`Dump`, `Save` vb.) artık bir yük Webhook'u geliyor olma olasılığına karşı gönderilmeden önce debounce penceresine kadar bekler. Grup sohbeti komutları anında gönderilmeyi korur.
|
||||
- **Birleştirilmiş çıktı sınırlandırılır** - birleştirilmiş metin, açık bir `…[truncated]` işaretiyle 4000 karakterde sınırlanır; ekler 20 ile sınırlanır; kaynak girdileri 10 ile sınırlanır (bunun ötesinde ilk ve en son korunur). Her kaynak `messageId` yine de gelen tekilleştirmeye ulaşır; bu nedenle daha sonra herhangi bir tekil olayın MessagePoller yeniden oynatımı yinelenen olarak tanınır.
|
||||
- **Kanala göre isteğe bağlı.** Diğer kanallar (Telegram, WhatsApp, Slack, …) etkilenmez.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Senaryolar ve aracının gördükleri
|
||||
|
||||
| Kullanıcının oluşturduğu | Apple'ın teslim ettiği | Bayrak kapalı (varsayılan) | Bayrak açık + 2500 ms pencere |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (tek gönderim) | Yaklaşık 1 sn arayla 2 Webhook | İki aracı turu: yalnızca "Dump", sonra URL | Tek tur: birleştirilmiş metin `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (ek + metin) | 2 Webhook | İki tur | Tek tur: metin + görsel |
|
||||
| `/status` (bağımsız komut) | 1 Webhook | Anında gönderim | **Pencereye kadar bekle, sonra gönder** |
|
||||
| Tek başına yapıştırılan URL | 1 Webhook | Anında gönderim | Anında gönderim (kovada yalnızca bir girdi) |
|
||||
| Metin + URL dakika arayla kasıtlı iki ayrı ileti olarak gönderildi | Pencere dışında 2 Webhook | İki tur | İki tur (pencere aralarında dolar) |
|
||||
| Hızlı taşma (pencere içinde >10 küçük DM) | N Webhook | N tur | Tek tur, sınırlandırılmış çıktı (ilk + en son, metin/ek sınırları uygulanır) |
|
||||
|
||||
### Bölünmüş gönderim birleştirme sorun giderme
|
||||
|
||||
Bayrak açıksa ve bölünmüş gönderimler yine de iki tur olarak geliyorsa her katmanı denetleyin:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Yapılandırma gerçekten yüklendi">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Ardından `openclaw gateway restart` çalıştırın; bayrak debouncer kayıt defteri oluşturulurken okunur.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce penceresi kurulumunuz için yeterince geniş">
|
||||
BlueBubbles sunucu günlüğüne `~/Library/Logs/bluebubbles-server/main.log` altında bakın:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
`"Dump"` tarzı metin gönderimi ile onu izleyen `"https://..."; Attachments:` gönderimi arasındaki boşluğu ölçün. `messages.inbound.byChannel.bluebubbles` değerini bu boşluğu rahatça kapsayacak şekilde artırın.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Oturum JSONL zaman damgaları ≠ Webhook varışı">
|
||||
Oturum olayı zaman damgaları (`~/.openclaw/agents/<id>/sessions/*.jsonl`), Webhook'un ne zaman geldiğini **değil**, Gateway'in bir iletiyi aracıya ne zaman verdiğini yansıtır. `[Queued messages while agent was busy]` etiketi taşıyan kuyruğa alınmış ikinci ileti, ikinci Webhook geldiğinde ilk turun hâlâ çalıştığı anlamına gelir; birleştirme kovası zaten boşaltılmıştı. Pencereyi oturum günlüğüne göre değil, BB sunucu günlüğüne göre ayarlayın.
|
||||
</Accordion>
|
||||
<Accordion title="Bellek baskısı yanıt gönderimini yavaşlatıyor">
|
||||
Daha küçük makinelerde (8 GB), aracı turları yanıt tamamlanmadan önce birleştirme kovasının boşalmasına yetecek kadar uzun sürebilir ve URL kuyruğa alınmış ikinci tur olarak düşer. `memory_pressure` ve `ps -o rss -p $(pgrep openclaw-gateway)` değerlerini denetleyin; Gateway ~500 MB RSS üzerindeyse ve sıkıştırıcı etkinse diğer ağır süreçleri kapatın veya daha büyük bir ana makineye geçin.
|
||||
</Accordion>
|
||||
<Accordion title="Yanıt alıntısı gönderimleri farklı bir yoldur">
|
||||
Kullanıcı mevcut bir URL balonuna **yanıt** olarak `Dump` öğesine dokunduysa (iMessage, Dump balonunda "1 Reply" rozeti gösterir), URL ikinci bir Webhook'ta değil `replyToBody` içinde yaşar. Birleştirme uygulanmaz; bu bir debouncer konusu değil, Skills/istem konusudur.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Blok akışı
|
||||
|
||||
Yanıtların tek bir ileti olarak mı yoksa bloklar halinde akışla mı gönderileceğini denetleyin:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Medya + sınırlar
|
||||
|
||||
- Gelen ekler indirilir ve medya önbelleğinde saklanır.
|
||||
- Gelen ve giden medya için `channels.bluebubbles.mediaMaxMb` üzerinden medya sınırı (varsayılan: 8 MB).
|
||||
- Giden metin `channels.bluebubbles.textChunkLimit` değerine göre parçalara ayrılır (varsayılan: 4000 karakter).
|
||||
|
||||
## Yapılandırma referansı
|
||||
|
||||
Tam yapılandırma: [Yapılandırma](/tr/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Bağlantı ve webhook">
|
||||
- `channels.bluebubbles.enabled`: Kanalı etkinleştir/devre dışı bırak.
|
||||
- `channels.bluebubbles.serverUrl`: BlueBubbles REST API temel URL'si.
|
||||
- `channels.bluebubbles.password`: API parolası.
|
||||
- `channels.bluebubbles.webhookPath`: Webhook uç nokta yolu (varsayılan: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Erişim politikası">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (varsayılan: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: DM izin listesi (tanıtıcılar, e-postalar, E.164 numaraları, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (varsayılan: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Grup gönderen izin listesi.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: macOS'te, kapı denetiminden geçildikten sonra adsız grup katılımcılarını isteğe bağlı olarak yerel Kişiler'den zenginleştirir. Varsayılan: `false`.
|
||||
- `channels.bluebubbles.groups`: Grup başına yapılandırma (`requireMention` vb.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Teslim ve parçalama">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Okundu bilgisi gönder (varsayılan: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Blok akışını etkinleştir (varsayılan: `false`; akış yanıtları için gereklidir).
|
||||
- `channels.bluebubbles.textChunkLimit`: Karakter cinsinden giden parça boyutu (varsayılan: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: `/api/v1/message/text` üzerinden giden metin gönderimleri için istek başına ms cinsinden zaman aşımı (varsayılan: 30000). Private API iMessage gönderimlerinin iMessage framework'ü içinde 60+ saniye takılabildiği macOS 26 kurulumlarında artırın; örneğin `45000` veya `60000`. Yoklamalar, sohbet aramaları, tepkiler, düzenlemeler ve sağlık denetimleri şu anda daha kısa 10 sn varsayılanını korur; kapsamın tepkiler ve düzenlemelere genişletilmesi takip işi olarak planlanmıştır. Hesap başına geçersiz kılma: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (varsayılan), yalnızca `textChunkLimit` aşıldığında böler; `newline`, uzunluğa göre parçalamadan önce boş satırlardan (paragraf sınırları) böler.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Medya ve geçmiş">
|
||||
- `channels.bluebubbles.mediaMaxMb`: MB cinsinden gelen/giden medya sınırı (varsayılan: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Giden yerel medya yolları için izin verilen mutlak yerel dizinlerin açık izin listesi. Bu yapılandırılmadıkça yerel yol gönderimleri varsayılan olarak reddedilir. Hesap başına geçersiz kılma: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Apple's metin+URL bölünmüş gönderimi tek ileti olarak gelsin diye art arda gelen aynı gönderenli DM webhook'larını tek bir ajan turunda birleştir (varsayılan: `false`). Senaryolar, pencere ayarı ve ödünleşimler için [Bölünmüş gönderimli DM'leri birleştirme](#coalescing-split-send-dms-command--url-in-one-composition) bölümüne bakın. Açık bir `messages.inbound.byChannel.bluebubbles` olmadan etkinleştirildiğinde varsayılan gelen debounce penceresini 500 ms'den 2500 ms'ye genişletir.
|
||||
- `channels.bluebubbles.historyLimit`: Bağlam için en fazla grup iletisi (0 devre dışı bırakır).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM geçmiş sınırı.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Gelen bir yanıt `replyToBody`/`replyToSender` olmadan geldiğinde ve bellek içi yanıt bağlamı önbelleğinde eşleşme bulunmadığında, en iyi çaba yedeği olarak özgün iletiyi BlueBubbles HTTP API'sinden getir (varsayılan: `false`). Tek BlueBubbles hesabını paylaşan çok örnekli dağıtımlar, işlem yeniden başlatmaları veya uzun ömürlü TTL/LRU önbellek tahliyesinden sonra kullanışlıdır. Getirme işlemi, diğer tüm BlueBubbles istemci istekleriyle aynı politika tarafından SSRF'ye karşı korunur, asla hata fırlatmaz ve sonraki yanıtların maliyetini yaymak için önbelleği doldurur. Hesap başına geçersiz kılma: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Kanal düzeyindeki bir ayar, bayrağı atlayan hesaplara yayılır.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Eylemler ve hesaplar">
|
||||
- `channels.bluebubbles.actions`: Belirli eylemleri etkinleştir/devre dışı bırak.
|
||||
- `channels.bluebubbles.accounts`: Çok hesaplı yapılandırma.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
İlgili genel seçenekler:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (veya `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Adresleme / teslim hedefleri
|
||||
|
||||
Kararlı yönlendirme için `chat_guid` tercih edin:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (gruplar için tercih edilir)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Doğrudan tanıtıcılar: `+15555550123`, `user@example.com`
|
||||
- Doğrudan bir tanıtıcının mevcut bir DM sohbeti yoksa OpenClaw, `POST /api/v1/chat/new` aracılığıyla bir tane oluşturur. Bu, BlueBubbles Private API'nin etkin olmasını gerektirir.
|
||||
|
||||
### iMessage ve SMS yönlendirmesi
|
||||
|
||||
Aynı tanıtıcının Mac'te hem iMessage hem de SMS sohbeti olduğunda (örneğin iMessage'a kayıtlı olan ancak yeşil balonlu yedekleri de almış bir telefon numarası), OpenClaw iMessage sohbetini tercih eder ve asla sessizce SMS'e düşmez. SMS sohbetini zorlamak için açık bir `sms:` hedef öneki kullanın (örneğin `sms:+15555550123`). Eşleşen iMessage sohbeti olmayan tanıtıcılar yine BlueBubbles'ın bildirdiği sohbet üzerinden gönderilir.
|
||||
|
||||
## Güvenlik
|
||||
|
||||
- Webhook isteklerinin kimliği, `guid`/`password` sorgu parametreleri veya başlıkları `channels.bluebubbles.password` ile karşılaştırılarak doğrulanır.
|
||||
- API parolasını ve webhook uç noktasını gizli tutun (bunları kimlik bilgileri gibi ele alın).
|
||||
- BlueBubbles webhook kimlik doğrulaması için localhost atlaması yoktur. Webhook trafiğini proxy'liyorsanız BlueBubbles parolasını istekte uçtan uca koruyun. `gateway.trustedProxies` burada `channels.bluebubbles.password` yerine geçmez. Bkz. [Gateway güvenliği](/tr/gateway/security#reverse-proxy-configuration).
|
||||
- BlueBubbles sunucusunu LAN dışına açıyorsanız HTTPS + güvenlik duvarı kurallarını etkinleştirin.
|
||||
|
||||
## Sorun giderme
|
||||
|
||||
- Yazma/okundu olayları çalışmayı durdurursa BlueBubbles webhook günlüklerini kontrol edin ve Gateway yolunun `channels.bluebubbles.webhookPath` ile eşleştiğini doğrulayın.
|
||||
- Eşleştirme kodlarının süresi bir saat sonra dolar; `openclaw pairing list bluebubbles` ve `openclaw pairing approve bluebubbles <code>` kullanın.
|
||||
- Tepkiler BlueBubbles private API'sini gerektirir (`POST /api/v1/message/react`); sunucu sürümünün bunu sunduğundan emin olun.
|
||||
- Düzenleme/göndermeyi geri alma için macOS 13+ ve uyumlu bir BlueBubbles sunucu sürümü gerekir. macOS 26'da (Tahoe), private API değişiklikleri nedeniyle düzenleme şu anda bozuk.
|
||||
- Grup simgesi güncellemeleri macOS 26'da (Tahoe) güvenilmez olabilir: API başarı döndürebilir ancak yeni simge eşitlenmeyebilir.
|
||||
- OpenClaw, BlueBubbles sunucusunun macOS sürümüne göre bozuk olduğu bilinen eylemleri otomatik olarak gizler. Düzenleme macOS 26'da (Tahoe) hâlâ görünüyorsa `channels.bluebubbles.actions.edit=false` ile el ile devre dışı bırakın.
|
||||
- `coalesceSameSenderDms` etkin ama bölünmüş gönderimler (örn. `Dump` + URL) hâlâ iki tur olarak geliyorsa: [bölünmüş gönderim birleştirme sorun giderme](#split-send-coalescing-troubleshooting) kontrol listesine bakın - yaygın nedenler çok dar debounce penceresi, oturum günlüğü zaman damgalarının webhook geliş zamanı olarak yanlış okunması veya bir yanıt alıntısı gönderimidir (`replyToBody` kullanır, ikinci bir webhook değil).
|
||||
- Durum/sağlık bilgisi için: `openclaw status --all` veya `openclaw status --deep`.
|
||||
|
||||
Genel kanal iş akışı başvurusu için [Kanallar](/tr/channels) ve [Plugins](/tr/tools/plugin) kılavuzuna bakın.
|
||||
|
||||
## İlgili
|
||||
|
||||
- [Kanal Yönlendirme](/tr/channels/channel-routing) - iletiler için oturum yönlendirmesi
|
||||
- [Kanallara Genel Bakış](/tr/channels) - desteklenen tüm kanallar
|
||||
- [Gruplar](/tr/channels/groups) - grup sohbeti davranışı ve bahsetme kapı denetimi
|
||||
- [Eşleştirme](/tr/channels/pairing) - DM kimlik doğrulaması ve eşleştirme akışı
|
||||
- [Güvenlik](/tr/gateway/security) - erişim modeli ve sıkılaştırma
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- bluebubbles Plugin'ini kuruyor, yapılandırıyor veya denetliyorsunuz
|
||||
summary: OpenClaw mesajlarını göndermek ve almak için BlueBubbles kanal yüzeyini ekler.
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T08:58:58Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles Plugin
|
||||
|
||||
OpenClaw mesajlarını göndermek ve almak için BlueBubbles kanal yüzeyini ekler.
|
||||
|
||||
## Dağıtım
|
||||
|
||||
- Paket: `@openclaw/bluebubbles`
|
||||
- Kurulum yolu: npm; ClawHub
|
||||
|
||||
## Yüzey
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## İlgili belgeler
|
||||
|
||||
- [bluebubbles](/tr/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Налаштування каналу BlueBubbles
|
||||
- Усунення несправностей зі сполученням Webhook
|
||||
- Налаштування iMessage на macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Застаріла підтримка iMessage через macOS-сервер BlueBubbles (надсилання/отримання через REST, введення тексту, реакції, сполучення, розширені дії).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:53Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Статус: вбудований застарілий plugin, який спілкується із сервером BlueBubbles для macOS через HTTP. Наявні налаштування BlueBubbles продовжують працювати, але для нових розгортань OpenClaw iMessage варто віддавати перевагу нативному plugin [iMessage](/uk/channels/imessage), коли його вимоги підходять для вашого хоста.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles застарілий для нових налаштувань OpenClaw.
|
||||
|
||||
Висхідна екосистема BlueBubbles усе ще активна, але OpenClaw залежить від API сервера BlueBubbles для macOS. Станом на 6 травня 2026 року офіційна гілка розробки [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) востаннє змінювалася [22 січня 2026 року](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), а останній випуск сервера ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) було опубліковано 16 травня 2025 року. Клієнтський застосунок і допоміжні репозиторії мають новішу активність, тому це не твердження про занедбаність; позначення як застарілого стосується зменшення залежності OpenClaw від зовнішнього HTTP-сервера, webhooks і поверхні сумісності приватного API, коли нативний шлях `imsg` утримує інтеграцію на локальному контракті stdio.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Поточні випуски OpenClaw постачають BlueBubbles у комплекті, тому звичайні пакетні збірки не потребують окремого кроку `openclaw plugins install`.
|
||||
</Note>
|
||||
|
||||
## Огляд
|
||||
|
||||
- Працює на macOS через допоміжний застосунок BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Застарілий резервний варіант для інсталяцій, які вже покладаються на ідентифікатори каналів BlueBubbles, стан webhook, цілі груп, доставку cron або маршрутизацію робочих просторів.
|
||||
- Рекомендовано/протестовано: macOS Sequoia (15). macOS Tahoe (26) працює; редагування наразі зламане на Tahoe, а оновлення піктограм груп можуть повідомляти про успіх, але не синхронізуватися.
|
||||
- OpenClaw спілкується з ним через його REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Вхідні повідомлення надходять через webhooks; вихідні відповіді, індикатори набору, сповіщення про прочитання й tapbacks є REST-викликами.
|
||||
- Вкладення та стікери приймаються як вхідні медіа (і за можливості показуються агенту).
|
||||
- Автоматичні TTS-відповіді, які синтезують аудіо MP3 або CAF, доставляються як бульбашки голосових нотаток iMessage, а не як звичайні файлові вкладення.
|
||||
- Парування/список дозволених працює так само, як для інших каналів (`/channels/pairing` тощо), з `channels.bluebubbles.allowFrom` + кодами парування.
|
||||
- Реакції відображаються як системні події, так само як у Slack/Telegram, щоб агенти могли «згадати» їх перед відповіддю.
|
||||
- Розширені можливості: редагування, скасування надсилання, гілки відповідей, ефекти повідомлень, керування групами.
|
||||
|
||||
## Швидкий старт
|
||||
|
||||
<Steps>
|
||||
<Step title="Установіть BlueBubbles">
|
||||
Установіть сервер BlueBubbles на ваш Mac (дотримуйтеся інструкцій на [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Увімкніть веб-API">
|
||||
У конфігурації BlueBubbles увімкніть веб-API та задайте пароль.
|
||||
</Step>
|
||||
<Step title="Налаштуйте OpenClaw">
|
||||
Запустіть `openclaw onboard` і виберіть BlueBubbles або налаштуйте вручну:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Спрямуйте webhooks на Gateway">
|
||||
Спрямуйте webhooks BlueBubbles на ваш gateway (приклад: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Запустіть Gateway">
|
||||
Запустіть gateway; він зареєструє обробник webhook і почне парування.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Безпека**
|
||||
|
||||
- Завжди задавайте пароль webhook.
|
||||
- Автентифікація webhook завжди обов’язкова. OpenClaw відхиляє запити webhook BlueBubbles, якщо вони не містять password/guid, що збігається з `channels.bluebubbles.password` (наприклад, `?password=<password>` або `x-password`), незалежно від топології loopback/proxy.
|
||||
- Автентифікація паролем перевіряється перед читанням/розбором повних тіл webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Підтримання Messages.app активним (VM / безголові налаштування)
|
||||
|
||||
Деякі налаштування macOS VM / always-on можуть призводити до того, що Messages.app переходить у стан «idle» (вхідні події зупиняються, доки застосунок не відкриють/не виведуть на передній план). Простий обхідний шлях — **підштовхувати Messages кожні 5 хвилин** за допомогою AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Збережіть AppleScript">
|
||||
Збережіть це як `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Установіть LaunchAgent">
|
||||
Збережіть це як `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Це запускається **кожні 300 секунд** і **під час входу**. Перший запуск може спричинити запити macOS **Automation** (`osascript` → Messages). Підтвердьте їх у тій самій сесії користувача, яка запускає LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Завантажте його">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Початкове налаштування
|
||||
|
||||
BlueBubbles доступний в інтерактивному початковому налаштуванні:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Майстер запитує:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Адреса сервера BlueBubbles (наприклад, `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Пароль API з налаштувань BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Шлях кінцевої точки webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open` або `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Номери телефонів, електронні адреси або цілі чатів.
|
||||
</ParamField>
|
||||
|
||||
Також можна додати BlueBubbles через CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Контроль доступу (DM + групи)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- За замовчуванням: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Невідомі відправники отримують код парування; повідомлення ігноруються, доки їх не схвалять (коди спливають через 1 годину).
|
||||
- Схвалення через:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Парування є типовим обміном токенами. Докладніше: [Парування](/uk/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Групи">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (за замовчуванням: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` визначає, хто може запускати в групах, коли встановлено `allowlist`.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Збагачення імен контактів (macOS, необов’язково)
|
||||
|
||||
Групові webhooks BlueBubbles часто містять лише сирі адреси учасників. Якщо ви хочете, щоб контекст `GroupMembers` натомість показував локальні імена контактів, можна увімкнути локальне збагачення з Contacts на macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` вмикає пошук. За замовчуванням: `false`.
|
||||
- Пошуки виконуються лише після того, як груповий доступ, авторизація команд і фільтрація згадок дозволили повідомлення.
|
||||
- Збагачуються лише учасники з телефонними номерами без імен.
|
||||
- Сирі номери телефонів залишаються резервним варіантом, коли локальний збіг не знайдено.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Фільтрація згадок (групи)
|
||||
|
||||
BlueBubbles підтримує фільтрацію згадок для групових чатів, відповідно до поведінки iMessage/WhatsApp:
|
||||
|
||||
- Використовує `agents.list[].groupChat.mentionPatterns` (або `messages.groupChat.mentionPatterns`) для виявлення згадок.
|
||||
- Коли `requireMention` увімкнено для групи, агент відповідає лише тоді, коли його згадано.
|
||||
- Команди керування від авторизованих відправників обходять фільтрацію згадок.
|
||||
|
||||
Конфігурація для окремої групи:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Фільтрація команд
|
||||
|
||||
- Команди керування (наприклад, `/config`, `/model`) потребують авторизації.
|
||||
- Використовує `allowFrom` і `groupAllowFrom`, щоб визначити авторизацію команд.
|
||||
- Авторизовані відправники можуть запускати команди керування навіть без згадки в групах.
|
||||
|
||||
### Системна підказка для окремої групи
|
||||
|
||||
Кожен запис у `channels.bluebubbles.groups.*` приймає необов’язковий рядок `systemPrompt`. Значення вставляється в системну підказку агента на кожному ході, який обробляє повідомлення в цій групі, тож можна задавати персоналію або поведінкові правила для окремої групи без редагування підказок агента:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Ключ відповідає тому, що BlueBubbles повідомляє як `chatGuid` / `chatIdentifier` / числовий `chatId` для групи, а запис із wildcard `"*"` надає значення за замовчуванням для кожної групи без точного збігу (той самий шаблон використовується `requireMention` і політиками інструментів для окремих груп). Точні збіги завжди мають перевагу над wildcard. DM ігнорують це поле; натомість використовуйте налаштування підказок на рівні агента або облікового запису.
|
||||
|
||||
#### Робочий приклад: гілкові відповіді та реакції tapback (приватний API)
|
||||
|
||||
Коли приватний API BlueBubbles увімкнено, вхідні повідомлення надходять із короткими ідентифікаторами повідомлень (наприклад, `[[reply_to:5]]`), і агент може викликати `action=reply`, щоб відповісти в гілці конкретного повідомлення, або `action=react`, щоб додати tapback. `systemPrompt` для окремої групи — надійний спосіб утримати агента у виборі правильного інструмента:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Реакції tapback і гілкові відповіді обидві потребують приватного API BlueBubbles; див. [Розширені дії](#advanced-actions) і [Ідентифікатори повідомлень](#message-ids-short-vs-full) щодо базової механіки.
|
||||
|
||||
## Прив’язки розмов ACP
|
||||
|
||||
Чати BlueBubbles можна перетворити на довговічні робочі простори ACP без зміни транспортного рівня.
|
||||
|
||||
Швидкий потік оператора:
|
||||
|
||||
- Запустіть `/acp spawn codex --bind here` у DM або дозволеному груповому чаті.
|
||||
- Майбутні повідомлення в тій самій розмові BlueBubbles маршрутизуються до породженої сесії ACP.
|
||||
- `/new` і `/reset` скидають ту саму прив’язану сесію ACP на місці.
|
||||
- `/acp close` закриває сесію ACP і видаляє прив’язку.
|
||||
|
||||
Налаштовані сталі прив’язки також підтримуються через записи верхнього рівня `bindings[]` з `type: "acp"` і `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` може використовувати будь-яку підтримувану форму цілі BlueBubbles:
|
||||
|
||||
- нормалізований DM-ідентифікатор, як-от `+15555550123` або `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Для стабільних прив’язок груп надавайте перевагу `chat_id:*` або `chat_identifier:*`.
|
||||
|
||||
Приклад:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Див. [ACP Agents](/uk/tools/acp-agents) щодо спільної поведінки прив’язок ACP.
|
||||
|
||||
## Індикатори набору + сповіщення про прочитання
|
||||
|
||||
- **Індикатори набору**: надсилаються автоматично до та під час генерації відповіді.
|
||||
- **Сповіщення про прочитання**: керуються `channels.bluebubbles.sendReadReceipts` (типово: `true`).
|
||||
- **Індикатори набору**: OpenClaw надсилає події початку набору; BlueBubbles автоматично очищає індикатор набору під час надсилання або після тайм-ауту (ручна зупинка через DELETE ненадійна).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Розширені дії
|
||||
|
||||
BlueBubbles підтримує розширені дії з повідомленнями, якщо їх увімкнено в конфігурації:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Доступні дії">
|
||||
- **react**: додати/видалити реакції tapback (`messageId`, `emoji`, `remove`). Власний набір tapback в iMessage: `love`, `like`, `dislike`, `laugh`, `emphasize` і `question`. Коли агент вибирає emoji поза цим набором (наприклад `👀`), інструмент реакцій повертається до `love`, щоб tapback усе одно відобразився, а не зламав увесь запит. Налаштовані ack-реакції й надалі перевіряються суворо й дають помилку для невідомих значень.
|
||||
- **edit**: редагувати надіслане повідомлення (`messageId`, `text`).
|
||||
- **unsend**: скасувати надсилання повідомлення (`messageId`).
|
||||
- **reply**: відповісти на конкретне повідомлення (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: надіслати з ефектом iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: перейменувати груповий чат (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: установити іконку/фото групового чату (`chatGuid`, `media`) - нестабільно на macOS 26 Tahoe (API може повернути успіх, але іконка не синхронізується).
|
||||
- **addParticipant**: додати когось до групи (`chatGuid`, `address`).
|
||||
- **removeParticipant**: видалити когось із групи (`chatGuid`, `address`).
|
||||
- **leaveGroup**: вийти з групового чату (`chatGuid`).
|
||||
- **upload-file**: надіслати медіа/файли (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Голосові нотатки: установіть `asVoice: true` з аудіо **MP3** або **CAF**, щоб надіслати його як голосове повідомлення iMessage. BlueBubbles перетворює MP3 → CAF під час надсилання голосових нотаток.
|
||||
- Застарілий псевдонім: `sendAttachment` усе ще працює, але `upload-file` є канонічною назвою дії.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID повідомлень (короткі та повні)
|
||||
|
||||
OpenClaw може показувати _короткі_ ID повідомлень (наприклад, `1`, `2`), щоб заощаджувати токени.
|
||||
|
||||
- `MessageSid` / `ReplyToId` можуть бути короткими ID.
|
||||
- `MessageSidFull` / `ReplyToIdFull` містять повні ID провайдера.
|
||||
- Короткі ID зберігаються в пам’яті; вони можуть застаріти після перезапуску або витіснення з кешу.
|
||||
- Дії приймають короткий або повний `messageId`, але короткі ID даватимуть помилку, якщо вони більше недоступні.
|
||||
|
||||
Використовуйте повні ID для довговічних автоматизацій і зберігання:
|
||||
|
||||
- Шаблони: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Контекст: `MessageSidFull` / `ReplyToIdFull` у вхідних payload
|
||||
|
||||
Див. [Конфігурація](/uk/gateway/configuration) щодо змінних шаблонів.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Об’єднання split-send DM (команда + URL в одному введенні)
|
||||
|
||||
Коли користувач вводить команду та URL разом в iMessage - наприклад `Dump https://example.com/article` - Apple розбиває надсилання на **дві окремі доставки webhook**:
|
||||
|
||||
1. Текстове повідомлення (`"Dump"`).
|
||||
2. Бульбашка URL-перегляду (`"https://..."`) із зображеннями OG-перегляду як вкладеннями.
|
||||
|
||||
У більшості налаштувань ці два webhooks надходять до OpenClaw з інтервалом приблизно 0.8-2.0 с. Без об’єднання агент отримує лише команду на ході 1, відповідає (часто «надішліть мені URL») і бачить URL лише на ході 2 - коли контекст команди вже втрачено.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` вмикає для DM злиття послідовних webhooks від того самого відправника в один хід агента. Групові чати й надалі ключуються за окремими повідомленнями, щоб зберегти структуру ходів із багатьма користувачами.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Коли вмикати">
|
||||
Увімкніть, коли:
|
||||
|
||||
- Ви постачаєте Skills, які очікують `command + payload` в одному повідомленні (dump, paste, save, queue тощо).
|
||||
- Ваші користувачі вставляють URL, зображення або довгий вміст поруч із командами.
|
||||
- Ви можете прийняти додану затримку ходу DM (див. нижче).
|
||||
|
||||
Залиште вимкненим, коли:
|
||||
|
||||
- Вам потрібна мінімальна затримка команд для однослівних DM-тригерів.
|
||||
- Усі ваші потоки є одноразовими командами без подальших payload.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Увімкнення">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Якщо прапорець увімкнено й немає явного `messages.inbound.byChannel.bluebubbles`, вікно debounce розширюється до **2500 мс** (типове значення без об’єднання: 500 мс). Ширше вікно потрібне, бо каденція split-send Apple у 0.8-2.0 с не вміщується в тісніше типове значення.
|
||||
|
||||
Щоб налаштувати вікно самостійно:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Компроміси">
|
||||
- **Додана затримка для керівних команд DM.** Коли прапорець увімкнено, повідомлення керівних команд DM (як-от `Dump`, `Save` тощо) тепер чекають до завершення вікна debounce перед dispatch, на випадок якщо надходить webhook із payload. Команди групового чату зберігають миттєвий dispatch.
|
||||
- **Об’єднаний вихід обмежений** - об’єднаний текст обмежується 4000 символами з явним маркером `…[truncated]`; вкладення - 20; записи джерел - 10 (після цього зберігаються перший і найновіший). Кожен source `messageId` усе одно потрапляє до inbound-dedupe, тож пізніший replay будь-якої окремої події від MessagePoller розпізнається як дублікат.
|
||||
- **Opt-in, на рівні каналу.** Інші канали (Telegram, WhatsApp, Slack, …) не зачіпаються.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Сценарії та що бачить агент
|
||||
|
||||
| Що вводить користувач | Що доставляє Apple | Прапорець вимкнено (типово) | Прапорець увімкнено + вікно 2500 мс |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (одне надсилання) | 2 webhooks з інтервалом ~1 с | Два ходи агента: лише "Dump", потім URL | Один хід: об’єднаний текст `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (вкладення + текст) | 2 webhooks | Два ходи | Один хід: текст + зображення |
|
||||
| `/status` (самостійна команда) | 1 webhook | Миттєвий dispatch | **Очікування до вікна, потім dispatch** |
|
||||
| URL, вставлений окремо | 1 webhook | Миттєвий dispatch | Миттєвий dispatch (лише один запис у bucket) |
|
||||
| Текст + URL, надіслані як два навмисно окремі повідомлення з різницею в кілька хвилин | 2 webhooks поза вікном | Два ходи | Два ходи (вікно спливає між ними) |
|
||||
| Швидкий потік (>10 малих DM у межах вікна) | N webhooks | N ходів | Один хід, обмежений вихід (перший + найновіший, застосовано ліміти тексту/вкладень) |
|
||||
|
||||
### Усунення проблем з об’єднанням split-send
|
||||
|
||||
Якщо прапорець увімкнено, але split-send усе одно надходять як два ходи, перевірте кожен шар:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Конфігурація справді завантажена">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Потім `openclaw gateway restart` - прапорець зчитується під час створення debouncer-registry.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Вікно debounce достатньо широке для вашого налаштування">
|
||||
Подивіться журнал сервера BlueBubbles у `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Виміряйте проміжок між dispatch тексту в стилі `"Dump"` і наступним dispatch `"https://..."; Attachments:`. Збільште `messages.inbound.byChannel.bluebubbles`, щоб із запасом покрити цей проміжок.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Мітки часу Session JSONL ≠ надходження webhook">
|
||||
Мітки часу подій сесії (`~/.openclaw/agents/<id>/sessions/*.jsonl`) відображають, коли gateway передає повідомлення агенту, **а не** коли надійшов webhook. Друге повідомлення в черзі з тегом `[Queued messages while agent was busy]` означає, що перший хід усе ще виконувався, коли надійшов другий webhook - bucket об’єднання вже було flushed. Налаштовуйте вікно за журналом сервера BB, а не за журналом сесії.
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure сповільнює dispatch відповіді">
|
||||
На менших машинах (8 GB) ходи агента можуть тривати достатньо довго, щоб bucket об’єднання flushed до завершення відповіді, і URL потрапив як другий хід у черзі. Перевірте `memory_pressure` і `ps -o rss -p $(pgrep openclaw-gateway)`; якщо gateway має понад ~500 MB RSS і compressor активний, закрийте інші важкі процеси або перейдіть на більший хост.
|
||||
</Accordion>
|
||||
<Accordion title="Надсилання reply-quote йде іншим шляхом">
|
||||
Якщо користувач натиснув `Dump` як **reply** до наявної URL-бульбашки (iMessage показує значок "1 Reply" на бульбашці Dump), URL міститься в `replyToBody`, а не в другому webhook. Об’єднання не застосовується - це питання skill/prompt, а не debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Блокове streaming
|
||||
|
||||
Керуйте тим, чи відповіді надсилаються одним повідомленням, чи streamed блоками:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Медіа + ліміти
|
||||
|
||||
- Вхідні вкладення завантажуються й зберігаються в media cache.
|
||||
- Ліміт медіа через `channels.bluebubbles.mediaMaxMb` для вхідних і вихідних медіа (типово: 8 MB).
|
||||
- Вихідний текст ділиться на фрагменти за `channels.bluebubbles.textChunkLimit` (типово: 4000 символів).
|
||||
|
||||
## Довідник конфігурації
|
||||
|
||||
Повна конфігурація: [Конфігурація](/uk/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Підключення та Webhook">
|
||||
- `channels.bluebubbles.enabled`: Увімкнути/вимкнути канал.
|
||||
- `channels.bluebubbles.serverUrl`: Базова URL-адреса BlueBubbles REST API.
|
||||
- `channels.bluebubbles.password`: Пароль API.
|
||||
- `channels.bluebubbles.webhookPath`: Шлях кінцевої точки Webhook (типово: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Політика доступу">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (типово: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Список дозволених DM (handles, email-адреси, номери E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (типово: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Список дозволених відправників групи.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: У macOS можна додатково збагачувати неназваних учасників групи з локальних Contacts після проходження перевірок доступу. Типово: `false`.
|
||||
- `channels.bluebubbles.groups`: Конфігурація для кожної групи (`requireMention` тощо).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Доставка та розбиття на фрагменти">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Надсилати сповіщення про прочитання (типово: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Увімкнути блокове потокове передавання (типово: `false`; потрібно для потокових відповідей).
|
||||
- `channels.bluebubbles.textChunkLimit`: Розмір вихідного фрагмента в символах (типово: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Тайм-аут кожного запиту в мс для надсилання вихідного тексту через `/api/v1/message/text` (типово: 30000). Збільшуйте його в конфігураціях macOS 26, де надсилання iMessage через Private API може зависати на 60+ секунд усередині фреймворку iMessage; наприклад `45000` або `60000`. Зонди, пошук чатів, реакції, редагування та перевірки справності наразі зберігають коротше типове значення 10 с; розширення покриття на реакції та редагування заплановано як наступний крок. Перевизначення для окремого облікового запису: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (типово) розбиває лише за перевищення `textChunkLimit`; `newline` розбиває за порожніми рядками (межами абзаців) перед розбиттям за довжиною.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Медіа та історія">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Ліміт вхідних/вихідних медіа в МБ (типово: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Явний список дозволених абсолютних локальних каталогів, дозволених для шляхів вихідних локальних медіа. Надсилання локальних шляхів типово заборонене, якщо це не налаштовано. Перевизначення для окремого облікового запису: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Об’єднувати послідовні DM Webhook від одного відправника в один хід агента, щоб розділене надсилання тексту+URL від Apple надходило як одне повідомлення (типово: `false`). Див. [Об’єднання DM із розділеним надсиланням](#coalescing-split-send-dms-command--url-in-one-composition) для сценаріїв, налаштування вікна та компромісів. Розширює типове вікно debounce для вхідних повідомлень із 500 мс до 2500 мс, коли увімкнено без явного `messages.inbound.byChannel.bluebubbles`.
|
||||
- `channels.bluebubbles.historyLimit`: Максимальна кількість групових повідомлень для контексту (0 вимикає).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Ліміт історії DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Коли вхідна відповідь надходить без `replyToBody`/`replyToSender`, а кеш контексту відповіді в пам’яті не спрацьовує, отримати оригінальне повідомлення з BlueBubbles HTTP API як резервний варіант із найкращим зусиллям (типово: `false`). Корисно для розгортань із кількома екземплярами, що спільно використовують один обліковий запис BlueBubbles, після перезапусків процесу або після витіснення з довгоживучого кешу TTL/LRU. Отримання захищене від SSRF тією самою політикою, що й кожен інший клієнтський запит BlueBubbles, ніколи не викидає помилку та заповнює кеш, щоб наступні відповіді амортизували витрати. Перевизначення для окремого облікового запису: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Налаштування на рівні каналу поширюється на облікові записи, які не задають цей прапорець.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Дії та облікові записи">
|
||||
- `channels.bluebubbles.actions`: Увімкнути/вимкнути певні дії.
|
||||
- `channels.bluebubbles.accounts`: Конфігурація кількох облікових записів.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Пов’язані глобальні параметри:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (або `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Адресація / цілі доставки
|
||||
|
||||
Надавайте перевагу `chat_guid` для стабільної маршрутизації:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (бажано для груп)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Прямі handles: `+15555550123`, `user@example.com`
|
||||
- Якщо прямий handle не має наявного DM-чату, OpenClaw створить його через `POST /api/v1/chat/new`. Для цього потрібно ввімкнути BlueBubbles Private API.
|
||||
|
||||
### Маршрутизація iMessage і SMS
|
||||
|
||||
Коли той самий handle має і чат iMessage, і чат SMS на Mac (наприклад, номер телефону, зареєстрований в iMessage, але який також отримував резервні зелені SMS), OpenClaw надає перевагу чату iMessage і ніколи непомітно не понижує доставку до SMS. Щоб примусово використати чат SMS, застосуйте явний префікс цілі `sms:` (наприклад `sms:+15555550123`). Handles без відповідного чату iMessage усе одно надсилаються через будь-який чат, який повідомляє BlueBubbles.
|
||||
|
||||
## Безпека
|
||||
|
||||
- Запити Webhook автентифікуються порівнянням query-параметрів або заголовків `guid`/`password` із `channels.bluebubbles.password`.
|
||||
- Тримайте пароль API і кінцеву точку Webhook у секреті (ставтеся до них як до облікових даних).
|
||||
- Для автентифікації Webhook BlueBubbles немає обходу через localhost. Якщо ви проксіюєте трафік Webhook, зберігайте пароль BlueBubbles у запиті від початку до кінця. `gateway.trustedProxies` тут не замінює `channels.bluebubbles.password`. Див. [Безпека Gateway](/uk/gateway/security#reverse-proxy-configuration).
|
||||
- Увімкніть HTTPS + правила брандмауера на сервері BlueBubbles, якщо відкриваєте його за межі своєї LAN.
|
||||
|
||||
## Усунення несправностей
|
||||
|
||||
- Якщо події введення/прочитання перестали працювати, перевірте журнали Webhook BlueBubbles і переконайтеся, що шлях Gateway відповідає `channels.bluebubbles.webhookPath`.
|
||||
- Коди спарювання спливають через одну годину; використовуйте `openclaw pairing list bluebubbles` і `openclaw pairing approve bluebubbles <code>`.
|
||||
- Реакції потребують приватного API BlueBubbles (`POST /api/v1/message/react`); переконайтеся, що версія сервера його надає.
|
||||
- Редагування/скасування надсилання потребує macOS 13+ і сумісної версії сервера BlueBubbles. У macOS 26 (Tahoe) редагування наразі зламане через зміни приватного API.
|
||||
- Оновлення піктограм груп можуть бути нестабільними в macOS 26 (Tahoe): API може повернути успіх, але нова піктограма не синхронізується.
|
||||
- OpenClaw автоматично приховує відомо зламані дії на основі версії macOS сервера BlueBubbles. Якщо редагування все ще відображається в macOS 26 (Tahoe), вимкніть його вручну через `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` увімкнено, але розділені надсилання (наприклад `Dump` + URL) усе ще надходять як два ходи: див. контрольний список [усунення несправностей об’єднання розділених надсилань](#split-send-coalescing-troubleshooting) - поширені причини: занадто вузьке вікно debounce, часові позначки журналу сеансу помилково сприйняті як надходження Webhook або надсилання цитати-відповіді (яке використовує `replyToBody`, а не другий Webhook).
|
||||
- Для інформації про стан/справність: `openclaw status --all` або `openclaw status --deep`.
|
||||
|
||||
Загальну довідку щодо робочого процесу каналів див. у [Канали](/uk/channels) та посібнику [Plugins](/uk/tools/plugin).
|
||||
|
||||
## Пов’язане
|
||||
|
||||
- [Маршрутизація каналів](/uk/channels/channel-routing) - маршрутизація сеансів для повідомлень
|
||||
- [Огляд каналів](/uk/channels) - усі підтримувані канали
|
||||
- [Групи](/uk/channels/groups) - поведінка групових чатів і фільтрація за згадками
|
||||
- [Спарювання](/uk/channels/pairing) - автентифікація DM і потік спарювання
|
||||
- [Безпека](/uk/gateway/security) - модель доступу та посилення захисту
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Ви встановлюєте, налаштовуєте або виконуєте аудит Plugin bluebubbles
|
||||
summary: Додає поверхню каналу BlueBubbles для надсилання й отримання повідомлень OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T02:48:48Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Додає поверхню каналу BlueBubbles для надсилання та отримання повідомлень OpenClaw.
|
||||
|
||||
## Розповсюдження
|
||||
|
||||
- Пакет: `@openclaw/bluebubbles`
|
||||
- Маршрут встановлення: npm; ClawHub
|
||||
|
||||
## Поверхня
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Пов’язана документація
|
||||
|
||||
- [bluebubbles](/uk/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Thiết lập kênh BlueBubbles
|
||||
- Khắc phục sự cố ghép nối Webhook
|
||||
- Cấu hình iMessage trên macOS
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: Hỗ trợ iMessage cũ thông qua máy chủ macOS BlueBubbles (gửi/nhận qua REST, trạng thái đang nhập, phản ứng, ghép đôi, hành động nâng cao).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:51Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Trạng thái: plugin kế thừa được đóng gói sẵn giao tiếp với máy chủ BlueBubbles trên macOS qua HTTP. Các thiết lập BlueBubbles hiện có vẫn tiếp tục hoạt động, nhưng các triển khai OpenClaw iMessage mới nên ưu tiên plugin [iMessage](/vi/channels/imessage) gốc khi các yêu cầu của plugin này phù hợp với máy chủ của bạn.
|
||||
|
||||
<Warning>
|
||||
BlueBubbles không còn được khuyến nghị cho các thiết lập OpenClaw mới.
|
||||
|
||||
Hệ sinh thái BlueBubbles upstream vẫn đang hoạt động, nhưng OpenClaw phụ thuộc vào API máy chủ BlueBubbles trên macOS. Tính đến ngày 6 tháng 5 năm 2026, nhánh phát triển chính thức [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) thay đổi lần cuối vào [ngày 22 tháng 1 năm 2026](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037), và bản phát hành máy chủ mới nhất ([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9)) được phát hành vào ngày 16 tháng 5 năm 2025. Ứng dụng khách và các kho trợ giúp có hoạt động mới hơn, vì vậy đây không phải là tuyên bố dự án bị bỏ rơi; việc ngừng khuyến nghị nhằm giảm sự phụ thuộc của OpenClaw vào một máy chủ HTTP bên ngoài, webhooks, và bề mặt tương thích private-API khi đường dẫn `imsg` gốc giữ tích hợp trên một hợp đồng stdio cục bộ.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
Các bản phát hành OpenClaw hiện tại đóng gói sẵn BlueBubbles, vì vậy các bản dựng đóng gói thông thường không cần bước `openclaw plugins install` riêng.
|
||||
</Note>
|
||||
|
||||
## Tổng quan
|
||||
|
||||
- Chạy trên macOS thông qua ứng dụng trợ giúp BlueBubbles ([bluebubbles.app](https://bluebubbles.app)).
|
||||
- Phương án dự phòng kế thừa cho các bản cài đặt đã phụ thuộc vào ID kênh BlueBubbles, trạng thái webhook, mục tiêu nhóm, phân phối cron, hoặc định tuyến workspace.
|
||||
- Được khuyến nghị/đã kiểm thử: macOS Sequoia (15). macOS Tahoe (26) hoạt động; chỉnh sửa hiện đang bị lỗi trên Tahoe, và cập nhật biểu tượng nhóm có thể báo thành công nhưng không đồng bộ.
|
||||
- OpenClaw giao tiếp với nó thông qua REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`).
|
||||
- Tin nhắn đến đi qua webhooks; phản hồi gửi đi, chỉ báo đang nhập, xác nhận đã đọc, và tapbacks là các lệnh gọi REST.
|
||||
- Tệp đính kèm và nhãn dán được nạp dưới dạng phương tiện đầu vào (và được hiển thị cho agent khi có thể).
|
||||
- Phản hồi Auto-TTS tổng hợp âm thanh MP3 hoặc CAF được gửi dưới dạng bong bóng ghi âm iMessage thay vì tệp đính kèm thông thường.
|
||||
- Cơ chế ghép đôi/danh sách cho phép hoạt động giống các kênh khác (`/channels/pairing` v.v.) với `channels.bluebubbles.allowFrom` + mã ghép đôi.
|
||||
- Reactions được hiển thị dưới dạng sự kiện hệ thống giống như Slack/Telegram để agents có thể "nhắc đến" chúng trước khi trả lời.
|
||||
- Tính năng nâng cao: chỉnh sửa, thu hồi gửi, luồng trả lời, hiệu ứng tin nhắn, quản lý nhóm.
|
||||
|
||||
## Bắt đầu nhanh
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
Cài đặt máy chủ BlueBubbles trên máy Mac của bạn (làm theo hướng dẫn tại [bluebubbles.app/install](https://bluebubbles.app/install)).
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
Trong cấu hình BlueBubbles, bật web API và đặt mật khẩu.
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
Chạy `openclaw onboard` và chọn BlueBubbles, hoặc cấu hình thủ công:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
Trỏ webhooks của BlueBubbles tới Gateway của bạn (ví dụ: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
Khởi động Gateway; nó sẽ đăng ký trình xử lý webhook và bắt đầu ghép đôi.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Bảo mật**
|
||||
|
||||
- Luôn đặt mật khẩu webhook.
|
||||
- Xác thực webhook luôn bắt buộc. OpenClaw từ chối các yêu cầu webhook BlueBubbles trừ khi chúng bao gồm mật khẩu/guid khớp với `channels.bluebubbles.password` (ví dụ `?password=<password>` hoặc `x-password`), bất kể cấu trúc local loopback/proxy.
|
||||
- Xác thực mật khẩu được kiểm tra trước khi đọc/phân tích toàn bộ thân webhook.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Giữ Messages.app hoạt động (thiết lập VM / headless)
|
||||
|
||||
Một số thiết lập VM macOS / luôn bật có thể khiến Messages.app chuyển sang trạng thái "nhàn rỗi" (sự kiện đến dừng lại cho đến khi ứng dụng được mở/đưa lên trước). Cách khắc phục đơn giản là **đánh thức Messages mỗi 5 phút** bằng AppleScript + LaunchAgent.
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
Lưu nội dung này dưới dạng `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
Lưu nội dung này dưới dạng `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Thao tác này chạy **mỗi 300 giây** và **khi đăng nhập**. Lần chạy đầu tiên có thể kích hoạt lời nhắc **Automation** của macOS (`osascript` → Messages). Phê duyệt chúng trong cùng phiên người dùng chạy LaunchAgent.
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles có trong quy trình onboarding tương tác:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Trình hướng dẫn yêu cầu:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
Địa chỉ máy chủ BlueBubbles (ví dụ: `http://192.168.1.100:1234`).
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
Mật khẩu API từ phần cài đặt BlueBubbles Server.
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Đường dẫn endpoint webhook.
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`, `allowlist`, `open`, hoặc `disabled`.
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
Số điện thoại, email, hoặc mục tiêu chat.
|
||||
</ParamField>
|
||||
|
||||
Bạn cũng có thể thêm BlueBubbles qua CLI:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## Kiểm soát truy cập (DMs + nhóm)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- Mặc định: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- Người gửi không xác định nhận mã ghép đôi; tin nhắn bị bỏ qua cho đến khi được phê duyệt (mã hết hạn sau 1 giờ).
|
||||
- Phê duyệt qua:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Ghép đôi là cơ chế trao đổi token mặc định. Chi tiết: [Ghép đôi](/vi/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (mặc định: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom` kiểm soát ai có thể kích hoạt trong nhóm khi `allowlist` được đặt.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Bổ sung tên liên hệ (macOS, tùy chọn)
|
||||
|
||||
Webhooks nhóm của BlueBubbles thường chỉ bao gồm địa chỉ người tham gia thô. Nếu bạn muốn ngữ cảnh `GroupMembers` hiển thị tên liên hệ cục bộ thay vào đó, bạn có thể chọn bật bổ sung từ Contacts cục bộ trên macOS:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` bật tra cứu. Mặc định: `false`.
|
||||
- Tra cứu chỉ chạy sau khi quyền truy cập nhóm, ủy quyền lệnh, và chặn theo nhắc đến đã cho phép tin nhắn đi qua.
|
||||
- Chỉ người tham gia bằng số điện thoại chưa có tên mới được bổ sung.
|
||||
- Số điện thoại thô vẫn là phương án dự phòng khi không tìm thấy khớp cục bộ.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Chặn theo nhắc đến (nhóm)
|
||||
|
||||
BlueBubbles hỗ trợ chặn theo nhắc đến cho chat nhóm, khớp với hành vi iMessage/WhatsApp:
|
||||
|
||||
- Dùng `agents.list[].groupChat.mentionPatterns` (hoặc `messages.groupChat.mentionPatterns`) để phát hiện nhắc đến.
|
||||
- Khi `requireMention` được bật cho một nhóm, agent chỉ phản hồi khi được nhắc đến.
|
||||
- Lệnh điều khiển từ người gửi được ủy quyền bỏ qua chặn theo nhắc đến.
|
||||
|
||||
Cấu hình theo nhóm:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Chặn lệnh
|
||||
|
||||
- Lệnh điều khiển (ví dụ: `/config`, `/model`) yêu cầu ủy quyền.
|
||||
- Dùng `allowFrom` và `groupAllowFrom` để xác định ủy quyền lệnh.
|
||||
- Người gửi được ủy quyền có thể chạy lệnh điều khiển ngay cả khi không nhắc đến trong nhóm.
|
||||
|
||||
### System prompt theo nhóm
|
||||
|
||||
Mỗi mục dưới `channels.bluebubbles.groups.*` chấp nhận chuỗi `systemPrompt` tùy chọn. Giá trị này được đưa vào system prompt của agent ở mỗi lượt xử lý tin nhắn trong nhóm đó, vì vậy bạn có thể đặt persona hoặc quy tắc hành vi theo nhóm mà không cần chỉnh sửa prompt của agent:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Khóa khớp với bất cứ gì BlueBubbles báo cáo là `chatGuid` / `chatIdentifier` / `chatId` dạng số cho nhóm, và mục wildcard `"*"` cung cấp mặc định cho mọi nhóm không có khớp chính xác (cùng mẫu được dùng bởi `requireMention` và chính sách công cụ theo nhóm). Khớp chính xác luôn thắng wildcard. DMs bỏ qua trường này; hãy dùng tùy chỉnh prompt ở cấp agent hoặc cấp tài khoản thay vào đó.
|
||||
|
||||
#### Ví dụ hoàn chỉnh: trả lời theo luồng và phản ứng tapback (Private API)
|
||||
|
||||
Khi bật BlueBubbles Private API, tin nhắn đầu vào đi kèm ID tin nhắn ngắn (ví dụ `[[reply_to:5]]`) và agent có thể gọi `action=reply` để trả lời theo luồng vào một tin nhắn cụ thể hoặc `action=react` để thả một tapback. `systemPrompt` theo nhóm là cách đáng tin cậy để giữ agent chọn đúng công cụ:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Phản ứng tapback và trả lời theo luồng đều yêu cầu BlueBubbles Private API; xem [Hành động nâng cao](#advanced-actions) và [ID tin nhắn](#message-ids-short-vs-full) để biết cơ chế nền tảng.
|
||||
|
||||
## Liên kết cuộc trò chuyện ACP
|
||||
|
||||
Chat BlueBubbles có thể được chuyển thành workspace ACP bền vững mà không thay đổi lớp truyền tải.
|
||||
|
||||
Luồng thao tác nhanh:
|
||||
|
||||
- Chạy `/acp spawn codex --bind here` bên trong DM hoặc chat nhóm được phép.
|
||||
- Các tin nhắn sau này trong cùng cuộc trò chuyện BlueBubbles đó sẽ định tuyến tới phiên ACP đã tạo.
|
||||
- `/new` và `/reset` đặt lại cùng phiên ACP đã liên kết tại chỗ.
|
||||
- `/acp close` đóng phiên ACP và xóa liên kết.
|
||||
|
||||
Liên kết liên tục được cấu hình cũng được hỗ trợ thông qua các mục `bindings[]` cấp cao nhất với `type: "acp"` và `match.channel: "bluebubbles"`.
|
||||
|
||||
`match.peer.id` có thể dùng bất kỳ dạng mục tiêu BlueBubbles nào được hỗ trợ:
|
||||
|
||||
- handle DM đã chuẩn hóa như `+15555550123` hoặc `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
Để có các liên kết nhóm ổn định, ưu tiên `chat_id:*` hoặc `chat_identifier:*`.
|
||||
|
||||
Ví dụ:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Xem [Tác nhân ACP](/vi/tools/acp-agents) để biết hành vi liên kết ACP dùng chung.
|
||||
|
||||
## Đang nhập + biên nhận đã đọc
|
||||
|
||||
- **Chỉ báo đang nhập**: Được gửi tự động trước và trong khi tạo phản hồi.
|
||||
- **Biên nhận đã đọc**: Được kiểm soát bởi `channels.bluebubbles.sendReadReceipts` (mặc định: `true`).
|
||||
- **Chỉ báo đang nhập**: OpenClaw gửi sự kiện bắt đầu nhập; BlueBubbles tự động xóa trạng thái đang nhập khi gửi hoặc hết thời gian chờ (dừng thủ công qua DELETE không đáng tin cậy).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Hành động nâng cao
|
||||
|
||||
BlueBubbles hỗ trợ các hành động tin nhắn nâng cao khi được bật trong cấu hình:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Các hành động có sẵn">
|
||||
- **react**: Thêm/xóa phản ứng tapback (`messageId`, `emoji`, `remove`). Bộ tapback gốc của iMessage là `love`, `like`, `dislike`, `laugh`, `emphasize` và `question`. Khi tác nhân chọn một emoji ngoài bộ đó (ví dụ `👀`), công cụ phản ứng sẽ chuyển về `love` để tapback vẫn hiển thị thay vì làm hỏng toàn bộ yêu cầu. Các phản ứng xác nhận đã cấu hình vẫn được xác thực nghiêm ngặt và báo lỗi với giá trị không xác định.
|
||||
- **edit**: Sửa một tin nhắn đã gửi (`messageId`, `text`).
|
||||
- **unsend**: Thu hồi một tin nhắn (`messageId`).
|
||||
- **reply**: Trả lời một tin nhắn cụ thể (`messageId`, `text`, `to`).
|
||||
- **sendWithEffect**: Gửi với hiệu ứng iMessage (`text`, `to`, `effectId`).
|
||||
- **renameGroup**: Đổi tên một cuộc trò chuyện nhóm (`chatGuid`, `displayName`).
|
||||
- **setGroupIcon**: Đặt biểu tượng/ảnh của cuộc trò chuyện nhóm (`chatGuid`, `media`) - không ổn định trên macOS 26 Tahoe (API có thể trả về thành công nhưng biểu tượng không đồng bộ).
|
||||
- **addParticipant**: Thêm ai đó vào một nhóm (`chatGuid`, `address`).
|
||||
- **removeParticipant**: Xóa ai đó khỏi một nhóm (`chatGuid`, `address`).
|
||||
- **leaveGroup**: Rời một cuộc trò chuyện nhóm (`chatGuid`).
|
||||
- **upload-file**: Gửi phương tiện/tệp (`to`, `buffer`, `filename`, `asVoice`).
|
||||
- Ghi âm thoại: đặt `asVoice: true` với âm thanh **MP3** hoặc **CAF** để gửi dưới dạng tin nhắn thoại iMessage. BlueBubbles chuyển đổi MP3 → CAF khi gửi ghi âm thoại.
|
||||
- Bí danh cũ: `sendAttachment` vẫn hoạt động, nhưng `upload-file` là tên hành động chuẩn.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### ID tin nhắn (ngắn so với đầy đủ)
|
||||
|
||||
OpenClaw có thể hiển thị ID tin nhắn _ngắn_ (ví dụ `1`, `2`) để tiết kiệm token.
|
||||
|
||||
- `MessageSid` / `ReplyToId` có thể là ID ngắn.
|
||||
- `MessageSidFull` / `ReplyToIdFull` chứa ID đầy đủ của nhà cung cấp.
|
||||
- ID ngắn nằm trong bộ nhớ; chúng có thể hết hạn khi khởi động lại hoặc khi bộ nhớ đệm bị loại bỏ.
|
||||
- Các hành động chấp nhận `messageId` ngắn hoặc đầy đủ, nhưng ID ngắn sẽ báo lỗi nếu không còn khả dụng.
|
||||
|
||||
Dùng ID đầy đủ cho tự động hóa và lưu trữ bền vững:
|
||||
|
||||
- Mẫu: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- Ngữ cảnh: `MessageSidFull` / `ReplyToIdFull` trong payload đến
|
||||
|
||||
Xem [Cấu hình](/vi/gateway/configuration) để biết các biến mẫu.
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## Gộp các DM gửi tách (lệnh + URL trong một lần soạn)
|
||||
|
||||
Khi người dùng nhập cùng lúc một lệnh và một URL trong iMessage - ví dụ `Dump https://example.com/article` - Apple tách lần gửi thành **hai lần gửi webhook riêng biệt**:
|
||||
|
||||
1. Một tin nhắn văn bản (`"Dump"`).
|
||||
2. Một bong bóng xem trước URL (`"https://..."`) với ảnh xem trước OG dưới dạng tệp đính kèm.
|
||||
|
||||
Hai webhook đến OpenClaw cách nhau khoảng 0,8-2,0 giây trên hầu hết thiết lập. Nếu không gộp, tác nhân nhận riêng lệnh ở lượt 1, trả lời (thường là "gửi tôi URL"), và chỉ thấy URL ở lượt 2 - lúc đó ngữ cảnh lệnh đã bị mất.
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` chọn một DM để gộp các webhook liên tiếp từ cùng người gửi thành một lượt tác nhân duy nhất. Trò chuyện nhóm vẫn khóa theo từng tin nhắn để giữ nguyên cấu trúc lượt nhiều người dùng.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Khi nào bật">
|
||||
Bật khi:
|
||||
|
||||
- Bạn cung cấp skills cần `command + payload` trong một tin nhắn (dump, paste, save, queue, v.v.).
|
||||
- Người dùng của bạn dán URL, hình ảnh hoặc nội dung dài kèm theo lệnh.
|
||||
- Bạn có thể chấp nhận độ trễ lượt DM tăng thêm (xem bên dưới).
|
||||
|
||||
Để tắt khi:
|
||||
|
||||
- Bạn cần độ trễ lệnh tối thiểu cho các kích hoạt DM một từ.
|
||||
- Tất cả luồng của bạn là lệnh một lần, không có payload theo sau.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Bật">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Khi bật cờ này và không có `messages.inbound.byChannel.bluebubbles` rõ ràng, cửa sổ debounce mở rộng thành **2500 ms** (mặc định cho trường hợp không gộp là 500 ms). Cửa sổ rộng hơn là bắt buộc - nhịp gửi tách của Apple 0,8-2,0 giây không vừa với mặc định chặt hơn.
|
||||
|
||||
Để tự điều chỉnh cửa sổ:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Đánh đổi">
|
||||
- **Độ trễ tăng thêm cho các lệnh điều khiển DM.** Khi bật cờ này, tin nhắn lệnh điều khiển DM (như `Dump`, `Save`, v.v.) hiện sẽ chờ tới cửa sổ debounce trước khi điều phối, phòng trường hợp một webhook payload đang đến. Lệnh trong trò chuyện nhóm vẫn được điều phối tức thì.
|
||||
- **Đầu ra đã gộp có giới hạn** - văn bản đã gộp bị giới hạn ở 4000 ký tự với dấu `…[truncated]` rõ ràng; tệp đính kèm bị giới hạn ở 20; mục nguồn bị giới hạn ở 10 (giữ lại mục đầu tiên cộng với các mục mới nhất sau giới hạn đó). Mỗi `messageId` nguồn vẫn đi tới bước chống trùng lặp đầu vào, nên lần phát lại MessagePoller sau này của bất kỳ sự kiện riêng lẻ nào cũng được nhận diện là trùng lặp.
|
||||
- **Chọn bật, theo từng kênh.** Các kênh khác (Telegram, WhatsApp, Slack, …) không bị ảnh hưởng.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Tình huống và những gì tác nhân thấy
|
||||
|
||||
| Người dùng soạn | Apple gửi | Tắt cờ (mặc định) | Bật cờ + cửa sổ 2500 ms |
|
||||
| ------------------------------------------------------------------ | ------------------------- | ------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com` (một lần gửi) | 2 webhook cách nhau ~1 giây | Hai lượt tác nhân: chỉ "Dump", rồi URL | Một lượt: văn bản đã gộp `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption` (tệp đính kèm + văn bản) | 2 webhook | Hai lượt | Một lượt: văn bản + hình ảnh |
|
||||
| `/status` (lệnh độc lập) | 1 webhook | Điều phối tức thì | **Chờ tới cửa sổ, rồi điều phối** |
|
||||
| Chỉ dán URL | 1 webhook | Điều phối tức thì | Điều phối tức thì (chỉ một mục trong bucket) |
|
||||
| Văn bản + URL được gửi thành hai tin nhắn riêng có chủ ý, cách nhau vài phút | 2 webhook ngoài cửa sổ | Hai lượt | Hai lượt (cửa sổ hết hạn giữa chúng) |
|
||||
| Gửi dồn nhanh (>10 DM nhỏ trong cửa sổ) | N webhook | N lượt | Một lượt, đầu ra có giới hạn (áp dụng giới hạn đầu + mới nhất, văn bản/tệp đính kèm) |
|
||||
|
||||
### Khắc phục sự cố gộp gửi tách
|
||||
|
||||
Nếu cờ đã bật nhưng các lần gửi tách vẫn đến thành hai lượt, hãy kiểm tra từng lớp:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Cấu hình thực sự đã tải">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
Sau đó `openclaw gateway restart` - cờ được đọc khi tạo debouncer-registry.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Cửa sổ debounce đủ rộng cho thiết lập của bạn">
|
||||
Xem nhật ký máy chủ BlueBubbles tại `~/Library/Logs/bluebubbles-server/main.log`:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
Đo khoảng cách giữa lần điều phối văn bản kiểu `"Dump"` và lần điều phối `"https://..."; Attachments:` theo sau. Tăng `messages.inbound.byChannel.bluebubbles` để bao phủ thoải mái khoảng cách đó.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Dấu thời gian JSONL phiên ≠ thời điểm webhook đến">
|
||||
Dấu thời gian sự kiện phiên (`~/.openclaw/agents/<id>/sessions/*.jsonl`) phản ánh lúc Gateway chuyển một tin nhắn cho tác nhân, **không phải** lúc webhook đến. Tin nhắn thứ hai trong hàng đợi được gắn `[Queued messages while agent was busy]` nghĩa là lượt đầu tiên vẫn đang chạy khi webhook thứ hai đến - bucket gộp đã được xả. Điều chỉnh cửa sổ theo nhật ký máy chủ BB, không phải nhật ký phiên.
|
||||
</Accordion>
|
||||
<Accordion title="Áp lực bộ nhớ làm chậm điều phối trả lời">
|
||||
Trên máy nhỏ hơn (8 GB), các lượt tác nhân có thể mất đủ lâu để bucket gộp xả trước khi phản hồi hoàn tất, và URL rơi vào một lượt thứ hai trong hàng đợi. Kiểm tra `memory_pressure` và `ps -o rss -p $(pgrep openclaw-gateway)`; nếu Gateway vượt quá ~500 MB RSS và bộ nén đang hoạt động, hãy đóng các tiến trình nặng khác hoặc chuyển sang máy chủ lớn hơn.
|
||||
</Accordion>
|
||||
<Accordion title="Lần gửi trích dẫn trả lời là một đường đi khác">
|
||||
Nếu người dùng chạm vào `Dump` dưới dạng **trả lời** một bong bóng URL hiện có (iMessage hiển thị huy hiệu "1 Reply" trên bong bóng Dump), URL nằm trong `replyToBody`, không nằm trong webhook thứ hai. Việc gộp không áp dụng - đó là vấn đề skill/prompt, không phải vấn đề debouncer.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Truyền phát theo khối
|
||||
|
||||
Kiểm soát việc phản hồi được gửi dưới dạng một tin nhắn duy nhất hay được truyền phát theo các khối:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Phương tiện + giới hạn
|
||||
|
||||
- Tệp đính kèm đầu vào được tải xuống và lưu trong bộ nhớ đệm phương tiện.
|
||||
- Giới hạn phương tiện qua `channels.bluebubbles.mediaMaxMb` cho phương tiện đầu vào và đầu ra (mặc định: 8 MB).
|
||||
- Văn bản đầu ra được chia nhỏ theo `channels.bluebubbles.textChunkLimit` (mặc định: 4000 ký tự).
|
||||
|
||||
## Tham chiếu cấu hình
|
||||
|
||||
Cấu hình đầy đủ: [Cấu hình](/vi/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Kết nối và Webhook">
|
||||
- `channels.bluebubbles.enabled`: Bật/tắt kênh.
|
||||
- `channels.bluebubbles.serverUrl`: URL cơ sở của BlueBubbles REST API.
|
||||
- `channels.bluebubbles.password`: Mật khẩu API.
|
||||
- `channels.bluebubbles.webhookPath`: Đường dẫn điểm cuối Webhook (mặc định: `/bluebubbles-webhook`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Chính sách truy cập">
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (mặc định: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: Danh sách cho phép DM (handle, email, số E.164, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (mặc định: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: Danh sách cho phép người gửi trong nhóm.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: Trên macOS, tùy chọn bổ sung thông tin cho người tham gia nhóm chưa có tên từ Contacts cục bộ sau khi vượt qua kiểm soát truy cập. Mặc định: `false`.
|
||||
- `channels.bluebubbles.groups`: Cấu hình theo từng nhóm (`requireMention`, v.v.).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Phân phối và chia đoạn">
|
||||
- `channels.bluebubbles.sendReadReceipts`: Gửi xác nhận đã đọc (mặc định: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: Bật truyền trực tuyến theo khối (mặc định: `false`; bắt buộc để trả lời dạng streaming).
|
||||
- `channels.bluebubbles.textChunkLimit`: Kích thước đoạn gửi đi tính bằng ký tự (mặc định: 4000).
|
||||
- `channels.bluebubbles.sendTimeoutMs`: Thời gian chờ theo từng yêu cầu tính bằng ms cho việc gửi văn bản đi qua `/api/v1/message/text` (mặc định: 30000). Tăng giá trị này trên các thiết lập macOS 26 nơi việc gửi iMessage bằng Private API có thể bị kẹt hơn 60 giây bên trong framework iMessage; ví dụ `45000` hoặc `60000`. Các phép thăm dò, tra cứu cuộc trò chuyện, phản ứng, chỉnh sửa và kiểm tra tình trạng hiện vẫn giữ mặc định 10 giây ngắn hơn; việc mở rộng phạm vi sang phản ứng và chỉnh sửa được lên kế hoạch cho bước tiếp theo. Ghi đè theo tài khoản: `channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`.
|
||||
- `channels.bluebubbles.chunkMode`: `length` (mặc định) chỉ tách khi vượt quá `textChunkLimit`; `newline` tách theo dòng trống (ranh giới đoạn văn) trước khi chia đoạn theo độ dài.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Phương tiện và lịch sử">
|
||||
- `channels.bluebubbles.mediaMaxMb`: Giới hạn phương tiện vào/ra tính bằng MB (mặc định: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: Danh sách cho phép rõ ràng các thư mục cục bộ tuyệt đối được phép dùng cho đường dẫn phương tiện cục bộ gửi đi. Gửi bằng đường dẫn cục bộ bị từ chối theo mặc định trừ khi mục này được cấu hình. Ghi đè theo tài khoản: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`: Gộp các Webhook DM liên tiếp từ cùng một người gửi thành một lượt của agent để thao tác gửi tách văn bản+URL của Apple đến dưới dạng một tin nhắn duy nhất (mặc định: `false`). Xem [Gộp các DM gửi tách](#coalescing-split-send-dms-command--url-in-one-composition) để biết các kịch bản, tinh chỉnh cửa sổ và đánh đổi. Khi bật mà không có `messages.inbound.byChannel.bluebubbles` rõ ràng, mở rộng cửa sổ debounce mặc định cho tin nhắn đến từ 500 ms lên 2500 ms.
|
||||
- `channels.bluebubbles.historyLimit`: Số tin nhắn nhóm tối đa cho ngữ cảnh (0 để tắt).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: Giới hạn lịch sử DM.
|
||||
- `channels.bluebubbles.replyContextApiFallback`: Khi một trả lời đến không có `replyToBody`/`replyToSender` và bộ đệm ngữ cảnh trả lời trong bộ nhớ bị miss, tìm nạp tin nhắn gốc từ BlueBubbles HTTP API như một phương án dự phòng nỗ lực tối đa (mặc định: `false`). Hữu ích cho triển khai nhiều phiên bản dùng chung một tài khoản BlueBubbles, sau khi tiến trình khởi động lại, hoặc sau khi mục trong bộ đệm TTL/LRU tồn tại lâu bị loại bỏ. Lần tìm nạp này được bảo vệ SSRF bằng cùng chính sách như mọi yêu cầu client BlueBubbles khác, không bao giờ throw và điền vào bộ đệm để các trả lời tiếp theo được phân bổ chi phí. Ghi đè theo tài khoản: `channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`. Thiết lập cấp kênh được truyền sang các tài khoản không đặt cờ này.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Hành động và tài khoản">
|
||||
- `channels.bluebubbles.actions`: Bật/tắt các hành động cụ thể.
|
||||
- `channels.bluebubbles.accounts`: Cấu hình nhiều tài khoản.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Các tùy chọn toàn cục liên quan:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (hoặc `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## Địa chỉ hóa / mục tiêu phân phối
|
||||
|
||||
Ưu tiên `chat_guid` để định tuyến ổn định:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (ưu tiên cho nhóm)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- Handle trực tiếp: `+15555550123`, `user@example.com`
|
||||
- Nếu một handle trực tiếp chưa có cuộc trò chuyện DM hiện có, OpenClaw sẽ tạo một cuộc trò chuyện qua `POST /api/v1/chat/new`. Việc này yêu cầu bật BlueBubbles Private API.
|
||||
|
||||
### Định tuyến iMessage so với SMS
|
||||
|
||||
Khi cùng một handle có cả cuộc trò chuyện iMessage và SMS trên Mac (ví dụ một số điện thoại đã đăng ký iMessage nhưng cũng đã nhận các dự phòng bong bóng xanh), OpenClaw ưu tiên cuộc trò chuyện iMessage và không bao giờ âm thầm hạ cấp xuống SMS. Để buộc dùng cuộc trò chuyện SMS, hãy dùng tiền tố mục tiêu `sms:` rõ ràng (ví dụ `sms:+15555550123`). Các handle không có cuộc trò chuyện iMessage khớp vẫn sẽ gửi qua bất kỳ cuộc trò chuyện nào BlueBubbles báo cáo.
|
||||
|
||||
## Bảo mật
|
||||
|
||||
- Các yêu cầu Webhook được xác thực bằng cách so sánh tham số truy vấn hoặc header `guid`/`password` với `channels.bluebubbles.password`.
|
||||
- Giữ bí mật mật khẩu API và điểm cuối Webhook (xem chúng như thông tin xác thực).
|
||||
- Không có cơ chế bỏ qua xác thực BlueBubbles Webhook cho localhost. Nếu bạn proxy lưu lượng Webhook, hãy giữ mật khẩu BlueBubbles trên yêu cầu từ đầu đến cuối. `gateway.trustedProxies` không thay thế `channels.bluebubbles.password` ở đây. Xem [Bảo mật Gateway](/vi/gateway/security#reverse-proxy-configuration).
|
||||
- Bật HTTPS + quy tắc tường lửa trên máy chủ BlueBubbles nếu để lộ nó ra ngoài LAN.
|
||||
|
||||
## Khắc phục sự cố
|
||||
|
||||
- Nếu sự kiện nhập/xác nhận đọc ngừng hoạt động, hãy kiểm tra nhật ký Webhook của BlueBubbles và xác minh đường dẫn gateway khớp với `channels.bluebubbles.webhookPath`.
|
||||
- Mã ghép đôi hết hạn sau một giờ; dùng `openclaw pairing list bluebubbles` và `openclaw pairing approve bluebubbles <code>`.
|
||||
- Phản ứng yêu cầu BlueBubbles private API (`POST /api/v1/message/react`); hãy đảm bảo phiên bản máy chủ cung cấp API này.
|
||||
- Chỉnh sửa/thu hồi yêu cầu macOS 13+ và phiên bản máy chủ BlueBubbles tương thích. Trên macOS 26 (Tahoe), chỉnh sửa hiện bị hỏng do các thay đổi trong private API.
|
||||
- Cập nhật biểu tượng nhóm có thể không ổn định trên macOS 26 (Tahoe): API có thể trả về thành công nhưng biểu tượng mới không đồng bộ.
|
||||
- OpenClaw tự động ẩn các hành động đã biết là bị hỏng dựa trên phiên bản macOS của máy chủ BlueBubbles. Nếu chỉnh sửa vẫn xuất hiện trên macOS 26 (Tahoe), hãy tắt thủ công bằng `channels.bluebubbles.actions.edit=false`.
|
||||
- `coalesceSameSenderDms` đã bật nhưng các lượt gửi tách (ví dụ `Dump` + URL) vẫn đến thành hai lượt: xem danh sách kiểm tra [khắc phục sự cố gộp lượt gửi tách](#split-send-coalescing-troubleshooting) - nguyên nhân phổ biến là cửa sổ debounce quá chặt, dấu thời gian nhật ký phiên bị đọc nhầm là thời điểm Webhook đến, hoặc một lần gửi trích dẫn trả lời (dùng `replyToBody`, không phải Webhook thứ hai).
|
||||
- Để xem thông tin trạng thái/tình trạng: `openclaw status --all` hoặc `openclaw status --deep`.
|
||||
|
||||
Để tham khảo quy trình kênh chung, xem [Kênh](/vi/channels) và hướng dẫn [Plugins](/vi/tools/plugin).
|
||||
|
||||
## Liên quan
|
||||
|
||||
- [Định tuyến kênh](/vi/channels/channel-routing) - định tuyến phiên cho tin nhắn
|
||||
- [Tổng quan kênh](/vi/channels) - tất cả các kênh được hỗ trợ
|
||||
- [Nhóm](/vi/channels/groups) - hành vi trò chuyện nhóm và kiểm soát nhắc đến
|
||||
- [Ghép đôi](/vi/channels/pairing) - xác thực DM và luồng ghép đôi
|
||||
- [Bảo mật](/vi/gateway/security) - mô hình truy cập và gia cố
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- Bạn đang cài đặt, cấu hình hoặc kiểm tra Plugin bluebubbles
|
||||
summary: Thêm giao diện kênh BlueBubbles để gửi và nhận tin nhắn OpenClaw.
|
||||
title: Plugin BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T10:40:23Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# Plugin BlueBubbles
|
||||
|
||||
Thêm bề mặt kênh BlueBubbles để gửi và nhận tin nhắn OpenClaw.
|
||||
|
||||
## Phân phối
|
||||
|
||||
- Gói: `@openclaw/bluebubbles`
|
||||
- Tuyến cài đặt: npm; ClawHub
|
||||
|
||||
## Bề mặt
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## Tài liệu liên quan
|
||||
|
||||
- [bluebubbles](/vi/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- 设置 BlueBubbles 渠道
|
||||
- 网络钩子配对故障排除
|
||||
- 在 macOS 上配置 iMessage
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: 通过 BlueBubbles macOS 服务器提供旧版 iMessage 支持(REST 发送/接收、正在输入状态、表情回应、配对、高级操作)。
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:47Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status: 内置旧版插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。现有 BlueBubbles 设置会继续工作,但新的 OpenClaw iMessage 部署在主机满足要求时,应优先使用原生 [iMessage](/zh-CN/channels/imessage) 插件。
|
||||
|
||||
<Warning>
|
||||
对于新的 OpenClaw 设置,BlueBubbles 已弃用。
|
||||
|
||||
上游 BlueBubbles 生态仍然活跃,但 OpenClaw 依赖 BlueBubbles macOS 服务器 API。截至 2026 年 5 月 6 日,官方 [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) 开发分支最后一次变更发生在 [2026 年 1 月 22 日](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037),最新服务器版本([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9))发布于 2025 年 5 月 16 日。客户端应用和辅助仓库有更新的活动,因此这不是废弃项目的声明;弃用的重点是,当原生 `imsg` 路径把集成保留在本地 stdio 契约上时,减少 OpenClaw 对外部 HTTP 服务器、webhook 和私有 API 兼容性面的依赖。
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
当前 OpenClaw 版本内置 BlueBubbles,因此普通打包构建不需要单独的 `openclaw plugins install` 步骤。
|
||||
</Note>
|
||||
|
||||
## 概览
|
||||
|
||||
- 通过 BlueBubbles 辅助应用([bluebubbles.app](https://bluebubbles.app))在 macOS 上运行。
|
||||
- 适用于已依赖 BlueBubbles 渠道 ID、webhook 状态、群组目标、cron 投递或工作区路由的安装的旧版回退方案。
|
||||
- 推荐/已测试:macOS Sequoia (15)。macOS Tahoe (26) 可用;编辑目前在 Tahoe 上损坏,群组图标更新可能报告成功但不同步。
|
||||
- OpenClaw 通过其 REST API(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)与它通信。
|
||||
- 传入消息通过 webhook 到达;传出回复、输入状态、已读回执和 tapback 都是 REST 调用。
|
||||
- 附件和贴纸会作为入站媒体摄取(并在可能时暴露给智能体)。
|
||||
- 合成 MP3 或 CAF 音频的自动 TTS 回复会作为 iMessage 语音备忘录气泡发送,而不是普通文件附件。
|
||||
- 配对/allowlist 的工作方式与其他渠道相同(`/channels/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。
|
||||
- 反应会像 Slack/Telegram 一样作为系统事件暴露,因此智能体可以在回复前“提及”它们。
|
||||
- 高级功能:编辑、撤回、回复线程、消息效果、群组管理。
|
||||
|
||||
## 快速开始
|
||||
|
||||
<Steps>
|
||||
<Step title="Install BlueBubbles">
|
||||
在你的 Mac 上安装 BlueBubbles 服务器(遵循 [bluebubbles.app/install](https://bluebubbles.app/install) 上的说明)。
|
||||
</Step>
|
||||
<Step title="Enable the web API">
|
||||
在 BlueBubbles 配置中,启用 Web API 并设置密码。
|
||||
</Step>
|
||||
<Step title="Configure OpenClaw">
|
||||
运行 `openclaw onboard` 并选择 BlueBubbles,或手动配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Point webhooks at the gateway">
|
||||
将 BlueBubbles webhook 指向你的 Gateway 网关(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
|
||||
</Step>
|
||||
<Step title="Start the gateway">
|
||||
启动 Gateway 网关;它会注册 webhook 处理程序并开始配对。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**安全**
|
||||
|
||||
- 始终设置 webhook 密码。
|
||||
- 始终要求 webhook 身份验证。除非 BlueBubbles webhook 请求包含与 `channels.bluebubbles.password` 匹配的密码/guid(例如 `?password=<password>` 或 `x-password`),否则 OpenClaw 会拒绝该请求,无论 loopback/代理拓扑如何。
|
||||
- 在读取/解析完整 webhook 正文之前,会先检查密码身份验证。
|
||||
|
||||
</Warning>
|
||||
|
||||
## 保持 Messages.app 活跃(VM / 无头设置)
|
||||
|
||||
某些 macOS VM / 始终在线设置可能会导致 Messages.app 进入“空闲”状态(传入事件会停止,直到应用被打开/置于前台)。一个简单的解决方法是使用 AppleScript + LaunchAgent **每 5 分钟 poke Messages 一次**。
|
||||
|
||||
<Steps>
|
||||
<Step title="Save the AppleScript">
|
||||
将以下内容保存为 `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="Install a LaunchAgent">
|
||||
将以下内容保存为 `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
这会**每 300 秒**以及**登录时**运行。首次运行可能会触发 macOS **自动化**提示(`osascript` → Messages)。请在运行 LaunchAgent 的同一用户会话中批准它们。
|
||||
|
||||
</Step>
|
||||
<Step title="Load it">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 新手引导
|
||||
|
||||
BlueBubbles 可在交互式新手引导中使用:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
向导会提示输入:
|
||||
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`)。
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
来自 BlueBubbles Server 设置的 API 密码。
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook 端点路径。
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`、`allowlist`、`open` 或 `disabled`。
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
电话号码、电子邮件或聊天目标。
|
||||
</ParamField>
|
||||
|
||||
你也可以通过 CLI 添加 BlueBubbles:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## 访问控制(私信 + 群组)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DMs">
|
||||
- 默认:`channels.bluebubbles.dmPolicy = "pairing"`。
|
||||
- 未知发送者会收到配对码;消息会被忽略,直到获得批准(代码 1 小时后过期)。
|
||||
- 通过以下方式批准:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- 配对是默认令牌交换方式。详情:[配对](/zh-CN/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="Groups">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(默认:`allowlist`)。
|
||||
- 当设置为 `allowlist` 时,`channels.bluebubbles.groupAllowFrom` 控制谁可以在群组中触发。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 联系人名称增强(macOS,可选)
|
||||
|
||||
BlueBubbles 群组 webhook 通常只包含原始参与者地址。如果你希望 `GroupMembers` 上下文改为显示本地联系人名称,可以选择在 macOS 上启用本地 Contacts 增强:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` 启用查找。默认值:`false`。
|
||||
- 只有在群组访问、命令授权和提及门控允许消息通过后,才会运行查找。
|
||||
- 只会增强未命名的电话参与者。
|
||||
- 未找到本地匹配时,原始电话号码会保留为回退值。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 提及门控(群组)
|
||||
|
||||
BlueBubbles 支持群组聊天的提及门控,匹配 iMessage/WhatsApp 行为:
|
||||
|
||||
- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)检测提及。
|
||||
- 当某个群组启用 `requireMention` 时,智能体只有在被提及时才会回应。
|
||||
- 授权发送者发出的控制命令会绕过提及门控。
|
||||
|
||||
按群组配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 命令门控
|
||||
|
||||
- 控制命令(例如 `/config`、`/model`)需要授权。
|
||||
- 使用 `allowFrom` 和 `groupAllowFrom` 来确定命令授权。
|
||||
- 授权发送者即使未在群组中提及也可以运行控制命令。
|
||||
|
||||
### 按群组系统提示词
|
||||
|
||||
`channels.bluebubbles.groups.*` 下的每个条目都接受可选的 `systemPrompt` 字符串。该值会注入到处理该群组消息的每个轮次中的智能体系统提示词里,因此你可以设置按群组的人设或行为规则,而无需编辑智能体提示词:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
该键匹配 BlueBubbles 为群组报告的任何 `chatGuid` / `chatIdentifier` / 数字 `chatId`,并且 `"*"` 通配符条目会为没有精确匹配的每个群组提供默认值(与 `requireMention` 和按群组工具策略使用相同模式)。精确匹配始终优先于通配符。私信会忽略此字段;请改用智能体级别或账号级别的提示词自定义。
|
||||
|
||||
#### 示例:线程回复和 tapback 反应(Private API)
|
||||
|
||||
启用 BlueBubbles Private API 后,入站消息会带有短消息 ID(例如 `[[reply_to:5]]`),智能体可以调用 `action=reply` 以在特定消息下创建线程,或调用 `action=react` 来发送 tapback。按群组的 `systemPrompt` 是让智能体选择正确工具的可靠方式:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback 反应和线程回复都需要 BlueBubbles Private API;请参阅[高级操作](#advanced-actions)和[消息 ID](#message-ids-short-vs-full)了解底层机制。
|
||||
|
||||
## ACP 对话绑定
|
||||
|
||||
BlueBubbles 聊天可以转换为持久 ACP 工作区,而无需更改传输层。
|
||||
|
||||
快速操作员流程:
|
||||
|
||||
- 在私信或允许的群组聊天中运行 `/acp spawn codex --bind here`。
|
||||
- 之后同一 BlueBubbles 对话中的消息会路由到生成的 ACP 会话。
|
||||
- `/new` 和 `/reset` 会就地重置同一个已绑定的 ACP 会话。
|
||||
- `/acp close` 会关闭 ACP 会话并移除绑定。
|
||||
|
||||
还支持通过顶层 `bindings[]` 条目配置持久绑定,其中包含 `type: "acp"` 和 `match.channel: "bluebubbles"`。
|
||||
|
||||
`match.peer.id` 可以使用任何受支持的 BlueBubbles 目标形式:
|
||||
|
||||
- 规范化的私信句柄,例如 `+15555550123` 或 `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
对于稳定的群组绑定,优先使用 `chat_id:*` 或 `chat_identifier:*`。
|
||||
|
||||
示例:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
请参阅 [ACP Agents](/zh-CN/tools/acp-agents),了解共享的 ACP 绑定行为。
|
||||
|
||||
## 输入状态 + 已读回执
|
||||
|
||||
- **输入状态指示器**:在响应生成之前和期间自动发送。
|
||||
- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认:`true`)。
|
||||
- **输入状态指示器**:OpenClaw 会发送开始输入事件;BlueBubbles 会在发送或超时后自动清除输入状态(通过 DELETE 手动停止不可靠)。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 高级操作
|
||||
|
||||
启用配置后,BlueBubbles 支持高级消息操作:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Available actions">
|
||||
- **react**:添加/移除 tapback 反应(`messageId`、`emoji`、`remove`)。iMessage 的原生 tapback 集合是 `love`、`like`、`dislike`、`laugh`、`emphasize` 和 `question`。当智能体选择该集合之外的 emoji(例如 `👀`)时,反应工具会回退到 `love`,这样 tapback 仍会渲染,而不是让整个请求失败。已配置的确认反应仍会严格校验,并对未知值报错。
|
||||
- **edit**:编辑已发送消息(`messageId`、`text`)。
|
||||
- **unsend**:撤回消息(`messageId`)。
|
||||
- **reply**:回复特定消息(`messageId`、`text`、`to`)。
|
||||
- **sendWithEffect**:使用 iMessage 效果发送(`text`、`to`、`effectId`)。
|
||||
- **renameGroup**:重命名群聊(`chatGuid`、`displayName`)。
|
||||
- **setGroupIcon**:设置群聊图标/照片(`chatGuid`、`media`)- 在 macOS 26 Tahoe 上不稳定(API 可能返回成功,但图标不会同步)。
|
||||
- **addParticipant**:向群组添加某人(`chatGuid`、`address`)。
|
||||
- **removeParticipant**:从群组移除某人(`chatGuid`、`address`)。
|
||||
- **leaveGroup**:退出群聊(`chatGuid`)。
|
||||
- **upload-file**:发送媒体/文件(`to`、`buffer`、`filename`、`asVoice`)。
|
||||
- 语音备忘录:设置 `asVoice: true` 并使用 **MP3** 或 **CAF** 音频,即可作为 iMessage 语音消息发送。BlueBubbles 在发送语音备忘录时会将 MP3 → CAF。
|
||||
- 旧版别名:`sendAttachment` 仍然可用,但 `upload-file` 是规范操作名称。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 消息 ID(短 ID 与完整 ID)
|
||||
|
||||
OpenClaw 可能会显示 _短_ 消息 ID(例如 `1`、`2`)以节省 token。
|
||||
|
||||
- `MessageSid` / `ReplyToId` 可以是短 ID。
|
||||
- `MessageSidFull` / `ReplyToIdFull` 包含提供商完整 ID。
|
||||
- 短 ID 位于内存中;它们可能会在重启或缓存淘汰后过期。
|
||||
- 操作接受短或完整的 `messageId`,但如果短 ID 已不可用就会报错。
|
||||
|
||||
持久自动化和存储请使用完整 ID:
|
||||
|
||||
- 模板:`{{MessageSidFull}}`、`{{ReplyToIdFull}}`
|
||||
- 上下文:入站载荷中的 `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
请参阅 [配置](/zh-CN/gateway/configuration),了解模板变量。
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## 合并拆分发送的私信(一次编写中的命令 + URL)
|
||||
|
||||
当用户在 iMessage 中同时输入命令和 URL,例如 `Dump https://example.com/article`,Apple 会将发送拆分为**两个独立的 webhook 投递**:
|
||||
|
||||
1. 一条文本消息(`"Dump"`)。
|
||||
2. 一个 URL 预览气泡(`"https://..."`),其中 OG 预览图片作为附件。
|
||||
|
||||
在多数设置中,这两个 webhook 到达 OpenClaw 的间隔约为 0.8-2.0 秒。如果不进行合并,智能体会在第 1 个轮次只收到命令并回复(通常是“把 URL 发给我”),然后在第 2 个轮次才看到 URL,此时命令上下文已经丢失。
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` 会让私信把同一发送者连续的 webhook 合并为单个智能体轮次。群聊仍按每条消息作为键,以保留多用户轮次结构。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to enable">
|
||||
在以下情况启用:
|
||||
|
||||
- 你发布的 Skills 预期在一条消息中收到 `command + payload`(dump、paste、save、queue 等)。
|
||||
- 你的用户会将 URL、图片或长内容与命令一起粘贴。
|
||||
- 你可以接受新增的私信轮次延迟(见下文)。
|
||||
|
||||
在以下情况保持禁用:
|
||||
|
||||
- 单词私信触发器需要最低命令延迟。
|
||||
- 你的所有流程都是没有后续载荷的一次性命令。
|
||||
|
||||
</Tab>
|
||||
<Tab title="Enabling">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
开启该标志且没有显式 `messages.inbound.byChannel.bluebubbles` 时,防抖窗口会扩大到 **2500 ms**(非合并的默认值为 500 ms)。更宽的窗口是必要的,因为 Apple 0.8-2.0 秒的拆分发送节奏无法适应更紧的默认值。
|
||||
|
||||
如需自行调节窗口:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="Trade-offs">
|
||||
- **私信控制命令会增加延迟。**开启该标志后,私信控制命令消息(如 `Dump`、`Save` 等)现在会在派发前等待最多一个防抖窗口,以防载荷 webhook 正在到来。群聊命令保持即时派发。
|
||||
- **合并输出有边界** - 合并文本上限为 4000 个字符,并带有显式 `…[truncated]` 标记;附件上限为 20 个;来源条目上限为 10 个(超过后保留首条和最新条目)。每个来源 `messageId` 仍会进入入站去重,因此之后 MessagePoller 重放任何单个事件都会被识别为重复。
|
||||
- **按渠道选择启用。**其他渠道(Telegram、WhatsApp、Slack、……)不受影响。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 场景和智能体看到的内容
|
||||
|
||||
| 用户编写 | Apple 投递 | 标志关闭(默认) | 标志开启 + 2500 ms 窗口 |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(一次发送) | 2 个 webhook,相隔约 1 秒 | 两个智能体轮次:“Dump” 单独出现,然后 URL | 一个轮次:合并文本 `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(附件 + 文本) | 2 个 webhook | 两个轮次 | 一个轮次:文本 + 图片 |
|
||||
| `/status`(独立命令) | 1 个 webhook | 即时派发 | **最多等待一个窗口,然后派发** |
|
||||
| 单独粘贴 URL | 1 个 webhook | 即时派发 | 即时派发(桶中只有一个条目) |
|
||||
| 文本 + URL 作为两条有意分开发送的消息,间隔数分钟 | 2 个 webhook,位于窗口之外 | 两个轮次 | 两个轮次(它们之间窗口过期) |
|
||||
| 快速涌入(窗口内 >10 条小私信) | N 个 webhook | N 个轮次 | 一个轮次,有边界输出(保留首条 + 最新条目,并应用文本/附件上限) |
|
||||
|
||||
### 拆分发送合并故障排除
|
||||
|
||||
如果标志已开启,但拆分发送仍作为两个轮次到达,请检查每一层:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Config actually loaded">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
然后运行 `openclaw gateway restart` - 该标志会在创建防抖器注册表时读取。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Debounce window wide enough for your setup">
|
||||
查看 `~/Library/Logs/bluebubbles-server/main.log` 下的 BlueBubbles 服务器日志:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
测量 `"Dump"` 风格文本派发与随后 `"https://..."; Attachments:` 派发之间的间隔。将 `messages.inbound.byChannel.bluebubbles` 提高到足以覆盖该间隔的值。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Session JSONL timestamps ≠ webhook arrival">
|
||||
会话事件时间戳(`~/.openclaw/agents/<id>/sessions/*.jsonl`)反映的是 Gateway 网关把消息交给智能体的时间,**不是** webhook 到达的时间。标记为 `[Queued messages while agent was busy]` 的排队第二条消息表示第一个轮次在第二个 webhook 到达时仍在运行,合并桶已经刷新。请根据 BB 服务器日志调节窗口,而不是会话日志。
|
||||
</Accordion>
|
||||
<Accordion title="Memory pressure slowing reply dispatch">
|
||||
在较小的机器(8 GB)上,智能体轮次可能耗时足够久,导致合并桶在回复完成前刷新,URL 作为排队的第二个轮次落入。检查 `memory_pressure` 和 `ps -o rss -p $(pgrep openclaw-gateway)`;如果 Gateway 网关超过约 500 MB RSS 且压缩器处于活动状态,请关闭其他繁重进程或升级到更大的主机。
|
||||
</Accordion>
|
||||
<Accordion title="Reply-quote sends are a different path">
|
||||
如果用户将 `Dump` 作为对现有 URL 气泡的**回复**点击发送(iMessage 在 Dump 气泡上显示 “1 Reply” 徽标),URL 位于 `replyToBody` 中,而不是第二个 webhook 中。合并不适用,这是 Skills/提示词相关问题,不是防抖器问题。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 分块流式传输
|
||||
|
||||
控制响应是作为单条消息发送,还是以块形式流式传输:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 媒体 + 限制
|
||||
|
||||
- 入站附件会被下载并存储在媒体缓存中。
|
||||
- 通过 `channels.bluebubbles.mediaMaxMb` 为入站和出站媒体设置媒体上限(默认:8 MB)。
|
||||
- 出站文本会按 `channels.bluebubbles.textChunkLimit` 分块(默认:4000 个字符)。
|
||||
|
||||
## 配置参考
|
||||
|
||||
完整配置:[配置](/zh-CN/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="连接和 webhook">
|
||||
- `channels.bluebubbles.enabled`:启用/停用该渠道。
|
||||
- `channels.bluebubbles.serverUrl`:BlueBubbles REST API 基础 URL。
|
||||
- `channels.bluebubbles.password`:API 密码。
|
||||
- `channels.bluebubbles.webhookPath`:Webhook 端点路径(默认:`/bluebubbles-webhook`)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="访问策略">
|
||||
- `channels.bluebubbles.dmPolicy`:`pairing | allowlist | open | disabled`(默认:`pairing`)。
|
||||
- `channels.bluebubbles.allowFrom`:私信允许列表(句柄、邮箱、E.164 号码、`chat_id:*`、`chat_guid:*`)。
|
||||
- `channels.bluebubbles.groupPolicy`:`open | allowlist | disabled`(默认:`allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom`:群组发送者允许列表。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`:在 macOS 上,门控通过后,可选择从本地通讯录补全未命名的群组参与者。默认:`false`。
|
||||
- `channels.bluebubbles.groups`:按群组配置(`requireMention` 等)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="发送和分块">
|
||||
- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。
|
||||
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`false`;流式回复需要启用)。
|
||||
- `channels.bluebubbles.textChunkLimit`:出站分块大小,单位为字符(默认:4000)。
|
||||
- `channels.bluebubbles.sendTimeoutMs`:通过 `/api/v1/message/text` 发送出站文本时,每个请求的超时时间,单位为毫秒(默认:30000)。在 macOS 26 设置中,如果 Private API iMessage 发送可能在 iMessage 框架内停滞 60 秒以上,可调高该值;例如 `45000` 或 `60000`。探测、聊天查询、回应、编辑和健康检查目前仍使用较短的 10 秒默认值;计划在后续扩展覆盖到回应和编辑。按账号覆盖:`channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`。
|
||||
- `channels.bluebubbles.chunkMode`:`length`(默认)仅在超过 `textChunkLimit` 时拆分;`newline` 先按空行(段落边界)拆分,再按长度分块。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="媒体和历史记录">
|
||||
- `channels.bluebubbles.mediaMaxMb`:入站/出站媒体大小上限,单位为 MB(默认:8)。
|
||||
- `channels.bluebubbles.mediaLocalRoots`:明确允许用于出站本地媒体路径的绝对本地目录允许列表。默认拒绝发送本地路径,除非已配置此项。按账号覆盖:`channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`。
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`:将连续的同一发送者私信 webhook 合并为一个智能体轮次,使 Apple 的文本 + URL 拆分发送作为单条消息到达(默认:`false`)。有关场景、窗口调优和权衡,请参阅[合并拆分发送的私信](#coalescing-split-send-dms-command--url-in-one-composition)。启用且未显式设置 `messages.inbound.byChannel.bluebubbles` 时,会将默认入站防抖窗口从 500 ms 扩大到 2500 ms。
|
||||
- `channels.bluebubbles.historyLimit`:用于上下文的最大群组消息数(0 表示停用)。
|
||||
- `channels.bluebubbles.dmHistoryLimit`:私信历史记录限制。
|
||||
- `channels.bluebubbles.replyContextApiFallback`:当入站回复没有 `replyToBody`/`replyToSender` 且内存中的回复上下文缓存未命中时,尽力从 BlueBubbles HTTP API 获取原始消息作为回退(默认:`false`)。适用于多个实例共享一个 BlueBubbles 账号的部署、进程重启后,或长期 TTL/LRU 缓存驱逐后。该获取操作受与其他所有 BlueBubbles 客户端请求相同的 SSRF 防护策略保护,绝不抛出异常,并会填充缓存,以便后续回复摊销成本。按账号覆盖:`channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`。渠道级设置会传播到未设置该标志的账号。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="操作和账号">
|
||||
- `channels.bluebubbles.actions`:启用/停用特定操作。
|
||||
- `channels.bluebubbles.accounts`:多账号配置。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
相关全局选项:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。
|
||||
- `messages.responsePrefix`。
|
||||
|
||||
## 地址指定 / 发送目标
|
||||
|
||||
优先使用 `chat_guid` 以获得稳定路由:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123`(群组首选)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 直接句柄:`+15555550123`、`user@example.com`
|
||||
- 如果某个直接句柄没有现有私信聊天,OpenClaw 会通过 `POST /api/v1/chat/new` 创建一个。这需要启用 BlueBubbles Private API。
|
||||
|
||||
### iMessage 与 SMS 路由
|
||||
|
||||
当同一个句柄在 Mac 上同时有 iMessage 和 SMS 聊天时(例如某个电话号码已注册 iMessage,但也收到过绿色气泡回退消息),OpenClaw 会优先使用 iMessage 聊天,并且绝不会静默降级到 SMS。若要强制使用 SMS 聊天,请使用显式的 `sms:` 目标前缀(例如 `sms:+15555550123`)。没有匹配 iMessage 聊天的句柄,仍会通过 BlueBubbles 报告的任意聊天发送。
|
||||
|
||||
## 安全
|
||||
|
||||
- Webhook 请求通过将 `guid`/`password` 查询参数或标头与 `channels.bluebubbles.password` 比较来认证。
|
||||
- 请保密 API 密码和 webhook 端点(像凭证一样处理)。
|
||||
- BlueBubbles webhook 认证没有 localhost 绕过。如果你代理 webhook 流量,请在请求端到端保留 BlueBubbles 密码。这里的 `gateway.trustedProxies` 不能替代 `channels.bluebubbles.password`。请参阅 [Gateway 网关安全](/zh-CN/gateway/security#reverse-proxy-configuration)。
|
||||
- 如果将 BlueBubbles 服务器暴露到你的局域网之外,请启用 HTTPS 和防火墙规则。
|
||||
|
||||
## 故障排除
|
||||
|
||||
- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志,并确认 Gateway 网关路径与 `channels.bluebubbles.webhookPath` 匹配。
|
||||
- 配对码一小时后过期;请使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
|
||||
- 回应需要 BlueBubbles private API(`POST /api/v1/message/react`);请确保服务器版本公开了它。
|
||||
- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26(Tahoe)上,由于 private API 变更,编辑目前已损坏。
|
||||
- 在 macOS 26(Tahoe)上,群组图标更新可能不稳定:API 可能返回成功,但新图标不会同步。
|
||||
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知损坏的操作。如果编辑在 macOS 26(Tahoe)上仍然出现,请使用 `channels.bluebubbles.actions.edit=false` 手动停用它。
|
||||
- 已启用 `coalesceSameSenderDms`,但拆分发送(例如 `Dump` + URL)仍作为两个轮次到达:请参阅[拆分发送合并故障排除](#split-send-coalescing-troubleshooting)检查清单 - 常见原因包括防抖窗口过短、将会话日志时间戳误读为 webhook 到达时间,或回复引用发送(它使用 `replyToBody`,而不是第二个 webhook)。
|
||||
- 如需 Status/健康信息:`openclaw status --all` 或 `openclaw status --deep`。
|
||||
|
||||
如需通用渠道工作流参考,请参阅[渠道](/zh-CN/channels)和[插件](/zh-CN/tools/plugin)指南。
|
||||
|
||||
## 相关
|
||||
|
||||
- [渠道路由](/zh-CN/channels/channel-routing) - 消息的会话路由
|
||||
- [渠道概览](/zh-CN/channels) - 所有支持的渠道
|
||||
- [群组](/zh-CN/channels/groups) - 群聊行为和提及门控
|
||||
- [配对](/zh-CN/channels/pairing) - 私信认证和配对流程
|
||||
- [安全](/zh-CN/gateway/security) - 访问模型和加固
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在安装、配置或审计 bluebubbles 插件
|
||||
summary: 添加用于发送和接收 OpenClaw 消息的 BlueBubbles 渠道接口。
|
||||
title: BlueBubbles 插件
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T02:48:34Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles 插件
|
||||
|
||||
添加用于发送和接收 OpenClaw 消息的 BlueBubbles 渠道接入面。
|
||||
|
||||
## 分发
|
||||
|
||||
- 软件包:`@openclaw/bluebubbles`
|
||||
- 安装路径:npm;ClawHub
|
||||
|
||||
## 接入面
|
||||
|
||||
渠道:bluebubbles
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [bluebubbles](/zh-CN/channels/bluebubbles)
|
||||
@ -1,645 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- 設定 BlueBubbles 通道
|
||||
- Webhook 配對疑難排解
|
||||
- 在 macOS 上設定 iMessage
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: 透過 BlueBubbles macOS 伺服器支援舊版 iMessage(REST 傳送/接收、輸入中狀態、回應、配對、進階動作)。
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-05-07T01:50:50Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: e32b35242c7e751b49dcd8d839bc291c80cb4d88c0b4ce6f65635b7ef2ed97c3
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Status:內建的舊版 Plugin,透過 HTTP 與 BlueBubbles macOS 伺服器通訊。現有 BlueBubbles 設定會繼續運作,但新的 OpenClaw iMessage 部署在需求符合主機條件時,應優先使用原生 [iMessage](/zh-TW/channels/imessage) Plugin。
|
||||
|
||||
<Warning>
|
||||
BlueBubbles 已不建議用於新的 OpenClaw 設定。
|
||||
|
||||
上游 BlueBubbles 生態系仍然活躍,但 OpenClaw 依賴 BlueBubbles macOS 伺服器 API。截至 2026 年 5 月 6 日,官方 [`bluebubbles-server`](https://github.com/BlueBubblesApp/bluebubbles-server) 開發分支最後一次變更是在 [2026 年 1 月 22 日](https://github.com/BlueBubblesApp/bluebubbles-server/commit/88a4921bbd5a8111f1e9582b83715cf877171037),而最新伺服器版本([`v1.9.9`](https://github.com/BlueBubblesApp/bluebubbles-server/releases/tag/v1.9.9))發佈於 2025 年 5 月 16 日。用戶端應用程式與輔助儲存庫有較新的活動,因此這不是聲稱專案已被放棄;此棄用是為了減少 OpenClaw 對外部 HTTP 伺服器、webhooks,以及私有 API 相容性表面的依賴,因為原生 `imsg` 路徑會將整合維持在本機 stdio 合約上。
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
目前的 OpenClaw 發行版內建 BlueBubbles,因此一般套裝建置不需要另外執行 `openclaw plugins install` 步驟。
|
||||
</Note>
|
||||
|
||||
## 概觀
|
||||
|
||||
- 透過 BlueBubbles 輔助應用程式在 macOS 上執行([bluebubbles.app](https://bluebubbles.app))。
|
||||
- 適用於已依賴 BlueBubbles 頻道 ID、webhook 狀態、群組目標、cron 傳遞或工作區路由的安裝,作為舊版備援。
|
||||
- 建議/已測試:macOS Sequoia (15)。macOS Tahoe (26) 可運作;目前 Tahoe 上的編輯功能已損壞,群組圖示更新可能回報成功但未同步。
|
||||
- OpenClaw 透過其 REST API 與它通訊(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)。
|
||||
- 傳入訊息會透過 webhooks 抵達;傳出回覆、輸入中指示、已讀回條與 tapbacks 都是 REST 呼叫。
|
||||
- 附件與貼圖會作為傳入媒體擷取(並在可行時呈現給代理)。
|
||||
- 會合成 MP3 或 CAF 音訊的自動 TTS 回覆,會以 iMessage 語音備忘錄泡泡傳遞,而不是一般檔案附件。
|
||||
- 配對/允許清單的運作方式與其他頻道相同(`/channels/pairing` 等),搭配 `channels.bluebubbles.allowFrom` + 配對碼。
|
||||
- 反應會像 Slack/Telegram 一樣以系統事件呈現,讓代理可在回覆前「提及」它們。
|
||||
- 進階功能:編輯、收回、回覆串接、訊息效果、群組管理。
|
||||
|
||||
## 快速開始
|
||||
|
||||
<Steps>
|
||||
<Step title="安裝 BlueBubbles">
|
||||
在你的 Mac 上安裝 BlueBubbles 伺服器(依照 [bluebubbles.app/install](https://bluebubbles.app/install) 的指示)。
|
||||
</Step>
|
||||
<Step title="啟用 Web API">
|
||||
在 BlueBubbles 設定中啟用 Web API 並設定密碼。
|
||||
</Step>
|
||||
<Step title="設定 OpenClaw">
|
||||
執行 `openclaw onboard` 並選取 BlueBubbles,或手動設定:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="將 webhooks 指向 gateway">
|
||||
將 BlueBubbles webhooks 指向你的 gateway(範例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
|
||||
</Step>
|
||||
<Step title="啟動 gateway">
|
||||
啟動 gateway;它會註冊 webhook 處理常式並開始配對。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**安全性**
|
||||
|
||||
- 一律設定 webhook 密碼。
|
||||
- Webhook 驗證一律為必要。除非 BlueBubbles webhook 請求包含與 `channels.bluebubbles.password` 相符的密碼/guid(例如 `?password=<password>` 或 `x-password`),否則 OpenClaw 會拒絕該請求,無論 loopback/proxy 拓撲為何。
|
||||
- 在讀取/剖析完整 webhook 主體前會先檢查密碼驗證。
|
||||
|
||||
</Warning>
|
||||
|
||||
## 讓 Messages.app 保持運作(VM / 無頭設定)
|
||||
|
||||
某些 macOS VM / 常時開機設定可能會讓 Messages.app 進入「閒置」狀態(傳入事件會停止,直到應用程式被開啟/帶到前景)。一個簡單的解法是使用 AppleScript + LaunchAgent **每 5 分鐘 poke Messages 一次**。
|
||||
|
||||
<Steps>
|
||||
<Step title="儲存 AppleScript">
|
||||
將以下內容儲存為 `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="安裝 LaunchAgent">
|
||||
將以下內容儲存為 `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
這會**每 300 秒**執行一次,並在**登入時**執行。第一次執行可能會觸發 macOS **自動化**提示(`osascript` → Messages)。請在執行 LaunchAgent 的同一個使用者工作階段中核准。
|
||||
|
||||
</Step>
|
||||
<Step title="載入它">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 入門設定
|
||||
|
||||
BlueBubbles 可在互動式入門設定中使用:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
精靈會提示輸入:
|
||||
|
||||
<ParamField path="伺服器 URL" type="string" required>
|
||||
BlueBubbles 伺服器位址(例如 `http://192.168.1.100:1234`)。
|
||||
</ParamField>
|
||||
<ParamField path="密碼" type="string" required>
|
||||
來自 BlueBubbles Server 設定的 API 密碼。
|
||||
</ParamField>
|
||||
<ParamField path="Webhook 路徑" type="string" default="/bluebubbles-webhook">
|
||||
Webhook 端點路徑。
|
||||
</ParamField>
|
||||
<ParamField path="DM 政策" type="string">
|
||||
`pairing`、`allowlist`、`open` 或 `disabled`。
|
||||
</ParamField>
|
||||
<ParamField path="允許清單" type="string[]">
|
||||
電話號碼、電子郵件或聊天目標。
|
||||
</ParamField>
|
||||
|
||||
你也可以透過 CLI 新增 BlueBubbles:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## 存取控制(DM + 群組)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM">
|
||||
- 預設:`channels.bluebubbles.dmPolicy = "pairing"`。
|
||||
- 未知寄件者會收到配對碼;訊息在核准前會被忽略(代碼會在 1 小時後過期)。
|
||||
- 透過以下方式核准:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- 配對是預設的權杖交換。詳細資訊:[配對](/zh-TW/channels/pairing)
|
||||
|
||||
</Tab>
|
||||
<Tab title="群組">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(預設:`allowlist`)。
|
||||
- 設定 `allowlist` 時,`channels.bluebubbles.groupAllowFrom` 控制誰可以在群組中觸發。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 聯絡人名稱補充(macOS,選用)
|
||||
|
||||
BlueBubbles 群組 webhooks 通常只包含原始參與者位址。如果你希望 `GroupMembers` context 改為顯示本機聯絡人名稱,可以在 macOS 上選擇啟用本機聯絡人補充:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` 會啟用查詢。預設:`false`。
|
||||
- 查詢只會在群組存取、命令授權與提及門控允許訊息通過後執行。
|
||||
- 只會補充未命名的電話參與者。
|
||||
- 找不到本機相符項目時,原始電話號碼仍會作為備援。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 提及門控(群組)
|
||||
|
||||
BlueBubbles 支援群組聊天的提及門控,符合 iMessage/WhatsApp 行為:
|
||||
|
||||
- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)偵測提及。
|
||||
- 為群組啟用 `requireMention` 時,代理只會在被提及時回應。
|
||||
- 來自授權寄件者的控制命令會略過提及門控。
|
||||
|
||||
每群組設定:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // default for all groups
|
||||
"iMessage;-;chat123": { requireMention: false }, // override for specific group
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 命令門控
|
||||
|
||||
- 控制命令(例如 `/config`、`/model`)需要授權。
|
||||
- 使用 `allowFrom` 與 `groupAllowFrom` 判斷命令授權。
|
||||
- 授權寄件者即使未在群組中提及,也可以執行控制命令。
|
||||
|
||||
### 每群組系統提示
|
||||
|
||||
`channels.bluebubbles.groups.*` 底下的每個項目都接受選用的 `systemPrompt` 字串。該值會在處理該群組訊息的每一輪注入代理的系統提示,因此你可以設定每群組 persona 或行為規則,而不用編輯代理提示:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
鍵會對應 BlueBubbles 回報給該群組的 `chatGuid` / `chatIdentifier` / 數字 `chatId`,而 `"*"` 萬用字元項目會為每個沒有精確相符項目的群組提供預設值(與 `requireMention` 以及每群組工具政策使用相同模式)。精確相符一律優先於萬用字元。DM 會忽略此欄位;請改用代理層級或帳號層級的提示自訂。
|
||||
|
||||
#### 實例:串接回覆與 tapback 反應(私有 API)
|
||||
|
||||
啟用 BlueBubbles 私有 API 後,傳入訊息會帶有短訊息 ID(例如 `[[reply_to:5]]`),且代理可以呼叫 `action=reply` 來串接到特定訊息,或呼叫 `action=react` 放置 tapback。每群組 `systemPrompt` 是讓代理選擇正確工具的可靠方式:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: "When replying in this group, always call action=reply with the [[reply_to:N]] messageId from context so your response threads under the triggering message. Never send a new unlinked message. For short acknowledgements ('ok', 'got it', 'on it'), use action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓) instead of sending a text reply.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Tapback 反應與串接回覆都需要 BlueBubbles 私有 API;底層機制請參閱[進階動作](#advanced-actions)與[訊息 ID](#message-ids-short-vs-full)。
|
||||
|
||||
## ACP 對話繫結
|
||||
|
||||
BlueBubbles 聊天可以轉換成持久的 ACP 工作區,而不需要變更傳輸層。
|
||||
|
||||
快速操作員流程:
|
||||
|
||||
- 在 DM 或允許的群組聊天中執行 `/acp spawn codex --bind here`。
|
||||
- 未來同一個 BlueBubbles 對話中的訊息會路由到產生的 ACP 工作階段。
|
||||
- `/new` 與 `/reset` 會就地重設同一個已繫結的 ACP 工作階段。
|
||||
- `/acp close` 會關閉 ACP 工作階段並移除繫結。
|
||||
|
||||
也支援透過頂層 `bindings[]` 項目設定持久繫結,其中包含 `type: "acp"` 與 `match.channel: "bluebubbles"`。
|
||||
|
||||
`match.peer.id` 可以使用任何支援的 BlueBubbles 目標形式:
|
||||
|
||||
- 正規化的 DM 識別碼,例如 `+15555550123` 或 `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
若要穩定的群組繫結,優先使用 `chat_id:*` 或 `chat_identifier:*`。
|
||||
|
||||
範例:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
請參閱 [ACP 代理程式](/zh-TW/tools/acp-agents)了解共用 ACP 繫結行為。
|
||||
|
||||
## 輸入中 + 已讀回執
|
||||
|
||||
- **輸入中指示器**:在回應產生前及期間自動傳送。
|
||||
- **已讀回執**:由 `channels.bluebubbles.sendReadReceipts` 控制(預設:`true`)。
|
||||
- **輸入中指示器**:OpenClaw 會傳送輸入開始事件;BlueBubbles 會在送出或逾時時自動清除輸入中狀態(透過 DELETE 手動停止並不可靠)。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // disable read receipts
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 進階動作
|
||||
|
||||
在設定中啟用後,BlueBubbles 支援進階訊息動作:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapbacks (default: true)
|
||||
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
|
||||
unsend: true, // unsend messages (macOS 13+)
|
||||
reply: true, // reply threading by message GUID
|
||||
sendWithEffect: true, // message effects (slam, loud, etc.)
|
||||
renameGroup: true, // rename group chats
|
||||
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
|
||||
addParticipant: true, // add participants to groups
|
||||
removeParticipant: true, // remove participants from groups
|
||||
leaveGroup: true, // leave group chats
|
||||
sendAttachment: true, // send attachments/media
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="可用動作">
|
||||
- **react**:新增/移除 Tapback 反應(`messageId`、`emoji`、`remove`)。iMessage 的原生 Tapback 集合是 `love`、`like`、`dislike`、`laugh`、`emphasize` 和 `question`。當代理程式選擇該集合以外的表情符號(例如 `👀`)時,反應工具會退回到 `love`,讓 Tapback 仍可呈現,而不是讓整個請求失敗。已設定的確認反應仍會嚴格驗證,並在值未知時報錯。
|
||||
- **edit**:編輯已傳送的訊息(`messageId`、`text`)。
|
||||
- **unsend**:收回訊息(`messageId`)。
|
||||
- **reply**:回覆特定訊息(`messageId`、`text`、`to`)。
|
||||
- **sendWithEffect**:使用 iMessage 效果傳送(`text`、`to`、`effectId`)。
|
||||
- **renameGroup**:重新命名群組聊天(`chatGuid`、`displayName`)。
|
||||
- **setGroupIcon**:設定群組聊天的圖示/照片(`chatGuid`、`media`)- 在 macOS 26 Tahoe 上不穩定(API 可能回傳成功,但圖示不會同步)。
|
||||
- **addParticipant**:將某人加入群組(`chatGuid`、`address`)。
|
||||
- **removeParticipant**:從群組移除某人(`chatGuid`、`address`)。
|
||||
- **leaveGroup**:離開群組聊天(`chatGuid`)。
|
||||
- **upload-file**:傳送媒體/檔案(`to`、`buffer`、`filename`、`asVoice`)。
|
||||
- 語音備忘錄:設定 `asVoice: true`,搭配 **MP3** 或 **CAF** 音訊,以 iMessage 語音訊息傳送。BlueBubbles 會在傳送語音備忘錄時將 MP3 → CAF。
|
||||
- 舊版別名:`sendAttachment` 仍可使用,但 `upload-file` 是正式動作名稱。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 訊息 ID(短版與完整)
|
||||
|
||||
為節省 token,OpenClaw 可能會顯示_短版_訊息 ID(例如 `1`、`2`)。
|
||||
|
||||
- `MessageSid` / `ReplyToId` 可以是短 ID。
|
||||
- `MessageSidFull` / `ReplyToIdFull` 包含提供者完整 ID。
|
||||
- 短 ID 存於記憶體中;重新啟動或快取淘汰時可能會過期。
|
||||
- 動作接受短版或完整 `messageId`,但若短 ID 已無法取得會報錯。
|
||||
|
||||
若要用於持久的自動化和儲存,請使用完整 ID:
|
||||
|
||||
- 範本:`{{MessageSidFull}}`、`{{ReplyToIdFull}}`
|
||||
- 脈絡:傳入酬載中的 `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
請參閱[設定](/zh-TW/gateway/configuration)了解範本變數。
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## 合併分割傳送的 DM(同一段撰寫中的命令 + URL)
|
||||
|
||||
當使用者在 iMessage 中把命令和 URL 一起輸入時,例如 `Dump https://example.com/article`,Apple 會將傳送拆成**兩個獨立的 Webhook 傳遞**:
|
||||
|
||||
1. 一則文字訊息(`"Dump"`)。
|
||||
2. 一個 URL 預覽泡泡(`"https://..."`),並以附件附上 OG 預覽圖片。
|
||||
|
||||
在多數環境中,兩個 Webhook 抵達 OpenClaw 的間隔約為 0.8-2.0 秒。若未合併,代理程式會在第 1 輪只收到命令並回覆(通常是「把 URL 傳給我」),到第 2 輪才看到 URL,此時命令脈絡已經遺失。
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` 讓 DM 選擇將連續且同一傳送者的 Webhook 合併為單一代理程式輪次。群組聊天仍會以每則訊息作為鍵,因此保留多使用者輪次結構。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="啟用時機">
|
||||
在以下情況啟用:
|
||||
|
||||
- 你提供預期 `command + payload` 位於同一則訊息中的 Skills(傾印、貼上、儲存、排入佇列等)。
|
||||
- 你的使用者會把 URL、圖片或長內容與命令一起貼上。
|
||||
- 你可以接受額外的 DM 輪次延遲(見下方)。
|
||||
|
||||
在以下情況保持停用:
|
||||
|
||||
- 你需要單字 DM 觸發詞的最低命令延遲。
|
||||
- 你的所有流程都是沒有後續酬載的一次性命令。
|
||||
|
||||
</Tab>
|
||||
<Tab title="啟用">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // opt in (default: false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
旗標開啟且沒有明確設定 `messages.inbound.byChannel.bluebubbles` 時,防彈跳視窗會加寬到 **2500 ms**(非合併模式預設為 500 ms)。較寬的視窗是必要的,因為 Apple 的分割傳送節奏為 0.8-2.0 秒,無法放入較緊的預設值。
|
||||
|
||||
若要自行調整視窗:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms works for most setups; raise to 4000 ms if your Mac is slow
|
||||
// or under memory pressure (observed gap can stretch past 2 s then).
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="取捨">
|
||||
- **DM 控制命令的額外延遲。** 旗標開啟時,DM 控制命令訊息(如 `Dump`、`Save` 等)現在會最多等待到防彈跳視窗結束才派送,以防酬載 Webhook 即將抵達。群組聊天命令維持即時派送。
|
||||
- **合併輸出有界** - 合併文字上限為 4000 字元,並帶有明確的 `…[truncated]` 標記;附件上限為 20;來源項目上限為 10(超過後保留第一筆加最新項目)。每個來源 `messageId` 仍會到達傳入去重,因此之後 MessagePoller 重播任何個別事件時,會被辨識為重複。
|
||||
- **選擇加入、按頻道設定。** 其他頻道(Telegram、WhatsApp、Slack、…)不受影響。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 情境以及代理程式看到的內容
|
||||
|
||||
| 使用者撰寫 | Apple 傳遞 | 旗標關閉(預設) | 旗標開啟 + 2500 ms 視窗 |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(一次傳送) | 2 個 Webhook,間隔約 1 秒 | 兩個代理程式輪次:只有「Dump」,然後是 URL | 一個輪次:合併文字 `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(附件 + 文字) | 2 個 Webhook | 兩個輪次 | 一個輪次:文字 + 圖片 |
|
||||
| `/status`(獨立命令) | 1 個 Webhook | 即時派送 | **最多等待到視窗結束,然後派送** |
|
||||
| 只貼上 URL | 1 個 Webhook | 即時派送 | 即時派送(儲存桶中只有一筆項目) |
|
||||
| 文字 + URL 作為兩則刻意分開的訊息傳送,相隔數分鐘 | 2 個 Webhook,位於視窗之外 | 兩個輪次 | 兩個輪次(視窗在兩者之間到期) |
|
||||
| 快速大量訊息(視窗內 >10 則小型 DM) | N 個 Webhook | N 個輪次 | 一個輪次,有界輸出(套用第一筆 + 最新,以及文字/附件上限) |
|
||||
|
||||
### 分割傳送合併疑難排解
|
||||
|
||||
如果旗標已開啟,但分割傳送仍以兩個輪次抵達,請逐層檢查:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="設定確實已載入">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
接著執行 `openclaw gateway restart` - 此旗標會在建立防彈跳登錄表時讀取。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="防彈跳視窗對你的環境足夠寬">
|
||||
查看 `~/Library/Logs/bluebubbles-server/main.log` 下的 BlueBubbles 伺服器記錄:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
測量 `"Dump"` 這類文字派送與其後 `"https://..."; Attachments:` 派送之間的間隔。將 `messages.inbound.byChannel.bluebubbles` 提高到足以涵蓋該間隔。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="工作階段 JSONL 時間戳 ≠ Webhook 抵達時間">
|
||||
工作階段事件時間戳(`~/.openclaw/agents/<id>/sessions/*.jsonl`)反映的是 Gateway 將訊息交給代理程式的時間,**不是** Webhook 抵達的時間。標記為 `[Queued messages while agent was busy]` 的排隊第二則訊息,表示第二個 Webhook 抵達時第一個輪次仍在執行,合併儲存桶已經送出並清空。請依據 BB 伺服器記錄調整視窗,而不是依據工作階段記錄。
|
||||
</Accordion>
|
||||
<Accordion title="記憶體壓力拖慢回覆派送">
|
||||
在較小的主機(8 GB)上,代理程式輪次可能耗時足以讓合併儲存桶在回覆完成前就送出並清空,URL 會落入排隊的第二個輪次。檢查 `memory_pressure` 和 `ps -o rss -p $(pgrep openclaw-gateway)`;如果 Gateway 超過約 500 MB RSS 且壓縮器作用中,請關閉其他繁重處理程序,或升級到較大的主機。
|
||||
</Accordion>
|
||||
<Accordion title="引用回覆傳送是不同路徑">
|
||||
如果使用者是點選 `Dump` 作為現有 URL 泡泡的**回覆**(iMessage 會在 Dump 泡泡上顯示「1 則回覆」徽章),URL 會位於 `replyToBody`,而不是第二個 Webhook。合併不適用 - 這是 Skills/提示詞層面的問題,不是防彈跳器層面的問題。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 區塊串流
|
||||
|
||||
控制回應是作為單一訊息傳送,還是以區塊串流傳送:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // enable block streaming (off by default)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 媒體 + 限制
|
||||
|
||||
- 傳入附件會下載並儲存在媒體快取中。
|
||||
- 透過 `channels.bluebubbles.mediaMaxMb` 設定傳入與傳出媒體的媒體上限(預設:8 MB)。
|
||||
- 傳出文字會依 `channels.bluebubbles.textChunkLimit` 分塊(預設:4000 字元)。
|
||||
|
||||
## 設定參考
|
||||
|
||||
完整設定:[設定](/zh-TW/gateway/configuration)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="連線與 Webhook">
|
||||
- `channels.bluebubbles.enabled`:啟用/停用此頻道。
|
||||
- `channels.bluebubbles.serverUrl`:BlueBubbles REST API 基底 URL。
|
||||
- `channels.bluebubbles.password`:API 密碼。
|
||||
- `channels.bluebubbles.webhookPath`:Webhook 端點路徑(預設:`/bluebubbles-webhook`)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="存取政策">
|
||||
- `channels.bluebubbles.dmPolicy`:`pairing | allowlist | open | disabled`(預設:`pairing`)。
|
||||
- `channels.bluebubbles.allowFrom`:DM 允許清單(帳號代稱、電子郵件、E.164 號碼、`chat_id:*`、`chat_guid:*`)。
|
||||
- `channels.bluebubbles.groupPolicy`:`open | allowlist | disabled`(預設:`allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom`:群組寄件者允許清單。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`:在 macOS 上,可選擇在通過閘門檢查後,從本機「聯絡人」補充未命名的群組參與者。預設:`false`。
|
||||
- `channels.bluebubbles.groups`:每個群組的設定(`requireMention` 等)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="傳送與分段">
|
||||
- `channels.bluebubbles.sendReadReceipts`:傳送讀取回條(預設:`true`)。
|
||||
- `channels.bluebubbles.blockStreaming`:啟用區塊串流(預設:`false`;串流回覆需要此設定)。
|
||||
- `channels.bluebubbles.textChunkLimit`:傳出分段大小,以字元計(預設:4000)。
|
||||
- `channels.bluebubbles.sendTimeoutMs`:透過 `/api/v1/message/text` 傳送傳出文字時,每個請求的逾時時間,以毫秒計(預設:30000)。在 macOS 26 設定中,Private API iMessage 傳送可能在 iMessage framework 內停滯 60 秒以上;此時請提高此值,例如 `45000` 或 `60000`。探測、聊天查詢、反應、編輯和健康檢查目前仍保留較短的 10 秒預設值;後續計畫將涵蓋範圍擴展到反應和編輯。每個帳號的覆寫:`channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`。
|
||||
- `channels.bluebubbles.chunkMode`:`length`(預設)只會在超過 `textChunkLimit` 時分割;`newline` 會先依空白行(段落邊界)分割,再依長度分段。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="媒體與歷史記錄">
|
||||
- `channels.bluebubbles.mediaMaxMb`:傳入/傳出媒體大小上限,以 MB 計(預設:8)。
|
||||
- `channels.bluebubbles.mediaLocalRoots`:明確允許用於傳出本機媒體路徑的絕對本機目錄清單。除非已設定此項,否則預設拒絕傳送本機路徑。每個帳號的覆寫:`channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`。
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`:將連續的同寄件者 DM Webhook 合併為一次代理程式回合,讓 Apple 的文字+URL 分開傳送能以單一訊息抵達(預設:`false`)。如需情境、視窗調整與取捨,請參閱[合併分開傳送的 DM](#coalescing-split-send-dms-command--url-in-one-composition)。啟用且未明確設定 `messages.inbound.byChannel.bluebubbles` 時,會將預設傳入防抖視窗從 500 毫秒放寬為 2500 毫秒。
|
||||
- `channels.bluebubbles.historyLimit`:用於上下文的群組訊息數量上限(0 表示停用)。
|
||||
- `channels.bluebubbles.dmHistoryLimit`:DM 歷史記錄限制。
|
||||
- `channels.bluebubbles.replyContextApiFallback`:當傳入回覆缺少 `replyToBody`/`replyToSender`,且記憶體中的回覆上下文快取未命中時,以盡力而為的後備方式從 BlueBubbles HTTP API 擷取原始訊息(預設:`false`)。適用於共用同一個 BlueBubbles 帳號的多執行個體部署、程序重新啟動後,或長時間存活的 TTL/LRU 快取遭逐出後。此擷取受與所有其他 BlueBubbles 用戶端請求相同的 SSRF 防護政策保護,絕不會擲出錯誤,並會填入快取,讓後續回覆分攤成本。每個帳號的覆寫:`channels.bluebubbles.accounts.<accountId>.replyContextApiFallback`。頻道層級設定會傳播到省略此旗標的帳號。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="動作與帳號">
|
||||
- `channels.bluebubbles.actions`:啟用/停用特定動作。
|
||||
- `channels.bluebubbles.accounts`:多帳號設定。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
相關全域選項:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。
|
||||
- `messages.responsePrefix`。
|
||||
|
||||
## 定址 / 傳送目標
|
||||
|
||||
偏好使用 `chat_guid` 以取得穩定路由:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123`(群組建議使用)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 直接帳號代稱:`+15555550123`、`user@example.com`
|
||||
- 如果直接帳號代稱沒有現有的 DM 聊天,OpenClaw 會透過 `POST /api/v1/chat/new` 建立一個。這需要啟用 BlueBubbles Private API。
|
||||
|
||||
### iMessage 與 SMS 路由
|
||||
|
||||
當同一個帳號代稱在 Mac 上同時有 iMessage 和 SMS 聊天時(例如某個電話號碼已註冊 iMessage,但也曾收到綠色泡泡後備訊息),OpenClaw 會偏好 iMessage 聊天,且絕不會無聲降級到 SMS。若要強制使用 SMS 聊天,請使用明確的 `sms:` 目標前綴(例如 `sms:+15555550123`)。沒有相符 iMessage 聊天的帳號代稱,仍會透過 BlueBubbles 回報的任何聊天傳送。
|
||||
|
||||
## 安全性
|
||||
|
||||
- Webhook 請求會透過比對 `guid`/`password` 查詢參數或標頭與 `channels.bluebubbles.password` 進行驗證。
|
||||
- 請保密 API 密碼和 Webhook 端點(將它們視為憑證)。
|
||||
- BlueBubbles Webhook 驗證沒有 localhost 旁路。如果你代理 Webhook 流量,請讓 BlueBubbles 密碼在請求端到端保留。`gateway.trustedProxies` 在此不會取代 `channels.bluebubbles.password`。請參閱 [Gateway 安全性](/zh-TW/gateway/security#reverse-proxy-configuration)。
|
||||
- 如果將 BlueBubbles 伺服器暴露到 LAN 之外,請啟用 HTTPS 與防火牆規則。
|
||||
|
||||
## 疑難排解
|
||||
|
||||
- 如果輸入/讀取事件停止運作,請檢查 BlueBubbles Webhook 記錄,並確認 Gateway 路徑符合 `channels.bluebubbles.webhookPath`。
|
||||
- 配對碼會在一小時後到期;請使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
|
||||
- 反應需要 BlueBubbles Private API(`POST /api/v1/message/react`);請確認伺服器版本有公開它。
|
||||
- 編輯/收回需要 macOS 13+ 和相容的 BlueBubbles 伺服器版本。在 macOS 26(Tahoe)上,編輯目前因 Private API 變更而無法運作。
|
||||
- 群組圖示更新在 macOS 26(Tahoe)上可能不穩定:API 可能回傳成功,但新圖示不會同步。
|
||||
- OpenClaw 會根據 BlueBubbles 伺服器的 macOS 版本自動隱藏已知無法運作的動作。如果編輯仍出現在 macOS 26(Tahoe)上,請用 `channels.bluebubbles.actions.edit=false` 手動停用。
|
||||
- 已啟用 `coalesceSameSenderDms`,但分開傳送(例如 `Dump` + URL)仍以兩個回合抵達:請參閱[分開傳送合併疑難排解](#split-send-coalescing-troubleshooting)檢查清單 - 常見原因包括防抖視窗太緊、工作階段記錄時間戳記被誤讀為 Webhook 抵達時間,或傳送的是回覆引用(它使用 `replyToBody`,不是第二個 Webhook)。
|
||||
- 如需狀態/健康資訊:`openclaw status --all` 或 `openclaw status --deep`。
|
||||
|
||||
如需一般頻道工作流程參考,請參閱[頻道](/zh-TW/channels)和 [Plugins](/zh-TW/tools/plugin) 指南。
|
||||
|
||||
## 相關
|
||||
|
||||
- [頻道路由](/zh-TW/channels/channel-routing) - 訊息的工作階段路由
|
||||
- [頻道概覽](/zh-TW/channels) - 所有支援的頻道
|
||||
- [群組](/zh-TW/channels/groups) - 群組聊天行為與提及閘門檢查
|
||||
- [配對](/zh-TW/channels/pairing) - DM 驗證與配對流程
|
||||
- [安全性](/zh-TW/gateway/security) - 存取模型與強化
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
read_when:
|
||||
- 您正在安裝、設定或稽核 bluebubbles Plugin
|
||||
summary: 新增 BlueBubbles 頻道介面,用於傳送和接收 OpenClaw 訊息。
|
||||
title: BlueBubbles Plugin
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:39:35Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 7946a26ab304025ed8c40ea9477e3846547bbecd7952a257001eb003abf6c521
|
||||
source_path: plugins/reference/bluebubbles.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# BlueBubbles Plugin
|
||||
|
||||
新增 BlueBubbles 通道介面,用於傳送和接收 OpenClaw 訊息。
|
||||
|
||||
## 發行
|
||||
|
||||
- 套件:`@openclaw/bluebubbles`
|
||||
- 安裝途徑:npm;ClawHub
|
||||
|
||||
## 介面
|
||||
|
||||
channels: bluebubbles
|
||||
|
||||
## 相關文件
|
||||
|
||||
- [bluebubbles](/zh-TW/channels/bluebubbles)
|
||||
Loading…
Reference in New Issue
Block a user