@openclaw/imessage 2026.9.8 → 2026.10.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/.setup/{accounts-nzcU0cq2.mjs → accounts-evTpvJMv.mjs} +6 -12
  2. package/dist/.setup/{group-policy-90pw4tyG.mjs → actions-DJqbUmbN.mjs} +103 -269
  3. package/dist/.setup/{actions.runtime-DdBN29zj.mjs → actions.runtime-DL5i-Y4J.mjs} +49 -84
  4. package/dist/.setup/{api-B9Qx21G-.mjs → api-SAVMfMoY.mjs} +5 -5
  5. package/dist/.setup/{api-D2S6FhGw.mjs → api-oq_MryN7.mjs} +6 -6
  6. package/dist/.setup/{approval-handler.runtime-DKSq0DWq.mjs → approval-handler.runtime-Bj2NGNXF.mjs} +26 -62
  7. package/dist/.setup/{approval-reactions-Bp33xc83.mjs → approval-reactions-L9Ul7PAu.mjs} +3 -2
  8. package/dist/.setup/{channel-9fyvuN_p.mjs → channel-CL73qdMG.mjs} +134 -60
  9. package/dist/.setup/{monitor-fv9nRuTH.mjs → channel.runtime-DY7JJ0_9.mjs} +202 -206
  10. package/dist/.setup/{sanitize-outbound-3MLljgtY.mjs → client-12apu4Ip.mjs} +26 -635
  11. package/dist/.setup/{config-schema-4Q3_EqYt.mjs → config-schema-DXwa_3V5.mjs} +1 -1
  12. package/dist/.setup/{media-contract-CagwSMvo.mjs → media-contract-DjQGZlfl.mjs} +1 -1
  13. package/dist/.setup/{message-tool-api-D032l82H.mjs → message-tool-api-CqfRxLlT.mjs} +2 -2
  14. package/dist/.setup/{question-reactions-Cy-dmU_j.mjs → question-reactions-DJV-TnA8.mjs} +2 -1
  15. package/dist/.setup/{reaction-context-Br-vAJFp.mjs → reaction-context-By7kUMBC.mjs} +2 -7
  16. package/dist/.setup/{remote-file-DRPCaVmg.mjs → remote-file-BU7pA-Zi.mjs} +7 -11
  17. package/dist/.setup/sanitize-outbound-C0x4BPky.mjs +564 -0
  18. package/dist/.setup/{send-Cu9nl757.mjs → send-pkYwL6Rt.mjs} +56 -103
  19. package/dist/.setup/{setup-core-8MDdYHj5.mjs → setup-core-DqOBe-n0.mjs} +1 -1
  20. package/dist/.setup/{setup-surface-tGXFDdWh.mjs → setup-surface-zKhIinwY.mjs} +2 -2
  21. package/dist/api.js +6 -6
  22. package/dist/channel-config-api.js +1 -1
  23. package/dist/channel-plugin-api.js +1 -1
  24. package/dist/contract-api.js +1 -1
  25. package/dist/doctor-contract-api.js +29 -21
  26. package/dist/media-contract-api.js +1 -1
  27. package/dist/message-tool-api.js +1 -1
  28. package/dist/runtime-api.js +2 -24
  29. package/dist/setup-entry.js +1 -1
  30. package/openclaw.plugin.json +1 -1
  31. package/package.json +4 -4
  32. package/dist/.setup/channel.runtime-n-MPKL8k.mjs +0 -92
  33. package/dist/.setup/state-migrations-B-Q7bO0Y.mjs +0 -47
