@openclaw/imessage 2026.9.2 → 2026.9.4

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.
@@ -1,5 +1,5 @@
1
- import { n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, p as resolveIMessageMessageId, s as runIMessageCliJsonCommand, v as normalizeDirectChatIdentifier } from "./sanitize-outbound-Bvo4g1Mp.js";
2
- import { n as authorizeIMessageResourceReference, t as withIMessageRemoteFile } from "./remote-file-Biz5PjXi.js";
1
+ import { n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, p as resolveIMessageMessageId, s as runIMessageCliJsonCommand, v as normalizeDirectChatIdentifier } from "./sanitize-outbound-C6UF2cvr.js";
2
+ import { n as authorizeIMessageResourceReference, t as withIMessageRemoteFile } from "./remote-file-5n5LznCa.js";
3
3
  import { basename, parse, win32 } from "node:path";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { asDateTimestampMs, parseStrictInteger, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
package/dist/api.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, r as listEnabledIMessageAccounts } from "./accounts-CCirBEIm.js";
2
2
  import { _ as IMESSAGE_ACTION_NAMES, a as isAllowedIMessageSender, c as parseIMessageAllowTarget, g as IMESSAGE_ACTIONS, l as parseIMessageTarget, n as formatIMessageChatTarget, o as looksLikeIMessageExplicitTargetId, r as inferIMessageTargetChatType, s as normalizeIMessageHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { m as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./sanitize-outbound-Bvo4g1Mp.js";
4
- import { a as normalizeIMessageAcpConversationId, c as normalizeIMessageMessagingTarget, f as probeIMessage, i as matchIMessageAcpConversation, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, r as resolveIMessageInboundConversationId, s as looksLikeIMessageTargetId, t as resolveIMessageGroupRequireMention, v as imessageSetupContract } from "./group-policy-Cp8SDG4G.js";
5
- import { n as createIMessagePluginBase, r as imessageSetupWizard, t as imessagePlugin } from "./channel-BxraMrmK.js";
3
+ import { m as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "./sanitize-outbound-C6UF2cvr.js";
4
+ import { a as normalizeIMessageAcpConversationId, c as normalizeIMessageMessagingTarget, f as probeIMessage, i as matchIMessageAcpConversation, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, r as resolveIMessageInboundConversationId, s as looksLikeIMessageTargetId, t as resolveIMessageGroupRequireMention, v as imessageSetupContract } from "./group-policy-Duro87b4.js";
5
+ import { n as createIMessagePluginBase, r as imessageSetupWizard, t as imessagePlugin } from "./channel-BwKxE8Ge.js";
6
6
  import { t as createIMessageConversationBindingManager } from "./conversation-bindings-GDQ_Laxj.js";
7
7
  import { t as IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-send-deps-B-QEsLSM.js";
8
8
  import { createAllowedChatSenderMatcher, parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, resolveServicePrefixedAllowTarget, resolveServicePrefixedChatTarget, resolveServicePrefixedOrChatAllowTarget, resolveServicePrefixedTarget } from "openclaw/plugin-sdk/channel-targets";
@@ -1,9 +1,9 @@
1
1
  import { o as resolveIMessageAccount } from "./accounts-CCirBEIm.js";
2
2
  import { f as getCachedIMessagePrivateApiStatus, l as parseIMessageTarget } from "./message-tool-api-CUoFESHj.js";
3
- import { i as extractMarkdownFormatRuns } from "./sanitize-outbound-Bvo4g1Mp.js";
4
- import { c as normalizeIMessageMessagingTarget, l as getIMessageApprovalApprovers } from "./group-policy-Cp8SDG4G.js";
5
- import { a as unregisterIMessageApprovalReactionTarget, c as buildIMessageApprovalConversationKeyForTarget, i as registerIMessageApprovalReactionTarget } from "./approval-reactions-sVpDno7d.js";
6
- import { a as iMessageApprovalPollTargets, c as iMessageApprovalControlBindings, i as buildApprovalPollOptions, o as mapSentPollOptionsToDecisions, t as sendMessageIMessage } from "./send-DC981dqK.js";
3
+ import { i as extractMarkdownFormatRuns } from "./sanitize-outbound-C6UF2cvr.js";
4
+ import { c as normalizeIMessageMessagingTarget, l as getIMessageApprovalApprovers } from "./group-policy-Duro87b4.js";
5
+ import { a as unregisterIMessageApprovalReactionTarget, c as buildIMessageApprovalConversationKeyForTarget, i as registerIMessageApprovalReactionTarget } from "./approval-reactions-BM_AwHPq.js";
6
+ import { a as iMessageApprovalPollTargets, c as iMessageApprovalControlBindings, i as buildApprovalPollOptions, o as mapSentPollOptionsToDecisions, t as sendMessageIMessage } from "./send-CIHiLtcY.js";
7
7
  import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
8
8
  import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
9
9
  import { createActionGate } from "openclaw/plugin-sdk/channel-actions";
@@ -13,7 +13,7 @@ import { buildChannelApprovalExpiredText, buildChannelApprovalResolvedText, crea
13
13
  import { setTimeout } from "node:timers/promises";
14
14
  //#region extensions/imessage/src/approval-handler.runtime.ts
15
15
  const log = createSubsystemLogger("imessage/approvals");
16
- const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-D5MAgeSs.js"), "imessageActionsRuntime");
16
+ const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-CzvR20qT.js"), "imessageActionsRuntime");
17
17
  const DEFAULT_PROBE_TIMEOUT_MS = 5e3;
18
18
  const APPROVAL_POLL_ORDERING_DELAY_MS = 1100;
19
19
  function buildPendingPayload(params) {
@@ -1,13 +1,12 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { l as parseIMessageTarget, s as normalizeIMessageHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { l as getIMessageApprovalApprovers, u as imessageApprovalAuth } from "./group-policy-Cp8SDG4G.js";
3
+ import { l as getIMessageApprovalApprovers, u as imessageApprovalAuth } from "./group-policy-Duro87b4.js";
4
4
  import { n as getOptionalIMessageRuntime } from "./runtime-Cza4CY5T.js";
5
5
  import { n as normalizeIMessageGuid, t as resolveIMessageReactionContext } from "./reaction-context-Br-vAJFp.js";
6
6
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
7
7
  import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { asDateTimestampMs, isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
9
- import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
10
- import { addApprovalReactionHintToText, approvalReactionDecisionSetsMatch, buildApprovalReactionDeliveredBindingMarker, buildApprovalReactionHint, createApprovalReactionTargetStore, listApprovalReactionBindings, normalizeApprovalReactionDecision, readApprovalReactionDecisionList, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
9
+ import { addApprovalReactionHintToText, approvalReactionDecisionSetsMatch, buildApprovalReactionDeliveredBindingMarker, buildApprovalReactionHint, createApprovalReactionTargetStore, listApprovalReactionBindings, normalizeApprovalReactionDecision, readApprovalReactionDecisionList, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, readApprovalReactionTargetRecord, resolveTypedApprovalReactionTarget, settleApprovalReaction } from "openclaw/plugin-sdk/approval-reaction-runtime";
11
10
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
12
11
  //#region extensions/imessage/src/approval-target-keys.ts
13
12
  function chatIdToKeyValue(chatId) {
@@ -236,24 +235,13 @@ function reportApprovalBindingCorrelationMismatch(binding) {
236
235
  });
237
236
  } catch {}
238
237
  }
239
- function readPersistedTarget(value) {
240
- const target = value;
241
- if (!target || typeof target.approvalId !== "string" || target.approvalKind !== "exec" && target.approvalKind !== "plugin") return null;
242
- const allowedDecisions = readApprovalReactionDecisionList(target.allowedDecisions);
243
- if (!allowedDecisions) return null;
244
- return {
245
- approvalId: target.approvalId,
246
- approvalKind: target.approvalKind,
247
- allowedDecisions
248
- };
249
- }
250
238
  const imessageApprovalReactionTargets = createApprovalReactionTargetStore({
251
239
  namespace: PERSISTENT_NAMESPACE,
252
240
  maxEntries: PERSISTENT_MAX_ENTRIES,
253
241
  defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
254
242
  openStore: (params) => getOptionalIMessageRuntime()?.state.openKeyedStore(params),
255
243
  logPersistentError: reportPersistentApprovalReactionError,
256
- readPersistedTarget
244
+ readPersistedTarget: readApprovalReactionTargetRecord
257
245
  });
258
246
  const IMESSAGE_APPROVAL_DELIVERY_BINDING_KEY = "imessageApprovalReactionBindingV1";
259
247
  function visibleApprovalBindingMatches(text, binding, options) {
@@ -452,50 +440,27 @@ async function handleIMessageApprovalReaction(params) {
452
440
  handled: false,
453
441
  stopPolling: false
454
442
  };
455
- let target = null;
443
+ let matchedTarget = null;
456
444
  let matchedMessageId = null;
457
445
  for (const candidate of event.messageIdCandidates) {
458
- target = await resolveIMessageApprovalReactionTargetWithPersistence({
446
+ matchedTarget = await resolveIMessageApprovalReactionTargetWithPersistence({
459
447
  accountId: params.accountId,
460
448
  conversation: event.conversation,
461
449
  messageId: candidate,
462
450
  reactionKey: event.reactionKey
463
451
  });
464
- if (target) {
452
+ if (matchedTarget) {
465
453
  matchedMessageId = candidate;
466
454
  break;
467
455
  }
468
456
  }
457
+ const target = matchedTarget;
469
458
  if (!target) return {
470
459
  handled: false,
471
460
  stopPolling: false
472
461
  };
473
- if (getIMessageApprovalApprovers({
474
- cfg: params.cfg,
475
- accountId: params.accountId
476
- }).length === 0) {
477
- params.logVerboseMessage?.(`imessage: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
478
- return {
479
- handled: true,
480
- stopPolling: false
481
- };
482
- }
483
- if (!imessageApprovalAuth.authorizeActorAction({
484
- cfg: params.cfg,
485
- accountId: params.accountId,
486
- senderId: event.actorHandle,
487
- action: "approve",
488
- approvalKind: target.approvalKind
489
- }).authorized) {
490
- params.logVerboseMessage?.(`imessage: approval reaction denied id=${target.approvalId} sender=${event.actorHandle}`);
491
- return {
492
- handled: true,
493
- stopPolling: false
494
- };
495
- }
496
- const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
497
- try {
498
- const result = await resolveApprovalOverGateway({
462
+ const settlement = await settleApprovalReaction({
463
+ request: {
499
464
  cfg: params.cfg,
500
465
  approvalId: target.approvalId,
501
466
  approvalKind: target.approvalKind,
@@ -505,46 +470,46 @@ async function handleIMessageApprovalReaction(params) {
505
470
  senderId: event.actorHandle,
506
471
  gatewayUrl: params.gatewayUrl,
507
472
  ...params.gatewayRuntime ? { gatewayRuntime: params.gatewayRuntime } : {}
508
- });
509
- for (const candidate of event.messageIdCandidates) unregisterIMessageApprovalReactionTarget({
510
- accountId: params.accountId,
511
- conversation: event.conversation,
512
- messageId: candidate
513
- });
514
- const outcome = result.applied ? "resolved" : "already resolved";
515
- params.logVerboseMessage?.(`imessage: approval reaction ${outcome} id=${target.approvalId} sender=${event.actorHandle} ${formatCanonicalApprovalTerminalState(result.approval)} via messageId=${matchedMessageId ?? event.messageId}`);
516
- return {
517
- handled: true,
518
- stopPolling: true,
519
- stopPollingReason: "resolved"
520
- };
521
- } catch (error) {
522
- if (isApprovalNotFoundError(error)) {
473
+ },
474
+ approvers: getIMessageApprovalApprovers({
475
+ cfg: params.cfg,
476
+ accountId: params.accountId
477
+ }),
478
+ authorizeActorAction: (input) => imessageApprovalAuth.authorizeActorAction(input),
479
+ loadResolver: loadResolveApprovalOverGateway,
480
+ clearTarget: () => {
523
481
  for (const candidate of event.messageIdCandidates) unregisterIMessageApprovalReactionTarget({
524
482
  accountId: params.accountId,
525
483
  conversation: event.conversation,
526
484
  messageId: candidate
527
485
  });
528
- params.logVerboseMessage?.(`imessage: approval reaction ignored for expired approval id=${target.approvalId} sender=${event.actorHandle}`);
529
- return {
530
- handled: true,
531
- stopPolling: true,
532
- stopPollingReason: "not-found"
533
- };
534
- }
535
- try {
536
- getOptionalIMessageRuntime()?.logging.getChildLogger({
537
- plugin: "imessage",
538
- feature: "approval-reactions"
539
- }).warn("approval reaction failed", {
540
- approvalId: target.approvalId,
541
- senderId: event.actorHandle,
542
- error: String(error)
543
- });
544
- } catch {}
545
- params.logVerboseMessage?.(`imessage: approval reaction failed id=${target.approvalId} sender=${event.actorHandle}: ${String(error)}`);
546
- throw error;
547
- }
486
+ },
487
+ onResolved: (result) => {
488
+ const outcome = result.applied ? "resolved" : "already resolved";
489
+ params.logVerboseMessage?.(`imessage: approval reaction ${outcome} id=${target.approvalId} sender=${event.actorHandle} ${formatCanonicalApprovalTerminalState(result.approval)} via messageId=${matchedMessageId ?? event.messageId}`);
490
+ },
491
+ onError: (error) => {
492
+ try {
493
+ getOptionalIMessageRuntime()?.logging.getChildLogger({
494
+ plugin: "imessage",
495
+ feature: "approval-reactions"
496
+ }).warn("approval reaction failed", {
497
+ approvalId: target.approvalId,
498
+ senderId: event.actorHandle,
499
+ error: String(error)
500
+ });
501
+ } catch {}
502
+ },
503
+ logVerboseMessage: params.logVerboseMessage
504
+ });
505
+ return settlement === "denied" ? {
506
+ handled: true,
507
+ stopPolling: false
508
+ } : {
509
+ handled: true,
510
+ stopPolling: true,
511
+ stopPollingReason: settlement
512
+ };
548
513
  }
549
514
  async function maybeResolveIMessageApprovalReaction(params) {
550
515
  return (await handleIMessageApprovalReaction(params)).handled;
@@ -1,15 +1,16 @@
1
1
  import { a as resolveDefaultIMessageAccountId, i as listIMessageAccountIds, o as resolveIMessageAccount, t as collectIMessageDuplicateAccountSourceWarnings } from "./accounts-CCirBEIm.js";
2
2
  import { l as parseIMessageTarget, o as looksLikeIMessageExplicitTargetId, r as inferIMessageTargetChatType, s as normalizeIMessageHandle, u as isIMessagePhoneLikeHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { n as sanitizeIMessageFinalOutboundText, r as sanitizeOutboundText, y as resolveIMessageDirectChatService } from "./sanitize-outbound-Bvo4g1Mp.js";
4
- import { a as normalizeIMessageAcpConversationId, c as normalizeIMessageMessagingTarget, d as imessageMessageActions, h as createIMessageSetupWizardProxy, i as matchIMessageAcpConversation, l as getIMessageApprovalApprovers, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, t as resolveIMessageGroupRequireMention, u as imessageApprovalAuth, v as imessageSetupContract } from "./group-policy-Cp8SDG4G.js";
3
+ import { n as sanitizeIMessageFinalOutboundText, r as sanitizeOutboundText, y as resolveIMessageDirectChatService } from "./sanitize-outbound-C6UF2cvr.js";
4
+ import { a as normalizeIMessageAcpConversationId, c as normalizeIMessageMessagingTarget, d as imessageMessageActions, h as createIMessageSetupWizardProxy, i as matchIMessageAcpConversation, l as getIMessageApprovalApprovers, n as resolveIMessageGroupToolPolicy, o as resolveIMessageConversationIdFromTarget, t as resolveIMessageGroupRequireMention, u as imessageApprovalAuth, v as imessageSetupContract } from "./group-policy-Duro87b4.js";
5
5
  import { t as createIMessageConversationBindingManager } from "./conversation-bindings-GDQ_Laxj.js";
6
- import { t as IMessageChannelConfigSchema } from "./config-schema-DuGbA8Kp.js";
6
+ import { t as IMessageChannelConfigSchema } from "./config-schema-CCbTcJEV.js";
7
7
  import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-pns3TSS5.js";
8
8
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
9
9
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
10
10
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, formatTrimmedAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
11
11
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
12
12
  import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
13
+ import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
13
14
  import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared";
14
15
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
15
16
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
@@ -74,6 +75,7 @@ const imessageApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
74
75
  }) }
75
76
  },
76
77
  createNativeRuntime: (routing) => createLazyChannelApprovalNativeRuntimeAdapter({
78
+ capabilityBoundary: true,
77
79
  eventKinds: [
78
80
  "exec",
79
81
  "plugin",
@@ -90,7 +92,7 @@ const imessageApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
90
92
  approvalKind,
91
93
  request
92
94
  }),
93
- load: async () => (await import("./approval-handler.runtime-47rs6THN.js")).imessageApprovalNativeRuntime
95
+ load: async () => (await import("./approval-handler.runtime-B6JGnxQf.js")).imessageApprovalNativeRuntime
94
96
  })
95
97
  });
96
98
  const imessageApprovalRouting = imessageApproval.routing;
@@ -205,7 +207,7 @@ const imessageDoctor = {
205
207
  //#region extensions/imessage/src/shared.ts
206
208
  const IMESSAGE_CHANNEL = "imessage";
207
209
  async function loadIMessageChannelRuntime$1() {
208
- return await import("./channel.runtime-2jwkMPGR.js");
210
+ return await import("./channel.runtime-BGwNkU9Z.js");
209
211
  }
210
212
  const imessageSetupWizard = createIMessageSetupWizardProxy(async () => (await loadIMessageChannelRuntime$1()).imessageSetupWizard);
211
213
  const imessageConfigAdapter = createScopedChannelConfigAdapter({
@@ -307,7 +309,7 @@ async function probeIMessageStatusAccount(params) {
307
309
  }
308
310
  //#endregion
309
311
  //#region extensions/imessage/src/channel.ts
310
- const loadIMessageChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-2jwkMPGR.js"));
312
+ const loadIMessageChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-BGwNkU9Z.js"));
311
313
  function toIMessageMessageSendResult(result, kind, replyToId) {
312
314
  const receipt = result.receipt ?? createMessageReceiptFromOutboundResults({
313
315
  results: result.messageId ? [{
@@ -323,7 +325,7 @@ function toIMessageMessageSendResult(result, kind, replyToId) {
323
325
  ...result.meta && Object.keys(result.meta).length > 0 ? { meta: result.meta } : {}
324
326
  };
325
327
  }
326
- const loadIMessageApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-sVpDno7d.js").then((n) => n.t));
328
+ const loadIMessageApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-BM_AwHPq.js").then((n) => n.t));
327
329
  const loadIMessageQuestionReactionsModule = createLazyRuntimeModule(() => import("./question-reactions-9tBYB1_F.js").then((n) => n.r));
328
330
  async function prepareForwardedIMessageApprovalPayload(params) {
329
331
  const prepared = (await loadIMessageApprovalReactionsModule()).addIMessageApprovalReactionHintToStructuredPayload(params);
@@ -505,9 +507,12 @@ const imessagePlugin = createChatChannelPlugin({
505
507
  if (!to) return null;
506
508
  const chatType = inferIMessageTargetChatType(to);
507
509
  if (!chatType) return null;
510
+ const parsed = parseIMessageTarget(to);
511
+ const display = parsed.kind === "handle" && !isCanonicalIMessageDirectHandle(parsed.to, normalizeIMessageHandle(parsed.to)) ? parsed.to.trim() : void 0;
508
512
  return {
509
513
  to,
510
514
  kind: chatType === "direct" ? "user" : "group",
515
+ ...display ? { display } : {},
511
516
  source: "normalized"
512
517
  };
513
518
  }
@@ -557,11 +562,14 @@ const imessagePlugin = createChatChannelPlugin({
557
562
  },
558
563
  pairing: { text: {
559
564
  idLabel: "imessageSenderId",
560
- message: "OpenClaw: your access has been approved.",
561
- notify: async ({ id, cfg }) => await (await loadIMessageChannelRuntime()).notifyIMessageApproval({
562
- id,
563
- cfg
564
- })
565
+ message: PAIRING_APPROVED_MESSAGE,
566
+ notify: async (params) => {
567
+ await (await loadIMessageChannelRuntime()).sendIMessageOutbound({
568
+ ...params,
569
+ to: params.id,
570
+ text: params.message
571
+ });
572
+ }
565
573
  } },
566
574
  security: imessageSecurityAdapter,
567
575
  outbound: {
@@ -1,2 +1,2 @@
1
- import { t as IMessageChannelConfigSchema } from "./config-schema-DuGbA8Kp.js";
1
+ import { t as IMessageChannelConfigSchema } from "./config-schema-CCbTcJEV.js";
2
2
  export { IMessageChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as imessagePlugin } from "./channel-BxraMrmK.js";
1
+ import { t as imessagePlugin } from "./channel-BwKxE8Ge.js";
2
2
  export { imessagePlugin };
@@ -1,8 +1,8 @@
1
1
  import { l as resolveIMessageRemoteHost, o as resolveIMessageAccount, r as listEnabledIMessageAccounts, s as resolveIMessageDuplicateSourceOwner } from "./accounts-CCirBEIm.js";
2
- import { _ as imessageDmPolicy, b as isAutoManagedIMessageCliPath, f as probeIMessage, g as imessageCompletionNote, m as createIMessageCliPathTextInput, p as IMESSAGE_INSTALL_COMMAND, x as normalizeIMessageCliPathForSetup, y as imessageSetupStatusBase } from "./group-policy-Cp8SDG4G.js";
2
+ import { _ as imessageDmPolicy, b as isAutoManagedIMessageCliPath, f as probeIMessage, g as imessageCompletionNote, m as createIMessageCliPathTextInput, p as IMESSAGE_INSTALL_COMMAND, x as normalizeIMessageCliPathForSetup, y as imessageSetupStatusBase } from "./group-policy-Duro87b4.js";
3
3
  import { t as IMESSAGE_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-send-deps-B-QEsLSM.js";
4
- import { t as sendMessageIMessage } from "./send-DC981dqK.js";
5
- import { t as monitorIMessageProvider } from "./monitor-CESwxMQ4.js";
4
+ import { t as sendMessageIMessage } from "./send-CIHiLtcY.js";
5
+ import { t as monitorIMessageProvider } from "./monitor-xaD-9h0b.js";
6
6
  import { createAccountStatusSink, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
7
7
  import path from "node:path";
8
8
  import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
@@ -10,7 +10,6 @@ import fs from "node:fs/promises";
10
10
  import { createDetectedBinaryStatus, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
11
11
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
12
12
  import { detectBinary as detectBinary$1, resolveBrewExecutable } from "openclaw/plugin-sdk/setup-tools";
13
- import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
14
13
  import { runPluginCommandWithTimeout } from "openclaw/plugin-sdk/run-command";
15
14
  //#region extensions/imessage/src/install-imsg.ts
16
15
  const IMESSAGE_BREW_FORMULA = "steipete/tap/imsg";
@@ -226,9 +225,6 @@ async function sendIMessageOutbound(params) {
226
225
  meta
227
226
  } : result;
228
227
  }
229
- async function notifyIMessageApproval(params) {
230
- await sendMessageIMessage(params.id, PAIRING_APPROVED_MESSAGE, { config: params.cfg });
231
- }
232
228
  async function probeIMessageAccount(params) {
233
229
  return await probeIMessage(params?.timeoutMs, {
234
230
  cliPath: params?.cliPath,
@@ -280,4 +276,4 @@ async function startIMessageGatewayAccount(ctx) {
280
276
  });
281
277
  }
282
278
  //#endregion
283
- export { imessageSetupWizard, notifyIMessageApproval, probeIMessageAccount, sendIMessageOutbound, startIMessageGatewayAccount };
279
+ export { imessageSetupWizard, probeIMessageAccount, sendIMessageOutbound, startIMessageGatewayAccount };
@@ -1,5 +1,5 @@
1
1
  import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
2
- import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, isSafeScpRemoteHost, isValidInboundPathRootPattern, requireAllowlistAllowFrom, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
2
+ import { ChannelDeliveryStreamingConfigSchema, ChannelSendReadReceiptsSchema, ExecutableTokenSchema, buildChannelAccountSchemaParts, buildChannelConfigSchema, buildChannelReactionShape, buildGroupEntrySchema, isSafeScpRemoteHost, isValidInboundPathRootPattern, refineChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-schema";
3
3
  import { z } from "zod";
4
4
  //#region extensions/imessage/src/config-ui-hints.ts
5
5
  const iMessageChannelConfigUiHints = {
@@ -93,46 +93,19 @@ const IMessageConfigSchema = IMessageAccountSchemaBase.extend({
93
93
  accounts: z.record(z.string(), IMessageAccountSchemaBase.optional()).optional(),
94
94
  defaultAccount: z.string().optional()
95
95
  }).superRefine((value, ctx) => {
96
- requireOpenAllowFrom({
97
- policy: value.dmPolicy,
98
- allowFrom: value.allowFrom,
99
- ctx,
100
- path: ["allowFrom"],
101
- message: "channels.imessage.dmPolicy=\"open\" requires channels.imessage.allowFrom to include \"*\""
102
- });
103
- requireAllowlistAllowFrom({
104
- policy: value.dmPolicy,
105
- allowFrom: value.allowFrom,
106
- ctx,
107
- path: ["allowFrom"],
108
- message: "channels.imessage.dmPolicy=\"allowlist\" requires channels.imessage.allowFrom to contain at least one sender ID"
96
+ refineChannelDmPolicy({
97
+ channelId: "imessage",
98
+ value,
99
+ ctx
109
100
  });
110
101
  if (!value.accounts) return;
111
102
  for (const [accountId, account] of Object.entries(value.accounts)) {
112
103
  if (!account) continue;
113
- const effectivePolicy = account.dmPolicy ?? value.dmPolicy;
114
- const effectiveAllowFrom = account.allowFrom ?? value.allowFrom;
115
- requireOpenAllowFrom({
116
- policy: effectivePolicy,
117
- allowFrom: effectiveAllowFrom,
118
- ctx,
119
- path: [
120
- "accounts",
121
- accountId,
122
- "allowFrom"
123
- ],
124
- message: "channels.imessage.accounts.*.dmPolicy=\"open\" requires channels.imessage.accounts.*.allowFrom (or channels.imessage.allowFrom) to include \"*\""
125
- });
126
- requireAllowlistAllowFrom({
127
- policy: effectivePolicy,
128
- allowFrom: effectiveAllowFrom,
129
- ctx,
130
- path: [
131
- "accounts",
132
- accountId,
133
- "allowFrom"
134
- ],
135
- message: "channels.imessage.accounts.*.dmPolicy=\"allowlist\" requires channels.imessage.accounts.*.allowFrom (or channels.imessage.allowFrom) to contain at least one sender ID"
104
+ refineChannelDmPolicy({
105
+ channelId: "imessage",
106
+ value,
107
+ accountId,
108
+ ctx
136
109
  });
137
110
  }
138
111
  });
@@ -1,6 +1,6 @@
1
1
  import { a as resolveDefaultIMessageAccountId, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-CCirBEIm.js";
2
2
  import { _ as IMESSAGE_ACTION_NAMES, d as normalizeBareIMessageChatIdentifier, f as getCachedIMessagePrivateApiStatus, g as IMESSAGE_ACTIONS, h as setCachedIMessagePrivateApiStatus, l as parseIMessageTarget, p as imessageRpcSupportsMethod, s as normalizeIMessageHandle$1, t as describeIMessageMessageTool, u as isIMessagePhoneLikeHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { c as findLatestIMessageEntryForChat, d as rememberIMessageReplyCache, g as chatContextFromIMessageTarget, l as isIMessageCurrentMessageInChat, o as createIMessageRpcClient } from "./sanitize-outbound-Bvo4g1Mp.js";
3
+ import { c as findLatestIMessageEntryForChat, d as rememberIMessageReplyCache, g as chatContextFromIMessageTarget, l as isIMessageCurrentMessageInChat, o as createIMessageRpcClient } from "./sanitize-outbound-C6UF2cvr.js";
4
4
  import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
5
5
  import path from "node:path";
6
6
  import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
@@ -519,7 +519,7 @@ async function probeIMessage(timeoutMs, opts = {}) {
519
519
  }
520
520
  //#endregion
521
521
  //#region extensions/imessage/src/actions.ts
522
- const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-D5MAgeSs.js"), "imessageActionsRuntime");
522
+ const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-CzvR20qT.js"), "imessageActionsRuntime");
523
523
  const log = createSubsystemLogger("channels/imessage");
524
524
  const providerId = "imessage";
525
525
  const SUPPORTED_ACTIONS = /* @__PURE__ */ new Set([...IMESSAGE_ACTION_NAMES, "upload-file"]);
@@ -1,15 +1,15 @@
1
1
  import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-CCirBEIm.js";
2
2
  import { c as parseIMessageAllowTarget, f as getCachedIMessagePrivateApiStatus, i as isAllowedIMessageReplyContextSender, l as parseIMessageTarget, n as formatIMessageChatTarget, p as imessageRpcSupportsMethod, s as normalizeIMessageHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { d as rememberIMessageReplyCache, o as createIMessageRpcClient, r as sanitizeOutboundText, u as isKnownFromMeIMessageMessageId, y as resolveIMessageDirectChatService } from "./sanitize-outbound-Bvo4g1Mp.js";
4
- import { f as probeIMessage, r as resolveIMessageInboundConversationId } from "./group-policy-Cp8SDG4G.js";
3
+ import { d as rememberIMessageReplyCache, o as createIMessageRpcClient, r as sanitizeOutboundText, u as isKnownFromMeIMessageMessageId, y as resolveIMessageDirectChatService } from "./sanitize-outbound-C6UF2cvr.js";
4
+ import { f as probeIMessage, r as resolveIMessageInboundConversationId } from "./group-policy-Duro87b4.js";
5
5
  import { t as getIMessageRuntime } from "./runtime-Cza4CY5T.js";
6
6
  import { d as resolveIMessageEchoMediaKey, l as capFailureRetriesMap, t as IMESSAGE_CATCHUP_CURSOR_NAMESPACE, u as resolveIMessageCatchupCursorKey } from "./state-contract-DvahEY4X.js";
7
7
  import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-pns3TSS5.js";
8
- import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction, s as buildIMessageApprovalConversationKeyForInbound } from "./approval-reactions-sVpDno7d.js";
9
- import { c as iMessageApprovalControlBindings, n as hasPersistedIMessageEcho, r as stripLeadingEchoTextCorruptionMarkers, s as maybeResolveIMessageApprovalPollVote, t as sendMessageIMessage } from "./send-DC981dqK.js";
8
+ import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction, s as buildIMessageApprovalConversationKeyForInbound } from "./approval-reactions-BM_AwHPq.js";
9
+ import { c as iMessageApprovalControlBindings, n as hasPersistedIMessageEcho, r as stripLeadingEchoTextCorruptionMarkers, s as maybeResolveIMessageApprovalPollVote, t as sendMessageIMessage } from "./send-CIHiLtcY.js";
10
10
  import { n as normalizeIMessageGuid, t as resolveIMessageReactionContext } from "./reaction-context-Br-vAJFp.js";
11
11
  import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-9tBYB1_F.js";
12
- import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, createMessageReceiptFromOutboundResults, listMessageReceiptPlatformIds, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
12
+ import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
13
13
  import { chunkMarkdownTextWithMode as chunkTextWithMode, resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
14
14
  import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
15
15
  import path from "node:path";
@@ -25,7 +25,7 @@ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-util
25
25
  import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
26
26
  import { buildChannelGroupsScopeTree, resolveChannelGroupPolicy, resolveChannelGroups, resolveChannelGroupsConfigPath, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
27
27
  import { convertMarkdownTables as convertMarkdownTables$1, findCodeRegions, isInsideCode, sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
28
- import { buildChannelInboundEventContext, buildMentionRegexes, createChannelInboundDebouncer, createChannelPartialDeliveryError, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, formatMediaPlaceholderText, isChannelPartialDeliveryError, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundDebounceMs, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
28
+ import { buildChannelInboundEventContext, buildMentionRegexes, createAcceptedChannelDeliveryResult, createChannelInboundDebouncer, createChannelPartialDeliveryError, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, formatMediaPlaceholderText, isChannelPartialDeliveryError, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundDebounceMs, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
29
29
  import { resolveAgentConfig, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
30
30
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-runtime";
31
31
  import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
@@ -585,7 +585,7 @@ function parseIMessageNotification(raw) {
585
585
  const maybeMessage = raw.message;
586
586
  if (!isRecord(maybeMessage)) return null;
587
587
  const message = maybeMessage;
588
- if (!isOptionalNumber(message.id) || !isOptionalString(message.guid) || !isOptionalNumber(message.chat_id) || !isOptionalString(message.sender) || !isOptionalString(message.destination_caller_id) || !isOptionalBoolean(message.is_from_me) || !isOptionalString(message.text) || !isOptionalString(message.thread_originator_guid) || !isOptionalString(message.reply_to_guid) || !isOptionalString(message.reply_to_text) || !isOptionalString(message.reply_to_sender) || !isOptionalString(message.created_at) || !isOptionalBoolean(message.is_reaction) || !isOptionalBoolean(message.is_tapback) || !isOptionalString(message.associated_message_guid) || !isOptionalNumber(message.associated_message_type) || !isOptionalString(message.reaction_type) || !isOptionalString(message.reaction_emoji) || !isOptionalBoolean(message.is_reaction_add) || !isOptionalString(message.reacted_to_guid) || !isOptionalAttachments(message.attachments) || !isOptionalString(message.chat_identifier) || !isOptionalString(message.chat_guid) || !isOptionalString(message.chat_name) || !isOptionalStringArray(message.participants) || !isOptionalBoolean(message.is_group)) return null;
588
+ if (!isOptionalNumber(message.id) || !isOptionalString(message.guid) || !isOptionalNumber(message.chat_id) || !isOptionalString(message.sender) || !isOptionalString(message.sender_name) || !isOptionalString(message.destination_caller_id) || !isOptionalBoolean(message.is_from_me) || !isOptionalString(message.text) || !isOptionalString(message.thread_originator_guid) || !isOptionalString(message.reply_to_guid) || !isOptionalString(message.reply_to_text) || !isOptionalString(message.reply_to_sender) || !isOptionalString(message.created_at) || !isOptionalBoolean(message.is_reaction) || !isOptionalBoolean(message.is_tapback) || !isOptionalString(message.associated_message_guid) || !isOptionalNumber(message.associated_message_type) || !isOptionalString(message.reaction_type) || !isOptionalString(message.reaction_emoji) || !isOptionalBoolean(message.is_reaction_add) || !isOptionalString(message.reacted_to_guid) || !isOptionalAttachments(message.attachments) || !isOptionalString(message.chat_identifier) || !isOptionalString(message.chat_guid) || !isOptionalString(message.chat_name) || !isOptionalStringArray(message.participants) || !isOptionalBoolean(message.is_group)) return null;
589
589
  return {
590
590
  ...message,
591
591
  text: typeof message.text === "string" ? stripImessageLengthPrefixedUtf8Text(message.text) : message.text,
@@ -991,32 +991,24 @@ async function deliverIMessageReply(params) {
991
991
  } catch (error) {
992
992
  const partial = isChannelPartialDeliveryError(error) ? error.deliveryResult : void 0;
993
993
  if (accepted.length === 0 && partial?.visibleReplySent !== true) throw error;
994
- const receipt = createMessageReceiptFromOutboundResults({
995
- results: [...accepted.map((result) => ({ receipt: result.receipt })), ...partial?.receipt ? [{ receipt: partial.receipt }] : (partial?.messageIds ?? []).map((messageId) => ({ messageId }))],
996
- kind: reply.mediaUrls.length > 0 ? "media" : "text"
997
- });
998
- throw createChannelPartialDeliveryError(error, {
999
- messageIds: listMessageReceiptPlatformIds(receipt),
1000
- receipt,
1001
- visibleReplySent: true,
994
+ throw createChannelPartialDeliveryError(error, createAcceptedChannelDeliveryResult({
995
+ results: accepted.map((result) => ({ receipt: result.receipt })),
996
+ deliveryResults: partial ? [partial] : [],
997
+ kind: reply.mediaUrls.length > 0 ? "media" : "text",
1002
998
  content: [...accepted.map((result) => result.sentText), partial?.content].filter(Boolean).join("\n")
1003
- });
999
+ }));
1004
1000
  }
1005
1001
  if (delivered === "empty") return {
1006
1002
  visibleReplySent: false,
1007
1003
  suppression: { reason: "no_visible_result" }
1008
1004
  };
1009
- const receipt = createMessageReceiptFromOutboundResults({
1005
+ const deliveryResult = createAcceptedChannelDeliveryResult({
1010
1006
  results: accepted.map((result) => ({ receipt: result.receipt })),
1011
- kind: delivered
1007
+ kind: delivered,
1008
+ content: accepted.map((result) => result.sentText).filter(Boolean).join("\n")
1012
1009
  });
1013
1010
  runtime.log?.(`imessage: delivered reply to ${target}`);
1014
- return {
1015
- messageIds: listMessageReceiptPlatformIds(receipt),
1016
- receipt,
1017
- visibleReplySent: true,
1018
- content: accepted.map((result) => result.sentText).filter(Boolean).join("\n")
1019
- };
1011
+ return deliveryResult;
1020
1012
  }
1021
1013
  function createIMessageEchoCachingSend(params) {
1022
1014
  return async (target, text, opts) => {
@@ -1942,12 +1934,15 @@ async function buildIMessageInboundContext(params) {
1942
1934
  isFromMe: false
1943
1935
  }) : null)?.shortId || void 0;
1944
1936
  const replySuffix = decision.replyContext ? `\n\n[Replying to ${decision.replyContext.sender ?? "unknown sender"}${decision.replyContext.id ? ` id:${decision.replyContext.id}` : ""}]\n${decision.replyContext.body}\n[/Replying]` : "";
1937
+ const senderDisplayName = normalizeNonEmpty(params.message.sender_name ?? "");
1938
+ const directConversationName = senderDisplayName ?? normalizeNonEmpty(params.message.chat_name ?? "") ?? decision.senderNormalized;
1939
+ const conversationName = decision.isGroup ? normalizeNonEmpty(params.message.chat_name ?? "") ?? void 0 : directConversationName;
1945
1940
  const fromLabel = formatInboundFromLabel({
1946
1941
  isGroup: decision.isGroup,
1947
1942
  groupLabel: params.message.chat_name ?? void 0,
1948
1943
  groupId: chatId !== void 0 ? String(chatId) : "unknown",
1949
1944
  groupFallback: "Group",
1950
- directLabel: decision.senderNormalized,
1945
+ directLabel: directConversationName,
1951
1946
  directId: decision.sender
1952
1947
  });
1953
1948
  let combinedBody = formatInboundEnvelope({
@@ -1957,7 +1952,7 @@ async function buildIMessageInboundContext(params) {
1957
1952
  body: `${decision.agentBodyText ?? decision.bodyText}${replySuffix}`,
1958
1953
  chatType: decision.isGroup ? "group" : "direct",
1959
1954
  sender: {
1960
- name: decision.senderNormalized,
1955
+ name: senderDisplayName ?? decision.senderNormalized,
1961
1956
  id: decision.sender
1962
1957
  },
1963
1958
  previousTimestamp: params.previousTimestamp,
@@ -2009,7 +2004,7 @@ async function buildIMessageInboundContext(params) {
2009
2004
  from: imessageFrom,
2010
2005
  sender: {
2011
2006
  id: decision.sender,
2012
- name: decision.senderNormalized,
2007
+ name: senderDisplayName ?? decision.senderNormalized,
2013
2008
  isSelf: params.message.is_from_me === true
2014
2009
  },
2015
2010
  conversation: {
@@ -2019,7 +2014,7 @@ async function buildIMessageInboundContext(params) {
2019
2014
  kind: decision.isGroup ? "group" : "direct",
2020
2015
  id: decision.isGroup ? String(chatId) : decision.senderNormalized
2021
2016
  } },
2022
- label: fromLabel
2017
+ label: conversationName
2023
2018
  },
2024
2019
  route: {
2025
2020
  agentId: decision.route.agentId,
@@ -3416,6 +3411,7 @@ async function monitorIMessageProvider(opts = {}) {
3416
3411
  let directTypingController;
3417
3412
  const directToolTypingOptions = shouldUseDirectToolTypingOptions ? {
3418
3413
  suppressDefaultToolProgressMessages: true,
3414
+ allowToolLifecycleWhenProgressHidden: true,
3419
3415
  allowProgressCallbacksWhenSourceDeliverySuppressed: true,
3420
3416
  onTypingController: (typing) => {
3421
3417
  directTypingController = typing;
@@ -1,5 +1,5 @@
1
1
  import { p as resolveLocalIMessageChatDbPath } from "./accounts-CCirBEIm.js";
2
- import { _ as isIMessageEmailChatIdentifier, f as resolveIMessageCachedResourceBinding, g as chatContextFromIMessageTarget, p as resolveIMessageMessageId } from "./sanitize-outbound-Bvo4g1Mp.js";
2
+ import { _ as isIMessageEmailChatIdentifier, f as resolveIMessageCachedResourceBinding, g as chatContextFromIMessageTarget, p as resolveIMessageMessageId } from "./sanitize-outbound-C6UF2cvr.js";
3
3
  import path from "node:path";
4
4
  import { normalizeScpRemoteHost } from "openclaw/plugin-sdk/host-runtime";
5
5
  import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
@@ -1,16 +1,16 @@
1
1
  import { o as resolveIMessageAccount } from "./accounts-CCirBEIm.js";
2
- import { c as normalizeIMessageMessagingTarget, d as imessageMessageActions, f as probeIMessage, n as resolveIMessageGroupToolPolicy, s as looksLikeIMessageTargetId, t as resolveIMessageGroupRequireMention } from "./group-policy-Cp8SDG4G.js";
2
+ import { c as normalizeIMessageMessagingTarget, d as imessageMessageActions, f as probeIMessage, n as resolveIMessageGroupToolPolicy, s as looksLikeIMessageTargetId, t as resolveIMessageGroupRequireMention } from "./group-policy-Duro87b4.js";
3
3
  import { r as setIMessageRuntime } from "./runtime-Cza4CY5T.js";
4
- import { n as IMessageConfigSchema } from "./config-schema-DuGbA8Kp.js";
5
- import { t as sendMessageIMessage } from "./send-DC981dqK.js";
6
- import { t as monitorIMessageProvider } from "./monitor-CESwxMQ4.js";
4
+ import { n as IMessageConfigSchema } from "./config-schema-CCbTcJEV.js";
5
+ import { t as sendMessageIMessage } from "./send-CIHiLtcY.js";
6
+ import { t as monitorIMessageProvider } from "./monitor-xaD-9h0b.js";
7
7
  import { formatTrimmedAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
8
+ import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
8
9
  import { buildComputedAccountStatusSnapshot, collectStatusIssuesFromLastError } from "openclaw/plugin-sdk/status-helpers";
9
10
  import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
10
11
  import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
11
12
  import { DEFAULT_ACCOUNT_ID, getChatChannelMeta } from "openclaw/plugin-sdk/core";
12
13
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
13
- import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
14
14
  //#region extensions/imessage/src/config-accessors.ts
15
15
  function resolveIMessageConfigAllowFrom(params) {
16
16
  return (resolveIMessageAccount(params).config.allowFrom ?? []).map((entry) => String(entry));
@@ -450,6 +450,29 @@ function normalizeIMessageFullDiskAccessError(message) {
450
450
  if (!normalized.includes("full disk access") || !normalized.includes("chat.db")) return;
451
451
  return PUBLIC_IMESSAGE_FULL_DISK_ACCESS_ERROR;
452
452
  }
453
+ function createLfLineFramer(onLine) {
454
+ const decoder = new StringDecoder("utf8");
455
+ let buffer = "";
456
+ return {
457
+ write(chunk) {
458
+ buffer += typeof chunk === "string" ? chunk : decoder.write(chunk);
459
+ let newlineIndex = buffer.indexOf("\n");
460
+ while (newlineIndex !== -1) {
461
+ const line = buffer.slice(0, newlineIndex);
462
+ buffer = buffer.slice(newlineIndex + 1);
463
+ onLine(line);
464
+ newlineIndex = buffer.indexOf("\n");
465
+ }
466
+ },
467
+ flush() {
468
+ buffer += decoder.end();
469
+ if (!buffer) return;
470
+ const line = buffer;
471
+ buffer = "";
472
+ onLine(line);
473
+ }
474
+ };
475
+ }
453
476
  var IMessageRpcClient = class {
454
477
  constructor(opts = {}) {
455
478
  this.pending = /* @__PURE__ */ new Map();
@@ -458,10 +481,8 @@ var IMessageRpcClient = class {
458
481
  this.isReaped = false;
459
482
  this.child = null;
460
483
  this.stopPromise = null;
461
- this.stdoutBuffer = "";
462
- this.stdoutDecoder = new StringDecoder("utf8");
463
- this.stderrBuffer = "";
464
- this.stderrDecoder = new StringDecoder("utf8");
484
+ this.stdoutFramer = createLfLineFramer((line) => this.handleStdoutLine(line));
485
+ this.stderrFramer = createLfLineFramer((line) => this.handleStderrLine(line));
465
486
  this.nextId = 1;
466
487
  this.publicProcessError = null;
467
488
  this.configuredCliPath = opts.cliPath?.trim() || "imsg";
@@ -490,21 +511,29 @@ var IMessageRpcClient = class {
490
511
  this.child = child;
491
512
  child.stdout.on("data", (chunk) => {
492
513
  if (this.child !== child) return;
493
- this.handleStdoutChunk(chunk);
514
+ this.stdoutFramer.write(chunk);
494
515
  });
495
516
  child.stderr?.on("data", (chunk) => {
496
517
  if (this.child !== child) return;
497
- this.handleStderrChunk(chunk);
518
+ this.stderrFramer.write(chunk);
498
519
  });
499
520
  const failFromProcessError = (err) => this.failTransport(err, child);
500
521
  child.on("error", failFromProcessError);
501
- child.stdin.on("error", failFromProcessError);
502
- child.stdout.on("error", failFromProcessError);
503
- child.stderr.on("error", failFromProcessError);
522
+ for (const stream of [
523
+ child.stdin,
524
+ child.stdout,
525
+ child.stderr
526
+ ]) {
527
+ stream.on("error", failFromProcessError);
528
+ stream.once("close", () => {
529
+ const error = stream.errored;
530
+ if (error) failFromProcessError(error);
531
+ });
532
+ }
504
533
  child.on("close", (code, signal) => {
505
534
  if (this.child === child) {
506
- this.flushStdoutBuffer();
507
- this.flushStderrBuffer();
535
+ this.stdoutFramer.flush();
536
+ this.stderrFramer.flush();
508
537
  this.child = null;
509
538
  }
510
539
  this.finish(this.buildCloseError(code, signal));
@@ -597,48 +626,11 @@ var IMessageRpcClient = class {
597
626
  if (!this.finish(err instanceof Error ? err : new Error(String(err)))) return;
598
627
  if (child) this.signalChild(child, "SIGTERM");
599
628
  }
600
- handleStdoutChunk(chunk) {
601
- const text = typeof chunk === "string" ? chunk : this.stdoutDecoder.write(chunk);
602
- this.stdoutBuffer += text;
603
- let newlineIndex = this.stdoutBuffer.indexOf("\n");
604
- while (newlineIndex !== -1) {
605
- const line = this.stdoutBuffer.slice(0, newlineIndex);
606
- this.stdoutBuffer = this.stdoutBuffer.slice(newlineIndex + 1);
607
- this.handleStdoutLine(line);
608
- newlineIndex = this.stdoutBuffer.indexOf("\n");
609
- }
610
- }
611
- flushStdoutBuffer() {
612
- const tail = this.stdoutDecoder.end();
613
- if (tail) this.stdoutBuffer += tail;
614
- if (!this.stdoutBuffer) return;
615
- const line = this.stdoutBuffer;
616
- this.stdoutBuffer = "";
617
- this.handleStdoutLine(line);
618
- }
619
629
  handleStdoutLine(line) {
620
630
  const trimmed = line.trim();
621
631
  if (!trimmed) return;
622
632
  this.handleLine(trimmed);
623
633
  }
624
- handleStderrChunk(chunk) {
625
- const text = typeof chunk === "string" ? chunk : this.stderrDecoder.write(chunk);
626
- this.stderrBuffer += text;
627
- let newlineIndex = this.stderrBuffer.indexOf("\n");
628
- while (newlineIndex !== -1) {
629
- const line = this.stderrBuffer.slice(0, newlineIndex);
630
- this.stderrBuffer = this.stderrBuffer.slice(newlineIndex + 1);
631
- this.handleStderrLine(line);
632
- newlineIndex = this.stderrBuffer.indexOf("\n");
633
- }
634
- }
635
- flushStderrBuffer() {
636
- this.stderrBuffer += this.stderrDecoder.end();
637
- if (!this.stderrBuffer) return;
638
- const line = this.stderrBuffer;
639
- this.stderrBuffer = "";
640
- this.handleStderrLine(line);
641
- }
642
634
  handleStderrLine(line) {
643
635
  const trimmed = line.trim();
644
636
  if (!trimmed) return;
@@ -764,6 +756,10 @@ function codeDelimiter(content) {
764
756
  return "`".repeat(longestRun + 1);
765
757
  }
766
758
  function restoreCodeMarkers(text, ranges, codeRanges) {
759
+ if (codeRanges.length === 0) return {
760
+ text,
761
+ ranges
762
+ };
767
763
  let rendered = "";
768
764
  let cursor = 0;
769
765
  const edits = codeRanges.map((range) => {
@@ -812,12 +808,12 @@ function extractMarkdownFormatRuns(input) {
812
808
  preserveSourceBlockSpacing: true
813
809
  });
814
810
  const rendered = renderMarkdownWithAttributedRanges(ir, { styleMap: IMESSAGE_STYLE_MAP }, IMESSAGE_FORMAT_PROFILE);
815
- const code = renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE);
811
+ const codeRanges = ir.styles.some((span) => span.style === "code") ? renderMarkdownWithAttributedRanges(ir, { styleMap: { code: "code" } }, IMESSAGE_CODE_PROFILE).ranges : [];
816
812
  return restoreCodeMarkers(rendered.text, rendered.ranges.map(({ start, length, style }) => ({
817
813
  start,
818
814
  length,
819
815
  styles: [style]
820
- })), code.ranges);
816
+ })), codeRanges);
821
817
  }
822
818
  //#endregion
823
819
  //#region extensions/imessage/src/monitor/sanitize-outbound.ts
@@ -1,12 +1,12 @@
1
1
  import { d as resolveIMessageChatDbLookupPath, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount } from "./accounts-CCirBEIm.js";
2
2
  import { l as parseIMessageTarget, n as formatIMessageChatTarget, s as normalizeIMessageHandle } from "./message-tool-api-CUoFESHj.js";
3
- import { a as IMessageRpcRequestError, d as rememberIMessageReplyCache, g as chatContextFromIMessageTarget, n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, s as runIMessageCliJsonCommand, t as protectIMessageFencedRoleMarkers, y as resolveIMessageDirectChatService } from "./sanitize-outbound-Bvo4g1Mp.js";
4
- import { l as getIMessageApprovalApprovers, u as imessageApprovalAuth } from "./group-policy-Cp8SDG4G.js";
3
+ import { a as IMessageRpcRequestError, d as rememberIMessageReplyCache, g as chatContextFromIMessageTarget, n as sanitizeIMessageFinalOutboundText, o as createIMessageRpcClient, s as runIMessageCliJsonCommand, t as protectIMessageFencedRoleMarkers, y as resolveIMessageDirectChatService } from "./sanitize-outbound-C6UF2cvr.js";
4
+ import { l as getIMessageApprovalApprovers, u as imessageApprovalAuth } from "./group-policy-Duro87b4.js";
5
5
  import { n as getOptionalIMessageRuntime, t as getIMessageRuntime } from "./runtime-Cza4CY5T.js";
6
6
  import { c as IMESSAGE_SENT_ECHOES_TTL_MS, d as resolveIMessageEchoMediaKey, p as resolveIMessageSentEchoEntryKey, s as IMESSAGE_SENT_ECHOES_NAMESPACE } from "./state-contract-DvahEY4X.js";
7
- import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-sVpDno7d.js";
7
+ import { d as normalizeConversationKey, i as registerIMessageApprovalReactionTarget, l as enumerateApprovalTargetKeys, s as buildIMessageApprovalConversationKeyForInbound, u as enumerateConversationKeyForms } from "./approval-reactions-BM_AwHPq.js";
8
8
  import { n as normalizeIMessageGuid } from "./reaction-context-Br-vAJFp.js";
9
- import { r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-Biz5PjXi.js";
9
+ import { r as resolveAuthorizedIMessageReplyReference, t as withIMessageRemoteFile } from "./remote-file-5n5LznCa.js";
10
10
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
11
11
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
12
12
  import { accessSync, constants } from "node:fs";
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "id": "imessage",
3
+ "categories": [
4
+ "channels"
5
+ ],
3
6
  "name": "iMessage",
4
7
  "description": "OpenClaw iMessage channel plugin using imsg on a signed-in Mac.",
5
8
  "doctorContract": {
6
9
  "configRepair": true,
7
- "stateMigrations": true
10
+ "stateMigrations": [
11
+ {
12
+ "id": "imessage-legacy-state"
13
+ }
14
+ ]
8
15
  },
9
16
  "activation": {
10
17
  "onStartup": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/imessage",
3
- "version": "2026.9.2",
3
+ "version": "2026.9.4",
4
4
  "description": "OpenClaw iMessage channel plugin using imsg on a signed-in Mac",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.9.2"
15
+ "openclaw": ">=2026.9.4"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -92,10 +92,10 @@
92
92
  "allowInvalidConfigRecovery": true
93
93
  },
94
94
  "compat": {
95
- "pluginApi": ">=2026.9.2"
95
+ "pluginApi": ">=2026.9.4"
96
96
  },
97
97
  "build": {
98
- "openclawVersion": "2026.9.2",
98
+ "openclawVersion": "2026.9.4",
99
99
  "bundledDist": false
100
100
  },
101
101
  "release": {