@openclaw/imessage 2026.10.10-beta.5 → 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 (142) hide show
  1. package/dist/.setup/{accounts-DacCvDBt.mjs → accounts-C1Ypv3Wn.mjs} +9 -13
  2. package/dist/.setup/{actions-762Azi-J.mjs → actions-qOuKy8To.mjs} +364 -116
  3. package/dist/.setup/{actions.runtime-DHiRiPHe.mjs → actions.runtime-Ccg9CARL.mjs} +12 -61
  4. package/dist/.setup/{api-Deyo8NDs.mjs → api-BXXuQQCS.mjs} +8 -9
  5. package/dist/.setup/{api-BFGXDHiC.mjs → api-DTbxSOPc.mjs} +9 -9
  6. package/dist/.setup/{approval-handler.runtime-fsSBf2jf.mjs → approval-handler.runtime-B6vrFfZx.mjs} +113 -133
  7. package/dist/.setup/{approval-reactions-CoAkCiwf.mjs → approval-reactions-DBBsqbRC.mjs} +156 -79
  8. package/dist/.setup/{channel-C61YdcZR.mjs → channel-CLaN4mQn.mjs} +151 -137
  9. package/dist/.setup/{channel.runtime-B5jle0g3.mjs → channel.runtime-XJGx1MIH.mjs} +236 -425
  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-DXwa_3V5.mjs → config-schema-BjkQV5P5.mjs} +1 -4
  14. package/dist/.setup/{conversation-bindings-DR-dbHjs.mjs → conversation-bindings-8DjxoIYU.mjs} +10 -8
  15. package/dist/.setup/{media-contract-BwWs5PM7.mjs → media-contract-BErFBKV9.mjs} +2 -3
  16. package/dist/.setup/{message-tool-api-B5NfPnFL.mjs → message-tool-api-DtZ1wKbT.mjs} +6 -12
  17. package/dist/.setup/{outbound-send-deps-B-QEsLSM.mjs → outbound-send-deps-_da8jqeo.mjs} +1 -2
  18. package/dist/.setup/{remote-file-B94a787O.mjs → remote-file-DpK3GQFD.mjs} +12 -30
  19. package/dist/.setup/{rolldown-runtime-BBjsoOtd.mjs → rolldown-runtime-782esTHO.mjs} +1 -2
  20. package/dist/.setup/{sanitize-outbound-BtEY324R.mjs → sanitize-outbound-Dhjhz0a-.mjs} +25 -31
  21. package/dist/.setup/{send-BvxKNWzF.mjs → send-DhEW0gfe.mjs} +155 -236
  22. package/dist/.setup/{setup-core-BHyLkAEJ.mjs → setup-core-B1_P_t4T.mjs} +3 -4
  23. package/dist/.setup/{setup-surface-DPqiLGy0.mjs → setup-surface-CD28mXWK.mjs} +13 -29
  24. package/dist/.setup/{targets-B4oU7n-v.mjs → targets-C7CIWJ0k.mjs} +15 -9
  25. package/dist/.source-module-urls/929c518fa2986b0f85f66bceefead22868db0ab452dee914dc6a2bb86b2e60ad.json +1 -1
  26. package/dist/api.js +9 -9
  27. package/dist/channel-config-api.js +1 -1
  28. package/dist/channel-plugin-api.js +1 -1
  29. package/dist/contract-api.js +1 -1
  30. package/dist/doctor-contract-api.js +7 -13
  31. package/dist/index.js +1 -2
  32. package/dist/media-contract-api.js +1 -1
  33. package/dist/message-tool-api.js +1 -1
  34. package/dist/runtime-api.js +1 -3
  35. package/dist/secret-contract-api.js +1 -2
  36. package/dist/session-binding-contract-api.js +1 -1
  37. package/dist/setup-entry.js +2 -3
  38. package/dist/src/chat-db.worker.js +2 -3
  39. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  40. package/node_modules/typebox/build/format/duration.mjs +2 -2
  41. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  42. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  43. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  44. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  45. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  46. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  47. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  48. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  49. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  50. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  51. package/node_modules/typebox/build/schema/build.mjs +1 -0
  52. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  53. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  54. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  55. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  56. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  57. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  58. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  59. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  60. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  61. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  62. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  63. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  64. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  65. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  66. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  67. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  68. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  69. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  70. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  71. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  72. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  73. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  74. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  75. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  76. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  77. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  78. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  79. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  80. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  81. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  82. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  83. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  84. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  85. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  86. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  87. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  88. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  89. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  90. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  91. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  92. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  93. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  94. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  95. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  96. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  97. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  98. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  99. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  100. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  101. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  102. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  103. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  104. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  105. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  106. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  107. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  108. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  109. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  110. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  111. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  112. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  113. package/node_modules/typebox/package.json +1 -1
  114. package/node_modules/typebox/readme.md +1 -1
  115. package/node_modules/zod/package.json +1 -1
  116. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  117. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  118. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  119. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  120. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  121. package/node_modules/zod/src/v4/core/util.ts +13 -0
  122. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  123. package/node_modules/zod/v4/core/compile.cjs +8 -0
  124. package/node_modules/zod/v4/core/compile.js +8 -0
  125. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  126. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  127. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  128. package/node_modules/zod/v4/core/schemas.js +30 -0
  129. package/node_modules/zod/v4/core/util.cjs +15 -0
  130. package/node_modules/zod/v4/core/util.d.cts +2 -0
  131. package/node_modules/zod/v4/core/util.d.ts +2 -0
  132. package/node_modules/zod/v4/core/util.js +14 -0
  133. package/node_modules/zod/v4/core/versions.cjs +1 -1
  134. package/node_modules/zod/v4/core/versions.js +1 -1
  135. package/openclaw.plugin.json +0 -30
  136. package/package.json +6 -6
  137. package/dist/.setup/client-CcROCvRq.mjs +0 -746
  138. package/dist/.setup/question-reactions-BD06B1Lx.mjs +0 -68
  139. package/dist/.setup/reaction-context-Q26DYzQH.mjs +0 -106
  140. package/dist/.setup/runtime-Cza4CY5T.mjs +0 -8
  141. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  142. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
