@openclaw/whatsapp 2026.7.2-beta.7 → 2026.8.1-beta.3
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-CSqLvCY5.js → accounts-BX2fZUyR.js} +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/{action-runtime-BzfDFPbH.js → action-runtime-pM-ExU0l.js} +2 -2
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{agent-tools-login-DE9MU98T.js → agent-tools-login-BjRpD-JQ.js} +5 -4
- package/dist/api.js +69 -127
- package/dist/{approval-handler.runtime-DrA59QSA.js → approval-handler.runtime-CkMMvUjk.js} +4 -4
- package/dist/{approval-reactions-Cu66aYdq.js → approval-reactions-Jyr1JaAK.js} +29 -81
- package/dist/auth-presence.js +1 -1
- package/dist/{auth-store-DcEpIOmE.js → auth-store-CtpBqH5S.js} +82 -18
- package/dist/call-tool-api.js +1 -1
- package/dist/{channel-Dg62olhy.js → channel-DRMYRfZ8.js} +56 -160
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-J_YtyMGX.js → channel-react-action-CstrR0CT.js} +14 -12
- package/dist/{channel.runtime-BP0xNmLi.js → channel.runtime-X3JC2gaq.js} +4 -4
- package/dist/channel.setup-DhBBhbQv.js +14 -0
- package/dist/{connection-controller-BOB2MVKY.js → connection-controller-CIYuBJrs.js} +2 -3
- package/dist/contract-api.js +2 -3
- package/dist/{creds-files-B1kSWtBg.js → creds-files-W6B3EMZ8.js} +17 -1
- package/dist/{directory-config-DalGrfGN.js → directory-config-P7_3U73Z.js} +3 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +37 -2
- package/dist/{group-session-key-DVMZlO3x.js → group-session-key-DmFc_Cqi.js} +23 -4
- package/dist/light-runtime-api.js +2 -2
- package/dist/{login-CvY2Dhch.js → login-BkpKpndm.js} +4 -4
- package/dist/{login-qr-Bncpb6js.js → login-qr-1dpv6jjT.js} +4 -4
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-CfkaUSL2.js → monitor-IzwQKizW.js} +545 -549
- package/dist/{question-reactions-CRsnyoMK.js → question-reactions-D3eAeB0i.js} +29 -78
- package/dist/runtime-api.js +9 -9
- package/dist/runtime-group-policy-DeSRFXEV.js +11 -0
- package/dist/{send-D37ddk22.js → send-CwvTU4RI.js} +298 -23
- package/dist/{send-api-7wk6eQyW.js → send-api-obOSm2cC.js} +126 -137
- package/dist/setup-entry.js +1 -8
- package/dist/{setup-finalize-BZucx24W.js → setup-finalize-n4K2I2gJ.js} +4 -4
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BkVcd769.js → setup-surface-Cwn3zyxK.js} +3 -3
- package/dist/{shared-CAxd15bp.js → shared-wg42NKFB.js} +13 -8
- package/dist/{socket-close-DridEuzz.js → socket-close-2T0_jZTN.js} +4 -10
- package/openclaw.plugin.json +4 -0
- package/package.json +4 -5
- package/skills/wacli/SKILL.md +8 -1
- package/dist/access-control-pZcxTmd5.js +0 -363
- package/dist/approval-resolver-DoeBBt22.js +0 -16
- package/dist/channel.setup-pMwNVkCA.js +0 -19
- package/dist/identity-CPrT5aEU.js +0 -76
- package/dist/legacy-state-migrations-api.js +0 -2
- package/dist/state-migrations-CAMTrs2U.js +0 -33
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as listConfiguredAccountIds, r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
|
|
2
|
-
import { n as hasWebCredsRegularFileSync, r as hasWebCredsSync } from "./creds-files-
|
|
2
|
+
import { n as hasWebCredsRegularFileSync, r as hasWebCredsSync } from "./creds-files-W6B3EMZ8.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { DEFAULT_ACCOUNT_ID, mergeAccountConfig, normalizeAccountId, resolveAccountEntry, resolveMergedAccountConfig, resolveUserPath } from "openclaw/plugin-sdk/account-core";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as handleWhatsAppAction } from "./action-runtime-
|
|
1
|
+
import { t as handleWhatsAppAction } from "./action-runtime-pM-ExU0l.js";
|
|
2
2
|
export { handleWhatsAppAction };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount } from "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-1GqbT1uX.js";
|
|
3
|
-
import { r as sendReactionWhatsApp,
|
|
3
|
+
import { r as sendReactionWhatsApp, v as resolveWhatsAppReactionLevel } from "./send-CwvTU4RI.js";
|
|
4
4
|
import { ToolAuthorizationError, createActionGate, jsonResult, readReactionParams, readStringParam } from "openclaw/plugin-sdk/channel-actions";
|
|
5
5
|
//#region extensions/whatsapp/src/action-runtime-target-auth.ts
|
|
6
6
|
function resolveAuthorizedWhatsAppOutboundTarget(params) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as handleWhatsAppAction } from "./action-runtime-
|
|
1
|
+
import { t as handleWhatsAppAction } from "./action-runtime-pM-ExU0l.js";
|
|
2
2
|
export { handleWhatsAppAction };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { startWebLoginWithQr, waitForWebLogin } from "./login-qr-runtime.js";
|
|
2
2
|
import "./login-qr-api.js";
|
|
3
3
|
import { optionalPositiveIntegerSchema, readPositiveIntegerParam } from "openclaw/plugin-sdk/channel-actions";
|
|
4
|
+
import { hasNonEmptyString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
5
|
import { Type } from "typebox";
|
|
5
6
|
//#region extensions/whatsapp/src/agent-tools-login.ts
|
|
6
7
|
const QR_DATA_URL_MAX_LENGTH = 16384;
|
|
7
|
-
function
|
|
8
|
-
return
|
|
8
|
+
function readLoginStringPreservingWhitespace(value) {
|
|
9
|
+
return hasNonEmptyString(value) ? value : void 0;
|
|
9
10
|
}
|
|
10
11
|
function createWhatsAppLoginTool() {
|
|
11
12
|
return {
|
|
@@ -42,13 +43,13 @@ function createWhatsAppLoginTool() {
|
|
|
42
43
|
};
|
|
43
44
|
};
|
|
44
45
|
const action = args?.action ?? "start";
|
|
45
|
-
const accountId =
|
|
46
|
+
const accountId = readLoginStringPreservingWhitespace(args.accountId);
|
|
46
47
|
const timeoutMs = readPositiveIntegerParam(args, "timeoutMs");
|
|
47
48
|
if (action === "wait") {
|
|
48
49
|
const result = await waitForWebLogin({
|
|
49
50
|
accountId,
|
|
50
51
|
timeoutMs,
|
|
51
|
-
currentQrDataUrl:
|
|
52
|
+
currentQrDataUrl: readLoginStringPreservingWhitespace(args.currentQrDataUrl)
|
|
52
53
|
});
|
|
53
54
|
if (result.qrDataUrl) return renderQrReply({
|
|
54
55
|
message: result.message,
|
package/dist/api.js
CHANGED
|
@@ -1,108 +1,63 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount, i as listWhatsAppAuthDirs, n as hasAnyWhatsAppAuth, o as resolveWhatsAppAuthDir, r as listEnabledWhatsAppAccounts, s as resolveWhatsAppMediaMaxBytes, t as DEFAULT_WHATSAPP_MEDIA_MAX_MB } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount, i as listWhatsAppAuthDirs, n as hasAnyWhatsAppAuth, o as resolveWhatsAppAuthDir, r as listEnabledWhatsAppAccounts, s as resolveWhatsAppMediaMaxBytes, t as DEFAULT_WHATSAPP_MEDIA_MAX_MB } from "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
|
|
3
3
|
import { a as normalizeWhatsAppAllowFromEntries, c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, r as isWhatsAppUserTarget, s as normalizeWhatsAppMessagingTarget, t as isWhatsAppGroupJid } from "./normalize-target-CugRyONv.js";
|
|
4
4
|
import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-1GqbT1uX.js";
|
|
5
5
|
import { c as toWhatsappJid, i as markdownToWhatsApp, l as toWhatsappJidWithLid, n as isSelfChatMode, r as jidToE164, s as resolveJidToE164, t as assertWebChannel } from "./targets-runtime-TMk0lGuy.js";
|
|
6
6
|
import { n as resolveUserPath, t as normalizeE164 } from "./text-runtime-CaKLhowd.js";
|
|
7
|
-
import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, t as whatsappPlugin } from "./channel-
|
|
8
|
-
import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-
|
|
7
|
+
import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, t as whatsappPlugin } from "./channel-DRMYRfZ8.js";
|
|
8
|
+
import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-wg42NKFB.js";
|
|
9
9
|
import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
|
|
10
|
-
import { t as whatsappSetupPlugin } from "./channel.setup-
|
|
10
|
+
import { t as whatsappSetupPlugin } from "./channel.setup-DhBBhbQv.js";
|
|
11
11
|
import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-HU41RHGI.js";
|
|
12
|
-
import { a as waitForWaConnection, o as DEFAULT_WHATSAPP_SOCKET_TIMING, r as createWaSocket, s as createWhatsAppSocketOperationTimeoutAdapter } from "./socket-close-
|
|
12
|
+
import { a as waitForWaConnection, o as DEFAULT_WHATSAPP_SOCKET_TIMING, r as createWaSocket, s as createWhatsAppSocketOperationTimeoutAdapter } from "./socket-close-2T0_jZTN.js";
|
|
13
13
|
import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
|
|
14
|
-
import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
14
|
+
import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-P7_3U73Z.js";
|
|
15
|
+
import { _ as resolveInboundMediaMimetype, c as extractContextInfo, m as findMessageSection, o as describeReplyContext, p as extractText, t as createWebSendApi, u as extractLocationData } from "./send-api-obOSm2cC.js";
|
|
16
|
+
import { asBoolean, isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
17
|
import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound";
|
|
18
18
|
//#region extensions/whatsapp/src/qa-driver.runtime.ts
|
|
19
|
-
function isRecord(value) {
|
|
20
|
-
return Boolean(value && typeof value === "object");
|
|
21
|
-
}
|
|
22
|
-
function readString(value) {
|
|
23
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
24
|
-
}
|
|
25
|
-
function readBoolean(value) {
|
|
26
|
-
return typeof value === "boolean" ? value : void 0;
|
|
27
|
-
}
|
|
28
|
-
function findMessageSection(message, sectionNames) {
|
|
29
|
-
if (!isRecord(message)) return;
|
|
30
|
-
const queue = [{
|
|
31
|
-
depth: 0,
|
|
32
|
-
value: message
|
|
33
|
-
}];
|
|
34
|
-
const seen = /* @__PURE__ */ new Set();
|
|
35
|
-
while (queue.length > 0) {
|
|
36
|
-
const current = queue.shift();
|
|
37
|
-
if (!current || seen.has(current.value)) continue;
|
|
38
|
-
seen.add(current.value);
|
|
39
|
-
for (const sectionName of sectionNames) {
|
|
40
|
-
const section = current.value[sectionName];
|
|
41
|
-
if (isRecord(section)) return section;
|
|
42
|
-
}
|
|
43
|
-
if (current.depth >= 4) continue;
|
|
44
|
-
for (const wrapperName of [
|
|
45
|
-
"botInvokeMessage",
|
|
46
|
-
"documentWithCaptionMessage",
|
|
47
|
-
"ephemeralMessage",
|
|
48
|
-
"groupMentionedMessage",
|
|
49
|
-
"viewOnceMessage",
|
|
50
|
-
"viewOnceMessageV2",
|
|
51
|
-
"viewOnceMessageV2Extension"
|
|
52
|
-
]) {
|
|
53
|
-
const wrapper = current.value[wrapperName];
|
|
54
|
-
if (isRecord(wrapper) && isRecord(wrapper.message)) queue.push({
|
|
55
|
-
depth: current.depth + 1,
|
|
56
|
-
value: wrapper.message
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
19
|
function readReaction(message) {
|
|
62
|
-
const reaction = findMessageSection(message, ["reactionMessage"]);
|
|
20
|
+
const reaction = findMessageSection(message ?? void 0, ["reactionMessage"])?.value;
|
|
63
21
|
if (!reaction) return;
|
|
64
|
-
const emoji =
|
|
22
|
+
const emoji = normalizeOptionalString(reaction.text) ?? "";
|
|
65
23
|
const key = isRecord(reaction.key) ? reaction.key : void 0;
|
|
66
24
|
return {
|
|
67
25
|
emoji,
|
|
68
|
-
fromMe:
|
|
69
|
-
messageId:
|
|
70
|
-
participant:
|
|
26
|
+
fromMe: asBoolean(key?.fromMe),
|
|
27
|
+
messageId: normalizeOptionalString(key?.id),
|
|
28
|
+
participant: normalizeOptionalString(key?.participant)
|
|
71
29
|
};
|
|
72
30
|
}
|
|
73
31
|
function readPoll(message) {
|
|
74
|
-
const poll = findMessageSection(message, [
|
|
32
|
+
const poll = findMessageSection(message ?? void 0, [
|
|
75
33
|
"pollCreationMessage",
|
|
76
34
|
"pollCreationMessageV2",
|
|
77
|
-
"pollCreationMessageV3"
|
|
78
|
-
|
|
35
|
+
"pollCreationMessageV3",
|
|
36
|
+
"pollCreationMessageV5"
|
|
37
|
+
])?.value;
|
|
79
38
|
if (!poll) return;
|
|
80
39
|
return {
|
|
81
|
-
options: (Array.isArray(poll.options) ? poll.options : []).map((option) => isRecord(option) ?
|
|
82
|
-
question:
|
|
40
|
+
options: (Array.isArray(poll.options) ? poll.options : []).map((option) => isRecord(option) ? normalizeOptionalString(option.optionName) : void 0).filter((option) => Boolean(option)),
|
|
41
|
+
question: normalizeOptionalString(poll.name)
|
|
83
42
|
};
|
|
84
43
|
}
|
|
85
44
|
function readMedia(message) {
|
|
86
|
-
const
|
|
87
|
-
for (const sectionName of [
|
|
45
|
+
const media = findMessageSection(message ?? void 0, [
|
|
88
46
|
"imageMessage",
|
|
89
47
|
"videoMessage",
|
|
48
|
+
"ptvMessage",
|
|
90
49
|
"audioMessage",
|
|
91
50
|
"documentMessage",
|
|
92
51
|
"stickerMessage"
|
|
93
|
-
])
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
fileName: readString(section.fileName),
|
|
99
|
-
mediaType: resolveInboundMediaMimetype(mediaMessage)
|
|
100
|
-
};
|
|
101
|
-
}
|
|
52
|
+
]);
|
|
53
|
+
return media ? {
|
|
54
|
+
fileName: normalizeOptionalString(media.value.fileName),
|
|
55
|
+
mediaType: resolveInboundMediaMimetype({ [media.name]: media.value })
|
|
56
|
+
} : void 0;
|
|
102
57
|
}
|
|
103
58
|
function readQuotedMessage(message) {
|
|
104
59
|
const contextInfo = extractContextInfo(message.message ?? void 0);
|
|
105
|
-
const replyContext = describeReplyContext(message.message);
|
|
60
|
+
const replyContext = describeReplyContext(message.message ?? void 0);
|
|
106
61
|
if (!contextInfo && !replyContext) return;
|
|
107
62
|
if (!contextInfo?.stanzaId && !contextInfo?.participant && !replyContext?.body) return;
|
|
108
63
|
return {
|
|
@@ -114,7 +69,7 @@ function readQuotedMessage(message) {
|
|
|
114
69
|
function normalizeObservedMessage(message, authDir) {
|
|
115
70
|
if (message.key.fromMe) return null;
|
|
116
71
|
const extractedText = extractText(message.message ?? void 0);
|
|
117
|
-
const location = extractLocationData(message.message);
|
|
72
|
+
const location = extractLocationData(message.message ?? void 0);
|
|
118
73
|
const text = [extractedText, location ? formatLocationText(location) : void 0].filter(Boolean).join("\n").trim() || void 0;
|
|
119
74
|
const reaction = readReaction(message.message);
|
|
120
75
|
const poll = readPoll(message.message);
|
|
@@ -141,15 +96,6 @@ function normalizeObservedMessage(message, authDir) {
|
|
|
141
96
|
text: text ?? ""
|
|
142
97
|
};
|
|
143
98
|
}
|
|
144
|
-
function closeSocket(sock) {
|
|
145
|
-
const maybeEnd = sock.end;
|
|
146
|
-
if (typeof maybeEnd === "function") {
|
|
147
|
-
maybeEnd.call(sock);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const maybeClose = sock.ws?.close;
|
|
151
|
-
if (typeof maybeClose === "function") maybeClose.call(sock.ws);
|
|
152
|
-
}
|
|
153
99
|
function createConnectionClosedError(update) {
|
|
154
100
|
const reason = update.lastDisconnect?.error;
|
|
155
101
|
const status = getStatusCode(reason);
|
|
@@ -160,32 +106,26 @@ function createConnectionClosedError(update) {
|
|
|
160
106
|
async function startWhatsAppQaDriverSession(params) {
|
|
161
107
|
const sock = await createWaSocket(false, false, { authDir: params.authDir });
|
|
162
108
|
const observedMessages = [];
|
|
163
|
-
const
|
|
164
|
-
|
|
109
|
+
const waiters = /* @__PURE__ */ new Set();
|
|
110
|
+
let pendingNotificationsWaiter;
|
|
165
111
|
let closed = false;
|
|
166
112
|
let closedError;
|
|
167
113
|
let receivedPendingNotifications = false;
|
|
168
114
|
const removeWaiter = (waiter) => {
|
|
169
|
-
|
|
170
|
-
if (index >= 0) waiters.splice(index, 1);
|
|
115
|
+
waiters.delete(waiter);
|
|
171
116
|
clearTimeout(waiter.timeout);
|
|
172
117
|
};
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
118
|
+
const settlePendingNotifications = (error) => {
|
|
119
|
+
const waiter = pendingNotificationsWaiter;
|
|
120
|
+
if (!waiter) return;
|
|
121
|
+
pendingNotificationsWaiter = void 0;
|
|
176
122
|
clearTimeout(waiter.timeout);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (receivedPendingNotifications) return;
|
|
180
|
-
receivedPendingNotifications = true;
|
|
181
|
-
for (const waiter of pendingNotificationsWaiters.slice()) {
|
|
182
|
-
removePendingNotificationsWaiter(waiter);
|
|
183
|
-
waiter.resolve();
|
|
184
|
-
}
|
|
123
|
+
if (error) waiter.reject(error);
|
|
124
|
+
else waiter.resolve();
|
|
185
125
|
};
|
|
186
126
|
const observe = (message) => {
|
|
187
127
|
observedMessages.push(message);
|
|
188
|
-
for (const waiter of waiters
|
|
128
|
+
for (const waiter of waiters) {
|
|
189
129
|
if (!waiter.predicate(message)) continue;
|
|
190
130
|
removeWaiter(waiter);
|
|
191
131
|
waiter.resolve(message);
|
|
@@ -198,28 +138,27 @@ async function startWhatsAppQaDriverSession(params) {
|
|
|
198
138
|
}
|
|
199
139
|
};
|
|
200
140
|
const onConnectionUpdate = (event) => {
|
|
201
|
-
if (event.receivedPendingNotifications === true)
|
|
141
|
+
if (event.receivedPendingNotifications === true) {
|
|
142
|
+
receivedPendingNotifications = true;
|
|
143
|
+
settlePendingNotifications();
|
|
144
|
+
}
|
|
202
145
|
if (event.connection === "close") closeSessionResources(createConnectionClosedError(event));
|
|
203
146
|
};
|
|
204
147
|
const removeMessageListener = () => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
evWithOff.off?.("connection.update", onConnectionUpdate);
|
|
148
|
+
sock.ev.off("messages.upsert", onMessagesUpsert);
|
|
149
|
+
sock.ev.off("connection.update", onConnectionUpdate);
|
|
208
150
|
};
|
|
209
151
|
const closeSessionResources = (waiterError) => {
|
|
210
152
|
if (closed) return;
|
|
211
153
|
closed = true;
|
|
212
154
|
closedError = waiterError;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (waiterError) waiter.reject(waiterError);
|
|
216
|
-
}
|
|
217
|
-
for (const waiter of waiters.slice()) {
|
|
155
|
+
settlePendingNotifications(waiterError);
|
|
156
|
+
for (const waiter of waiters) {
|
|
218
157
|
removeWaiter(waiter);
|
|
219
158
|
if (waiterError) waiter.reject(waiterError);
|
|
220
159
|
}
|
|
221
160
|
removeMessageListener();
|
|
222
|
-
|
|
161
|
+
sock.end(void 0);
|
|
223
162
|
};
|
|
224
163
|
sock.ev.on("messages.upsert", onMessagesUpsert);
|
|
225
164
|
sock.ev.on("connection.update", onConnectionUpdate);
|
|
@@ -235,15 +174,14 @@ async function startWhatsAppQaDriverSession(params) {
|
|
|
235
174
|
return;
|
|
236
175
|
}
|
|
237
176
|
const timeoutMs = params.connectionTimeoutMs ?? 45e3;
|
|
238
|
-
|
|
177
|
+
pendingNotificationsWaiter = {
|
|
239
178
|
resolve,
|
|
240
179
|
reject,
|
|
241
180
|
timeout: setTimeout(() => {
|
|
242
|
-
|
|
181
|
+
pendingNotificationsWaiter = void 0;
|
|
243
182
|
reject(/* @__PURE__ */ new Error(`timed out after ${timeoutMs}ms waiting for WhatsApp QA driver pending notifications`));
|
|
244
183
|
}, timeoutMs)
|
|
245
184
|
};
|
|
246
|
-
pendingNotificationsWaiters.push(waiter);
|
|
247
185
|
});
|
|
248
186
|
} catch (error) {
|
|
249
187
|
closeSessionResources(error instanceof Error ? error : /* @__PURE__ */ new Error("failed starting WhatsApp QA driver session"));
|
|
@@ -261,26 +199,26 @@ async function startWhatsAppQaDriverSession(params) {
|
|
|
261
199
|
getObservedMessages() {
|
|
262
200
|
return [...observedMessages];
|
|
263
201
|
},
|
|
264
|
-
|
|
265
|
-
return
|
|
202
|
+
sendContact(to, contact) {
|
|
203
|
+
return toMessageIdResult(sendApi.sendContact(to, contact));
|
|
266
204
|
},
|
|
267
|
-
|
|
268
|
-
return
|
|
205
|
+
sendLocation(to, location) {
|
|
206
|
+
return toMessageIdResult(sendApi.sendLocation(to, location));
|
|
269
207
|
},
|
|
270
|
-
|
|
271
|
-
return
|
|
208
|
+
sendMedia(to, text, mediaBuffer, mediaType, options) {
|
|
209
|
+
return toMessageIdResult(sendApi.sendMessage(to, text, mediaBuffer, mediaType, options));
|
|
272
210
|
},
|
|
273
|
-
|
|
274
|
-
return
|
|
211
|
+
sendPoll(to, poll) {
|
|
212
|
+
return toMessageIdResult(sendApi.sendPoll(to, poll));
|
|
275
213
|
},
|
|
276
|
-
|
|
277
|
-
return
|
|
214
|
+
sendReaction(chatJid, messageId, emoji, options) {
|
|
215
|
+
return toMessageIdResult(sendApi.sendReaction(chatJid, messageId, emoji, options.fromMe, options.participant));
|
|
278
216
|
},
|
|
279
|
-
|
|
280
|
-
return
|
|
217
|
+
sendSticker(to, stickerBuffer, options) {
|
|
218
|
+
return toMessageIdResult(sendApi.sendSticker(to, stickerBuffer, options));
|
|
281
219
|
},
|
|
282
|
-
|
|
283
|
-
return
|
|
220
|
+
sendText(to, text, options) {
|
|
221
|
+
return toMessageIdResult(sendApi.sendMessage(to, text, void 0, void 0, options));
|
|
284
222
|
},
|
|
285
223
|
async waitForMessage(paramsLocal) {
|
|
286
224
|
const predicate = (message) => (!paramsLocal.observedAfter || new Date(message.observedAt).getTime() >= paramsLocal.observedAfter.getTime()) && paramsLocal.match(message);
|
|
@@ -297,10 +235,14 @@ async function startWhatsAppQaDriverSession(params) {
|
|
|
297
235
|
reject(/* @__PURE__ */ new Error("timed out waiting for WhatsApp QA driver message"));
|
|
298
236
|
}, paramsLocal.timeoutMs)
|
|
299
237
|
};
|
|
300
|
-
waiters.
|
|
238
|
+
waiters.add(waiter);
|
|
301
239
|
});
|
|
302
240
|
}
|
|
303
241
|
};
|
|
304
242
|
}
|
|
243
|
+
async function toMessageIdResult(pending) {
|
|
244
|
+
const { messageId } = await pending;
|
|
245
|
+
return { messageId };
|
|
246
|
+
}
|
|
305
247
|
//#endregion
|
|
306
|
-
export { DEFAULT_WEB_MEDIA_BYTES, DEFAULT_WHATSAPP_MEDIA_MAX_MB, WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, assertWebChannel, hasAnyWhatsAppAuth, isSelfChatMode, isWhatsAppGroupJid, isWhatsAppUserTarget, jidToE164, listEnabledWhatsAppAccounts, listAccountIds as listWhatsAppAccountIds, listWhatsAppAuthDirs, listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig, looksLikeWhatsAppTargetId, markdownToWhatsApp, normalizeE164, normalizeWhatsAppAllowFromEntries, normalizeWhatsAppMessagingTarget, normalizeWhatsAppTarget, resolveDefaultWhatsAppAccountId, resolveJidToE164, resolveUserPath, resolveWhatsAppAccount, resolveWhatsAppAuthDir, resolveWhatsAppGroupRequireMention, resolveWhatsAppGroupToolPolicy, resolveWhatsAppMediaMaxBytes, resolveWhatsAppOutboundTarget, startWhatsAppQaDriverSession, toWhatsappJid, toWhatsappJidWithLid,
|
|
248
|
+
export { DEFAULT_WEB_MEDIA_BYTES, DEFAULT_WHATSAPP_MEDIA_MAX_MB, WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, assertWebChannel, hasAnyWhatsAppAuth, isSelfChatMode, isWhatsAppGroupJid, isWhatsAppUserTarget, jidToE164, listEnabledWhatsAppAccounts, listAccountIds as listWhatsAppAccountIds, listWhatsAppAuthDirs, listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig, looksLikeWhatsAppTargetId, markdownToWhatsApp, normalizeE164, normalizeWhatsAppAllowFromEntries, normalizeWhatsAppMessagingTarget, normalizeWhatsAppTarget, resolveDefaultWhatsAppAccountId, resolveJidToE164, resolveUserPath, resolveWhatsAppAccount, resolveWhatsAppAuthDir, resolveWhatsAppGroupRequireMention, resolveWhatsAppGroupToolPolicy, resolveWhatsAppMediaMaxBytes, resolveWhatsAppOutboundTarget, startWhatsAppQaDriverSession, toWhatsappJid, toWhatsappJidWithLid, whatsappCommandPolicy, whatsappPlugin, whatsappSetupPlugin };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import "./accounts-
|
|
1
|
+
import "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
|
|
3
3
|
import { s as normalizeWhatsAppMessagingTarget } from "./normalize-target-CugRyONv.js";
|
|
4
|
-
import { i as sendTypingWhatsApp, t as sendMessageWhatsApp } from "./send-
|
|
4
|
+
import { i as sendTypingWhatsApp, t as sendMessageWhatsApp } from "./send-CwvTU4RI.js";
|
|
5
5
|
import { i as getWhatsAppRuntime } from "./runtime-BLlToOi6.js";
|
|
6
6
|
import "./normalize-C7Hkc_vE.js";
|
|
7
|
-
import { i as unregisterWhatsAppApprovalReactionTarget, r as registerWhatsAppApprovalReactionTarget } from "./approval-reactions-
|
|
7
|
+
import { i as unregisterWhatsAppApprovalReactionTarget, r as registerWhatsAppApprovalReactionTarget } from "./approval-reactions-Jyr1JaAK.js";
|
|
8
8
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
9
9
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
10
|
-
import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
11
10
|
import { buildApprovalReactionPendingContent } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
12
11
|
import { buildChannelApprovalExpiredText, buildChannelApprovalResolvedText, createChannelApprovalNativeRuntimeAdapter, resolvePreparedApprovalAccountId } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
12
|
+
import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
13
13
|
//#region extensions/whatsapp/src/approval-handler.runtime.ts
|
|
14
14
|
const log = createSubsystemLogger("whatsapp/approvals");
|
|
15
15
|
function buildPendingPayload(params) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
2
|
+
import { a as resolveWhatsAppAccount } from "./accounts-BX2fZUyR.js";
|
|
3
3
|
import { n as getOptionalWhatsAppRuntime } from "./runtime-BLlToOi6.js";
|
|
4
|
-
import { c as getWhatsAppApprovalApprovers, l as whatsappApprovalAuth } from "./group-session-key-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { c as getWhatsAppApprovalApprovers, l as whatsappApprovalAuth } from "./group-session-key-DmFc_Cqi.js";
|
|
5
|
+
import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
6
|
+
import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
|
|
7
|
+
import { approvalReactionDecisionSetsMatch, buildApprovalReactionDeliveredBindingMarker, createApprovalReactionTargetStore, listApprovalReactionBindings, readApprovalReactionDecisionList, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
8
|
+
import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
|
|
7
9
|
//#region extensions/whatsapp/src/approval-reactions.ts
|
|
8
10
|
var approval_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
9
11
|
clearWhatsAppApprovalReactionTargetsForTest: () => clearWhatsAppApprovalReactionTargetsForTest,
|
|
@@ -18,16 +20,15 @@ const PERSISTENT_NAMESPACE = "whatsapp.approval-reactions";
|
|
|
18
20
|
const PERSISTENT_MAX_ENTRIES = 1e3;
|
|
19
21
|
const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
|
|
20
22
|
const DELIVERY_BINDING_CHANNEL_DATA_KEY = "whatsappApprovalReactionBindingV1";
|
|
21
|
-
const
|
|
23
|
+
const loadResolveApprovalOverGateway = createLazyRuntimeSurface(() => import("openclaw/plugin-sdk/approval-gateway-runtime"), (runtime) => runtime.resolveApprovalOverGateway);
|
|
22
24
|
const whatsappApprovalReactionTargets = createApprovalReactionTargetStore({
|
|
23
25
|
namespace: PERSISTENT_NAMESPACE,
|
|
24
26
|
maxEntries: PERSISTENT_MAX_ENTRIES,
|
|
25
27
|
defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
|
|
26
28
|
openStore: (storeParams) => getOptionalWhatsAppRuntime()?.state.openKeyedStore(storeParams),
|
|
27
|
-
logPersistentError:
|
|
29
|
+
logPersistentError: createPluginStateErrorReporter(getOptionalWhatsAppRuntime, "whatsapp", "approval-reaction-state", "WhatsApp persistent approval reaction state failed"),
|
|
28
30
|
readPersistedTarget
|
|
29
31
|
});
|
|
30
|
-
const loadApprovalResolver = resolverRuntimeLoader;
|
|
31
32
|
function buildReactionTargetKey(params) {
|
|
32
33
|
const accountId = params.accountId.trim();
|
|
33
34
|
const remoteJid = params.remoteJid.trim();
|
|
@@ -39,14 +40,6 @@ function addCandidateRemoteJid(target, value) {
|
|
|
39
40
|
const remoteJid = value?.trim();
|
|
40
41
|
if (remoteJid && !target.includes(remoteJid)) target.push(remoteJid);
|
|
41
42
|
}
|
|
42
|
-
function reportPersistentApprovalReactionError(error) {
|
|
43
|
-
try {
|
|
44
|
-
getOptionalWhatsAppRuntime()?.logging.getChildLogger({
|
|
45
|
-
plugin: "whatsapp",
|
|
46
|
-
feature: "approval-reaction-state"
|
|
47
|
-
}).warn("WhatsApp persistent approval reaction state failed", { error: String(error) });
|
|
48
|
-
} catch {}
|
|
49
|
-
}
|
|
50
43
|
function reportApprovalBindingCorrelationMismatch(binding) {
|
|
51
44
|
try {
|
|
52
45
|
getOptionalWhatsAppRuntime()?.logging.getChildLogger({
|
|
@@ -60,58 +53,17 @@ function reportApprovalBindingCorrelationMismatch(binding) {
|
|
|
60
53
|
}
|
|
61
54
|
function readPersistedTarget(target) {
|
|
62
55
|
const value = target;
|
|
63
|
-
if (!value || typeof value.approvalId !== "string" ||
|
|
56
|
+
if (!value || typeof value.approvalId !== "string" || value.approvalKind !== "exec" && value.approvalKind !== "plugin") return null;
|
|
57
|
+
const allowedDecisions = readApprovalReactionDecisionList(value.allowedDecisions);
|
|
58
|
+
if (!allowedDecisions) return null;
|
|
64
59
|
return {
|
|
65
60
|
approvalId: value.approvalId,
|
|
66
61
|
approvalKind: value.approvalKind,
|
|
67
|
-
allowedDecisions
|
|
62
|
+
allowedDecisions
|
|
68
63
|
};
|
|
69
64
|
}
|
|
70
|
-
function listWhatsAppApprovalReactionBindings(allowedDecisions) {
|
|
71
|
-
return listApprovalReactionBindings({ allowedDecisions });
|
|
72
|
-
}
|
|
73
65
|
const APPROVAL_ID_LINE_RE = /^\s*ID:\s*(\S(?:.*\S)?)\s*$/i;
|
|
74
66
|
const APPROVAL_KIND_LINE_RE = /^\s*(?:\S+\s+)?(Exec|Plugin) approval required\s*$/i;
|
|
75
|
-
function isApprovalDecision(value) {
|
|
76
|
-
return value === "allow-once" || value === "allow-always" || value === "deny";
|
|
77
|
-
}
|
|
78
|
-
function readStrictDecisionList(value) {
|
|
79
|
-
if (!Array.isArray(value) || value.length === 0 || !value.every(isApprovalDecision)) return null;
|
|
80
|
-
return new Set(value).size === value.length ? [...value] : null;
|
|
81
|
-
}
|
|
82
|
-
function readStrictApprovalMetadata(payload) {
|
|
83
|
-
const value = payload.channelData?.execApproval;
|
|
84
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
85
|
-
const record = value;
|
|
86
|
-
const approvalId = record.approvalId;
|
|
87
|
-
const approvalKind = record.approvalKind;
|
|
88
|
-
const allowedDecisions = readStrictDecisionList(record.allowedDecisions);
|
|
89
|
-
if (typeof approvalId !== "string" || !approvalId || approvalId !== approvalId.trim() || approvalKind !== "exec" && approvalKind !== "plugin" || !allowedDecisions) return null;
|
|
90
|
-
return {
|
|
91
|
-
version: 1,
|
|
92
|
-
approvalId,
|
|
93
|
-
approvalKind,
|
|
94
|
-
allowedDecisions
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
function listTypedApprovalActions(presentation) {
|
|
98
|
-
return presentation.blocks.flatMap((block) => {
|
|
99
|
-
if (block.type === "buttons") return block.buttons.flatMap((button) => button.action?.type === "approval" ? [button.action] : []);
|
|
100
|
-
return [];
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
function decisionSetsMatch(left, right) {
|
|
104
|
-
return left.length === right.length && left.every((decision) => right.includes(decision));
|
|
105
|
-
}
|
|
106
|
-
function readTypedApprovalDeliveryBinding(params) {
|
|
107
|
-
const metadata = readStrictApprovalMetadata(params.payload);
|
|
108
|
-
if (!metadata) return null;
|
|
109
|
-
const actions = listTypedApprovalActions(params.presentation);
|
|
110
|
-
if (actions.length === 0 || actions.some((action) => action.approvalId !== metadata.approvalId || action.approvalKind !== metadata.approvalKind)) return null;
|
|
111
|
-
const actionDecisions = actions.map((action) => action.decision);
|
|
112
|
-
if (new Set(actionDecisions).size !== actionDecisions.length || !decisionSetsMatch(metadata.allowedDecisions, actionDecisions)) return null;
|
|
113
|
-
return metadata;
|
|
114
|
-
}
|
|
115
67
|
function visibleApprovalBindingMatches(text, binding) {
|
|
116
68
|
const lines = (text ?? "").split(/\r?\n/).map((line) => line.replace(/\*\*/g, ""));
|
|
117
69
|
const kindMatches = lines.map((line) => line.match(APPROVAL_KIND_LINE_RE)).filter((match) => Boolean(match));
|
|
@@ -131,27 +83,18 @@ function visibleApprovalBindingMatches(text, binding) {
|
|
|
131
83
|
decisionLines.push(decisionLine);
|
|
132
84
|
cursor += 1;
|
|
133
85
|
}
|
|
134
|
-
const knownBindings =
|
|
86
|
+
const knownBindings = listApprovalReactionBindings({ allowedDecisions: [
|
|
135
87
|
"allow-once",
|
|
136
88
|
"allow-always",
|
|
137
89
|
"deny"
|
|
138
|
-
]);
|
|
139
|
-
const
|
|
140
|
-
if (!
|
|
141
|
-
return
|
|
142
|
-
}
|
|
143
|
-
function readDeliveredApprovalBinding(payload) {
|
|
144
|
-
const metadata = readStrictApprovalMetadata(payload);
|
|
145
|
-
const value = payload.channelData?.[DELIVERY_BINDING_CHANNEL_DATA_KEY];
|
|
146
|
-
if (!metadata || !value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
147
|
-
const record = value;
|
|
148
|
-
const allowedDecisions = readStrictDecisionList(record.allowedDecisions);
|
|
149
|
-
if (record.version !== 1 || record.approvalId !== metadata.approvalId || record.approvalKind !== metadata.approvalKind || !allowedDecisions || !decisionSetsMatch(metadata.allowedDecisions, allowedDecisions)) return null;
|
|
150
|
-
return metadata;
|
|
90
|
+
] });
|
|
91
|
+
const decisions = readApprovalReactionDecisionList(decisionLines.map((line) => knownBindings.find((entry) => `${entry.emoji} ${entry.label}` === line)?.decision));
|
|
92
|
+
if (!decisions) return false;
|
|
93
|
+
return approvalReactionDecisionSetsMatch(binding.allowedDecisions, decisions);
|
|
151
94
|
}
|
|
152
95
|
/** Preserve a validated typed approval binding until the platform message id is known. */
|
|
153
96
|
function prepareWhatsAppApprovalPayloadForDelivery(params) {
|
|
154
|
-
const binding =
|
|
97
|
+
const binding = readApprovalReactionPresentationBinding(params);
|
|
155
98
|
if (!binding) return null;
|
|
156
99
|
if (!visibleApprovalBindingMatches(params.payload.text, binding)) {
|
|
157
100
|
reportApprovalBindingCorrelationMismatch(binding);
|
|
@@ -161,14 +104,14 @@ function prepareWhatsAppApprovalPayloadForDelivery(params) {
|
|
|
161
104
|
...params.payload,
|
|
162
105
|
channelData: {
|
|
163
106
|
...params.payload.channelData,
|
|
164
|
-
[DELIVERY_BINDING_CHANNEL_DATA_KEY]: binding
|
|
107
|
+
[DELIVERY_BINDING_CHANNEL_DATA_KEY]: buildApprovalReactionDeliveredBindingMarker(binding)
|
|
165
108
|
}
|
|
166
109
|
};
|
|
167
110
|
}
|
|
168
111
|
function registerWhatsAppApprovalReactionTarget(params) {
|
|
169
112
|
const key = buildReactionTargetKey(params);
|
|
170
113
|
const approvalId = params.approvalId.trim();
|
|
171
|
-
const allowedDecisions =
|
|
114
|
+
const allowedDecisions = listApprovalReactionBindings({ allowedDecisions: params.allowedDecisions }).map((binding) => binding.decision);
|
|
172
115
|
if (!key || !approvalId || params.approvalKind !== "exec" && params.approvalKind !== "plugin" || allowedDecisions.length === 0) return null;
|
|
173
116
|
const target = {
|
|
174
117
|
approvalId,
|
|
@@ -208,7 +151,10 @@ function listWhatsAppDeliveredMessageIdentities(results) {
|
|
|
208
151
|
/** Bind generic forwarded approvals to the exact WhatsApp messages accepted by Baileys. */
|
|
209
152
|
function registerWhatsAppApprovalReactionTargetForDeliveredPayload(params) {
|
|
210
153
|
if (params.target.channel.trim().toLowerCase() !== "whatsapp") return false;
|
|
211
|
-
const binding =
|
|
154
|
+
const binding = readApprovalReactionDeliveredBinding({
|
|
155
|
+
payload: params.payload,
|
|
156
|
+
channelDataKey: DELIVERY_BINDING_CHANNEL_DATA_KEY
|
|
157
|
+
});
|
|
212
158
|
if (!binding) return false;
|
|
213
159
|
if (!visibleApprovalBindingMatches(params.payload.text, binding)) {
|
|
214
160
|
reportApprovalBindingCorrelationMismatch(binding);
|
|
@@ -333,13 +279,15 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
|
333
279
|
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId} sender=${actorId}`);
|
|
334
280
|
return true;
|
|
335
281
|
}
|
|
336
|
-
const
|
|
282
|
+
const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
|
|
337
283
|
try {
|
|
338
|
-
const result = await
|
|
284
|
+
const result = await resolveApprovalOverGateway({
|
|
339
285
|
cfg: params.cfg,
|
|
340
286
|
approvalId: target.approvalId,
|
|
341
287
|
approvalKind: target.approvalKind,
|
|
342
288
|
decision: target.decision,
|
|
289
|
+
channel: "whatsapp",
|
|
290
|
+
accountId: params.accountId,
|
|
343
291
|
senderId: actorId,
|
|
344
292
|
gatewayUrl: params.gatewayUrl
|
|
345
293
|
});
|
|
@@ -367,7 +315,7 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
|
367
315
|
}
|
|
368
316
|
function clearWhatsAppApprovalReactionTargetsForTest() {
|
|
369
317
|
whatsappApprovalReactionTargets.clearForTest();
|
|
370
|
-
|
|
318
|
+
loadResolveApprovalOverGateway.clear();
|
|
371
319
|
}
|
|
372
320
|
//#endregion
|
|
373
321
|
export { unregisterWhatsAppApprovalReactionTarget as i, maybeResolveWhatsAppApprovalReaction as n, registerWhatsAppApprovalReactionTarget as r, approval_reactions_exports as t };
|
package/dist/auth-presence.js
CHANGED