@openclaw/imessage 2026.9.6 → 2026.9.7

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 (81) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{accounts-CUxZrTcY.mjs → accounts-nzcU0cq2.mjs} +3 -6
  3. package/dist/.setup/{actions.runtime-D0zG_96v.mjs → actions.runtime-DdBN29zj.mjs} +3 -5
  4. package/dist/.setup/{api-RZv6yXul.mjs → api-B9Qx21G-.mjs} +6 -5
  5. package/dist/.setup/{api-VLVcFh7r.mjs → api-D2S6FhGw.mjs} +7 -7
  6. package/dist/.setup/{approval-handler.runtime-Bv5_XgNr.mjs → approval-handler.runtime-DKSq0DWq.mjs} +8 -8
  7. package/dist/.setup/{approval-reactions-D6RFg6lU.mjs → approval-reactions-Bp33xc83.mjs} +5 -5
  8. package/dist/.setup/{channel-BLTaKdSK.mjs → channel-9fyvuN_p.mjs} +97 -152
  9. package/dist/.setup/channel.runtime-n-MPKL8k.mjs +92 -0
  10. package/dist/.setup/{config-schema-CCbTcJEV.mjs → config-schema-4Q3_EqYt.mjs} +9 -1
  11. package/dist/.setup/{group-policy-Cjztkquv.mjs → group-policy-90pw4tyG.mjs} +48 -334
  12. package/dist/.setup/{media-contract-DKJK7rh3.mjs → media-contract-CagwSMvo.mjs} +1 -1
  13. package/dist/.setup/{message-tool-api-pvlcOJPG.mjs → message-tool-api-D032l82H.mjs} +3 -18
  14. package/dist/.setup/{monitor-BJ3Ozi6I.mjs → monitor-fv9nRuTH.mjs} +211 -280
  15. package/dist/.setup/{question-reactions-lm8OxWbb.mjs → question-reactions-Cy-dmU_j.mjs} +1 -1
  16. package/dist/.setup/{remote-file-Bye99O-C.mjs → remote-file-DRPCaVmg.mjs} +70 -21
  17. package/dist/.setup/rolldown-runtime-BBjsoOtd.mjs +27 -0
  18. package/dist/.setup/{sanitize-outbound-sJPF2DVM.mjs → sanitize-outbound-3MLljgtY.mjs} +86 -24
  19. package/dist/.setup/{send-odAfTQ2J.mjs → send-Cu9nl757.mjs} +28 -112
  20. package/dist/.setup/setup-core-8MDdYHj5.mjs +226 -0
  21. package/dist/.setup/{channel.runtime---s2k4YN.mjs → setup-surface-tGXFDdWh.mjs} +6 -103
  22. package/dist/.setup/state-migrations-B-Q7bO0Y.mjs +47 -0
  23. package/dist/.setup/{targets-Cc9vthzI.mjs → targets-BicBiYsM.mjs} +10 -16
  24. package/dist/api.js +7 -7
  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/doctor-contract-api.js +168 -7
  29. package/dist/media-contract-api.js +1 -1
  30. package/dist/message-tool-api.js +1 -1
  31. package/dist/runtime-api.js +6 -6
  32. package/dist/setup-entry.js +1 -1
  33. package/dist/src/chat-db.worker.js +6 -1
  34. package/node_modules/typebox/build/compile/code.mjs +1 -2
  35. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  36. package/node_modules/typebox/build/format/iri.mjs +16 -9
  37. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  38. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  39. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  40. package/node_modules/typebox/build/guard/index.mjs +6 -0
  41. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  42. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  43. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  44. package/node_modules/typebox/build/schema/build.mjs +2 -3
  45. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  46. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  47. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  48. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  49. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  50. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  51. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  52. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  53. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  54. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  55. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  56. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  57. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  58. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  59. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  60. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  61. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  62. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  63. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  64. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  65. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  66. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  67. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  68. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  69. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  70. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  71. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  72. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  73. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  74. package/node_modules/typebox/package.json +1 -1
  75. package/node_modules/typebox/readme.md +3 -1
  76. package/openclaw.plugin.json +14 -0
  77. package/package.json +5 -5
  78. package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
  79. package/dist/.setup/state-contract-DvahEY4X.mjs +0 -56
  80. package/dist/.setup/state-migrations-DIDzI99d.mjs +0 -277
  81. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -1,7 +1,8 @@
