@openclaw/imessage 2026.8.1-beta.2 → 2026.8.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 (157) hide show
  1. package/dist/{accounts-D00Njxg2.js → accounts-CCirBEIm.js} +4 -5
  2. package/dist/{actions.runtime-DTFKDN5p.js → actions.runtime-CAl3WcqD.js} +2 -3
  3. package/dist/api.js +6 -5
  4. package/dist/{approval-handler.runtime-BtLs4gho.js → approval-handler.runtime-UBd1j2Sg.js} +15 -9
  5. package/dist/approval-reactions-LL5yn1Rc.js +562 -0
  6. package/dist/{channel-lppmI51h.js → channel-DNI9DKGN.js} +26 -21
  7. package/dist/channel-config-api.js +1 -1
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.runtime-5wpCKQb7.js → channel.runtime-HSkrmWfW.js} +58 -11
  10. package/dist/{config-schema-DV0KP5nC.js → config-schema-DuGbA8Kp.js} +8 -7
  11. package/dist/contract-api.js +1 -1
  12. package/dist/doctor-contract-api.js +8 -281
  13. package/dist/{group-policy-DF9xSdik.js → group-policy-Dvc-BcWo.js} +19 -651
  14. package/dist/{media-contract-BEgdvYhW.js → media-contract-D-FhGE98.js} +1 -1
  15. package/dist/media-contract-api.js +1 -1
  16. package/dist/{message-tool-api-CPDfJJoE.js → message-tool-api-CvIgJpOo.js} +7 -4
  17. package/dist/message-tool-api.js +1 -1
  18. package/dist/{monitor-DnxJ8pW9.js → monitor-BywJn1QW.js} +343 -111
  19. package/dist/{question-reactions-DVe50UhB.js → question-reactions-viP7ZcyG.js} +2 -1
  20. package/dist/reaction-context-BAYI7pz0.js +105 -0
  21. package/dist/{remote-file-DLwO9ved.js → remote-file-6mCj2ZBy.js} +7 -3
  22. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  23. package/dist/runtime-Cza4CY5T.js +8 -0
  24. package/dist/runtime-api.js +10 -9
  25. package/dist/{sanitize-outbound-CoTZLXMw.js → sanitize-outbound-Du-r1lNQ.js} +345 -58
  26. package/dist/{send-BUXW76tw.js → send-mgWPKqSV.js} +147 -26
  27. package/dist/state-contract-4TK_cDDb.js +56 -0
  28. package/dist/state-migrations-SFdKp3GQ.js +277 -0
  29. package/node_modules/typebox/build/format/date.d.mts +1 -1
  30. package/node_modules/typebox/build/format/date.mjs +1 -1
  31. package/node_modules/typebox/build/format/date_time.d.mts +2 -2
  32. package/node_modules/typebox/build/format/date_time.mjs +3 -3
  33. package/node_modules/typebox/build/format/email.d.mts +1 -1
  34. package/node_modules/typebox/build/format/email.mjs +2 -2
  35. package/node_modules/typebox/build/format/hostname.mjs +2 -10
  36. package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
  37. package/node_modules/typebox/build/format/idn_email.mjs +3 -3
  38. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
  39. package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
  40. package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
  41. package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
  42. package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
  43. package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
  44. package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
  45. package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
  46. package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
  47. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
  48. package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
  49. package/node_modules/typebox/build/format/idna/index.mjs +2 -0
  50. package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
  51. package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
  52. package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
  53. package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
  54. package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
  55. package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
  56. package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
  57. package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
  58. package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
  59. package/node_modules/typebox/build/format/ipv4.mjs +2 -32
  60. package/node_modules/typebox/build/format/ipv6.mjs +2 -61
  61. package/node_modules/typebox/build/format/iri.d.mts +2 -2
  62. package/node_modules/typebox/build/format/iri.mjs +26 -8
  63. package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
  64. package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
  65. package/node_modules/typebox/build/format/regex.d.mts +1 -2
  66. package/node_modules/typebox/build/format/regex.mjs +2 -6
  67. package/node_modules/typebox/build/format/time.d.mts +2 -2
  68. package/node_modules/typebox/build/format/time.mjs +19 -14
  69. package/node_modules/typebox/build/format/uri.d.mts +1 -1
  70. package/node_modules/typebox/build/format/uri.mjs +3 -130
  71. package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
  72. package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
  73. package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
  74. package/node_modules/typebox/build/format/uri_template.mjs +4 -5
  75. package/node_modules/typebox/build/format/url.d.mts +3 -3
  76. package/node_modules/typebox/build/format/url.mjs +4 -5
  77. package/node_modules/typebox/build/guard/emit.d.mts +3 -1
  78. package/node_modules/typebox/build/guard/emit.mjs +12 -5
  79. package/node_modules/typebox/build/guard/guard.d.mts +8 -2
  80. package/node_modules/typebox/build/guard/guard.mjs +25 -4
  81. package/node_modules/typebox/build/guard/string.d.mts +2 -2
  82. package/node_modules/typebox/build/guard/string.mjs +7 -7
  83. package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
  84. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
  85. package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
  86. package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
  87. package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
  88. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
  89. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
  90. package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
  91. package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
  92. package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
  93. package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
  94. package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
  95. package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
  96. package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
  97. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
  98. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
  99. package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
  100. package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
  101. package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
  102. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
  103. package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
  104. package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
  105. package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
  106. package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
  107. package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
  108. package/node_modules/typebox/build/schema/types/index.mjs +0 -2
  109. package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
  110. package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
  111. package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
  112. package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
  113. package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
  114. package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
  115. package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
  116. package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
  117. package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
  118. package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
  119. package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
  120. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
  121. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
  122. package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
  123. package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
  124. package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
  125. package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
  126. package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
  127. package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
  128. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
  129. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
  130. package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
  131. package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
  132. package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
  133. package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
  134. package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
  135. package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
  136. package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
  137. package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
  138. package/node_modules/typebox/build/type/script/parser.mjs +27 -23
  139. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
  140. package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
  141. package/node_modules/typebox/package.json +27 -27
  142. package/node_modules/typebox/readme.md +79 -82
  143. package/openclaw.plugin.json +0 -6
  144. package/package.json +5 -5
  145. package/dist/catchup-D32oYNxR.js +0 -294
  146. package/dist/monitor-reply-cache-DKlYGd5x.js +0 -348
  147. package/dist/persisted-echo-cache-BPWGUK-L.js +0 -143
  148. package/node_modules/typebox/build/format/_idna.d.mts +0 -2
  149. package/node_modules/typebox/build/format/_idna.mjs +0 -246
  150. package/node_modules/typebox/build/format/_puny.d.mts +0 -1
  151. package/node_modules/typebox/build/format/_puny.mjs +0 -77
  152. package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
  153. package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
  154. package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
  155. package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
  156. package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
  157. package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
