@openclaw/whatsapp 2026.7.2-beta.7 → 2026.8.1-beta.2
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-BzfDFPbH.js → action-runtime-B4e3XFOY.js} +2 -2
- package/dist/action-runtime-api.js +1 -1
- 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-fgGZhALv.js} +4 -4
- package/dist/{approval-reactions-Cu66aYdq.js → approval-reactions-CmtJCxe_.js} +25 -73
- package/dist/auth-presence.js +1 -1
- package/dist/{auth-store-DcEpIOmE.js → auth-store-B_DQIdzp.js} +79 -12
- package/dist/call-tool-api.js +1 -1
- package/dist/{channel-Dg62olhy.js → channel-DJVQHz_V.js} +56 -160
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-J_YtyMGX.js → channel-react-action-d6OacTNj.js} +3 -3
- package/dist/{channel.runtime-BP0xNmLi.js → channel.runtime-RxuNGZ7w.js} +4 -4
- package/dist/channel.setup-Cmvd967u.js +14 -0
- package/dist/{connection-controller-BOB2MVKY.js → connection-controller-CUyZgGpf.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-Pc4f07wB.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-D6_rfxTZ.js} +4 -4
- package/dist/{login-qr-Bncpb6js.js → login-qr-B0VyVSqQ.js} +4 -4
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-CfkaUSL2.js → monitor-BCe5Mm-1.js} +574 -163
- 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-api-7wk6eQyW.js → send-api-DimZST3E.js} +86 -107
- package/dist/{send-D37ddk22.js → send-prK8F7Vj.js} +277 -16
- package/dist/setup-entry.js +1 -8
- package/dist/{setup-finalize-BZucx24W.js → setup-finalize-D3n71Uyx.js} +4 -4
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BkVcd769.js → setup-surface-BCZszf3l.js} +3 -3
- package/dist/{shared-CAxd15bp.js → shared-Dp9M3ZPX.js} +5 -6
- package/dist/{socket-close-DridEuzz.js → socket-close-09FojDO2.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,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 {
|
|
3
|
+
import { _ as resolveWhatsAppReactionLevel, r as sendReactionWhatsApp } from "./send-prK8F7Vj.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-B4e3XFOY.js";
|
|
2
2
|
export { handleWhatsAppAction };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as handleWhatsAppAction } from "./action-runtime-
|
|
1
|
+
import { t as handleWhatsAppAction } from "./action-runtime-B4e3XFOY.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-DJVQHz_V.js";
|
|
8
|
+
import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-Dp9M3ZPX.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-Cmvd967u.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-09FojDO2.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-Pc4f07wB.js";
|
|
15
|
+
import { c as extractContextInfo, g as resolveInboundMediaMimetype, m as findMessageSection, o as describeReplyContext, p as extractText, t as createWebSendApi, u as extractLocationData } from "./send-api-DimZST3E.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-prK8F7Vj.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-CmtJCxe_.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, 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({
|
|
@@ -72,46 +65,6 @@ function listWhatsAppApprovalReactionBindings(allowedDecisions) {
|
|
|
72
65
|
}
|
|
73
66
|
const APPROVAL_ID_LINE_RE = /^\s*ID:\s*(\S(?:.*\S)?)\s*$/i;
|
|
74
67
|
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
68
|
function visibleApprovalBindingMatches(text, binding) {
|
|
116
69
|
const lines = (text ?? "").split(/\r?\n/).map((line) => line.replace(/\*\*/g, ""));
|
|
117
70
|
const kindMatches = lines.map((line) => line.match(APPROVAL_KIND_LINE_RE)).filter((match) => Boolean(match));
|
|
@@ -136,22 +89,13 @@ function visibleApprovalBindingMatches(text, binding) {
|
|
|
136
89
|
"allow-always",
|
|
137
90
|
"deny"
|
|
138
91
|
]);
|
|
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;
|
|
92
|
+
const decisions = readApprovalReactionDecisionList(decisionLines.map((line) => knownBindings.find((entry) => `${entry.emoji} ${entry.label}` === line)?.decision));
|
|
93
|
+
if (!decisions) return false;
|
|
94
|
+
return approvalReactionDecisionSetsMatch(binding.allowedDecisions, decisions);
|
|
151
95
|
}
|
|
152
96
|
/** Preserve a validated typed approval binding until the platform message id is known. */
|
|
153
97
|
function prepareWhatsAppApprovalPayloadForDelivery(params) {
|
|
154
|
-
const binding =
|
|
98
|
+
const binding = readApprovalReactionPresentationBinding(params);
|
|
155
99
|
if (!binding) return null;
|
|
156
100
|
if (!visibleApprovalBindingMatches(params.payload.text, binding)) {
|
|
157
101
|
reportApprovalBindingCorrelationMismatch(binding);
|
|
@@ -161,7 +105,10 @@ function prepareWhatsAppApprovalPayloadForDelivery(params) {
|
|
|
161
105
|
...params.payload,
|
|
162
106
|
channelData: {
|
|
163
107
|
...params.payload.channelData,
|
|
164
|
-
[DELIVERY_BINDING_CHANNEL_DATA_KEY]:
|
|
108
|
+
[DELIVERY_BINDING_CHANNEL_DATA_KEY]: {
|
|
109
|
+
version: 1,
|
|
110
|
+
...binding
|
|
111
|
+
}
|
|
165
112
|
}
|
|
166
113
|
};
|
|
167
114
|
}
|
|
@@ -208,7 +155,10 @@ function listWhatsAppDeliveredMessageIdentities(results) {
|
|
|
208
155
|
/** Bind generic forwarded approvals to the exact WhatsApp messages accepted by Baileys. */
|
|
209
156
|
function registerWhatsAppApprovalReactionTargetForDeliveredPayload(params) {
|
|
210
157
|
if (params.target.channel.trim().toLowerCase() !== "whatsapp") return false;
|
|
211
|
-
const binding =
|
|
158
|
+
const binding = readApprovalReactionDeliveredBinding({
|
|
159
|
+
payload: params.payload,
|
|
160
|
+
channelDataKey: DELIVERY_BINDING_CHANNEL_DATA_KEY
|
|
161
|
+
});
|
|
212
162
|
if (!binding) return false;
|
|
213
163
|
if (!visibleApprovalBindingMatches(params.payload.text, binding)) {
|
|
214
164
|
reportApprovalBindingCorrelationMismatch(binding);
|
|
@@ -333,13 +283,15 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
|
333
283
|
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId} sender=${actorId}`);
|
|
334
284
|
return true;
|
|
335
285
|
}
|
|
336
|
-
const
|
|
286
|
+
const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
|
|
337
287
|
try {
|
|
338
|
-
const result = await
|
|
288
|
+
const result = await resolveApprovalOverGateway({
|
|
339
289
|
cfg: params.cfg,
|
|
340
290
|
approvalId: target.approvalId,
|
|
341
291
|
approvalKind: target.approvalKind,
|
|
342
292
|
decision: target.decision,
|
|
293
|
+
channel: "whatsapp",
|
|
294
|
+
accountId: params.accountId,
|
|
343
295
|
senderId: actorId,
|
|
344
296
|
gatewayUrl: params.gatewayUrl
|
|
345
297
|
});
|
|
@@ -367,7 +319,7 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
|
367
319
|
}
|
|
368
320
|
function clearWhatsAppApprovalReactionTargetsForTest() {
|
|
369
321
|
whatsappApprovalReactionTargets.clearForTest();
|
|
370
|
-
|
|
322
|
+
loadResolveApprovalOverGateway.clear();
|
|
371
323
|
}
|
|
372
324
|
//#endregion
|
|
373
325
|
export { unregisterWhatsAppApprovalReactionTarget as i, maybeResolveWhatsAppApprovalReaction as n, registerWhatsAppApprovalReactionTarget as r, approval_reactions_exports as t };
|
package/dist/auth-presence.js
CHANGED