@openclaw/imessage 2026.8.1-beta.2 → 2026.9.1-beta.1

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 (151) hide show
  1. package/dist/{accounts-D00Njxg2.js → accounts-DIpGOIiN.js} +2 -2
  2. package/dist/{actions.runtime-DTFKDN5p.js → actions.runtime-BhggncbG.js} +3 -3
  3. package/dist/api.js +6 -5
  4. package/dist/{approval-handler.runtime-BtLs4gho.js → approval-handler.runtime-BC-YsgAf.js} +15 -9
  5. package/dist/approval-reactions-Cvwmdlev.js +566 -0
  6. package/dist/{catchup-D32oYNxR.js → catchup-Dh-Rv4Ur.js} +1 -1
  7. package/dist/{channel-lppmI51h.js → channel-CnKQ2MVB.js} +26 -20
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.runtime-5wpCKQb7.js → channel.runtime-BQLCh7bE.js} +6 -4
  10. package/dist/contract-api.js +1 -1
  11. package/dist/doctor-contract-api.js +4 -4
  12. package/dist/{group-policy-DF9xSdik.js → group-policy-BipELT2x.js} +19 -650
  13. package/dist/{media-contract-BEgdvYhW.js → media-contract-BVXuQHG2.js} +1 -1
  14. package/dist/media-contract-api.js +1 -1
  15. package/dist/{message-tool-api-CPDfJJoE.js → message-tool-api-BwIxJDoz.js} +7 -4
  16. package/dist/message-tool-api.js +1 -1
  17. package/dist/{monitor-DnxJ8pW9.js → monitor-DRD_Dnp9.js} +76 -107
  18. package/dist/{monitor-reply-cache-DKlYGd5x.js → monitor-reply-cache-BdeUQaHO.js} +6 -1
  19. package/dist/{persisted-echo-cache-BPWGUK-L.js → persisted-echo-cache-DGxy-J4t.js} +1 -1
  20. package/dist/{question-reactions-DVe50UhB.js → question-reactions-viP7ZcyG.js} +2 -1
  21. package/dist/reaction-context-BAYI7pz0.js +105 -0
  22. package/dist/{remote-file-DLwO9ved.js → remote-file-CyTTuRAt.js} +7 -3
  23. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  24. package/dist/runtime-api.js +9 -8
  25. package/dist/{sanitize-outbound-CoTZLXMw.js → sanitize-outbound-g651fIhi.js} +2 -2
  26. package/dist/{send-BUXW76tw.js → send-DVQY6M5M.js} +24 -24
  27. package/node_modules/typebox/build/format/date.d.mts +1 -1
  28. package/node_modules/typebox/build/format/date.mjs +1 -1
  29. package/node_modules/typebox/build/format/date_time.d.mts +2 -2
  30. package/node_modules/typebox/build/format/date_time.mjs +3 -3
  31. package/node_modules/typebox/build/format/email.d.mts +1 -1
  32. package/node_modules/typebox/build/format/email.mjs +2 -2
  33. package/node_modules/typebox/build/format/hostname.mjs +2 -10
  34. package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
  35. package/node_modules/typebox/build/format/idn_email.mjs +3 -3
  36. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
  37. package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
  38. package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
  39. package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
  40. package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
  41. package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
  42. package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
  43. package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
  44. package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
  45. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
  46. package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
  47. package/node_modules/typebox/build/format/idna/index.mjs +2 -0
  48. package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
  49. package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
  50. package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
  51. package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
  52. package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
  53. package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
  54. package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
  55. package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
  56. package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
  57. package/node_modules/typebox/build/format/ipv4.mjs +2 -32
  58. package/node_modules/typebox/build/format/ipv6.mjs +2 -61
  59. package/node_modules/typebox/build/format/iri.d.mts +2 -2
  60. package/node_modules/typebox/build/format/iri.mjs +26 -8
  61. package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
  62. package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
  63. package/node_modules/typebox/build/format/regex.d.mts +1 -2
  64. package/node_modules/typebox/build/format/regex.mjs +2 -6
  65. package/node_modules/typebox/build/format/time.d.mts +2 -2
  66. package/node_modules/typebox/build/format/time.mjs +19 -14
  67. package/node_modules/typebox/build/format/uri.d.mts +1 -1
  68. package/node_modules/typebox/build/format/uri.mjs +3 -130
  69. package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
  70. package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
  71. package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
  72. package/node_modules/typebox/build/format/uri_template.mjs +4 -5
  73. package/node_modules/typebox/build/format/url.d.mts +3 -3
  74. package/node_modules/typebox/build/format/url.mjs +4 -5
  75. package/node_modules/typebox/build/guard/emit.d.mts +3 -1
  76. package/node_modules/typebox/build/guard/emit.mjs +12 -5
  77. package/node_modules/typebox/build/guard/guard.d.mts +8 -2
  78. package/node_modules/typebox/build/guard/guard.mjs +25 -4
  79. package/node_modules/typebox/build/guard/string.d.mts +2 -2
  80. package/node_modules/typebox/build/guard/string.mjs +7 -7
  81. package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
  82. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
  83. package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
  84. package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
  85. package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
  86. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
  87. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
  88. package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
  89. package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
  90. package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
  91. package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
  92. package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
  93. package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
  94. package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
  95. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
  96. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
  97. package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
  98. package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
  99. package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
  100. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
  101. package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
  102. package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
  103. package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
  104. package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
  105. package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
  106. package/node_modules/typebox/build/schema/types/index.mjs +0 -2
  107. package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
  108. package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
  109. package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
  110. package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
  111. package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
  112. package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
  113. package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
  114. package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
  115. package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
  116. package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
  117. package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
  118. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
  119. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
  120. package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
  121. package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
  122. package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
  123. package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
  124. package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
  125. package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
  126. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
  127. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
  128. package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
  129. package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
  130. package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
  131. package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
  132. package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
  133. package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
  134. package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
  135. package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
  136. package/node_modules/typebox/build/type/script/parser.mjs +27 -23
  137. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
  138. package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
  139. package/node_modules/typebox/package.json +27 -27
  140. package/node_modules/typebox/readme.md +79 -82
  141. package/package.json +5 -5
  142. package/node_modules/typebox/build/format/_idna.d.mts +0 -2
  143. package/node_modules/typebox/build/format/_idna.mjs +0 -246
  144. package/node_modules/typebox/build/format/_puny.d.mts +0 -1
  145. package/node_modules/typebox/build/format/_puny.mjs +0 -77
  146. package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
  147. package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
  148. package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
  149. package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
  150. package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
  151. package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