@@ -1,11 +1,13 @@
1
- import { F as imessageMessageActions, H as imessageSetupContract, N as getIMessageApprovalApprovers, P as imessageApprovalAuth, a as normalizeIMessageAcpConversationId, d as formatTrimmedAllowFromEntries$1, f as getChatChannelMeta, g as addIMessageApprovalReactionHintToText, h as normalizeIMessageMessagingTarget, i as matchIMessageAcpConversation, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, s as DEFAULT_ACCOUNT_ID, t as resolveIMessageGroupRequireMention, u as collectStatusIssuesFromLastError, z as createIMessageSetupWizardProxy } from "./group-policy-DF9xSdik.js";
2
- import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, t as collectIMessageDuplicateAccountSourceWarnings } from "./accounts-D00Njxg2.js";
3
- import { l as parseIMessageTarget, o as looksLikeIMessageExplicitTargetId, r as inferIMessageTargetChatType, s as normalizeIMessageHandle } from "./message-tool-api-CPDfJJoE.js";
4
- import { n as sanitizeIMessageFinalOutboundText, r as sanitizeOutboundText } from "./sanitize-outbound-CoTZLXMw.js";
1
+ import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, t as collectIMessageDuplicateAccountSourceWarnings } from "./accounts-CCirBEIm.js";
2
+ import { l as parseIMessageTarget, o as looksLikeIMessageExplicitTargetId, r as inferIMessageTargetChatType, s as normalizeIMessageHandle, u as isIMessagePhoneLikeHandle } from "./message-tool-api-CvIgJpOo.js";
3
+ import { n as sanitizeIMessageFinalOutboundText, r as sanitizeOutboundText, v as resolveIMessageDirectChatService } from "./sanitize-outbound-Du-r1lNQ.js";
4
+ import { a as normalizeIMessageAcpConversationId, c as normalizeIMessageMessagingTarget, d as imessageMessageActions, h as createIMessageSetupWizardProxy, i as matchIMessageAcpConversation, l as getIMessageApprovalApprovers, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, t as resolveIMessageGroupRequireMention, u as imessageApprovalAuth, v as imessageSetupContract } from "./group-policy-Dvc-BcWo.js";
5
5
  import { t as createIMessageConversationBindingManager } from "./conversation-bindings-GDQ_Laxj.js";
6
- import { t as IMessageChannelConfigSchema } from "./config-schema-DV0KP5nC.js";
7
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-BEgdvYhW.js";
6
+ import { t as IMessageChannelConfigSchema } from "./config-schema-DuGbA8Kp.js";
7
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-D-FhGE98.js";
8
+ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
8
9
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
10
+ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, formatTrimmedAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
9
11
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
10
12
  import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
11
13
  import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared";
@@ -13,17 +15,17 @@ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
13
15
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
14
16
  import { chunkMarkdownText } from "openclaw/plugin-sdk/reply-runtime";
15
17
  import { buildOutboundBaseSessionKey, normalizeAccountId, parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
16
- import { createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
18
+ import { collectStatusIssuesFromLastError, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
17
19
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
18
20
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
19
21
  import { createApproverRestrictedNativeApprovalCapabilityFromForwardingRoutes } from "openclaw/plugin-sdk/approval-delivery-runtime";
20
22
  import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
21
23
  import { shouldSuppressLocalNativeExecApprovalPrompt } from "openclaw/plugin-sdk/approval-native-runtime";
24
+ import { addApprovalReactionHintToText } from "openclaw/plugin-sdk/approval-reaction-runtime";
22
25
  import { buildTypedExecApprovalPendingReplyPayload, buildTypedPluginApprovalPendingReplyPayload } from "openclaw/plugin-sdk/approval-reply-runtime";
23
26
  import { getExecApprovalReplyMetadata, resolveExecApprovalCommandDisplay, resolveExecApprovalRequestAllowedDecisions } from "openclaw/plugin-sdk/approval-runtime";
24
- import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, formatTrimmedAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
25
- import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
26
27
  import { createRestrictSendersChannelSecurity } from "openclaw/plugin-sdk/channel-policy";
28
+ import { createChannelPluginBase, getChatChannelMeta } from "openclaw/plugin-sdk/core";
27
29
  //#region extensions/imessage/src/approval-text.ts
28
30
  function replaceApprovalIdPlaceholder(text, approvalId) {
29
31
  const safeApprovalId = approvalId.replace(/\$/g, "$$$$");
@@ -84,7 +86,7 @@ const imessageApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
84
86
  approvalKind,
85
87
  request
86
88
  }),
87
- load: async () => (await import("./approval-handler.runtime-BtLs4gho.js")).imessageApprovalNativeRuntime
89
+ load: async () => (await import("./approval-handler.runtime-UBd1j2Sg.js")).imessageApprovalNativeRuntime
88
90
  })
