@openclaw/whatsapp 2026.9.8 → 2026.10.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.
Files changed (44) hide show
  1. package/dist/.setup/{accounts-CtRPAQCL.mjs → accounts-F0vHuze2.mjs} +3 -11
  2. package/dist/.setup/{action-runtime-DeVk5V7r.mjs → action-runtime-CE3zGstN.mjs} +4 -5
  3. package/dist/.setup/{agent-tools-login-CL5C1rA2.mjs → agent-tools-login-B7VEvJO7.mjs} +17 -36
  4. package/dist/.setup/{approval-handler.runtime-CjqMlPOX.mjs → approval-handler.runtime-CKposl6w.mjs} +3 -3
  5. package/dist/.setup/{approval-reactions-DiOFvb1s.mjs → approval-reactions-CD6CDF9k.mjs} +9 -40
  6. package/dist/.setup/{auth-store-BBonwKks.mjs → auth-store-D2rN-hP5.mjs} +12 -19
  7. package/dist/.setup/{channel-CJFE0kD_.mjs → channel-DNgKHMCz.mjs} +15 -24
  8. package/dist/.setup/{channel-react-action-2r_hjLZV.mjs → channel-react-action-BaBV9X6M.mjs} +3 -3
  9. package/dist/.setup/{channel.runtime-C94goLw9.mjs → channel.runtime-BniF8Swm.mjs} +4 -4
  10. package/dist/.setup/{channel.setup-CfN1UfdY.mjs → channel.setup-CsS_NAKQ.mjs} +1 -1
  11. package/dist/.setup/{connection-controller-CHo1oRJA.mjs → connection-controller-COkcq48K.mjs} +5 -14
  12. package/dist/.setup/{creds-files-CDATZWWM.mjs → creds-files-B8WcOAmE.mjs} +1 -10
  13. package/dist/.setup/{directory-config-DUiJ5d8I.mjs → directory-config-RYQomHyB.mjs} +6 -14
  14. package/dist/.setup/{doctor-iMwg0Vhr.mjs → doctor-DKzeBEmH.mjs} +7 -1
  15. package/dist/.setup/{group-config-path-DZr3ucUO.mjs → group-config-path-BPrak_bJ.mjs} +3 -9
  16. package/dist/.setup/{group-session-key-2-mja4OF.mjs → group-session-key-BV8Le9r8.mjs} +5 -14
  17. package/dist/.setup/{login-BFlvSh9h.mjs → login-CV_4V021.mjs} +4 -4
  18. package/dist/.setup/{login-qr-Ayb8i25J.mjs → login-qr-DFhGc5yH.mjs} +11 -27
  19. package/dist/.setup/{monitor-CGpV2VNN.mjs → monitor-B5DS4PDV.mjs} +65 -186
  20. package/dist/.setup/{question-reactions-CPyyi5AY.mjs → question-reactions-LMeijbaq.mjs} +7 -37
  21. package/dist/.setup/{resolve-outbound-target-C2eUvsTc.mjs → resolve-outbound-target-CzyNKmrl.mjs} +2 -13
  22. package/dist/.setup/{send-BGdvf5cC.mjs → send-CGUsUdoX.mjs} +31 -6
  23. package/dist/.setup/{send-api-H4AkQJjT.mjs → send-api-B03VDwZ1.mjs} +35 -53
  24. package/dist/.setup/{setup-finalize-DmPX4EaW.mjs → setup-finalize-GtBmrO8p.mjs} +8 -20
  25. package/dist/.setup/setup-plugin-api-Bsp7jI-r.mjs +3 -0
  26. package/dist/.setup/{setup-surface-43fj197P.mjs → setup-surface-BuA39k6K.mjs} +3 -3
  27. package/dist/.setup/{shared-DgOG5Iqr.mjs → shared-CP_zs2U7.mjs} +12 -13
  28. package/dist/.setup/{socket-close-CT__V2fz.mjs → socket-close-DU7eerAa.mjs} +26 -54
  29. package/dist/.setup/{targets-runtime-DmiqXIXO.mjs → targets-runtime-Dls-Xh4F.mjs} +10 -34
  30. package/dist/action-runtime-api.js +1 -1
  31. package/dist/action-runtime.runtime.js +1 -1
  32. package/dist/agent-tools-api.js +3 -3
  33. package/dist/api.js +10 -10
  34. package/dist/auth-presence.js +3 -4
  35. package/dist/channel-plugin-api.js +1 -1
  36. package/dist/directory-contract-api.js +1 -1
  37. package/dist/doctor-contract-api.js +234 -59
  38. package/dist/light-runtime-api.js +2 -2
  39. package/dist/login-qr-runtime.js +1 -1
  40. package/dist/runtime-api.js +10 -10
  41. package/dist/setup-entry.js +1 -1
  42. package/dist/setup-plugin-api.js +1 -1
  43. package/package.json +5 -5
  44. package/dist/.setup/setup-plugin-api-vJlxKzca.mjs +0 -3