@@ -1,13 +1,15 @@
1
1
  import { c as parseIMessageTarget, o as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-BicBiYsM.mjs";
2
- import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
3
- import { D as resolveIMessageDirectChatService, _ as IMESSAGE_SENT_ECHOES_TTL_MS, a as IMessageRpcRequestError, b as resolveIMessageEchoMediaKey, f as rememberIMessageReplyCache, g as IMESSAGE_SENT_ECHOES_NAMESPACE, n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, s as runIMessageCliJsonCommand, t as protectIMessageFencedRoleMarkers, w as chatContextFromIMessageTarget, x as resolveIMessageSentEchoEntryKey } from "./sanitize-outbound-3MLljgtY.mjs";
4
- import { c as getIMessageApprovalApprovers, l as imessageApprovalAuth } from "./group-policy-90pw4tyG.mjs";
2
+ import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-evTpvJMv.mjs";
3
+ import { C as resolveIMessageDirectChatService, _ as resolveIMessageSentEchoEntryKey, b as chatContextFromIMessageTarget, c as rememberIMessageReplyCache, f as IMESSAGE_SENT_ECHOES_NAMESPACE, g as resolveIMessageEchoMediaKey, n as createIMessageRpcClient, p as IMESSAGE_SENT_ECHOES_TTL_MS, r as runIMessageCliJsonCommand, t as IMessageRpcRequestError } from "./client-12apu4Ip.mjs";
4
+ import { a as normalizeIMessageMessageId, i as normalizeIMessageGuid } from "./actions-DJqbUmbN.mjs";
5
5
  import { n as getOptionalIMessageRuntime, t as getIMessageRuntime } from "./runtime-Cza4CY5T.mjs";
6
- import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-Bp33xc83.mjs";
7
- import { n as normalizeIMessageGuid } from "./reaction-context-Br-vAJFp.mjs";
8
- import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-DRPCaVmg.mjs";
6
+ import { d as getIMessageApprovalApprovers, f as imessageApprovalAuth } from "./channel-CL73qdMG.mjs";
7
+ import { n as sanitizeIMessageFinalOutboundText, t as protectIMessageFencedRoleMarkers } from "./sanitize-outbound-C0x4BPky.mjs";
8
+ import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-BU7pA-Zi.mjs";
9
+ import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-L9Ul7PAu.mjs";
9
10
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
11
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
12
+ import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
11
13
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
12
14
  import { accessSync, constants } from "node:fs";
13
15
  import { basename } from "node:path";
@@ -15,13 +17,14 @@ import { extractOriginalFilename, kindFromMime, resolveOutboundAttachmentFromUrl
15
17
  import { logVerbose, sleep } from "openclaw/plugin-sdk/runtime-env";
16
18
  import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
17
19
  import { PlatformMessageNotDispatchedError, isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
20
+ import { racePromiseWithAbortSignal } from "openclaw/plugin-sdk/time-runtime";
18
21
  import { addApprovalReactionHintToText, createApprovalReactionTargetStore, listApprovalReactionBindings } from "openclaw/plugin-sdk/approval-reaction-runtime";
19
22
  import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
20
23
  import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
24
+ import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
21
25
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
22
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
23
26
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
24
- import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
27
+ import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
25
28
  //#region extensions/imessage/src/approval-control-binding-window.ts
26
29
  const pendingByConversation = /* @__PURE__ */ new Map();
27
30
  function approvalControlBindingAbortError(signal) {
@@ -35,23 +38,20 @@ function bindingKeys(accountId, conversation) {
35
38
  /** Marks the send-to-binding interval during which a visible control is not yet resolvable. */
36
39
  function beginIMessageApprovalControlBinding(params) {
37
40
  const keys = bindingKeys(params.accountId, params.conversation);
38
- let resolveDone = () => {};
39
- const window = {
40
- done: new Promise((resolve) => {
41
- resolveDone = resolve;
42
- }),
43
- close: () => {}
44
- };
41
+ const { promise, resolve } = createDeferred();
45
42
  let closed = false;
46
- window.close = () => {
47
- if (closed) return;
48
- closed = true;
49
- for (const key of keys) {
50
- const windows = pendingByConversation.get(key);
51
- windows?.delete(window);
52
- if (windows?.size === 0) pendingByConversation.delete(key);
43
+ const window = {
44
+ done: promise,
45
+ close: () => {
46
+ if (closed) return;
47
+ closed = true;
48
+ for (const key of keys) {
49
+ const windows = pendingByConversation.get(key);
50
+ windows?.delete(window);
51
+ if (windows?.size === 0) pendingByConversation.delete(key);
52
+ }
53
+ resolve();
53
54
  }
54
- resolveDone();
55
55
  };
56
56
  for (const key of keys) {
57
57
  const windows = pendingByConversation.get(key) ?? /* @__PURE__ */ new Set();
@@ -66,17 +66,7 @@ async function waitForIMessageApprovalControlBinding(params) {
66
66
  for (const key of bindingKeys(params.accountId, params.conversation)) for (const window of pendingByConversation.get(key) ?? []) windows.add(window);
67
67
  if (windows.size === 0) return false;
68
68
  if (params.abortSignal?.aborted) throw approvalControlBindingAbortError(params.abortSignal);
69
- let detachAbort = () => {};
70
- const aborted = new Promise((_resolve, reject) => {
71
- const onAbort = () => reject(approvalControlBindingAbortError(params.abortSignal));
72
- params.abortSignal?.addEventListener("abort", onAbort, { once: true });
73
- detachAbort = () => params.abortSignal?.removeEventListener("abort", onAbort);
74
- });
75
- try {
76
- await Promise.race([Promise.race([...windows].map((window) => window.done)), aborted]);
77
- } finally {
78
- detachAbort();
79
- }
69
+ await racePromiseWithAbortSignal(Promise.race([...windows].map((window) => window.done)), params.abortSignal, approvalControlBindingAbortError);
80
70
  return true;
81
71
  }
82
72
  function clearIMessageApprovalControlBindingsForTest() {
@@ -451,11 +441,6 @@ function normalizeIMessageEchoText(text) {
451
441
  }
452
442
  //#endregion
453
443
  //#region extensions/imessage/src/monitor/persisted-echo-cache.ts
454
- function normalizeMessageId(messageId) {
455
- const normalized = messageId?.trim();
456
- if (!normalized || normalized === "ok" || normalized === "unknown") return;
457
- return normalized;
458
- }
459
444
  let persistenceFailureLogged = false;
460
445
  function reportFailure(scope, err) {
461
446
  if (persistenceFailureLogged) return;
@@ -512,7 +497,7 @@ async function persistEntry(entry, ttlMs) {
512
497
  async function rememberPersistedIMessageEcho(params) {
513
498
  const text = normalizeIMessageEchoText(params.text);
514
499
  const media = normalizeMedia(params.media);
515
- const messageId = normalizeMessageId(params.messageId);
500
+ const messageId = normalizeIMessageMessageId(params.messageId);
516
501
  const entry = {
517
502
  scope: params.scope,
518
503
  timestamp: Date.now(),
@@ -536,7 +521,7 @@ async function forgetPersistedIMessageEchoKey(key) {
536
521
  async function hasPersistedIMessageEcho(params) {
537
522
  const text = normalizeIMessageEchoText(params.text);
538
523
  const mediaKey = resolveIMessageEchoMediaKey(params.media);
539
- const messageId = normalizeMessageId(params.messageId);
524
+ const messageId = normalizeIMessageMessageId(params.messageId);
540
525
  if (!text && !mediaKey && !messageId) return false;
541
526
  for (const entry of await readRecentEntries()) {
542
527
  if (entry.scope !== params.scope) continue;
@@ -593,7 +578,7 @@ function isNumericMessageRowId(value) {
593
578
  function normalizeResolvedMessageGuid(value) {
594
579
  if (typeof value !== "string") return null;
595
580
  const trimmed = value.trim();
596
- return isConcreteIMessageMessageId(trimmed) && !isNumericMessageRowId(trimmed) ? trimmed : null;
581
+ return normalizeIMessageMessageId(trimmed) && !isNumericMessageRowId(trimmed) ? trimmed : null;
597
582
  }
598
583
  async function resolveMessageGuidFromChatDb(params) {
599
584
  const dbPath = params.dbPath?.trim();
@@ -653,12 +638,6 @@ async function resolveFallbackSentMessageGuid(params) {
653
638
  }
654
639
  })));
655
640
  }
656
- function shouldRecoverApprovalPromptGuid(params) {
657
- return Boolean(params.approvalPrompt && !params.filePath && !params.replyToId);
658
- }
659
- function canCheckSentMessageAfterRpcTimeout(params) {
660
- return Boolean(params.resolveSentMessageGuidImpl) || canResolveLatestSentMessageGuidFromChatDb(params.dbPath);
661
- }
662
641
  function resolveOutboundEchoMedia(mediaContentType) {
663
642
  if (!mediaContentType) return;
664
643
  return {
@@ -668,7 +647,7 @@ function resolveOutboundEchoMedia(mediaContentType) {
668
647
  }
669
648
  function createIMessageSendReceipt(params) {
670
649
  const messageId = params.messageId.trim();
671
- const results = isConcreteIMessageMessageId(messageId) ? [{
650
+ const results = normalizeIMessageMessageId(messageId) ? [{
672
651
  channel: "imessage",
673
652
  messageId,
674
653
  meta: { targetKind: params.target.kind }
@@ -678,16 +657,11 @@ function createIMessageSendReceipt(params) {
678
657
  else if (params.target.kind === "chat_guid") results[0].conversationId = params.target.chatGuid;
679
658
  else if (params.target.kind === "chat_identifier") results[0].conversationId = params.target.chatIdentifier;
680
659
  }
681
- const receiptParams = {
660
+ return createMessageReceiptFromOutboundResults({
682
661
  results,
683
- kind: params.kind
684
- };
685
- if (params.replyToId) receiptParams.replyToId = params.replyToId;
686
- return createMessageReceiptFromOutboundResults(receiptParams);
687
- }
688
- function isConcreteIMessageMessageId(messageId) {
689
- const trimmed = messageId?.trim();
690
- return Boolean(trimmed && trimmed !== "unknown" && trimmed !== "ok");
662
+ kind: params.kind,
663
+ ...params.replyToId ? { replyToId: params.replyToId } : {}
664
+ });
691
665
  }
692
666
  async function withOriginalIMessageAttachmentPath(filePath, send) {
693
667
  const filename = extractOriginalFilename(filePath);
@@ -794,27 +768,23 @@ async function trySendAttachmentForTarget(params) {
794
768
  pending: true
795
769
  });
796
770
  result = await withOriginalIMessageAttachmentPath(params.filePath, async (attachmentPath) => {
797
- if (params.remoteHost) {
798
- const requestRpc = params.requestRpc;
799
- if (!requestRpc) throw new Error("iMessage remote attachment RPC is unavailable");
800
- return await params.withRemoteFile({
801
- remoteHost: params.remoteHost,
802
- localPath: attachmentPath,
803
- timeoutMs: params.timeoutMs,
804
- assertDirectAdapterHandoff: params.assertDirectAdapterHandoff,
805
- use: async (remotePath) => {
806
- const rpcParams = {
807
- file: remotePath,
808
- ...params.audioAsVoice ? { audio: true } : {},
809
- ...params.replyToId ? { reply_to: params.replyToId } : {}
810
- };
811
- if (params.target.kind === "chat_id") rpcParams.chat_id = params.target.chatId;
812
- else if (params.target.kind === "chat_guid") rpcParams.chat_guid = params.target.chatGuid;
813
- else rpcParams.chat_identifier = attachmentChatTarget;
814
- return await requestRpc("send.attachment", rpcParams);
815
- }
816
- });
817
- }
771
+ if (params.remoteHost) return await params.withRemoteFile({
772
+ remoteHost: params.remoteHost,
773
+ localPath: attachmentPath,
774
+ timeoutMs: params.timeoutMs,
775
+ assertDirectAdapterHandoff: params.assertDirectAdapterHandoff,
776
+ use: async (remotePath) => {
777
+ const rpcParams = {
778
+ file: remotePath,
779
+ ...params.audioAsVoice ? { audio: true } : {},
780
+ ...params.replyToId ? { reply_to: params.replyToId } : {}
781
+ };
782
+ if (params.target.kind === "chat_id") rpcParams.chat_id = params.target.chatId;
783
+ else if (params.target.kind === "chat_guid") rpcParams.chat_guid = params.target.chatGuid;
784
+ else rpcParams.chat_identifier = attachmentChatTarget;
785
+ return await params.requestRpc("send.attachment", rpcParams);
786
+ }
787
+ });
818
788
  params.assertDirectAdapterHandoff?.();
819
789
  await params.onPlatformSendDispatch?.();
820
790
  params.assertDirectAdapterHandoff?.();
@@ -830,18 +800,13 @@ async function trySendAttachmentForTarget(params) {
830
800
  params.sendTransport === "bridge" ? "dylib" : params.sendTransport
831
801
  ]);
832
802
  });
803
+ const failure = resolveIMessageSendFailure(result);
804
+ if (failure) throw new Error(failure);
833
805
  } catch (error) {
834
806
  await forgetPersistedIMessageEchoKey(pendingEchoKey);
835
807
  if (!params.audioAsVoice && isAttachmentCommandFallbackError(error)) return null;
836
808
  throw error;
837
809
  }
838
- const failure = resolveIMessageSendFailure(result);
839
- if (failure) {
840
- const error = new Error(failure);
841
- await forgetPersistedIMessageEchoKey(pendingEchoKey);
842
- if (!params.audioAsVoice && isAttachmentCommandFallbackError(error)) return null;
843
- throw error;
844
- }
845
810
  const resolvedId = resolveMessageId(result);
846
811
  const approvalBindingMessageId = await resolveApprovalBindingMessageGuid({
847
812
  dbPath: params.dbPath,
@@ -856,7 +821,7 @@ async function trySendAttachmentForTarget(params) {
856
821
  media: params.echoMedia,
857
822
  messageId: resolvedId ?? void 0
858
823
  });
859
- if (resolvedId && isConcreteIMessageMessageId(resolvedId)) await rememberIMessageReplyCache({
824
+ if (resolvedId && normalizeIMessageMessageId(resolvedId)) await rememberIMessageReplyCache({
860
825
  accountId: params.accountId,
861
826
  messageId: resolvedId,
862
827
  chatGuid: params.target.kind === "chat_guid" ? params.target.chatGuid : params.target.kind === "chat_id" ? attachmentChatTarget : void 0,
@@ -1023,7 +988,6 @@ async function sendMessageIMessage(to, text, opts) {
1023
988
  try {
1024
989
  captionResult = await sendMessageIMessage(to, text, {
1025
990
  ...opts,
1026
- ...opts.client ? { client: opts.client } : {},
1027
991
  mediaUrl: void 0,
1028
992
  onDeliveryResult: void 0
1029
993
  });
@@ -1036,7 +1000,7 @@ async function sendMessageIMessage(to, text, opts) {
1036
1000
  });
1037
1001
  }
1038
1002
  return {
1039
- messageId: isConcreteIMessageMessageId(attachmentResult.messageId) ? attachmentResult.messageId : captionResult.messageId,
1003
+ messageId: normalizeIMessageMessageId(attachmentResult.messageId) ? attachmentResult.messageId : captionResult.messageId,
1040
1004
  ...captionResult.guid ?? attachmentResult.guid ? { guid: captionResult.guid ?? attachmentResult.guid } : {},
1041
1005
  sentText: captionResult.sentText,
1042
1006
  ...captionResult.echoText ?? attachmentResult.echoText ? { echoText: captionResult.echoText ?? attachmentResult.echoText } : {},
@@ -1114,14 +1078,7 @@ async function sendMessageIMessage(to, text, opts) {
1114
1078
  result = await requestSuccessfulSend(plainParams);
1115
1079
  effectiveReplyToId = void 0;
1116
1080
  } else if (filePath || !isIMessageRpcSendTimeout(error)) throw error;
1117
- else if (!shouldRecoverApprovalPromptGuid({
1118
- approvalPrompt: opts.approvalPrompt,
1119
- filePath,
1120
- replyToId: resolvedReplyToId
1121
- }) || !canCheckSentMessageAfterRpcTimeout({
1122
- dbPath: chatDbLookupPath,
1123
- resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
1124
- })) throw error;
1081
+ else if (!opts.approvalPrompt || resolvedReplyToId || !(opts.resolveSentMessageGuidImpl || canResolveLatestSentMessageGuidFromChatDb(chatDbLookupPath))) throw error;
1125
1082
  else {
1126
1083
  const recoveredGuid = await resolveFallbackSentMessageGuid({
1127
1084
  dbPath: chatDbLookupPath,
@@ -1145,11 +1102,7 @@ async function sendMessageIMessage(to, text, opts) {
1145
1102
  result,
1146
1103
  resolveMessageGuidImpl: opts.resolveMessageGuidImpl
1147
1104
  });
1148
- if (!approvalBindingMessageId && shouldRecoverApprovalPromptGuid({
1149
- approvalPrompt: opts.approvalPrompt,
1150
- filePath,
1151
- replyToId: effectiveReplyToId
1152
- })) approvalBindingMessageId = await resolveFallbackSentMessageGuid({
1105
+ if (!approvalBindingMessageId && opts.approvalPrompt && !filePath && !effectiveReplyToId) approvalBindingMessageId = await resolveFallbackSentMessageGuid({
1153
1106
  dbPath: chatDbLookupPath,
1154
1107
  target,
1155
1108
  text: message,
@@ -1164,7 +1117,7 @@ async function sendMessageIMessage(to, text, opts) {
1164
1117
  });
1165
1118
  const providerChatGuid = normalizeOptionalString(result.chat_guid) ?? normalizeOptionalString(result.chatGuid);
1166
1119
  const confirmedService = resolveIMessageDirectChatService(resultService(result.service) ?? service, providerChatGuid);
1167
- if (resolvedId && isConcreteIMessageMessageId(resolvedId)) {
1120
+ if (resolvedId && normalizeIMessageMessageId(resolvedId)) {
1168
1121
  const chatContext = chatContextFromIMessageTarget(target, confirmedService ?? service);
1169
1122
  await rememberIMessageReplyCache({
1170
1123
  accountId: account.accountId,
@@ -1,5 +1,5 @@
1
1
  import { o as normalizeIMessageHandle } from "./targets-BicBiYsM.mjs";
2
- import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
2
+ import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-evTpvJMv.mjs";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
5
5
  import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
@@ -1,5 +1,5 @@
1
- import { o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
2
- import { a as imessageCompletionNote, c as imessageSetupStatusBase, l as isAutoManagedIMessageCliPath, o as imessageDmPolicy, r as createIMessageCliPathTextInput, t as IMESSAGE_INSTALL_COMMAND, u as normalizeIMessageCliPathForSetup } from "./setup-core-8MDdYHj5.mjs";
1
+ import { o as resolveIMessageAccount } from "./accounts-evTpvJMv.mjs";
2
+ import { a as imessageCompletionNote, c as imessageSetupStatusBase, l as isAutoManagedIMessageCliPath, o as imessageDmPolicy, r as createIMessageCliPathTextInput, t as IMESSAGE_INSTALL_COMMAND, u as normalizeIMessageCliPathForSetup } from "./setup-core-DqOBe-n0.mjs";
3
3
  import path from "node:path";
4
4
  import fs from "node:fs/promises";
5
5
  import { createDetectedBinaryStatus, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
package/dist/api.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { a as looksLikeIMessageExplicitTargetId, c as parseIMessageTarget, i as isAllowedIMessageSender, l as looksLikeIMessageTargetId, n as inferIMessageTargetChatType, o as normalizeIMessageHandle, s as parseIMessageAllowTarget, t as formatIMessageChatTarget, u as normalizeIMessageMessagingTarget } from "./.setup/targets-BicBiYsM.mjs";
2
- import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, r as listEnabledIMessageAccounts } from "./.setup/accounts-nzcU0cq2.mjs";
3
- import { o as IMESSAGE_ACTIONS, s as IMESSAGE_ACTION_NAMES } from "./.setup/message-tool-api-D032l82H.mjs";
4
- import { S as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./.setup/sanitize-outbound-3MLljgtY.mjs";
5
- import { a as matchIMessageAcpConversation, d as probeIMessage, i as resolveIMessageInboundConversationId, o as normalizeIMessageAcpConversationId, r as resolveIMessageGroupToolPolicy, s as resolveIMessageConversationIdFromTarget, t as resolveIMessageGroupRequireMention } from "./.setup/group-policy-90pw4tyG.mjs";
6
- import { t as imessagePlugin } from "./.setup/channel-9fyvuN_p.mjs";
2
+ import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, r as listEnabledIMessageAccounts } from "./.setup/accounts-evTpvJMv.mjs";
3
+ import { o as IMESSAGE_ACTIONS, s as IMESSAGE_ACTION_NAMES } from "./.setup/message-tool-api-CqfRxLlT.mjs";
4
+ import { v as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./.setup/client-12apu4Ip.mjs";
5
+ import { n as probeIMessage } from "./.setup/actions-DJqbUmbN.mjs";
6
+ import { c as matchIMessageAcpConversation, i as resolveIMessageGroupRequireMention, l as normalizeIMessageAcpConversationId, o as resolveIMessageGroupToolPolicy, s as resolveIMessageInboundConversationId, t as imessagePlugin, u as resolveIMessageConversationIdFromTarget } from "./.setup/channel-CL73qdMG.mjs";
7
7
  import { t as createIMessageConversationBindingManager } from "./.setup/conversation-bindings-GDQ_Laxj.mjs";
8
- import { a as resolveServicePrefixedChatTarget, c as imessageSetupPlugin, i as resolveServicePrefixedAllowTarget, n as parseChatAllowTargetPrefixes, o as resolveServicePrefixedOrChatAllowTarget, r as parseChatTargetPrefixesOrThrow, s as resolveServicePrefixedTarget, t as createAllowedChatSenderMatcher } from "./.setup/api-B9Qx21G-.mjs";
8
+ import { a as resolveServicePrefixedChatTarget, c as imessageSetupPlugin, i as resolveServicePrefixedAllowTarget, n as parseChatAllowTargetPrefixes, o as resolveServicePrefixedOrChatAllowTarget, r as parseChatTargetPrefixesOrThrow, s as resolveServicePrefixedTarget, t as createAllowedChatSenderMatcher } from "./.setup/api-SAVMfMoY.mjs";
9
9
  import { t as IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./.setup/outbound-send-deps-B-QEsLSM.mjs";
10
10
  export { DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS, IMESSAGE_ACTIONS, IMESSAGE_ACTION_NAMES, IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS, createAllowedChatSenderMatcher, createIMessageConversationBindingManager, formatIMessageChatTarget, imessagePlugin, imessageSetupPlugin, inferIMessageTargetChatType, isAllowedIMessageSender, listEnabledIMessageAccounts, listIMessageAccountIds, looksLikeIMessageExplicitTargetId, looksLikeIMessageTargetId, matchIMessageAcpConversation, normalizeIMessageAcpConversationId, normalizeIMessageHandle, normalizeIMessageMessagingTarget, parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, parseIMessageAllowTarget, parseIMessageTarget, probeIMessage, resolveDefaultIMessageAccountId, resolveIMessageAccount, resolveIMessageConversationIdFromTarget, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, resolveIMessageInboundConversationId, resolveServicePrefixedAllowTarget, resolveServicePrefixedChatTarget, resolveServicePrefixedOrChatAllowTarget, resolveServicePrefixedTarget };
@@ -1,2 +1,2 @@
1
- import { t as IMessageChannelConfigSchema } from "./.setup/config-schema-4Q3_EqYt.mjs";
1
+ import { t as IMessageChannelConfigSchema } from "./.setup/config-schema-DXwa_3V5.mjs";
2
2
  export { IMessageChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as imessagePlugin } from "./.setup/channel-9fyvuN_p.mjs";
1
+ import { t as imessagePlugin } from "./.setup/channel-CL73qdMG.mjs";
2
2
  export { imessagePlugin };
@@ -1,3 +1,3 @@
1
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./.setup/media-contract-CagwSMvo.mjs";
1
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./.setup/media-contract-DjQGZlfl.mjs";
2
2
  import "./media-contract-api.js";
3
3
  export { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, resolveIMessageAttachmentRoots, resolveIMessageAttachmentRoots as resolveInboundAttachmentRoots, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteAttachmentRoots as resolveRemoteInboundAttachmentRoots };
@@ -1,19 +1,20 @@
1
1
  import { n as __reExport, t as __exportAll } from "./.setup/rolldown-runtime-BBjsoOtd.mjs";
2
2
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import path from "node:path";
3
4
  //#region packages/normalization-core/src/record-coerce.ts
4
5
  /** Type guard for non-array object records at browser-safe boundaries. */
5
6
  function isRecord$1(value) {
6
7
  return value !== null && typeof value === "object" && !Array.isArray(value);
7
8
  }
8
9
  /** Returns a non-array record or null. */
9
- function asNullableRecord(value) {
10
+ function asNullableRecord$1(value) {
10
11
  return isRecord$1(value) ? value : null;
11
12
  }
12
13
  //#endregion
13
14
  //#region src/config/channel-config-normalization.ts
14
15
  /** Applies one channel-specific doctor migration to every object-shaped account. */
15
16
  function normalizeChannelAccounts(params) {
16
- const rawAccounts = asNullableRecord(params.entry.accounts);
17
+ const rawAccounts = asNullableRecord$1(params.entry.accounts);
17
18
  if (!rawAccounts) return {
18
19
  entry: params.entry,
19
20
  changed: false
@@ -21,7 +22,7 @@ function normalizeChannelAccounts(params) {
21
22
  let changed = false;
22
23
  const accounts = { ...rawAccounts };
23
24
  for (const [accountId, value] of Object.entries(rawAccounts)) {
24
- const account = asNullableRecord(value);
25
+ const account = asNullableRecord$1(value);
25
26
  if (!account) continue;
26
27
  const normalized = params.normalizeAccount({
27
28
  account,
@@ -49,7 +50,7 @@ function normalizeChannelAccounts(params) {
49
50
  function normalizeChannelConfigEntries(params) {
50
51
  const changes = params.changes ?? [];
51
52
  const channels = params.cfg.channels;
52
- const entry = asNullableRecord(channels?.[params.channelId]);
53
+ const entry = asNullableRecord$1(channels?.[params.channelId]);
53
54
  if (!entry) return {
54
55
  config: params.cfg,
55
56
  changes
@@ -92,26 +93,32 @@ function normalizeChannelConfigEntries(params) {
92
93
  function createLegacyWebhookListenerDoctorContract(params) {
93
94
  const portKey = params.portKey ?? "webhookPort";
94
95
  const hostKey = params.hostKey === void 0 ? "webhookHost" : params.hostKey;
95
- const source = (entry) => params.webhookKey ? asNullableRecord(entry[params.webhookKey]) : entry;
96
+ const source = (entry) => params.webhookKey ? asNullableRecord$1(entry[params.webhookKey]) : entry;
96
97
  const hasLegacy = (value) => {
97
- const entry = asNullableRecord(value);
98
+ const entry = asNullableRecord$1(value);
98
99
  const listener = entry && source(entry);
99
100
  return Boolean(listener && (Object.hasOwn(listener, portKey) || hostKey && Object.hasOwn(listener, hostKey)));
100
101
  };
101
102
  const prefix = `channels.${params.channelKey}`;
102
103
  return {
104
+ historicalWebhookListener: {
105
+ channelId: params.channelKey,
106
+ port: params.defaultPort,
107
+ preserveAuthoredActivation: params.preserveAuthoredActivation,
108
+ ...params.defaultHost === void 0 ? {} : { host: params.defaultHost }
109
+ },
103
110
  legacyConfigRules: [{
104
111
  path: ["channels", params.channelKey],
105
112
  message: `${prefix} webhook listeners moved to Gateway routes. Run "openclaw doctor --fix" to preserve explicitly configured listener settings as legacyWebhook.`,
106
113
  match: (value) => {
107
- const accounts = asNullableRecord(asNullableRecord(value)?.accounts);
114
+ const accounts = asNullableRecord$1(asNullableRecord$1(value)?.accounts);
108
115
  return hasLegacy(value) || Object.values(accounts ?? {}).some(hasLegacy);
109
116
  }
110
117
  }],
111
118
  normalizeCompatibilityConfig: ({ cfg }) => {
112
- const root = asNullableRecord(asNullableRecord(cfg.channels)?.[params.channelKey]);
119
+ const root = asNullableRecord$1(asNullableRecord$1(cfg.channels)?.[params.channelKey]);
113
120
  const inherited = root && source(root);
114
- const canonicalRoot = asNullableRecord(root?.legacyWebhook);
121
+ const canonicalRoot = asNullableRecord$1(root?.legacyWebhook);
115
122
  return normalizeChannelConfigEntries({
116
123
  cfg,
117
124
  channelId: params.channelKey,
@@ -229,17 +236,18 @@ function normalizeCompatibilityConfig({ cfg }) {
229
236
  }
230
237
  //#endregion
231
238
  //#region extensions/imessage/doctor-contract-api.ts
232
- const stateMigrations = [{
233
- id: "imessage-legacy-state",
234
- label: "iMessage legacy state",
235
- async detectLegacyState(params) {
236
- const { imessageRetiredStateMigration } = await import("./.setup/state-migrations-B-Q7bO0Y.mjs");
237
- return imessageRetiredStateMigration.detectLegacyState(params);
238
- },
239
- async migrateLegacyState(params) {
240
- const { imessageRetiredStateMigration } = await import("./.setup/state-migrations-B-Q7bO0Y.mjs");
241
- return imessageRetiredStateMigration.migrateLegacyState(params);
242
- }
243
- }];
239
+ const stateMigrations = [(0, runtime_doctor_migrations_exports.defineRetiredPluginStateMigration)({
240
+ id: "imessage-retired-state",
241
+ label: "iMessage retired monitor state",
242
+ intermediateVersion: "2026.9.5",
243
+ findSources: ({ stateDir }) => [
244
+ path.join(stateDir, "imessage", "reply-cache.jsonl"),
245
+ path.join(stateDir, "imessage", "sent-echoes.jsonl"),
246
+ {
247
+ directory: path.join(stateDir, "imessage", "catchup"),
248
+ suffix: ".json"
249
+ }
250
+ ]
251
+ })];
244
252
  //#endregion
245
253
  export { legacyConfigRules, normalizeCompatibilityConfig, stateMigrations };
@@ -1,2 +1,2 @@
1
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./.setup/media-contract-CagwSMvo.mjs";
1
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./.setup/media-contract-DjQGZlfl.mjs";
2
2
  export { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, resolveIMessageAttachmentRoots, resolveIMessageAttachmentRoots as resolveInboundAttachmentRoots, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteAttachmentRoots as resolveRemoteInboundAttachmentRoots };
@@ -1,2 +1,2 @@
1
- import { t as describeIMessageMessageTool } from "./.setup/message-tool-api-D032l82H.mjs";
1
+ import { t as describeIMessageMessageTool } from "./.setup/message-tool-api-CqfRxLlT.mjs";
2
2
  export { describeIMessageMessageTool as describeMessageTool };
@@ -1,25 +1,3 @@
1
- import { l as looksLikeIMessageTargetId, u as normalizeIMessageMessagingTarget } from "./.setup/targets-BicBiYsM.mjs";
2
- import { o as resolveIMessageAccount } from "./.setup/accounts-nzcU0cq2.mjs";
3
- import { d as probeIMessage, r as resolveIMessageGroupToolPolicy, t as resolveIMessageGroupRequireMention, u as imessageMessageActions } from "./.setup/group-policy-90pw4tyG.mjs";
1
+ import { t as imessageMessageActions } from "./.setup/actions-DJqbUmbN.mjs";
4
2
  import { r as setIMessageRuntime } from "./.setup/runtime-Cza4CY5T.mjs";
5
- import { n as IMessageConfigSchema } from "./.setup/config-schema-4Q3_EqYt.mjs";
6
- import { t as sendMessageIMessage } from "./.setup/send-Cu9nl757.mjs";
7
- import { t as monitorIMessageProvider } from "./.setup/monitor-fv9nRuTH.mjs";
8
- import { formatTrimmedAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
9
- import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
10
- import { buildComputedAccountStatusSnapshot, collectStatusIssuesFromLastError } from "openclaw/plugin-sdk/status-helpers";
11
- import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
12
- import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
13
- import { DEFAULT_ACCOUNT_ID, getChatChannelMeta } from "openclaw/plugin-sdk/core";
14
- import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
15
- //#region extensions/imessage/src/config-accessors.ts
16
- function resolveIMessageConfigAllowFrom(params) {
17
- return (resolveIMessageAccount(params).config.allowFrom ?? []).map((entry) => String(entry));
18
- }
19
- function resolveIMessageConfigDefaultTo(params) {
20
- const defaultTo = resolveIMessageAccount(params).config.defaultTo;
21
- if (defaultTo == null) return;
22
- return defaultTo.trim() || void 0;
23
- }
24
- //#endregion
25
- export { DEFAULT_ACCOUNT_ID, IMessageConfigSchema, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, buildComputedAccountStatusSnapshot, chunkTextForOutbound, collectStatusIssuesFromLastError, formatTrimmedAllowFromEntries, getChatChannelMeta, imessageMessageActions, looksLikeIMessageTargetId, monitorIMessageProvider, normalizeIMessageMessagingTarget, probeIMessage, resolveChannelMediaMaxBytes, resolveIMessageConfigAllowFrom, resolveIMessageConfigDefaultTo, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, sendMessageIMessage, setIMessageRuntime };
3
+ export { imessageMessageActions, setIMessageRuntime };
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  var setup_entry_default = defineBundledChannelSetupEntry({
5
5
  importMetaUrl: import.meta.url,
6
6
  plugin: {
7
- specifier: fileURLToPath(new URL(".setup/api-D2S6FhGw.mjs", import.meta.url).href),
7
+ specifier: fileURLToPath(new URL(".setup/api-oq_MryN7.mjs", import.meta.url).href),
8
8
  exportName: "imessageSetupPlugin"
9
9
  }
10
10
  });
@@ -9,7 +9,7 @@
9
9
  "configRepair": true,
10
10
  "stateMigrations": [
11
11
  {
12
- "id": "imessage-legacy-state"
12
+ "id": "imessage-retired-state"
13
13
  }
14
14
  ]
15
15
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/imessage",
3
- "version": "2026.9.8",
3
+ "version": "2026.10.1-beta.2",
4
4
  "description": "OpenClaw iMessage channel plugin using imsg on a signed-in Mac",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "zod": "4.6.5"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.9.8"
15
+ "openclaw": ">=2026.10.1-beta.2"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -92,10 +92,10 @@
92
92
  "allowInvalidConfigRecovery": true
93
93
  },
94
94
  "compat": {
95
- "pluginApi": ">=2026.9.8"
95
+ "pluginApi": ">=2026.10.1-beta.2"
96
96
  },
97
97
  "build": {
98
- "openclawVersion": "2026.9.8",
98
+ "openclawVersion": "2026.10.1-beta.2",
99
99
  "bundledDist": false,
100
100
  "workerEntries": [
101
101
  "./src/chat-db.worker.ts"