@openclaw/imessage 2026.8.1-beta.2 → 2026.9.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{accounts-D00Njxg2.js → accounts-DIpGOIiN.js} +2 -2
- package/dist/{actions.runtime-DTFKDN5p.js → actions.runtime-BhggncbG.js} +3 -3
- package/dist/api.js +6 -5
- package/dist/{approval-handler.runtime-BtLs4gho.js → approval-handler.runtime-BC-YsgAf.js} +15 -9
- package/dist/approval-reactions-Cvwmdlev.js +566 -0
- package/dist/{catchup-D32oYNxR.js → catchup-Dh-Rv4Ur.js} +1 -1
- package/dist/{channel-lppmI51h.js → channel-CnKQ2MVB.js} +26 -20
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-5wpCKQb7.js → channel.runtime-BQLCh7bE.js} +6 -4
- package/dist/contract-api.js +1 -1
- package/dist/doctor-contract-api.js +4 -4
- package/dist/{group-policy-DF9xSdik.js → group-policy-BipELT2x.js} +19 -650
- package/dist/{media-contract-BEgdvYhW.js → media-contract-BVXuQHG2.js} +1 -1
- package/dist/media-contract-api.js +1 -1
- package/dist/{message-tool-api-CPDfJJoE.js → message-tool-api-BwIxJDoz.js} +7 -4
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-DnxJ8pW9.js → monitor-DRD_Dnp9.js} +76 -107
- package/dist/{monitor-reply-cache-DKlYGd5x.js → monitor-reply-cache-BdeUQaHO.js} +6 -1
- package/dist/{persisted-echo-cache-BPWGUK-L.js → persisted-echo-cache-DGxy-J4t.js} +1 -1
- package/dist/{question-reactions-DVe50UhB.js → question-reactions-viP7ZcyG.js} +2 -1
- package/dist/reaction-context-BAYI7pz0.js +105 -0
- package/dist/{remote-file-DLwO9ved.js → remote-file-CyTTuRAt.js} +7 -3
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/runtime-api.js +9 -8
- package/dist/{sanitize-outbound-CoTZLXMw.js → sanitize-outbound-g651fIhi.js} +2 -2
- package/dist/{send-BUXW76tw.js → send-DVQY6M5M.js} +24 -24
- package/node_modules/typebox/build/format/date.d.mts +1 -1
- package/node_modules/typebox/build/format/date.mjs +1 -1
- package/node_modules/typebox/build/format/date_time.d.mts +2 -2
- package/node_modules/typebox/build/format/date_time.mjs +3 -3
- package/node_modules/typebox/build/format/email.d.mts +1 -1
- package/node_modules/typebox/build/format/email.mjs +2 -2
- package/node_modules/typebox/build/format/hostname.mjs +2 -10
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_email.mjs +3 -3
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
- package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
- package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
- package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
- package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
- package/node_modules/typebox/build/format/idna/index.mjs +2 -0
- package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
- package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
- package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
- package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
- package/node_modules/typebox/build/format/ipv4.mjs +2 -32
- package/node_modules/typebox/build/format/ipv6.mjs +2 -61
- package/node_modules/typebox/build/format/iri.d.mts +2 -2
- package/node_modules/typebox/build/format/iri.mjs +26 -8
- package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
- package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
- package/node_modules/typebox/build/format/regex.d.mts +1 -2
- package/node_modules/typebox/build/format/regex.mjs +2 -6
- package/node_modules/typebox/build/format/time.d.mts +2 -2
- package/node_modules/typebox/build/format/time.mjs +19 -14
- package/node_modules/typebox/build/format/uri.d.mts +1 -1
- package/node_modules/typebox/build/format/uri.mjs +3 -130
- package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
- package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
- package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
- package/node_modules/typebox/build/format/uri_template.mjs +4 -5
- package/node_modules/typebox/build/format/url.d.mts +3 -3
- package/node_modules/typebox/build/format/url.mjs +4 -5
- package/node_modules/typebox/build/guard/emit.d.mts +3 -1
- package/node_modules/typebox/build/guard/emit.mjs +12 -5
- package/node_modules/typebox/build/guard/guard.d.mts +8 -2
- package/node_modules/typebox/build/guard/guard.mjs +25 -4
- package/node_modules/typebox/build/guard/string.d.mts +2 -2
- package/node_modules/typebox/build/guard/string.mjs +7 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
- package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
- package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
- package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
- package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
- package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
- package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
- package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
- package/node_modules/typebox/build/schema/types/index.mjs +0 -2
- package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
- package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
- package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
- package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
- package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
- package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
- package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
- package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
- package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
- package/node_modules/typebox/build/type/script/parser.mjs +27 -23
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
- package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
- package/node_modules/typebox/package.json +27 -27
- package/node_modules/typebox/readme.md +79 -82
- package/package.json +5 -5
- package/node_modules/typebox/build/format/_idna.d.mts +0 -2
- package/node_modules/typebox/build/format/_idna.mjs +0 -246
- package/node_modules/typebox/build/format/_puny.d.mts +0 -1
- package/node_modules/typebox/build/format/_puny.mjs +0 -77
- package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
- package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
- package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
- package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
|
@@ -1,49 +1,29 @@
|
|
|
1
|
-
import { a as resolveDefaultIMessageAccountId, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-
|
|
2
|
-
import {
|
|
3
|
-
import { a as findLatestIMessageEntryForChat, c as rememberIMessageReplyCache, h as chatContextFromIMessageTarget, o as isIMessageCurrentMessageInChat
|
|
4
|
-
import { o as createIMessageRpcClient } from "./sanitize-outbound-
|
|
5
|
-
import { createLazyRuntimeNamedExport
|
|
6
|
-
import { collectStatusIssuesFromLastError } from "openclaw/plugin-sdk/status-helpers";
|
|
1
|
+
import { a as resolveDefaultIMessageAccountId, l as resolveIMessageRemoteHost, n as hasExclusiveIMessageLocalDatabase, o as resolveIMessageAccount, u as expandIMessageUserPath } from "./accounts-DIpGOIiN.js";
|
|
2
|
+
import { d as normalizeBareIMessageChatIdentifier, f as getCachedIMessagePrivateApiStatus, g as IMESSAGE_ACTION_NAMES, h as IMESSAGE_ACTIONS, l as parseIMessageTarget, m as setCachedIMessagePrivateApiStatus, p as imessageRpcSupportsMethod, s as normalizeIMessageHandle$1, t as describeIMessageMessageTool, u as isIMessagePhoneLikeHandle } from "./message-tool-api-BwIxJDoz.js";
|
|
3
|
+
import { a as findLatestIMessageEntryForChat, c as rememberIMessageReplyCache, h as chatContextFromIMessageTarget, o as isIMessageCurrentMessageInChat } from "./monitor-reply-cache-BdeUQaHO.js";
|
|
4
|
+
import { o as createIMessageRpcClient } from "./sanitize-outbound-g651fIhi.js";
|
|
5
|
+
import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
|
|
7
6
|
import path from "node:path";
|
|
8
7
|
import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
|
|
9
8
|
import { filterStringEntries, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
10
9
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
11
10
|
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
|
12
11
|
import { createActionGate, jsonResult, readNonNegativeIntegerParam, readPositiveIntegerParam, readReactionParams, readStringArrayParam, readStringParam } from "openclaw/plugin-sdk/channel-actions";
|
|
12
|
+
import { canonicalizeBase64 } from "openclaw/plugin-sdk/media-runtime";
|
|
13
13
|
import { normalizePollInput } from "openclaw/plugin-sdk/poll-runtime";
|
|
14
14
|
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
|
15
|
-
import { asDateTimestampMs,
|
|
15
|
+
import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
16
16
|
import { runCommandWithTimeout } from "openclaw/plugin-sdk/process-runtime";
|
|
17
17
|
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
18
18
|
import { detectBinary } from "openclaw/plugin-sdk/setup";
|
|
19
19
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
20
|
-
import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
21
20
|
import { parseAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
22
21
|
import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
|
|
23
22
|
import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
24
23
|
import { createCliPathTextInput, createDelegatedSetupWizardProxy, createDelegatedTextInputShouldPrompt, createPatchedAccountSetupAdapter, createSetupTranslator, promptParsedAllowFromForAccount, setAccountAllowFromForChannel, setSetupChannelEnabled as setSetupChannelEnabled$1 } from "openclaw/plugin-sdk/setup-runtime";
|
|
25
24
|
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
26
25
|
import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
27
|
-
import { addApprovalReactionHintToText, approvalReactionDecisionSetsMatch, buildApprovalReactionHint, createApprovalReactionTargetStore, extractApprovalReactionPromptBinding, hasApprovalReactionHintText, listApprovalReactionBindings, normalizeApprovalReactionDecision, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
28
|
-
import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
|
|
29
|
-
import { formatTrimmedAllowFromEntries as formatTrimmedAllowFromEntries$1 } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
30
|
-
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
31
|
-
import { DEFAULT_ACCOUNT_ID, getChatChannelMeta } from "openclaw/plugin-sdk/core";
|
|
32
|
-
import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
|
|
33
|
-
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
34
26
|
import { buildChannelGroupsScopeTree, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
|
|
35
|
-
//#region \0rolldown/runtime.js
|
|
36
|
-
var __defProp = Object.defineProperty;
|
|
37
|
-
var __exportAll = (all, no_symbols) => {
|
|
38
|
-
let target = {};
|
|
39
|
-
for (var name in all) __defProp(target, name, {
|
|
40
|
-
get: all[name],
|
|
41
|
-
enumerable: true
|
|
42
|
-
});
|
|
43
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
44
|
-
return target;
|
|
45
|
-
};
|
|
46
|
-
//#endregion
|
|
47
27
|
//#region extensions/imessage/src/message-action-reference.ts
|
|
48
28
|
async function resolveAuthorizedIMessageActionReference(params) {
|
|
49
29
|
const options = {
|
|
@@ -540,7 +520,7 @@ async function probeIMessage(timeoutMs, opts = {}) {
|
|
|
540
520
|
}
|
|
541
521
|
//#endregion
|
|
542
522
|
//#region extensions/imessage/src/actions.ts
|
|
543
|
-
const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-
|
|
523
|
+
const loadIMessageActionsRuntime = createLazyRuntimeNamedExport(() => import("./actions.runtime-BhggncbG.js"), "imessageActionsRuntime");
|
|
544
524
|
const log = createSubsystemLogger("channels/imessage");
|
|
545
525
|
const providerId = "imessage";
|
|
546
526
|
const SUPPORTED_ACTIONS = /* @__PURE__ */ new Set([...IMESSAGE_ACTION_NAMES, "upload-file"]);
|
|
@@ -701,7 +681,9 @@ function mapTapbackReaction(emoji) {
|
|
|
701
681
|
function decodeBase64Buffer(params, action) {
|
|
702
682
|
const base64Buffer = readStringParam(params, "buffer");
|
|
703
683
|
if (!base64Buffer) throw new Error(`iMessage ${action} requires buffer (base64) parameter.`);
|
|
704
|
-
|
|
684
|
+
const canonical = canonicalizeBase64(base64Buffer.replaceAll("-", "+").replaceAll("_", "/"));
|
|
685
|
+
if (!canonical) throw new Error(`iMessage ${action} buffer must be valid base64.`);
|
|
686
|
+
return Uint8Array.from(Buffer.from(canonical, "base64"));
|
|
705
687
|
}
|
|
706
688
|
const REPLY_ATTACHMENT_PATH_PARAM_NAMES = [
|
|
707
689
|
"filePath",
|
|
@@ -711,13 +693,12 @@ const REPLY_ATTACHMENT_PATH_PARAM_NAMES = [
|
|
|
711
693
|
"fileUrl"
|
|
712
694
|
];
|
|
713
695
|
function extractReplyAttachment(params) {
|
|
714
|
-
|
|
715
|
-
if (buffer) {
|
|
696
|
+
if (readStringParam(params, "buffer")) {
|
|
716
697
|
const filename = readStringParam(params, "filename") ?? "attachment.bin";
|
|
717
698
|
return {
|
|
718
699
|
spec: {
|
|
719
700
|
kind: "buffer",
|
|
720
|
-
buffer:
|
|
701
|
+
buffer: decodeBase64Buffer(params, "reply attachment"),
|
|
721
702
|
filename
|
|
722
703
|
},
|
|
723
704
|
sourceParam: "buffer"
|
|
@@ -1213,608 +1194,6 @@ const imessageApproval = createChannelApprovalAuth({
|
|
|
1213
1194
|
const getIMessageApprovalApprovers = imessageApproval.resolveApprovers;
|
|
1214
1195
|
const imessageApprovalAuth = imessageApproval.approvalAuth;
|
|
1215
1196
|
//#endregion
|
|
1216
|
-
//#region extensions/imessage/src/approval-target-keys.ts
|
|
1217
|
-
/** Strip the `p:<n>/` part prefix Messages puts on some GUIDs so keys match. */
|
|
1218
|
-
function normalizeIMessageGuid(value) {
|
|
1219
|
-
return value.trim().replace(/^p:\d+\//iu, "");
|
|
1220
|
-
}
|
|
1221
|
-
function chatIdToKeyValue(chatId) {
|
|
1222
|
-
if (chatId == null || chatId === "") return null;
|
|
1223
|
-
if (typeof chatId === "number") return Number.isFinite(chatId) && chatId > 0 ? String(chatId) : null;
|
|
1224
|
-
return chatId.trim() || null;
|
|
1225
|
-
}
|
|
1226
|
-
function enumerateConversationKeyForms(conversation) {
|
|
1227
|
-
const forms = [];
|
|
1228
|
-
const chatGuid = conversation.chatGuid?.trim();
|
|
1229
|
-
if (chatGuid) forms.push(`chat_guid:${chatGuid}`);
|
|
1230
|
-
const chatIdentifier = conversation.chatIdentifier?.trim();
|
|
1231
|
-
if (chatIdentifier) forms.push(`chat_identifier:${chatIdentifier}`);
|
|
1232
|
-
const chatIdValue = chatIdToKeyValue(conversation.chatId);
|
|
1233
|
-
if (chatIdValue) forms.push(`chat_id:${chatIdValue}`);
|
|
1234
|
-
const handle = conversation.handle?.trim();
|
|
1235
|
-
if (handle) forms.push(`handle:${handle}`);
|
|
1236
|
-
return forms;
|
|
1237
|
-
}
|
|
1238
|
-
function normalizeConversationKey(conversation) {
|
|
1239
|
-
return enumerateConversationKeyForms(conversation)[0];
|
|
1240
|
-
}
|
|
1241
|
-
/**
|
|
1242
|
-
* Index a binding under every key derivable from the conversation. Outbound and
|
|
1243
|
-
* inbound disagree about which key exists: send may only know
|
|
1244
|
-
* `{handle: "+1..."}` for a DM, while the bridge populates chat_guid on the
|
|
1245
|
-
* inbound event. Enumerating all forms keeps the two symmetric without making
|
|
1246
|
-
* callers guess which one the bridge will pick.
|
|
1247
|
-
*/
|
|
1248
|
-
function enumerateApprovalTargetKeys(params) {
|
|
1249
|
-
const accountId = params.accountId.trim();
|
|
1250
|
-
const messageId = params.messageId.trim();
|
|
1251
|
-
if (!accountId || !messageId) return [];
|
|
1252
|
-
return enumerateConversationKeyForms(params.conversation).map((form) => `${accountId}:${form}:${messageId}`);
|
|
1253
|
-
}
|
|
1254
|
-
function buildIMessageApprovalConversationKeyForTarget(to) {
|
|
1255
|
-
try {
|
|
1256
|
-
const target = parseIMessageTarget(to);
|
|
1257
|
-
if (target.kind === "chat_id") return { chatId: target.chatId };
|
|
1258
|
-
if (target.kind === "chat_guid") return { chatGuid: target.chatGuid };
|
|
1259
|
-
if (target.kind === "chat_identifier") return { chatIdentifier: target.chatIdentifier };
|
|
1260
|
-
const handle = normalizeIMessageHandle$1(target.to);
|
|
1261
|
-
return handle ? { handle } : null;
|
|
1262
|
-
} catch {
|
|
1263
|
-
return null;
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
/** Conversation key for an inbound event, mirroring the outbound key forms. */
|
|
1267
|
-
function buildIMessageApprovalConversationKeyForInbound(params) {
|
|
1268
|
-
return {
|
|
1269
|
-
...params.chatGuid?.trim() ? { chatGuid: params.chatGuid.trim() } : {},
|
|
1270
|
-
...params.chatIdentifier?.trim() ? { chatIdentifier: params.chatIdentifier.trim() } : {},
|
|
1271
|
-
...chatIdToKeyValue(params.chatId ?? void 0) ? { chatId: params.chatId } : {},
|
|
1272
|
-
...params.isGroup ? {} : { handle: params.actorHandle }
|
|
1273
|
-
};
|
|
1274
|
-
}
|
|
1275
|
-
//#endregion
|
|
1276
|
-
//#region extensions/imessage/src/monitor/reaction-context.ts
|
|
1277
|
-
const TAPBACK_TEXT_PATTERNS = [
|
|
1278
|
-
{
|
|
1279
|
-
prefix: "loved",
|
|
1280
|
-
action: "added",
|
|
1281
|
-
emoji: "❤️"
|
|
1282
|
-
},
|
|
1283
|
-
{
|
|
1284
|
-
prefix: "liked",
|
|
1285
|
-
action: "added",
|
|
1286
|
-
emoji: "👍"
|
|
1287
|
-
},
|
|
1288
|
-
{
|
|
1289
|
-
prefix: "disliked",
|
|
1290
|
-
action: "added",
|
|
1291
|
-
emoji: "👎"
|
|
1292
|
-
},
|
|
1293
|
-
{
|
|
1294
|
-
prefix: "laughed at",
|
|
1295
|
-
action: "added",
|
|
1296
|
-
emoji: "😂"
|
|
1297
|
-
},
|
|
1298
|
-
{
|
|
1299
|
-
prefix: "emphasized",
|
|
1300
|
-
action: "added",
|
|
1301
|
-
emoji: "‼️"
|
|
1302
|
-
},
|
|
1303
|
-
{
|
|
1304
|
-
prefix: "questioned",
|
|
1305
|
-
action: "added",
|
|
1306
|
-
emoji: "❓"
|
|
1307
|
-
},
|
|
1308
|
-
{
|
|
1309
|
-
prefix: "removed a heart from",
|
|
1310
|
-
action: "removed",
|
|
1311
|
-
emoji: "❤️"
|
|
1312
|
-
},
|
|
1313
|
-
{
|
|
1314
|
-
prefix: "removed a like from",
|
|
1315
|
-
action: "removed",
|
|
1316
|
-
emoji: "👍"
|
|
1317
|
-
},
|
|
1318
|
-
{
|
|
1319
|
-
prefix: "removed a dislike from",
|
|
1320
|
-
action: "removed",
|
|
1321
|
-
emoji: "👎"
|
|
1322
|
-
},
|
|
1323
|
-
{
|
|
1324
|
-
prefix: "removed a laugh from",
|
|
1325
|
-
action: "removed",
|
|
1326
|
-
emoji: "😂"
|
|
1327
|
-
},
|
|
1328
|
-
{
|
|
1329
|
-
prefix: "removed an emphasis from",
|
|
1330
|
-
action: "removed",
|
|
1331
|
-
emoji: "‼️"
|
|
1332
|
-
},
|
|
1333
|
-
{
|
|
1334
|
-
prefix: "removed a question from",
|
|
1335
|
-
action: "removed",
|
|
1336
|
-
emoji: "❓"
|
|
1337
|
-
}
|
|
1338
|
-
];
|
|
1339
|
-
function normalizeReactionValue(value) {
|
|
1340
|
-
return typeof value === "string" ? value.trim().replace(/^p:\d+\//iu, "") || void 0 : void 0;
|
|
1341
|
-
}
|
|
1342
|
-
function resolveReactionTargetGuidCandidates(...values) {
|
|
1343
|
-
const candidates = [];
|
|
1344
|
-
for (const value of values) {
|
|
1345
|
-
if (typeof value !== "string") continue;
|
|
1346
|
-
const raw = value.trim();
|
|
1347
|
-
if (!raw) continue;
|
|
1348
|
-
const normalized = raw.replace(/^p:\d+\//iu, "");
|
|
1349
|
-
for (const candidate of [normalized, raw]) if (candidate && !candidates.includes(candidate)) candidates.push(candidate);
|
|
1350
|
-
}
|
|
1351
|
-
return candidates;
|
|
1352
|
-
}
|
|
1353
|
-
function resolveTapbackTextContext(bodyText) {
|
|
1354
|
-
const lower = bodyText.toLowerCase();
|
|
1355
|
-
for (const pattern of TAPBACK_TEXT_PATTERNS) {
|
|
1356
|
-
if (!lower.startsWith(pattern.prefix)) continue;
|
|
1357
|
-
const afterPrefix = bodyText.slice(pattern.prefix.length).trim();
|
|
1358
|
-
if (!/^["“]/u.test(afterPrefix)) continue;
|
|
1359
|
-
return {
|
|
1360
|
-
action: pattern.action,
|
|
1361
|
-
emoji: pattern.emoji,
|
|
1362
|
-
targetText: afterPrefix.replace(/^["“]/u, "").replace(/["”]$/u, "").trim()
|
|
1363
|
-
};
|
|
1364
|
-
}
|
|
1365
|
-
return null;
|
|
1366
|
-
}
|
|
1367
|
-
function resolveIMessageReactionContext(message, bodyText) {
|
|
1368
|
-
if (message.is_reaction === true || message.is_tapback === true || typeof message.associated_message_type === "number" && Number.isFinite(message.associated_message_type) && message.associated_message_type >= 2e3 && message.associated_message_type < 4e3) {
|
|
1369
|
-
const targetGuids = resolveReactionTargetGuidCandidates(message.reacted_to_guid, message.associated_message_guid);
|
|
1370
|
-
return {
|
|
1371
|
-
action: message.is_reaction_add === false ? "removed" : "added",
|
|
1372
|
-
emoji: normalizeReactionValue(message.reaction_emoji) ?? normalizeReactionValue(message.reaction_type) ?? "reaction",
|
|
1373
|
-
targetGuid: targetGuids[0],
|
|
1374
|
-
targetGuids
|
|
1375
|
-
};
|
|
1376
|
-
}
|
|
1377
|
-
return resolveTapbackTextContext(bodyText);
|
|
1378
|
-
}
|
|
1379
|
-
//#endregion
|
|
1380
|
-
//#region extensions/imessage/src/approval-reactions.ts
|
|
1381
|
-
var approval_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
1382
|
-
addIMessageApprovalReactionHintToStructuredPayload: () => addIMessageApprovalReactionHintToStructuredPayload,
|
|
1383
|
-
addIMessageApprovalReactionHintToText: () => addIMessageApprovalReactionHintToText,
|
|
1384
|
-
appendIMessageApprovalReactionHintForOutboundMessage: () => appendIMessageApprovalReactionHintForOutboundMessage,
|
|
1385
|
-
buildIMessageApprovalConversationKeyForTarget: () => buildIMessageApprovalConversationKeyForTarget,
|
|
1386
|
-
buildIMessageApprovalReactionHint: () => buildIMessageApprovalReactionHint,
|
|
1387
|
-
clearIMessageApprovalReactionTargetsForTest: () => clearIMessageApprovalReactionTargetsForTest,
|
|
1388
|
-
extractIMessageApprovalPromptBinding: () => extractIMessageApprovalPromptBinding,
|
|
1389
|
-
handleIMessageApprovalReaction: () => handleIMessageApprovalReaction,
|
|
1390
|
-
listPendingIMessageApprovalReactionPollTargets: () => listPendingIMessageApprovalReactionPollTargets,
|
|
1391
|
-
maybeResolveIMessageApprovalReaction: () => maybeResolveIMessageApprovalReaction,
|
|
1392
|
-
registerIMessageApprovalReactionTarget: () => registerIMessageApprovalReactionTarget,
|
|
1393
|
-
registerIMessageApprovalReactionTargetForDeliveredPayload: () => registerIMessageApprovalReactionTargetForDeliveredPayload,
|
|
1394
|
-
registerIMessageApprovalReactionTargetForOutboundMessage: () => registerIMessageApprovalReactionTargetForOutboundMessage,
|
|
1395
|
-
resolveIMessageApprovalReactionTargetWithPersistence: () => resolveIMessageApprovalReactionTargetWithPersistence,
|
|
1396
|
-
unregisterIMessageApprovalReactionTarget: () => unregisterIMessageApprovalReactionTarget
|
|
1397
|
-
});
|
|
1398
|
-
const PERSISTENT_NAMESPACE = "imessage.approval-reactions";
|
|
1399
|
-
const PERSISTENT_MAX_ENTRIES = 1e3;
|
|
1400
|
-
const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
|
|
1401
|
-
const loadResolveApprovalOverGateway = createLazyRuntimeSurface(() => import("openclaw/plugin-sdk/approval-gateway-runtime"), (runtime) => runtime.resolveApprovalOverGateway);
|
|
1402
|
-
const pendingReactionPollTargets = /* @__PURE__ */ new Map();
|
|
1403
|
-
function prunePendingReactionPollTargets(nowMs = Date.now()) {
|
|
1404
|
-
for (const [key, target] of pendingReactionPollTargets.entries()) if (!isFutureDateTimestampMs(target.expiresAtMs, { nowMs })) pendingReactionPollTargets.delete(key);
|
|
1405
|
-
}
|
|
1406
|
-
function resolvePendingReactionPollExpiry(ttlMs) {
|
|
1407
|
-
const nowMs = asDateTimestampMs(Date.now());
|
|
1408
|
-
if (nowMs === void 0) return;
|
|
1409
|
-
const expiresAtMs = resolveExpiresAtMsFromDurationMs(ttlMs ?? DEFAULT_REACTION_TARGET_TTL_MS, { nowMs }) ?? resolveExpiresAtMsFromDurationMs(DEFAULT_REACTION_TARGET_TTL_MS, { nowMs });
|
|
1410
|
-
if (expiresAtMs === void 0) return;
|
|
1411
|
-
return {
|
|
1412
|
-
ttlMs: expiresAtMs - nowMs,
|
|
1413
|
-
expiresAtMs
|
|
1414
|
-
};
|
|
1415
|
-
}
|
|
1416
|
-
function mergePollTargetConversation(left, right) {
|
|
1417
|
-
return {
|
|
1418
|
-
chatGuid: left.chatGuid ?? right.chatGuid,
|
|
1419
|
-
chatIdentifier: left.chatIdentifier ?? right.chatIdentifier,
|
|
1420
|
-
chatId: left.chatId ?? right.chatId,
|
|
1421
|
-
handle: left.handle ?? right.handle
|
|
1422
|
-
};
|
|
1423
|
-
}
|
|
1424
|
-
function listPendingIMessageApprovalReactionPollTargets(params) {
|
|
1425
|
-
const accountId = params.accountId.trim();
|
|
1426
|
-
if (!accountId) return [];
|
|
1427
|
-
prunePendingReactionPollTargets();
|
|
1428
|
-
const targetByApprovalAndMessage = /* @__PURE__ */ new Map();
|
|
1429
|
-
for (const target of pendingReactionPollTargets.values()) {
|
|
1430
|
-
if (target.accountId !== accountId) continue;
|
|
1431
|
-
const key = `${target.approvalId}:${normalizeIMessageGuid(target.messageId)}`;
|
|
1432
|
-
const existing = targetByApprovalAndMessage.get(key);
|
|
1433
|
-
if (!existing) {
|
|
1434
|
-
targetByApprovalAndMessage.set(key, target);
|
|
1435
|
-
continue;
|
|
1436
|
-
}
|
|
1437
|
-
targetByApprovalAndMessage.set(key, {
|
|
1438
|
-
...existing,
|
|
1439
|
-
conversation: mergePollTargetConversation(existing.conversation, target.conversation),
|
|
1440
|
-
expiresAtMs: Math.max(existing.expiresAtMs, target.expiresAtMs)
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
|
-
return [...targetByApprovalAndMessage.values()];
|
|
1444
|
-
}
|
|
1445
|
-
const reportPersistentApprovalReactionError = createPluginStateErrorReporter(getOptionalIMessageRuntime, "imessage", "approval-reaction-state", "iMessage persistent approval reaction state failed");
|
|
1446
|
-
function reportApprovalBindingCorrelationMismatch(binding) {
|
|
1447
|
-
try {
|
|
1448
|
-
getOptionalIMessageRuntime()?.logging.getChildLogger({
|
|
1449
|
-
plugin: "imessage",
|
|
1450
|
-
feature: "approval-reaction-state"
|
|
1451
|
-
}).warn("iMessage approval prompt text failed binding correlation; tapbacks disabled", {
|
|
1452
|
-
approvalId: binding.approvalId,
|
|
1453
|
-
approvalKind: binding.approvalKind
|
|
1454
|
-
});
|
|
1455
|
-
} catch {}
|
|
1456
|
-
}
|
|
1457
|
-
function readPersistedTarget(value) {
|
|
1458
|
-
const target = value;
|
|
1459
|
-
if (!target || typeof target.approvalId !== "string" || !Array.isArray(target.allowedDecisions) || target.approvalKind !== "exec" && target.approvalKind !== "plugin") return null;
|
|
1460
|
-
const allowedDecisions = target.allowedDecisions.map((valueValue) => typeof valueValue === "string" ? normalizeApprovalReactionDecision(valueValue) : null).filter((valueLocal) => Boolean(valueLocal));
|
|
1461
|
-
if (allowedDecisions.length === 0) return null;
|
|
1462
|
-
return {
|
|
1463
|
-
approvalId: target.approvalId,
|
|
1464
|
-
approvalKind: target.approvalKind,
|
|
1465
|
-
allowedDecisions
|
|
1466
|
-
};
|
|
1467
|
-
}
|
|
1468
|
-
const imessageApprovalReactionTargets = createApprovalReactionTargetStore({
|
|
1469
|
-
namespace: PERSISTENT_NAMESPACE,
|
|
1470
|
-
maxEntries: PERSISTENT_MAX_ENTRIES,
|
|
1471
|
-
defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
|
|
1472
|
-
openStore: (params) => getOptionalIMessageRuntime()?.state.openKeyedStore(params),
|
|
1473
|
-
logPersistentError: reportPersistentApprovalReactionError,
|
|
1474
|
-
readPersistedTarget
|
|
1475
|
-
});
|
|
1476
|
-
function listIMessageApprovalReactionBindings(allowedDecisions) {
|
|
1477
|
-
return listApprovalReactionBindings({ allowedDecisions });
|
|
1478
|
-
}
|
|
1479
|
-
function buildIMessageApprovalReactionHint(allowedDecisions) {
|
|
1480
|
-
return buildApprovalReactionHint({ allowedDecisions });
|
|
1481
|
-
}
|
|
1482
|
-
function addIMessageApprovalReactionHintToText(params) {
|
|
1483
|
-
return addApprovalReactionHintToText(params);
|
|
1484
|
-
}
|
|
1485
|
-
function appendIMessageApprovalReactionHintForOutboundMessage(text) {
|
|
1486
|
-
if (hasApprovalReactionHintText(text)) return text;
|
|
1487
|
-
const binding = extractIMessageApprovalPromptBinding(text);
|
|
1488
|
-
if (!binding) return text;
|
|
1489
|
-
return addIMessageApprovalReactionHintToText({
|
|
1490
|
-
text,
|
|
1491
|
-
allowedDecisions: binding.allowedDecisions
|
|
1492
|
-
});
|
|
1493
|
-
}
|
|
1494
|
-
const IMESSAGE_APPROVAL_DELIVERY_BINDING_KEY = "imessageApprovalReactionBindingV1";
|
|
1495
|
-
function visibleApprovalBindingMatches(text, binding, options) {
|
|
1496
|
-
if (!text) return false;
|
|
1497
|
-
const lines = text.split(/\r?\n/).map((line) => line.replace(/\*\*/g, "").trim());
|
|
1498
|
-
const normalizedHeaders = lines.map((line) => line.replace(/^[^A-Za-z0-9]*/, ""));
|
|
1499
|
-
const hasKindHeader = binding.approvalKind === "exec" ? lines.includes("Approval required.") || normalizedHeaders.some((line) => /^Exec approval required$/i.test(line)) : normalizedHeaders.some((line) => /^Plugin approval required$/i.test(line));
|
|
1500
|
-
const hasId = lines.includes(`ID: ${binding.approvalId}`) || lines.includes(`Full id: \`${binding.approvalId}\``) || lines.includes(`Full id: ${binding.approvalId}`);
|
|
1501
|
-
if (!hasKindHeader || !hasId) return false;
|
|
1502
|
-
const visibleDecisions = [];
|
|
1503
|
-
for (const line of lines) {
|
|
1504
|
-
const match = line.match(APPROVE_COMMAND_LINE_RE);
|
|
1505
|
-
const approvalId = match?.[1];
|
|
1506
|
-
const decisionsText = match?.[2];
|
|
1507
|
-
if (!approvalId || !decisionsText || approvalId !== binding.approvalId && approvalId !== binding.approvalSlug) continue;
|
|
1508
|
-
for (const token of decisionsText.split(/[\s|,]+/)) {
|
|
1509
|
-
const decision = normalizeApprovalReactionDecision(token);
|
|
1510
|
-
if (decision && !visibleDecisions.includes(decision)) visibleDecisions.push(decision);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
if (!approvalReactionDecisionSetsMatch(binding.allowedDecisions, visibleDecisions)) return false;
|
|
1514
|
-
if (!options.requireReactionHint) return true;
|
|
1515
|
-
const hint = buildIMessageApprovalReactionHint(binding.allowedDecisions);
|
|
1516
|
-
return Boolean(hint && text.includes(hint));
|
|
1517
|
-
}
|
|
1518
|
-
/** Preserve a validated typed approval binding until the iMessage GUID is known. */
|
|
1519
|
-
function addIMessageApprovalReactionHintToStructuredPayload(params) {
|
|
1520
|
-
const metadata = readApprovalReactionPresentationBinding({
|
|
1521
|
-
payload: params.payload,
|
|
1522
|
-
requireApprovalSlug: true,
|
|
1523
|
-
trimApprovalId: true
|
|
1524
|
-
});
|
|
1525
|
-
const text = params.payload.text;
|
|
1526
|
-
if (metadata?.approvalKind !== params.approvalKind || !text) return null;
|
|
1527
|
-
if (!visibleApprovalBindingMatches(text, metadata, { requireReactionHint: false })) {
|
|
1528
|
-
reportApprovalBindingCorrelationMismatch(metadata);
|
|
1529
|
-
return null;
|
|
1530
|
-
}
|
|
1531
|
-
return {
|
|
1532
|
-
...params.payload,
|
|
1533
|
-
text: addIMessageApprovalReactionHintToText({
|
|
1534
|
-
text,
|
|
1535
|
-
allowedDecisions: metadata.allowedDecisions
|
|
1536
|
-
}),
|
|
1537
|
-
channelData: {
|
|
1538
|
-
...params.payload.channelData,
|
|
1539
|
-
[IMESSAGE_APPROVAL_DELIVERY_BINDING_KEY]: {
|
|
1540
|
-
version: 1,
|
|
1541
|
-
approvalId: metadata.approvalId,
|
|
1542
|
-
approvalSlug: metadata.approvalSlug,
|
|
1543
|
-
approvalKind: metadata.approvalKind,
|
|
1544
|
-
allowedDecisions: metadata.allowedDecisions
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1549
|
-
const APPROVE_COMMAND_LINE_RE = /\/approve(?:@[^\s]+)?\s+([A-Za-z0-9][A-Za-z0-9._:-]*)\s+(.+)$/i;
|
|
1550
|
-
function extractIMessageApprovalPromptBinding(text) {
|
|
1551
|
-
return extractApprovalReactionPromptBinding({ text });
|
|
1552
|
-
}
|
|
1553
|
-
function registerIMessageApprovalReactionTarget(params) {
|
|
1554
|
-
const approvalId = params.approvalId.trim();
|
|
1555
|
-
const allowedDecisions = listIMessageApprovalReactionBindings(params.allowedDecisions).map((binding) => binding.decision);
|
|
1556
|
-
if (!approvalId || params.approvalKind !== "exec" && params.approvalKind !== "plugin" || allowedDecisions.length === 0) return null;
|
|
1557
|
-
const target = {
|
|
1558
|
-
approvalId,
|
|
1559
|
-
approvalKind: params.approvalKind,
|
|
1560
|
-
allowedDecisions
|
|
1561
|
-
};
|
|
1562
|
-
const expiry = resolvePendingReactionPollExpiry(params.ttlMs);
|
|
1563
|
-
if (!expiry) return null;
|
|
1564
|
-
const keys = enumerateApprovalTargetKeys({
|
|
1565
|
-
accountId: params.accountId,
|
|
1566
|
-
conversation: params.conversation,
|
|
1567
|
-
messageId: params.messageId
|
|
1568
|
-
});
|
|
1569
|
-
if (keys.length === 0) return null;
|
|
1570
|
-
for (const key of keys) {
|
|
1571
|
-
imessageApprovalReactionTargets.register(key, target, { ttlMs: expiry.ttlMs });
|
|
1572
|
-
pendingReactionPollTargets.set(key, {
|
|
1573
|
-
accountId: params.accountId,
|
|
1574
|
-
conversation: params.conversation,
|
|
1575
|
-
messageId: params.messageId,
|
|
1576
|
-
approvalId,
|
|
1577
|
-
approvalKind: params.approvalKind,
|
|
1578
|
-
allowedDecisions,
|
|
1579
|
-
expiresAtMs: expiry.expiresAtMs
|
|
1580
|
-
});
|
|
1581
|
-
}
|
|
1582
|
-
prunePendingReactionPollTargets();
|
|
1583
|
-
return target;
|
|
1584
|
-
}
|
|
1585
|
-
function registerIMessageApprovalReactionTargetForOutboundMessage(params) {
|
|
1586
|
-
const binding = extractIMessageApprovalPromptBinding(params.text);
|
|
1587
|
-
if (!binding || binding.approvalKind !== params.approvalKind) return false;
|
|
1588
|
-
return Boolean(registerIMessageApprovalReactionTarget({
|
|
1589
|
-
accountId: params.accountId,
|
|
1590
|
-
conversation: params.conversation,
|
|
1591
|
-
messageId: params.messageId,
|
|
1592
|
-
approvalId: binding.approvalId,
|
|
1593
|
-
approvalKind: params.approvalKind,
|
|
1594
|
-
allowedDecisions: binding.allowedDecisions,
|
|
1595
|
-
ttlMs: params.ttlMs
|
|
1596
|
-
}));
|
|
1597
|
-
}
|
|
1598
|
-
function listDeliveredIMessageApprovalGuids(params) {
|
|
1599
|
-
const deliveries = [];
|
|
1600
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1601
|
-
for (const result of params.results) {
|
|
1602
|
-
if (result.channel !== "imessage") continue;
|
|
1603
|
-
const guid = typeof result.meta?.imessageMessageGuid === "string" ? result.meta.imessageMessageGuid.trim() : "";
|
|
1604
|
-
const visibleText = result.meta?.imessageVisibleText;
|
|
1605
|
-
if (!guid || /^\d+$/.test(guid) || seen.has(guid) || typeof visibleText !== "string") continue;
|
|
1606
|
-
seen.add(guid);
|
|
1607
|
-
deliveries.push({
|
|
1608
|
-
guid,
|
|
1609
|
-
visibleText
|
|
1610
|
-
});
|
|
1611
|
-
}
|
|
1612
|
-
if (!visibleApprovalBindingMatches(deliveries.map((delivery) => delivery.visibleText).join("\n"), params.binding, { requireReactionHint: true })) {
|
|
1613
|
-
if (params.results.some((result) => result.channel === "imessage")) reportApprovalBindingCorrelationMismatch(params.binding);
|
|
1614
|
-
return [];
|
|
1615
|
-
}
|
|
1616
|
-
return deliveries.map((delivery) => delivery.guid);
|
|
1617
|
-
}
|
|
1618
|
-
/** Bind a typed forwarded approval after iMessage returns the stable tapback GUID. */
|
|
1619
|
-
function registerIMessageApprovalReactionTargetForDeliveredPayload(params) {
|
|
1620
|
-
if (params.target.channel.trim().toLowerCase() !== "imessage") return false;
|
|
1621
|
-
const binding = readApprovalReactionDeliveredBinding({
|
|
1622
|
-
payload: params.payload,
|
|
1623
|
-
channelDataKey: IMESSAGE_APPROVAL_DELIVERY_BINDING_KEY,
|
|
1624
|
-
requireApprovalSlug: true,
|
|
1625
|
-
trimApprovalId: true
|
|
1626
|
-
});
|
|
1627
|
-
if (!binding) return false;
|
|
1628
|
-
const conversation = buildIMessageApprovalConversationKeyForTarget(params.target.to);
|
|
1629
|
-
if (!conversation) return false;
|
|
1630
|
-
let registered = false;
|
|
1631
|
-
for (const messageId of listDeliveredIMessageApprovalGuids({
|
|
1632
|
-
binding,
|
|
1633
|
-
results: params.results
|
|
1634
|
-
})) registered = Boolean(registerIMessageApprovalReactionTarget({
|
|
1635
|
-
accountId: params.accountId,
|
|
1636
|
-
conversation,
|
|
1637
|
-
messageId,
|
|
1638
|
-
approvalId: binding.approvalId,
|
|
1639
|
-
approvalKind: binding.approvalKind,
|
|
1640
|
-
allowedDecisions: binding.allowedDecisions,
|
|
1641
|
-
ttlMs: params.ttlMs
|
|
1642
|
-
})) || registered;
|
|
1643
|
-
return registered;
|
|
1644
|
-
}
|
|
1645
|
-
function unregisterIMessageApprovalReactionTarget(params) {
|
|
1646
|
-
const keys = enumerateApprovalTargetKeys(params);
|
|
1647
|
-
for (const key of keys) {
|
|
1648
|
-
imessageApprovalReactionTargets.delete(key);
|
|
1649
|
-
pendingReactionPollTargets.delete(key);
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
function resolveTarget(params) {
|
|
1653
|
-
const target = resolveTypedApprovalReactionTarget(params);
|
|
1654
|
-
return target ? {
|
|
1655
|
-
approvalId: target.approvalId,
|
|
1656
|
-
approvalKind: target.approvalKind,
|
|
1657
|
-
decision: target.decision
|
|
1658
|
-
} : null;
|
|
1659
|
-
}
|
|
1660
|
-
function formatCanonicalApprovalTerminalState(approval) {
|
|
1661
|
-
const decision = approval.status === "allowed" || approval.status === "denied" ? ` decision=${approval.decision}` : "";
|
|
1662
|
-
return `status=${approval.status}${decision} reason=${approval.reason}`;
|
|
1663
|
-
}
|
|
1664
|
-
async function resolveIMessageApprovalReactionTargetWithPersistence(params) {
|
|
1665
|
-
const keys = enumerateApprovalTargetKeys(params);
|
|
1666
|
-
for (const key of keys) {
|
|
1667
|
-
const target = resolveTarget({
|
|
1668
|
-
target: await imessageApprovalReactionTargets.lookup(key),
|
|
1669
|
-
reactionKey: params.reactionKey
|
|
1670
|
-
});
|
|
1671
|
-
if (target) return target;
|
|
1672
|
-
}
|
|
1673
|
-
return null;
|
|
1674
|
-
}
|
|
1675
|
-
function readApprovalReactionEvent(message, bodyText) {
|
|
1676
|
-
const reaction = resolveIMessageReactionContext(message, bodyText);
|
|
1677
|
-
if (!reaction) return null;
|
|
1678
|
-
const reactionKey = reaction.emoji.trim();
|
|
1679
|
-
const candidates = (reaction.targetGuids ?? []).map((value) => value.trim()).filter((value) => value.length > 0);
|
|
1680
|
-
const primary = reaction.targetGuid?.trim() || candidates[0] || "";
|
|
1681
|
-
const messageIdCandidates = candidates.length > 0 ? candidates : primary ? [primary] : [];
|
|
1682
|
-
const actorHandle = normalizeIMessageHandle$1((message.sender ?? "").trim());
|
|
1683
|
-
if (!reactionKey || !primary || !actorHandle) return null;
|
|
1684
|
-
const conversation = buildIMessageApprovalConversationKeyForInbound({
|
|
1685
|
-
chatGuid: message.chat_guid,
|
|
1686
|
-
chatIdentifier: message.chat_identifier,
|
|
1687
|
-
chatId: message.chat_id,
|
|
1688
|
-
isGroup: message.is_group,
|
|
1689
|
-
actorHandle
|
|
1690
|
-
});
|
|
1691
|
-
if (!normalizeConversationKey(conversation)) return null;
|
|
1692
|
-
return {
|
|
1693
|
-
conversation,
|
|
1694
|
-
messageId: primary,
|
|
1695
|
-
messageIdCandidates,
|
|
1696
|
-
actorHandle,
|
|
1697
|
-
reactionKey,
|
|
1698
|
-
action: reaction.action
|
|
1699
|
-
};
|
|
1700
|
-
}
|
|
1701
|
-
async function handleIMessageApprovalReaction(params) {
|
|
1702
|
-
const event = readApprovalReactionEvent(params.message, params.bodyText);
|
|
1703
|
-
if (!event) return {
|
|
1704
|
-
handled: false,
|
|
1705
|
-
stopPolling: false
|
|
1706
|
-
};
|
|
1707
|
-
if (event.action === "removed") return {
|
|
1708
|
-
handled: false,
|
|
1709
|
-
stopPolling: false
|
|
1710
|
-
};
|
|
1711
|
-
let target = null;
|
|
1712
|
-
let matchedMessageId = null;
|
|
1713
|
-
for (const candidate of event.messageIdCandidates) {
|
|
1714
|
-
target = await resolveIMessageApprovalReactionTargetWithPersistence({
|
|
1715
|
-
accountId: params.accountId,
|
|
1716
|
-
conversation: event.conversation,
|
|
1717
|
-
messageId: candidate,
|
|
1718
|
-
reactionKey: event.reactionKey
|
|
1719
|
-
});
|
|
1720
|
-
if (target) {
|
|
1721
|
-
matchedMessageId = candidate;
|
|
1722
|
-
break;
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
if (!target) return {
|
|
1726
|
-
handled: false,
|
|
1727
|
-
stopPolling: false
|
|
1728
|
-
};
|
|
1729
|
-
if (getIMessageApprovalApprovers({
|
|
1730
|
-
cfg: params.cfg,
|
|
1731
|
-
accountId: params.accountId
|
|
1732
|
-
}).length === 0) {
|
|
1733
|
-
params.logVerboseMessage?.(`imessage: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
|
|
1734
|
-
return {
|
|
1735
|
-
handled: true,
|
|
1736
|
-
stopPolling: false
|
|
1737
|
-
};
|
|
1738
|
-
}
|
|
1739
|
-
if (!imessageApprovalAuth.authorizeActorAction({
|
|
1740
|
-
cfg: params.cfg,
|
|
1741
|
-
accountId: params.accountId,
|
|
1742
|
-
senderId: event.actorHandle,
|
|
1743
|
-
action: "approve",
|
|
1744
|
-
approvalKind: target.approvalKind
|
|
1745
|
-
}).authorized) {
|
|
1746
|
-
params.logVerboseMessage?.(`imessage: approval reaction denied id=${target.approvalId} sender=${event.actorHandle}`);
|
|
1747
|
-
return {
|
|
1748
|
-
handled: true,
|
|
1749
|
-
stopPolling: false
|
|
1750
|
-
};
|
|
1751
|
-
}
|
|
1752
|
-
const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
|
|
1753
|
-
try {
|
|
1754
|
-
const result = await resolveApprovalOverGateway({
|
|
1755
|
-
cfg: params.cfg,
|
|
1756
|
-
approvalId: target.approvalId,
|
|
1757
|
-
approvalKind: target.approvalKind,
|
|
1758
|
-
decision: target.decision,
|
|
1759
|
-
channel: "imessage",
|
|
1760
|
-
accountId: params.accountId,
|
|
1761
|
-
senderId: event.actorHandle,
|
|
1762
|
-
gatewayUrl: params.gatewayUrl,
|
|
1763
|
-
...params.gatewayRuntime ? { gatewayRuntime: params.gatewayRuntime } : {}
|
|
1764
|
-
});
|
|
1765
|
-
for (const candidate of event.messageIdCandidates) unregisterIMessageApprovalReactionTarget({
|
|
1766
|
-
accountId: params.accountId,
|
|
1767
|
-
conversation: event.conversation,
|
|
1768
|
-
messageId: candidate
|
|
1769
|
-
});
|
|
1770
|
-
const outcome = result.applied ? "resolved" : "already resolved";
|
|
1771
|
-
params.logVerboseMessage?.(`imessage: approval reaction ${outcome} id=${target.approvalId} sender=${event.actorHandle} ${formatCanonicalApprovalTerminalState(result.approval)} via messageId=${matchedMessageId ?? event.messageId}`);
|
|
1772
|
-
return {
|
|
1773
|
-
handled: true,
|
|
1774
|
-
stopPolling: true,
|
|
1775
|
-
stopPollingReason: "resolved"
|
|
1776
|
-
};
|
|
1777
|
-
} catch (error) {
|
|
1778
|
-
if (isApprovalNotFoundError(error)) {
|
|
1779
|
-
for (const candidate of event.messageIdCandidates) unregisterIMessageApprovalReactionTarget({
|
|
1780
|
-
accountId: params.accountId,
|
|
1781
|
-
conversation: event.conversation,
|
|
1782
|
-
messageId: candidate
|
|
1783
|
-
});
|
|
1784
|
-
params.logVerboseMessage?.(`imessage: approval reaction ignored for expired approval id=${target.approvalId} sender=${event.actorHandle}`);
|
|
1785
|
-
return {
|
|
1786
|
-
handled: true,
|
|
1787
|
-
stopPolling: true,
|
|
1788
|
-
stopPollingReason: "not-found"
|
|
1789
|
-
};
|
|
1790
|
-
}
|
|
1791
|
-
try {
|
|
1792
|
-
getOptionalIMessageRuntime()?.logging.getChildLogger({
|
|
1793
|
-
plugin: "imessage",
|
|
1794
|
-
feature: "approval-reactions"
|
|
1795
|
-
}).warn("approval reaction failed", {
|
|
1796
|
-
approvalId: target.approvalId,
|
|
1797
|
-
senderId: event.actorHandle,
|
|
1798
|
-
error: String(error)
|
|
1799
|
-
});
|
|
1800
|
-
} catch {}
|
|
1801
|
-
params.logVerboseMessage?.(`imessage: approval reaction failed id=${target.approvalId} sender=${event.actorHandle}: ${String(error)}`);
|
|
1802
|
-
return {
|
|
1803
|
-
handled: true,
|
|
1804
|
-
stopPolling: true,
|
|
1805
|
-
stopPollingReason: "resolver-error"
|
|
1806
|
-
};
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
async function maybeResolveIMessageApprovalReaction(params) {
|
|
1810
|
-
return (await handleIMessageApprovalReaction(params)).handled;
|
|
1811
|
-
}
|
|
1812
|
-
function clearIMessageApprovalReactionTargetsForTest() {
|
|
1813
|
-
imessageApprovalReactionTargets.clearForTest();
|
|
1814
|
-
pendingReactionPollTargets.clear();
|
|
1815
|
-
loadResolveApprovalOverGateway.clear();
|
|
1816
|
-
}
|
|
1817
|
-
//#endregion
|
|
1818
1197
|
//#region extensions/imessage/src/normalize.ts
|
|
1819
1198
|
const SERVICE_PREFIXES = [
|
|
1820
1199
|
"imessage:",
|
|
@@ -1822,14 +1201,7 @@ const SERVICE_PREFIXES = [
|
|
|
1822
1201
|
"auto:"
|
|
1823
1202
|
];
|
|
1824
1203
|
const CHAT_TARGET_PREFIX_RE = /^(chat_id:|chatid:|chat:|chat_guid:|chatguid:|guid:|chat_identifier:|chatidentifier:|chatident:)/i;
|
|
1825
|
-
function
|
|
1826
|
-
const trimmed = params.raw.trim();
|
|
1827
|
-
if (!trimmed) return false;
|
|
1828
|
-
if (params.prefixPattern.test(trimmed)) return true;
|
|
1829
|
-
if (trimmed.includes("@")) return true;
|
|
1830
|
-
return (params.phonePattern ?? /^\+?\d{3,}$/).test(trimmed);
|
|
1831
|
-
}
|
|
1832
|
-
function normalizeIMessageHandle(raw) {
|
|
1204
|
+
function normalizeIMessageHandle(raw, allowContactName = false) {
|
|
1833
1205
|
const trimmed = raw.trim();
|
|
1834
1206
|
if (!trimmed) return "";
|
|
1835
1207
|
const lowered = normalizeLowercaseStringOrEmpty(trimmed);
|
|
@@ -1845,16 +1217,16 @@ function normalizeIMessageHandle(raw) {
|
|
|
1845
1217
|
if (trimmed.includes("@")) return normalizeLowercaseStringOrEmpty(trimmed);
|
|
1846
1218
|
const bareChatIdentifier = normalizeBareIMessageChatIdentifier(trimmed);
|
|
1847
1219
|
if (bareChatIdentifier) return `chat_identifier:${bareChatIdentifier}`;
|
|
1848
|
-
const normalized = normalizeE164(trimmed);
|
|
1220
|
+
const normalized = isIMessagePhoneLikeHandle(trimmed) ? normalizeE164(trimmed) : "";
|
|
1849
1221
|
if (normalized) return normalized;
|
|
1850
|
-
return trimmed.replace(/\s+/g, "");
|
|
1222
|
+
return allowContactName ? trimmed.replace(/\s+/g, "") : "";
|
|
1851
1223
|
}
|
|
1852
1224
|
function normalizeIMessageMessagingTarget(raw) {
|
|
1853
1225
|
const trimmed = normalizeOptionalString(raw);
|
|
1854
1226
|
if (!trimmed) return;
|
|
1855
1227
|
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
|
1856
1228
|
for (const prefix of SERVICE_PREFIXES) if (lower.startsWith(prefix)) {
|
|
1857
|
-
const normalizedHandle = normalizeIMessageHandle(trimmed.slice(prefix.length).trim());
|
|
1229
|
+
const normalizedHandle = normalizeIMessageHandle(trimmed.slice(prefix.length).trim(), true);
|
|
1858
1230
|
if (!normalizedHandle) return;
|
|
1859
1231
|
if (CHAT_TARGET_PREFIX_RE.test(normalizedHandle)) return normalizedHandle;
|
|
1860
1232
|
return `${prefix}${normalizedHandle}`;
|
|
@@ -1866,10 +1238,7 @@ function looksLikeIMessageTargetId(raw) {
|
|
|
1866
1238
|
if (!trimmed) return false;
|
|
1867
1239
|
if (CHAT_TARGET_PREFIX_RE.test(trimmed)) return true;
|
|
1868
1240
|
if (normalizeBareIMessageChatIdentifier(trimmed)) return true;
|
|
1869
|
-
return
|
|
1870
|
-
raw: trimmed,
|
|
1871
|
-
prefixPattern: /^(imessage:|sms:|auto:)/i
|
|
1872
|
-
});
|
|
1241
|
+
return /^(imessage:|sms:|auto:)/i.test(trimmed) || trimmed.includes("@") || isIMessagePhoneLikeHandle(trimmed) && Boolean(normalizeE164(trimmed));
|
|
1873
1242
|
}
|
|
1874
1243
|
//#endregion
|
|
1875
1244
|
//#region extensions/imessage/src/conversation-id-core.ts
|
|
@@ -1929,4 +1298,4 @@ function resolveIMessageGroupToolPolicy(params) {
|
|
|
1929
1298
|
});
|
|
1930
1299
|
}
|
|
1931
1300
|
//#endregion
|
|
1932
|
-
export {
|
|
1301
|
+
export { imessageDmPolicy as _, normalizeIMessageAcpConversationId as a, isAutoManagedIMessageCliPath as b, normalizeIMessageMessagingTarget as c, imessageMessageActions as d, probeIMessage as f, imessageCompletionNote as g, createIMessageSetupWizardProxy as h, matchIMessageAcpConversation as i, getIMessageApprovalApprovers as l, createIMessageCliPathTextInput as m, resolveIMessageGroupToolPolicy as n, resolveIMessageConversationIdFromTarget as o, IMESSAGE_INSTALL_COMMAND as p, resolveIMessageInboundConversationId as r, looksLikeIMessageTargetId as s, resolveIMessageGroupRequireMention as t, imessageApprovalAuth as u, imessageSetupContract as v, normalizeIMessageCliPathForSetup as x, imessageSetupStatusBase as y };
|