@openclaw/whatsapp 2026.5.22 → 2026.5.24-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 (35) hide show
  1. package/dist/{action-runtime-D4UqEXqf.js → action-runtime-DGx8vCsS.js} +1 -1
  2. package/dist/action-runtime-api.js +1 -1
  3. package/dist/action-runtime.runtime.js +1 -1
  4. package/dist/api.js +6 -6
  5. package/dist/approval-handler.runtime-j8U6lgcp.js +171 -0
  6. package/dist/approval-resolver-e1hAVRRy.js +15 -0
  7. package/dist/{auth-store-GTQvJznL.js → auth-store-BrKb0mwT.js} +2 -2
  8. package/dist/{channel-BQqQ-Gp5.js → channel-DOxZCBxE.js} +415 -34
  9. package/dist/channel-plugin-api.js +1 -1
  10. package/dist/{channel-react-action-CHdR3gbn.js → channel-react-action-O7asbQQ1.js} +2 -2
  11. package/dist/{channel.runtime-BZ_ya3mR.js → channel.runtime-B0cFknwD.js} +4 -4
  12. package/dist/{channel.setup-vWI0fm8Y.js → channel.setup-Bk7Hmp4a.js} +2 -2
  13. package/dist/{connection-controller-9TXWZRhx.js → connection-controller-ja6z4F_k.js} +2 -2
  14. package/dist/light-runtime-api.js +1 -1
  15. package/dist/{login-nJwaNuC-.js → login-BEkrpJbZ.js} +3 -3
  16. package/dist/{login-qr-l4UaR8Dj.js → login-qr-BVRx8j_M.js} +3 -3
  17. package/dist/login-qr-runtime.js +1 -1
  18. package/dist/{monitor-ClhD-fQ6.js → monitor-BU1ydkuF.js} +324 -87
  19. package/dist/{outbound-adapter-ltiZkW9L.js → outbound-adapter-BObZXXzU.js} +1 -1
  20. package/dist/outbound-payload-test-api.js +1 -1
  21. package/dist/{runtime-CboC4QhQ.js → runtime-BfAdAEYT.js} +2 -2
  22. package/dist/runtime-api.js +8 -8
  23. package/dist/runtime-setter-api.js +1 -1
  24. package/dist/send-C9jEw6hx.js +625 -0
  25. package/dist/{send-api-CXPUXbUL.js → send-api-CC-vHBWG.js} +2 -2
  26. package/dist/{session-CPsgRMMa.js → session-CDgpDc0l.js} +2 -2
  27. package/dist/{session.runtime-C6uBkEaI.js → session.runtime-LZFdq3yb.js} +1 -1
  28. package/dist/{setup-core-BTDKEc-x.js → setup-core-Ce-b_wzQ.js} +2 -2
  29. package/dist/{setup-finalize-DUYdQs-v.js → setup-finalize-BqOudqJw.js} +2 -2
  30. package/dist/setup-plugin-api.js +1 -1
  31. package/dist/{setup-surface-Uoh9W_29.js → setup-surface-CAchPwW5.js} +2 -2
  32. package/dist/test-api.js +1 -1
  33. package/npm-shrinkwrap.json +3 -3
  34. package/package.json +4 -4
  35. package/dist/send-E_kMiuZP.js +0 -269
@@ -1,50 +1,431 @@
1
- import { t as listAccountIds } from "./account-ids-CB5SOWjc.js";
1
+ import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
2
2
  import { a as resolveWhatsAppAccount } from "./accounts-BPYgj8Fv.js";
3
3
  import { c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, n as isWhatsAppNewsletterJid, o as normalizeWhatsAppAllowFromEntry, s as normalizeWhatsAppMessagingTarget, t as isWhatsAppGroupJid } from "./normalize-target-bVWjgftN.js";
4
4
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CV-iBmSG.js";
5
5
  import { t as resolveWhatsAppReactionLevel } from "./reaction-level-BqMOEBeq.js";
6
- import { r as normalizeWhatsAppPayloadTextPreservingIndentation } from "./outbound-media-contract-ioTkt8tn.js";
7
6
  import "./normalize-Bxwqo-bW.js";
8
- import { i as sendTypingWhatsApp, n as sendPollWhatsApp, t as sendMessageWhatsApp } from "./send-E_kMiuZP.js";
7
+ import { d as getWhatsAppApprovalApprovers, f as whatsappApprovalAuth, i as sendTypingWhatsApp, n as sendPollWhatsApp, o as addWhatsAppApprovalReactionHintToText, t as sendMessageWhatsApp } from "./send-C9jEw6hx.js";
8
+ import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
9
+ import { r as normalizeWhatsAppPayloadTextPreservingIndentation } from "./outbound-media-contract-ioTkt8tn.js";
9
10
  import { t as createWhatsAppLoginTool } from "./agent-tools-login-BDzvb3ee.js";