@@ -1,4 +1,4 @@
1
- import { o as resolveIMessageAccount } from "./accounts-D00Njxg2.js";
1
+ import { o as resolveIMessageAccount } from "./accounts-DIpGOIiN.js";
2
2
  import { mergeInboundPathRoots } from "openclaw/plugin-sdk/channel-inbound";
3
3
  //#region extensions/imessage/src/media-contract.ts
4
4
  const DEFAULT_IMESSAGE_ATTACHMENT_ROOTS = ["/Users/*/Library/Messages/Attachments"];
@@ -1,2 +1,2 @@
1
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./media-contract-BEgdvYhW.js";
1
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots, t as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS } from "./media-contract-BVXuQHG2.js";
2
2
  export { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, resolveIMessageAttachmentRoots, resolveIMessageAttachmentRoots as resolveInboundAttachmentRoots, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteAttachmentRoots as resolveRemoteInboundAttachmentRoots };
@@ -1,10 +1,10 @@
1
- import { c as getCachedIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-D00Njxg2.js";
1
+ import { c as getCachedIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-DIpGOIiN.js";
2
2
  import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { createActionGate } from "openclaw/plugin-sdk/channel-actions";
5
5
  import { Type } from "typebox";
6
6
  import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
7
- import { createAllowedChatSenderMatcher, parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, resolveServicePrefixedAllowTarget, resolveServicePrefixedChatTarget, resolveServicePrefixedOrChatAllowTarget, resolveServicePrefixedTarget } from "openclaw/plugin-sdk/channel-targets";
7
+ import { createAllowedChatSenderMatcher, parseChatTargetPrefixesOrThrow, resolveServicePrefixedChatTarget, resolveServicePrefixedOrChatAllowTarget } from "openclaw/plugin-sdk/channel-targets";
8
8
  //#region extensions/imessage/src/actions-contract.ts
9
9
  const IMESSAGE_ACTIONS = {
10
10
  react: { gate: "reactions" },
@@ -77,6 +77,9 @@ function setCachedIMessagePrivateApiStatus(cliPath, status, expiresAt = 0) {
77
77
  //#endregion
78
78
  //#region extensions/imessage/src/target-identifiers.ts
79
79
  const BARE_CHAT_IDENTIFIER_RE = /^[0-9a-f]{32}$/i;
80
+ function isIMessagePhoneLikeHandle(raw) {
81
+ return /^(?:tel:)?[+\d\s().-]+$/i.test(raw.trim());
82
+ }
80
83
  function normalizeBareIMessageChatIdentifier(raw) {
81
84
  const trimmed = raw.trim();
82
85
  if (!BARE_CHAT_IDENTIFIER_RE.test(trimmed)) return;
@@ -136,7 +139,7 @@ function normalizeIMessageHandle(raw) {
136
139
  if (trimmed.includes("@")) return normalizeLowercaseStringOrEmpty(trimmed);
137
140
  const bareChatIdentifier = normalizeBareIMessageChatIdentifier(trimmed);
138
141
  if (bareChatIdentifier) return `chat_identifier:${bareChatIdentifier}`;
139
- const normalized = normalizeE164(trimmed);
142
+ const normalized = isIMessagePhoneLikeHandle(trimmed) ? normalizeE164(trimmed) : "";
140
143
  if (normalized) return normalized;
141
144
  return trimmed.replace(/\s+/g, "");
142
145
  }
@@ -312,4 +315,4 @@ function describeIMessageMessageTool({ cfg, accountId, currentChannelId }) {
312
315
  };
313
316
  }
314
317
  //#endregion
315
- export { IMESSAGE_ACTION_NAMES as S, normalizeBareIMessageChatIdentifier as _, isAllowedIMessageSender as a, setCachedIMessagePrivateApiStatus as b, parseIMessageAllowTarget as c, parseChatAllowTargetPrefixes as d, parseChatTargetPrefixesOrThrow as f, resolveServicePrefixedTarget as g, resolveServicePrefixedOrChatAllowTarget as h, isAllowedIMessageReplyContextSender as i, parseIMessageTarget as l, resolveServicePrefixedChatTarget as m, formatIMessageChatTarget as n, looksLikeIMessageExplicitTargetId as o, resolveServicePrefixedAllowTarget as p, inferIMessageTargetChatType as r, normalizeIMessageHandle as s, describeIMessageMessageTool as t, createAllowedChatSenderMatcher as u, getCachedIMessagePrivateApiStatus as v, IMESSAGE_ACTIONS as x, imessageRpcSupportsMethod as y };
318
+ export { isAllowedIMessageSender as a, parseIMessageAllowTarget as c, normalizeBareIMessageChatIdentifier as d, getCachedIMessagePrivateApiStatus as f, IMESSAGE_ACTION_NAMES as g, IMESSAGE_ACTIONS as h, isAllowedIMessageReplyContextSender as i, parseIMessageTarget as l, setCachedIMessagePrivateApiStatus as m, formatIMessageChatTarget as n, looksLikeIMessageExplicitTargetId as o, imessageRpcSupportsMethod as p, inferIMessageTargetChatType as r, normalizeIMessageHandle as s, describeIMessageMessageTool as t, isIMessagePhoneLikeHandle as u };
@@ -1,2 +1,2 @@
1
- import { t as describeIMessageMessageTool } from "./message-tool-api-CPDfJJoE.js";
1
+ import { t as describeIMessageMessageTool } from "./message-tool-api-BwIxJDoz.js";
2
2
  export { describeIMessageMessageTool as describeMessageTool };
@@ -1,13 +1,15 @@
1
- import { C as registerIMessageApprovalReactionTarget, D as buildIMessageApprovalConversationKeyForInbound, E as resolveIMessageReactionContext, I as probeIMessage, S as maybeResolveIMessageApprovalReaction, b as handleIMessageApprovalReaction, r as resolveIMessageInboundConversationId, x as listPendingIMessageApprovalReactionPollTargets, y as extractIMessageApprovalPromptBinding } from "./group-policy-DF9xSdik.js";
2
- import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-D00Njxg2.js";
3
- import { c as parseIMessageAllowTarget, i as isAllowedIMessageReplyContextSender, l as parseIMessageTarget, n as formatIMessageChatTarget, s as normalizeIMessageHandle, v as getCachedIMessagePrivateApiStatus, y as imessageRpcSupportsMethod } from "./message-tool-api-CPDfJJoE.js";
4
- import { c as rememberIMessageReplyCache, f as getIMessageRuntime, s as isKnownFromMeIMessageMessageId } from "./monitor-reply-cache-DKlYGd5x.js";
5
- import { o as createIMessageRpcClient, r as sanitizeOutboundText } from "./sanitize-outbound-CoTZLXMw.js";
6
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-BEgdvYhW.js";
7
- import { a as resolveCatchupConfig, i as performIMessageCatchup, n as advanceIMessageCatchupCursor } from "./catchup-D32oYNxR.js";
8
- import { c as stripLeadingEchoTextCorruptionMarkers, i as hasPersistedIMessageEcho, o as resolveIMessageEchoMediaKey } from "./persisted-echo-cache-BPWGUK-L.js";
9
- import { a as maybeResolveIMessageApprovalPollVote, o as iMessageApprovalControlBindings, t as sendMessageIMessage } from "./send-BUXW76tw.js";
10
- import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-DVe50UhB.js";
1
+ import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-DIpGOIiN.js";
2
+ import { c as parseIMessageAllowTarget, f as getCachedIMessagePrivateApiStatus, i as isAllowedIMessageReplyContextSender, l as parseIMessageTarget, n as formatIMessageChatTarget, p as imessageRpcSupportsMethod, s as normalizeIMessageHandle } from "./message-tool-api-BwIxJDoz.js";
3
+ import { c as rememberIMessageReplyCache, f as getIMessageRuntime, s as isKnownFromMeIMessageMessageId, v as resolveIMessageDirectChatService } from "./monitor-reply-cache-BdeUQaHO.js";
4
+ import { o as createIMessageRpcClient, r as sanitizeOutboundText } from "./sanitize-outbound-g651fIhi.js";
5
+ import { f as probeIMessage, r as resolveIMessageInboundConversationId } from "./group-policy-BipELT2x.js";
6
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-BVXuQHG2.js";
7
+ import { a as resolveCatchupConfig, i as performIMessageCatchup, n as advanceIMessageCatchupCursor } from "./catchup-Dh-Rv4Ur.js";
8
+ import { c as stripLeadingEchoTextCorruptionMarkers, i as hasPersistedIMessageEcho, o as resolveIMessageEchoMediaKey } from "./persisted-echo-cache-DGxy-J4t.js";
9
+ import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction, s as buildIMessageApprovalConversationKeyForInbound } from "./approval-reactions-Cvwmdlev.js";
10
+ import { a as maybeResolveIMessageApprovalPollVote, o as iMessageApprovalControlBindings, t as sendMessageIMessage } from "./send-DVQY6M5M.js";
11
+ import { t as resolveIMessageReactionContext } from "./reaction-context-BAYI7pz0.js";
12
+ import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-viP7ZcyG.js";
11
13
  import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, createMessageReceiptFromOutboundResults, listMessageReceiptPlatformIds, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
12
14
  import { chunkMarkdownTextWithMode as chunkTextWithMode, resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
13
15
  import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
@@ -16,14 +18,14 @@ import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
16
18
  import { asSafeIntegerInRange, hasNonEmptyString, isRecord, normalizeOptionalString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
17
19
  import fs from "node:fs/promises";
18
20
  import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
19
- import { asDateTimestampMs, asPositiveFiniteNumber, parseDateStringTimestampMs, resolveExpiresAtMsFromDurationMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
21
+ import { isInboundPathAllowed, kindFromMime } from "openclaw/plugin-sdk/media-runtime";
22
+ import { asDateTimestampMs, asPositiveFiniteNumber, parseDateStringTimestampMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
20
23
  import { createHash } from "node:crypto";
21
24
  import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
22
25
  import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
23
26
  import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
24
- import { isInboundPathAllowed, kindFromMime } from "openclaw/plugin-sdk/media-runtime";
25
- import { convertMarkdownTables as convertMarkdownTables$1, findCodeRegions, isInsideCode, sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
26
27
  import { buildChannelGroupsScopeTree, resolveChannelGroupPolicy, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
28
+ import { convertMarkdownTables as convertMarkdownTables$1, findCodeRegions, isInsideCode, sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
27
29
  import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, createChannelPartialDeliveryError, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, formatMediaPlaceholderText, isChannelPartialDeliveryError, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
28
30
  import { openLocalFileSafely, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
29
31
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
@@ -33,7 +35,7 @@ import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
33
35
  import { createChannelIngressResolver, defineStableChannelIngressIdentity, fanInChannelIngressLifecycles } from "openclaw/plugin-sdk/channel-ingress-runtime";
34
36
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
35
37
  import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
36
- import { readChannelAllowFromStore, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
38
+ import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
37
39
  import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
38
40
  import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
39
41
  import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
@@ -55,8 +57,6 @@ import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
55
57
  //#region extensions/imessage/src/approval-reaction-poller.ts
56
58
  const RECENT_CHAT_LIMIT = 50;
57
59
  const PER_CHAT_HISTORY_LIMIT = 30;
58
- const OBSERVED_APPROVAL_PROMPT_TARGET_TTL_MS = 300 * 1e3;
59
- const accountIdsWithCompletedNoTargetDiscovery = /* @__PURE__ */ new Set();
60
60
  function normalizeChatId(value) {
61
61
  return asPositiveFiniteNumber(value) ?? null;
62
62
  }
@@ -150,42 +150,13 @@ function bindObservedConversation(params) {
150
150
  ttlMs
151
151
  });
152
152
  }
153
- function bindObservedApprovalPrompt(params) {
154
- if (params.message.is_from_me !== true) return null;
155
- const messageId = params.message.guid?.trim();
156
- if (!messageId) return null;
157
- const binding = extractIMessageApprovalPromptBinding(params.message.text ?? "");
158
- if (!binding) return null;
159
- const conversation = buildConversationKeyFromMessage(params.message);
160
- const expiresAtMs = resolveExpiresAtMsFromDurationMs(OBSERVED_APPROVAL_PROMPT_TARGET_TTL_MS);
161
- if (expiresAtMs === void 0) return null;
162
- const target = {
163
- accountId: params.accountId,
164
- conversation,
165
- messageId,
166
- approvalId: binding.approvalId,
167
- approvalKind: binding.approvalKind,
168
- allowedDecisions: binding.allowedDecisions,
169
- expiresAtMs
170
- };
171
- bindObservedConversation({
172
- target,
173
- message: params.message
174
- });
175
- return target;
176
- }
177
153
  async function pollPendingIMessageApprovalReactions(params) {
178
- const targets = listPendingIMessageApprovalReactionPollTargets({ accountId: params.accountId });
179
- const shouldAttemptNoTargetDiscovery = targets.length === 0 && params.allowRecentChatDiscovery === true && !accountIdsWithCompletedNoTargetDiscovery.has(params.accountId);
180
- if (targets.length === 0 && !shouldAttemptNoTargetDiscovery) return;
154
+ const targets = await listPendingIMessageApprovalReactionPollTargets({ accountId: params.accountId });
155
+ if (targets.length === 0) return;
181
156
  const pendingByMessageId = buildPendingTargetsByMessageId(targets);
182
157
  const explicitChatIds = listTargetChatIds(targets);
183
- const chatIds = params.allowRecentChatDiscovery === true && (targets.length === 0 || hasUnscopedTarget(targets)) ? uniqueChatIds([...explicitChatIds, ...await listRecentChatIds(params.client)]) : explicitChatIds;
184
- if (chatIds.length === 0) {
185
- if (shouldAttemptNoTargetDiscovery) accountIdsWithCompletedNoTargetDiscovery.add(params.accountId);
186
- return;
187
- }
188
- let hadHistoryFetchError = false;
158
+ const chatIds = params.allowRecentChatDiscovery === true && targets.length > 0 && hasUnscopedTarget(targets) ? uniqueChatIds([...explicitChatIds, ...await listRecentChatIds(params.client)]) : explicitChatIds;
159
+ if (chatIds.length === 0) return;
189
160
  for (const chatId of chatIds) {
190
161
  let messages;
191
162
  try {
@@ -194,17 +165,13 @@ async function pollPendingIMessageApprovalReactions(params) {
194
165
  chatId
195
166
  });
196
167
  } catch (err) {
197
- hadHistoryFetchError = true;
198
168
  params.logVerboseMessage?.(`imessage: approval reaction poll skipped chat_id=${chatId}: ${String(err)}`);
199
169
  continue;
200
170
  }
201
171
  for (const message of messages) {
202
172
  const targetGuid = message.guid?.trim();
203
173
  if (!targetGuid) continue;
204
- const target = pendingByMessageId.get(targetGuid) ?? pendingByMessageId.get(normalizeMessageGuid(targetGuid)) ?? bindObservedApprovalPrompt({
205
- accountId: params.accountId,
206
- message
207
- });
174
+ const target = pendingByMessageId.get(targetGuid) ?? pendingByMessageId.get(normalizeMessageGuid(targetGuid));
208
175
  if (!target) continue;
209
176
  bindObservedConversation({
210
177
  target,
@@ -216,22 +183,17 @@ async function pollPendingIMessageApprovalReactions(params) {
216
183
  reaction
217
184
  });
218
185
  if (!reactionPayload) continue;
219
- const handled = await handleIMessageApprovalReaction({
186
+ if ((await handleIMessageApprovalReaction({
220
187
  cfg: params.cfg,
221
188
  accountId: params.accountId,
222
189
  message: reactionPayload,
223
190
  bodyText: reactionPayload.text ?? "",
224
191
  gatewayRuntime: params.gatewayRuntime,
225
192
  logVerboseMessage: params.logVerboseMessage
226
- });
227
- if (handled.stopPolling) {
228
- if (shouldAttemptNoTargetDiscovery && handled.stopPollingReason !== "resolver-error") break;
229
- return;
230
- }
193
+ })).stopPolling) return;
231
194
  }
232
195
  }
233
196
  }
234
- if (shouldAttemptNoTargetDiscovery && !hadHistoryFetchError) accountIdsWithCompletedNoTargetDiscovery.add(params.accountId);
235
197
  }
236
198
  //#endregion
237
199
  //#region extensions/imessage/src/chat.ts
@@ -342,9 +304,6 @@ function stripImessageLengthPrefixedUtf8Text(text) {
342
304
  function isOptionalString(value) {
343
305
  return value === void 0 || value === null || typeof value === "string";
344
306
  }
345
- function isOptionalStringOrNumber(value) {
346
- return value === void 0 || value === null || typeof value === "string" || typeof value === "number";
347
- }
348
307
  function isOptionalNumber(value) {
349
308
  return value === void 0 || value === null || typeof value === "number";
350
309
  }
@@ -367,7 +326,7 @@ function parseIMessageNotification(raw) {
367
326
  const maybeMessage = raw.message;
368
327
  if (!isRecord(maybeMessage)) return null;
369
328
  const message = maybeMessage;
370
- if (!isOptionalNumber(message.id) || !isOptionalString(message.guid) || !isOptionalNumber(message.chat_id) || !isOptionalString(message.sender) || !isOptionalString(message.destination_caller_id) || !isOptionalBoolean(message.is_from_me) || !isOptionalString(message.text) || !isOptionalStringOrNumber(message.reply_to_id) || !isOptionalString(message.reply_to_guid) || !isOptionalString(message.reply_to_text) || !isOptionalString(message.reply_to_sender) || !isOptionalString(message.created_at) || !isOptionalBoolean(message.is_reaction) || !isOptionalBoolean(message.is_tapback) || !isOptionalString(message.associated_message_guid) || !isOptionalNumber(message.associated_message_type) || !isOptionalString(message.reaction_type) || !isOptionalString(message.reaction_emoji) || !isOptionalBoolean(message.is_reaction_add) || !isOptionalString(message.reacted_to_guid) || !isOptionalAttachments(message.attachments) || !isOptionalString(message.chat_identifier) || !isOptionalString(message.chat_guid) || !isOptionalString(message.chat_name) || !isOptionalStringArray(message.participants) || !isOptionalBoolean(message.is_group)) return null;
329
+ if (!isOptionalNumber(message.id) || !isOptionalString(message.guid) || !isOptionalNumber(message.chat_id) || !isOptionalString(message.sender) || !isOptionalString(message.destination_caller_id) || !isOptionalBoolean(message.is_from_me) || !isOptionalString(message.text) || !isOptionalString(message.thread_originator_guid) || !isOptionalString(message.reply_to_guid) || !isOptionalString(message.reply_to_text) || !isOptionalString(message.reply_to_sender) || !isOptionalString(message.created_at) || !isOptionalBoolean(message.is_reaction) || !isOptionalBoolean(message.is_tapback) || !isOptionalString(message.associated_message_guid) || !isOptionalNumber(message.associated_message_type) || !isOptionalString(message.reaction_type) || !isOptionalString(message.reaction_emoji) || !isOptionalBoolean(message.is_reaction_add) || !isOptionalString(message.reacted_to_guid) || !isOptionalAttachments(message.attachments) || !isOptionalString(message.chat_identifier) || !isOptionalString(message.chat_guid) || !isOptionalString(message.chat_name) || !isOptionalStringArray(message.participants) || !isOptionalBoolean(message.is_group)) return null;
371
330
  return {
372
331
  ...message,
373
332
  text: typeof message.text === "string" ? stripImessageLengthPrefixedUtf8Text(message.text) : message.text,
@@ -587,15 +546,16 @@ function combineIMessagePayloads(payloads) {
587
546
  seenGuids.add(guid);
588
547
  coalescedMessageGuids.push(guid);
589
548
  }
590
- const entryWithReply = payloads.find((p) => p.reply_to_id != null);
549
+ const reply = payloads.find((payload) => payload.thread_originator_guid != null || payload.reply_to_guid != null) ?? first;
591
550
  return {
592
551
  ...first,
593
552
  text: combinedText,
594
553
  attachments: allAttachments.length > 0 ? allAttachments : null,
595
554
  created_at: latestCreatedAt,
596
- reply_to_id: entryWithReply?.reply_to_id ?? first.reply_to_id ?? null,
597
- reply_to_text: entryWithReply?.reply_to_text ?? first.reply_to_text ?? null,
598
- reply_to_sender: entryWithReply?.reply_to_sender ?? first.reply_to_sender ?? null,
555
+ thread_originator_guid: reply.thread_originator_guid ?? null,
556
+ reply_to_guid: reply.reply_to_guid ?? null,
557
+ reply_to_text: reply.reply_to_text ?? null,
558
+ reply_to_sender: reply.reply_to_sender ?? null,
599
559
  coalescedMessageGuids: coalescedMessageGuids.length > 0 ? coalescedMessageGuids : void 0,
600
560
  coalescedCatchupCursor: Number.isFinite(maxRowid) && Number.isFinite(maxDateMs) ? {
601
561
  lastSeenMs: maxDateMs,
@@ -1033,7 +993,7 @@ function isStaleIMessageBacklog(message, nowMs, thresholdMs = IMESSAGE_STALE_INB
1033
993
  //#endregion
1034
994
  //#region extensions/imessage/src/conversation-route.ts
1035
995
  function resolveIMessageConversationRoute(params) {
1036
- let route = resolveAgentRoute({
996
+ const route = resolveAgentRoute({
1037
997
  cfg: params.cfg,
1038
998
  channel: "imessage",
1039
999
  accountId: params.accountId,
@@ -1047,28 +1007,30 @@ function resolveIMessageConversationRoute(params) {
1047
1007
  sender: params.sender,
1048
1008
  chatId: params.chatId
1049
1009
  });
1050
- if (!conversationId) return route;
1051
- route = resolveConfiguredBindingRoute({
1010
+ if (!conversationId) return {
1011
+ route,
1012
+ bindingResolution: null
1013
+ };
1014
+ const conversation = {
1015
+ channel: "imessage",
1016
+ accountId: params.accountId,
1017
+ conversationId
1018
+ };
1019
+ const configuredRoute = resolveConfiguredBindingRoute({
1052
1020
  cfg: params.cfg,
1053
1021
  route,
1054
- conversation: {
1055
- channel: "imessage",
1056
- accountId: params.accountId,
1057
- conversationId
1058
- }
1059
- }).route;
1022
+ conversation
1023
+ });
1060
1024
  const runtimeRoute = resolveRuntimeConversationBindingRoute({
1061
- route,
1062
- conversation: {
1063
- channel: "imessage",
1064
- accountId: params.accountId,
1065
- conversationId
1066
- }
1025
+ route: configuredRoute.route,
1026
+ conversation
1067
1027
  });
1068
- route = runtimeRoute.route;
1069
1028
  if (runtimeRoute.bindingRecord && !runtimeRoute.boundSessionKey) logVerbose(`imessage: plugin-bound conversation ${conversationId}`);
1070
1029
  else if (runtimeRoute.boundSessionKey) logVerbose(`imessage: routed via bound conversation ${conversationId} -> ${runtimeRoute.boundSessionKey}`);
1071
- return route;
1030
+ return {
1031
+ route: runtimeRoute.route,
1032
+ bindingResolution: runtimeRoute.bindingRecord ? null : configuredRoute.bindingResolution
1033
+ };
1072
1034
  }
1073
1035
  //#endregion
1074
1036
  //#region extensions/imessage/src/monitor/reflection-guard.ts
@@ -1213,7 +1175,7 @@ function describeReplyContext(message) {
1213
1175
  if (!body) return null;
1214
1176
  return {
1215
1177
  body,
1216
- id: normalizeReplyField(message.reply_to_id),
1178
+ id: normalizeReplyField(message.thread_originator_guid) ?? normalizeReplyField(message.reply_to_guid),
1217
1179
  sender: normalizeReplyField(message.reply_to_sender)
1218
1180
  };
1219
1181
  }
@@ -1391,7 +1353,7 @@ async function resolveIMessageInboundDecision(params) {
1391
1353
  const groupId = isGroup ? groupIdCandidate : void 0;
1392
1354
  const hasControlCommandInMessage = hasControlCommand(messageText, params.cfg);
1393
1355
  const groupAllowFromForAccess = isGroup ? groupAllowFromWithLegacyChatTargets : params.groupAllowFrom;
1394
- const route = resolveIMessageConversationRoute({
1356
+ const { route, bindingResolution } = resolveIMessageConversationRoute({
1395
1357
  cfg: params.cfg,
1396
1358
  accountId: params.accountId,
1397
1359
  isGroup,
@@ -1689,6 +1651,7 @@ async function resolveIMessageInboundDecision(params) {
1689
1651
  sender,
1690
1652
  senderNormalized,
1691
1653
  route,
1654
+ bindingResolution,
1692
1655
  bodyText,
1693
1656
  createdAt,
1694
1657
  replyContext: filteredReplyContext,
@@ -1754,11 +1717,8 @@ async function buildIMessageInboundContext(params) {
1754
1717
  envelope: envelopeOptions
1755
1718
  })
1756
1719
  });
1757
- const imessageTo = decision.isGroup ? chatTarget || `imessage:${decision.sender}` : buildDirectIMessageReplyTarget({
1758
- cfg: params.cfg,
1759
- accountId: decision.route.accountId,
1760
- sender: decision.sender
1761
- });
1720
+ const directService = resolveIMessageDirectChatService(params.accountService, decision.chatGuid) ?? "auto";
1721
+ const imessageTo = decision.isGroup ? chatTarget || `imessage:${decision.sender}` : `${directService}:${decision.sender}`;
1762
1722
  const imessageFrom = decision.isGroup ? `imessage:group:${chatId ?? "unknown"}` : imessageTo;
1763
1723
  const inboundHistory = !decision.isGroup && params.dmHistory?.inboundHistory ? params.dmHistory.inboundHistory : decision.isGroup && decision.historyKey && params.historyLimit > 0 ? createChannelHistoryWindow({ historyMap: params.groupHistories }).buildInboundHistory({
1764
1724
  historyKey: decision.historyKey,
@@ -1792,6 +1752,10 @@ async function buildIMessageInboundContext(params) {
1792
1752
  conversation: {
1793
1753
  kind: decision.isGroup ? "group" : "direct",
1794
1754
  id: chatId != null ? String(chatId) : decision.sender,
1755
+ ...decision.isGroup && chatId == null ? {} : { routePeer: {
1756
+ kind: decision.isGroup ? "group" : "direct",
1757
+ id: decision.isGroup ? String(chatId) : decision.senderNormalized
1758
+ } },
1795
1759
  label: fromLabel
1796
1760
  },
1797
1761
  route: {
@@ -1840,13 +1804,6 @@ function buildIMessageEchoScope(params) {
1840
1804
  if (params.chatIdentifier) scopes.push(`${params.accountId}:chat_identifier:${params.chatIdentifier}`);
1841
1805
  return scopes;
1842
1806
  }
1843
- function buildDirectIMessageReplyTarget(params) {
1844
- if (resolveIMessageAccount({
1845
- cfg: params.cfg,
1846
- accountId: params.accountId
1847
- }).config.service === "sms") return `sms:${params.sender}`;
1848
- return `imessage:${params.sender}`;
1849
- }
1850
1807
  function describeIMessageEchoDropLog(params) {
1851
1808
  const preview = truncateUtf16Safe(params.messageText, 50);
1852
1809
  return `imessage: skipping echo message${params.messageId ? ` id=${params.messageId}` : ""}: "${preview}"`;
@@ -2956,6 +2913,16 @@ async function monitorIMessageProvider(opts = {}) {
2956
2913
  });
2957
2914
  return;
2958
2915
  }
2916
+ if (decision.bindingResolution) {
2917
+ const readiness = await ensureConfiguredBindingRouteReady({
2918
+ cfg,
2919
+ bindingResolution: decision.bindingResolution
2920
+ });
2921
+ if (!readiness.ok) {
2922
+ runtime.error?.(`imessage: dropped inbound message; configured ACP binding unavailable for ${decision.bindingResolution.record.conversation.conversationId}: ${readiness.error}`);
2923
+ return;
2924
+ }
2925
+ }
2959
2926
  const storePath = resolveStorePath(cfg.session?.store, { agentId: decision.route.agentId });
2960
2927
  const privateApiStatus = getCachedIMessagePrivateApiStatus(cliPath);
2961
2928
  const supportsTyping = imessageRpcSupportsMethod(privateApiStatus, "typing");
@@ -2975,11 +2942,9 @@ async function monitorIMessageProvider(opts = {}) {
2975
2942
  chatType: decision.isGroup ? "group" : "direct"
2976
2943
  });
2977
2944
  const shouldUseDirectToolTypingOptions = !decision.isGroup && sendPolicy !== "deny" && (configuredTypingMode === void 0 || configuredTypingMode === "instant");
2978
- const earlyDirectTypingTarget = supportsTyping && shouldUseDirectToolTypingOptions ? buildDirectIMessageReplyTarget({
2979
- cfg,
2980
- accountId: decision.route.accountId,
2981
- sender: decision.sender
2982
- }) : void 0;
2945
+ const shouldStartDirectTyping = supportsTyping && shouldUseDirectToolTypingOptions;
2946
+ const earlyDirectTypingService = resolveIMessageDirectChatService(imessageCfg.service, decision.chatGuid) ?? "auto";
2947
+ const earlyDirectTypingTarget = shouldStartDirectTyping ? `${earlyDirectTypingService}:${decision.sender}` : void 0;
2983
2948
  let stopEarlyDirectTyping;
2984
2949
  if (earlyDirectTypingTarget) {
2985
2950
  const earlyDirectTypingStarted = sendIMessageTyping(earlyDirectTypingTarget, true, {
@@ -3056,8 +3021,10 @@ async function monitorIMessageProvider(opts = {}) {
3056
3021
  envelopeOptions: resolveEnvelopeFormatOptions(cfg),
3057
3022
  logVerbose
3058
3023
  }) : void 0;
3024
+ const pluginChannelRuntime = opts.channelRuntime;
3059
3025
  const { ctxPayload, chatTarget, imessageTo } = await buildIMessageInboundContext({
3060
3026
  cfg,
3027
+ accountService: imessageCfg.service,
3061
3028
  decision: contextDecision,
3062
3029
  message,
3063
3030
  previousTimestamp,
@@ -3065,7 +3032,7 @@ async function monitorIMessageProvider(opts = {}) {
3065
3032
  historyLimit,
3066
3033
  groupHistories,
3067
3034
  dmHistory,
3068
- buildContext: opts.channelRuntime?.inbound.buildContext,
3035
+ buildContext: pluginChannelRuntime?.inbound.buildContext,
3069
3036
  media: { facts: mediaAttachments }
3070
3037
  });
3071
3038
  const updateTarget = chatTarget || imessageTo;
@@ -3080,7 +3047,8 @@ async function monitorIMessageProvider(opts = {}) {
3080
3047
  }
3081
3048
  const sendReadReceipts = imessageCfg.sendReadReceipts !== false;
3082
3049
  const typingTarget = ctxPayload.To;
3083
- if (supportsRead && sendReadReceipts && typingTarget) markIMessageChatRead(typingTarget, {
3050
+ const readTarget = !decision.isGroup && decision.chatGuid ? `chat_guid:${decision.chatGuid}` : typingTarget;
3051
+ if (supportsRead && sendReadReceipts && readTarget) markIMessageChatRead(readTarget, {
3084
3052
  cfg,
3085
3053
  accountId: accountInfo.accountId,
3086
3054
  cliPath,
@@ -3217,6 +3185,7 @@ async function monitorIMessageProvider(opts = {}) {
3217
3185
  sessionKey: decision.route.sessionKey
3218
3186
  },
3219
3187
  ctxPayload,
3188
+ dispatchReplyFromConfig: pluginChannelRuntime?.reply?.dispatchReplyFromConfig,
3220
3189
  record: {
3221
3190
  updateLastRoute: !decision.isGroup && updateTarget ? {
3222
3191
  sessionKey: inboundLastRouteSessionKey,
@@ -21,6 +21,11 @@ function parseDirectChatIdentity(raw) {
21
21
  if (parts.length !== 1) return;
22
22
  if (trimmed.startsWith("+") || EMAIL_HANDLE_PATTERN.test(trimmed)) return { identifier: trimmed.toLowerCase() };
23
23
  }
24
+ function resolveIMessageDirectChatService(configuredService, chatGuid) {
25
+ if (configuredService === "imessage" || configuredService === "sms") return configuredService;
26
+ const observedService = chatGuid ? parseDirectChatIdentity(chatGuid)?.service : void 0;
27
+ return observedService === "imessage" || observedService === "sms" ? observedService : void 0;
28
+ }
24
29
  function isIMessageEmailChatIdentifier(raw) {
25
30
  const identity = parseDirectChatIdentity(raw);
26
31
  return Boolean(identity && EMAIL_HANDLE_PATTERN.test(identity.identifier));
@@ -345,4 +350,4 @@ function isIMessageCurrentMessageInChat(params) {
345
350
  }) === "match";
346
351
  }
347
352
  //#endregion
348
- export { normalizeDirectChatIdentifier as _, findLatestIMessageEntryForChat as a, rememberIMessageReplyCache as c, resolveIMessageReplyCacheEntryKey as d, getIMessageRuntime as f, isIMessageEmailChatIdentifier as g, chatContextFromIMessageTarget as h, IMESSAGE_REPLY_CACHE_NAMESPACE as i, resolveIMessageCachedResourceBinding as l, setIMessageRuntime as m, IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE as n, isIMessageCurrentMessageInChat as o, getOptionalIMessageRuntime as p, IMESSAGE_REPLY_CACHE_MAX_ENTRIES as r, isKnownFromMeIMessageMessageId as s, IMESSAGE_REPLY_CACHE_COUNTER_KEY as t, resolveIMessageMessageId as u };
353
+ export { normalizeDirectChatIdentifier as _, findLatestIMessageEntryForChat as a, rememberIMessageReplyCache as c, resolveIMessageReplyCacheEntryKey as d, getIMessageRuntime as f, isIMessageEmailChatIdentifier as g, chatContextFromIMessageTarget as h, IMESSAGE_REPLY_CACHE_NAMESPACE as i, resolveIMessageCachedResourceBinding as l, setIMessageRuntime as m, IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE as n, isIMessageCurrentMessageInChat as o, getOptionalIMessageRuntime as p, IMESSAGE_REPLY_CACHE_MAX_ENTRIES as r, isKnownFromMeIMessageMessageId as s, IMESSAGE_REPLY_CACHE_COUNTER_KEY as t, resolveIMessageMessageId as u, resolveIMessageDirectChatService as v };
@@ -1,4 +1,4 @@
1
- import { f as getIMessageRuntime } from "./monitor-reply-cache-DKlYGd5x.js";
1
+ import { f as getIMessageRuntime } from "./monitor-reply-cache-BdeUQaHO.js";
2
2
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
3
3
  import { createHash } from "node:crypto";
4
4
  //#region extensions/imessage/src/monitor/echo-text-corruption.ts
@@ -1,4 +1,5 @@
1
- import { E as resolveIMessageReactionContext, K as __exportAll } from "./group-policy-DF9xSdik.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { t as resolveIMessageReactionContext } from "./reaction-context-BAYI7pz0.js";
2
3
  import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
3
4
  //#region extensions/imessage/src/question-reactions.ts
4
5
  var question_reactions_exports = /* @__PURE__ */ __exportAll({
@@ -0,0 +1,105 @@
1
+ //#region extensions/imessage/src/monitor/reaction-context.ts
2
+ const TAPBACK_TEXT_PATTERNS = [
3
+ {
4
+ prefix: "loved",
5
+ action: "added",
6
+ emoji: "❤️"
7
+ },
8
+ {
9
+ prefix: "liked",
10
+ action: "added",
11
+ emoji: "👍"
12
+ },
13
+ {
14
+ prefix: "disliked",
15
+ action: "added",
16
+ emoji: "👎"
17
+ },
18
+ {
19
+ prefix: "laughed at",
20
+ action: "added",
21
+ emoji: "😂"
22
+ },
23
+ {
24
+ prefix: "emphasized",
25
+ action: "added",
26
+ emoji: "‼️"
27
+ },
28
+ {
29
+ prefix: "questioned",
30
+ action: "added",
31
+ emoji: "❓"
32
+ },
33
+ {
34
+ prefix: "removed a heart from",
35
+ action: "removed",
36
+ emoji: "❤️"
37
+ },
38
+ {
39
+ prefix: "removed a like from",
40
+ action: "removed",
41
+ emoji: "👍"
42
+ },
43
+ {
44
+ prefix: "removed a dislike from",
45
+ action: "removed",
46
+ emoji: "👎"
47
+ },
48
+ {
49
+ prefix: "removed a laugh from",
50
+ action: "removed",
51
+ emoji: "😂"
52
+ },
53
+ {
54
+ prefix: "removed an emphasis from",
55
+ action: "removed",
56
+ emoji: "‼️"
57
+ },
58
+ {
59
+ prefix: "removed a question from",
60
+ action: "removed",
61
+ emoji: "❓"
62
+ }
63
+ ];
64
+ function normalizeReactionValue(value) {
65
+ return typeof value === "string" ? value.trim().replace(/^p:\d+\//iu, "") || void 0 : void 0;
66
+ }
67
+ function resolveReactionTargetGuidCandidates(...values) {
68
+ const candidates = [];
69
+ for (const value of values) {
70
+ if (typeof value !== "string") continue;
71
+ const raw = value.trim();
72
+ if (!raw) continue;
73
+ const normalized = raw.replace(/^p:\d+\//iu, "");
74
+ for (const candidate of [normalized, raw]) if (candidate && !candidates.includes(candidate)) candidates.push(candidate);
75
+ }
76
+ return candidates;
77
+ }
78
+ function resolveTapbackTextContext(bodyText) {
79
+ const lower = bodyText.toLowerCase();
80
+ for (const pattern of TAPBACK_TEXT_PATTERNS) {
81
+ if (!lower.startsWith(pattern.prefix)) continue;
82
+ const afterPrefix = bodyText.slice(pattern.prefix.length).trim();
83
+ if (!/^(?:"[\s\S]*"|“[\s\S]*”)$/u.test(afterPrefix)) continue;
84
+ return {
85
+ action: pattern.action,
86
+ emoji: pattern.emoji,
87
+ targetText: afterPrefix.slice(1, -1).trim()
88
+ };
89
+ }
90
+ return null;
91
+ }
92
+ function resolveIMessageReactionContext(message, bodyText) {
93
+ if (message.is_reaction === true || message.is_tapback === true || typeof message.associated_message_type === "number" && Number.isFinite(message.associated_message_type) && message.associated_message_type >= 2e3 && message.associated_message_type < 4e3) {
94
+ const targetGuids = resolveReactionTargetGuidCandidates(message.reacted_to_guid, message.associated_message_guid);
95
+ return {
96
+ action: message.is_reaction_add === false ? "removed" : "added",
97
+ emoji: normalizeReactionValue(message.reaction_emoji) ?? normalizeReactionValue(message.reaction_type) ?? "reaction",
98
+ targetGuid: targetGuids[0],
99
+ targetGuids
100
+ };
101
+ }
102
+ return resolveTapbackTextContext(bodyText);
103
+ }
104
+ //#endregion
105
+ export { resolveIMessageReactionContext as t };
@@ -1,5 +1,5 @@
1
- import { p as resolveLocalIMessageChatDbPath, u as expandIMessageUserPath } from "./accounts-D00Njxg2.js";
2
- import { g as isIMessageEmailChatIdentifier, h as chatContextFromIMessageTarget, l as resolveIMessageCachedResourceBinding, u as resolveIMessageMessageId } from "./monitor-reply-cache-DKlYGd5x.js";
1
+ import { p as resolveLocalIMessageChatDbPath, u as expandIMessageUserPath } from "./accounts-DIpGOIiN.js";
2
+ import { g as isIMessageEmailChatIdentifier, h as chatContextFromIMessageTarget, l as resolveIMessageCachedResourceBinding, u as resolveIMessageMessageId } from "./monitor-reply-cache-BdeUQaHO.js";
3
3
  import path from "node:path";
4
4
  import { normalizeScpRemoteHost } from "openclaw/plugin-sdk/host-runtime";
5
5
  import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
@@ -121,7 +121,11 @@ function checkIMessageResourceBinding(params) {
121
121
  FROM message m
122
122
  JOIN chat_message_join cmj ON cmj.message_id = m.ROWID
123
123
  JOIN chat c ON c.ROWID = cmj.chat_id
124
- WHERE m.guid = ?`).all(messageGuid).some((row) => (!hasChatId || row.chatId === chatId) && (expectedChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, expectedChatGuids)) && (expectedChatIdentifiers.length === 0 || matchesAnyChatCandidate(row.chatIdentifier, expectedChatIdentifiers)) && (identifierChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, identifierChatGuids))) ? "match" : "mismatch";
124
+ WHERE m.guid = ?`).all(messageGuid).map((row) => ({
125
+ chatId: row.chatId,
126
+ chatGuid: row.chatGuid,
127
+ chatIdentifier: row.chatIdentifier
128
+ })).some((row) => (!hasChatId || row.chatId === chatId) && (expectedChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, expectedChatGuids)) && (expectedChatIdentifiers.length === 0 || matchesAnyChatCandidate(row.chatIdentifier, expectedChatIdentifiers)) && (identifierChatGuids.length === 0 || matchesAnyChatCandidate(row.chatGuid, identifierChatGuids))) ? "match" : "mismatch";
125
129
  } catch {
126
130
  return "unavailable";
127
131
  } finally {
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };