Mainstream messaging
iMessage
وضعیت: یکپارچهسازی بومی CLI خارجی. Gateway، imsg rpc را اجرا میکند و از طریق JSON-RPC روی stdio ارتباط برقرار میکند (بدون daemon/port جداگانه). کنشهای پیشرفته به imsg launch و یک بررسی موفق API خصوصی نیاز دارند.
پاسخها، tapbackها، افکتها، پیوستها و مدیریت گروه.
پیامهای مستقیم iMessage بهصورت پیشفرض در حالت جفتسازی هستند.
وقتی Gateway روی Mac مربوط به Messages اجرا نمیشود، از یک پوشش SSH استفاده کنید.
مرجع کامل فیلدهای iMessage.
راهاندازی سریع
Mac محلی (مسیر سریع)
نصب و بررسی imsg
brew install steipete/tap/imsgimsg rpc --helpimsg launchopenclaw channels status --probeپیکربندی OpenClaw
{channels: {imessage: {enabled: true,cliPath: "/usr/local/bin/imsg",dbPath: "/Users/user/Library/Messages/chat.db",},},}راهاندازی gateway
openclaw gatewayتأیید نخستین جفتسازی پیام مستقیم (dmPolicy پیشفرض)
openclaw pairing list imessageopenclaw pairing approve imessage <CODE>درخواستهای جفتسازی پس از ۱ ساعت منقضی میشوند.
Mac راهدور از طریق SSH
OpenClaw فقط به یک cliPath سازگار با stdio نیاز دارد، بنابراین میتوانید cliPath را به یک اسکریپت پوششی اشاره دهید که با SSH به یک Mac راهدور وصل میشود و imsg را اجرا میکند.
#!/usr/bin/env bashexec ssh -T gateway-host imsg "$@"پیکربندی پیشنهادی وقتی پیوستها فعال هستند:
{channels: {imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "user@gateway-host", // used for SCP attachment fetches includeAttachments: true, // Optional: override allowed attachment roots. // Defaults include /Users/*/Library/Messages/Attachments attachmentRoots: ["/Users/*/Library/Messages/Attachments"], remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"],},},}اگر remoteHost تنظیم نشده باشد، OpenClaw تلاش میکند با تحلیل اسکریپت پوششی SSH آن را بهطور خودکار تشخیص دهد.
remoteHost باید host یا user@host باشد (بدون فاصله یا گزینههای SSH).
OpenClaw برای SCP از بررسی سختگیرانه کلید میزبان استفاده میکند، بنابراین کلید میزبان relay باید از قبل در ~/.ssh/known_hosts وجود داشته باشد.
مسیرهای پیوست در برابر ریشههای مجاز (attachmentRoots / remoteAttachmentRoots) اعتبارسنجی میشوند.
نیازمندیها و مجوزها (macOS)
- Messages باید روی Mac اجراکننده
imsgوارد حساب شده باشد. - برای زمینه فرایندی که OpenClaw/
imsgرا اجرا میکند، دسترسی کامل دیسک لازم است (دسترسی به پایگاه داده Messages). - برای ارسال پیامها از طریق Messages.app، مجوز Automation لازم است.
- برای کنشهای پیشرفته (واکنش / ویرایش / لغو ارسال / پاسخ رشتهای / افکتها / عملیات گروهی)، System Integrity Protection باید غیرفعال باشد — بخش فعالسازی API خصوصی imsg را در پایین ببینید. ارسال/دریافت متن و رسانه پایه بدون آن کار میکند.
فعالسازی API خصوصی imsg
imsg در دو حالت عملیاتی عرضه میشود:
- حالت پایه (پیشفرض، بدون نیاز به تغییر SIP): متن و رسانه خروجی از طریق
send، پایش/تاریخچه ورودی، فهرست گفتگوها. این همان چیزی است که بلافاصله پس از یکbrew install steipete/tap/imsgتازه، همراه با مجوزهای استاندارد macOS در بالا، دریافت میکنید. - حالت API خصوصی:
imsgیک dylib کمکی را بهMessages.appتزریق میکند تا توابع داخلیIMCoreرا فراخوانی کند. این همان چیزی است کهreact،edit،unsend،reply(رشتهای)،sendWithEffect،renameGroup،setGroupIcon،addParticipant،removeParticipant،leaveGroup، بهعلاوه نشانگرهای تایپ و رسیدهای خواندن را فعال میکند.
برای رسیدن به سطح کنش پیشرفتهای که این صفحه کانال مستند میکند، به حالت API خصوصی نیاز دارید. README مربوط به imsg درباره این نیاز صریح است:
قابلیتهای پیشرفته مانند
read،typing،launch، ارسال غنی مبتنی بر bridge، تغییر پیام، و مدیریت گفتگو اختیاری هستند. آنها نیاز دارند SIP غیرفعال باشد و یک dylib کمکی بهMessages.appتزریق شود. وقتی SIP فعال باشد،imsg launchاز تزریق خودداری میکند.
روش تزریق کمکی از dylib خود imsg برای دسترسی به APIهای خصوصی Messages استفاده میکند. در مسیر iMessage مربوط به OpenClaw هیچ سرور شخص ثالث یا runtime مربوط به BlueBubbles وجود ندارد.
راهاندازی
-
imsgرا نصب (یا ارتقا) کنید روی Macی که Messages.app را اجرا میکند:bash brew install steipete/tap/imsgimsg --versionimsg status --jsonخروجی
imsg status --json،bridge_version،rpc_methodsوselectorsمربوط به هر روش را گزارش میکند تا پیش از شروع ببینید build فعلی از چه چیزهایی پشتیبانی میکند. -
System Integrity Protection را غیرفعال کنید. این مورد وابسته به نسخه macOS است، چون نیاز زیربنایی Apple به سیستمعامل و سختافزار بستگی دارد:
- macOS 10.13–10.15 (Sierra–Catalina): Library Validation را از طریق Terminal غیرفعال کنید، به Recovery Mode راهاندازی مجدد کنید،
csrutil disableرا اجرا کنید، سپس دوباره راهاندازی کنید. - macOS 11+ (Big Sur و نسخههای بعدی)، Intel: Recovery Mode (یا Internet Recovery)،
csrutil disable، سپس راهاندازی مجدد. - macOS 11+، Apple Silicon: دنباله راهاندازی با دکمه روشن/خاموش برای ورود به Recovery؛ در نسخههای اخیر macOS هنگام کلیک روی Continue کلید Left Shift را نگه دارید، سپس
csrutil disable. تنظیمات ماشین مجازی مسیر جداگانهای دارند — ابتدا یک snapshot از VM بگیرید. - macOS 26 / Tahoe: سیاستهای library-validation و بررسیهای مجوز خصوصی
imagentسختگیرانهتر شدهاند؛ ممکن استimsgبرای همگام ماندن به build بهروز نیاز داشته باشد. اگر پس از ارتقای عمده macOS، تزریقimsg launchیاselectorsخاص شروع به برگرداندن false کردند، پیش از فرض موفق بودن مرحله SIP، یادداشتهای انتشارimsgرا بررسی کنید.
پیش از اجرای
imsg launch، جریان Recovery-mode مربوط به Apple را برای Mac خود دنبال کنید تا SIP را غیرفعال کنید. - macOS 10.13–10.15 (Sierra–Catalina): Library Validation را از طریق Terminal غیرفعال کنید، به Recovery Mode راهاندازی مجدد کنید،
-
کمککننده را تزریق کنید. با SIP غیرفعال و Messages.app وارد حسابشده:
bash imsg launchوقتی SIP هنوز فعال باشد،
imsg launchاز تزریق خودداری میکند، بنابراین این فرمان همچنین تأییدی است که مرحله ۲ اثر کرده است. -
bridge را از OpenClaw بررسی کنید:
bash openclaw channels status --probeورودی iMessage باید
worksگزارش کند، وimsg status --json | jq '.selectors'بایدretractMessagePart: trueرا بههمراه هر selector ویرایش / تایپ / خواندنی که build macOS شما ارائه میدهد نشان دهد. دروازهبندی هر روش در Plugin مربوط به OpenClaw درactions.tsفقط کنشهایی را تبلیغ میکند که selector زیربنایی آنهاtrueباشد، بنابراین سطح کنشی که در فهرست ابزارهای agent میبینید بازتابدهنده کاری است که bridge واقعاً میتواند روی این میزبان انجام دهد.
اگر openclaw channels status --probe کانال را بهعنوان works گزارش میکند اما کنشهای مشخص در زمان dispatch خطای "iMessage <action> requires the imsg private API bridge" میدهند، imsg launch را دوباره اجرا کنید — کمککننده ممکن است از کار بیفتد (راهاندازی مجدد Messages.app، بهروزرسانی OS و غیره) و وضعیت cacheشده available: true تا زمانی که بررسی بعدی تازهسازی شود، همچنان کنشها را تبلیغ میکند.
وقتی نمیتوانید SIP را غیرفعال کنید
اگر غیرفعال بودن SIP برای مدل تهدید شما قابل قبول نیست:
imsgبه حالت پایه برمیگردد — فقط متن + رسانه + دریافت.- Plugin مربوط به OpenClaw همچنان ارسال متن/رسانه و پایش ورودی را تبلیغ میکند؛ فقط
react،edit،unsend،reply،sendWithEffectو عملیات گروهی را از سطح کنش پنهان میکند (مطابق دروازه قابلیت هر روش). - میتوانید برای بار کاری iMessage یک Mac جداگانه غیر Apple-Silicon (یا یک Mac اختصاصی bot) با SIP خاموش اجرا کنید، در حالی که SIP را روی دستگاههای اصلی خود فعال نگه میدارید. بخش کاربر macOS اختصاصی bot (هویت iMessage جداگانه) را در پایین ببینید.
کنترل دسترسی و مسیریابی
سیاست پیام مستقیم
channels.imessage.dmPolicy پیامهای مستقیم را کنترل میکند:
pairing(پیشفرض)allowlistopen(نیاز داردallowFromشامل"*"باشد)disabled
فیلد allowlist: channels.imessage.allowFrom.
ورودیهای allowlist باید فرستندگان را مشخص کنند: handleها یا گروههای دسترسی ایستای فرستنده (accessGroup:<name>). برای هدفهای گفتگو مانند chat_id:*، chat_guid:* یا chat_identifier:* از channels.imessage.groupAllowFrom استفاده کنید؛ برای کلیدهای رجیستری عددی chat_id از channels.imessage.groups استفاده کنید.
سیاست گروه + mentionها
channels.imessage.groupPolicy مدیریت گروه را کنترل میکند:
allowlist(پیشفرض هنگام پیکربندی)opendisabled
allowlist فرستنده گروه: channels.imessage.groupAllowFrom.
ورودیهای groupAllowFrom همچنین میتوانند به گروههای دسترسی ایستای فرستنده (accessGroup:<name>) ارجاع دهند.
fallback زمان اجرا: اگر groupAllowFrom تنظیم نشده باشد، بررسیهای فرستنده گروه iMessage از allowFrom استفاده میکنند؛ وقتی پذیرش پیام مستقیم و گروه باید متفاوت باشد، groupAllowFrom را تنظیم کنید.
یادداشت زمان اجرا: اگر channels.imessage کاملاً وجود نداشته باشد، runtime به groupPolicy="allowlist" برمیگردد و یک هشدار ثبت میکند (حتی اگر channels.defaults.groupPolicy تنظیم شده باشد).
کنترل اشاره برای گروهها:
- iMessage فرادادهٔ اشارهٔ بومی ندارد
- تشخیص اشاره از الگوهای regex استفاده میکند (
agents.list[].groupChat.mentionPatterns، با جایگزینmessages.groupChat.mentionPatterns) - بدون الگوهای پیکربندیشده، کنترل اشاره قابل اعمال نیست
فرمانهای کنترلی از فرستندگان مجاز میتوانند کنترل اشاره را در گروهها دور بزنند.
systemPrompt برای هر گروه:
هر ورودی زیر channels.imessage.groups.* یک رشتهٔ اختیاری systemPrompt میپذیرد. مقدار در هر نوبتی که پیامی را در آن گروه پردازش میکند، به system prompt عامل تزریق میشود. تفکیک همانند تفکیک prompt برای هر گروه است که توسط channels.whatsapp.groups استفاده میشود:
- system prompt مخصوص گروه (
groups["<chat_id>"].systemPrompt): وقتی ورودی گروه مشخص در نگاشت وجود داشته باشد و کلیدsystemPromptآن تعریف شده باشد، استفاده میشود. اگرsystemPromptیک رشتهٔ خالی ("") باشد، wildcard سرکوب میشود و هیچ system prompt برای آن گروه اعمال نمیشود. - system prompt wildcard گروه (
groups["*"].systemPrompt): وقتی ورودی گروه مشخص کاملاً در نگاشت وجود نداشته باشد، یا وقتی وجود داشته باشد اما هیچ کلیدsystemPromptتعریف نکند، استفاده میشود.
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123"], groups: { "*": { systemPrompt: "Use British spelling." }, "8421": { requireMention: true, systemPrompt: "This is the on-call rotation chat. Keep replies under 3 sentences.", }, "9907": { // explicit suppression: the wildcard "Use British spelling." does not apply here systemPrompt: "", }, }, }, },}promptهای هر گروه فقط برای پیامهای گروهی اعمال میشوند — پیامهای مستقیم در این کانال تحت تأثیر قرار نمیگیرند.
جلسهها و پاسخهای قطعی
- DMها از مسیریابی مستقیم استفاده میکنند؛ گروهها از مسیریابی گروهی استفاده میکنند.
- با مقدار پیشفرض
session.dmScope=main، DMهای iMessage در جلسهٔ اصلی عامل ادغام میشوند. - جلسههای گروهی جدا هستند (
agent:<agentId>:imessage:group:<chat_id>). - پاسخها با استفاده از فرادادهٔ کانال/هدف مبدأ، به iMessage برگردانده میشوند.
رفتار رشتهگفتگوی شبیه گروه:
برخی رشتهگفتگوهای iMessage با چند شرکتکننده ممکن است با is_group=false وارد شوند.
اگر آن chat_id بهطور صریح زیر channels.imessage.groups پیکربندی شده باشد، OpenClaw آن را بهعنوان ترافیک گروهی در نظر میگیرد (کنترل گروه + جداسازی جلسهٔ گروهی).
اتصالهای مکالمهٔ ACP
گفتگوهای قدیمی iMessage نیز میتوانند به جلسههای ACP متصل شوند.
روند سریع اپراتور:
/acp spawn codex --bind hereرا داخل DM یا گفتگوی گروهی مجاز اجرا کنید.- پیامهای آینده در همان مکالمهٔ iMessage به جلسهٔ ACP ایجادشده مسیریابی میشوند.
/newو/resetهمان جلسهٔ ACP متصل را درجا بازنشانی میکنند./acp closeجلسهٔ ACP را میبندد و اتصال را حذف میکند.
اتصالهای پایدار پیکربندیشده از طریق ورودیهای سطح بالای bindings[] با type: "acp" و match.channel: "imessage" پشتیبانی میشوند.
match.peer.id میتواند از این موارد استفاده کند:
- شناسهٔ نرمالشدهٔ DM مانند
+15555550123یاuser@example.com chat_id:<id>(برای اتصالهای پایدار گروهی توصیه میشود)chat_guid:<guid>chat_identifier:<identifier>
مثال:
{ agents: { list: [ { id: "codex", runtime: { type: "acp", acp: { agent: "codex", backend: "acpx", mode: "persistent" }, }, }, ], }, bindings: [ { type: "acp", agentId: "codex", match: { channel: "imessage", accountId: "default", peer: { kind: "group", id: "chat_id:123" }, }, acp: { label: "codex-group" }, }, ],}برای رفتار مشترک اتصال ACP، عاملهای ACP را ببینید.
الگوهای استقرار
کاربر اختصاصی macOS برای بات (هویت جداگانهٔ iMessage)
از یک Apple ID و کاربر macOS اختصاصی استفاده کنید تا ترافیک بات از پروفایل شخصی Messages شما جدا باشد.
روند معمول:
- یک کاربر اختصاصی macOS ایجاد کنید/وارد آن شوید.
- در همان کاربر با Apple ID بات وارد Messages شوید.
imsgرا در همان کاربر نصب کنید.- wrapper مربوط به SSH را بسازید تا OpenClaw بتواند
imsgرا در زمینهٔ همان کاربر اجرا کند. channels.imessage.accounts.<id>.cliPathو.dbPathرا به پروفایل همان کاربر اشاره دهید.
اجرای نخست ممکن است در جلسهٔ همان کاربر بات به تأییدهای GUI نیاز داشته باشد (Automation + Full Disk Access).
Mac راهدور از طریق Tailscale (مثال)
توپولوژی رایج:
- Gateway روی Linux/VM اجرا میشود
- iMessage +
imsgروی یک Mac در tailnet شما اجرا میشود - wrapper مربوط به
cliPathاز SSH برای اجرایimsgاستفاده میکند remoteHostدریافت پیوستها با SCP را فعال میکند
مثال:
{ channels: { imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "bot@mac-mini.tailnet-1234.ts.net", includeAttachments: true, dbPath: "/Users/bot/Library/Messages/chat.db", }, },}#!/usr/bin/env bashexec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"از کلیدهای SSH استفاده کنید تا هم SSH و هم SCP غیرتعاملی باشند.
ابتدا مطمئن شوید کلید میزبان مورد اعتماد است (برای مثال ssh bot@mac-mini.tailnet-1234.ts.net) تا known_hosts پر شود.
الگوی چندحسابی
iMessage از پیکربندی هر حساب زیر channels.imessage.accounts پشتیبانی میکند.
هر حساب میتواند فیلدهایی مانند cliPath، dbPath، allowFrom، groupPolicy، mediaMaxMb، تنظیمات history، و فهرستهای مجاز ریشهٔ پیوست را بازنویسی کند.
رسانه، تکهبندی، و هدفهای تحویل
پیوستها و رسانه
- دریافت پیوستهای ورودی بهطور پیشفرض خاموش است — برای ارسال عکسها، یادداشتهای صوتی، ویدئو، و پیوستهای دیگر به عامل،
channels.imessage.includeAttachments: trueرا تنظیم کنید. وقتی غیرفعال باشد، iMessageهای فقطپیوست پیش از رسیدن به عامل حذف میشوند و ممکن است اصلاً هیچ خط گزارشInbound messageتولید نکنند. - مسیرهای پیوست راهدور وقتی
remoteHostتنظیم شده باشد، میتوانند از طریق SCP دریافت شوند - مسیرهای پیوست باید با ریشههای مجاز مطابقت داشته باشند:
channels.imessage.attachmentRoots(محلی)channels.imessage.remoteAttachmentRoots(حالت SCP راهدور)- الگوی ریشهٔ پیشفرض:
/Users/*/Library/Messages/Attachments
- SCP از بررسی سختگیرانهٔ کلید میزبان استفاده میکند (
StrictHostKeyChecking=yes) - اندازهٔ رسانهٔ خروجی از
channels.imessage.mediaMaxMbاستفاده میکند (پیشفرض 16 MB)
تکهبندی خروجی
- حد تکهٔ متن:
channels.imessage.textChunkLimit(پیشفرض 4000) - حالت تکهبندی:
channels.imessage.chunkModelength(پیشفرض)newline(تقسیمبندی با اولویت پاراگراف)
قالبهای آدرسدهی
هدفهای صریح ترجیحی:
chat_id:123(برای مسیریابی پایدار توصیه میشود)chat_guid:...chat_identifier:...
هدفهای handle نیز پشتیبانی میشوند:
imessage:+1555...sms:+1555...user@example.com
imsg chats --limit 20کنشهای API خصوصی
وقتی imsg launch در حال اجراست و openclaw channels status --probe مقدار privateApi.available: true را گزارش میکند، ابزار پیام علاوه بر ارسالهای متنی عادی میتواند از کنشهای بومی iMessage استفاده کند.
{ channels: { imessage: { actions: { reactions: true, edit: true, unsend: true, reply: true, sendWithEffect: true, sendAttachment: true, renameGroup: true, setGroupIcon: true, addParticipant: true, removeParticipant: true, leaveGroup: true, }, }, },}کنشهای موجود
- react: افزودن/حذف tapbackهای iMessage (
messageId،emoji،remove). tapbackهای پشتیبانیشده به love، like، dislike، laugh، emphasize، و question نگاشت میشوند. - reply: ارسال پاسخ رشتهای به یک پیام موجود (
messageId،textیاmessage، بههمراهchatGuid،chatId،chatIdentifier، یاto). - sendWithEffect: ارسال متن با یک جلوهٔ iMessage (
textیاmessage،effectیاeffectId). - edit: ویرایش پیام ارسالشده در نسخههای پشتیبانیشدهٔ macOS/API خصوصی (
messageId،textیاnewText). - unsend: پسگرفتن پیام ارسالشده در نسخههای پشتیبانیشدهٔ macOS/API خصوصی (
messageId). - upload-file: ارسال رسانه/فایلها (
bufferبهصورت base64 یا یکmedia/path/filePathآمادهشده،filename، وasVoiceاختیاری). نام مستعار قدیمی:sendAttachment. - renameGroup، setGroupIcon، addParticipant، removeParticipant، leaveGroup: مدیریت گفتگوهای گروهی وقتی هدف فعلی یک مکالمهٔ گروهی است.
شناسههای پیام
زمینهٔ iMessage ورودی، وقتی موجود باشد، هم مقادیر کوتاه MessageSid و هم GUIDهای کامل پیام را شامل میشود. شناسههای کوتاه به cache پاسخ اخیر در حافظه محدود هستند و پیش از استفاده با گفتگوی فعلی بررسی میشوند. اگر یک شناسهٔ کوتاه منقضی شده باشد یا به گفتگوی دیگری تعلق داشته باشد، با MessageSidFull کامل دوباره تلاش کنید.
تشخیص قابلیت
OpenClaw کنشهای API خصوصی را فقط زمانی پنهان میکند که وضعیت probe ذخیرهشده در cache بگوید bridge در دسترس نیست. اگر وضعیت ناشناخته باشد، کنشها همچنان دیده میشوند و dispatch بهصورت lazy probe میکند تا نخستین کنش بتواند پس از imsg launch بدون refresh وضعیت دستی جداگانه موفق شود.
رسیدهای خواندن و تایپ
وقتی bridge مربوط به API خصوصی فعال باشد، گفتگوهای ورودی پذیرفتهشده پیش از dispatch بهعنوان خواندهشده علامتگذاری میشوند و هنگام تولید پاسخ توسط عامل، حباب تایپ به فرستنده نشان داده میشود. علامتگذاری خواندن را با این پیکربندی غیرفعال کنید:
{ channels: { imessage: { sendReadReceipts: false, }, },}buildهای قدیمیتر imsg که پیش از فهرست قابلیتهای هر متد هستند، تایپ/خواندن را بیصدا gate میکنند؛ OpenClaw در هر راهاندازی دوباره یک هشدار یکباره ثبت میکند تا نبود receipt قابل نسبت دادن باشد.
tapbackهای ورودی
OpenClaw در tapbackهای iMessage مشترک میشود و واکنشهای پذیرفتهشده را بهجای متن پیام عادی، بهعنوان رخدادهای سیستم مسیریابی میکند؛ بنابراین tapback کاربر یک حلقهٔ پاسخ معمولی را فعال نمیکند.
حالت اعلان با channels.imessage.reactionNotifications کنترل میشود:
"own"(پیشفرض): فقط وقتی کاربران به پیامهای نوشتهشده توسط بات واکنش نشان میدهند، اطلاع بده."all": برای همهٔ tapbackهای ورودی از فرستندگان مجاز اطلاع بده."off": tapbackهای ورودی را نادیده بگیر.
بازنویسیهای هر حساب از channels.imessage.accounts.<id>.reactionNotifications استفاده میکنند.
نوشتن پیکربندی
iMessage بهطور پیشفرض امکان نوشتن پیکربندی آغازشده از کانال را میدهد (برای /config set|unset وقتی commands.config: true باشد).
غیرفعالسازی:
{ channels: { imessage: { configWrites: false, }, },}ادغام DMهای ارسالشده بهصورت جداشده (فرمان + URL در یک ترکیب)
وقتی کاربر یک فرمان و یک URL را با هم تایپ میکند — مثلاً Dump https://example.com/article — برنامهٔ Messages اپل ارسال را به دو ردیف جداگانهٔ chat.db تقسیم میکند:
- یک پیام متنی (
"Dump"). - یک بالون پیشنمایش URL (
"https://...") با تصاویر پیشنمایش OG بهعنوان پیوست.
این دو ردیف در بیشتر راهاندازیها با فاصله حدود 0.8 تا 2.0 ثانیه به OpenClaw میرسند. بدون ادغام، عامل در نوبت 1 فقط فرمان را دریافت میکند، پاسخ میدهد (اغلب «URL را برایم بفرست») و URL را فقط در نوبت 2 میبیند؛ در این نقطه، زمینه فرمان از قبل از دست رفته است. این خط لوله ارسال Apple است، نه چیزی که OpenClaw یا imsg اضافه کرده باشد.
channels.imessage.coalesceSameSenderDms یک DM را به ادغام ردیفهای پیاپی از همان فرستنده در یک نوبت واحد عامل وارد میکند. گفتگوهای گروهی همچنان هر پیام را جداگانه ارسال میکنند تا ساختار نوبت چندکاربره حفظ شود.
When to enable
زمانی فعال کنید که:
- Skillsی ارائه میکنید که انتظار دارند
command + payloadدر یک پیام باشد (dump، paste، save، queue و غیره). - کاربران شما URLها، تصاویر، یا محتوای طولانی را کنار فرمانها جایگذاری میکنند.
- میتوانید تأخیر اضافهشده در نوبت DM را بپذیرید (پایینتر را ببینید).
زمانی غیرفعال نگه دارید که:
- برای محرکهای DM تککلمهای به کمترین تأخیر فرمان نیاز دارید.
- همه جریانهای شما فرمانهای یکمرحلهای بدون پیگیری payload هستند.
Enabling
{ channels: { imessage: { coalesceSameSenderDms: true, // opt in (default: false) }, },}با روشن بودن این پرچم و بدون messages.inbound.byChannel.imessage صریح، پنجره دیبانس به 2500 ms گسترش مییابد (پیشفرض قدیمی 0 ms است، یعنی بدون دیبانس). این پنجره گستردهتر لازم است چون آهنگ ارسالِ تقسیمشده Apple با فاصله 0.8 تا 2.0 ثانیه در پیشفرضی تنگتر جا نمیشود.
برای تنظیم دستی این پنجره:
{ 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). imessage: 2500, }, }, },}Trade-offs
- تأخیر اضافه برای پیامهای DM. با روشن بودن این پرچم، هر DM (از جمله فرمانهای کنترلی مستقل و پیگیریهای تکمتنی) تا سقف پنجره دیبانس منتظر میماند و سپس ارسال میشود، شاید ردیف payload در راه باشد. پیامهای گفتگوی گروهی ارسال فوری را حفظ میکنند.
- خروجی ادغامشده محدود است. متن ادغامشده با نشانگر صریح
…[truncated]در 4000 نویسه محدود میشود؛ پیوستها به 20 محدود میشوند؛ ورودیهای منبع به 10 محدود میشوند (پس از آن، اولین و تازهترین مورد نگه داشته میشوند). هر GUID منبع برای تلهمتری پاییندست درcoalescedMessageGuidsردیابی میشود. - فقط DM. گفتگوهای گروهی به ارسال هر پیام بهصورت جداگانه عبور میکنند تا bot هنگام تایپ چند نفر پاسخگو بماند.
- اختیاری، برای هر کانال. کانالهای دیگر (Telegram، WhatsApp، Slack، …) بیتأثیر میمانند. پیکربندیهای قدیمی BlueBubbles که
channels.bluebubbles.coalesceSameSenderDmsرا تنظیم کردهاند باید آن مقدار را بهchannels.imessage.coalesceSameSenderDmsمنتقل کنند.
سناریوها و آنچه عامل میبیند
| آنچه کاربر مینویسد | آنچه chat.db تولید میکند |
پرچم خاموش (پیشفرض) | پرچم روشن + پنجره 2500 ms |
|---|---|---|---|
Dump https://example.com (یک ارسال) |
2 ردیف با فاصله حدود 1 ثانیه | دو نوبت عامل: فقط «Dump»، سپس URL | یک نوبت: متن ادغامشده Dump https://example.com |
Save this 📎image.jpg caption (پیوست + متن) |
2 ردیف | دو نوبت (پیوست هنگام ادغام حذف میشود) | یک نوبت: متن + تصویر حفظ میشود |
/status (فرمان مستقل) |
1 ردیف | ارسال فوری | تا سقف پنجره منتظر میماند، سپس ارسال میکند |
| URL بهتنهایی جایگذاری شده | 1 ردیف | ارسال فوری | ارسال فوری (فقط یک ورودی در bucket) |
| متن + URL که عمداً بهصورت دو پیام جدا، با فاصله چند دقیقه فرستاده شدهاند | 2 ردیف خارج از پنجره | دو نوبت | دو نوبت (پنجره بین آنها منقضی میشود) |
| سیل سریع (>10 DM کوچک داخل پنجره) | N ردیف | N نوبت | یک نوبت، خروجی محدود (اولین + تازهترین، سقفهای متن/پیوست اعمال میشود) |
| دو نفر در یک گفتگوی گروهی تایپ میکنند | N ردیف از M فرستنده | M+ نوبت (یکی برای هر bucket فرستنده) | M+ نوبت؛ گفتگوهای گروهی ادغام نمیشوند |
جبران پس از توقف Gateway
وقتی Gateway آفلاین است (خرابی، راهاندازی دوباره، خواب Mac، خاموش بودن دستگاه)، imsg watch پس از بالا آمدن دوباره Gateway از وضعیت فعلی chat.db ادامه میدهد؛ هر چیزی که در این فاصله رسیده باشد، بهصورت پیشفرض هرگز دیده نمیشود. جبران این پیامها را در راهاندازی بعدی بازپخش میکند تا عامل بیصدا ترافیک ورودی را از دست ندهد.
جبران بهصورت پیشفرض غیرفعال است. آن را برای هر کانال فعال کنید:
channels: { imessage: { catchup: { enabled: true, // master switch (default: false) maxAgeMinutes: 120, // skip rows older than now - 2h (default: 120, clamp 1..720) perRunLimit: 50, // max rows replayed per startup (default: 50, clamp 1..500) firstRunLookbackMinutes: 30, // first run with no cursor: look back 30 min (default: 30) maxFailureRetries: 10, // give up on a wedged guid after 10 dispatch failures (default: 10) }, },}نحوه اجرا
یک گذر در هر راهاندازی monitorIMessageProvider، بهترتیب imsg launch آماده → watch.subscribe → performIMessageCatchup → حلقه ارسال زنده. خود جبران از chats.list + messages.history برای هر گفتگو، روی همان کارخواه JSON-RPC که imsg watch استفاده میکند، بهره میبرد. هر چیزی که هنگام گذر جبران برسد، طبق معمول از مسیر ارسال زنده عبور میکند؛ کش موجود حذف تکرار ورودی، هر همپوشانی با ردیفهای بازپخششده را جذب میکند.
هر ردیف بازپخششده از مسیر ارسال زنده (evaluateIMessageInbound + dispatchInboundMessage) عبور داده میشود، بنابراین فهرستهای مجاز، سیاست گروه، دیبانسر، کش echo، و رسیدهای خواندن برای پیامهای بازپخششده و زنده رفتار یکسانی دارند.
معناشناسی cursor و تلاش دوباره
جبران برای هر حساب یک cursor در <openclawStateDir>/imessage/catchup/<account>__<hash>.json نگه میدارد (دایرکتوری وضعیت OpenClaw بهصورت پیشفرض ~/.openclaw است و با OPENCLAW_STATE_DIR قابل بازنویسی است):
{ "lastSeenMs": 1717900800000, "lastSeenRowid": 482910, "updatedAt": 1717900801234, "failureRetries": { "<guid>": 1 }}- cursor در هر ارسال موفق جلو میرود و وقتی ارسال یک ردیف خطا میدهد، نگه داشته میشود؛ راهاندازی بعدی همان ردیف را از cursor نگهداشتهشده دوباره امتحان میکند.
- پس از
maxFailureRetriesخطای پیاپی برای همانguid، جبران یکwarnثبت میکند و cursor را بهاجبار از پیام گیرکرده عبور میدهد تا راهاندازیهای بعدی بتوانند پیشرفت کنند. - guidهایی که از قبل کنار گذاشته شدهاند در اجراهای بعدی بهمحض دیدهشدن رد میشوند (بدون تلاش برای ارسال) و در خلاصه اجرا زیر
skippedGivenUpشمرده میشوند.
سیگنالهای قابل مشاهده برای اپراتور
imessage catchup: replayed=N skippedFromMe=… skippedGivenUp=… failed=… givenUp=… fetchedCount=…imessage catchup: giving up on guid=<guid> after <N> failures; advancing cursor past itimessage catchup: fetched <X> rows across chats, capped to perRunLimit=<Y>خط WARN ... capped to perRunLimit یعنی یک راهاندازی منفرد کل backlog را تخلیه نکرده است. اگر فاصلههای شما مرتباً از گذر پیشفرض 50 ردیفی بیشتر میشوند، perRunLimit (حداکثر 500) را افزایش دهید.
چه زمانی خاموش بماند
- Gateway بهصورت پیوسته با راهاندازی دوباره خودکار watchdog اجرا میشود و فاصلهها همیشه کمتر از چند ثانیهاند؛ پیشفرض خاموش مناسب است.
- حجم DM کم است و پیامهای ازدسترفته رفتار عامل را تغییر نمیدهند؛ پنجره اولیه
firstRunLookbackMinutesمیتواند هنگام اولین فعالسازی زمینه قدیمی غیرمنتظرهای را ارسال کند.
وقتی جبران را روشن میکنید، اولین راهاندازی بدون cursor فقط بهاندازه firstRunLookbackMinutes به عقب نگاه میکند (پیشفرض 30 دقیقه)، نه کل پنجره maxAgeMinutes؛ این از بازپخش تاریخچه طولانی پیامهای پیش از فعالسازی جلوگیری میکند.
عیبیابی
imsg not found or RPC unsupported
دودویی و پشتیبانی RPC را اعتبارسنجی کنید:
imsg rpc --helpimsg status --jsonopenclaw channels status --probeاگر probe گزارش داد RPC پشتیبانی نمیشود، imsg را بهروزرسانی کنید. اگر کنشهای private API در دسترس نیستند، imsg launch را در نشست کاربر واردشده macOS اجرا کنید و دوباره probe بگیرید. اگر Gateway روی macOS اجرا نمیشود، بهجای مسیر local پیشفرض imsg، از راهاندازی Remote Mac over SSH در بالا استفاده کنید.
Gateway is not running on macOS
مقدار پیشفرض cliPath: "imsg" باید روی Macی اجرا شود که به Messages وارد شده است. روی Linux یا Windows، channels.imessage.cliPath را روی یک اسکریپت wrapper تنظیم کنید که به آن Mac SSH میزند و imsg "$@" را اجرا میکند.
#!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"سپس اجرا کنید:
openclaw channels status --probe --channel imessageDMs are ignored
بررسی کنید:
channels.imessage.dmPolicychannels.imessage.allowFrom- تأییدهای pairing (
openclaw pairing list imessage)
Group messages are ignored
بررسی کنید:
channels.imessage.groupPolicychannels.imessage.groupAllowFrom- رفتار فهرست مجاز
channels.imessage.groups - پیکربندی الگوی mention (
agents.list[].groupChat.mentionPatterns)
Remote attachments fail
بررسی کنید:
channels.imessage.remoteHostchannels.imessage.remoteAttachmentRoots- احراز هویت کلید SSH/SCP از میزبان Gateway
- کلید میزبان در
~/.ssh/known_hostsروی میزبان Gateway وجود دارد - خوانایی مسیر remote روی Macی که Messages را اجرا میکند
macOS permission prompts were missed
دوباره در یک ترمینال GUI تعاملی در همان زمینه کاربر/نشست اجرا کنید و promptها را تأیید کنید:
imsg chats --limit 1imsg send <handle> "test"تأیید کنید Full Disk Access + Automation برای زمینه فرایندی که OpenClaw/imsg را اجرا میکند اعطا شدهاند.
اشارهگرهای مرجع پیکربندی
مرتبط
- نمای کلی کانالها — همه کانالهای پشتیبانیشده
- حذف BlueBubbles و مسیر imsg iMessage — اعلان و خلاصه مهاجرت
- مهاجرت از BlueBubbles — جدول ترجمه پیکربندی و cutover گامبهگام
- Pairing — احراز هویت DM و جریان pairing
- گروهها — رفتار گفتگوی گروهی و gating بر پایه mention
- مسیریابی کانال — مسیریابی نشست برای پیامها
- امنیت — مدل دسترسی و سختسازی