@@ -1,26 +1,27 @@
1
- import { c as parseIMessageTarget } from "./targets-B4oU7n-v.mjs";
2
- import { l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-DacCvDBt.mjs";
3
- import { a as setCachedIMessagePrivateApiStatus, n as getCachedIMessagePrivateApiStatus, o as IMESSAGE_ACTIONS, r as imessageRpcSupportsMethod, s as IMESSAGE_ACTION_NAMES, t as describeIMessageMessageTool } from "./message-tool-api-B5NfPnFL.mjs";
4
- import { a as isIMessageCurrentMessageInChatAsync, i as findLatestIMessageEntryForChat, n as createIMessageRpcClient, s as rememberIMessageReplyCache, y as chatContextFromIMessageTarget } from "./client-CcROCvRq.mjs";
5
- import { l as isAutoManagedIMessageCliPath, n as IMESSAGE_UPDATE_COMMAND, t as IMESSAGE_INSTALL_COMMAND } from "./setup-core-BHyLkAEJ.mjs";
6
- import { filterStringEntries, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { l as parseIMessageTarget } from "./targets-C7CIWJ0k.mjs";
2
+ import { l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-C1Ypv3Wn.mjs";
3
+ import { a as setCachedIMessagePrivateApiStatus, n as getCachedIMessagePrivateApiStatus, o as IMESSAGE_ACTIONS, r as imessageRpcSupportsMethod, s as IMESSAGE_ACTION_NAMES, t as describeIMessageMessageTool } from "./message-tool-api-DtZ1wKbT.mjs";
4
+ import { i as resolveIMessageChatMatch, t as chatContextFromIMessageTarget } from "./chat-context-fTfJVqAi.mjs";
5
+ import { n as createIMessageRpcClient } from "./client-D_BaG8sC.mjs";
6
+ import { l as isAutoManagedIMessageCliPath, n as IMESSAGE_UPDATE_COMMAND, t as IMESSAGE_INSTALL_COMMAND } from "./setup-core-B1_P_t4T.mjs";
7
+ import { filterStringEntries, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
7
8
  import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
8
9
  import path from "node:path";
9
10
  import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
10
11
  import { createActionGate, jsonResult, readNonNegativeIntegerParam, readPositiveIntegerParam, readReactionParams, readStringArrayParam, readStringParam } from "openclaw/plugin-sdk/channel-actions";
11
12
  import { canonicalizeBase64 } from "openclaw/plugin-sdk/media-runtime";
12
13
  import { normalizePollInput } from "openclaw/plugin-sdk/poll-runtime";
13
- import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
14
+ import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
14
15
  import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
15
- import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
16
+ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
17
+ import { createHash } from "node:crypto";
16
18
  import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
17
19
  import { captureRuntimeConfigAsyncReader } from "openclaw/plugin-sdk/runtime-config-snapshot";
18
20
  import { detectBinary } from "openclaw/plugin-sdk/setup";
19
21
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
20
- //#region extensions/imessage/src/message-action-reference.ts
22
+ // extensions/imessage/src/message-action-reference.ts
21
23
  async function resolveAuthorizedIMessageActionReference(params) {
22
24
  const options = {
23
- requireKnownShortId: true,
24
25
  chatContext: params.inputChatContext,
25
26
  ...params.requireFromMe ? { requireFromMe: true } : {}
26
27
  };
@@ -34,18 +35,14 @@ async function resolveAuthorizedIMessageActionReference(params) {
34
35
  await authorize(messageId, params.inputChatContext);
35
36
  const chatGuid = await params.resolveChatGuid();
36
37
  const chatContext = { chatGuid };
37
- const resolvedMessageId = await params.resolveMessageId(messageId, {
38
- requireKnownShortId: true,
39
- chatContext
40
- });
38
+ const resolvedMessageId = await params.resolveMessageId(messageId, { chatContext });
41
39
  await authorize(resolvedMessageId, chatContext);
42
40
  return {
43
41
  messageId: resolvedMessageId,
44
42
  chatGuid
45
43
  };
46
44
  }
47
- //#endregion
48
- //#region extensions/imessage/src/message-guid.ts
45
+ // extensions/imessage/src/message-guid.ts
49
46
  /** Strip the `p:<n>/` part prefix Messages puts on some GUIDs so keys match. */
50
47
  function normalizeIMessageGuid(value) {
51
48
  return value.trim().replace(/^p:\d+\//iu, "");
@@ -55,32 +52,312 @@ function normalizeIMessageMessageId(value) {
55
52
  const id = value?.trim();
56
53
  return id && id !== "ok" && id !== "unknown" ? id : void 0;
57
54
  }
58
- //#endregion
59
- //#region extensions/imessage/src/probe.ts
55
+ // extensions/imessage/src/persistence-failure.ts
56
+ function createPersistenceFailureReporter(cache) {
57
+ let reported = false;
58
+ return (scope, err) => {
59
+ if (reported) return;
60
+ reported = true;
61
+ logVerbose(`imessage ${cache}: ${scope} disabled after first failure: ${String(err)}`);
62
+ };
63
+ }
64
+ // extensions/imessage/src/runtime.ts
65
+ const { getRuntime: getIMessageRuntime, setRuntime: setIMessageRuntime, tryGetRuntime: getOptionalIMessageRuntime } = createPluginRuntimeStore({
66
+ pluginId: "imessage",
67
+ errorMessage: "iMessage runtime not initialized"
68
+ });
69
+ // extensions/imessage/src/state-contract.ts
70
+ const IMESSAGE_REPLY_CACHE_NAMESPACE = "imessage.reply-cache";
71
+ const IMESSAGE_REPLY_CACHE_MAX_ENTRIES = 2e3;
72
+ const IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE = "imessage.reply-cache-counter";
73
+ const IMESSAGE_REPLY_CACHE_COUNTER_KEY = "short-id-counter";
74
+ const IMESSAGE_REPLY_CACHE_TTL_MS = 216e5;
75
+ function resolveIMessageReplyCacheEntryKey(messageId) {
76
+ return createHash("sha256").update(messageId, "utf8").digest("hex").slice(0, 32);
77
+ }
78
+ const MAX_FAILURE_RETRY_MAP_SIZE = 512;
79
+ const textEncoder = new TextEncoder();
80
+ const IMESSAGE_CATCHUP_CURSOR_NAMESPACE = "imessage.catchup-cursors";
81
+ function resolveIMessageCatchupCursorKey(accountId) {
82
+ return createHash("sha256").update(accountId, "utf8").digest("hex").slice(0, 32);
83
+ }
84
+ /**
85
+ * Bound the retry map so a pathological storm of unique failing GUIDs
86
+ * cannot grow the cursor value without limit. Keeps the `maxSize` entries
87
+ * with the highest counts (closest to give-up) when over the bound.
88
+ */
89
+ function capFailureRetriesMap(map, maxSize = MAX_FAILURE_RETRY_MAP_SIZE) {
90
+ const maxBytes = 48e3;
91
+ const entries = Object.entries(map);
92
+ if (entries.length <= maxSize && textEncoder.encode(JSON.stringify(map)).byteLength <= maxBytes) return map;
93
+ entries.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
94
+ const capped = {};
95
+ for (const [guid, count] of entries.slice(0, maxSize)) {
96
+ capped[guid] = count;
97
+ if (textEncoder.encode(JSON.stringify(capped)).byteLength > maxBytes) {
98
+ delete capped[guid];
99
+ break;
100
+ }
101
+ }
102
+ return capped;
103
+ }
104
+ const IMESSAGE_SENT_ECHOES_TTL_MS = 432e5;
105
+ const IMESSAGE_SENT_ECHOES_NAMESPACE = "imessage.sent-echoes";
106
+ function resolveIMessageSentEchoEntryKey(entry) {
107
+ return createHash("sha256").update(JSON.stringify([
108
+ entry.scope,
109
+ entry.text ?? "",
110
+ resolveIMessageEchoMediaKey(entry.media) ?? "",
111
+ entry.messageId ?? "",
112
+ entry.timestamp
113
+ ])).digest("hex").slice(0, 32);
114
+ }
115
+ function resolveIMessageEchoMediaKey(media) {
116
+ const contentType = media?.contentType?.trim().toLowerCase() || void 0;
117
+ const kind = media?.kind && media.kind !== "unknown" ? media.kind : void 0;
118
+ if (kind) return `kind:${kind}`;
119
+ const normalizedContentType = contentType?.split(";", 1)[0]?.trim();
120
+ return normalizedContentType ? `mime:${normalizedContentType}` : void 0;
121
+ }
122
+ // extensions/imessage/src/monitor-reply-cache.ts
123
+ /** Recency window for the "react to the latest message" fallback. */
124
+ const LATEST_FALLBACK_MS = 6e5;
125
+ const reportPersistenceFailure = createPersistenceFailureReporter("reply-cache");
126
+ const imessageReplyCacheByMessageId = /* @__PURE__ */ new Map();
127
+ const imessageShortIdToUuid = /* @__PURE__ */ new Map();
128
+ let imessageShortIdCounter = 0;
129
+ function openReplyCacheStore() {
130
+ return getIMessageRuntime().state.openKeyedStoreV2({
131
+ namespace: IMESSAGE_REPLY_CACHE_NAMESPACE,
132
+ maxEntries: IMESSAGE_REPLY_CACHE_MAX_ENTRIES
133
+ });
134
+ }
135
+ function openReplyCacheCounterStore() {
136
+ return getIMessageRuntime().state.openKeyedStoreV2({
137
+ namespace: IMESSAGE_REPLY_CACHE_COUNTER_NAMESPACE,
138
+ maxEntries: 1
139
+ });
140
+ }
141
+ function remainingTtlMs(timestamp) {
142
+ const remaining = IMESSAGE_REPLY_CACHE_TTL_MS - Math.max(0, Date.now() - timestamp);
143
+ return remaining > 0 ? remaining : void 0;
144
+ }
145
+ let hydrated = false;
146
+ let hydration;
147
+ let persistence = Promise.resolve();
148
+ function hydrateCounter(counter) {
149
+ if (counter && Number.isSafeInteger(counter.counter) && counter.counter > 0) imessageShortIdCounter = Math.max(imessageShortIdCounter, counter.counter);
150
+ }
151
+ function hydrateRows(entries) {
152
+ const cutoff = Date.now() - IMESSAGE_REPLY_CACHE_TTL_MS;
153
+ for (const entry of entries.filter((cached) => cached.timestamp >= cutoff).toSorted((a, b) => a.timestamp - b.timestamp).slice(-2e3)) {
154
+ const numeric = Number.parseInt(entry.shortId, 10);
155
+ if (Number.isFinite(numeric) && numeric > imessageShortIdCounter) imessageShortIdCounter = numeric;
156
+ imessageReplyCacheByMessageId.set(entry.messageId, entry);
157
+ imessageShortIdToUuid.set(entry.shortId, entry.messageId);
158
+ }
159
+ }
160
+ async function hydrateFromStoreOnce() {
161
+ if (hydrated) return;
162
+ hydration ??= (async () => {
163
+ try {
164
+ hydrateCounter(await openReplyCacheCounterStore().lookup(IMESSAGE_REPLY_CACHE_COUNTER_KEY));
165
+ hydrateRows((await openReplyCacheStore().entries()).map(({ value }) => value));
166
+ } catch (err) {
167
+ reportPersistenceFailure("read", err);
168
+ } finally {
169
+ hydrated = true;
170
+ }
171
+ })();
172
+ await hydration;
173
+ }
174
+ async function persistReplyCacheEntry(entry) {
175
+ const ttlMs = remainingTtlMs(entry.timestamp);
176
+ if (!ttlMs) return;
177
+ try {
178
+ await openReplyCacheStore().register(resolveIMessageReplyCacheEntryKey(entry.messageId), entry, { ttlMs });
179
+ } catch (err) {
180
+ reportPersistenceFailure("write", err);
181
+ }
182
+ }
183
+ async function deleteReplyCacheEntry(messageId) {
184
+ try {
185
+ await openReplyCacheStore().delete(resolveIMessageReplyCacheEntryKey(messageId));
186
+ } catch (err) {
187
+ reportPersistenceFailure("delete", err);
188
+ }
189
+ }
190
+ async function persistReplyCacheCounter(counter) {
191
+ try {
192
+ await openReplyCacheCounterStore().register(IMESSAGE_REPLY_CACHE_COUNTER_KEY, { counter });
193
+ } catch (err) {
194
+ reportPersistenceFailure("counter", err);
195
+ }
196
+ }
197
+ function buildReplyCacheEntry(entry, messageId, shortId) {
198
+ return {
199
+ accountId: entry.accountId,
200
+ messageId,
201
+ shortId,
202
+ timestamp: entry.timestamp,
203
+ ...entry.chatGuid !== void 0 ? { chatGuid: entry.chatGuid } : {},
204
+ ...entry.chatIdentifier !== void 0 ? { chatIdentifier: entry.chatIdentifier } : {},
205
+ ...entry.chatId !== void 0 ? { chatId: entry.chatId } : {},
206
+ ...entry.isFromMe !== void 0 ? { isFromMe: entry.isFromMe } : {}
207
+ };
208
+ }
209
+ async function rememberIMessageReplyCache(entry) {
210
+ await hydrateFromStoreOnce();
211
+ const messageId = entry.messageId.trim();
212
+ if (!messageId) return {
213
+ ...entry,
214
+ shortId: ""
215
+ };
216
+ let shortId = imessageReplyCacheByMessageId.get(messageId)?.shortId;
217
+ const isNewMessage = !shortId;
218
+ if (!shortId) {
219
+ shortId = String(++imessageShortIdCounter);
220
+ imessageShortIdToUuid.set(shortId, messageId);
221
+ }
222
+ const fullEntry = buildReplyCacheEntry(entry, messageId, shortId);
223
+ imessageReplyCacheByMessageId.delete(messageId);
224
+ imessageReplyCacheByMessageId.set(messageId, fullEntry);
225
+ const cutoff = Date.now() - IMESSAGE_REPLY_CACHE_TTL_MS;
226
+ const deletedMessageIds = [];
227
+ const pruneUntil = (retain) => {
228
+ for (const [key, cached] of imessageReplyCacheByMessageId) {
229
+ if (retain(key, cached)) break;
230
+ imessageReplyCacheByMessageId.delete(key);
231
+ deletedMessageIds.push(key);
232
+ if (cached.shortId) imessageShortIdToUuid.delete(cached.shortId);
233
+ }
234
+ };
235
+ pruneUntil((_key, cached) => cached.timestamp >= cutoff);
236
+ pruneUntil((key) => !key || imessageReplyCacheByMessageId.size <= 2e3);
237
+ const counter = imessageShortIdCounter;
238
+ persistence = persistence.then(async () => {
239
+ if (isNewMessage) await persistReplyCacheCounter(counter);
240
+ for (const messageIdToDelete of deletedMessageIds) await deleteReplyCacheEntry(messageIdToDelete);
241
+ await persistReplyCacheEntry(fullEntry);
242
+ });
243
+ await persistence;
244
+ return fullEntry;
245
+ }
246
+ function hasChatScope(ctx) {
247
+ if (!ctx) return false;
248
+ return Boolean(normalizeOptionalString(ctx.chatGuid) || normalizeOptionalString(ctx.chatIdentifier) || typeof ctx.chatId === "number");
249
+ }
250
+ function describeChatForError(values) {
251
+ const parts = [];
252
+ if (normalizeOptionalString(values.chatGuid)) parts.push("chatGuid=<redacted>");
253
+ if (normalizeOptionalString(values.chatIdentifier)) parts.push("chatIdentifier=<redacted>");
254
+ if (typeof values.chatId === "number") parts.push("chatId=<redacted>");
255
+ return parts.length === 0 ? "<unknown chat>" : parts.join(", ");
256
+ }
257
+ function describeMessageIdForError(inputId, inputKind) {
258
+ if (inputKind === "short") return `<short:${inputId.length}-digit>`;
259
+ return `<uuid:${inputId.slice(0, 8)}...>`;
260
+ }
261
+ function buildCrossChatError(inputId, inputKind, cached, ctx) {
262
+ const remediation = inputKind === "short" ? "Use a message ID from the current chat target; MessageSidFull from another chat is rejected." : "Retry with the correct chat target.";
263
+ return /* @__PURE__ */ new Error(`iMessage message id ${describeMessageIdForError(inputId, inputKind)} belongs to a different chat (${describeChatForError(cached)}) than the current call target (${describeChatForError(ctx)}). ${remediation}`);
264
+ }
265
+ async function resolveIMessageMessageId(shortOrUuid, opts) {
266
+ const trimmed = shortOrUuid.trim();
267
+ if (!trimmed) return trimmed;
268
+ await hydrateFromStoreOnce();
269
+ const inputKind = /^\d+$/.test(trimmed) ? "short" : "uuid";
270
+ const messageId = inputKind === "short" ? imessageShortIdToUuid.get(trimmed) : trimmed;
271
+ if (!messageId) {
272
+ if (!hasChatScope(opts?.chatContext)) throw new Error(`iMessage short message id ${describeMessageIdForError(trimmed, "short")} requires a chat scope (chatGuid / chatIdentifier / chatId or a target).`);
273
+ throw new Error(`iMessage short message id ${describeMessageIdForError(trimmed, "short")} is no longer available. Use MessageSidFull.`);
274
+ }
275
+ const cached = imessageReplyCacheByMessageId.get(messageId);
276
+ if (cached && opts?.chatContext && (inputKind === "uuid" || hasChatScope(opts.chatContext)) && resolveIMessageChatMatch(cached, opts.chatContext) === "mismatch") throw buildCrossChatError(trimmed, inputKind, cached, opts.chatContext);
277
+ if (opts?.requireFromMe && cached?.isFromMe !== true) throw buildFromMeError(trimmed, inputKind);
278
+ return messageId;
279
+ }
280
+ async function isKnownFromMeIMessageMessageId(messageId, ctx) {
281
+ const trimmed = normalizeOptionalString(messageId);
282
+ if (!trimmed || !ctx.accountId || !hasChatScope(ctx)) return false;
283
+ await hydrateFromStoreOnce();
284
+ const cached = imessageReplyCacheByMessageId.get(trimmed);
285
+ if (!cached || cached.isFromMe !== true) return false;
286
+ return resolveCachedResourceBinding(trimmed, {
287
+ ...ctx,
288
+ accountId: ctx.accountId
289
+ }) === "match";
290
+ }
291
+ async function isKnownFromMeIMessageTarget(params) {
292
+ const { accountId, chatId, chatGuid, chatIdentifier } = params;
293
+ const ctx = {
294
+ accountId,
295
+ chatId,
296
+ chatGuid,
297
+ chatIdentifier
298
+ };
299
+ for (const messageId of params.messageIds) if (await isKnownFromMeIMessageMessageId(messageId, ctx)) return true;
300
+ return false;
301
+ }
302
+ function buildFromMeError(inputId, inputKind) {
303
+ return /* @__PURE__ */ new Error(`iMessage message id ${describeMessageIdForError(inputId, inputKind)} is not one this agent sent. edit and unsend can only target messages the gateway delivered itself; messages received from other participants cannot be modified.`);
304
+ }
305
+ /** Latest recent entry with a positive same-account conversation match; never guess a chat. */
306
+ function findLatestIMessageEntryForChat(ctx) {
307
+ if (!hasChatScope(ctx) || !ctx.accountId) return;
308
+ const cutoff = Date.now() - LATEST_FALLBACK_MS;
309
+ let best;
310
+ for (const entry of imessageReplyCacheByMessageId.values()) {
311
+ if (entry.accountId !== ctx.accountId) continue;
312
+ if (entry.timestamp < cutoff) continue;
313
+ if (resolveIMessageChatMatch(entry, ctx) !== "match") continue;
314
+ if (!best || entry.timestamp > best.timestamp) best = entry;
315
+ }
316
+ return best;
317
+ }
318
+ async function resolveIMessageCachedResourceBinding(messageId, ctx) {
319
+ await hydrateFromStoreOnce();
320
+ return resolveCachedResourceBinding(messageId, ctx);
321
+ }
322
+ function resolveCachedResourceBinding(messageId, ctx) {
323
+ const entry = imessageReplyCacheByMessageId.get(messageId.trim());
324
+ if (!entry) return "unknown";
325
+ if (Date.now() - entry.timestamp > 216e5) return "unknown";
326
+ if (entry.accountId !== ctx.accountId) return "mismatch";
327
+ return resolveIMessageChatMatch(entry, ctx);
328
+ }
329
+ async function isIMessageCurrentMessageInChatAsync(params) {
330
+ await hydrateFromStoreOnce();
331
+ return isCurrentMessageInChat(params);
332
+ }
333
+ function isCurrentMessageInChat(params) {
334
+ if (!params.accountId || !hasChatScope(params.chatContext)) return false;
335
+ const currentMessageId = normalizeOptionalString(String(params.currentMessageId));
336
+ if (!currentMessageId) return false;
337
+ const fullMessageId = /^\d+$/.test(currentMessageId) ? imessageShortIdToUuid.get(currentMessageId) : currentMessageId;
338
+ if (!fullMessageId) return false;
339
+ return resolveCachedResourceBinding(fullMessageId, {
340
+ ...params.chatContext,
341
+ accountId: params.accountId
342
+ }) === "match";
343
+ }
344
+ // extensions/imessage/src/probe.ts
60
345
  const RPC_SUPPORT_CACHE_TTL_MS = 3e5;
61
346
  const PRIVATE_API_NEGATIVE_TTL_MS = 1e4;
62
347
  const rpcSupportCache = /* @__PURE__ */ new Map();
63
348
  function cacheIMessagePrivateApiStatus(cliPath, status) {
64
- if (status.available) {
65
- setCachedIMessagePrivateApiStatus(cliPath, status, 0);
66
- return;
67
- }
68
- const expiresAt = resolveExpiresAtMsFromDurationMs(PRIVATE_API_NEGATIVE_TTL_MS);
69
- if (expiresAt !== void 0) setCachedIMessagePrivateApiStatus(cliPath, status, expiresAt);
349
+ setCachedIMessagePrivateApiStatus(cliPath, status, status.available ? 0 : Date.now() + PRIVATE_API_NEGATIVE_TTL_MS);
70
350
  }
71
351
  function setCachedRpcSupport(cliPath, result) {
72
- const expiresAt = resolveExpiresAtMsFromDurationMs(RPC_SUPPORT_CACHE_TTL_MS);
73
- if (expiresAt === void 0) return;
74
352
  rpcSupportCache.set(cliPath, {
75
353
  result,
76
- expiresAt
354
+ expiresAt: Date.now() + RPC_SUPPORT_CACHE_TTL_MS
77
355
  });
78
356
  }
79
357
  async function probeRpcSupport(cliPath, timeoutMs) {
80
358
  const cached = rpcSupportCache.get(cliPath);
81
359
  if (cached) {
82
- const now = asDateTimestampMs(Date.now());
83
- if (now !== void 0 && cached.expiresAt > now) return cached.result;
360
+ if (cached.expiresAt > Date.now()) return cached.result;
84
361
  rpcSupportCache.delete(cliPath);
85
362
  }
86
363
  try {
@@ -136,6 +413,21 @@ async function probeIMessagePrivateApi(cliPath, timeoutMs, options = {}) {
136
413
  const cached = getCachedIMessagePrivateApiStatus(key);
137
414
  if (cached) return cached;
138
415
  }
416
+ const unavailable = (error) => {
417
+ const status = {
418
+ available: false,
419
+ v2Ready: false,
420
+ selectors: {},
421
+ rpcMethods: [],
422
+ cliCapabilities: {
423
+ sendRichSupportsAttachment: false,
424
+ pollSendSupportsNoComment: false
425
+ },
426
+ error
427
+ };
428
+ cacheIMessagePrivateApiStatus(key, status);
429
+ return status;
430
+ };
139
431
  try {
140
432
  const result = await runCommandWithTimeout([
141
433
  expandIMessageUserPath(key),
@@ -144,21 +436,7 @@ async function probeIMessagePrivateApi(cliPath, timeoutMs, options = {}) {
144
436
  ], { timeoutMs });
145
437
  const combined = `${result.stdout}\n${result.stderr}`.trim();
146
438
  const normalized = normalizeLowercaseStringOrEmpty(combined);
147
- if (result.code !== 0 && normalized.includes("unknown subcommand") && normalized.includes("status")) {
148
- const status = {
149
- available: false,
150
- v2Ready: false,
151
- selectors: {},
152
- rpcMethods: [],
153
- cliCapabilities: {
154
- sendRichSupportsAttachment: false,
155
- pollSendSupportsNoComment: false
156
- },
157
- error: `imsg CLI does not support the "status" subcommand. Update imsg on the Messages Mac: ${IMESSAGE_UPDATE_COMMAND}`
158
- };
159
- cacheIMessagePrivateApiStatus(key, status);
160
- return status;
161
- }
439
+ if (result.code !== 0 && normalized.includes("unknown subcommand") && normalized.includes("status")) return unavailable(`imsg CLI does not support the "status" subcommand. Update imsg on the Messages Mac: ${IMESSAGE_UPDATE_COMMAND}`);
162
440
  const lines = normalizeStringEntries(result.stdout.split(/\r?\n/));
163
441
  let payload = null;
164
442
  for (const line of lines.toReversed()) try {
@@ -195,19 +473,7 @@ async function probeIMessagePrivateApi(cliPath, timeoutMs, options = {}) {
195
473
  cacheIMessagePrivateApiStatus(key, status);
196
474
  return status;
197
475
  } catch (err) {
198
- const status = {
199
- available: false,
200
- v2Ready: false,
201
- selectors: {},
202
- rpcMethods: [],
203
- cliCapabilities: {
204
- sendRichSupportsAttachment: false,
205
- pollSendSupportsNoComment: false
206
- },
207
- error: String(err)
208
- };
209
- cacheIMessagePrivateApiStatus(key, status);
210
- return status;
476
+ return unavailable(String(err));
211
477
  }
212
478
  }
213
479
  async function probeIMessage(timeoutMs, opts = {}) {
@@ -258,9 +524,8 @@ async function probeIMessage(timeoutMs, opts = {}) {
258
524
  await client.stop();
259
525
  }
260
526
  }
261
- //#endregion
262
- //#region extensions/imessage/src/actions.ts
263
- const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-DHiRiPHe.mjs"), "imessageActionsRuntime");
527
+ // extensions/imessage/src/actions.ts
528
+ const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-Ccg9CARL.mjs"), "imessageActionsRuntime");
264
529
  const log = createSubsystemLogger("channels/imessage");
265
530
  const providerId = "imessage";
266
531
  const SUPPORTED_ACTIONS = /* @__PURE__ */ new Set([...IMESSAGE_ACTION_NAMES, "upload-file"]);
@@ -332,32 +597,9 @@ function readMessageIdWithChatFallback(params, chatContext) {
332
597
  if (latest?.messageId) return latest.messageId;
333
598
  return readStringParam(params, "messageId", { required: true });
334
599
  }
335
- async function resolveChatGuid(params) {
336
- const target = resolveIMessageActionTarget(params);
337
- if (!target) throw new Error(`iMessage ${params.action} requires chatGuid, chatId, chatIdentifier, or a chat target.`);
338
- if (target.kind === "chat_guid") return target.chatGuid;
339
- const synthesizedIdentifier = target.kind === "handle" ? `${target.service === "sms" ? "SMS" : "iMessage"};-;${target.to}` : "";
340
- const lookupTarget = target.kind === "handle" ? {
341
- kind: "chat_identifier",
342
- chatIdentifier: synthesizedIdentifier
343
- } : target;
344
- const resolved = await params.runtime.resolveChatGuidForTarget({
345
- target: lookupTarget,
346
- options: params.options,
347
- conversationReadOrigin: params.conversationReadOrigin
348
- });
349
- if (resolved) return resolved;
350
- if (target.kind !== "handle") throw new Error(`iMessage ${params.action} failed: chatGuid not found for ${formatUnresolvedTarget(target)}.`);
351
- if (params.action === "react" || params.action === "edit" || params.action === "unsend") throw new Error(`iMessage ${params.action} requires a known chat. No registered chat for the supplied target; send a message first or pass an explicit chatGuid.`);
352
- return synthesizedIdentifier;
353
- }
354
600
  function formatUnresolvedTarget(target) {
355
601
  return target.kind === "chat_id" ? "chat_id:<redacted>" : "chat_identifier:<redacted>";
356
602
  }
357
- function buildChatContextFromActionParams(params) {
358
- const target = resolveIMessageActionTarget(params);
359
- return target ? chatContextFromIMessageTarget(target, params.service) : {};
360
- }
361
603
  function mapTapbackReaction(emoji) {
362
604
  const value = normalizeOptionalLowercaseString(emoji)?.replace(/\ufe0f/g, "");
363
605
  return value ? [
@@ -402,7 +644,7 @@ function decodeBase64Buffer(params, action) {
402
644
  if (!base64Buffer) throw new Error(`iMessage ${action} requires buffer (base64) parameter.`);
403
645
  const canonical = canonicalizeBase64(base64Buffer.replaceAll("-", "+").replaceAll("_", "/"));
404
646
  if (!canonical) throw new Error(`iMessage ${action} buffer must be valid base64.`);
405
- return Uint8Array.from(Buffer.from(canonical, "base64"));
647
+ return Buffer.from(canonical, "base64");
406
648
  }
407
649
  const REPLY_ATTACHMENT_PATH_PARAM_NAMES = [
408
650
  "filePath",
@@ -411,21 +653,6 @@ const REPLY_ATTACHMENT_PATH_PARAM_NAMES = [
411
653
  "mediaUrl",
412
654
  "fileUrl"
413
655
  ];
414
- function extractReplyAttachment(params) {
415
- if (readStringParam(params, "buffer")) {
416
- const filename = readStringParam(params, "filename") ?? "attachment.bin";
417
- return { spec: {
418
- kind: "buffer",
419
- buffer: decodeBase64Buffer(params, "reply attachment"),
420
- filename
421
- } };
422
- }
423
- for (const name of REPLY_ATTACHMENT_PATH_PARAM_NAMES) if (readStringParam(params, name)) return {
424
- spec: null,
425
- bypassParam: name
426
- };
427
- return null;
428
- }
429
656
  const EFFECT_ALIASES = {
430
657
  slam: "com.apple.MobileSMS.expressivesend.impact",
431
658
  impact: "com.apple.MobileSMS.expressivesend.impact",
@@ -512,20 +739,35 @@ const imessageMessageActions = {
512
739
  timeoutMs: account.config.probeTimeoutMs
513
740
  };
514
741
  const attestedConversationReadOrigin = conversationReadOrigin ?? "delegated";
515
- const chatGuid = async () => await resolveChatGuid({
516
- action,
517
- actionParams: params,
518
- currentChannelId: toolContext?.currentChannelId,
519
- conversationReadOrigin: attestedConversationReadOrigin,
520
- runtime,
521
- options: opts
522
- });
742
+ const chatGuid = async () => {
743
+ const target = resolveIMessageActionTarget({
744
+ actionParams: params,
745
+ currentChannelId: toolContext?.currentChannelId
746
+ });
747
+ if (!target) throw new Error(`iMessage ${action} requires chatGuid, chatId, chatIdentifier, or a chat target.`);
748
+ if (target.kind === "chat_guid") return target.chatGuid;
749
+ const synthesizedIdentifier = target.kind === "handle" ? `${target.service === "sms" ? "SMS" : "iMessage"};-;${target.to}` : "";
750
+ const lookupTarget = target.kind === "handle" ? {
751
+ kind: "chat_identifier",
752
+ chatIdentifier: synthesizedIdentifier
753
+ } : target;
754
+ const resolved = await runtime.resolveChatGuidForTarget({
755
+ target: lookupTarget,
756
+ options: opts,
757
+ conversationReadOrigin: attestedConversationReadOrigin
758
+ });
759
+ if (resolved) return resolved;
760
+ if (target.kind !== "handle") throw new Error(`iMessage ${action} failed: chatGuid not found for ${formatUnresolvedTarget(target)}.`);
761
+ if (action === "react" || action === "edit" || action === "unsend") throw new Error(`iMessage ${action} requires a known chat. No registered chat for the supplied target; send a message first or pass an explicit chatGuid.`);
762
+ return synthesizedIdentifier;
763
+ };
523
764
  const messageReference = async (input) => {
524
- const inputChatContext = buildChatContextFromActionParams({
765
+ const service = account.config.service;
766
+ const target = resolveIMessageActionTarget({
525
767
  actionParams: params,
526
- currentChannelId: toolContext?.currentChannelId,
527
- service: account.config.service
768
+ currentChannelId: toolContext?.currentChannelId
528
769
  });
770
+ const inputChatContext = target ? chatContextFromIMessageTarget(target, service) : {};
529
771
  return await resolveAuthorizedIMessageActionReference({
530
772
  messageId: input?.messageId,
531
773
  inputChatContext,
@@ -583,7 +825,7 @@ const imessageMessageActions = {
583
825
  if (!remove && (isEmpty || !reaction)) throw new Error("iMessage react supports love, like, dislike, laugh, emphasize, and question tapbacks.");
584
826
  const partIndex = readNonNegativeIntegerParam(params, "partIndex");
585
827
  const reference = await messageReference();
586
- const reactionsToSend = remove && !reaction ? [...TAPBACK_KINDS] : reaction ? [reaction] : [];
828
+ const reactionsToSend = remove && !reaction ? TAPBACK_KINDS : reaction ? [reaction] : [];
587
829
  for (const kind of reactionsToSend) await runtime.sendReaction({
588
830
  chatGuid: reference.chatGuid,
589
831
  messageId: reference.messageId,
@@ -634,9 +876,16 @@ const imessageMessageActions = {
634
876
  const text = readMessageText(params);
635
877
  if (!text) throw new Error("iMessage reply requires text or message.");
636
878
  const reference = await messageReference();
637
- const attachment = extractReplyAttachment(params);
879
+ let attachment;
880
+ if (readStringParam(params, "buffer")) {
881
+ const filename = readStringParam(params, "filename") ?? "attachment.bin";
882
+ attachment = {
883
+ kind: "buffer",
884
+ buffer: decodeBase64Buffer(params, "reply attachment"),
885
+ filename
886
+ };
887
+ } else for (const name of REPLY_ATTACHMENT_PATH_PARAM_NAMES) if (readStringParam(params, name)) throw new Error(`iMessage reply rejected \`${name}\` because it did not pass through the outbound media resolver. Pass a base64 \`buffer\` + \`filename\` directly, or invoke message(action: "reply") through the runner so the resolver can validate the path against mediaLocalRoots/sandbox/size before sending.`);
638
888
  if (attachment) {
639
- if (attachment.spec === null) throw new Error(`iMessage reply rejected \`${attachment.bypassParam}\` because it did not pass through the outbound media resolver. Pass a base64 \`buffer\` + \`filename\` directly, or invoke message(action: "reply") through the runner so the resolver can validate the path against mediaLocalRoots/sandbox/size before sending.`);
640
889
  if (!opts.remoteHost && privateApiStatus?.cliCapabilities?.sendRichSupportsAttachment !== true) throw new Error("iMessage reply with an attachment needs an imsg build that exposes `send-rich --file` (openclaw/imsg#114). Upgrade imsg, or use action 'upload-file' (with filePath/filename) or action 'send' (with media) to deliver the file plus a separate 'reply' for any text.");
641
890
  }
642
891
  const partIndex = readNonNegativeIntegerParam(params, "partIndex");
@@ -645,7 +894,7 @@ const imessageMessageActions = {
645
894
  text,
646
895
  replyToMessageId: reference.messageId,
647
896
  partIndex,
648
- attachment: attachment?.spec ?? void 0,
897
+ attachment,
649
898
  options: opts
650
899
  }), reference.chatGuid, { repliedTo: reference.messageId });
651
900
  }
@@ -776,5 +1025,4 @@ const imessageMessageActions = {
776
1025
  throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
777
1026
  }
778
1027
  };
779
- //#endregion
780
- export { normalizeIMessageMessageId as a, normalizeIMessageGuid as i, probeIMessage as n, probeIMessagePrivateApi as r, imessageMessageActions as t };
1028
+ export { setIMessageRuntime as _, rememberIMessageReplyCache as a, normalizeIMessageMessageId as b, IMESSAGE_CATCHUP_CURSOR_NAMESPACE as c, capFailureRetriesMap as d, resolveIMessageCatchupCursorKey as f, getOptionalIMessageRuntime as g, getIMessageRuntime as h, isKnownFromMeIMessageTarget as i, IMESSAGE_SENT_ECHOES_NAMESPACE as l, resolveIMessageSentEchoEntryKey as m, probeIMessage as n, resolveIMessageCachedResourceBinding as o, resolveIMessageEchoMediaKey as p, probeIMessagePrivateApi as r, resolveIMessageMessageId as s, imessageMessageActions as t, IMESSAGE_SENT_ECHOES_TTL_MS as u, createPersistenceFailureReporter as v, normalizeIMessageGuid as y };