@openclaw/whatsapp 2026.5.12 → 2026.5.14-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +3 -3
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-DgVXntVm.js → channel-yIjmVwof.js} +1 -1
- package/dist/{channel.runtime-C4Ywu0dZ.js → channel.runtime-Dc5rfgsF.js} +1 -1
- package/dist/{channel.setup-DKp_w5Ru.js → channel.setup-KnsEGgS2.js} +1 -1
- package/dist/{monitor-CmK0ER1u.js → monitor-DTi0QRV4.js} +178 -26
- package/dist/runtime-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-DW9W6SXy.js → shared-B2VGBfCy.js} +1 -1
- package/package.json +4 -4
package/dist/api.js
CHANGED
|
@@ -5,12 +5,12 @@ import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-BK
|
|
|
5
5
|
import "./reaction-level-2m9sWGCw.js";
|
|
6
6
|
import { c as assertWebChannel, d as markdownToWhatsApp, f as resolveJidToE164, l as isSelfChatMode, m as toWhatsappJidWithLid, n as normalizeE164, p as toWhatsappJid, r as resolveUserPath, u as jidToE164 } from "./text-runtime-CMxQczvs.js";
|
|
7
7
|
import "./send-DBfXQDd4.js";
|
|
8
|
-
import { t as whatsappPlugin } from "./channel-
|
|
8
|
+
import { t as whatsappPlugin } from "./channel-yIjmVwof.js";
|
|
9
9
|
import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-base-BgtywpNm.js";
|
|
10
10
|
import { t as whatsappCommandPolicy } from "./command-policy-O8sRnqUV.js";
|
|
11
|
-
import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint } from "./shared-
|
|
11
|
+
import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint } from "./shared-B2VGBfCy.js";
|
|
12
12
|
import "./config-schema-Dmo66Ubb.js";
|
|
13
|
-
import { t as whatsappSetupPlugin } from "./channel.setup-
|
|
13
|
+
import { t as whatsappSetupPlugin } from "./channel.setup-KnsEGgS2.js";
|
|
14
14
|
import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-DLGCIbfl.js";
|
|
15
15
|
import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-CE74HYlw.js";
|
|
16
16
|
import { t as __testing } from "./access-control-BEpPB-Jx.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as whatsappPlugin } from "./channel-
|
|
1
|
+
import { t as whatsappPlugin } from "./channel-yIjmVwof.js";
|
|
2
2
|
export { whatsappPlugin };
|
|
@@ -10,7 +10,7 @@ import { t as createWhatsAppLoginTool } from "./agent-tools-login-DpRxLNRB.js";
|
|
|
10
10
|
import { t as createWhatsAppOutboundBase } from "./outbound-base-BgtywpNm.js";
|
|
11
11
|
import { t as getWhatsAppRuntime } from "./runtime-6fZ67abR.js";
|
|
12
12
|
import { t as whatsappCommandPolicy } from "./command-policy-O8sRnqUV.js";
|
|
13
|
-
import { a as resolveWhatsAppGroupToolPolicy, c as formatWhatsAppConfigAllowFromEntries, i as resolveWhatsAppGroupRequireMention, n as loadWhatsAppChannelRuntime, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, s as resolveWhatsAppMentionStripRegexes, t as createWhatsAppPluginBase } from "./shared-
|
|
13
|
+
import { a as resolveWhatsAppGroupToolPolicy, c as formatWhatsAppConfigAllowFromEntries, i as resolveWhatsAppGroupRequireMention, n as loadWhatsAppChannelRuntime, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, s as resolveWhatsAppMentionStripRegexes, t as createWhatsAppPluginBase } from "./shared-B2VGBfCy.js";
|
|
14
14
|
import { d as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-_ScMvp7r.js";
|
|
15
15
|
import { t as whatsappSetupAdapter } from "./setup-core-DZKvpzbH.js";
|
|
16
16
|
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-Bm0S67yH.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { startWebLoginWithQr as startWebLoginWithQr$1, waitForWebLogin as waitForWebLogin$1 } from "./login-qr-runtime.js";
|
|
2
2
|
import { a as getWebAuthAgeMs$1, b as webAuthExists$1, d as readWebAuthExistsForDecision$1, f as readWebAuthSnapshot$1, h as readWebSelfId$1, m as readWebAuthState$1, o as logWebSelfId$1, p as readWebAuthSnapshotBestEffort$1, s as logoutWeb$1, u as readWebAuthExistsBestEffort$1 } from "./auth-store-_ScMvp7r.js";
|
|
3
3
|
import { t as getActiveWebListener$1 } from "./active-listener-DTbKS-j-.js";
|
|
4
|
-
import { t as monitorWebChannel$1 } from "./monitor-
|
|
4
|
+
import { t as monitorWebChannel$1 } from "./monitor-DTi0QRV4.js";
|
|
5
5
|
import { t as loginWeb$1 } from "./login-B_pa3YAU.js";
|
|
6
6
|
import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-BbwSSEsy.js";
|
|
7
7
|
//#region extensions/whatsapp/src/channel.runtime.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, t as createWhatsAppPluginBase } from "./shared-
|
|
1
|
+
import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, t as createWhatsAppPluginBase } from "./shared-B2VGBfCy.js";
|
|
2
2
|
import { m as readWebAuthState } from "./auth-store-_ScMvp7r.js";
|
|
3
3
|
import { t as whatsappSetupAdapter } from "./setup-core-DZKvpzbH.js";
|
|
4
4
|
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-Bm0S67yH.js";
|
|
@@ -14,7 +14,7 @@ import { i as resolveWhatsAppSocketTiming, r as waitForWaConnection, t as create
|
|
|
14
14
|
import { c as computeBackoff, d as resolveReconnectPolicy, f as sleepWithAbort, l as newConnectionId, n as WHATSAPP_WATCHDOG_TIMEOUT_ERROR, r as WhatsAppConnectionController, s as DEFAULT_RECONNECT_POLICY, u as resolveHeartbeatSeconds } from "./connection-controller-CT8NA6Zf.js";
|
|
15
15
|
import { resolveAccountEntry } from "openclaw/plugin-sdk/account-core";
|
|
16
16
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
|
-
import { createAckReactionHandle, logAckFailure, removeAckReactionHandleAfterReply, shouldAckReactionForWhatsApp } from "openclaw/plugin-sdk/channel-feedback";
|
|
17
|
+
import { DEFAULT_TIMING, createAckReactionHandle, createStatusReactionController, logAckFailure, removeAckReactionHandleAfterReply, shouldAckReactionForWhatsApp } from "openclaw/plugin-sdk/channel-feedback";
|
|
18
18
|
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
19
19
|
import { getChildLogger } from "openclaw/plugin-sdk/logging-core";
|
|
20
20
|
import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
@@ -38,7 +38,7 @@ import { drainPendingDeliveries } from "openclaw/plugin-sdk/delivery-queue-runti
|
|
|
38
38
|
import { DEFAULT_GROUP_HISTORY_LIMIT, buildHistoryContextFromEntries, recordPendingHistoryEntryIfEnabled } from "openclaw/plugin-sdk/reply-history";
|
|
39
39
|
import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
40
40
|
import { createClaimableDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
41
|
-
import {
|
|
41
|
+
import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
42
42
|
import { getRuntimeConfig as getRuntimeConfig$1, getRuntimeConfigSourceSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
43
43
|
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
44
44
|
import { buildMentionRegexes, implicitMentionKindWhen, normalizeMentionText, resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-mention-gating";
|
|
@@ -159,6 +159,12 @@ function closeInboundMonitorSocket(sock) {
|
|
|
159
159
|
}
|
|
160
160
|
//#endregion
|
|
161
161
|
//#region extensions/whatsapp/src/inbound/media.ts
|
|
162
|
+
var WhatsAppInboundMediaLimitExceededError = class extends Error {
|
|
163
|
+
constructor(maxBytes) {
|
|
164
|
+
super(`Media exceeds ${Math.round(maxBytes / (1024 * 1024))}MB limit`);
|
|
165
|
+
this.name = "WhatsAppInboundMediaLimitExceededError";
|
|
166
|
+
}
|
|
167
|
+
};
|
|
162
168
|
function unwrapMessage(message) {
|
|
163
169
|
return normalizeMessageContent$1(message);
|
|
164
170
|
}
|
|
@@ -174,7 +180,7 @@ function resolveMediaMimetype(message) {
|
|
|
174
180
|
if (message.videoMessage) return "video/mp4";
|
|
175
181
|
if (message.stickerMessage) return "image/webp";
|
|
176
182
|
}
|
|
177
|
-
async function downloadInboundMedia(msg, sock) {
|
|
183
|
+
async function downloadInboundMedia(msg, sock, maxBytes = 50 * 1024 * 1024) {
|
|
178
184
|
const message = unwrapMessage(msg.message);
|
|
179
185
|
if (!message) return;
|
|
180
186
|
const mimetype = resolveMediaMimetype(message);
|
|
@@ -182,19 +188,23 @@ async function downloadInboundMedia(msg, sock) {
|
|
|
182
188
|
if (!message.imageMessage && !message.videoMessage && !message.documentMessage && !message.audioMessage && !message.stickerMessage) return;
|
|
183
189
|
try {
|
|
184
190
|
return {
|
|
185
|
-
|
|
191
|
+
saved: await saveMediaStream(await downloadMediaMessage(msg, "stream", {}, {
|
|
186
192
|
reuploadRequest: sock.updateMediaMessage,
|
|
187
193
|
logger: sock.logger
|
|
194
|
+
}), mimetype, "inbound", maxBytes, fileName).catch((err) => {
|
|
195
|
+
if (err instanceof Error && /Media exceeds/i.test(err.message)) throw new WhatsAppInboundMediaLimitExceededError(maxBytes);
|
|
196
|
+
throw err;
|
|
188
197
|
}),
|
|
189
198
|
mimetype,
|
|
190
199
|
fileName
|
|
191
200
|
};
|
|
192
201
|
} catch (err) {
|
|
202
|
+
if (err instanceof WhatsAppInboundMediaLimitExceededError) throw err;
|
|
193
203
|
logVerbose(`downloadMediaMessage failed: ${String(err)}`);
|
|
194
204
|
return;
|
|
195
205
|
}
|
|
196
206
|
}
|
|
197
|
-
async function downloadQuotedInboundMedia(msg, sock) {
|
|
207
|
+
async function downloadQuotedInboundMedia(msg, sock, maxBytes = 50 * 1024 * 1024) {
|
|
198
208
|
const contextInfo = extractContextInfo(unwrapMessage(msg.message));
|
|
199
209
|
if (!contextInfo?.quotedMessage) return;
|
|
200
210
|
const quotedMessage = contextInfo.quotedMessage;
|
|
@@ -207,7 +217,7 @@ async function downloadQuotedInboundMedia(msg, sock) {
|
|
|
207
217
|
},
|
|
208
218
|
message: quotedMessage,
|
|
209
219
|
messageTimestamp: msg.messageTimestamp
|
|
210
|
-
}, sock);
|
|
220
|
+
}, sock, maxBytes);
|
|
211
221
|
}
|
|
212
222
|
//#endregion
|
|
213
223
|
//#region extensions/whatsapp/src/inbound/monitor.ts
|
|
@@ -557,16 +567,16 @@ async function attachWebInboxToSocket(options) {
|
|
|
557
567
|
let mediaPath;
|
|
558
568
|
let mediaType;
|
|
559
569
|
let mediaFileName;
|
|
570
|
+
const maxBytes = (typeof options.mediaMaxMb === "number" && options.mediaMaxMb > 0 ? options.mediaMaxMb : 50) * 1024 * 1024;
|
|
560
571
|
const saveInboundMedia = async (inboundMedia) => {
|
|
561
572
|
if (!inboundMedia) return;
|
|
562
|
-
|
|
563
|
-
mediaPath = (await saveMediaBuffer(inboundMedia.buffer, inboundMedia.mimetype, "inbound", maxBytes, inboundMedia.fileName)).path;
|
|
573
|
+
mediaPath = inboundMedia.saved.path;
|
|
564
574
|
mediaType = inboundMedia.mimetype;
|
|
565
575
|
mediaFileName = inboundMedia.fileName;
|
|
566
576
|
};
|
|
567
577
|
try {
|
|
568
|
-
await saveInboundMedia(await downloadInboundMedia(msg, sock));
|
|
569
|
-
if (!mediaPath && replyContext) await saveInboundMedia(await downloadQuotedInboundMedia(msg, sock));
|
|
578
|
+
await saveInboundMedia(await downloadInboundMedia(msg, sock, maxBytes));
|
|
579
|
+
if (!mediaPath && replyContext) await saveInboundMedia(await downloadQuotedInboundMedia(msg, sock, maxBytes));
|
|
570
580
|
} catch (err) {
|
|
571
581
|
logWhatsAppVerbose(options.verbose, `Inbound media download failed: ${String(err)}`);
|
|
572
582
|
}
|
|
@@ -1810,6 +1820,12 @@ function updateWhatsAppMainLastRoute(params) {
|
|
|
1810
1820
|
if (params.dmRouteTarget && inboundLastRouteSessionKey === params.route.mainSessionKey && params.pinnedMainDmRecipient) logVerbose$1(`Skipping main-session last route update for ${params.dmRouteTarget} (pinned owner ${params.pinnedMainDmRecipient})`);
|
|
1811
1821
|
}
|
|
1812
1822
|
async function dispatchWhatsAppBufferedReply(params) {
|
|
1823
|
+
const statusReactionController = params.statusReactionController ?? null;
|
|
1824
|
+
const statusReactionTiming = {
|
|
1825
|
+
...DEFAULT_TIMING,
|
|
1826
|
+
...params.cfg.messages?.statusReactions?.timing
|
|
1827
|
+
};
|
|
1828
|
+
const removeAckAfterReply = params.cfg.messages?.removeAckAfterReply ?? false;
|
|
1813
1829
|
const textLimit = params.maxMediaTextChunkLimit ?? resolveTextChunkLimit(params.cfg, "whatsapp");
|
|
1814
1830
|
const chunkMode = resolveChunkMode(params.cfg, "whatsapp", params.route.accountId);
|
|
1815
1831
|
const tableMode = resolveMarkdownTableMode$1({
|
|
@@ -1869,6 +1885,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
1869
1885
|
const mediaOnlyCoalescer = createWhatsAppMediaOnlyReplyCoalescer({ deliver: async (pending) => {
|
|
1870
1886
|
await deliverNormalizedPayload(pending.payload, pending.info);
|
|
1871
1887
|
} });
|
|
1888
|
+
if (statusReactionController) statusReactionController.setThinking();
|
|
1872
1889
|
const { queuedFinal, counts } = await dispatchReplyWithBufferedBlockDispatcher({
|
|
1873
1890
|
ctx: params.context,
|
|
1874
1891
|
cfg: params.cfg,
|
|
@@ -1940,6 +1957,15 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
1940
1957
|
await deliverNormalizedPayload(normalizedDeliveryPayload, info);
|
|
1941
1958
|
},
|
|
1942
1959
|
onReplyStart: params.msg.sendComposing,
|
|
1960
|
+
...statusReactionController ? {
|
|
1961
|
+
onCompactionStart: async () => {
|
|
1962
|
+
await statusReactionController.setCompacting();
|
|
1963
|
+
},
|
|
1964
|
+
onCompactionEnd: async () => {
|
|
1965
|
+
statusReactionController.cancelPending();
|
|
1966
|
+
await statusReactionController.setThinking();
|
|
1967
|
+
}
|
|
1968
|
+
} : {},
|
|
1943
1969
|
onError: (err, info) => {
|
|
1944
1970
|
logWhatsAppReplyDeliveryError({
|
|
1945
1971
|
err,
|
|
@@ -1954,7 +1980,11 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
1954
1980
|
replyOptions: {
|
|
1955
1981
|
disableBlockStreaming,
|
|
1956
1982
|
...sourceReplyDeliveryMode ? { sourceReplyDeliveryMode } : {},
|
|
1957
|
-
onModelSelected: params.onModelSelected
|
|
1983
|
+
onModelSelected: params.onModelSelected,
|
|
1984
|
+
...statusReactionController ? { onToolStart: async (payload) => {
|
|
1985
|
+
const toolName = payload.name?.trim();
|
|
1986
|
+
if (toolName) await statusReactionController.setTool(toolName);
|
|
1987
|
+
} } : {}
|
|
1958
1988
|
}
|
|
1959
1989
|
});
|
|
1960
1990
|
logWhatsAppMediaOnlyFlushResult(await mediaOnlyCoalescer.flushAll());
|
|
@@ -1962,13 +1992,47 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
1962
1992
|
queuedFinal,
|
|
1963
1993
|
counts
|
|
1964
1994
|
})) {
|
|
1995
|
+
if (statusReactionController) finalizeWhatsAppStatusReaction({
|
|
1996
|
+
controller: statusReactionController,
|
|
1997
|
+
outcome: "error",
|
|
1998
|
+
hasFinalResponse: false,
|
|
1999
|
+
removeAckAfterReply,
|
|
2000
|
+
timing: statusReactionTiming
|
|
2001
|
+
});
|
|
1965
2002
|
if (params.shouldClearGroupHistory) params.groupHistories.set(params.groupHistoryKey, []);
|
|
1966
2003
|
logVerbose$1("Skipping auto-reply: silent token or no text/media returned from resolver");
|
|
1967
2004
|
return false;
|
|
1968
2005
|
}
|
|
2006
|
+
if (statusReactionController) finalizeWhatsAppStatusReaction({
|
|
2007
|
+
controller: statusReactionController,
|
|
2008
|
+
outcome: didSendReply ? "done" : "error",
|
|
2009
|
+
hasFinalResponse: didSendReply,
|
|
2010
|
+
removeAckAfterReply,
|
|
2011
|
+
timing: statusReactionTiming
|
|
2012
|
+
});
|
|
1969
2013
|
if (params.shouldClearGroupHistory) params.groupHistories.set(params.groupHistoryKey, []);
|
|
1970
2014
|
return didSendReply;
|
|
1971
2015
|
}
|
|
2016
|
+
async function finalizeWhatsAppStatusReaction(params) {
|
|
2017
|
+
if (params.outcome === "done") {
|
|
2018
|
+
await params.controller.setDone();
|
|
2019
|
+
if (params.removeAckAfterReply) {
|
|
2020
|
+
await new Promise((resolve) => setTimeout(resolve, params.timing.doneHoldMs));
|
|
2021
|
+
await params.controller.clear();
|
|
2022
|
+
} else await params.controller.restoreInitial();
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
await params.controller.setError();
|
|
2026
|
+
if (params.hasFinalResponse) {
|
|
2027
|
+
if (params.removeAckAfterReply) {
|
|
2028
|
+
await new Promise((resolve) => setTimeout(resolve, params.timing.errorHoldMs));
|
|
2029
|
+
await params.controller.clear();
|
|
2030
|
+
} else await params.controller.restoreInitial();
|
|
2031
|
+
return;
|
|
2032
|
+
}
|
|
2033
|
+
if (params.removeAckAfterReply) await new Promise((resolve) => setTimeout(resolve, params.timing.errorHoldMs));
|
|
2034
|
+
await params.controller.restoreInitial();
|
|
2035
|
+
}
|
|
1972
2036
|
//#endregion
|
|
1973
2037
|
//#region extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts
|
|
1974
2038
|
function normalizeAgentId$1(agentId) {
|
|
@@ -2019,6 +2083,66 @@ function buildInboundLine(params) {
|
|
|
2019
2083
|
});
|
|
2020
2084
|
}
|
|
2021
2085
|
//#endregion
|
|
2086
|
+
//#region extensions/whatsapp/src/auto-reply/monitor/status-reaction.ts
|
|
2087
|
+
async function createWhatsAppStatusReactionController(params) {
|
|
2088
|
+
if (!params.msg.id) return null;
|
|
2089
|
+
const statusReactionsConfig = params.cfg.messages?.statusReactions;
|
|
2090
|
+
if (statusReactionsConfig?.enabled !== true) return null;
|
|
2091
|
+
if (resolveWhatsAppReactionLevel({
|
|
2092
|
+
cfg: params.cfg,
|
|
2093
|
+
accountId: params.accountId
|
|
2094
|
+
}).level === "off") return null;
|
|
2095
|
+
const ackConfig = params.cfg.channels?.whatsapp?.ackReaction;
|
|
2096
|
+
const ackEmoji = (ackConfig?.emoji ?? "").trim();
|
|
2097
|
+
if (!ackEmoji) return null;
|
|
2098
|
+
const directEnabled = ackConfig?.direct ?? true;
|
|
2099
|
+
const groupMode = ackConfig?.group ?? "mentions";
|
|
2100
|
+
const conversationIdForCheck = params.msg.conversationId ?? params.msg.from;
|
|
2101
|
+
const activation = params.msg.chatType === "group" ? await resolveGroupActivationFor({
|
|
2102
|
+
cfg: params.cfg,
|
|
2103
|
+
accountId: params.accountId,
|
|
2104
|
+
agentId: params.agentId,
|
|
2105
|
+
sessionKey: params.sessionKey,
|
|
2106
|
+
conversationId: conversationIdForCheck
|
|
2107
|
+
}) : null;
|
|
2108
|
+
if (!shouldAckReactionForWhatsApp({
|
|
2109
|
+
emoji: ackEmoji,
|
|
2110
|
+
isDirect: params.msg.chatType === "direct",
|
|
2111
|
+
isGroup: params.msg.chatType === "group",
|
|
2112
|
+
directEnabled,
|
|
2113
|
+
groupMode,
|
|
2114
|
+
wasMentioned: params.msg.wasMentioned === true,
|
|
2115
|
+
groupActivated: activation === "always"
|
|
2116
|
+
})) return null;
|
|
2117
|
+
const sender = getSenderIdentity(params.msg);
|
|
2118
|
+
const reactionOptions = {
|
|
2119
|
+
verbose: params.verbose,
|
|
2120
|
+
fromMe: false,
|
|
2121
|
+
...sender.jid ? { participant: sender.jid } : {},
|
|
2122
|
+
...params.accountId ? { accountId: params.accountId } : {},
|
|
2123
|
+
cfg: params.cfg
|
|
2124
|
+
};
|
|
2125
|
+
const chatId = params.msg.chatId;
|
|
2126
|
+
const msgId = params.msg.id;
|
|
2127
|
+
return createStatusReactionController({
|
|
2128
|
+
enabled: true,
|
|
2129
|
+
adapter: {
|
|
2130
|
+
setReaction: async (emoji) => {
|
|
2131
|
+
await sendReactionWhatsApp(chatId, msgId, emoji, reactionOptions);
|
|
2132
|
+
},
|
|
2133
|
+
clearReaction: async () => {
|
|
2134
|
+
await sendReactionWhatsApp(chatId, msgId, "", reactionOptions);
|
|
2135
|
+
}
|
|
2136
|
+
},
|
|
2137
|
+
initialEmoji: ackEmoji,
|
|
2138
|
+
emojis: statusReactionsConfig.emojis,
|
|
2139
|
+
timing: statusReactionsConfig.timing,
|
|
2140
|
+
onError: (err) => {
|
|
2141
|
+
logVerbose(`WhatsApp status-reaction error for chat ${chatId}/${msgId}: ${String(err)}`);
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
//#endregion
|
|
2022
2146
|
//#region extensions/whatsapp/src/auto-reply/monitor/process-message.ts
|
|
2023
2147
|
const WHATSAPP_MESSAGE_RECEIVED_HOOK_LIMITS = {
|
|
2024
2148
|
maxConcurrency: 8,
|
|
@@ -2147,8 +2271,18 @@ async function processMessage(params) {
|
|
|
2147
2271
|
params.echoForget(combinedEchoKey);
|
|
2148
2272
|
return false;
|
|
2149
2273
|
}
|
|
2274
|
+
const statusReactionController = params.statusReactionController ?? (params.cfg.messages?.statusReactions?.enabled === true && !params.ackAlreadySent ? await createWhatsAppStatusReactionController({
|
|
2275
|
+
cfg: params.cfg,
|
|
2276
|
+
msg: params.msg,
|
|
2277
|
+
agentId: params.route.agentId,
|
|
2278
|
+
sessionKey: params.route.sessionKey,
|
|
2279
|
+
conversationId,
|
|
2280
|
+
verbose: params.verbose,
|
|
2281
|
+
accountId: account.accountId
|
|
2282
|
+
}) : null);
|
|
2283
|
+
if (statusReactionController && !params.statusReactionController) statusReactionController.setQueued();
|
|
2150
2284
|
let ackReaction = params.ackReaction ?? null;
|
|
2151
|
-
if (!ackReaction && params.ackAlreadySent !== true) ackReaction = await maybeSendAckReaction({
|
|
2285
|
+
if (!statusReactionController && !ackReaction && params.ackAlreadySent !== true) ackReaction = await maybeSendAckReaction({
|
|
2152
2286
|
cfg: params.cfg,
|
|
2153
2287
|
msg: params.msg,
|
|
2154
2288
|
agentId: params.route.agentId,
|
|
@@ -2305,7 +2439,8 @@ async function processMessage(params) {
|
|
|
2305
2439
|
},
|
|
2306
2440
|
replyResolver: params.replyResolver,
|
|
2307
2441
|
route: params.route,
|
|
2308
|
-
shouldClearGroupHistory
|
|
2442
|
+
shouldClearGroupHistory,
|
|
2443
|
+
statusReactionController
|
|
2309
2444
|
})
|
|
2310
2445
|
})
|
|
2311
2446
|
}
|
|
@@ -2352,6 +2487,7 @@ function createWebOnMessageHandler(params) {
|
|
|
2352
2487
|
if (opts?.preflightAudioTranscript !== void 0) processParams.preflightAudioTranscript = opts.preflightAudioTranscript;
|
|
2353
2488
|
if (opts?.ackAlreadySent === true) processParams.ackAlreadySent = true;
|
|
2354
2489
|
if (opts?.ackReaction !== void 0) processParams.ackReaction = opts.ackReaction;
|
|
2490
|
+
if (opts?.statusReactionController !== void 0) processParams.statusReactionController = opts.statusReactionController;
|
|
2355
2491
|
return processMessage(processParams);
|
|
2356
2492
|
};
|
|
2357
2493
|
return async (msg) => {
|
|
@@ -2390,20 +2526,34 @@ function createWebOnMessageHandler(params) {
|
|
|
2390
2526
|
const canRunEarlyAudioPreflight = msg.chatType === "group" || msg.accessControlPassed === true;
|
|
2391
2527
|
let ackAlreadySent = false;
|
|
2392
2528
|
let ackReaction = null;
|
|
2529
|
+
let statusReactionController = null;
|
|
2393
2530
|
const runAudioPreflightOnce = async () => {
|
|
2394
2531
|
if (preflightAudioTranscript !== void 0 || !canRunEarlyAudioPreflight || !hasAudioBody || !msg.mediaPath) return;
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2532
|
+
if (cfg.messages?.statusReactions?.enabled === true) {
|
|
2533
|
+
statusReactionController = await createWhatsAppStatusReactionController({
|
|
2534
|
+
cfg,
|
|
2535
|
+
msg,
|
|
2536
|
+
agentId: route.agentId,
|
|
2537
|
+
sessionKey: route.sessionKey,
|
|
2538
|
+
conversationId,
|
|
2539
|
+
verbose: params.verbose,
|
|
2540
|
+
accountId: route.accountId
|
|
2541
|
+
});
|
|
2542
|
+
if (statusReactionController) await statusReactionController.setQueued();
|
|
2543
|
+
} else {
|
|
2544
|
+
ackReaction = await maybeSendAckReaction({
|
|
2545
|
+
cfg,
|
|
2546
|
+
msg,
|
|
2547
|
+
agentId: route.agentId,
|
|
2548
|
+
sessionKey: route.sessionKey,
|
|
2549
|
+
conversationId,
|
|
2550
|
+
verbose: params.verbose,
|
|
2551
|
+
accountId: route.accountId,
|
|
2552
|
+
info: params.replyLogger.info.bind(params.replyLogger),
|
|
2553
|
+
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
2554
|
+
});
|
|
2555
|
+
ackAlreadySent = ackReaction !== null;
|
|
2556
|
+
}
|
|
2407
2557
|
try {
|
|
2408
2558
|
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-MmkB-pgX.js");
|
|
2409
2559
|
preflightAudioTranscript = await transcribeFirstAudio({
|
|
@@ -2512,12 +2662,14 @@ function createWebOnMessageHandler(params) {
|
|
|
2512
2662
|
...preflightAudioTranscript !== void 0 ? { preflightAudioTranscript } : {},
|
|
2513
2663
|
...ackAlreadySent && msg.chatType !== "group" ? { ackAlreadySent: true } : {},
|
|
2514
2664
|
...ackReaction && msg.chatType !== "group" ? { ackReaction } : {},
|
|
2665
|
+
...statusReactionController && msg.chatType !== "group" ? { ackAlreadySent: true } : {},
|
|
2515
2666
|
processMessage: (m, r, k, opts) => processForRoute(cfg, m, r, k, opts)
|
|
2516
2667
|
})) return;
|
|
2517
2668
|
await processForRoute(cfg, msg, route, groupHistoryKey, {
|
|
2518
2669
|
...preflightAudioTranscript !== void 0 ? { preflightAudioTranscript } : {},
|
|
2519
2670
|
...ackAlreadySent ? { ackAlreadySent: true } : {},
|
|
2520
|
-
...ackReaction ? { ackReaction } : {}
|
|
2671
|
+
...ackReaction ? { ackReaction } : {},
|
|
2672
|
+
...statusReactionController ? { statusReactionController } : {}
|
|
2521
2673
|
});
|
|
2522
2674
|
};
|
|
2523
2675
|
}
|
package/dist/runtime-api.js
CHANGED
|
@@ -10,7 +10,7 @@ import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-DLGCIbfl.js";
|
|
|
10
10
|
import { c as extractContactContext, d as extractMediaPlaceholder, p as extractText, u as extractLocationData } from "./send-api-DD93aPIQ.js";
|
|
11
11
|
import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-ZZQKkOTz.js";
|
|
12
12
|
import { n as resolveWebAccountId, t as getActiveWebListener } from "./active-listener-DTbKS-j-.js";
|
|
13
|
-
import { a as loadWebMediaRaw, c as monitorWebInbox, i as loadWebMedia, l as resetWebInboundDedupe, n as LocalMediaAccessError, o as optimizeImageToJpeg, r as getDefaultLocalRoots, s as optimizeImageToPng, t as monitorWebChannel } from "./monitor-
|
|
13
|
+
import { a as loadWebMediaRaw, c as monitorWebInbox, i as loadWebMedia, l as resetWebInboundDedupe, n as LocalMediaAccessError, o as optimizeImageToJpeg, r as getDefaultLocalRoots, s as optimizeImageToPng, t as monitorWebChannel } from "./monitor-DTi0QRV4.js";
|
|
14
14
|
import { t as loginWeb } from "./login-B_pa3YAU.js";
|
|
15
15
|
import { HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, SILENT_REPLY_TOKEN, stripHeartbeatToken } from "openclaw/plugin-sdk/reply-runtime";
|
|
16
16
|
export { DEFAULT_WEB_MEDIA_BYTES, HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, LocalMediaAccessError, SILENT_REPLY_TOKEN, WA_WEB_AUTH_DIR, WHATSAPP_AUTH_UNSTABLE_CODE, WhatsAppAuthUnstableError, createWaSocket, createWhatsAppLoginTool, extractContactContext, extractLocationData, extractMediaPlaceholder, extractText, formatError, formatWhatsAppWebAuthStatusState, getActiveWebListener, getDefaultLocalRoots, getStatusCode, getWebAuthAgeMs, handleWhatsAppAction, hasWebCredsSync, loadWebMedia, loadWebMediaRaw, logWebSelfId, loginWeb, logoutWeb, monitorWebChannel, monitorWebInbox, newConnectionId, optimizeImageToJpeg, optimizeImageToPng, pickWebChannel, readCredsJsonRaw, readWebAuthExistsBestEffort, readWebAuthExistsForDecision, readWebAuthSnapshot, readWebAuthSnapshotBestEffort, readWebAuthState, readWebSelfId, readWebSelfIdentity, readWebSelfIdentityForDecision, resetWebInboundDedupe, resolveDefaultWebAuthDir, resolveWebAccountId, resolveWebCredsBackupPath, resolveWebCredsPath, restoreCredsFromBackupIfNeeded, sendMessageWhatsApp, sendPollWhatsApp, sendReactionWhatsApp, sendTypingWhatsApp, setWhatsAppRuntime, startWebLoginWithQr, stripHeartbeatToken, waitForCredsSaveQueue, waitForCredsSaveQueueWithTimeout, waitForWaConnection, waitForWebLogin, webAuthExists, whatsAppActionRuntime, writeCredsJsonAtomically };
|
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-KnsEGgS2.js";
|
|
2
2
|
export { whatsappSetupPlugin };
|
|
@@ -124,7 +124,7 @@ function resolveWhatsAppConfigPath(params) {
|
|
|
124
124
|
return `${resolveWhatsAppGroupScopeBasePath(params)}.${params.field}`;
|
|
125
125
|
}
|
|
126
126
|
async function loadWhatsAppChannelRuntime() {
|
|
127
|
-
return await import("./channel.runtime-
|
|
127
|
+
return await import("./channel.runtime-Dc5rfgsF.js");
|
|
128
128
|
}
|
|
129
129
|
async function loadWhatsAppSetupSurface() {
|
|
130
130
|
return await import("./setup-surface-BbwSSEsy.js");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/whatsapp",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.14-beta.1",
|
|
4
4
|
"description": "OpenClaw WhatsApp channel plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"openclaw": "workspace:*"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"openclaw": ">=2026.5.
|
|
23
|
+
"openclaw": ">=2026.5.14-beta.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependenciesMeta": {
|
|
26
26
|
"openclaw": {
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"minHostVersion": ">=2026.4.25"
|
|
64
64
|
},
|
|
65
65
|
"compat": {
|
|
66
|
-
"pluginApi": ">=2026.5.
|
|
66
|
+
"pluginApi": ">=2026.5.14-beta.1"
|
|
67
67
|
},
|
|
68
68
|
"build": {
|
|
69
|
-
"openclawVersion": "2026.5.
|
|
69
|
+
"openclawVersion": "2026.5.14-beta.1"
|
|
70
70
|
},
|
|
71
71
|
"release": {
|
|
72
72
|
"publishToClawHub": true,
|