@openclaw/imessage 2026.10.10 → 2026.11.5-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 (137) hide show
  1. package/dist/.setup/{accounts-BH0coL46.mjs → accounts-C1Ypv3Wn.mjs} +6 -7
  2. package/dist/.setup/{actions-CW7XYYF4.mjs → actions-qOuKy8To.mjs} +360 -108
  3. package/dist/.setup/{actions.runtime-B2ZHQ3TJ.mjs → actions.runtime-Ccg9CARL.mjs} +10 -56
  4. package/dist/.setup/{api-6xi-NBrt.mjs → api-BXXuQQCS.mjs} +7 -7
  5. package/dist/.setup/{api-B0ih8Iof.mjs → api-DTbxSOPc.mjs} +8 -8
  6. package/dist/.setup/{approval-handler.runtime-BKmqba3L.mjs → approval-handler.runtime-B6vrFfZx.mjs} +112 -131
  7. package/dist/.setup/{approval-reactions-B9CJS0NT.mjs → approval-reactions-DBBsqbRC.mjs} +152 -72
  8. package/dist/.setup/{channel-6kcKpSRw.mjs → channel-CLaN4mQn.mjs} +142 -119
  9. package/dist/.setup/{channel.runtime-BW4A0m4h.mjs → channel.runtime-XJGx1MIH.mjs} +205 -363
  10. package/dist/.setup/chat-context-fTfJVqAi.mjs +77 -0
  11. package/dist/.setup/chat-lookup-xtPsOBkl.mjs +50 -0
  12. package/dist/.setup/client-D_BaG8sC.mjs +367 -0
  13. package/dist/.setup/{config-schema-DRkdRC21.mjs → config-schema-BjkQV5P5.mjs} +1 -2
  14. package/dist/.setup/{conversation-bindings-vZFn6sN2.mjs → conversation-bindings-8DjxoIYU.mjs} +9 -6
  15. package/dist/.setup/{media-contract-CoixpXRX.mjs → media-contract-BErFBKV9.mjs} +1 -1
  16. package/dist/.setup/{message-tool-api-CxSY_rh7.mjs → message-tool-api-DtZ1wKbT.mjs} +3 -6
  17. package/dist/.setup/{remote-file-CCgMYZ-u.mjs → remote-file-DpK3GQFD.mjs} +8 -22
  18. package/dist/.setup/{sanitize-outbound-C02fJrn6.mjs → sanitize-outbound-Dhjhz0a-.mjs} +23 -27
  19. package/dist/.setup/{send-D98hQFdv.mjs → send-DhEW0gfe.mjs} +150 -226
  20. package/dist/.setup/{setup-core-BWnW0czE.mjs → setup-core-B1_P_t4T.mjs} +2 -2
  21. package/dist/.setup/{setup-surface-aRZhAzzQ.mjs → setup-surface-CD28mXWK.mjs} +11 -25
  22. package/dist/.setup/{targets-CIx4BKqL.mjs → targets-C7CIWJ0k.mjs} +12 -3
  23. package/dist/.source-module-urls/929c518fa2986b0f85f66bceefead22868db0ab452dee914dc6a2bb86b2e60ad.json +1 -1
  24. package/dist/api.js +8 -8
  25. package/dist/channel-config-api.js +1 -1
  26. package/dist/channel-plugin-api.js +1 -1
  27. package/dist/contract-api.js +1 -1
  28. package/dist/media-contract-api.js +1 -1
  29. package/dist/message-tool-api.js +1 -1
  30. package/dist/runtime-api.js +1 -3
  31. package/dist/session-binding-contract-api.js +1 -1
  32. package/dist/setup-entry.js +1 -1
  33. package/dist/src/chat-db.worker.js +1 -1
  34. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  35. package/node_modules/typebox/build/format/duration.mjs +2 -2
  36. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  37. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  38. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  39. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  40. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  41. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  42. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  43. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  44. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  45. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  46. package/node_modules/typebox/build/schema/build.mjs +1 -0
  47. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  48. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  49. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  50. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  51. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  52. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  53. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  54. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  55. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  56. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  57. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  58. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  59. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  60. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  61. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  62. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  63. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  64. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  65. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  66. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  67. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  68. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  69. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  70. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  71. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  72. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  73. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  74. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  75. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  76. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  77. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  78. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  79. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  80. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  81. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  82. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  83. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  84. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  85. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  86. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  87. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  88. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  89. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  90. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  91. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  92. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  93. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  94. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  95. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  96. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  97. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  98. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  99. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  100. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  101. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  102. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  103. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  104. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  105. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  106. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  107. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  108. package/node_modules/typebox/package.json +1 -1
  109. package/node_modules/typebox/readme.md +1 -1
  110. package/node_modules/zod/package.json +1 -1
  111. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  112. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  113. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  114. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  115. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  116. package/node_modules/zod/src/v4/core/util.ts +13 -0
  117. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  118. package/node_modules/zod/v4/core/compile.cjs +8 -0
  119. package/node_modules/zod/v4/core/compile.js +8 -0
  120. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  121. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  122. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  123. package/node_modules/zod/v4/core/schemas.js +30 -0
  124. package/node_modules/zod/v4/core/util.cjs +15 -0
  125. package/node_modules/zod/v4/core/util.d.cts +2 -0
  126. package/node_modules/zod/v4/core/util.d.ts +2 -0
  127. package/node_modules/zod/v4/core/util.js +14 -0
  128. package/node_modules/zod/v4/core/versions.cjs +1 -1
  129. package/node_modules/zod/v4/core/versions.js +1 -1
  130. package/openclaw.plugin.json +0 -30
  131. package/package.json +6 -6
  132. package/dist/.setup/client-C3e7ZLqA.mjs +0 -739
  133. package/dist/.setup/question-reactions-DTj-VH3N.mjs +0 -67
  134. package/dist/.setup/reaction-context-Bw00FkmU.mjs +0 -105
  135. package/dist/.setup/runtime-BRQCPuAD.mjs +0 -7
  136. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  137. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