89
91
  });
90
92
  const imessageApprovalRouting = imessageApproval.routing;
@@ -139,7 +141,7 @@ function shouldSuppressLocalIMessageExecApprovalPrompt(params) {
139
141
  });
140
142
  }
141
143
  function appendIMessageReactionHint(params) {
142
- return addIMessageApprovalReactionHintToText({
144
+ return addApprovalReactionHintToText({
143
145
  text: params.text ?? "",
144
146
  allowedDecisions: params.allowedDecisions
145
147
  });
@@ -159,6 +161,7 @@ function buildIMessageExecPendingPayload(params) {
159
161
  cwd: params.request.request.cwd ?? void 0,
160
162
  host: params.request.request.host === "node" ? "node" : "gateway",
161
163
  nodeId: params.request.request.nodeId ?? void 0,
164
+ scope: params.request.request.scope ?? void 0,
162
165
  sessionKey: params.request.request.sessionKey ?? null,
163
166
  expiresAtMs: params.request.expiresAtMs,
164
167
  nowMs: params.nowMs
@@ -198,7 +201,7 @@ const imessageDoctor = {
198
201
  //#region extensions/imessage/src/shared.ts
199
202
  const IMESSAGE_CHANNEL = "imessage";
200
203
  async function loadIMessageChannelRuntime$1() {
201
- return await import("./channel.runtime-5wpCKQb7.js");
204
+ return await import("./channel.runtime-HSkrmWfW.js");
202
205
  }
203
206
  const imessageSetupWizard = createIMessageSetupWizardProxy(async () => (await loadIMessageChannelRuntime$1()).imessageSetupWizard);
204
207
  const imessageConfigAdapter = createScopedChannelConfigAdapter({
@@ -227,6 +230,7 @@ const imessageSecurityAdapter = createRestrictSendersChannelSecurity({
227
230
  groupPolicyPath: "channels.imessage.groupPolicy",
228
231
  groupAllowFromPath: "channels.imessage.groupAllowFrom",
229
232
  mentionGated: false,
233
+ findingTitle: "iMessage security warning",
230
234
  policyPathSuffix: "dmPolicy"
231
235
  });
232
236
  function createIMessagePluginBase(params) {
@@ -296,7 +300,7 @@ async function probeIMessageStatusAccount(params) {
296
300
  }
297
301
  //#endregion
298
302
  //#region extensions/imessage/src/channel.ts
299
- const loadIMessageChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-5wpCKQb7.js"));
303
+ const loadIMessageChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-HSkrmWfW.js"));
300
304
  function toIMessageMessageSendResult(result, kind, replyToId) {
301
305
  const receipt = result.receipt ?? createMessageReceiptFromOutboundResults({
302
306
  results: result.messageId ? [{
@@ -312,8 +316,8 @@ function toIMessageMessageSendResult(result, kind, replyToId) {
312
316
  ...result.meta && Object.keys(result.meta).length > 0 ? { meta: result.meta } : {}
313
317
  };
314
318
  }
315
- const loadIMessageApprovalReactionsModule = createLazyRuntimeModule(() => import("./group-policy-DF9xSdik.js").then((n) => n.v));
316
- const loadIMessageQuestionReactionsModule = createLazyRuntimeModule(() => import("./question-reactions-DVe50UhB.js").then((n) => n.r));
319
+ const loadIMessageApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-LL5yn1Rc.js").then((n) => n.t));
320
+ const loadIMessageQuestionReactionsModule = createLazyRuntimeModule(() => import("./question-reactions-viP7ZcyG.js").then((n) => n.r));
317
321
  async function prepareForwardedIMessageApprovalPayload(params) {
318
322
  const prepared = (await loadIMessageApprovalReactionsModule()).addIMessageApprovalReactionHintToStructuredPayload(params);
319
323
  if (prepared) Object.assign(params.payload, prepared);
@@ -386,7 +390,7 @@ function buildIMessageBaseSessionKey(params) {
386
390
  function isCanonicalIMessageDirectHandle(raw, normalized) {
387
391
  const trimmed = raw.trim();
388
392
  if (!trimmed || !normalized) return false;
389
- if (normalized.startsWith("+")) return /^[+\d\s().-]+$/.test(trimmed);
393
+ if (normalized.startsWith("+")) return isIMessagePhoneLikeHandle(trimmed);
390
394
  return /^[^\s@<>()[\]`]+@[^\s@<>()[\]`]+\.[^\s@<>()[\]`]+$/.test(trimmed);
391
395
  }
392
396
  function resolveIMessageOutboundSessionRoute(params) {
@@ -398,7 +402,7 @@ function resolveIMessageOutboundSessionRoute(params) {
398
402
  cfg: params.cfg,
399
403
  accountId: params.accountId
400
404
  });
401
- const directTarget = `${parsed.serviceExplicit || parsed.service !== "auto" ? parsed.service : account.config.service === "sms" ? "sms" : "imessage"}:${handle}`;
405
+ const directTarget = `${resolveIMessageDirectChatService(parsed.serviceExplicit ? parsed.service : account.config.service) ?? "auto"}:${handle}`;
402
406
  const peer = {
403
407
  kind: "direct",
404
408
  id: handle
@@ -451,7 +455,7 @@ const imessagePlugin = createChatChannelPlugin({
451
455
  allowlist: buildDmGroupAccountAllowlistAdapter({
452
456
  channelId: "imessage",
453
457
  resolveAccount: resolveIMessageAccount,
454
- normalize: ({ values }) => formatTrimmedAllowFromEntries$1(values),
458
+ normalize: ({ values }) => formatTrimmedAllowFromEntries(values),
455
459
  resolveDmAllowFrom: (account) => account.config.allowFrom,
456
460
  resolveGroupAllowFrom: (account) => account.config.groupAllowFrom,
457
461
  resolveDmPolicy: (account) => account.config.dmPolicy,
@@ -464,6 +468,7 @@ const imessagePlugin = createChatChannelPlugin({
464
468
  doctor: imessageDoctor,
465
469
  conversationBindings: {
466
470
  supportsCurrentConversationBinding: true,
471
+ bindingStore: "adapter",
467
472
  createManager: ({ cfg, accountId }) => createIMessageConversationBindingManager({
468
473
  cfg,
469
474
  accountId: accountId ?? void 0
@@ -486,9 +491,9 @@ const imessagePlugin = createChatChannelPlugin({
486
491
  resolveOutboundSessionRoute: (params) => resolveIMessageOutboundSessionRoute(params),
487
492
  targetResolver: {
488
493
  looksLikeId: looksLikeIMessageExplicitTargetId,
489
- hint: "<handle|chat_id:ID>",
490
- resolveTarget: async ({ normalized }) => {
491
- const to = normalized?.trim();
494
+ hint: "<phone|email|chat_id:ID|auto:contact|imessage:contact|sms:contact>",
495
+ resolveTarget: async ({ input }) => {
496
+ const to = normalizeIMessageMessagingTarget(input);
492
497
  if (!to) return null;
493
498
  const chatType = inferIMessageTargetChatType(to);
494
499
  if (!chatType) return null;
@@ -1,2 +1,2 @@
1
- import { t as IMessageChannelConfigSchema } from "./config-schema-DV0KP5nC.js";
1
+ import { t as IMessageChannelConfigSchema } from "./config-schema-DuGbA8Kp.js";
2
2
  export { IMessageChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as imessagePlugin } from "./channel-lppmI51h.js";
1
+ import { t as imessagePlugin } from "./channel-DNI9DKGN.js";
2
2
  export { imessagePlugin };
@@ -1,26 +1,66 @@
1
- import { B as imessageCompletionNote, G as normalizeIMessageCliPathForSetup, I as probeIMessage, L as IMESSAGE_INSTALL_COMMAND, R as createIMessageCliPathTextInput, U as imessageSetupStatusBase, V as imessageDmPolicy, W as isAutoManagedIMessageCliPath, c as PAIRING_APPROVED_MESSAGE, p as resolveChannelMediaMaxBytes } from "./group-policy-DF9xSdik.js";
2
- import { l as resolveIMessageRemoteHost, o as resolveIMessageAccount, r as listEnabledIMessageAccounts, s as resolveIMessageDuplicateSourceOwner } from "./accounts-D00Njxg2.js";
1
+ import { l as resolveIMessageRemoteHost, o as resolveIMessageAccount, r as listEnabledIMessageAccounts, s as resolveIMessageDuplicateSourceOwner } from "./accounts-CCirBEIm.js";
2
+ import { _ as imessageDmPolicy, b as isAutoManagedIMessageCliPath, f as probeIMessage, g as imessageCompletionNote, m as createIMessageCliPathTextInput, p as IMESSAGE_INSTALL_COMMAND, x as normalizeIMessageCliPathForSetup, y as imessageSetupStatusBase } from "./group-policy-Dvc-BcWo.js";
3
3
  import { t as IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-send-deps-B-QEsLSM.js";
4
- import { t as sendMessageIMessage } from "./send-BUXW76tw.js";
5
- import { t as monitorIMessageProvider } from "./monitor-DnxJ8pW9.js";
4
+ import { t as sendMessageIMessage } from "./send-mgWPKqSV.js";
5
+ import { t as monitorIMessageProvider } from "./monitor-BywJn1QW.js";
6
6
  import { createAccountStatusSink, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
7
7
  import path from "node:path";
8
+ import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
8
9
  import fs from "node:fs/promises";
9
10
  import { createDetectedBinaryStatus, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
10
11
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
11
12
  import { detectBinary as detectBinary$1, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
13
+ import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
12
14
  import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/run-command";
13
15
  //#region extensions/imessage/src/install-imsg.ts
14
- async function resolveBrewIMessageCliPath(brewExe) {
16
+ const IMESSAGE_BREW_FORMULA = "steipete/tap/imsg";
17
+ function isPathInside(parentPath, candidatePath) {
18
+ const relative = path.relative(parentPath, candidatePath);
19
+ return relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
20
+ }
21
+ async function resolveBrewManagedIMessageCliPath(brewExe, cliPath) {
15
22
  try {
16
- const result = await runPluginCommandWithTimeout({
23
+ const formulae = await runPluginCommandWithTimeout({
17
24
  argv: [
18
25
  brewExe,
19
- "--prefix",
20
- "imsg"
26
+ "list",
27
+ "--formula",
28
+ "--full-name"
21
29
  ],
22
30
  timeoutMs: 1e4
23
31
  });
32
+ const installed = formulae.stdout.split(/\r?\n/u).some((formula) => formula.trim() === IMESSAGE_BREW_FORMULA);
33
+ if (formulae.code !== 0 || !installed) return null;
34
+ let resolvedCliPath = cliPath;
35
+ if (!path.isAbsolute(resolvedCliPath)) {
36
+ const resolved = await runPluginCommandWithTimeout({
37
+ argv: [
38
+ "/usr/bin/env",
39
+ "which",
40
+ resolvedCliPath
41
+ ],
42
+ timeoutMs: 1e4
43
+ });
44
+ resolvedCliPath = resolved.code === 0 ? resolved.stdout.split(/\r?\n/u)[0]?.trim() ?? "" : "";
45
+ }
46
+ if (!resolvedCliPath) return null;
47
+ const cellar = await runPluginCommandWithTimeout({
48
+ argv: [brewExe, "--cellar"],
49
+ timeoutMs: 1e4
50
+ });
51
+ if (cellar.code !== 0 || !cellar.stdout.trim()) return null;
52
+ const [realCliPath, realFormulaPath] = await Promise.all([fs.realpath(resolvedCliPath), fs.realpath(path.join(cellar.stdout.trim(), "imsg"))]);
53
+ return isPathInside(realFormulaPath, realCliPath) ? resolvedCliPath : null;
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+ async function resolveBrewIMessageCliPath(brewExe) {
59
+ try {
60
+ const result = await runPluginCommandWithTimeout({
61
+ argv: [brewExe, "--prefix"],
62
+ timeoutMs: 1e4
63
+ });
24
64
  if (result.code !== 0 || !result.stdout.trim()) return null;
25
65
  const candidate = path.join(result.stdout.trim(), "bin", "imsg");
26
66
  await fs.access(candidate);
@@ -41,6 +81,10 @@ async function installIMessageCli(runtime, opts) {
41
81
  };
42
82
  runtime.log(`${opts?.upgrade ? "Updating" : "Installing"} imsg via Homebrew (${brewExe})...`);
43
83
  if (opts?.upgrade) {
84
+ if (!await resolveBrewManagedIMessageCliPath(brewExe, opts.cliPath ?? "imsg")) {
85
+ runtime.log("Keeping the detected imsg binary because Homebrew does not manage it.");
86
+ return { ok: true };
87
+ }
44
88
  const update = await runPluginCommandWithTimeout({
45
89
  argv: [brewExe, "update"],
46
90
  timeoutMs: 5 * 6e4
@@ -129,11 +173,15 @@ const imessageSetupWizard = {
129
173
  })) return;
130
174
  try {
131
175
  await options?.beforePersistentEffect?.();
132
- const result = await installIMessageCli(runtime, { upgrade: cliDetected });
176
+ const result = await installIMessageCli(runtime, {
177
+ upgrade: cliDetected,
178
+ cliPath: normalizedCliPath
179
+ });
133
180
  if (result.ok && result.cliPath) {
134
181
  await prompter.note(`Installed imsg at ${result.cliPath}`, "iMessage");
135
182
  return { credentialValues: { cliPath: result.cliPath } };
136
183
  }
184
+ if (result.ok) await prompter.note(`Using existing imsg at ${normalizedCliPath}; Homebrew does not manage this binary.`, "iMessage");
137
185
  if (!result.ok) await prompter.note(result.error ?? "imsg install failed.", "iMessage");
138
186
  } catch (error) {
139
187
  await prompter.note(`imsg install failed: ${String(error)}`, "iMessage");
@@ -153,8 +201,7 @@ async function sendIMessageOutbound(params) {
153
201
  const send = resolveOutboundSendDep(params.deps, "imessage", { legacyKeys: IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS }) ?? sendMessageIMessage;
154
202
  const maxBytes = resolveChannelMediaMaxBytes({
155
203
  cfg: params.cfg,
156
- resolveChannelLimitMb: ({ cfg, accountId }) => cfg.channels?.imessage?.accounts?.[accountId]?.mediaMaxMb ?? cfg.channels?.imessage?.mediaMaxMb,
157
- accountId: params.accountId
204
+ resolveChannelLimitMb: () => resolveIMessageAccount(params).config.mediaMaxMb
158
205
  });
159
206
  const result = await send(params.to, params.text, {
160
207
  config: params.cfg,
@@ -1,5 +1,5 @@
1
1
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
2
- import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, buildChannelConfigSchema, buildChannelReactionShape, buildCommonChannelAccountShape, buildGroupEntrySchema, isSafeScpRemoteHost, isValidInboundPathRootPattern, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
2
+ import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, isSafeScpRemoteHost, isValidInboundPathRootPattern, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
3
3
  import { z } from "zod";
4
4
  //#region extensions/imessage/src/config-ui-hints.ts
5
5
  const iMessageChannelConfigUiHints = {
@@ -43,13 +43,13 @@ const IMessageActionSchema = z.object({
43
43
  sendAttachment: z.boolean().optional(),
44
44
  polls: z.boolean().optional()
45
45
  }).strict().optional();
46
+ const { accountShape, rootPolicyShape } = buildChannelAccountSchemaParts({
47
+ omit: ["mentionPatterns", "replyToMode"],
48
+ streaming: ChannelDeliveryStreamingConfigSchema.optional(),
49
+ mediaMaxMb: z.number().int().positive().optional()
50
+ });
46
51
  const IMessageAccountSchemaBase = z.object({
47
- ...buildCommonChannelAccountShape({
48
- useDefaults: true,
49
- omit: ["mentionPatterns", "replyToMode"],
50
- streaming: ChannelDeliveryStreamingConfigSchema.optional(),
51
- mediaMaxMb: z.number().int().positive().optional()
52
- }),
52
+ ...accountShape,
53
53
  cliPath: ExecutableTokenSchema.optional(),
54
54
  dbPath: z.string().optional(),
55
55
  remoteHost: z.string().refine(isSafeScpRemoteHost, "expected SSH host or user@host (no spaces/options)").optional(),
@@ -89,6 +89,7 @@ const IMessageAccountSchemaBase = z.object({
89
89
  ] }).optional()).optional()
90
90
  }).strict();
91
91
  const IMessageConfigSchema = IMessageAccountSchemaBase.extend({
92
+ ...rootPolicyShape,
92
93
  accounts: z.record(z.string(), IMessageAccountSchemaBase.optional()).optional(),
93
94
  defaultAccount: z.string().optional()
94
95
  }).superRefine((value, ctx) => {
@@ -1,3 +1,3 @@
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-D-FhGE98.js";
2
2
  import "./media-contract-api.js";
3
3
  export { DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, resolveIMessageAttachmentRoots, resolveIMessageAttachmentRoots as resolveInboundAttachmentRoots, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteAttachmentRoots as resolveRemoteInboundAttachmentRoots };
@@ -1,284 +1,6 @@
1
- import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount } from "./accounts-D00Njxg2.js";
2
- import { d as resolveIMessageReplyCacheEntryKey, i as IMESSAGE_REPLY_CACHE_NAMESPACE, n as IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE, r as IMESSAGE_REPLY_CACHE_MAX_ENTRIES, t as IMESSAGE_REPLY_CACHE_COUNTER_KEY } from "./monitor-reply-cache-DKlYGd5x.js";
3
- import { o as resolveIMessageCatchupCursorKey, r as capFailureRetriesMap, t as IMESSAGE_CATCHUP_CURSOR_NAMESPACE } from "./catchup-D32oYNxR.js";
4
- import { n as IMESSAGE_SENT_ECHOES_TTL_MS, s as resolveIMessageSentEchoEntryKey, t as IMESSAGE_SENT_ECHOES_NAMESPACE } from "./persisted-echo-cache-BPWGUK-L.js";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { asFiniteNumber, isRecord, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
8
- import { createHash } from "node:crypto";
1
+ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
9
2
  import { defineChannelAliasMigration, definePluginDoctorMigrationFromPlans } from "openclaw/plugin-sdk/runtime-doctor-migrations";
10
- import { fileExists } from "openclaw/plugin-sdk/security-runtime";
11
- import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
12
- //#region extensions/imessage/src/state-migrations.ts
13
- const REPLY_CACHE_TTL_MS = 360 * 60 * 1e3;
14
- function resolveMigrationStateDir(params) {
15
- return params.stateDir ?? resolveStateDir(params.env);
16
- }
17
- function remainingTtlMs(timestamp, ttlMs) {
18
- const remaining = ttlMs - Math.max(0, Date.now() - timestamp);
19
- return remaining > 0 ? remaining : void 0;
20
- }
21
- function readJsonl(pathValue) {
22
- try {
23
- return fs.readFileSync(pathValue, "utf8").split(/\n+/).flatMap((line) => {
24
- if (!line) return [];
25
- try {
26
- return [JSON.parse(line)];
27
- } catch {
28
- return [];
29
- }
30
- });
31
- } catch (err) {
32
- throw new Error(`Failed reading ${pathValue}: ${String(err)}`, { cause: err });
33
- }
34
- }
35
- function parseReplyCacheEntry(raw) {
36
- if (!raw || typeof raw !== "object") return null;
37
- const parsed = raw;
38
- if (typeof parsed.accountId !== "string" || typeof parsed.messageId !== "string" || typeof parsed.shortId !== "string" || typeof parsed.timestamp !== "number") return null;
39
- return {
40
- accountId: parsed.accountId,
41
- messageId: parsed.messageId,
42
- shortId: parsed.shortId,
43
- timestamp: parsed.timestamp,
44
- ...typeof parsed.chatGuid === "string" ? { chatGuid: parsed.chatGuid } : {},
45
- ...typeof parsed.chatIdentifier === "string" ? { chatIdentifier: parsed.chatIdentifier } : {},
46
- ...typeof parsed.chatId === "number" ? { chatId: parsed.chatId } : {},
47
- ...typeof parsed.isFromMe === "boolean" ? { isFromMe: parsed.isFromMe } : {}
48
- };
49
- }
50
- function readReplyCacheMaxShortId(sourcePath) {
51
- let max = 0;
52
- for (const raw of readJsonl(sourcePath)) {
53
- if (!raw || typeof raw !== "object") continue;
54
- const shortId = raw.shortId;
55
- if (typeof shortId !== "string") continue;
56
- const numeric = Number.parseInt(shortId, 10);
57
- if (Number.isFinite(numeric) && numeric > max) max = numeric;
58
- }
59
- return max;
60
- }
61
- function readReplyCounterValue(value) {
62
- if (!value || typeof value !== "object") return null;
63
- const counter = value.counter;
64
- return asFiniteNumber(counter) ?? null;
65
- }
66
- function shouldReplaceReplyCounter(existingValue, incomingValue) {
67
- const incomingCounter = readReplyCounterValue(incomingValue);
68
- if (incomingCounter === null) return false;
69
- const existingCounter = readReplyCounterValue(existingValue);
70
- return existingCounter === null || incomingCounter > existingCounter;
71
- }
72
- function parseSentEchoEntry(raw) {
73
- if (!raw || typeof raw !== "object") return null;
74
- const parsed = raw;
75
- if (typeof parsed.scope !== "string" || typeof parsed.timestamp !== "number") return null;
76
- return {
77
- scope: parsed.scope,
78
- timestamp: parsed.timestamp,
79
- ...typeof parsed.text === "string" ? { text: parsed.text } : {},
80
- ...typeof parsed.messageId === "string" ? { messageId: parsed.messageId } : {}
81
- };
82
- }
83
- function listReplyCacheEntries(sourcePath) {
84
- const entriesByKey = /* @__PURE__ */ new Map();
85
- for (const entry of readJsonl(sourcePath).map(parseReplyCacheEntry)) {
86
- if (!entry) continue;
87
- const ttlMs = remainingTtlMs(entry.timestamp, REPLY_CACHE_TTL_MS);
88
- if (!ttlMs) continue;
89
- const key = resolveIMessageReplyCacheEntryKey(entry.messageId);
90
- entriesByKey.delete(key);
91
- entriesByKey.set(key, {
92
- value: entry,
93
- ttlMs
94
- });
95
- }
96
- return [...entriesByKey.entries()].slice(-IMESSAGE_REPLY_CACHE_MAX_ENTRIES).map(([key, entry]) => ({
97
- key,
98
- value: entry.value,
99
- ttlMs: entry.ttlMs
100
- }));
101
- }
102
- function listSentEchoEntries(sourcePath) {
103
- return readJsonl(sourcePath).map(parseSentEchoEntry).filter((entry) => Boolean(entry)).slice(-256).flatMap((entry) => {
104
- const ttlMs = remainingTtlMs(entry.timestamp, IMESSAGE_SENT_ECHOES_TTL_MS);
105
- if (!ttlMs) return [];
106
- return [{
107
- key: resolveIMessageSentEchoEntryKey(entry),
108
- value: entry,
109
- ttlMs
110
- }];
111
- });
112
- }
113
- function resolveLegacyCatchupCursorPath(stateDir, accountId) {
114
- const safePrefix = accountId.replace(/[^a-zA-Z0-9_-]/g, "_") || "account";
115
- const hash = createHash("sha256").update(accountId, "utf8").digest("hex").slice(0, 12);
116
- return path.join(stateDir, "imessage", "catchup", `${safePrefix}__${hash}.json`);
117
- }
118
- function listLegacyCatchupCursorPaths(stateDir) {
119
- const dir = path.join(stateDir, "imessage", "catchup");
120
- try {
121
- return fs.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => path.join(dir, entry.name));
122
- } catch {
123
- return [];
124
- }
125
- }
126
- function normalizeCatchupCursor(raw) {
127
- if (!raw || typeof raw !== "object") return null;
128
- const value = raw;
129
- if (typeof value.lastSeenMs !== "number" || !Number.isFinite(value.lastSeenMs) || typeof value.lastSeenRowid !== "number" || !Number.isFinite(value.lastSeenRowid)) return null;
130
- const failureRetries = sanitizeCatchupFailureRetries(value.failureRetries);
131
- const hasRetries = Object.keys(failureRetries).length > 0;
132
- return {
133
- lastSeenMs: value.lastSeenMs,
134
- lastSeenRowid: value.lastSeenRowid,
135
- updatedAt: typeof value.updatedAt === "number" ? value.updatedAt : 0,
136
- ...hasRetries ? { failureRetries } : {}
137
- };
138
- }
139
- function readCatchupCursor(sourcePath) {
140
- let parsed;
141
- try {
142
- parsed = JSON.parse(fs.readFileSync(sourcePath, "utf8"));
143
- } catch (err) {
144
- throw new Error(`Failed reading ${sourcePath}: ${String(err)}`, { cause: err });
145
- }
146
- const cursor = normalizeCatchupCursor(parsed);
147
- if (!cursor) throw new Error(`Invalid iMessage catchup cursor: ${sourcePath}`);
148
- return cursor;
149
- }
150
- function sanitizeCatchupFailureRetries(raw) {
151
- if (!raw || typeof raw !== "object") return {};
152
- const out = {};
153
- for (const [guid, count] of Object.entries(raw)) if (typeof count === "number" && Number.isFinite(count) && count > 0) out[guid] = Math.floor(count);
154
- return capFailureRetriesMap(out);
155
- }
156
- function shouldReplaceCatchupCursor(existingValue, incomingValue) {
157
- const incoming = normalizeCatchupCursor(incomingValue);
158
- if (!incoming) return false;
159
- const existing = normalizeCatchupCursor(existingValue);
160
- return !existing || incoming.lastSeenRowid > existing.lastSeenRowid || incoming.lastSeenRowid === existing.lastSeenRowid && incoming.lastSeenMs > existing.lastSeenMs;
161
- }
162
- function detectReplyCacheMigration(params) {
163
- const stateDir = resolveMigrationStateDir(params);
164
- const sourcePath = path.join(stateDir, "imessage", "reply-cache.jsonl");
165
- if (!fileExists(sourcePath)) return [];
166
- const plans = [];
167
- plans.push({
168
- kind: "plugin-state-import",
169
- label: "iMessage reply short-id counter",
170
- sourcePath,
171
- targetPath: `plugin state:${IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE}`,
172
- pluginId: "imessage",
173
- namespace: IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE,
174
- maxEntries: 1,
175
- scopeKey: "",
176
- stateDir,
177
- preview: `- iMessage reply short-id counter: ${sourcePath} → plugin state (${IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE})`,
178
- readEntries: () => {
179
- const maxShortId = readReplyCacheMaxShortId(sourcePath);
180
- return maxShortId > 0 ? [{
181
- key: IMESSAGE_REPLY_CACHE_COUNTER_KEY,
182
- value: { counter: maxShortId }
183
- }] : [];
184
- },
185
- shouldReplaceExistingEntry: ({ existingValue, incomingValue }) => shouldReplaceReplyCounter(existingValue, incomingValue)
186
- });
187
- plans.push({
188
- kind: "plugin-state-import",
189
- label: "iMessage reply short-id cache",
190
- sourcePath,
191
- targetPath: `plugin state:${IMESSAGE_REPLY_CACHE_NAMESPACE}`,
192
- pluginId: "imessage",
193
- namespace: IMESSAGE_REPLY_CACHE_NAMESPACE,
194
- maxEntries: IMESSAGE_REPLY_CACHE_MAX_ENTRIES,
195
- scopeKey: "",
196
- stateDir,
197
- cleanupSource: "rename",
198
- cleanupWhenEmpty: true,
199
- preview: `- iMessage reply short-id cache: ${sourcePath} → plugin state (${IMESSAGE_REPLY_CACHE_NAMESPACE})`,
200
- readEntries: () => listReplyCacheEntries(sourcePath)
201
- });
202
- return plans;
203
- }
204
- function detectSentEchoMigration(params) {
205
- const stateDir = resolveMigrationStateDir(params);
206
- const sourcePath = path.join(stateDir, "imessage", "sent-echoes.jsonl");
207
- if (!fileExists(sourcePath)) return [];
208
- return [{
209
- kind: "plugin-state-import",
210
- label: "iMessage sent-echo dedupe cache",
211
- sourcePath,
212
- targetPath: `plugin state:${IMESSAGE_SENT_ECHOES_NAMESPACE}`,
213
- pluginId: "imessage",
214
- namespace: IMESSAGE_SENT_ECHOES_NAMESPACE,
215
- maxEntries: 256,
216
- scopeKey: "",
217
- stateDir,
218
- cleanupSource: "rename",
219
- cleanupWhenEmpty: true,
220
- preview: `- iMessage sent-echo dedupe cache: ${sourcePath} → plugin state (${IMESSAGE_SENT_ECHOES_NAMESPACE})`,
221
- readEntries: () => listSentEchoEntries(sourcePath)
222
- }];
223
- }
224
- function detectCatchupCursorMigrations(params) {
225
- const stateDir = resolveMigrationStateDir(params);
226
- const accountIds = uniqueStrings([resolveDefaultIMessageAccountId(params.cfg), ...listIMessageAccountIds(params.cfg)].map((accountId) => resolveIMessageAccount({
227
- cfg: params.cfg,
228
- accountId
229
- }).accountId));
230
- const configuredPaths = new Set(accountIds.map((accountId) => resolveLegacyCatchupCursorPath(stateDir, accountId)));
231
- const configuredPlans = accountIds.flatMap((accountId) => {
232
- const sourcePath = resolveLegacyCatchupCursorPath(stateDir, accountId);
233
- if (!fileExists(sourcePath)) return [];
234
- return {
235
- kind: "plugin-state-import",
236
- label: "iMessage catchup cursor",
237
- sourcePath,
238
- targetPath: `plugin state:${IMESSAGE_CATCHUP_CURSOR_NAMESPACE}`,
239
- pluginId: "imessage",
240
- namespace: IMESSAGE_CATCHUP_CURSOR_NAMESPACE,
241
- maxEntries: 256,
242
- scopeKey: "",
243
- stateDir,
244
- cleanupSource: "rename",
245
- preview: `- iMessage catchup cursor: ${sourcePath} → plugin state (${IMESSAGE_CATCHUP_CURSOR_NAMESPACE})`,
246
- readEntries: () => {
247
- const cursor = readCatchupCursor(sourcePath);
248
- return [{
249
- key: resolveIMessageCatchupCursorKey(accountId),
250
- value: cursor
251
- }];
252
- },
253
- shouldReplaceExistingEntry: (replaceParams) => shouldReplaceCatchupCursor(replaceParams.existingValue, replaceParams.incomingValue)
254
- };
255
- });
256
- const orphanPlans = listLegacyCatchupCursorPaths(stateDir).filter((sourcePath) => !configuredPaths.has(sourcePath)).map((sourcePath) => ({
257
- kind: "plugin-state-import",
258
- label: "iMessage orphan catchup cursor",
259
- sourcePath,
260
- targetPath: `plugin state:${IMESSAGE_CATCHUP_CURSOR_NAMESPACE}`,
261
- pluginId: "imessage",
262
- namespace: IMESSAGE_CATCHUP_CURSOR_NAMESPACE,
263
- maxEntries: 256,
264
- scopeKey: "",
265
- stateDir,
266
- cleanupSource: "rename",
267
- cleanupWhenEmpty: true,
268
- preview: `- iMessage orphan catchup cursor: ${sourcePath} → archived legacy state`,
269
- readEntries: () => []
270
- }));
271
- return [...configuredPlans, ...orphanPlans];
272
- }
273
- async function detectIMessageLegacyStateMigrations(params) {
274
- return [
275
- ...detectCatchupCursorMigrations(params),
276
- ...detectReplyCacheMigration(params),
277
- ...detectSentEchoMigration(params)
278
- ];
279
- }
280
- //#endregion
281
- //#region extensions/imessage/doctor-contract-api.ts
3
+ //#region extensions/imessage/config-doctor-api.ts
282
4
  function isEnabledCatchup(value) {
283
5
  return isRecord(value) && value.enabled === true;
284
6
  }
@@ -348,10 +70,15 @@ function normalizeCompatibilityConfig({ cfg }) {
348
70
  changes
349
71
  };
350
72
  }
73
+ //#endregion
74
+ //#region extensions/imessage/doctor-contract-api.ts
351
75
  const stateMigrations = [definePluginDoctorMigrationFromPlans({
352
76
  id: "imessage-legacy-state",
353
77
  label: "iMessage legacy state",
354
- resolvePlans: detectIMessageLegacyStateMigrations
78
+ resolvePlans: async (params) => {
79
+ const { detectIMessageLegacyStateMigrations } = await import("./state-migrations-SFdKp3GQ.js");
80
+ return detectIMessageLegacyStateMigrations(params);
81
+ }
355
82
  })];
356
83
  //#endregion
357
84
  export { legacyConfigRules, normalizeCompatibilityConfig, stateMigrations };