@@ -1,5 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-BBjsoOtd.mjs";
2
- import { a as resolveWhatsAppAccount } from "./accounts-CtRPAQCL.mjs";
2
+ import { a as resolveWhatsAppAccount } from "./accounts-F0vHuze2.mjs";
3
+ import { d as listWhatsAppDeliveredMessageIdentities } from "./send-CGUsUdoX.mjs";
4
+ import { normalizeUniqueTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
3
5
  import { createQuestionReactionTargetStore, questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
4
6
  //#region extensions/whatsapp/src/question-reactions.ts
5
7
  var question_reactions_exports = /* @__PURE__ */ __exportAll({
@@ -21,33 +23,6 @@ const questionReactionTargets = createQuestionReactionTargetStore({
21
23
  registerChannelDelivery: questionGatewayRuntime.registerChannelDelivery,
22
24
  resolveReaction: questionGatewayRuntime.resolveReaction
23
25
  });
24
- function addCandidate(values, value) {
25
- const normalized = value?.trim();
26
- if (normalized && !values.includes(normalized)) values.push(normalized);
27
- }
28
- function listDeliveredIdentities(results) {
29
- const identities = [];
30
- const seen = /* @__PURE__ */ new Set();
31
- const add = (messageId, remoteJid) => {
32
- const id = messageId?.trim() ?? "";
33
- const jid = remoteJid?.trim() ?? "";
34
- const key = `${jid}:${id}`;
35
- if (id && id !== "unknown" && jid && !seen.has(key)) {
36
- seen.add(key);
37
- identities.push({
38
- messageId: id,
39
- remoteJid: jid
40
- });
41
- }
42
- };
43
- for (const result of results) {
44
- if (result.channel !== "whatsapp") continue;
45
- add(result.messageId, result.toJid);
46
- for (const raw of result.receipt?.raw ?? []) add(raw.messageId, raw.toJid);
47
- for (const part of result.receipt?.parts ?? []) add(part.raw?.messageId ?? part.platformMessageId, part.raw?.toJid);
48
- }
49
- return identities;
50
- }
51
26
  function registerWhatsAppQuestionReactionTargetForDeliveredPayload(params) {
52
27
  const binding = questionGatewayRuntime.readReactionBinding(params.payload);
53
28
  if (params.target.channel !== "whatsapp" || !binding) return false;
@@ -56,7 +31,7 @@ function registerWhatsAppQuestionReactionTargetForDeliveredPayload(params) {
56
31
  accountId: params.target.accountId
57
32
  }).accountId;
58
33
  let registered = false;
59
- for (const identity of listDeliveredIdentities(params.results)) registered = questionReactionTargets.register(binding, {
34
+ for (const identity of listWhatsAppDeliveredMessageIdentities(params.results, () => true)) registered = questionReactionTargets.register(binding, {
60
35
  accountId,
61
36
  ...identity
62
37
  }) || registered;
@@ -68,16 +43,11 @@ async function maybeResolveWhatsAppQuestionReaction(params) {
68
43
  const messageId = reaction?.key?.id?.trim() ?? "";
69
44
  const optionIndex = questionGatewayRuntime.resolveReactionIndex(reactionKey);
70
45
  if (optionIndex === void 0 || !messageId) return false;
71
- const remoteJids = [];
72
- addCandidate(remoteJids, reaction?.key?.remoteJid);
73
- addCandidate(remoteJids, params.msg.key?.remoteJid);
46
+ const remoteJids = normalizeUniqueTrimmedStringList([reaction?.key?.remoteJid, params.msg.key?.remoteJid]);
74
47
  const candidates = [];
75
- for (const remoteJid of remoteJids) {
76
- addCandidate(candidates, remoteJid);
77
- for (const mapped of await params.resolveReactionTargetJids?.(remoteJid) ?? []) addCandidate(candidates, mapped);
78
- }
48
+ for (const remoteJid of remoteJids) candidates.push(remoteJid, ...await params.resolveReactionTargetJids?.(remoteJid) ?? []);
79
49
  return await questionReactionTargets.resolve({
80
- identities: candidates.map((remoteJid) => ({
50
+ identities: normalizeUniqueTrimmedStringList(candidates).map((remoteJid) => ({
81
51
  accountId: params.accountId,
82
52
  remoteJid,
83
53
  messageId
@@ -2,15 +2,8 @@ import { c as normalizeWhatsAppTarget, n as isWhatsAppNewsletterJid, t as isWhat
2
2
  import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { missingTargetError } from "openclaw/plugin-sdk/channel-feedback";
4
4
  //#region extensions/whatsapp/src/resolve-outbound-target.ts
5
- function whatsappAllowFromPolicyError(target) {
6
- return /* @__PURE__ */ new Error(`Target "${target}" is not listed in the configured WhatsApp allowFrom policy.`);
7
- }
8
5
  function resolveWhatsAppOutboundTarget(params) {
9
6
  const trimmed = params.to?.trim() ?? "";
10
- if (!trimmed) return {
11
- ok: false,
12
- error: missingTargetError("WhatsApp", "<E.164|group JID|newsletter JID>")
13
- };
14
7
  const normalizedTo = normalizeWhatsAppTarget(trimmed);
15
8
  if (!normalizedTo) return {
16
9
  ok: false,
@@ -23,17 +16,13 @@ function resolveWhatsAppOutboundTarget(params) {
23
16
  const allowListRaw = normalizeStringEntries(params.allowFrom ?? []);
24
17
  const hasWildcard = allowListRaw.includes("*");
25
18
  const allowList = allowListRaw.filter((entry) => entry !== "*").map((entry) => normalizeWhatsAppTarget(entry)).filter((entry) => Boolean(entry));
26
- if (hasWildcard || allowList.length === 0) return {
27
- ok: true,
28
- to: normalizedTo
29
- };
30
- if (allowList.includes(normalizedTo)) return {
19
+ if (hasWildcard || allowList.length === 0 || allowList.includes(normalizedTo)) return {
31
20
  ok: true,
32
21
  to: normalizedTo
33
22
  };
34
23
  return {
35
24
  ok: false,
36
- error: whatsappAllowFromPolicyError(normalizedTo)
25
+ error: /* @__PURE__ */ new Error(`Target "${normalizedTo}" is not listed in the configured WhatsApp allowFrom policy.`)
37
26
  };
38
27
  }
39
28
  //#endregion
@@ -1,8 +1,8 @@
1
- import { a as resolveWhatsAppAccount, c as resolveMergedWhatsAppAccountConfig, s as resolveWhatsAppMediaMaxBytes } from "./accounts-CtRPAQCL.mjs";
1
+ import { a as resolveWhatsAppAccount, c as resolveMergedWhatsAppAccountConfig, s as resolveWhatsAppMediaMaxBytes } from "./accounts-F0vHuze2.mjs";
2
2
  import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.mjs";
3
3
  import { n as isWhatsAppNewsletterJid } from "./normalize-target-BGra1ZnM.mjs";
4
4
  import { r as getWhatsAppConnectionController } from "./connection-controller-runtime-context-hgLJoRc8.mjs";
5
- import { a as markdownToWhatsAppChunks, c as toWhatsappJid } from "./targets-runtime-DmiqXIXO.mjs";
5
+ import { a as markdownToWhatsAppChunks, c as toWhatsappJid } from "./targets-runtime-Dls-Xh4F.mjs";
6
6
  import path from "node:path";
7
7
  import { normalizeStringEntries, normalizeUniqueStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { resolveReactionLevel } from "openclaw/plugin-sdk/status-helpers";
@@ -53,6 +53,33 @@ function stripAsciiControlCharacters(value) {
53
53
  }
54
54
  //#endregion
55
55
  //#region extensions/whatsapp/src/inbound/send-result.ts
56
+ function listWhatsAppDeliveredMessageIdentities(results, acceptChannel) {
57
+ const identities = [];
58
+ const seen = /* @__PURE__ */ new Set();
59
+ const add = (params) => {
60
+ if (!acceptChannel(params.channel)) return;
61
+ const messageId = params.messageId?.trim() ?? "";
62
+ const remoteJid = params.toJid?.trim() ?? "";
63
+ const key = `${remoteJid}:${messageId}`;
64
+ if (!messageId || messageId === "unknown" || !remoteJid || seen.has(key)) return;
65
+ seen.add(key);
66
+ identities.push({
67
+ messageId,
68
+ remoteJid
69
+ });
70
+ };
71
+ for (const result of results) {
72
+ if (result.channel !== "whatsapp") continue;
73
+ add(result);
74
+ for (const raw of result.receipt?.raw ?? []) add(raw);
75
+ for (const part of result.receipt?.parts ?? []) add({
76
+ channel: part.raw?.channel,
77
+ messageId: part.raw?.messageId ?? part.platformMessageId,
78
+ toJid: part.raw?.toJid
79
+ });
80
+ }
81
+ return identities;
82
+ }
56
83
  const activityAccountedWhatsAppSendResults = /* @__PURE__ */ new WeakSet();
57
84
  const logicalWhatsAppDeliveryActivity = new AsyncLocalStorage();
58
85
  /** Keep all separately produced platform sends inside one logical reply accounting scope. */
@@ -286,9 +313,7 @@ function combineWhatsAppSendResults(kind, results) {
286
313
  function listWhatsAppSendResultMessageIds(result) {
287
314
  const receiptIds = result.receipt ? listMessageReceiptPlatformIds(result.receipt) : [];
288
315
  if (receiptIds.length > 0) return receiptIds;
289
- const keyIds = normalizeStringEntries(result.keys.map((key) => key.id));
290
- if (keyIds.length > 0) return uniqueStrings(keyIds);
291
- return [];
316
+ return uniqueStrings(normalizeStringEntries(result.keys.map((key) => key.id)));
292
317
  }
293
318
  //#endregion
294
319
  //#region extensions/whatsapp/src/outbound-media-contract.ts
@@ -684,4 +709,4 @@ async function sendPollWhatsApp(to, poll, options) {
684
709
  }
685
710
  }
686
711
  //#endregion
687
- export { resolveWhatsAppDocumentFileName as _, sendWhatsAppUploadFile as a, normalizeWhatsAppPayloadTextPreservingIndentation as c, listWhatsAppSendResultMessageIds as d, mergeWhatsAppAcceptedSendError as f, withWhatsAppLogicalDeliveryActivity as g, rememberWhatsAppPartialSend as h, sendTypingWhatsApp as i, prepareWhatsAppOutboundMedia as l, rememberWhatsAppAcceptedSend as m, sendPollWhatsApp as n, normalizeWhatsAppOutboundPayload as o, normalizeWhatsAppSendResult as p, sendReactionWhatsApp as r, normalizeWhatsAppPayloadText as s, sendMessageWhatsApp as t, combineWhatsAppSendResults as u, resolveWhatsAppReactionLevel as v };
712
+ export { withWhatsAppLogicalDeliveryActivity as _, sendWhatsAppUploadFile as a, normalizeWhatsAppPayloadTextPreservingIndentation as c, listWhatsAppDeliveredMessageIdentities as d, listWhatsAppSendResultMessageIds as f, rememberWhatsAppPartialSend as g, rememberWhatsAppAcceptedSend as h, sendTypingWhatsApp as i, prepareWhatsAppOutboundMedia as l, normalizeWhatsAppSendResult as m, sendPollWhatsApp as n, normalizeWhatsAppOutboundPayload as o, mergeWhatsAppAcceptedSendError as p, sendReactionWhatsApp as r, normalizeWhatsAppPayloadText as s, sendMessageWhatsApp as t, combineWhatsAppSendResults as u, resolveWhatsAppDocumentFileName as v, resolveWhatsAppReactionLevel as y };
@@ -1,12 +1,13 @@
1
1
  import { n as isWhatsAppNewsletterJid } from "./normalize-target-BGra1ZnM.mjs";
2
- import { _ as resolveWhatsAppDocumentFileName, f as mergeWhatsAppAcceptedSendError, m as rememberWhatsAppAcceptedSend, p as normalizeWhatsAppSendResult, u as combineWhatsAppSendResults } from "./send-BGdvf5cC.mjs";
3
- import { c as toWhatsappJid, l as toWhatsappJidWithLid, r as jidToE164 } from "./targets-runtime-DmiqXIXO.mjs";
4
- import { i as buildQuotedMessageOptions } from "./group-session-key-2-mja4OF.mjs";
5
- import { k as resolveComparableIdentity } from "./auth-store-BBonwKks.mjs";
2
+ import { h as rememberWhatsAppAcceptedSend, m as normalizeWhatsAppSendResult, p as mergeWhatsAppAcceptedSendError, u as combineWhatsAppSendResults, v as resolveWhatsAppDocumentFileName } from "./send-CGUsUdoX.mjs";
3
+ import { c as toWhatsappJid, l as toWhatsappJidWithLid, r as jidToE164 } from "./targets-runtime-Dls-Xh4F.mjs";
4
+ import { r as buildQuotedMessageOptions } from "./group-session-key-BV8Le9r8.mjs";
5
+ import { O as resolveComparableIdentity } from "./auth-store-D2rN-hP5.mjs";
6
6
  import { isRecord, normalizeLowercaseStringOrEmpty, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
8
8
  import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound";
9
9
  import { getImageMetadata, resizeToJpeg } from "openclaw/plugin-sdk/media-runtime";
10
+ import { isInsideCode } from "openclaw/plugin-sdk/text-chunking";
10
11
  import { extractMessageContent, getContentType, normalizeMessageContent } from "baileys";
11
12
  //#region extensions/whatsapp/src/vcard.ts
12
13
  const ALLOWED_VCARD_KEYS = /* @__PURE__ */ new Set([
@@ -379,7 +380,7 @@ function collectCodeRanges(text) {
379
380
  });
380
381
  for (const match of text.matchAll(INLINE_CODE_RE)) {
381
382
  const start = match.index;
382
- if (ranges.some((range) => start >= range.start && start < range.end)) continue;
383
+ if (isInsideCode(start, ranges)) continue;
383
384
  ranges.push({
384
385
  start,
385
386
  end: start + match[0].length
@@ -387,9 +388,6 @@ function collectCodeRanges(text) {
387
388
  }
388
389
  return ranges.toSorted((a, b) => a.start - b.start);
389
390
  }
390
- function isInRange(index, ranges) {
391
- return ranges.some((range) => index >= range.start && index < range.end);
392
- }
393
391
  function normalizeKnownUserJid(value) {
394
392
  const trimmed = value.replace(/^whatsapp:/i, "").trim();
395
393
  const jidMatch = trimmed.match(KNOWN_USER_JID_RE);
@@ -425,11 +423,7 @@ function extractLidDigits(value) {
425
423
  const parts = extractKnownJidParts(value);
426
424
  return parts && LID_JID_DOMAIN_RE.test(parts.domain) ? parts.user : null;
427
425
  }
428
- function participantValues(participant) {
429
- return typeof participant === "string" ? { id: participant } : participant;
430
- }
431
- function chooseMentionJid(participant) {
432
- const values = participantValues(participant);
426
+ function chooseMentionJid(values) {
433
427
  const idJid = normalizeKnownUserJid(values.id ?? "");
434
428
  const lidJid = normalizeKnownUserJid(values.lid ?? "");
435
429
  return (extractLidDigits(idJid) ? idJid : null) ?? (extractLidDigits(lidJid) ? lidJid : null) ?? idJid ?? lidJid ?? normalizeKnownUserJid(values.phoneNumber ?? "") ?? normalizeKnownUserJid(values.e164 ?? "");
@@ -438,14 +432,14 @@ function buildMentionTargetMaps(participants) {
438
432
  const byPhone = /* @__PURE__ */ new Map();
439
433
  const byLid = /* @__PURE__ */ new Map();
440
434
  for (const participant of participants) {
441
- const mentionJid = chooseMentionJid(participant);
435
+ const values = typeof participant === "string" ? { id: participant } : participant;
436
+ const mentionJid = chooseMentionJid(values);
442
437
  if (!mentionJid) continue;
443
438
  const lidDigits = extractLidDigits(mentionJid);
444
439
  const target = {
445
440
  mentionJid,
446
441
  ...lidDigits ? { replacementText: `@${lidDigits}` } : {}
447
442
  };
448
- const values = participantValues(participant);
449
443
  for (const value of [
450
444
  values.id,
451
445
  values.phoneNumber,
@@ -465,7 +459,7 @@ function buildMentionTargetMaps(participants) {
465
459
  };
466
460
  }
467
461
  function shouldSkipMentionAt(text, index, end, codeRanges) {
468
- if (isInRange(index, codeRanges)) return true;
462
+ if (isInsideCode(index, codeRanges)) return true;
469
463
  const previous = index > 0 ? text[index - 1] : "";
470
464
  const next = text[end] ?? "";
471
465
  return Boolean(previous && /[\w@]/.test(previous) || next && /[\w@]/.test(next));
@@ -482,8 +476,7 @@ function resolveWhatsAppOutboundMentions(params) {
482
476
  };
483
477
  const codeRanges = collectCodeRanges(params.text);
484
478
  const replacements = [];
485
- const mentionedJids = [];
486
- const seenMentionJids = /* @__PURE__ */ new Set();
479
+ const mentionedJids = /* @__PURE__ */ new Set();
487
480
  for (const match of params.text.matchAll(OUTBOUND_MENTION_RE)) {
488
481
  const start = match.index;
489
482
  const token = match[0];
@@ -493,10 +486,7 @@ function resolveWhatsAppOutboundMentions(params) {
493
486
  const digits = rawDigits.replace(/\D/g, "");
494
487
  const target = token.startsWith("@+") ? byPhone.get(digits) ?? byLid.get(digits) : byLid.get(digits) ?? byPhone.get(digits);
495
488
  if (!target) continue;
496
- if (!seenMentionJids.has(target.mentionJid)) {
497
- seenMentionJids.add(target.mentionJid);
498
- mentionedJids.push(target.mentionJid);
499
- }
489
+ mentionedJids.add(target.mentionJid);
500
490
  if (target.replacementText && target.replacementText !== token) replacements.push({
501
491
  start,
502
492
  end: start + token.length,
@@ -505,7 +495,7 @@ function resolveWhatsAppOutboundMentions(params) {
505
495
  }
506
496
  if (replacements.length === 0) return {
507
497
  text: params.text,
508
- mentionedJids
498
+ mentionedJids: [...mentionedJids]
509
499
  };
510
500
  let text = "";
511
501
  let cursor = 0;
@@ -517,7 +507,7 @@ function resolveWhatsAppOutboundMentions(params) {
517
507
  text += params.text.slice(cursor);
518
508
  return {
519
509
  text,
520
- mentionedJids
510
+ mentionedJids: [...mentionedJids]
521
511
  };
522
512
  }
523
513
  function addWhatsAppOutboundMentionsToContent(content, mentionedJids) {
@@ -620,36 +610,28 @@ function createWebSendApi(params) {
620
610
  }
621
611
  });
622
612
  },
623
- sendPoll: async (to, poll) => {
624
- return await sendStructuredMessage(to, { poll: {
625
- name: poll.question,
626
- values: poll.options,
627
- selectableCount: poll.maxSelections ?? 1
628
- } }, "poll");
629
- },
630
- sendContact: async (to, contact) => {
631
- return await sendStructuredMessage(to, { contacts: {
613
+ sendPoll: async (to, poll) => await sendStructuredMessage(to, { poll: {
614
+ name: poll.question,
615
+ values: poll.options,
616
+ selectableCount: poll.maxSelections ?? 1
617
+ } }, "poll"),
618
+ sendContact: async (to, contact) => await sendStructuredMessage(to, { contacts: {
619
+ displayName: contact.displayName,
620
+ contacts: [{
632
621
  displayName: contact.displayName,
633
- contacts: [{
634
- displayName: contact.displayName,
635
- vcard: contact.vcard
636
- }]
637
- } }, "contact");
638
- },
639
- sendLocation: async (to, location) => {
640
- return await sendStructuredMessage(to, { location: {
641
- degreesLatitude: location.degreesLatitude,
642
- degreesLongitude: location.degreesLongitude,
643
- name: location.name,
644
- address: location.address
645
- } }, "location");
646
- },
647
- sendSticker: async (to, stickerBuffer, options) => {
648
- return await sendStructuredMessage(to, {
649
- sticker: stickerBuffer,
650
- mimetype: options?.mimetype ?? "image/webp"
651
- }, "sticker");
652
- },
622
+ vcard: contact.vcard
623
+ }]
624
+ } }, "contact"),
625
+ sendLocation: async (to, location) => await sendStructuredMessage(to, { location: {
626
+ degreesLatitude: location.degreesLatitude,
627
+ degreesLongitude: location.degreesLongitude,
628
+ name: location.name,
629
+ address: location.address
630
+ } }, "location"),
631
+ sendSticker: async (to, stickerBuffer, options) => await sendStructuredMessage(to, {
632
+ sticker: stickerBuffer,
633
+ mimetype: options?.mimetype ?? "image/webp"
634
+ }, "sticker"),
653
635
  sendReaction: async (chatJid, messageId, emoji, fromMe, participant) => {
654
636
  const jid = resolveOutboundJid(chatJid);
655
637
  const result = await params.sock.sendMessage(jid, { react: {
@@ -1,8 +1,8 @@
1
- import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-CtRPAQCL.mjs";
1
+ import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-F0vHuze2.mjs";
2
2
  import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.mjs";
3
- import { r as hasWebCredsSync } from "./creds-files-CDATZWWM.mjs";
3
+ import { n as hasWebCredsSync } from "./creds-files-B8WcOAmE.mjs";
4
4
  import { a as normalizeWhatsAppAllowFromEntries, o as normalizeWhatsAppAllowFromEntry } from "./normalize-target-BGra1ZnM.mjs";
5
- import { n as whatsappSetupAdapter } from "./shared-DgOG5Iqr.mjs";
5
+ import { n as whatsappSetupAdapter } from "./shared-CP_zs2U7.mjs";
6
6
  import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
7
7
  import { DEFAULT_ACCOUNT_ID, createSetupTranslator, splitSetupEntries } from "openclaw/plugin-sdk/setup";
8
8
  //#region extensions/whatsapp/src/setup-finalize.ts
@@ -15,9 +15,7 @@ function isDefaultWhatsAppAccountKey(accountId) {
15
15
  }
16
16
  function shouldWriteDefaultWhatsAppAccountConfigAtAccountScope(cfg) {
17
17
  const accounts = cfg.channels?.whatsapp?.accounts;
18
- if (!accounts) return false;
19
- if (accounts.default) return true;
20
- return Object.keys(accounts).some((accountId) => !isDefaultWhatsAppAccountKey(accountId));
18
+ return Boolean(accounts && (accounts.default || Object.keys(accounts).some((accountId) => !isDefaultWhatsAppAccountKey(accountId))));
21
19
  }
22
20
  function resolveDefaultWhatsAppAccountWriteKey(cfg) {
23
21
  const accounts = cfg.channels?.whatsapp?.accounts;
@@ -96,14 +94,8 @@ async function applyWhatsAppOwnerAllowlist(params) {
96
94
  return next;
97
95
  }
98
96
  function parseWhatsAppAllowFromEntries(raw) {
99
- const parts = splitSetupEntries(raw);
100
- if (parts.length === 0) return { entries: [] };
101
97
  const entries = [];
102
- for (const part of parts) {
103
- if (part === "*") {
104
- entries.push("*");
105
- continue;
106
- }
98
+ for (const part of splitSetupEntries(raw)) {
107
99
  const normalized = normalizeWhatsAppAllowFromEntry(part);
108
100
  if (!normalized) return {
109
101
  entries: [],
@@ -181,15 +173,11 @@ async function promptWhatsAppDmAccess(params) {
181
173
  }
182
174
  ]
183
175
  });
184
- let next = mergeWhatsAppConfig(params.cfg, accountId, {
176
+ const next = mergeWhatsAppConfig(params.cfg, accountId, {
185
177
  selfChatMode: false,
186
178
  dmPolicy: policy
187
179
  });
188
- if (policy === "open") {
189
- const allowFrom = normalizeWhatsAppAllowFromEntries(["*", ...existingAllowFrom]);
190
- next = setWhatsAppAllowFrom(next, accountId, allowFrom.length > 0 ? allowFrom : ["*"]);
191
- return next;
192
- }
180
+ if (policy === "open") return setWhatsAppAllowFrom(next, accountId, normalizeWhatsAppAllowFromEntries(["*", ...existingAllowFrom]));
193
181
  if (policy === "disabled") return next;
194
182
  const allowOptions = existingAllowFrom.length > 0 ? [
195
183
  {
@@ -264,7 +252,7 @@ async function finalizeWhatsAppSetup(params) {
264
252
  })) {
265
253
  let persistenceGuardFailure;
266
254
  try {
267
- const { loginWeb } = await import("./login-BFlvSh9h.mjs").then((n) => n.n);
255
+ const { loginWeb } = await import("./login-CV_4V021.mjs").then((n) => n.n);
268
256
  const beforeCredentialPersistence = params.options?.beforePersistentEffect ? async () => {
269
257
  try {
270
258
  await params.options?.beforePersistentEffect?.();
@@ -0,0 +1,3 @@
1
+ import { t as whatsappSetupPlugin } from "./channel.setup-CsS_NAKQ.mjs";
2
+ import "../setup-plugin-api.js";
3
+ export { whatsappSetupPlugin };
@@ -1,6 +1,6 @@
1
- import { o as resolveWhatsAppAuthDir } from "./accounts-CtRPAQCL.mjs";
1
+ import { o as resolveWhatsAppAuthDir } from "./accounts-F0vHuze2.mjs";
2
2
  import { t as listAccountIds } from "./account-ids-CB5SOWjc.mjs";
3
- import { a as formatWhatsAppWebAuthStatusState, h as readWebAuthState } from "./auth-store-BBonwKks.mjs";
3
+ import { a as formatWhatsAppWebAuthStatusState, m as readWebAuthState } from "./auth-store-D2rN-hP5.mjs";
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-DmPX4EaW.mjs")).finalizeWhatsAppSetup(params),
39
+ finalize: async (params) => await (await import("./setup-finalize-GtBmrO8p.mjs")).finalizeWhatsAppSetup(params),
40
40
  disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
41
41
  onAccountRecorded: (accountId, options) => {
42
42
  options?.onAccountId?.(channel, accountId);
@@ -1,16 +1,16 @@
1
- import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-CtRPAQCL.mjs";
1
+ import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-F0vHuze2.mjs";
2
2
  import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.mjs";
3
3
  import { a as normalizeWhatsAppAllowFromEntries } from "./normalize-target-BGra1ZnM.mjs";
4
4
  import { t as WhatsAppChannelConfigSchema } from "./config-schema-BYA6e_Ii.mjs";
5
- import { n as whatsappDoctor } from "./doctor-iMwg0Vhr.mjs";
6
- import { t as resolveWhatsAppConfigPath } from "./group-config-path-DZr3ucUO.mjs";
5
+ import { n as whatsappDoctor } from "./doctor-DKzeBEmH.mjs";
6
+ import { t as resolveWhatsAppConfigPath } from "./group-config-path-BPrak_bJ.mjs";
7
7
  import { t as resolveLegacyGroupSessionKey } from "./group-session-contract-DDnZSsJ1.mjs";
8
8
  import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-nAzD945y.mjs";
9
9
  import { n as deriveLegacySessionChatType, r as isLegacyGroupSessionKey, t as canonicalizeLegacySessionKey } from "./session-contract-DMTm6Q_L.mjs";
10
10
  import { normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
11
11
  import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
12
12
  import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
13
- import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
13
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
14
14
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
15
15
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
16
16
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
@@ -20,14 +20,14 @@ import { readChannelAllowFromStore } from "openclaw/plugin-sdk/channel-pairing";
20
20
  import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
21
21
  import { createPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup";
22
22
  //#region extensions/whatsapp/src/channel-runtime-loader.ts
23
- const loadWhatsAppAuthStore = createLazyRuntimeModule(() => import("./auth-store-BBonwKks.mjs").then((n) => n.i));
23
+ const loadWhatsAppAuthStore = createLazyRuntimeModule(() => import("./auth-store-D2rN-hP5.mjs").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-C94goLw9.mjs");
30
+ return await import("./channel.runtime-BniF8Swm.mjs");
31
31
  });
32
32
  //#endregion
33
33
  //#region extensions/whatsapp/src/group-policy.ts
@@ -73,7 +73,7 @@ function applyGroupAllowFromFromStore(params) {
73
73
  return changed ? next : params.cfg;
74
74
  }
75
75
  async function applyWhatsAppSecurityConfigFixes(params) {
76
- const fromStore = await readChannelAllowFromStore("whatsapp", params.env, DEFAULT_ACCOUNT_ID).catch(() => []);
76
+ const fromStore = await readChannelAllowFromStore("whatsapp", params.env, DEFAULT_ACCOUNT_ID$1).catch(() => []);
77
77
  const normalized = normalizeUniqueStringEntries(fromStore);
78
78
  if (normalized.length === 0) return {
79
79
  config: params.cfg,
@@ -95,6 +95,7 @@ const whatsappSetupAdapter = {
95
95
  alwaysUseAccounts: true,
96
96
  buildPatch: (input) => input.authDir ? { authDir: input.authDir } : {}
97
97
  }),
98
+ configPromotion: "preserve-root",
98
99
  singleAccountKeysToMove: ["authDir"]
99
100
  };
100
101
  const whatsappSetupContract = defineChannelSetupContract({
@@ -126,12 +127,12 @@ const whatsappResolveDmPolicy = createScopedDmSecurityResolver({
126
127
  resolvePolicy: (account) => account.dmPolicy,
127
128
  resolveAllowFrom: (account) => account.allowFrom,
128
129
  policyPathSuffix: "dmPolicy",
129
- normalizeEntry: (raw) => normalizeE164(raw),
130
+ normalizeEntry: normalizeE164,
130
131
  inheritSharedDefaultsFromDefaultAccount: true
131
132
  });
132
133
  const whatsappSetupWizardProxy = createDelegatedSetupWizardProxy({
133
134
  channel: WHATSAPP_CHANNEL,
134
- loadWizard: async () => (await import("./setup-surface-43fj197P.mjs")).whatsappSetupWizard,
135
+ loadWizard: async () => (await import("./setup-surface-BuA39k6K.mjs")).whatsappSetupWizard,
135
136
  status: {
136
137
  configuredLabel: "linked",
137
138
  unconfiguredLabel: "not linked",
@@ -220,6 +221,7 @@ function createWhatsAppPluginBase() {
220
221
  ],
221
222
  polls: true,
222
223
  reactions: true,
224
+ reactionSlots: "single",
223
225
  media: true,
224
226
  tts: { voice: {
225
227
  synthesisTarget: "voice-note",
@@ -279,10 +281,7 @@ function createWhatsAppPluginBase() {
279
281
  deriveLegacySessionChatType,
280
282
  resolveLegacyGroupSessionKey,
281
283
  isLegacyGroupSessionKey,
282
- canonicalizeLegacySessionKey: (paramsLocal) => canonicalizeLegacySessionKey({
283
- key: paramsLocal.key,
284
- agentId: paramsLocal.agentId
285
- })
284
+ canonicalizeLegacySessionKey
286
285
  },
287
286
  secrets: {
288
287
  unsupportedSecretRefSurfacePatterns,