@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,17 +1,15 @@
|
|
|
1
1
|
import { n as isWhatsAppNewsletterJid } from "./normalize-target-CugRyONv.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as resolveWhatsAppDocumentFileName, f as mergeWhatsAppAcceptedSendError, m as rememberWhatsAppAcceptedSend, p as normalizeWhatsAppSendResult, u as combineWhatsAppSendResults } from "./send-CwvTU4RI.js";
|
|
3
3
|
import "./normalize-C7Hkc_vE.js";
|
|
4
4
|
import { c as toWhatsappJid, l as toWhatsappJidWithLid, r as jidToE164 } from "./targets-runtime-TMk0lGuy.js";
|
|
5
5
|
import "./text-runtime-CaKLhowd.js";
|
|
6
|
-
import { i as buildQuotedMessageOptions } from "./group-session-key-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { i as buildQuotedMessageOptions } from "./group-session-key-DmFc_Cqi.js";
|
|
7
|
+
import { k as resolveComparableIdentity } from "./auth-store-CtpBqH5S.js";
|
|
8
|
+
import { isRecord, normalizeLowercaseStringOrEmpty, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
10
|
-
import { createMessageReceiptFromOutboundResults, listMessageReceiptPlatformIds } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
|
-
import { getImageMetadata, resizeToJpeg } from "openclaw/plugin-sdk/media-runtime";
|
|
12
10
|
import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { getImageMetadata, resizeToJpeg } from "openclaw/plugin-sdk/media-runtime";
|
|
12
|
+
import { extractMessageContent, getContentType, normalizeMessageContent } from "baileys";
|
|
15
13
|
//#region extensions/whatsapp/src/vcard.ts
|
|
16
14
|
const ALLOWED_VCARD_KEYS = /* @__PURE__ */ new Set([
|
|
17
15
|
"FN",
|
|
@@ -79,11 +77,11 @@ function normalizeVcardPhone(value) {
|
|
|
79
77
|
* Falls back to WhatsApp's standard formats when Baileys omits the MIME.
|
|
80
78
|
*/
|
|
81
79
|
function resolveInboundMediaMimetype(message) {
|
|
82
|
-
const explicit = message.imageMessage?.mimetype ?? message.videoMessage?.mimetype ?? message.documentMessage?.mimetype ?? message.audioMessage?.mimetype ?? message.stickerMessage?.mimetype ?? void 0;
|
|
80
|
+
const explicit = message.imageMessage?.mimetype ?? message.videoMessage?.mimetype ?? message.ptvMessage?.mimetype ?? message.documentMessage?.mimetype ?? message.audioMessage?.mimetype ?? message.stickerMessage?.mimetype ?? void 0;
|
|
83
81
|
if (explicit) return explicit;
|
|
84
82
|
if (message.audioMessage) return "audio/ogg; codecs=opus";
|
|
85
83
|
if (message.imageMessage) return "image/jpeg";
|
|
86
|
-
if (message.videoMessage) return "video/mp4";
|
|
84
|
+
if (message.videoMessage || message.ptvMessage) return "video/mp4";
|
|
87
85
|
if (message.stickerMessage) return "image/webp";
|
|
88
86
|
}
|
|
89
87
|
//#endregion
|
|
@@ -99,7 +97,7 @@ function getFutureProofInnerMessage(message) {
|
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
|
-
function
|
|
100
|
+
function projectWhatsAppInboundMessage(message) {
|
|
103
101
|
const chain = [];
|
|
104
102
|
let current = normalizeMessageContent(message);
|
|
105
103
|
while (current && chain.length < 4) {
|
|
@@ -108,8 +106,24 @@ function buildMessageChain(message) {
|
|
|
108
106
|
}
|
|
109
107
|
return chain;
|
|
110
108
|
}
|
|
109
|
+
function isWhatsAppInboundMessageProjection(message) {
|
|
110
|
+
return Array.isArray(message);
|
|
111
|
+
}
|
|
112
|
+
function resolveWhatsAppInboundMessageProjection(message) {
|
|
113
|
+
return isWhatsAppInboundMessageProjection(message) ? message : projectWhatsAppInboundMessage(message);
|
|
114
|
+
}
|
|
115
|
+
function findMessageSection(rawMessage, sectionNames) {
|
|
116
|
+
const chain = projectWhatsAppInboundMessage(rawMessage);
|
|
117
|
+
for (const name of sectionNames) for (const message of chain) {
|
|
118
|
+
const value = message[name];
|
|
119
|
+
if (isRecord(value)) return {
|
|
120
|
+
name,
|
|
121
|
+
value
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
111
125
|
function unwrapMessage(message) {
|
|
112
|
-
return
|
|
126
|
+
return resolveWhatsAppInboundMessageProjection(message).at(-1);
|
|
113
127
|
}
|
|
114
128
|
function extractContextInfoFromMessage(message) {
|
|
115
129
|
const contentType = getContentType(message);
|
|
@@ -134,29 +148,30 @@ function extractContextInfoFromMessage(message) {
|
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
150
|
function extractContextInfo(message) {
|
|
137
|
-
for (const candidate of
|
|
151
|
+
for (const candidate of resolveWhatsAppInboundMessageProjection(message)) {
|
|
138
152
|
const contextInfo = extractContextInfoFromMessage(candidate);
|
|
139
153
|
if (contextInfo) return contextInfo;
|
|
140
154
|
}
|
|
141
155
|
}
|
|
142
|
-
function extractMentionedJids(
|
|
143
|
-
const
|
|
144
|
-
if (!
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
function extractText(
|
|
159
|
-
const
|
|
156
|
+
function extractMentionedJids(message) {
|
|
157
|
+
const mentionedJids = extractContextInfo(message)?.mentionedJid?.filter(Boolean);
|
|
158
|
+
if (!mentionedJids?.length) return;
|
|
159
|
+
return uniqueStrings(mentionedJids);
|
|
160
|
+
}
|
|
161
|
+
function extractNativeFlowResponseText(response) {
|
|
162
|
+
const paramsJson = response?.nativeFlowResponseMessage?.paramsJson;
|
|
163
|
+
if (!paramsJson) return;
|
|
164
|
+
try {
|
|
165
|
+
const params = JSON.parse(paramsJson);
|
|
166
|
+
if (!isRecord(params)) return;
|
|
167
|
+
return [params.title, params.id].find((value) => typeof value === "string" && Boolean(value.trim()));
|
|
168
|
+
} catch {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function extractText(source) {
|
|
173
|
+
const projection = resolveWhatsAppInboundMessageProjection(source);
|
|
174
|
+
const message = unwrapMessage(projection);
|
|
160
175
|
if (!message) return;
|
|
161
176
|
const extracted = extractMessageContent(message);
|
|
162
177
|
const candidates = [message, extracted && extracted !== message ? extracted : void 0];
|
|
@@ -165,14 +180,30 @@ function extractText(rawMessage) {
|
|
|
165
180
|
if (typeof candidate.conversation === "string" && candidate.conversation.trim()) return candidate.conversation.trim();
|
|
166
181
|
const extended = candidate.extendedTextMessage?.text;
|
|
167
182
|
if (extended?.trim()) return extended.trim();
|
|
168
|
-
const caption = candidate.imageMessage?.caption ?? candidate.videoMessage?.caption ?? candidate.documentMessage?.caption;
|
|
183
|
+
const caption = candidate.imageMessage?.caption ?? candidate.videoMessage?.caption ?? candidate.ptvMessage?.caption ?? candidate.documentMessage?.caption;
|
|
169
184
|
if (caption?.trim()) return caption.trim();
|
|
185
|
+
const interactiveSelection = [
|
|
186
|
+
candidate.buttonsResponseMessage?.selectedDisplayText,
|
|
187
|
+
candidate.buttonsResponseMessage?.selectedButtonId,
|
|
188
|
+
candidate.listResponseMessage?.title,
|
|
189
|
+
candidate.listResponseMessage?.singleSelectReply?.selectedRowId,
|
|
190
|
+
candidate.templateButtonReplyMessage?.selectedDisplayText,
|
|
191
|
+
candidate.templateButtonReplyMessage?.selectedId,
|
|
192
|
+
candidate.interactiveResponseMessage?.body?.text,
|
|
193
|
+
extractNativeFlowResponseText(candidate.interactiveResponseMessage)
|
|
194
|
+
].find((value) => Boolean(value?.trim()));
|
|
195
|
+
if (interactiveSelection) return interactiveSelection.trim();
|
|
196
|
+
const poll = candidate.pollCreationMessage ?? candidate.pollCreationMessageV2 ?? candidate.pollCreationMessageV3 ?? candidate.pollCreationMessageV5;
|
|
197
|
+
if (poll) {
|
|
198
|
+
const pollText = [poll.name?.trim(), ...(poll.options ?? []).map((option) => option.optionName?.trim()).filter((option) => Boolean(option)).map((option) => `- ${option}`)].filter(Boolean).join("\n");
|
|
199
|
+
if (pollText) return pollText;
|
|
200
|
+
}
|
|
170
201
|
}
|
|
171
|
-
const contactPlaceholder = extractContactPlaceholder(
|
|
202
|
+
const contactPlaceholder = extractContactPlaceholder(projection) ?? (extracted && extracted !== message ? extractContactPlaceholder(extracted) : void 0);
|
|
172
203
|
if (contactPlaceholder) return contactPlaceholder;
|
|
173
204
|
}
|
|
174
|
-
function extractExternalAdReplyContext(
|
|
175
|
-
const message = unwrapMessage(
|
|
205
|
+
function extractExternalAdReplyContext(source) {
|
|
206
|
+
const message = unwrapMessage(source);
|
|
176
207
|
const adReply = message?.imageMessage?.contextInfo?.externalAdReply ?? message?.videoMessage?.contextInfo?.externalAdReply;
|
|
177
208
|
if (!adReply) return;
|
|
178
209
|
const title = adReply.title?.trim() || void 0;
|
|
@@ -184,24 +215,24 @@ function extractExternalAdReplyContext(rawMessage) {
|
|
|
184
215
|
body
|
|
185
216
|
} : void 0;
|
|
186
217
|
}
|
|
187
|
-
function extractMediaKind(
|
|
188
|
-
const message = unwrapMessage(
|
|
218
|
+
function extractMediaKind(source) {
|
|
219
|
+
const message = unwrapMessage(source);
|
|
189
220
|
if (!message) return;
|
|
190
221
|
if (message.imageMessage) return "image";
|
|
191
|
-
if (message.videoMessage) return "video";
|
|
222
|
+
if (message.videoMessage || message.ptvMessage) return "video";
|
|
192
223
|
if (message.audioMessage) return "audio";
|
|
193
224
|
if (message.documentMessage) return "document";
|
|
194
225
|
if (message.stickerMessage) return "sticker";
|
|
195
226
|
}
|
|
196
|
-
function extractContactPlaceholder(
|
|
197
|
-
const contactContext = extractContactContext(
|
|
227
|
+
function extractContactPlaceholder(source) {
|
|
228
|
+
const contactContext = extractContactContext(source);
|
|
198
229
|
if (!contactContext) return;
|
|
199
230
|
if (contactContext.kind === "contact") return "<contact>";
|
|
200
231
|
const suffix = contactContext.total === 1 ? "contact" : "contacts";
|
|
201
232
|
return `<contacts: ${contactContext.total} ${suffix}>`;
|
|
202
233
|
}
|
|
203
|
-
function extractContactContext(
|
|
204
|
-
const message = unwrapMessage(
|
|
234
|
+
function extractContactContext(source) {
|
|
235
|
+
const message = unwrapMessage(source);
|
|
205
236
|
if (!message) return;
|
|
206
237
|
const contact = message.contactMessage ?? void 0;
|
|
207
238
|
if (contact) {
|
|
@@ -237,8 +268,8 @@ function describeContact(input) {
|
|
|
237
268
|
phones: parsed.phones
|
|
238
269
|
};
|
|
239
270
|
}
|
|
240
|
-
function extractLocationData(
|
|
241
|
-
const message = unwrapMessage(
|
|
271
|
+
function extractLocationData(source) {
|
|
272
|
+
const message = unwrapMessage(source);
|
|
242
273
|
if (!message) return null;
|
|
243
274
|
const live = message.liveLocationMessage ?? void 0;
|
|
244
275
|
if (live) {
|
|
@@ -281,10 +312,11 @@ function extractLocationData(rawMessage) {
|
|
|
281
312
|
}
|
|
282
313
|
return null;
|
|
283
314
|
}
|
|
284
|
-
function describeReplyContext(
|
|
285
|
-
const
|
|
315
|
+
function describeReplyContext(source) {
|
|
316
|
+
const projection = resolveWhatsAppInboundMessageProjection(source);
|
|
317
|
+
const message = unwrapMessage(projection);
|
|
286
318
|
if (!message) return null;
|
|
287
|
-
const contextInfo = extractContextInfo(message);
|
|
319
|
+
const contextInfo = extractContextInfo(projection.length === 1 && projection[0] === message ? projection : projectWhatsAppInboundMessage(message));
|
|
288
320
|
const quoted = normalizeMessageContent(contextInfo?.quotedMessage);
|
|
289
321
|
if (!quoted && !contextInfo?.stanzaId) return null;
|
|
290
322
|
const senderJid = contextInfo?.participant ?? void 0;
|
|
@@ -297,10 +329,11 @@ function describeReplyContext(rawMessage) {
|
|
|
297
329
|
body: "[quoted message unavailable]",
|
|
298
330
|
sender
|
|
299
331
|
};
|
|
300
|
-
const
|
|
332
|
+
const quotedProjection = projectWhatsAppInboundMessage(quoted);
|
|
333
|
+
const location = extractLocationData(quotedProjection);
|
|
301
334
|
const locationText = location ? formatLocationText(location) : void 0;
|
|
302
|
-
const body = [extractText(
|
|
303
|
-
const mediaKind = extractMediaKind(
|
|
335
|
+
const body = [extractText(quotedProjection), locationText].filter(Boolean).join("\n").trim();
|
|
336
|
+
const mediaKind = extractMediaKind(quotedProjection);
|
|
304
337
|
const media = mediaKind ? {
|
|
305
338
|
kind: mediaKind,
|
|
306
339
|
contentType: resolveInboundMediaMimetype(quoted)
|
|
@@ -328,12 +361,13 @@ function hasInteractiveResponseContent(message) {
|
|
|
328
361
|
* `messages.upsert` stream as real messages but should not trigger pairing
|
|
329
362
|
* access-control side effects.
|
|
330
363
|
*/
|
|
331
|
-
function hasInboundUserContent(
|
|
332
|
-
|
|
333
|
-
if (
|
|
334
|
-
if (
|
|
335
|
-
if (
|
|
336
|
-
|
|
364
|
+
function hasInboundUserContent(source) {
|
|
365
|
+
const projection = resolveWhatsAppInboundMessageProjection(source);
|
|
366
|
+
if (projection.length === 0) return false;
|
|
367
|
+
if (extractText(projection)) return true;
|
|
368
|
+
if (extractMediaKind(projection)) return true;
|
|
369
|
+
if (extractLocationData(projection)) return true;
|
|
370
|
+
for (const candidate of projection) if (hasInteractiveResponseContent(candidate)) return true;
|
|
337
371
|
return false;
|
|
338
372
|
}
|
|
339
373
|
//#endregion
|
|
@@ -542,75 +576,7 @@ function addWhatsAppOutboundMentionsToContent(content, mentionedJids) {
|
|
|
542
576
|
} : content;
|
|
543
577
|
}
|
|
544
578
|
//#endregion
|
|
545
|
-
//#region extensions/whatsapp/src/inbound/send-result.ts
|
|
546
|
-
function resolveWhatsAppReceiptKind(kind) {
|
|
547
|
-
if (kind === "media" || kind === "text") return kind;
|
|
548
|
-
return "unknown";
|
|
549
|
-
}
|
|
550
|
-
function toReceiptSourceResult(key) {
|
|
551
|
-
return {
|
|
552
|
-
channel: "whatsapp",
|
|
553
|
-
messageId: key.id,
|
|
554
|
-
...key.remoteJid ? { toJid: key.remoteJid } : {},
|
|
555
|
-
meta: {
|
|
556
|
-
fromMe: key.fromMe,
|
|
557
|
-
participant: key.participant
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
function createWhatsAppSendReceipt(kind, keys) {
|
|
562
|
-
return createMessageReceiptFromOutboundResults({
|
|
563
|
-
kind: resolveWhatsAppReceiptKind(kind),
|
|
564
|
-
results: keys.map(toReceiptSourceResult)
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
function normalizeKey(key) {
|
|
568
|
-
const id = typeof key?.id === "string" ? key.id.trim() : "";
|
|
569
|
-
if (!id) return;
|
|
570
|
-
return {
|
|
571
|
-
id,
|
|
572
|
-
remoteJid: key?.remoteJid,
|
|
573
|
-
fromMe: key?.fromMe,
|
|
574
|
-
participant: key?.participant
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
function normalizeWhatsAppSendResult(result, kind) {
|
|
578
|
-
const key = normalizeKey(result?.key);
|
|
579
|
-
return {
|
|
580
|
-
kind,
|
|
581
|
-
messageId: key?.id ?? "unknown",
|
|
582
|
-
receipt: createWhatsAppSendReceipt(kind, key ? [key] : []),
|
|
583
|
-
keys: key ? [key] : [],
|
|
584
|
-
providerAccepted: Boolean(key)
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
function combineWhatsAppSendResults(kind, results) {
|
|
588
|
-
const messageIds = uniqueStrings(results.flatMap(listWhatsAppSendResultMessageIds));
|
|
589
|
-
const keys = results.flatMap((result) => result.keys);
|
|
590
|
-
return {
|
|
591
|
-
kind,
|
|
592
|
-
messageId: messageIds[0] ?? "unknown",
|
|
593
|
-
receipt: createWhatsAppSendReceipt(kind, keys),
|
|
594
|
-
keys,
|
|
595
|
-
providerAccepted: results.some((result) => result.providerAccepted)
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
function listWhatsAppSendResultMessageIds(result) {
|
|
599
|
-
const receiptIds = result.receipt ? listMessageReceiptPlatformIds(result.receipt) : [];
|
|
600
|
-
if (receiptIds.length > 0) return receiptIds;
|
|
601
|
-
const keyIds = normalizeStringEntries(result.keys.map((key) => key.id));
|
|
602
|
-
if (keyIds.length > 0) return uniqueStrings(keyIds);
|
|
603
|
-
return [];
|
|
604
|
-
}
|
|
605
|
-
//#endregion
|
|
606
579
|
//#region extensions/whatsapp/src/inbound/send-api.ts
|
|
607
|
-
function recordWhatsAppOutbound(accountId) {
|
|
608
|
-
recordChannelActivity({
|
|
609
|
-
channel: "whatsapp",
|
|
610
|
-
accountId,
|
|
611
|
-
direction: "outbound"
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
580
|
function supportsForcedDocumentMediaType(mediaType) {
|
|
615
581
|
return mediaType.startsWith("image/") || mediaType.startsWith("video/");
|
|
616
582
|
}
|
|
@@ -623,11 +589,30 @@ function createWebSendApi(params) {
|
|
|
623
589
|
text,
|
|
624
590
|
mentionedJids: []
|
|
625
591
|
};
|
|
592
|
+
const runAcceptedSend = async (kind, accountId, send) => {
|
|
593
|
+
const results = [];
|
|
594
|
+
try {
|
|
595
|
+
await send((result, sendKind) => {
|
|
596
|
+
rememberWhatsAppAcceptedSend({
|
|
597
|
+
accountId,
|
|
598
|
+
result: normalizeWhatsAppSendResult(result, sendKind),
|
|
599
|
+
results
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
return combineWhatsAppSendResults(kind, results);
|
|
603
|
+
} catch (error) {
|
|
604
|
+
throw mergeWhatsAppAcceptedSendError({
|
|
605
|
+
error,
|
|
606
|
+
kind,
|
|
607
|
+
results
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
};
|
|
626
611
|
const sendStructuredMessage = async (to, content, kind) => {
|
|
627
612
|
const jid = resolveOutboundJid(to);
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
613
|
+
return await runAcceptedSend(kind, params.defaultAccountId, async (capture) => {
|
|
614
|
+
capture(await params.sock.sendMessage(jid, content), kind);
|
|
615
|
+
});
|
|
631
616
|
};
|
|
632
617
|
return {
|
|
633
618
|
sendMessage: async (to, text, mediaBuffer, mediaTypeInput, sendOptions) => {
|
|
@@ -683,18 +668,22 @@ function createWebSendApi(params) {
|
|
|
683
668
|
remoteJid: sendOptions?.quotedMessageKey?.remoteJid,
|
|
684
669
|
fromMe: sendOptions?.quotedMessageKey?.fromMe,
|
|
685
670
|
participant: sendOptions?.quotedMessageKey?.participant,
|
|
671
|
+
destinationJid: jid,
|
|
672
|
+
requestedJid: toWhatsappJid(to),
|
|
673
|
+
lookupTargetJid: sendOptions?.quotedMessageKey?.lookupTargetJid,
|
|
686
674
|
messageText: sendOptions?.quotedMessageKey?.messageText,
|
|
687
675
|
media: sendOptions?.quotedMessageKey?.media
|
|
688
676
|
});
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
677
|
+
const kind = mediaBuffer ? "media" : "text";
|
|
678
|
+
const accountId = sendOptions?.accountId ?? params.defaultAccountId;
|
|
679
|
+
return await runAcceptedSend(kind, accountId, async (capture) => {
|
|
680
|
+
const sendPayload = async (content) => quotedOpts ? await params.sock.sendMessage(jid, content, quotedOpts) : await params.sock.sendMessage(jid, content);
|
|
681
|
+
capture(await sendPayload(payload), kind);
|
|
682
|
+
if (shouldSendAudioText) {
|
|
683
|
+
const resolvedAudioText = await resolveMentions(jid, text);
|
|
684
|
+
capture(await sendPayload(addWhatsAppOutboundMentionsToContent({ text: resolvedAudioText.text }, resolvedAudioText.mentionedJids)), "text");
|
|
685
|
+
}
|
|
686
|
+
});
|
|
698
687
|
},
|
|
699
688
|
sendPoll: async (to, poll) => {
|
|
700
689
|
return await sendStructuredMessage(to, { poll: {
|
|
@@ -746,4 +735,4 @@ function createWebSendApi(params) {
|
|
|
746
735
|
};
|
|
747
736
|
}
|
|
748
737
|
//#endregion
|
|
749
|
-
export {
|
|
738
|
+
export { resolveInboundMediaMimetype as _, addWhatsAppImagePreviewFields as a, extractContextInfo as c, extractMediaKind as d, extractMentionedJids as f, projectWhatsAppInboundMessage as g, hasInboundUserContent as h, resolveWhatsAppOutboundMentions as i, extractExternalAdReplyContext as l, findMessageSection as m, addWhatsAppOutboundMentionsToContent as n, describeReplyContext as o, extractText as p, mayContainWhatsAppOutboundMention as r, extractContactContext as s, createWebSendApi as t, extractLocationData as u };
|
package/dist/setup-entry.js
CHANGED
|
@@ -2,18 +2,11 @@ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entr
|
|
|
2
2
|
//#region extensions/whatsapp/setup-entry.ts
|
|
3
3
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
4
4
|
importMetaUrl: import.meta.url,
|
|
5
|
-
features: {
|
|
6
|
-
legacyStateMigrations: true,
|
|
7
|
-
legacySessionSurfaces: true
|
|
8
|
-
},
|
|
5
|
+
features: { legacySessionSurfaces: true },
|
|
9
6
|
plugin: {
|
|
10
7
|
specifier: "./setup-plugin-api.js",
|
|
11
8
|
exportName: "whatsappSetupPlugin"
|
|
12
9
|
},
|
|
13
|
-
legacyStateMigrations: {
|
|
14
|
-
specifier: "./legacy-state-migrations-api.js",
|
|
15
|
-
exportName: "detectWhatsAppLegacyStateMigrations"
|
|
16
|
-
},
|
|
17
10
|
legacySessionSurface: {
|
|
18
11
|
specifier: "./legacy-session-surface-api.js",
|
|
19
12
|
exportName: "whatsappLegacySessionSurface"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
|
|
3
|
-
import { r as hasWebCredsSync } from "./creds-files-
|
|
3
|
+
import { r as hasWebCredsSync } from "./creds-files-W6B3EMZ8.js";
|
|
4
4
|
import { a as normalizeWhatsAppAllowFromEntries, o as normalizeWhatsAppAllowFromEntry } from "./normalize-target-CugRyONv.js";
|
|
5
|
-
import { r as whatsappSetupAdapter } from "./shared-
|
|
5
|
+
import { r as whatsappSetupAdapter } from "./shared-wg42NKFB.js";
|
|
6
6
|
import { DEFAULT_ACCOUNT_ID, createSetupTranslator, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
7
7
|
import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
8
8
|
//#region extensions/whatsapp/src/setup-finalize.ts
|
|
@@ -295,7 +295,7 @@ async function finalizeWhatsAppSetup(params) {
|
|
|
295
295
|
};
|
|
296
296
|
let loginWeb;
|
|
297
297
|
try {
|
|
298
|
-
({loginWeb} = await import("./login-
|
|
298
|
+
({loginWeb} = await import("./login-BkpKpndm.js").then((n) => n.n));
|
|
299
299
|
} catch (error) {
|
|
300
300
|
await reportLoginFailure(error);
|
|
301
301
|
}
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as whatsappSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as whatsappSetupPlugin } from "./channel.setup-DhBBhbQv.js";
|
|
2
2
|
export { whatsappSetupPlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { o as resolveWhatsAppAuthDir } from "./accounts-
|
|
1
|
+
import { o as resolveWhatsAppAuthDir } from "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { t as listAccountIds } from "./account-ids-CB5SOWjc.js";
|
|
3
|
-
import { a as formatWhatsAppWebAuthStatusState, h as readWebAuthState } from "./auth-store-
|
|
3
|
+
import { a as formatWhatsAppWebAuthStatusState, h as readWebAuthState } from "./auth-store-CtpBqH5S.js";
|
|
4
4
|
import { DEFAULT_ACCOUNT_ID, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
5
5
|
//#region extensions/whatsapp/src/setup-surface.ts
|
|
6
6
|
const t = createSetupTranslator();
|
|
@@ -36,7 +36,7 @@ const whatsappSetupWizard = {
|
|
|
36
36
|
},
|
|
37
37
|
resolveShouldPromptAccountIds: ({ shouldPromptAccountIds }) => shouldPromptAccountIds,
|
|
38
38
|
credentials: [],
|
|
39
|
-
finalize: async (params) => await (await import("./setup-finalize-
|
|
39
|
+
finalize: async (params) => await (await import("./setup-finalize-n4K2I2gJ.js")).finalizeWhatsAppSetup(params),
|
|
40
40
|
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
|
|
41
41
|
onAccountRecorded: (accountId, options) => {
|
|
42
42
|
options?.onAccountId?.(channel, accountId);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-BX2fZUyR.js";
|
|
2
2
|
import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
|
|
3
3
|
import { a as normalizeWhatsAppAllowFromEntries } from "./normalize-target-CugRyONv.js";
|
|
4
4
|
import { t as WhatsAppChannelConfigSchema } from "./config-schema-BQP5YCeK.js";
|
|
@@ -12,7 +12,7 @@ import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
|
|
|
12
12
|
import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
|
|
13
13
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
14
14
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
15
|
-
import { buildChannelGroupsScopeTree, collectOpenGroupPolicyRouteAllowlistWarnings, createAllowlistProviderGroupPolicyWarningCollector, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
|
|
15
|
+
import { buildChannelGroupsScopeTree, collectOpenGroupPolicyRouteAllowlistWarnings, createAllowlistProviderGroupPolicyWarningCollector, createConditionalWarningCollector, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
|
|
16
16
|
import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
17
17
|
import { createPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup";
|
|
18
18
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
@@ -20,14 +20,14 @@ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createSco
|
|
|
20
20
|
import { createDelegatedSetupWizardProxy } from "openclaw/plugin-sdk/setup-runtime";
|
|
21
21
|
import { readChannelAllowFromStore } from "openclaw/plugin-sdk/channel-pairing";
|
|
22
22
|
//#region extensions/whatsapp/src/channel-runtime-loader.ts
|
|
23
|
-
const loadWhatsAppAuthStore = createLazyRuntimeModule(() => import("./auth-store-
|
|
23
|
+
const loadWhatsAppAuthStore = createLazyRuntimeModule(() => import("./auth-store-CtpBqH5S.js").then((n) => n.i));
|
|
24
24
|
async function readWhatsAppAccountLinkState(authDir) {
|
|
25
25
|
const state = await (await loadWhatsAppAuthStore()).readWebAuthState(authDir);
|
|
26
26
|
return state === "unstable" ? "unknown" : state;
|
|
27
27
|
}
|
|
28
28
|
const loadWhatsAppChannelRuntime = createLazyRuntimeModule(async () => {
|
|
29
29
|
await loadWhatsAppAuthStore();
|
|
30
|
-
return await import("./channel.runtime-
|
|
30
|
+
return await import("./channel.runtime-X3JC2gaq.js");
|
|
31
31
|
});
|
|
32
32
|
//#endregion
|
|
33
33
|
//#region extensions/whatsapp/src/config-accessors.ts
|
|
@@ -115,7 +115,7 @@ async function applyWhatsAppSecurityConfigFixes(params) {
|
|
|
115
115
|
//#region extensions/whatsapp/src/shared.ts
|
|
116
116
|
const WHATSAPP_CHANNEL = "whatsapp";
|
|
117
117
|
async function loadWhatsAppSetupSurface() {
|
|
118
|
-
return await import("./setup-surface-
|
|
118
|
+
return await import("./setup-surface-Cwn3zyxK.js");
|
|
119
119
|
}
|
|
120
120
|
const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(async () => (await loadWhatsAppSetupSurface()).whatsappSetupWizard);
|
|
121
121
|
const whatsappConfigAdapter = createScopedChannelConfigAdapter({
|
|
@@ -209,6 +209,12 @@ function createWhatsAppPluginBase(params) {
|
|
|
209
209
|
}
|
|
210
210
|
})
|
|
211
211
|
});
|
|
212
|
+
const collectWhatsAppOpenGroupFindings = createConditionalWarningCollector.findings({
|
|
213
|
+
collectWarnings: collectWhatsAppSecurityWarnings,
|
|
214
|
+
checkId: "channels.whatsapp.groups.open",
|
|
215
|
+
severity: "critical",
|
|
216
|
+
title: "WhatsApp security warning"
|
|
217
|
+
});
|
|
212
218
|
const base = createChannelPluginBase({
|
|
213
219
|
id: WHATSAPP_CHANNEL,
|
|
214
220
|
meta: {
|
|
@@ -270,11 +276,10 @@ function createWhatsAppPluginBase(params) {
|
|
|
270
276
|
security: {
|
|
271
277
|
applyConfigFixes: applyWhatsAppSecurityConfigFixes,
|
|
272
278
|
resolveDmPolicy: whatsappResolveDmPolicy,
|
|
273
|
-
collectWarnings:
|
|
279
|
+
collectWarnings: collectWhatsAppOpenGroupFindings
|
|
274
280
|
},
|
|
275
281
|
doctor: whatsappDoctor,
|
|
276
|
-
|
|
277
|
-
...params.setupContract ? { setupContract: params.setupContract } : {},
|
|
282
|
+
setupContract: params.setupContract,
|
|
278
283
|
groups: params.groups
|
|
279
284
|
});
|
|
280
285
|
return {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { c as resolveWebCredsPath, s as resolveWebCredsBackupPath, t as assertWebCredsPathRegularFileOrMissing } from "./creds-files-W6B3EMZ8.js";
|
|
2
|
+
import { A as enqueueCredsSave, M as waitForCredsSaveQueueWithTimeout, N as writeCredsJsonAtomically, P as writeWebCredsRawAtomically, b as restoreCredsFromBackupIfNeeded, u as readCredsJsonRaw, y as resolveDefaultWebAuthDir } from "./auth-store-CtpBqH5S.js";
|
|
3
3
|
import { n as getStatusCode } from "./session-errors-JuazczrA.js";
|
|
4
4
|
import { a as makeWASocket, i as makeCacheableSignalKeyStore, n as createBaileysSignalRepository, r as fetchLatestBaileysVersion, s as useMultiFileAuthState } from "./session.runtime-Nsqaehbd.js";
|
|
5
5
|
import { VERSION, formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
6
|
+
import { toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
6
7
|
import { danger, getChildLogger, success, toPinoLikeLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
7
8
|
import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
|
|
8
9
|
import { ensureDir, resolveUserPath } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
@@ -541,7 +542,7 @@ async function waitForWaConnection(sock, options = { timeout: "none" }) {
|
|
|
541
542
|
}
|
|
542
543
|
if (update.connection === "close") {
|
|
543
544
|
cleanup();
|
|
544
|
-
reject(
|
|
545
|
+
reject(toErrorObject(update.lastDisconnect?.error ?? update.lastDisconnect ?? /* @__PURE__ */ new Error("Connection closed"), "Non-Error rejection"));
|
|
545
546
|
}
|
|
546
547
|
};
|
|
547
548
|
sock.ev.on("connection.update", handler);
|
|
@@ -558,13 +559,6 @@ async function waitForWaConnection(sock, options = { timeout: "none" }) {
|
|
|
558
559
|
function newConnectionId() {
|
|
559
560
|
return randomUUID();
|
|
560
561
|
}
|
|
561
|
-
function toLintErrorObject(value, fallbackMessage) {
|
|
562
|
-
if (value instanceof Error) return value;
|
|
563
|
-
if (typeof value === "string") return new Error(value);
|
|
564
|
-
const error = new Error(fallbackMessage, { cause: value });
|
|
565
|
-
if (typeof value === "object" && value !== null || typeof value === "function") Object.assign(error, value);
|
|
566
|
-
return error;
|
|
567
|
-
}
|
|
568
562
|
function createConnectionTimeoutError(timeoutMs) {
|
|
569
563
|
const error = /* @__PURE__ */ new Error(`WhatsApp connection timed out after ${timeoutMs}ms`);
|
|
570
564
|
Object.assign(error, { output: { statusCode: 408 } });
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/whatsapp",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.8.1-beta.3",
|
|
4
4
|
"description": "OpenClaw WhatsApp channel plugin for WhatsApp Web chats.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"typebox": "1.3.6"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.
|
|
16
|
+
"openclaw": ">=2026.8.1-beta.3"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"setupEntry": "./dist/setup-entry.js",
|
|
28
28
|
"setupFeatures": {
|
|
29
29
|
"configPromotion": true,
|
|
30
|
-
"legacyStateMigrations": true,
|
|
31
30
|
"legacySessionSurfaces": true
|
|
32
31
|
},
|
|
33
32
|
"channel": {
|
|
@@ -66,10 +65,10 @@
|
|
|
66
65
|
"minHostVersion": ">=2026.4.25"
|
|
67
66
|
},
|
|
68
67
|
"compat": {
|
|
69
|
-
"pluginApi": ">=2026.
|
|
68
|
+
"pluginApi": ">=2026.8.1-beta.3"
|
|
70
69
|
},
|
|
71
70
|
"build": {
|
|
72
|
-
"openclawVersion": "2026.
|
|
71
|
+
"openclawVersion": "2026.8.1-beta.3"
|
|
73
72
|
},
|
|
74
73
|
"release": {
|
|
75
74
|
"publishToClawHub": true,
|
package/skills/wacli/SKILL.md
CHANGED
|
@@ -20,7 +20,7 @@ metadata:
|
|
|
20
20
|
{
|
|
21
21
|
"id": "go",
|
|
22
22
|
"kind": "go",
|
|
23
|
-
"module": "github.com/
|
|
23
|
+
"module": "github.com/openclaw/wacli/cmd/wacli@latest",
|
|
24
24
|
"bins": ["wacli"],
|
|
25
25
|
"label": "Install wacli (go)",
|
|
26
26
|
},
|
|
@@ -53,6 +53,12 @@ Find chats + messages
|
|
|
53
53
|
- `wacli messages search "query" --limit 20 --chat <jid>`
|
|
54
54
|
- `wacli messages search "invoice" --after 2025-01-01 --before 2025-12-31`
|
|
55
55
|
|
|
56
|
+
Inspect / verify messages
|
|
57
|
+
|
|
58
|
+
- `wacli messages show --chat <jid> --id <message_id> --json --full`
|
|
59
|
+
- `messages show` requires both `--chat` and `--id`; do not pass the message ID as a positional argument.
|
|
60
|
+
- After sending, verify the stored message when exact formatting matters, especially multiline text.
|
|
61
|
+
|
|
56
62
|
History backfill
|
|
57
63
|
|
|
58
64
|
- `wacli history backfill --chat <jid> --requests 2 --count 50`
|
|
@@ -62,6 +68,7 @@ Send
|
|
|
62
68
|
- Text: `wacli send text --to "+14155551212" --message "Hello! Are you free at 3pm?"`
|
|
63
69
|
- Group: `wacli send text --to "1234567890-123456789@g.us" --message "Running 5 min late."`
|
|
64
70
|
- File: `wacli send file --to "+14155551212" --file /path/agenda.pdf --caption "Agenda"`
|
|
71
|
+
- Multiline: `--message` is literal by default; pass `--message-escapes` to interpret `\n`, `\r`, `\t`.
|
|
65
72
|
|
|
66
73
|
Notes
|
|
67
74
|
|