1
- import { c as parseIMessageTarget, o as normalizeIMessageHandle } from "./targets-Cc9vthzI.mjs";
2
- import { a as resolveDefaultIMessageAccountId, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-CUxZrTcY.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-pvlcOJPG.mjs";
4
- import { _ as chatContextFromIMessageTarget, c as findLatestIMessageEntryForChat, f as rememberIMessageReplyCache, l as isIMessageCurrentMessageInChat, o as createIMessageRpcClient, u as isIMessageCurrentMessageInChatAsync } from "./sanitize-outbound-sJPF2DVM.mjs";
1
+ import { c as parseIMessageTarget, o as normalizeIMessageHandle } from "./targets-BicBiYsM.mjs";
2
+ import { l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-nzcU0cq2.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-D032l82H.mjs";
4
+ import { c as findLatestIMessageEntryForChat, f as rememberIMessageReplyCache, l as isIMessageCurrentMessageInChat, o as createIMessageRpcClient, u as isIMessageCurrentMessageInChatAsync, w as chatContextFromIMessageTarget } from "./sanitize-outbound-3MLljgtY.mjs";
5
+ import { l as isAutoManagedIMessageCliPath, n as IMESSAGE_UPDATE_COMMAND, t as IMESSAGE_INSTALL_COMMAND } from "./setup-core-8MDdYHj5.mjs";
5
6
  import { filterStringEntries, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
6
7
  import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
7
8
  import path from "node:path";
@@ -16,11 +17,6 @@ import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
16
17
  import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
17
18
  import { detectBinary } from "openclaw/plugin-sdk/setup";
18
19
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
19
- import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
20
- import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
21
- import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
22
- import { createCliPathTextInput, createDelegatedSetupWizardProxy, createDelegatedTextInputShouldPrompt, createPatchedAccountSetupAdapter, createSetupTranslator, promptParsedAllowFromForAccount, setAccountAllowFromForChannel, setSetupChannelEnabled as setSetupChannelEnabled$1 } from "openclaw/plugin-sdk/setup-runtime";
23
- import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
24
20
  import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
25
21
  import { buildChannelGroupsScopeTree, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
26
22
  //#region extensions/imessage/src/message-action-reference.ts
@@ -51,230 +47,6 @@ async function resolveAuthorizedIMessageActionReference(params) {
51
47
  };
52
48
  }
53
49
  //#endregion
54
- //#region extensions/imessage/src/setup-core.ts
55
- const t = createSetupTranslator();
56
- const channel = "imessage";
57
- const IMESSAGE_INSTALL_COMMAND = "brew install steipete/tap/imsg";
58
- const IMESSAGE_UPDATE_COMMAND = "brew update && brew upgrade imsg";
59
- const HOMEBREW_IMSG_PATHS = /* @__PURE__ */ new Set([
60
- "/opt/homebrew/bin/imsg",
61
- "/opt/homebrew/opt/imsg/bin/imsg",
62
- "/usr/local/bin/imsg",
63
- "/usr/local/opt/imsg/bin/imsg"
64
- ]);
65
- function normalizeIMessageCliPathForSetup(cliPath) {
66
- return cliPath?.trim() || "imsg";
67
- }
68
- function isAutoManagedIMessageCliPath(cliPath, opts) {
69
- const normalized = normalizeIMessageCliPathForSetup(cliPath);
70
- return !opts?.explicit && normalized === "imsg" || HOMEBREW_IMSG_PATHS.has(normalized);
71
- }
72
- const CHAT_TARGET_ALLOWFROM_PREFIXES = [
73
- "chat_id:",
74
- "chatid:",
75
- "chat:",
76
- "chat_guid:",
77
- "chatguid:",
78
- "guid:",
79
- "chat_identifier:",
80
- "chatidentifier:",
81
- "chatident:"
82
- ];
83
- const SERVICE_ALLOWFROM_PREFIXES = [
84
- "imessage:",
85
- "sms:",
86
- "auto:"
87
- ];
88
- function normalizeAllowFromEntryForPrefixCheck(entry) {
89
- let lower = normalizeLowercaseStringOrEmpty(entry);
90
- let stripped = true;
91
- while (stripped) {
92
- stripped = false;
93
- for (const prefix of SERVICE_ALLOWFROM_PREFIXES) if (lower.startsWith(prefix)) {
94
- lower = lower.slice(prefix.length).trim();
95
- stripped = true;
96
- }
97
- }
98
- return lower;
99
- }
100
- function parseIMessageAllowFromEntries(raw) {
101
- return parseAllowFromEntries(raw, (entry) => {
102
- const lower = normalizeAllowFromEntryForPrefixCheck(entry);
103
- if (CHAT_TARGET_ALLOWFROM_PREFIXES.some((prefix) => lower.startsWith(prefix))) return { error: `iMessage allowFrom entries must be sender handles: ${entry}` };
104
- if (!normalizeIMessageHandle(entry)) return { error: `Invalid handle: ${entry}` };
105
- return { value: entry };
106
- });
107
- }
108
- function buildIMessageSetupPatch(input) {
109
- return {
110
- ...input.cliPath ? { cliPath: input.cliPath } : {},
111
- ...input.dbPath ? { dbPath: input.dbPath } : {},
112
- ...input.service ? { service: input.service } : {},
113
- ...input.region ? { region: input.region } : {}
114
- };
115
- }
116
- async function promptIMessageAllowFrom(params) {
117
- return promptParsedAllowFromForAccount({
118
- cfg: params.cfg,
119
- accountId: params.accountId,
120
- defaultAccountId: resolveDefaultIMessageAccountId(params.cfg),
121
- prompter: params.prompter,
122
- noteTitle: "iMessage allowlist",
123
- noteLines: [
124
- "Allowlist iMessage DMs by sender handle.",
125
- "Examples:",
126
- "- +15555550123",
127
- "- user@example.com",
128
- "Multiple entries: comma-separated.",
129
- `Docs: ${formatDocsLink("/imessage", "imessage")}`
130
- ],
131
- message: "iMessage allowFrom (sender handle)",
132
- placeholder: "+15555550123, user@example.com",
133
- parseEntries: parseIMessageAllowFromEntries,
134
- getExistingAllowFrom: ({ cfg, accountId }) => resolveIMessageAccount({
135
- cfg,
136
- accountId
137
- }).config.allowFrom ?? [],
138
- applyAllowFrom: ({ cfg, accountId, allowFrom }) => setAccountAllowFromForChannel({
139
- cfg,
140
- channel,
141
- accountId,
142
- allowFrom,
143
- setupSurface: imessageSetupAdapter
144
- })
145
- });
146
- }
147
- const imessageDmPolicy = createChannelDmPolicy({
148
- label: "iMessage",
149
- channel,
150
- resolveAccount: (cfg, accountId) => resolveIMessageAccount({
151
- cfg,
152
- accountId: accountId ?? resolveDefaultIMessageAccountId(cfg)
153
- }),
154
- setupSurface: () => imessageSetupAdapter,
155
- promptAllowFrom: promptIMessageAllowFrom
156
- });
157
- function resolveIMessageCliPath(params) {
158
- return resolveIMessageAccount(params).config.cliPath ?? "imsg";
159
- }
160
- function createIMessageCliPathTextInput(shouldPrompt) {
161
- return createCliPathTextInput({
162
- inputKey: "cliPath",
163
- message: "imsg CLI path",
164
- resolvePath: ({ cfg, accountId }) => resolveIMessageCliPath({
165
- cfg,
166
- accountId
167
- }),
168
- shouldPrompt,
169
- helpTitle: "iMessage",
170
- helpLines: [
171
- "imsg CLI path required to enable iMessage.",
172
- `Install imsg on the Messages Mac: ${IMESSAGE_INSTALL_COMMAND}`,
173
- `Update imsg when channel probes report missing RPC or private API capabilities: ${IMESSAGE_UPDATE_COMMAND}`
174
- ]
175
- });
176
- }
177
- const imessageCompletionNote = {
178
- title: "iMessage next steps",
179
- lines: [
180
- "For the usual setup, run OpenClaw on the Mac signed into Messages.",
181
- "If the Gateway runs elsewhere, set cliPath to a transparent SSH wrapper that runs imsg on the Messages Mac.",
182
- `Install imsg on the Messages Mac: ${IMESSAGE_INSTALL_COMMAND}`,
183
- `Update imsg after imsg fixes or missing-capability errors: ${IMESSAGE_UPDATE_COMMAND}`,
184
- "Private API mode is strongly encouraged for replies, tapbacks, effects, polls, attachments, and group actions.",
185
- "After Private API setup, run `imsg launch`, then `openclaw channels status --probe`.",
186
- "Ensure OpenClaw has Full Disk Access to Messages DB.",
187
- "Grant Automation permission for Messages when prompted.",
188
- "List chats with: imsg chats --limit 20",
189
- `Docs: ${formatDocsLink("/imessage", "imessage")}`
190
- ]
191
- };
192
- const imessageSetupAdapter = {
193
- ...createPatchedAccountSetupAdapter({
194
- channelKey: channel,
195
- buildPatch: (input) => buildIMessageSetupPatch(input)
196
- }),
197
- singleAccountKeysToMove: [
198
- "cliPath",
199
- "dbPath",
200
- "service",
201
- "region"
202
- ]
203
- };
204
- const imessageSetupContract = defineChannelSetupContract({
205
- fields: {
206
- cliPath: {
207
- kind: "string",
208
- cli: {
209
- flags: "--cli-path <path>",
210
- description: "iMessage CLI path"
211
- }
212
- },
213
- dbPath: {
214
- kind: "string",
215
- cli: {
216
- flags: "--db-path <path>",
217
- description: "iMessage database path"
218
- }
219
- },
220
- service: {
221
- kind: "choice",
222
- choices: [
223
- "imessage",
224
- "sms",
225
- "auto"
226
- ],
227
- cli: {
228
- flags: "--service <service>",
229
- description: "iMessage service"
230
- }
231
- },
232
- region: {
233
- kind: "string",
234
- cli: {
235
- flags: "--region <region>",
236
- description: "SMS region"
237
- }
238
- }
239
- },
240
- legacyAdapter: imessageSetupAdapter
241
- });
242
- const imessageSetupStatusBase = {
243
- configuredLabel: t("wizard.channels.statusConfigured"),
244
- unconfiguredLabel: t("wizard.channels.statusNeedsSetup"),
245
- configuredHint: t("wizard.imessage.imsgFound"),
246
- unconfiguredHint: t("wizard.imessage.imsgMissing"),
247
- configuredScore: 1,
248
- unconfiguredScore: 0,
249
- resolveConfigured: ({ cfg, accountId }) => resolveIMessageAccount({
250
- cfg,
251
- accountId
252
- }).configured
253
- };
254
- function createIMessageSetupWizardProxy(loadWizard) {
255
- return createDelegatedSetupWizardProxy({
256
- channel,
257
- loadWizard,
258
- status: {
259
- configuredLabel: imessageSetupStatusBase.configuredLabel,
260
- unconfiguredLabel: imessageSetupStatusBase.unconfiguredLabel,
261
- configuredHint: imessageSetupStatusBase.configuredHint,
262
- unconfiguredHint: imessageSetupStatusBase.unconfiguredHint,
263
- configuredScore: imessageSetupStatusBase.configuredScore,
264
- unconfiguredScore: imessageSetupStatusBase.unconfiguredScore
265
- },
266
- delegatePrepare: true,
267
- credentials: [],
268
- textInputs: [createIMessageCliPathTextInput(createDelegatedTextInputShouldPrompt({
269
- loadWizard,
270
- inputKey: "cliPath"
271
- }))],
272
- completionNote: imessageCompletionNote,
273
- dmPolicy: imessageDmPolicy,
274
- disable: (cfg) => setSetupChannelEnabled$1(cfg, channel, false)
275
- });
276
- }
277
- //#endregion
278
50
  //#region extensions/imessage/src/probe.ts
279
51
  const RPC_SUPPORT_CACHE_TTL_MS = 3e5;
280
52
  const PRIVATE_API_NEGATIVE_TTL_MS = 1e4;
@@ -367,31 +139,16 @@ function selectorsFromPayload(payload) {
367
139
  for (const [key, value] of Object.entries(raw)) if (typeof value === "boolean") selectors[key] = value;
368
140
  return selectors;
369
141
  }
370
- async function probeSendRichSupportsAttachment(cliPath, timeoutMs) {
371
- try {
372
- const result = await runCommandWithTimeout([
373
- expandIMessageUserPath(cliPath),
374
- "send-rich",
375
- "--help"
376
- ], { timeoutMs });
377
- if (result.code !== 0) return false;
378
- const combined = `${result.stdout}\n${result.stderr}`;
379
- return /(?:^|\s)--file\b/m.test(combined);
380
- } catch {
381
- return false;
382
- }
383
- }
384
- async function probePollSendSupportsNoComment(cliPath, timeoutMs) {
142
+ async function probeIMessageCliFlag(cliPath, timeoutMs, command, flag) {
385
143
  try {
386
144
  const result = await runCommandWithTimeout([
387
145
  expandIMessageUserPath(cliPath),
388
- "poll",
389
- "send",
146
+ ...command,
390
147
  "--help"
391
148
  ], { timeoutMs });
392
149
  if (result.code !== 0) return false;
393
150
  const combined = `${result.stdout}\n${result.stderr}`;
394
- return /(?:^|\s)--no-comment\b/m.test(combined);
151
+ return flag.test(combined);
395
152
  } catch {
396
153
  return false;
397
154
  }
@@ -431,8 +188,8 @@ async function probeIMessagePrivateApi(cliPath, timeoutMs, options = {}) {
431
188
  const advancedFeatures = payload?.advanced_features === true;
432
189
  const v2Ready = payload?.v2_ready === true;
433
190
  const statusMessage = typeof payload?.message === "string" ? payload.message : void 0;
434
- const sendRichSupportsAttachment = await probeSendRichSupportsAttachment(key, timeoutMs);
435
- const pollSendSupportsNoComment = await probePollSendSupportsNoComment(key, timeoutMs);
191
+ const sendRichSupportsAttachment = await probeIMessageCliFlag(key, timeoutMs, ["send-rich"], /(?:^|\s)--file\b/m);
192
+ const pollSendSupportsNoComment = await probeIMessageCliFlag(key, timeoutMs, ["poll", "send"], /(?:^|\s)--no-comment\b/m);
436
193
  const status = {
437
194
  available: result.code === 0 && advancedFeatures && v2Ready,
438
195
  v2Ready,
@@ -519,7 +276,7 @@ async function probeIMessage(timeoutMs, opts = {}) {
519
276
  }
520
277
  //#endregion
521
278
  //#region extensions/imessage/src/actions.ts
522
- const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-D0zG_96v.mjs"), "imessageActionsRuntime");
279
+ const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-DdBN29zj.mjs"), "imessageActionsRuntime");
523
280
  const log = createSubsystemLogger("channels/imessage");
524
281
  const providerId = "imessage";
525
282
  const SUPPORTED_ACTIONS = /* @__PURE__ */ new Set([...IMESSAGE_ACTION_NAMES, "upload-file"]);
@@ -706,14 +463,11 @@ const REPLY_ATTACHMENT_PATH_PARAM_NAMES = [
706
463
  function extractReplyAttachment(params) {
707
464
  if (readStringParam(params, "buffer")) {
708
465
  const filename = readStringParam(params, "filename") ?? "attachment.bin";
709
- return {
710
- spec: {
711
- kind: "buffer",
712
- buffer: decodeBase64Buffer(params, "reply attachment"),
713
- filename
714
- },
715
- sourceParam: "buffer"
716
- };
466
+ return { spec: {
467
+ kind: "buffer",
468
+ buffer: decodeBase64Buffer(params, "reply attachment"),
469
+ filename
470
+ } };
717
471
  }
718
472
  for (const name of REPLY_ATTACHMENT_PATH_PARAM_NAMES) if (readStringParam(params, name)) return {
719
473
  spec: null,
@@ -721,46 +475,32 @@ function extractReplyAttachment(params) {
721
475
  };
722
476
  return null;
723
477
  }
724
- const KNOWN_EFFECT_IDS = /* @__PURE__ */ new Set([
725
- "com.apple.MobileSMS.expressivesend.impact",
726
- "com.apple.MobileSMS.expressivesend.loud",
727
- "com.apple.MobileSMS.expressivesend.gentle",
728
- "com.apple.MobileSMS.expressivesend.invisibleink",
729
- "com.apple.MobileSMS.expressivesend.confetti",
730
- "com.apple.MobileSMS.expressivesend.lasers",
731
- "com.apple.MobileSMS.expressivesend.fireworks",
732
- "com.apple.MobileSMS.expressivesend.balloon",
733
- "com.apple.MobileSMS.expressivesend.heart",
734
- "com.apple.messages.effect.CKEchoEffect",
735
- "com.apple.messages.effect.CKHappyBirthdayEffect",
736
- "com.apple.messages.effect.CKShootingStarEffect",
737
- "com.apple.messages.effect.CKSparklesEffect",
738
- "com.apple.messages.effect.CKSpotlightEffect"
739
- ]);
478
+ const EFFECT_ALIASES = {
479
+ slam: "com.apple.MobileSMS.expressivesend.impact",
480
+ impact: "com.apple.MobileSMS.expressivesend.impact",
481
+ loud: "com.apple.MobileSMS.expressivesend.loud",
482
+ gentle: "com.apple.MobileSMS.expressivesend.gentle",
483
+ "invisible-ink": "com.apple.MobileSMS.expressivesend.invisibleink",
484
+ invisibleink: "com.apple.MobileSMS.expressivesend.invisibleink",
485
+ confetti: "com.apple.MobileSMS.expressivesend.confetti",
486
+ lasers: "com.apple.MobileSMS.expressivesend.lasers",
487
+ fireworks: "com.apple.MobileSMS.expressivesend.fireworks",
488
+ balloons: "com.apple.MobileSMS.expressivesend.balloon",
489
+ balloon: "com.apple.MobileSMS.expressivesend.balloon",
490
+ heart: "com.apple.MobileSMS.expressivesend.heart",
491
+ echo: "com.apple.messages.effect.CKEchoEffect",
492
+ happybirthday: "com.apple.messages.effect.CKHappyBirthdayEffect",
493
+ "happy-birthday": "com.apple.messages.effect.CKHappyBirthdayEffect",
494
+ shootingstar: "com.apple.messages.effect.CKShootingStarEffect",
495
+ "shooting-star": "com.apple.messages.effect.CKShootingStarEffect",
496
+ sparkles: "com.apple.messages.effect.CKSparklesEffect",
497
+ spotlight: "com.apple.messages.effect.CKSpotlightEffect"
498
+ };
499
+ const KNOWN_EFFECT_IDS = new Set(Object.values(EFFECT_ALIASES));
740
500
  function effectIdFromParam(raw) {
741
501
  const value = normalizeOptionalLowercaseString(raw);
742
502
  if (!value) return;
743
- const resolved = {
744
- slam: "com.apple.MobileSMS.expressivesend.impact",
745
- impact: "com.apple.MobileSMS.expressivesend.impact",
746
- loud: "com.apple.MobileSMS.expressivesend.loud",
747
- gentle: "com.apple.MobileSMS.expressivesend.gentle",
748
- "invisible-ink": "com.apple.MobileSMS.expressivesend.invisibleink",
749
- invisibleink: "com.apple.MobileSMS.expressivesend.invisibleink",
750
- confetti: "com.apple.MobileSMS.expressivesend.confetti",
751
- lasers: "com.apple.MobileSMS.expressivesend.lasers",
752
- fireworks: "com.apple.MobileSMS.expressivesend.fireworks",
753
- balloons: "com.apple.MobileSMS.expressivesend.balloon",
754
- balloon: "com.apple.MobileSMS.expressivesend.balloon",
755
- heart: "com.apple.MobileSMS.expressivesend.heart",
756
- echo: "com.apple.messages.effect.CKEchoEffect",
757
- happybirthday: "com.apple.messages.effect.CKHappyBirthdayEffect",
758
- "happy-birthday": "com.apple.messages.effect.CKHappyBirthdayEffect",
759
- shootingstar: "com.apple.messages.effect.CKShootingStarEffect",
760
- "shooting-star": "com.apple.messages.effect.CKShootingStarEffect",
761
- sparkles: "com.apple.messages.effect.CKSparklesEffect",
762
- spotlight: "com.apple.messages.effect.CKSpotlightEffect"
763
- }[value] ?? raw;
503
+ const resolved = EFFECT_ALIASES[value] ?? raw;
764
504
  if (typeof resolved === "string" && KNOWN_EFFECT_IDS.has(resolved)) return resolved;
765
505
  throw new Error(`iMessage sendWithEffect rejected unknown effect "${raw}". Use one of: slam, loud, gentle, invisibleink, confetti, lasers, fireworks, balloon, heart, echo, happybirthday, shootingstar, sparkles, spotlight (or the canonical com.apple.MobileSMS.expressivesend.* / com.apple.messages.effect.* identifier).`);
766
506
  }
@@ -863,8 +603,8 @@ const imessageMessageActions = {
863
603
  }
864
604
  });
865
605
  };
606
+ await assertPrivateApiEnabled();
866
607
  if (action === "react") {
867
- await assertPrivateApiEnabled();
868
608
  const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove an iMessage reaction." });
869
609
  const reaction = mapTapbackReaction(emoji);
870
610
  const TAPBACK_KINDS = [
@@ -884,7 +624,7 @@ const imessageMessageActions = {
884
624
  messageId: reference.messageId,
885
625
  reaction: kind,
886
626
  remove: remove || void 0,
887
- partIndex: typeof partIndex === "number" ? partIndex : void 0,
627
+ partIndex,
888
628
  options: {
889
629
  ...opts,
890
630
  chatGuid: reference.chatGuid
@@ -896,7 +636,6 @@ const imessageMessageActions = {
896
636
  });
897
637
  }
898
638
  if (action === "edit") {
899
- await assertPrivateApiEnabled();
900
639
  const text = readStringParam(params, "text") ?? readStringParam(params, "newText") ?? readStringParam(params, "message");
901
640
  if (!text) throw new Error("iMessage edit requires text, newText, or message.");
902
641
  const partIndex = readNonNegativeIntegerParam(params, "partIndex");
@@ -906,8 +645,8 @@ const imessageMessageActions = {
906
645
  chatGuid: reference.chatGuid,
907
646
  messageId: reference.messageId,
908
647
  text,
909
- backwardsCompatMessage: backwardsCompatMessage ?? void 0,
910
- partIndex: typeof partIndex === "number" ? partIndex : void 0,
648
+ backwardsCompatMessage,
649
+ partIndex,
911
650
  options: {
912
651
  ...opts,
913
652
  chatGuid: reference.chatGuid
@@ -919,13 +658,12 @@ const imessageMessageActions = {
919
658
  });
920
659
  }
921
660
  if (action === "unsend") {
922
- await assertPrivateApiEnabled();
923
661
  const partIndex = readNonNegativeIntegerParam(params, "partIndex");
924
662
  const reference = await messageReference({ requireFromMe: true });
925
663
  await runtime.unsendMessage({
926
664
  chatGuid: reference.chatGuid,
927
665
  messageId: reference.messageId,
928
- partIndex: typeof partIndex === "number" ? partIndex : void 0,
666
+ partIndex,
929
667
  options: {
930
668
  ...opts,
931
669
  chatGuid: reference.chatGuid
@@ -937,7 +675,6 @@ const imessageMessageActions = {
937
675
  });
938
676
  }
939
677
  if (action === "reply") {
940
- await assertPrivateApiEnabled();
941
678
  const text = readMessageText(params);
942
679
  if (!text) throw new Error("iMessage reply requires text or message.");
943
680
  const reference = await messageReference();
@@ -951,7 +688,7 @@ const imessageMessageActions = {
951
688
  chatGuid: reference.chatGuid,
952
689
  text,
953
690
  replyToMessageId: reference.messageId,
954
- partIndex: typeof partIndex === "number" ? partIndex : void 0,
691
+ partIndex,
955
692
  attachment: attachment?.spec ?? void 0,
956
693
  options: {
957
694
  ...opts,
@@ -970,7 +707,6 @@ const imessageMessageActions = {
970
707
  });
971
708
  }
972
709
  if (action === "sendWithEffect") {
973
- await assertPrivateApiEnabled();
974
710
  const text = readMessageText(params);
975
711
  const effectId = effectIdFromParam(readStringParam(params, "effectId") ?? readStringParam(params, "effect"));
976
712
  if (!text || !effectId) throw new Error("iMessage sendWithEffect requires text/message and effect/effectId.");
@@ -996,7 +732,6 @@ const imessageMessageActions = {
996
732
  });
997
733
  }
998
734
  if (action === "renameGroup") {
999
- await assertPrivateApiEnabled();
1000
735
  const displayName = readStringParam(params, "displayName") ?? readStringParam(params, "name");
1001
736
  if (!displayName) throw new Error("iMessage renameGroup requires displayName or name.");
1002
737
  const resolvedChatGuid = await chatGuid();
@@ -1015,7 +750,6 @@ const imessageMessageActions = {
1015
750
  });
1016
751
  }
1017
752
  if (action === "setGroupIcon") {
1018
- await assertPrivateApiEnabled();
1019
753
  const filename = readStringParam(params, "filename") ?? readStringParam(params, "name") ?? "icon.png";
1020
754
  const resolvedChatGuid = await chatGuid();
1021
755
  await runtime.setGroupIcon({
@@ -1034,26 +768,10 @@ const imessageMessageActions = {
1034
768
  });
1035
769
  }
1036
770
  if (action === "addParticipant" || action === "removeParticipant") {
1037
- await assertPrivateApiEnabled();
1038
771
  const address = readStringParam(params, "address") ?? readStringParam(params, "participant");
1039
772
  if (!address) throw new Error(`iMessage ${action} requires address or participant.`);
1040
773
  const resolvedChatGuid = await chatGuid();
1041
- if (action === "addParticipant") {
1042
- await runtime.addParticipant({
1043
- chatGuid: resolvedChatGuid,
1044
- address,
1045
- options: {
1046
- ...opts,
1047
- chatGuid: resolvedChatGuid
1048
- }
1049
- });
1050
- return jsonResult({
1051
- ok: true,
1052
- added: address,
1053
- chatGuid: resolvedChatGuid
1054
- });
1055
- }
1056
- await runtime.removeParticipant({
774
+ await runtime[action]({
1057
775
  chatGuid: resolvedChatGuid,
1058
776
  address,
1059
777
  options: {
@@ -1063,12 +781,11 @@ const imessageMessageActions = {
1063
781
  });
1064
782
  return jsonResult({
1065
783
  ok: true,
1066
- removed: address,
784
+ [action === "addParticipant" ? "added" : "removed"]: address,
1067
785
  chatGuid: resolvedChatGuid
1068
786
  });
1069
787
  }
1070
788
  if (action === "leaveGroup") {
1071
- await assertPrivateApiEnabled();
1072
789
  const resolvedChatGuid = await chatGuid();
1073
790
  await runtime.leaveGroup({
1074
791
  chatGuid: resolvedChatGuid,
@@ -1083,7 +800,6 @@ const imessageMessageActions = {
1083
800
  });
1084
801
  }
1085
802
  if (action === "sendAttachment" || action === "upload-file") {
1086
- await assertPrivateApiEnabled();
1087
803
  const filename = readStringParam(params, "filename", { required: true });
1088
804
  const asVoice = readBooleanParam(params, "asVoice");
1089
805
  const resolvedChatGuid = await chatGuid();
@@ -1108,7 +824,6 @@ const imessageMessageActions = {
1108
824
  });
1109
825
  }
1110
826
  if (action === "poll") {
1111
- await assertPrivateApiEnabled();
1112
827
  if (privateApiStatus?.selectors?.pollPayloadMessage !== true) await probePrivateApiStatus(true);
1113
828
  if (privateApiStatus?.selectors?.pollPayloadMessage !== true) throw new Error("iMessage poll requires an imsg bridge that advertises the pollPayloadMessage selector. Update imsg, run imsg launch to re-inject the bridge, then run openclaw channels status --probe to refresh capability detection.");
1114
829
  const question = readStringParam(params, "pollQuestion", { required: true });
@@ -1138,7 +853,6 @@ const imessageMessageActions = {
1138
853
  });
1139
854
  }
1140
855
  if (action === "poll-vote") {
1141
- await assertPrivateApiEnabled();
1142
856
  if (privateApiStatus?.selectors?.pollVoteMessage !== true || !imessageRpcSupportsMethod(privateApiStatus, "poll.vote")) await probePrivateApiStatus(true);
1143
857
  if (privateApiStatus?.selectors?.pollVoteMessage !== true) throw new Error("iMessage poll-vote requires an imsg bridge that advertises the pollVoteMessage selector. Update imsg, run imsg launch to re-inject the bridge, then run openclaw channels status --probe to refresh capability detection.");
1144
858
  if (!imessageRpcSupportsMethod(privateApiStatus, "poll.vote")) throw new Error("iMessage poll-vote requires an imsg build that advertises the poll.vote capability. Update imsg, then run openclaw channels status --probe to refresh capability detection.");
@@ -1280,4 +994,4 @@ function resolveIMessageGroupSystemPrompt(params) {
1280
994
  return typeof prompt === "string" ? prompt.trim() || void 0 : void 0;
1281
995
  }
1282
996
  //#endregion
1283
- export { imessageDmPolicy as _, matchIMessageAcpConversation as a, isAutoManagedIMessageCliPath as b, getIMessageApprovalApprovers as c, probeIMessage as d, probeIMessagePrivateApi as f, imessageCompletionNote as g, createIMessageSetupWizardProxy as h, resolveIMessageInboundConversationId as i, imessageApprovalAuth as l, createIMessageCliPathTextInput as m, resolveIMessageGroupSystemPrompt as n, normalizeIMessageAcpConversationId as o, IMESSAGE_INSTALL_COMMAND as p, resolveIMessageGroupToolPolicy as r, resolveIMessageConversationIdFromTarget as s, resolveIMessageGroupRequireMention as t, imessageMessageActions as u, imessageSetupContract as v, normalizeIMessageCliPathForSetup as x, imessageSetupStatusBase as y };
997
+ export { matchIMessageAcpConversation as a, getIMessageApprovalApprovers as c, probeIMessage as d, probeIMessagePrivateApi as f, resolveIMessageInboundConversationId as i, imessageApprovalAuth as l, resolveIMessageGroupSystemPrompt as n, normalizeIMessageAcpConversationId as o, resolveIMessageGroupToolPolicy as r, resolveIMessageConversationIdFromTarget as s, resolveIMessageGroupRequireMention as t, imessageMessageActions as u };
@@ -1,4 +1,4 @@
1
- import { o as resolveIMessageAccount } from "./accounts-CUxZrTcY.mjs";
1
+ import { o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
2
2
  import { mergeInboundPathRoots } from "openclaw/plugin-sdk/channel-inbound";
3
3
  //#region extensions/imessage/src/media-contract.ts
4
4
  const DEFAULT_IMESSAGE_ATTACHMENT_ROOTS = ["/Users/*/Library/Messages/Attachments"];
@@ -1,5 +1,5 @@
1
- import { n as inferIMessageTargetChatType } from "./targets-Cc9vthzI.mjs";
2
- import { c as getCachedIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-CUxZrTcY.mjs";
1
+ import { n as inferIMessageTargetChatType } from "./targets-BicBiYsM.mjs";
2
+ import { c as getCachedIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
3
3
  import { createActionGate } from "openclaw/plugin-sdk/channel-actions";
4
4
  import { Type } from "typebox";
5
5
  import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
@@ -77,21 +77,6 @@ function setCachedIMessagePrivateApiStatus(cliPath, status, expiresAt = 0) {
77
77
  }
78
78
  //#endregion
79
79
  //#region extensions/imessage/src/message-tool-api.ts
80
- const PRIVATE_API_ACTIONS = /* @__PURE__ */ new Set([
81
- "react",
82
- "edit",
83
- "unsend",
84
- "reply",
85
- "sendWithEffect",
86
- "renameGroup",
87
- "setGroupIcon",
88
- "addParticipant",
89
- "removeParticipant",
90
- "leaveGroup",
91
- "sendAttachment",
92
- "poll",
93
- "poll-vote"
94
- ]);
95
80
  function isGroupTarget(raw, chatType) {
96
81
  if (chatType) return chatType !== "direct";
97
82
  if (!raw) return false;
@@ -114,7 +99,7 @@ function describeIMessageMessageTool({ cfg, accountId, chatType, currentChannelI
114
99
  for (const action of IMESSAGE_ACTION_NAMES) {
115
100
  const spec = IMESSAGE_ACTIONS[action];
116
101
  if (!spec?.gate || !gate(spec.gate)) continue;
117
- if (privateApiStatus?.available === false && PRIVATE_API_ACTIONS.has(action)) continue;
102
+ if (privateApiStatus?.available === false) continue;
118
103
  if (action === "edit" && privateApiStatus?.selectors && !privateApiStatus.selectors.editMessage && !privateApiStatus.selectors.editMessageItem) continue;
119
104
  if (action === "unsend" && privateApiStatus?.selectors?.retractMessagePart !== true) continue;
120
105
  if (action === "poll" && privateApiStatus?.selectors && !privateApiStatus.selectors.pollPayloadMessage) continue;