@@ -35,11 +35,23 @@ const IMESSAGE_STYLE_MAP = {
35
35
  underline: "underline",
36
36
  strikethrough: "strikethrough"
37
37
  };
38
- function codeDelimiter(content) {
39
- const longestRun = Math.max(0, ...[...content.matchAll(/`+/gu)].map((match) => match[0].length));
40
- return "`".repeat(longestRun + 1);
41
- }
42
- function restoreCodeMarkers(text, ranges, codeRanges) {
38
+ function extractMarkdownFormatRuns(input) {
39
+ const ir = markdownToIR(input, {
40
+ autolink: false,
41
+ enableHtmlUnderline: true,
42
+ headingStyle: "rich",
43
+ linkify: false,
44
+ preserveDunderIdentifiers: true,
45
+ preserveSourceBlockSpacing: true
46
+ });
47
+ const rendered = renderMarkdownWithAttributedRanges(ir, { styleMap: IMESSAGE_STYLE_MAP }, IMESSAGE_FORMAT_PROFILE);
48
+ const codeRanges = ir.styles.some((span) => span.style === "code") ? renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE).ranges : [];
49
+ const text = rendered.text;
50
+ const ranges = rendered.ranges.map(({ start, length, style }) => ({
51
+ start,
52
+ length,
53
+ styles: [style]
54
+ }));
43
55
  if (codeRanges.length === 0) return {
44
56
  text,
45
57
  ranges
@@ -47,7 +59,8 @@ function restoreCodeMarkers(text, ranges, codeRanges) {
47
59
  const edits = codeRanges.map((range) => {
48
60
  const end = range.start + range.length;
49
61
  const content = text.slice(range.start, end);
50
- const marker = codeDelimiter(content);
62
+ const longestRun = Math.max(0, ...[...content.matchAll(/`+/gu)].map((match) => match[0].length));
63
+ const marker = "`".repeat(longestRun + 1);
51
64
  const padding = content.startsWith("`") || content.endsWith("`") ? " " : "";
52
65
  return {
53
66
  start: range.start,
@@ -55,36 +68,19 @@ function restoreCodeMarkers(text, ranges, codeRanges) {
55
68
  text: `${marker}${padding}${content}${padding}${marker}`
56
69
  };
57
70
  });
58
- const { text: rendered, mapOffset } = applyMarkdownTextEdits(text, edits);
71
+ const { text: restoredText, mapOffset } = applyMarkdownTextEdits(text, edits);
59
72
  return {
60
- text: rendered,
73
+ text: restoredText,
61
74
  ranges: ranges.map((range) => {
62
75
  const start = mapOffset(range.start);
63
76
  return {
64
- ...range,
65
77
  start,
66
- length: mapOffset(range.start + range.length) - start
78
+ length: mapOffset(range.start + range.length) - start,
79
+ styles: range.styles
67
80
  };
68
81
  })
69
82
  };
70
83
  }
71
- function extractMarkdownFormatRuns(input) {
72
- const ir = markdownToIR(input, {
73
- autolink: false,
74
- enableHtmlUnderline: true,
75
- headingStyle: "rich",
76
- linkify: false,
77
- preserveDunderIdentifiers: true,
78
- preserveSourceBlockSpacing: true
79
- });
80
- const rendered = renderMarkdownWithAttributedRanges(ir, { styleMap: IMESSAGE_STYLE_MAP }, IMESSAGE_FORMAT_PROFILE);
81
- const codeRanges = ir.styles.some((span) => span.style === "code") ? renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE).ranges : [];
82
- return restoreCodeMarkers(rendered.text, rendered.ranges.map(({ start, length, style }) => ({
83
- start,
84
- length,
85
- styles: [style]
86
- })), codeRanges);
87
- }
88
84
  // extensions/imessage/src/monitor/sanitize-outbound.ts
89
85
  /**
90
86
  * Patterns that indicate assistant-internal metadata leaked into text.
@@ -1,26 +1,26 @@
1
- import { c as parseIMessageTarget, o as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-CIx4BKqL.mjs";
2
- import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-BH0coL46.mjs";
3
- import { S as resolveIMessageDirectChatService, d as IMESSAGE_SENT_ECHOES_NAMESPACE, f as IMESSAGE_SENT_ECHOES_TTL_MS, g as resolveIMessageSentEchoEntryKey, h as resolveIMessageEchoMediaKey, n as createIMessageRpcClient, r as runIMessageCliJsonCommand, s as rememberIMessageReplyCache, t as IMessageRpcRequestError, y as chatContextFromIMessageTarget } from "./client-C3e7ZLqA.mjs";
4
- import { a as normalizeIMessageMessageId, i as normalizeIMessageGuid } from "./actions-CW7XYYF4.mjs";
5
- import { n as getOptionalIMessageRuntime, t as getIMessageRuntime } from "./runtime-BRQCPuAD.mjs";
6
- import { d as getIMessageApprovalApprovers, f as imessageApprovalAuth } from "./channel-6kcKpSRw.mjs";
7
- import { n as sanitizeIMessageFinalOutboundText, t as protectIMessageFencedRoleMarkers } from "./sanitize-outbound-C02fJrn6.mjs";
8
- import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-CCgMYZ-u.mjs";
9
- import { d as resolveIMessageApprovalControlActor, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as normalizeConversationKey } from "./approval-reactions-B9CJS0NT.mjs";
1
+ import { l as parseIMessageTarget, n as iMessageTargetRpcParams, s as normalizeIMessageHandle, t as formatIMessageChatTarget } from "./targets-C7CIWJ0k.mjs";
2
+ import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-C1Ypv3Wn.mjs";
3
+ import { a as resolveIMessageDirectChatService, t as chatContextFromIMessageTarget } from "./chat-context-fTfJVqAi.mjs";
4
+ import { i as runIMessageCliJsonCommand, n as createIMessageRpcClient, t as IMessageRpcRequestError } from "./client-D_BaG8sC.mjs";
5
+ import { a as rememberIMessageReplyCache, b as normalizeIMessageMessageId, g as getOptionalIMessageRuntime, h as getIMessageRuntime, l as IMESSAGE_SENT_ECHOES_NAMESPACE, m as resolveIMessageSentEchoEntryKey, p as resolveIMessageEchoMediaKey, u as IMESSAGE_SENT_ECHOES_TTL_MS, v as createPersistenceFailureReporter, y as normalizeIMessageGuid } from "./actions-qOuKy8To.mjs";
6
+ import { d as getIMessageApprovalApprovers, f as imessageApprovalAuth } from "./channel-CLaN4mQn.mjs";
7
+ import { n as sanitizeIMessageFinalOutboundText, t as protectIMessageFencedRoleMarkers } from "./sanitize-outbound-Dhjhz0a-.mjs";
8
+ import { a as withIMessageReceiptGuidReader, r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-DpK3GQFD.mjs";
9
+ import { d as resolveIMessageApprovalControlActor, l as enumerateApprovalTargetKeys, r as registerIMessageApprovalReactionTarget, s as buildIMessageApprovalConversationKeyForInbound, u as normalizeConversationKey } from "./approval-reactions-DBBsqbRC.mjs";
10
10
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
11
11
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
12
12
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
13
13
  import { accessSync, constants } from "node:fs";
14
14
  import { basename } from "node:path";
15
15
  import { extractOriginalFilename, kindFromMime, resolveOutboundAttachmentFromUrl } from "openclaw/plugin-sdk/media-runtime";
16
- import { logVerbose, sleep } from "openclaw/plugin-sdk/runtime-env";
17
- import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
16
+ import { sleep } from "openclaw/plugin-sdk/runtime-env";
18
17
  import { PlatformMessageNotDispatchedError, isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
19
18
  import { captureChannelReadAuthority, captureEffectAuthority } from "openclaw/plugin-sdk/fetch-runtime";
20
19
  import { addApprovalReactionHintToText, createApprovalReactionTargetStore, listApprovalReactionBindings } from "openclaw/plugin-sdk/approval-reaction-runtime";
21
20
  import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
22
21
  import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
23
22
  import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
23
+ import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
24
24
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
25
25
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
26
26
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -313,7 +313,6 @@ async function maybeResolveIMessageApprovalPollVote(params) {
313
313
  channel: "imessage",
314
314
  accountId: params.accountId,
315
315
  senderId: event.actorHandle,
316
- gatewayUrl: params.gatewayUrl,
317
316
  ...params.gatewayRuntime ? { gatewayRuntime: params.gatewayRuntime } : {}
318
317
  });
319
318
  await unregisterIMessageApprovalPollTarget({
@@ -345,16 +344,10 @@ async function maybeResolveIMessageApprovalPollVote(params) {
345
344
  throw error;
346
345
  }
347
346
  }
348
- function clearIMessageApprovalPollTargetsForTest() {
349
- pollTargets.clearForTest();
350
- pollTombstones.clearForTest();
351
- loadResolveApprovalOverGateway.clear();
352
- }
353
347
  const iMessageApprovalPollTargets = {
354
348
  register: registerIMessageApprovalPollTarget,
355
349
  unregister: unregisterIMessageApprovalPollTarget,
356
- registerTombstone: registerIMessageApprovalPollTombstone,
357
- clearForTest: clearIMessageApprovalPollTargetsForTest
350
+ registerTombstone: registerIMessageApprovalPollTombstone
358
351
  };
359
352
  // extensions/imessage/src/monitor/echo-text-corruption.ts
360
353
  function isLeadingEchoTextCorruptionMarker(code) {
@@ -368,12 +361,7 @@ function normalizeIMessageEchoText(text) {
368
361
  return normalized.slice(offset).trim() || void 0;
369
362
  }
370
363
  // extensions/imessage/src/monitor/persisted-echo-cache.ts
371
- let persistenceFailureLogged = false;
372
- function reportFailure(scope, err) {
373
- if (persistenceFailureLogged) return;
374
- persistenceFailureLogged = true;
375
- logVerbose(`imessage echo-cache: ${scope} disabled after first failure: ${String(err)}`);
376
- }
364
+ const reportFailure = createPersistenceFailureReporter("echo-cache");
377
365
  function normalizeMedia(media) {
378
366
  if (!resolveIMessageEchoMediaKey(media)) return;
379
367
  const contentType = media?.contentType?.trim().toLowerCase() || void 0;
@@ -393,28 +381,23 @@ function remainingTtlMs(timestamp) {
393
381
  const remaining = IMESSAGE_SENT_ECHOES_TTL_MS - Math.max(0, Date.now() - timestamp);
394
382
  return remaining > 0 ? remaining : void 0;
395
383
  }
396
- function resolveEntryTtlMs(entry, ttlMs) {
397
- if (typeof ttlMs === "number" && Number.isFinite(ttlMs) && ttlMs > 0) return ttlMs;
398
- return remainingTtlMs(entry.timestamp);
399
- }
400
384
  function isLiveEntry(entry, now = Date.now()) {
401
385
  const cutoff = now - IMESSAGE_SENT_ECHOES_TTL_MS;
402
386
  return entry.timestamp >= cutoff && (entry.expiresAt == null || entry.expiresAt > now);
403
387
  }
404
388
  async function readRecentEntries() {
405
389
  try {
406
- return (await openPersistedEchoStore().entries()).map(({ value }) => value).filter((entry) => isLiveEntry(entry)).toSorted((a, b) => a.timestamp - b.timestamp).slice(-256);
390
+ return (await openPersistedEchoStore().entries()).map(({ value }) => value).filter((entry) => isLiveEntry(entry));
407
391
  } catch (err) {
408
392
  reportFailure("read", err);
409
393
  return [];
410
394
  }
411
395
  }
412
396
  async function persistEntry(entry, ttlMs) {
413
- const effectiveTtlMs = resolveEntryTtlMs(entry, ttlMs);
414
- if (!effectiveTtlMs) return;
397
+ if (!ttlMs) return;
415
398
  const key = resolveIMessageSentEchoEntryKey(entry);
416
399
  try {
417
- await openPersistedEchoStore().register(key, entry, { ttlMs: effectiveTtlMs });
400
+ await openPersistedEchoStore().register(key, entry, { ttlMs });
418
401
  } catch (err) {
419
402
  reportFailure("write", err);
420
403
  return;
@@ -433,9 +416,10 @@ async function rememberPersistedIMessageEcho(params) {
433
416
  ...messageId ? { messageId } : {},
434
417
  ...params.pending ? { pending: true } : {}
435
418
  };
436
- if (typeof params.ttlMs === "number" && Number.isFinite(params.ttlMs) && params.ttlMs > 0) entry.expiresAt = entry.timestamp + params.ttlMs;
419
+ const ttlMs = typeof params.ttlMs === "number" && Number.isFinite(params.ttlMs) && params.ttlMs > 0 ? params.ttlMs : void 0;
420
+ if (ttlMs !== void 0) entry.expiresAt = entry.timestamp + ttlMs;
437
421
  if (!entry.text && !entry.media && !entry.messageId) return;
438
- return await persistEntry(entry, params.ttlMs);
422
+ return await persistEntry(entry, ttlMs ?? remainingTtlMs(entry.timestamp));
439
423
  }
440
424
  async function forgetPersistedIMessageEchoKey(key) {
441
425
  if (!key) return;
@@ -463,14 +447,13 @@ async function hasPersistedIMessageEcho(params) {
463
447
  function bindIMessageCliSend(handoff, options) {
464
448
  const effect = captureEffectAuthority();
465
449
  const assertReadAuthority = captureChannelReadAuthority();
466
- const runCli = handoff.runCliJson ?? ((args) => runIMessageCliJsonCommand({
467
- ...options,
468
- args
469
- }));
470
450
  return (args) => effect.initiate(() => {
471
451
  assertReadAuthority?.();
472
452
  handoff.assertDirectAdapterHandoff?.();
473
- return runCli(args);
453
+ return runIMessageCliJsonCommand({
454
+ ...options,
455
+ args
456
+ });
474
457
  });
475
458
  }
476
459
  function normalizeIMessageRpcSendError(error) {
@@ -517,74 +500,25 @@ function canResolveLatestSentMessageGuidFromChatDb(dbPath) {
517
500
  return false;
518
501
  }
519
502
  }
520
- async function resolveApprovalBindingMessageGuid(params) {
521
- for (const key of [
522
- "messageGuid",
523
- "guid",
524
- "messageId",
525
- "message_id",
526
- "id"
527
- ]) {
528
- const guid = normalizeResolvedMessageGuid(params.result?.[key]);
529
- if (guid) return guid;
530
- }
531
- const messageId = params.messageId?.trim();
532
- if (!messageId || !isNumericMessageRowId(messageId)) return null;
533
- if (params.resolveMessageGuidImpl) return normalizeResolvedMessageGuid(await params.resolveMessageGuidImpl({
534
- dbPath: params.dbPath,
535
- messageId
536
- }));
537
- const dbPath = params.dbPath?.trim();
538
- return dbPath ? normalizeResolvedMessageGuid(await withIMessageReceiptGuidReader(dbPath, (read) => read({
539
- type: "messageGuid",
540
- input: { messageId }
541
- }))) : null;
542
- }
543
503
  async function resolveFallbackSentMessageGuid(params) {
544
504
  const dbPath = params.dbPath?.trim();
545
- if (!params.resolveSentMessageGuidImpl && !canResolveLatestSentMessageGuidFromChatDb(dbPath)) return null;
505
+ if (!dbPath || !canResolveLatestSentMessageGuidFromChatDb(dbPath)) return null;
546
506
  const deadlineMs = Date.now() + 5e3;
547
- const poll = async (resolver) => {
507
+ return await withIMessageReceiptGuidReader(dbPath, async (read) => {
548
508
  while (Date.now() <= deadlineMs) {
549
- const resolved = normalizeResolvedMessageGuid(await resolver({
550
- dbPath: params.dbPath,
551
- target: params.target,
552
- text: params.text,
553
- sentAfterMs: params.sentAfterMs
509
+ const resolved = normalizeResolvedMessageGuid(await read({
510
+ type: "latestSentGuid",
511
+ input: {
512
+ target: params.target,
513
+ text: params.text,
514
+ sentAfterMs: params.sentAfterMs
515
+ }
554
516
  }));
555
517
  if (resolved) return resolved;
556
518
  if (Date.now() >= deadlineMs) return null;
557
519
  await sleep(250);
558
520
  }
559
521
  return null;
560
- };
561
- if (params.resolveSentMessageGuidImpl) return await poll(params.resolveSentMessageGuidImpl);
562
- if (!dbPath) return null;
563
- return await withIMessageReceiptGuidReader(dbPath, (read) => poll(({ target, text, sentAfterMs }) => read({
564
- type: "latestSentGuid",
565
- input: {
566
- target,
567
- text,
568
- sentAfterMs
569
- }
570
- })));
571
- }
572
- function createIMessageSendReceipt(params) {
573
- const messageId = params.messageId.trim();
574
- const results = normalizeIMessageMessageId(messageId) ? [{
575
- channel: "imessage",
576
- messageId,
577
- meta: { targetKind: params.target.kind }
578
- }] : [];
579
- if (results[0]) {
580
- if (params.target.kind === "chat_id") results[0].chatId = String(params.target.chatId);
581
- else if (params.target.kind === "chat_guid") results[0].conversationId = params.target.chatGuid;
582
- else if (params.target.kind === "chat_identifier") results[0].conversationId = params.target.chatIdentifier;
583
- }
584
- return createMessageReceiptFromOutboundResults({
585
- results,
586
- kind: params.kind,
587
- ...params.replyToId ? { replyToId: params.replyToId } : {}
588
522
  });
589
523
  }
590
524
  async function withOriginalIMessageAttachmentPath(filePath, send) {
@@ -595,12 +529,6 @@ async function withOriginalIMessageAttachmentPath(filePath, send) {
595
529
  prefix: "openclaw-imessage-outbound-"
596
530
  }, async (workspace) => await send(await workspace.copyIn(filename, filePath)));
597
531
  }
598
- function resolveOutboundEchoScope(params) {
599
- if (params.target.kind === "chat_id") return `${params.accountId}:${formatIMessageChatTarget(params.target.chatId)}`;
600
- if (params.target.kind === "chat_guid") return `${params.accountId}:chat_guid:${params.target.chatGuid}`;
601
- if (params.target.kind === "chat_identifier") return `${params.accountId}:chat_identifier:${params.target.chatIdentifier}`;
602
- return `${params.accountId}:imessage:${params.target.to}`;
603
- }
604
532
  function resolveIMessageSendFailure(result) {
605
533
  if (result.success !== false) return null;
606
534
  return typeof result.error === "string" && result.error.trim() ? result.error.trim() : "iMessage action failed";
@@ -664,7 +592,7 @@ async function sendMessageIMessage(to, text, opts) {
664
592
  const timeoutMs = opts.timeoutMs ?? Math.max(account.config.probeTimeoutMs ?? 0, 18e4);
665
593
  const pendingEchoTtlMs = Math.max(MIN_PENDING_PERSISTED_ECHO_TTL_MS, Math.max(0, timeoutMs) + PENDING_PERSISTED_ECHO_GRACE_MS);
666
594
  const region = opts.region?.trim() || account.config.region?.trim() || "US";
667
- const maxBytes = typeof opts.maxBytes === "number" ? opts.maxBytes : typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : 16777216;
595
+ const maxBytes = opts.maxBytes ?? (account.config.mediaMaxMb ?? 16) * 1024 * 1024;
668
596
  let message = opts.approvalPrompt ? addApprovalReactionHintToText({
669
597
  text,
670
598
  allowedDecisions: opts.approvalPrompt.allowedDecisions
@@ -674,7 +602,7 @@ async function sendMessageIMessage(to, text, opts) {
674
602
  let filePath;
675
603
  let mediaContentType;
676
604
  if (opts.mediaUrl?.trim()) {
677
- const resolved = await (opts.resolveAttachmentImpl ?? resolveOutboundAttachmentFromUrl)(opts.mediaUrl.trim(), maxBytes, {
605
+ const resolved = await resolveOutboundAttachmentFromUrl(opts.mediaUrl.trim(), maxBytes, {
678
606
  mediaAccess: opts.mediaAccess,
679
607
  localRoots: opts.mediaLocalRoots,
680
608
  readFile: opts.mediaReadFile
@@ -717,7 +645,7 @@ async function sendMessageIMessage(to, text, opts) {
717
645
  });
718
646
  const requestOwnedRpc = async (method, rpcParams) => {
719
647
  opts.assertDirectAdapterHandoff?.();
720
- const rpcClient = await (opts.createClient ?? createIMessageRpcClient)({
648
+ const rpcClient = await createIMessageRpcClient({
721
649
  cliPath,
722
650
  dbPath,
723
651
  remoteHost
@@ -728,10 +656,109 @@ async function sendMessageIMessage(to, text, opts) {
728
656
  await rpcClient.stop();
729
657
  }
730
658
  };
731
- const withRemoteFile = opts.withRemoteFile ?? withIMessageRemoteFile;
659
+ const echoScope = target.kind === "chat_id" ? `${account.accountId}:${formatIMessageChatTarget(target.chatId)}` : target.kind === "chat_guid" ? `${account.accountId}:chat_guid:${target.chatGuid}` : target.kind === "chat_identifier" ? `${account.accountId}:chat_identifier:${target.chatIdentifier}` : `${account.accountId}:imessage:${target.to}`;
660
+ async function recordAcceptedSend(result, delivery) {
661
+ const isMessage = delivery.kind === "message";
662
+ const resolvedId = resolveMessageId(result);
663
+ const messageId = resolvedId ?? (result.ok || result.success || isMessage && result.status === "sent" ? "ok" : "unknown");
664
+ let guid = null;
665
+ for (const key of [
666
+ "messageGuid",
667
+ "guid",
668
+ "messageId",
669
+ "message_id",
670
+ "id"
671
+ ]) {
672
+ guid = normalizeResolvedMessageGuid(result[key]);
673
+ if (guid) break;
674
+ }
675
+ if (!guid) {
676
+ const rowId = resolvedId?.trim();
677
+ if (rowId && isNumericMessageRowId(rowId)) {
678
+ const lookupPath = chatDbLookupPath?.trim();
679
+ if (lookupPath) guid = normalizeResolvedMessageGuid(await withIMessageReceiptGuidReader(lookupPath, (read) => read({
680
+ type: "messageGuid",
681
+ input: { messageId: rowId }
682
+ })));
683
+ }
684
+ }
685
+ if (!guid && isMessage && opts.approvalPrompt && !filePath && !effectiveReplyToId) guid = await resolveFallbackSentMessageGuid({
686
+ dbPath: chatDbLookupPath,
687
+ target,
688
+ text: message,
689
+ sentAfterMs: delivery.startedAtMs
690
+ });
691
+ await rememberPersistedIMessageEcho({
692
+ scope: echoScope,
693
+ text: isMessage ? echoText : void 0,
694
+ media: echoMedia,
695
+ messageId: resolvedId ?? void 0
696
+ });
697
+ const providerChatGuid = isMessage ? normalizeOptionalString(result.chat_guid) ?? normalizeOptionalString(result.chatGuid) : void 0;
698
+ const confirmedService = isMessage ? resolveIMessageDirectChatService(resultService(result.service) ?? service, providerChatGuid) : void 0;
699
+ if (resolvedId && normalizeIMessageMessageId(resolvedId)) {
700
+ const chatContext = isMessage ? {
701
+ ...chatContextFromIMessageTarget(target, confirmedService ?? service),
702
+ ...providerChatGuid ? { chatGuid: providerChatGuid } : {}
703
+ } : {
704
+ chatGuid: target.kind === "chat_guid" ? target.chatGuid : target.kind === "chat_id" ? delivery.chatTarget : void 0,
705
+ chatIdentifier: target.kind === "chat_identifier" || target.kind === "handle" ? delivery.chatTarget : void 0,
706
+ chatId: target.kind === "chat_id" ? target.chatId : void 0
707
+ };
708
+ await rememberIMessageReplyCache({
709
+ accountId: account.accountId,
710
+ messageId: resolvedId,
711
+ ...chatContext,
712
+ timestamp: Date.now(),
713
+ isFromMe: true
714
+ });
715
+ }
716
+ if (isMessage && message && guid && opts.approvalPrompt) {
717
+ const handle = target.kind === "handle" ? normalizeIMessageHandle(target.to) : void 0;
718
+ const conversation = {
719
+ ...target.kind === "chat_guid" ? { chatGuid: target.chatGuid } : {},
720
+ ...target.kind === "chat_identifier" ? { chatIdentifier: target.chatIdentifier } : {},
721
+ ...target.kind === "chat_id" ? { chatId: target.chatId } : {},
722
+ ...handle ? { handle } : {}
723
+ };
724
+ await registerIMessageApprovalReactionTarget({
725
+ accountId: account.accountId,
726
+ conversation,
727
+ messageId: guid,
728
+ approvalId: opts.approvalPrompt.approvalId,
729
+ approvalKind: opts.approvalPrompt.approvalKind,
730
+ allowedDecisions: opts.approvalPrompt.allowedDecisions
731
+ });
732
+ }
733
+ const replyToId = isMessage ? effectiveReplyToId : resolvedReplyToId;
734
+ const receiptMessageId = messageId.trim();
735
+ const results = normalizeIMessageMessageId(receiptMessageId) ? [{
736
+ channel: "imessage",
737
+ messageId: receiptMessageId,
738
+ meta: { targetKind: target.kind }
739
+ }] : [];
740
+ if (results[0]) {
741
+ if (target.kind === "chat_id") results[0].chatId = String(target.chatId);
742
+ else if (target.kind === "chat_guid") results[0].conversationId = target.chatGuid;
743
+ else if (target.kind === "chat_identifier") results[0].conversationId = target.chatIdentifier;
744
+ }
745
+ return {
746
+ messageId,
747
+ ...guid ? { guid } : {},
748
+ ...confirmedService ? { service: confirmedService } : {},
749
+ ...providerChatGuid ? { chatGuid: providerChatGuid } : {},
750
+ sentText: isMessage ? message : "",
751
+ ...isMessage && echoText ? { echoText } : {},
752
+ ...echoMedia ? { echoMedia } : {},
753
+ receipt: createMessageReceiptFromOutboundResults({
754
+ results,
755
+ kind: isMessage ? filePath ? "media" : "text" : delivery.audioAsVoice ? "voice" : "media",
756
+ ...replyToId ? { replyToId } : {}
757
+ })
758
+ };
759
+ }
732
760
  async function trySendAttachment(attachmentFilePath) {
733
- const { audioAsVoice, resolveMessageGuidImpl, assertDirectAdapterHandoff, onPlatformSendDispatch } = opts;
734
- const accountId = account.accountId;
761
+ const { audioAsVoice, assertDirectAdapterHandoff, onPlatformSendDispatch } = opts;
735
762
  if (audioAsVoice && sendTransport === "applescript") throw new Error("iMessage voice messages require bridge transport; AppleScript cannot send native voice notes. Set sendTransport to bridge or auto.");
736
763
  if (target.kind === "handle" && !audioAsVoice && sendTransport !== "bridge" && (service === "sms" || service === "imessage")) return null;
737
764
  if (remoteHost && sendTransport === "applescript") return null;
@@ -763,10 +790,6 @@ async function sendMessageIMessage(to, text, opts) {
763
790
  return null;
764
791
  }
765
792
  assertDirectAdapterHandoff?.();
766
- const echoScope = resolveOutboundEchoScope({
767
- accountId,
768
- target
769
- });
770
793
  let result;
771
794
  let pendingEchoKey;
772
795
  try {
@@ -777,7 +800,7 @@ async function sendMessageIMessage(to, text, opts) {
777
800
  pending: true
778
801
  });
779
802
  result = await withOriginalIMessageAttachmentPath(attachmentFilePath, async (attachmentPath) => {
780
- if (remoteHost) return await withRemoteFile({
803
+ if (remoteHost) return await withIMessageRemoteFile({
781
804
  remoteHost,
782
805
  localPath: attachmentPath,
783
806
  timeoutMs,
@@ -816,40 +839,11 @@ async function sendMessageIMessage(to, text, opts) {
816
839
  if (!audioAsVoice && isAttachmentCommandFallbackError(error)) return null;
817
840
  throw error;
818
841
  }
819
- const resolvedId = resolveMessageId(result);
820
- const approvalBindingMessageId = await resolveApprovalBindingMessageGuid({
821
- dbPath: chatDbLookupPath,
822
- messageId: resolvedId,
823
- result,
824
- resolveMessageGuidImpl
842
+ return await recordAcceptedSend(result, {
843
+ kind: "attachment",
844
+ chatTarget: attachmentChatTarget,
845
+ audioAsVoice
825
846
  });
826
- const messageId = resolvedId ?? (result.ok || result.success ? "ok" : "unknown");
827
- await rememberPersistedIMessageEcho({
828
- scope: echoScope,
829
- media: echoMedia,
830
- messageId: resolvedId ?? void 0
831
- });
832
- if (resolvedId && normalizeIMessageMessageId(resolvedId)) await rememberIMessageReplyCache({
833
- accountId,
834
- messageId: resolvedId,
835
- chatGuid: target.kind === "chat_guid" ? target.chatGuid : target.kind === "chat_id" ? attachmentChatTarget : void 0,
836
- chatIdentifier: target.kind === "chat_identifier" || target.kind === "handle" ? attachmentChatTarget : void 0,
837
- chatId: target.kind === "chat_id" ? target.chatId : void 0,
838
- timestamp: Date.now(),
839
- isFromMe: true
840
- });
841
- return {
842
- messageId,
843
- ...approvalBindingMessageId ? { guid: approvalBindingMessageId } : {},
844
- sentText: "",
845
- ...echoMedia ? { echoMedia } : {},
846
- receipt: createIMessageSendReceipt({
847
- messageId,
848
- target,
849
- kind: audioAsVoice ? "voice" : "media",
850
- ...resolvedReplyToId ? { replyToId: resolvedReplyToId } : {}
851
- })
852
- };
853
847
  }
854
848
  if (filePath && (!resolvedReplyToId || opts.audioAsVoice)) {
855
849
  const attachmentResult = await trySendAttachment(filePath);
@@ -891,6 +885,7 @@ async function sendMessageIMessage(to, text, opts) {
891
885
  }
892
886
  }
893
887
  const params = {
888
+ ...iMessageTargetRpcParams(target),
894
889
  text: message,
895
890
  service: service || "auto",
896
891
  region,
@@ -899,16 +894,8 @@ async function sendMessageIMessage(to, text, opts) {
899
894
  if (resolvedReplyToId) params.reply_to = resolvedReplyToId;
900
895
  if (formatted.ranges.length > 0) params.formatting = formatted.ranges;
901
896
  if (filePath) params.file = filePath;
902
- if (target.kind === "chat_id") params.chat_id = target.chatId;
903
- else if (target.kind === "chat_guid") params.chat_guid = target.chatGuid;
904
- else if (target.kind === "chat_identifier") params.chat_identifier = target.chatIdentifier;
905
- else params.to = target.to;
906
- const echoScope = resolveOutboundEchoScope({
907
- accountId: account.accountId,
908
- target
909
- });
910
897
  opts.assertDirectAdapterHandoff?.();
911
- const client = opts.client ?? await (opts.createClient ?? createIMessageRpcClient)({
898
+ const client = opts.client ?? await createIMessageRpcClient({
912
899
  cliPath,
913
900
  dbPath,
914
901
  remoteHost
@@ -917,7 +904,7 @@ async function sendMessageIMessage(to, text, opts) {
917
904
  const requestSuccessfulSend = async (sendParams) => {
918
905
  const request = async (nativeParams) => await requestIMessageRpcSend(client, "send", nativeParams, timeoutMs, opts);
919
906
  const response = filePath ? await withOriginalIMessageAttachmentPath(filePath, async (attachmentPath) => {
920
- if (remoteHost) return await withRemoteFile({
907
+ if (remoteHost) return await withIMessageRemoteFile({
921
908
  remoteHost,
922
909
  localPath: attachmentPath,
923
910
  timeoutMs,
@@ -956,14 +943,13 @@ async function sendMessageIMessage(to, text, opts) {
956
943
  result = await requestSuccessfulSend(plainParams);
957
944
  effectiveReplyToId = void 0;
958
945
  } else if (filePath || !isIMessageRpcSendTimeout(error)) throw error;
959
- else if (!opts.approvalPrompt || resolvedReplyToId || !(opts.resolveSentMessageGuidImpl || canResolveLatestSentMessageGuidFromChatDb(chatDbLookupPath))) throw error;
946
+ else if (!opts.approvalPrompt || resolvedReplyToId || !canResolveLatestSentMessageGuidFromChatDb(chatDbLookupPath)) throw error;
960
947
  else {
961
948
  const recoveredGuid = await resolveFallbackSentMessageGuid({
962
949
  dbPath: chatDbLookupPath,
963
950
  target,
964
951
  text: message,
965
- sentAfterMs: sendStartedAtMs,
966
- resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
952
+ sentAfterMs: sendStartedAtMs
967
953
  });
968
954
  if (recoveredGuid) result = {
969
955
  guid: recoveredGuid,
@@ -972,72 +958,10 @@ async function sendMessageIMessage(to, text, opts) {
972
958
  else throw error;
973
959
  }
974
960
  }
975
- const resolvedId = resolveMessageId(result);
976
- const messageId = resolvedId ?? (result?.ok || result?.success || result?.status === "sent" ? "ok" : "unknown");
977
- let approvalBindingMessageId = await resolveApprovalBindingMessageGuid({
978
- dbPath: chatDbLookupPath,
979
- messageId: resolvedId,
980
- result,
981
- resolveMessageGuidImpl: opts.resolveMessageGuidImpl
982
- });
983
- if (!approvalBindingMessageId && opts.approvalPrompt && !filePath && !effectiveReplyToId) approvalBindingMessageId = await resolveFallbackSentMessageGuid({
984
- dbPath: chatDbLookupPath,
985
- target,
986
- text: message,
987
- sentAfterMs: sendStartedAtMs,
988
- resolveSentMessageGuidImpl: opts.resolveSentMessageGuidImpl
989
- });
990
- await rememberPersistedIMessageEcho({
991
- scope: echoScope,
992
- text: echoText,
993
- media: echoMedia,
994
- messageId: resolvedId ?? void 0
961
+ return await recordAcceptedSend(result, {
962
+ kind: "message",
963
+ startedAtMs: sendStartedAtMs
995
964
  });
996
- const providerChatGuid = normalizeOptionalString(result.chat_guid) ?? normalizeOptionalString(result.chatGuid);
997
- const confirmedService = resolveIMessageDirectChatService(resultService(result.service) ?? service, providerChatGuid);
998
- if (resolvedId && normalizeIMessageMessageId(resolvedId)) {
999
- const chatContext = chatContextFromIMessageTarget(target, confirmedService ?? service);
1000
- await rememberIMessageReplyCache({
1001
- accountId: account.accountId,
1002
- messageId: resolvedId,
1003
- ...chatContext,
1004
- ...providerChatGuid ? { chatGuid: providerChatGuid } : {},
1005
- timestamp: Date.now(),
1006
- isFromMe: true
1007
- });
1008
- }
1009
- if (message && approvalBindingMessageId && opts.approvalPrompt) {
1010
- const handleForKey = target.kind === "handle" ? normalizeIMessageHandle(target.to) : void 0;
1011
- const conversation = {
1012
- ...target.kind === "chat_guid" ? { chatGuid: target.chatGuid } : {},
1013
- ...target.kind === "chat_identifier" ? { chatIdentifier: target.chatIdentifier } : {},
1014
- ...target.kind === "chat_id" ? { chatId: target.chatId } : {},
1015
- ...handleForKey ? { handle: handleForKey } : {}
1016
- };
1017
- await registerIMessageApprovalReactionTarget({
1018
- accountId: account.accountId,
1019
- conversation,
1020
- messageId: approvalBindingMessageId,
1021
- approvalId: opts.approvalPrompt.approvalId,
1022
- approvalKind: opts.approvalPrompt.approvalKind,
1023
- allowedDecisions: opts.approvalPrompt.allowedDecisions
1024
- });
1025
- }
1026
- return {
1027
- messageId,
1028
- ...approvalBindingMessageId ? { guid: approvalBindingMessageId } : {},
1029
- ...confirmedService ? { service: confirmedService } : {},
1030
- ...providerChatGuid ? { chatGuid: providerChatGuid } : {},
1031
- sentText: message,
1032
- ...echoText ? { echoText } : {},
1033
- ...echoMedia ? { echoMedia } : {},
1034
- receipt: createIMessageSendReceipt({
1035
- messageId,
1036
- target,
1037
- kind: filePath ? "media" : "text",
1038
- ...effectiveReplyToId ? { replyToId: effectiveReplyToId } : {}
1039
- })
1040
- };
1041
965
  } catch (error) {
1042
966
  await forgetPersistedIMessageEchoKey(pendingEchoKey);
1043
967
  throw error;
@@ -1,5 +1,5 @@
1
- import { l as IMESSAGE_CHAT_TARGET_PREFIX_RE, o as normalizeIMessageHandle } from "./targets-CIx4BKqL.mjs";
2
- import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-BH0coL46.mjs";
1
+ import { s as normalizeIMessageHandle, u as IMESSAGE_CHAT_TARGET_PREFIX_RE } from "./targets-C7CIWJ0k.mjs";
2
+ import { a as resolveDefaultIMessageAccountId, o as resolveIMessageAccount } from "./accounts-C1Ypv3Wn.mjs";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
5
5
  import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";