10
11
  import { t as createWhatsAppOutboundBase } from "./outbound-base-E84SMkd9.js";
11
- import { t as getWhatsAppRuntime } from "./runtime-CboC4QhQ.js";
12
12
  import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
13
- import { a as resolveWhatsAppGroupRequireMention, c as resolveWhatsAppMentionStripRegexes, i as whatsappSetupWizardProxy, l as formatWhatsAppConfigAllowFromEntries, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, r as loadWhatsAppChannelRuntime, s as resolveWhatsAppGroupIntroHint, t as whatsappSetupAdapter } from "./setup-core-BTDKEc-x.js";
14
- import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-GTQvJznL.js";
13
+ import { a as resolveWhatsAppGroupRequireMention, c as resolveWhatsAppMentionStripRegexes, i as whatsappSetupWizardProxy, l as formatWhatsAppConfigAllowFromEntries, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, r as loadWhatsAppChannelRuntime, s as resolveWhatsAppGroupIntroHint, t as whatsappSetupAdapter } from "./setup-core-Ce-b_wzQ.js";
14
+ import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-BrKb0mwT.js";
15
15
  import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-D_BmQUR9.js";
16
16
  import { createActionGate as createActionGate$1 } from "openclaw/plugin-sdk/channel-actions";
17
- import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord } from "openclaw/plugin-sdk/status-helpers";
17
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
18
+ import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord as isRecord$1 } from "openclaw/plugin-sdk/status-helpers";
18
19
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
19
20
  import { buildChannelOutboundSessionRoute } from "openclaw/plugin-sdk/core";
20
21
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
21
22
  import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
22
23
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
23
24
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
24
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
25
+ import { matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
26
+ import { createChannelApprovalCapability, splitChannelApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
27
+ import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
28
+ import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver, doesApprovalRequestMatchChannelAccount, resolveApprovalRequestSessionTarget } from "openclaw/plugin-sdk/approval-native-runtime";
29
+ import { buildExecApprovalPendingReplyPayload, buildPluginApprovalPendingReplyPayload, resolveExecApprovalCommandDisplay, resolveExecApprovalRequestAllowedDecisions } from "openclaw/plugin-sdk/approval-runtime";
30
+ import { channelRouteTargetsMatchExact } from "openclaw/plugin-sdk/channel-route";
31
+ import { normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/routing";
25
32
  import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
26
33
  import { chunkText } from "openclaw/plugin-sdk/reply-chunking";
27
- //#region extensions/whatsapp/src/approval-auth.ts
28
- function normalizeWhatsAppApproverId(value) {
29
- const normalized = normalizeWhatsAppTarget(String(value));
30
- if (!normalized || normalized.endsWith("@g.us")) return;
31
- return normalized;
32
- }
33
- const whatsappApprovalAuth = createResolvedApproverActionAuthAdapter({
34
- channelLabel: "WhatsApp",
35
- resolveApprovers: ({ cfg, accountId }) => {
36
- const account = resolveWhatsAppAccount({
37
- cfg,
38
- accountId
39
- });
40
- return resolveApprovalApprovers({
41
- allowFrom: account.allowFrom,
42
- defaultTo: account.defaultTo,
43
- normalizeApprover: normalizeWhatsAppApproverId
34
+ //#region extensions/whatsapp/src/approval-native.ts
35
+ const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
36
+ const DEFAULT_PLUGIN_APPROVAL_DECISIONS = [
37
+ "allow-once",
38
+ "allow-always",
39
+ "deny"
40
+ ];
41
+ function isWhatsAppApprovalTransportEnabled(params) {
42
+ return resolveWhatsAppAccount({
43
+ cfg: params.cfg,
44
+ accountId: params.accountId
45
+ }).enabled;
46
+ }
47
+ function resolveApprovalKind(request, approvalKind) {
48
+ if (approvalKind) return approvalKind;
49
+ return "command" in request.request ? "exec" : "plugin";
50
+ }
51
+ function resolveApprovalForwardingConfig(params) {
52
+ return params.approvalKind === "plugin" ? params.cfg.approvals?.plugin : params.cfg.approvals?.exec;
53
+ }
54
+ function normalizeApprovalForwardingMode(mode) {
55
+ return mode ?? DEFAULT_APPROVAL_FORWARDING_MODE;
56
+ }
57
+ function approvalModeIncludesSession(mode) {
58
+ return mode === "session" || mode === "both";
59
+ }
60
+ function approvalModeIncludesTargets(mode) {
61
+ return mode === "targets" || mode === "both";
62
+ }
63
+ function matchesForwardingFilters(params) {
64
+ return matchesApprovalRequestFilters({
65
+ request: params.request.request,
66
+ agentFilter: params.config.agentFilter,
67
+ sessionFilter: params.config.sessionFilter,
68
+ fallbackAgentIdFromSessionKey: true
69
+ });
70
+ }
71
+ function targetAccountMatchesWhatsAppAccount(params) {
72
+ const targetAccountId = normalizeOptionalString(params.targetAccountId);
73
+ const accountId = normalizeOptionalString(params.accountId);
74
+ if (targetAccountId) return !accountId || normalizeAccountId$1(targetAccountId) === normalizeAccountId$1(accountId);
75
+ if (!accountId) return true;
76
+ const normalizedAccountId = normalizeAccountId$1(accountId);
77
+ if (normalizedAccountId === normalizeAccountId$1(resolveDefaultWhatsAppAccountId(params.cfg))) return true;
78
+ const enabledAccountIds = listAccountIds(params.cfg).filter((candidateAccountId) => isWhatsAppApprovalTransportEnabled({
79
+ cfg: params.cfg,
80
+ accountId: candidateAccountId
81
+ })).map((candidateAccountId) => normalizeAccountId$1(candidateAccountId));
82
+ return enabledAccountIds.length === 1 && enabledAccountIds[0] === normalizedAccountId;
83
+ }
84
+ function normalizeWhatsAppForwardTarget(target) {
85
+ if (normalizeLowercaseStringOrEmpty(target.channel) !== "whatsapp") return null;
86
+ const to = normalizeWhatsAppMessagingTarget(target.to);
87
+ if (!to) return null;
88
+ return {
89
+ to,
90
+ accountId: normalizeOptionalString(target.accountId),
91
+ threadId: target.threadId ?? null
92
+ };
93
+ }
94
+ function nativeApprovalTargetsMatch(params) {
95
+ return channelRouteTargetsMatchExact({
96
+ left: {
97
+ channel: "whatsapp",
98
+ to: params.left.to,
99
+ accountId: params.left.accountId,
100
+ threadId: params.left.threadId
101
+ },
102
+ right: {
103
+ channel: "whatsapp",
104
+ to: params.right.to,
105
+ accountId: params.right.accountId,
106
+ threadId: params.right.threadId
107
+ }
108
+ });
109
+ }
110
+ function hasMatchingWhatsAppTarget(params) {
111
+ const candidateTarget = params.target ? normalizeWhatsAppForwardTarget(params.target) : null;
112
+ return (params.config.targets ?? []).some((target) => {
113
+ const configuredTarget = normalizeWhatsAppForwardTarget(target);
114
+ if (!configuredTarget) return false;
115
+ if (!targetAccountMatchesWhatsAppAccount({
116
+ cfg: params.cfg,
117
+ targetAccountId: configuredTarget.accountId,
118
+ accountId: params.accountId
119
+ })) return false;
120
+ if (!candidateTarget) return true;
121
+ return nativeApprovalTargetsMatch({
122
+ left: configuredTarget,
123
+ right: candidateTarget
44
124
  });
125
+ });
126
+ }
127
+ function hasWhatsAppOriginOrSessionTarget(params) {
128
+ if (resolveTurnSourceWhatsAppOriginTarget(params.request)) return true;
129
+ const sessionTarget = resolveApprovalRequestSessionTarget({
130
+ cfg: params.cfg,
131
+ request: params.request
132
+ });
133
+ return normalizeLowercaseStringOrEmpty(sessionTarget?.channel) === "whatsapp" && targetAccountMatchesWhatsAppAccount({
134
+ cfg: params.cfg,
135
+ targetAccountId: sessionTarget?.accountId,
136
+ accountId: params.accountId
137
+ });
138
+ }
139
+ function canApprovalPotentiallyRouteToWhatsApp(params) {
140
+ if (!isWhatsAppApprovalTransportEnabled(params)) return false;
141
+ const config = resolveApprovalForwardingConfig(params);
142
+ if (!config?.enabled) return false;
143
+ const mode = normalizeApprovalForwardingMode(config.mode);
144
+ if (approvalModeIncludesSession(mode)) return true;
145
+ if (params.nativeSessionOnly) return false;
146
+ return approvalModeIncludesTargets(mode) && hasMatchingWhatsAppTarget({
147
+ cfg: params.cfg,
148
+ config,
149
+ accountId: params.accountId
150
+ });
151
+ }
152
+ function canAnyApprovalPotentiallyRouteToWhatsApp(params) {
153
+ return canApprovalPotentiallyRouteToWhatsApp({
154
+ ...params,
155
+ approvalKind: "exec"
156
+ }) || canApprovalPotentiallyRouteToWhatsApp({
157
+ ...params,
158
+ approvalKind: "plugin"
159
+ });
160
+ }
161
+ function isWhatsAppSessionApprovalEligible(params) {
162
+ if (!isWhatsAppApprovalTransportEnabled(params)) return false;
163
+ const config = resolveApprovalForwardingConfig(params);
164
+ if (!config?.enabled) return false;
165
+ if (!approvalModeIncludesSession(normalizeApprovalForwardingMode(config.mode))) return false;
166
+ if (!matchesForwardingFilters({
167
+ config,
168
+ request: params.request
169
+ })) return false;
170
+ if (!doesApprovalRequestMatchChannelAccount({
171
+ cfg: params.cfg,
172
+ request: params.request,
173
+ channel: "whatsapp",
174
+ accountId: params.accountId
175
+ })) return false;
176
+ return hasWhatsAppOriginOrSessionTarget({
177
+ cfg: params.cfg,
178
+ accountId: params.accountId,
179
+ request: params.request
180
+ });
181
+ }
182
+ function isWhatsAppExplicitTargetEligible(params) {
183
+ if (!isWhatsAppApprovalTransportEnabled(params)) return false;
184
+ const config = resolveApprovalForwardingConfig(params);
185
+ if (!config?.enabled) return false;
186
+ if (!approvalModeIncludesTargets(normalizeApprovalForwardingMode(config.mode))) return false;
187
+ if (!matchesForwardingFilters({
188
+ config,
189
+ request: params.request
190
+ })) return false;
191
+ return hasMatchingWhatsAppTarget({
192
+ cfg: params.cfg,
193
+ config,
194
+ accountId: params.accountId,
195
+ target: params.target
196
+ });
197
+ }
198
+ function resolveTurnSourceWhatsAppOriginTarget(request) {
199
+ if (normalizeLowercaseStringOrEmpty(request.request.turnSourceChannel) !== "whatsapp") return null;
200
+ const to = normalizeWhatsAppMessagingTarget(request.request.turnSourceTo ?? "");
201
+ if (!to) return null;
202
+ return {
203
+ to,
204
+ accountId: normalizeOptionalString(request.request.turnSourceAccountId)
205
+ };
206
+ }
207
+ function resolveSessionWhatsAppOriginTarget(sessionTarget) {
208
+ const to = normalizeWhatsAppMessagingTarget(sessionTarget.to);
209
+ return to ? {
210
+ to,
211
+ accountId: normalizeOptionalString(sessionTarget.accountId)
212
+ } : null;
213
+ }
214
+ function shouldHandleWhatsAppApprovalRequest(params) {
215
+ return isWhatsAppSessionApprovalEligible({
216
+ ...params,
217
+ approvalKind: resolveApprovalKind(params.request, params.approvalKind)
218
+ });
219
+ }
220
+ const resolveWhatsAppOriginTargetBase = createChannelNativeOriginTargetResolver({
221
+ channel: "whatsapp",
222
+ shouldHandleRequest: shouldHandleWhatsAppApprovalRequest,
223
+ resolveTurnSourceTarget: resolveTurnSourceWhatsAppOriginTarget,
224
+ resolveSessionTarget: resolveSessionWhatsAppOriginTarget,
225
+ normalizeTarget: (target) => {
226
+ const to = normalizeWhatsAppMessagingTarget(target.to);
227
+ return to ? {
228
+ ...target,
229
+ to
230
+ } : null;
231
+ }
232
+ });
233
+ function resolveWhatsAppOriginTarget(params) {
234
+ const target = resolveWhatsAppOriginTargetBase(params);
235
+ if (!target) return null;
236
+ if (isWhatsAppGroupJid(target.to) && getWhatsAppApprovalApprovers({
237
+ cfg: params.cfg,
238
+ accountId: params.accountId
239
+ }).length === 0) return null;
240
+ return target;
241
+ }
242
+ const resolveWhatsAppApproverDmTargets = createChannelApproverDmTargetResolver({
243
+ shouldHandleRequest: shouldHandleWhatsAppApprovalRequest,
244
+ resolveApprovers: getWhatsAppApprovalApprovers,
245
+ mapApprover: (approver, params) => {
246
+ const to = normalizeWhatsAppMessagingTarget(approver);
247
+ if (!to) return null;
248
+ return {
249
+ to,
250
+ accountId: normalizeOptionalString(params.accountId)
251
+ };
252
+ }
253
+ });
254
+ function appendWhatsAppReactionHint(params) {
255
+ return addWhatsAppApprovalReactionHintToText({
256
+ text: params.text ?? "",
257
+ allowedDecisions: params.allowedDecisions
258
+ });
259
+ }
260
+ function replaceApprovalIdPlaceholder(text, approvalId) {
261
+ return (text ?? "").replace(/\/approve\s+<id>/g, `/approve ${approvalId}`);
262
+ }
263
+ function buildWhatsAppExecPendingPayload(params) {
264
+ const allowedDecisions = resolveExecApprovalRequestAllowedDecisions(params.request.request);
265
+ const command = resolveExecApprovalCommandDisplay(params.request.request).commandText;
266
+ const payload = buildExecApprovalPendingReplyPayload({
267
+ approvalId: params.request.id,
268
+ approvalSlug: params.request.id.slice(0, 8),
269
+ approvalCommandId: params.request.id,
270
+ warningText: params.request.request.warningText ?? void 0,
271
+ ask: params.request.request.ask ?? null,
272
+ agentId: params.request.request.agentId ?? null,
273
+ allowedDecisions,
274
+ command,
275
+ cwd: params.request.request.cwd ?? void 0,
276
+ host: params.request.request.host === "node" ? "node" : "gateway",
277
+ nodeId: params.request.request.nodeId ?? void 0,
278
+ sessionKey: params.request.request.sessionKey ?? null,
279
+ expiresAtMs: params.request.expiresAtMs,
280
+ nowMs: params.nowMs
281
+ });
282
+ return {
283
+ ...payload,
284
+ text: appendWhatsAppReactionHint({
285
+ text: replaceApprovalIdPlaceholder(payload.text, params.request.id),
286
+ allowedDecisions
287
+ })
288
+ };
289
+ }
290
+ function buildWhatsAppPluginPendingPayload(params) {
291
+ const configuredDecisions = params.request.request.allowedDecisions;
292
+ const allowedDecisions = configuredDecisions && configuredDecisions.length > 0 ? configuredDecisions : DEFAULT_PLUGIN_APPROVAL_DECISIONS;
293
+ const payload = buildPluginApprovalPendingReplyPayload({
294
+ request: params.request,
295
+ nowMs: params.nowMs,
296
+ allowedDecisions
297
+ });
298
+ return {
299
+ ...payload,
300
+ text: appendWhatsAppReactionHint({
301
+ text: replaceApprovalIdPlaceholder(payload.text, params.request.id),
302
+ allowedDecisions
303
+ })
304
+ };
305
+ }
306
+ const whatsappApprovalCapability = createChannelApprovalCapability({
307
+ ...whatsappApprovalAuth,
308
+ getActionAvailabilityState: ({ cfg, accountId, approvalKind }) => (approvalKind ? canApprovalPotentiallyRouteToWhatsApp({
309
+ cfg,
310
+ accountId,
311
+ approvalKind
312
+ }) : canAnyApprovalPotentiallyRouteToWhatsApp({
313
+ cfg,
314
+ accountId
315
+ })) ? { kind: "enabled" } : { kind: "disabled" },
316
+ getExecInitiatingSurfaceState: ({ cfg, accountId }) => canApprovalPotentiallyRouteToWhatsApp({
317
+ cfg,
318
+ accountId,
319
+ approvalKind: "exec"
320
+ }) ? { kind: "enabled" } : { kind: "disabled" },
321
+ describeExecApprovalSetup: ({ accountId }) => {
322
+ return `WhatsApp supports native exec approvals for this account when \`approvals.exec.enabled\` is true and the route allows WhatsApp. Link WhatsApp and keep the gateway running; configure \`${accountId && accountId !== "default" ? `channels.whatsapp.accounts.${accountId}` : "channels.whatsapp"}.allowFrom\` to restrict approvers.`;
45
323
  },
46
- normalizeSenderId: (value) => normalizeWhatsAppApproverId(value)
324
+ delivery: {
325
+ hasConfiguredDmRoute: ({ cfg }) => listAccountIds(cfg).some((accountId) => {
326
+ if (!canAnyApprovalPotentiallyRouteToWhatsApp({
327
+ cfg,
328
+ accountId,
329
+ nativeSessionOnly: true
330
+ })) return false;
331
+ return getWhatsAppApprovalApprovers({
332
+ cfg,
333
+ accountId
334
+ }).length > 0;
335
+ }),
336
+ shouldSuppressForwardingFallback: ({ cfg, approvalKind, target, request }) => {
337
+ const forwardingTarget = normalizeWhatsAppForwardTarget(target);
338
+ if (!forwardingTarget) return false;
339
+ const accountId = forwardingTarget.accountId ?? normalizeOptionalString(request.request.turnSourceAccountId);
340
+ const forwardingTargetForMatch = {
341
+ ...forwardingTarget,
342
+ accountId
343
+ };
344
+ const kind = resolveApprovalKind(request, approvalKind);
345
+ if (!(target.source === "target" ? isWhatsAppExplicitTargetEligible({
346
+ cfg,
347
+ accountId,
348
+ approvalKind: kind,
349
+ request,
350
+ target
351
+ }) : isWhatsAppSessionApprovalEligible({
352
+ cfg,
353
+ accountId,
354
+ approvalKind: kind,
355
+ request
356
+ }))) return false;
357
+ const originTarget = resolveWhatsAppOriginTarget({
358
+ cfg,
359
+ accountId,
360
+ approvalKind: kind,
361
+ request
362
+ });
363
+ if (originTarget && nativeApprovalTargetsMatch({
364
+ left: forwardingTargetForMatch,
365
+ right: originTarget
366
+ })) return true;
367
+ return resolveWhatsAppApproverDmTargets({
368
+ cfg,
369
+ accountId,
370
+ approvalKind: kind,
371
+ request
372
+ }).some((approverTarget) => nativeApprovalTargetsMatch({
373
+ left: forwardingTargetForMatch,
374
+ right: approverTarget
375
+ }));
376
+ }
377
+ },
378
+ render: {
379
+ exec: { buildPendingPayload: ({ request, nowMs }) => buildWhatsAppExecPendingPayload({
380
+ request,
381
+ nowMs
382
+ }) },
383
+ plugin: { buildPendingPayload: ({ request, nowMs }) => buildWhatsAppPluginPendingPayload({
384
+ request,
385
+ nowMs
386
+ }) }
387
+ },
388
+ native: {
389
+ describeDeliveryCapabilities: ({ cfg, accountId, approvalKind, request }) => {
390
+ const originTarget = resolveWhatsAppOriginTarget({
391
+ cfg,
392
+ accountId,
393
+ approvalKind,
394
+ request
395
+ });
396
+ const approverTargets = resolveWhatsAppApproverDmTargets({
397
+ cfg,
398
+ accountId,
399
+ approvalKind,
400
+ request
401
+ });
402
+ return {
403
+ enabled: Boolean(originTarget) || approverTargets.length > 0,
404
+ preferredSurface: originTarget ? "origin" : "approver-dm",
405
+ supportsOriginSurface: Boolean(originTarget),
406
+ supportsApproverDmSurface: approverTargets.length > 0,
407
+ notifyOriginWhenDmOnly: true
408
+ };
409
+ },
410
+ resolveOriginTarget: resolveWhatsAppOriginTarget,
411
+ resolveApproverDmTargets: resolveWhatsAppApproverDmTargets
412
+ },
413
+ nativeRuntime: createLazyChannelApprovalNativeRuntimeAdapter({
414
+ eventKinds: ["exec", "plugin"],
415
+ isConfigured: ({ cfg, accountId, context }) => Boolean(context) && canAnyApprovalPotentiallyRouteToWhatsApp({
416
+ cfg,
417
+ accountId,
418
+ nativeSessionOnly: true
419
+ }),
420
+ shouldHandle: ({ cfg, accountId, context, request }) => Boolean(context) && shouldHandleWhatsAppApprovalRequest({
421
+ cfg,
422
+ accountId,
423
+ request
424
+ }),
425
+ load: async () => (await import("./approval-handler.runtime-j8U6lgcp.js")).whatsappApprovalNativeRuntime
426
+ })
47
427
  });
428
+ splitChannelApprovalCapability(whatsappApprovalCapability);
48
429
  //#endregion
49
430
  //#region extensions/whatsapp/src/channel-actions.ts
50
431
  function areWhatsAppAgentReactionsEnabled(params) {
@@ -201,7 +582,7 @@ function resolveWhatsAppOutboundSessionRoute(params) {
201
582
  //#region extensions/whatsapp/src/status-issues.ts
202
583
  const RECENT_DISCONNECT_WARNING_WINDOW_MS = 900 * 1e3;
203
584
  function readWhatsAppAccountStatus(value) {
204
- if (!isRecord(value)) return null;
585
+ if (!isRecord$1(value)) return null;
205
586
  return {
206
587
  accountId: value.accountId,
207
588
  statusState: value.statusState,
@@ -224,7 +605,7 @@ function readLastDisconnect(value) {
224
605
  error
225
606
  } : null;
226
607
  }
227
- if (!isRecord(value)) return null;
608
+ if (!isRecord$1(value)) return null;
228
609
  return {
229
610
  at: typeof value.at === "number" ? value.at : null,
230
611
  error: asString(value.error)
@@ -323,8 +704,8 @@ function collectWhatsAppStatusIssues(accounts) {
323
704
  //#endregion
324
705
  //#region extensions/whatsapp/src/channel.ts
325
706
  const loadWhatsAppDirectoryConfig = createLazyRuntimeModule(() => import("./directory-config-CfLFAK54.js").then((n) => n.t));
326
- const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-CHdR3gbn.js"));
327
- function parseWhatsAppExplicitTarget(raw) {
707
+ const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-O7asbQQ1.js"));
708
+ function resolveWhatsAppTargetInfo(raw) {
328
709
  const normalized = normalizeWhatsAppTarget(raw);
329
710
  if (!normalized) return null;
330
711
  return {
@@ -384,8 +765,7 @@ const whatsappPlugin = createChatChannelPlugin({
384
765
  targetPrefixes: ["whatsapp"],
385
766
  normalizeTarget: normalizeWhatsAppMessagingTarget,
386
767
  resolveOutboundSessionRoute: (params) => resolveWhatsAppOutboundSessionRoute(params),
387
- parseExplicitTarget: ({ raw }) => parseWhatsAppExplicitTarget(raw),
388
- inferTargetChatType: ({ to }) => parseWhatsAppExplicitTarget(to)?.chatType,
768
+ inferTargetChatType: ({ to }) => resolveWhatsAppTargetInfo(to)?.chatType,
389
769
  targetResolver: {
390
770
  looksLikeId: looksLikeWhatsAppTargetId,
391
771
  hint: "<E.164|group JID|newsletter JID>"
@@ -433,7 +813,7 @@ const whatsappPlugin = createChatChannelPlugin({
433
813
  toolContext
434
814
  })
435
815
  },
436
- approvalCapability: whatsappApprovalAuth,
816
+ approvalCapability: whatsappApprovalCapability,
437
817
  auth: { login: async ({ cfg, accountId, runtime, verbose }) => {
438
818
  const resolvedAccountId = accountId?.trim() || whatsappPlugin.config.defaultAccountId?.(cfg) || DEFAULT_ACCOUNT_ID;
439
819
  await (await loadWhatsAppChannelRuntime()).loginWeb(Boolean(verbose), void 0, runtime, resolvedAccountId);
@@ -543,7 +923,8 @@ const whatsappPlugin = createChatChannelPlugin({
543
923
  accountId: ctx.accountId,
544
924
  ...next
545
925
  }),
546
- accountId: account.accountId
926
+ accountId: account.accountId,
927
+ channelRuntime: ctx.channelRuntime
547
928
  });
548
929
  },
549
930
  loginWithQrStart: async ({ accountId, force, timeoutMs, verbose }) => await (await loadWhatsAppChannelRuntime()).startWebLoginWithQr({
@@ -1,2 +1,2 @@
1
- import { t as whatsappPlugin } from "./channel-BQqQ-Gp5.js";
1
+ import { t as whatsappPlugin } from "./channel-DOxZCBxE.js";
2
2
  export { whatsappPlugin };
@@ -1,8 +1,8 @@
1
1
  import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-BPYgj8Fv.js";
2
2
  import { c as normalizeWhatsAppTarget, t as isWhatsAppGroupJid } from "./normalize-target-bVWjgftN.js";
3
- import { r as resolveAuthorizedWhatsAppOutboundTarget, t as handleWhatsAppAction } from "./action-runtime-D4UqEXqf.js";
3
+ import { r as resolveAuthorizedWhatsAppOutboundTarget, t as handleWhatsAppAction } from "./action-runtime-DGx8vCsS.js";
4
4
  import "./normalize-Bxwqo-bW.js";
5
- import { t as sendMessageWhatsApp } from "./send-E_kMiuZP.js";
5
+ import { t as sendMessageWhatsApp } from "./send-C9jEw6hx.js";
6
6
  import { jsonResult, readStringOrNumberParam, readStringParam as readStringParam$1, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
7
7
  //#region extensions/whatsapp/src/channel-react-action.ts
8
8
  const WHATSAPP_CHANNEL = "whatsapp";
@@ -1,9 +1,9 @@
1
1
  import { startWebLoginWithQr as startWebLoginWithQr$1, waitForWebLogin as waitForWebLogin$1 } from "./login-qr-runtime.js";
2
- import { c as logoutWeb$1, d as readWebAuthExistsBestEffort$1, f as readWebAuthExistsForDecision$1, g as readWebSelfId$1, h as readWebAuthState$1, m as readWebAuthSnapshotBestEffort$1, o as getWebAuthAgeMs$1, p as readWebAuthSnapshot$1, s as logWebSelfId$1, x as webAuthExists$1 } from "./auth-store-GTQvJznL.js";
2
+ import { c as logoutWeb$1, d as readWebAuthExistsBestEffort$1, f as readWebAuthExistsForDecision$1, g as readWebSelfId$1, h as readWebAuthState$1, m as readWebAuthSnapshotBestEffort$1, o as getWebAuthAgeMs$1, p as readWebAuthSnapshot$1, s as logWebSelfId$1, x as webAuthExists$1 } from "./auth-store-BrKb0mwT.js";
3
3
  import { t as getActiveWebListener$1 } from "./active-listener-B4SDebQ6.js";
4
- import { t as monitorWebChannel$1 } from "./monitor-ClhD-fQ6.js";
5
- import { t as loginWeb$1 } from "./login-nJwaNuC-.js";
6
- import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-Uoh9W_29.js";
4
+ import { t as monitorWebChannel$1 } from "./monitor-BU1ydkuF.js";
5
+ import { t as loginWeb$1 } from "./login-BEkrpJbZ.js";
6
+ import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-CAchPwW5.js";
7
7
  //#region extensions/whatsapp/src/channel.runtime.ts
8
8
  function getActiveWebListener(...args) {
9
9
  return getActiveWebListener$1(...args);
@@ -1,8 +1,8 @@
1
- import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, s as resolveWhatsAppGroupIntroHint, t as whatsappSetupAdapter } from "./setup-core-BTDKEc-x.js";
1
+ import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, s as resolveWhatsAppGroupIntroHint, t as whatsappSetupAdapter } from "./setup-core-Ce-b_wzQ.js";
2
2
  import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-D_BmQUR9.js";
3
3
  //#region extensions/whatsapp/src/channel.setup.ts
4
4
  async function isWhatsAppAuthConfigured(account) {
5
- const { readWebAuthState } = await import("./auth-store-GTQvJznL.js").then((n) => n.i);
5
+ const { readWebAuthState } = await import("./auth-store-BrKb0mwT.js").then((n) => n.i);
6
6
  return await readWebAuthState(account.authDir) === "linked";
7
7
  }
8
8
  const whatsappSetupPlugin = {
@@ -1,7 +1,7 @@
1
1
  import { n as registerWhatsAppConnectionController, r as unregisterWhatsAppConnectionController } from "./connection-controller-registry-TSX_udJp.js";
2
2
  import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
3
- import { c as logoutWeb } from "./auth-store-GTQvJznL.js";
4
- import { r as waitForWaConnection, t as createWaSocket } from "./session-CPsgRMMa.js";
3
+ import { c as logoutWeb } from "./auth-store-BrKb0mwT.js";
4
+ import { r as waitForWaConnection, t as createWaSocket } from "./session-CDgpDc0l.js";
5
5
  import { computeBackoff, info, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
6
6
  import { clamp } from "openclaw/plugin-sdk/text-utility-runtime";
7
7
  import { DisconnectReason } from "baileys";
@@ -1,5 +1,5 @@
1
1
  import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
2
2
  import { t as createWhatsAppLoginTool } from "./agent-tools-login-BDzvb3ee.js";
3
- import { c as logoutWeb, g as readWebSelfId, l as pickWebChannel, o as getWebAuthAgeMs, s as logWebSelfId, t as WA_WEB_AUTH_DIR, x as webAuthExists } from "./auth-store-GTQvJznL.js";
3
+ import { c as logoutWeb, g as readWebSelfId, l as pickWebChannel, o as getWebAuthAgeMs, s as logWebSelfId, t as WA_WEB_AUTH_DIR, x as webAuthExists } from "./auth-store-BrKb0mwT.js";
4
4
  import { t as getActiveWebListener } from "./active-listener-B4SDebQ6.js";
5
5
  export { WA_WEB_AUTH_DIR, createWhatsAppLoginTool, formatError, getActiveWebListener, getStatusCode, getWebAuthAgeMs, logWebSelfId, logoutWeb, pickWebChannel, readWebSelfId, webAuthExists };
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { a as resolveWhatsAppAccount } from "./accounts-BPYgj8Fv.js";
3
- import { b as restoreCredsFromBackupIfNeeded } from "./auth-store-GTQvJznL.js";
4
- import { a as renderQrTerminal, i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-CPsgRMMa.js";
5
- import { a as closeWaSocketSoon, o as waitForWhatsAppLoginResult } from "./connection-controller-9TXWZRhx.js";
3
+ import { b as restoreCredsFromBackupIfNeeded } from "./auth-store-BrKb0mwT.js";
4
+ import { a as renderQrTerminal, i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-CDgpDc0l.js";
5
+ import { a as closeWaSocketSoon, o as waitForWhatsAppLoginResult } from "./connection-controller-ja6z4F_k.js";
6
6
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
7
7
  import { logInfo } from "openclaw/plugin-sdk/logging-core";
8
8
  import { danger, defaultRuntime, success } from "openclaw/plugin-sdk/runtime-env";
@@ -1,7 +1,7 @@
1
1
  import { a as resolveWhatsAppAccount } from "./accounts-BPYgj8Fv.js";
2
- import { f as readWebAuthExistsForDecision, g as readWebSelfId, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-GTQvJznL.js";
3
- import { i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-CPsgRMMa.js";
4
- import { i as closeWaSocket, o as waitForWhatsAppLoginResult, t as WHATSAPP_LOGGED_OUT_QR_MESSAGE } from "./connection-controller-9TXWZRhx.js";
2
+ import { f as readWebAuthExistsForDecision, g as readWebSelfId, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-BrKb0mwT.js";
3
+ import { i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-CDgpDc0l.js";
4
+ import { i as closeWaSocket, o as waitForWhatsAppLoginResult, t as WHATSAPP_LOGGED_OUT_QR_MESSAGE } from "./connection-controller-ja6z4F_k.js";
5
5
  import { logInfo } from "openclaw/plugin-sdk/logging-core";
6
6
  import { danger, defaultRuntime, info, success } from "openclaw/plugin-sdk/runtime-env";
7
7
  import { renderQrPngDataUrl } from "openclaw/plugin-sdk/media-runtime";
@@ -1,7 +1,7 @@
1
1
  //#region extensions/whatsapp/login-qr-runtime.ts
2
2
  let loginQrModulePromise = null;
3
3
  function loadLoginQrModule() {
4
- loginQrModulePromise ??= import("./login-qr-l4UaR8Dj.js");
4
+ loginQrModulePromise ??= import("./login-qr-BVRx8j_M.js");
5
5
  return loginQrModulePromise;
6
6
  }
7
7
  async function startWebLoginWithQr(...args) {