@openclaw/whatsapp 2026.9.2 → 2026.9.4

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 CHANGED
@@ -4,10 +4,10 @@ import { a as normalizeWhatsAppAllowFromEntries, c as normalizeWhatsAppTarget, i
4
4
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-1GqbT1uX.js";
5
5
  import { c as toWhatsappJid, i as markdownToWhatsApp, l as toWhatsappJidWithLid, n as isSelfChatMode, r as jidToE164, s as resolveJidToE164, t as assertWebChannel } from "./targets-runtime-RBjx3pg_.js";
6
6
  import { n as resolveUserPath, t as normalizeE164 } from "./text-runtime-DyfmcATV.js";
7
- import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, t as whatsappPlugin } from "./channel-dwfgnadr.js";
8
- import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-ByeKDmh0.js";
7
+ import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, t as whatsappPlugin } from "./channel-CzEIEZqG.js";
8
+ import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-CLKLJLgY.js";
9
9
  import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
10
- import { t as whatsappSetupPlugin } from "./channel.setup-DckQm9ma.js";
10
+ import { t as whatsappSetupPlugin } from "./channel.setup-gIWoRLzt.js";
11
11
  import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-C7m81BNe.js";
12
12
  import { a as waitForWaConnection, o as DEFAULT_WHATSAPP_SOCKET_TIMING, r as createWaSocket, s as createWhatsAppSocketOperationTimeoutAdapter } from "./socket-close-B3X9uerq.js";
13
13
  import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
@@ -4,7 +4,7 @@ import { s as normalizeWhatsAppMessagingTarget } from "./normalize-target-CugRyO
4
4
  import { i as sendTypingWhatsApp, t as sendMessageWhatsApp } from "./send-BDDGPxav.js";
5
5
  import { i as getWhatsAppRuntime } from "./runtime-BLlToOi6.js";
6
6
  import "./normalize-C7Hkc_vE.js";
7
- import { i as unregisterWhatsAppApprovalReactionTarget, r as registerWhatsAppApprovalReactionTarget } from "./approval-reactions-DrZe-NmN.js";
7
+ import { i as unregisterWhatsAppApprovalReactionTarget, r as registerWhatsAppApprovalReactionTarget } from "./approval-reactions-DSFH6Mtx.js";
8
8
  import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
9
9
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
10
10
  import { buildApprovalReactionPendingContent } from "openclaw/plugin-sdk/approval-reaction-runtime";
@@ -2,9 +2,8 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { a as resolveWhatsAppAccount } from "./accounts-CiKHiuEe.js";
3
3
  import { n as getOptionalWhatsAppRuntime } from "./runtime-BLlToOi6.js";
4
4
  import { c as getWhatsAppApprovalApprovers, l as whatsappApprovalAuth } from "./group-session-key-BmVDSPr1.js";
5
- import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
6
5
  import { createLazyRuntimeSurface } from "openclaw/plugin-sdk/lazy-runtime";
7
- import { approvalReactionDecisionSetsMatch, buildApprovalReactionDeliveredBindingMarker, createApprovalReactionTargetStore, listApprovalReactionBindings, readApprovalReactionDecisionList, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, resolveTypedApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
6
+ import { approvalReactionDecisionSetsMatch, buildApprovalReactionDeliveredBindingMarker, createApprovalReactionTargetStore, listApprovalReactionBindings, readApprovalReactionDecisionList, readApprovalReactionDeliveredBinding, readApprovalReactionPresentationBinding, readApprovalReactionTargetRecord, resolveTypedApprovalReactionTarget, settleApprovalReaction } from "openclaw/plugin-sdk/approval-reaction-runtime";
8
7
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
9
8
  //#region extensions/whatsapp/src/approval-reactions.ts
10
9
  var approval_reactions_exports = /* @__PURE__ */ __exportAll({
@@ -28,7 +27,7 @@ const whatsappApprovalReactionTargets = createApprovalReactionTargetStore({
28
27
  defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
29
28
  openStore: (storeParams) => getOptionalWhatsAppRuntime()?.state.openKeyedStore(storeParams),
30
29
  logPersistentError: reportPersistentApprovalReactionError,
31
- readPersistedTarget
30
+ readPersistedTarget: readApprovalReactionTargetRecord
32
31
  });
33
32
  function buildReactionTargetKey(params) {
34
33
  const accountId = params.accountId.trim();
@@ -52,17 +51,6 @@ function reportApprovalBindingCorrelationMismatch(binding) {
52
51
  });
53
52
  } catch {}
54
53
  }
55
- function readPersistedTarget(target) {
56
- const value = target;
57
- if (!value || typeof value.approvalId !== "string" || value.approvalKind !== "exec" && value.approvalKind !== "plugin") return null;
58
- const allowedDecisions = readApprovalReactionDecisionList(value.allowedDecisions);
59
- if (!allowedDecisions) return null;
60
- return {
61
- approvalId: value.approvalId,
62
- approvalKind: value.approvalKind,
63
- allowedDecisions
64
- };
65
- }
66
54
  const APPROVAL_ID_LINE_RE = /^\s*ID:\s*(\S(?:.*\S)?)\s*$/i;
67
55
  const APPROVAL_KIND_LINE_RE = /^\s*(?:\S+\s+)?(Exec|Plugin) approval required\s*$/i;
68
56
  function visibleApprovalBindingMatches(text, binding) {
@@ -264,26 +252,8 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
264
252
  params.logVerboseMessage?.(`whatsapp: approval reaction ignored for ${target.approvalId}; missing actor identity`);
265
253
  return true;
266
254
  }
267
- if (getWhatsAppApprovalApprovers({
268
- cfg: params.cfg,
269
- accountId: params.accountId
270
- }).length === 0) {
271
- params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
272
- return true;
273
- }
274
- if (!whatsappApprovalAuth.authorizeActorAction({
275
- cfg: params.cfg,
276
- accountId: params.accountId,
277
- senderId: actorId,
278
- action: "approve",
279
- approvalKind: target.approvalKind
280
- }).authorized) {
281
- params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId} sender=${actorId}`);
282
- return true;
283
- }
284
- const resolveApprovalOverGateway = await loadResolveApprovalOverGateway();
285
- try {
286
- const result = await resolveApprovalOverGateway({
255
+ await settleApprovalReaction({
256
+ request: {
287
257
  cfg: params.cfg,
288
258
  approvalId: target.approvalId,
289
259
  approvalKind: target.approvalKind,
@@ -292,28 +262,25 @@ async function maybeResolveWhatsAppApprovalReaction(params) {
292
262
  accountId: params.accountId,
293
263
  senderId: actorId,
294
264
  gatewayUrl: params.gatewayUrl
295
- });
296
- unregisterWhatsAppApprovalReactionTarget({
265
+ },
266
+ approvers: getWhatsAppApprovalApprovers({
267
+ cfg: params.cfg,
268
+ accountId: params.accountId
269
+ }),
270
+ authorizeActorAction: (input) => whatsappApprovalAuth.authorizeActorAction(input),
271
+ loadResolver: loadResolveApprovalOverGateway,
272
+ clearTarget: () => unregisterWhatsAppApprovalReactionTarget({
297
273
  accountId: params.accountId,
298
274
  remoteJid: target.remoteJid,
299
275
  messageId: event.messageId
300
- });
301
- const canonicalDecision = "decision" in result.approval ? ` decision=${result.approval.decision}` : "";
302
- params.logVerboseMessage?.(result.applied ? `whatsapp: approval reaction applied id=${target.approvalId} sender=${actorId} status=${result.approval.status}${canonicalDecision}` : `whatsapp: approval reaction already resolved id=${target.approvalId} sender=${actorId} status=${result.approval.status}${canonicalDecision}`);
303
- return true;
304
- } catch (error) {
305
- if (isApprovalNotFoundError(error)) {
306
- unregisterWhatsAppApprovalReactionTarget({
307
- accountId: params.accountId,
308
- remoteJid: target.remoteJid,
309
- messageId: event.messageId
310
- });
311
- params.logVerboseMessage?.(`whatsapp: approval reaction ignored for expired approval id=${target.approvalId} sender=${actorId}`);
312
- return true;
313
- }
314
- params.logVerboseMessage?.(`whatsapp: approval reaction failed id=${target.approvalId} sender=${actorId}: ${String(error)}`);
315
- return true;
316
- }
276
+ }),
277
+ onResolved: (result) => {
278
+ const canonicalDecision = "decision" in result.approval ? ` decision=${result.approval.decision}` : "";
279
+ params.logVerboseMessage?.(result.applied ? `whatsapp: approval reaction applied id=${target.approvalId} sender=${actorId} status=${result.approval.status}${canonicalDecision}` : `whatsapp: approval reaction already resolved id=${target.approvalId} sender=${actorId} status=${result.approval.status}${canonicalDecision}`);
280
+ },
281
+ logVerboseMessage: params.logVerboseMessage
282
+ });
283
+ return true;
317
284
  }
318
285
  function clearWhatsAppApprovalReactionTargetsForTest() {
319
286
  whatsappApprovalReactionTargets.clearForTest();
@@ -8,7 +8,7 @@ import "./normalize-C7Hkc_vE.js";
8
8
  import { c as toWhatsappJid } from "./targets-runtime-RBjx3pg_.js";
9
9
  import "./text-runtime-DyfmcATV.js";
10
10
  import { c as getWhatsAppApprovalApprovers, l as whatsappApprovalAuth, s as lookupInboundMessageMetaForTarget, t as resolveWhatsAppGroupSessionKey } from "./group-session-key-BmVDSPr1.js";
11
- import { a as resolveWhatsAppGroupRequireMention, c as loadWhatsAppChannelRuntime, i as whatsappSetupContract, l as readWhatsAppAccountLinkState, n as whatsappSetupWizardProxy, o as resolveWhatsAppGroupToolPolicy, s as formatWhatsAppConfigAllowFromEntries, t as createWhatsAppPluginBase } from "./shared-ByeKDmh0.js";
11
+ import { a as resolveWhatsAppGroupRequireMention, c as loadWhatsAppChannelRuntime, i as whatsappSetupContract, l as readWhatsAppAccountLinkState, n as whatsappSetupWizardProxy, o as resolveWhatsAppGroupToolPolicy, s as formatWhatsAppConfigAllowFromEntries, t as createWhatsAppPluginBase } from "./shared-CLKLJLgY.js";
12
12
  import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
13
13
  import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-ZWaclAbd.js";
14
14
  import { createActionGate as createActionGate$1 } from "openclaw/plugin-sdk/channel-actions";
@@ -66,6 +66,7 @@ const whatsappApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
66
66
  }, "plugin") }
67
67
  },
68
68
  createNativeRuntime: (routing) => createLazyChannelApprovalNativeRuntimeAdapter({
69
+ capabilityBoundary: true,
69
70
  eventKinds: [
70
71
  "exec",
71
72
  "plugin",
@@ -82,7 +83,7 @@ const whatsappApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
82
83
  approvalKind,
83
84
  request
84
85
  }),
85
- load: async () => (await import("./approval-handler.runtime-C2cpkbpY.js")).whatsappApprovalNativeRuntime
86
+ load: async () => (await import("./approval-handler.runtime-DGJEaoqh.js")).whatsappApprovalNativeRuntime
86
87
  })
87
88
  });
88
89
  function buildWhatsAppPendingPayload(params, approvalKind) {
@@ -250,7 +251,7 @@ function createWhatsAppOutboundBase({ sendMessageWhatsApp, sendPollWhatsApp, sho
250
251
  }
251
252
  //#endregion
252
253
  //#region extensions/whatsapp/src/channel-outbound.ts
253
- const loadWhatsAppApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DrZe-NmN.js").then((n) => n.t));
254
+ const loadWhatsAppApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DSFH6Mtx.js").then((n) => n.t));
254
255
  const loadWhatsAppQuestionReactionsModule = createLazyRuntimeModule(() => import("./question-reactions-bbe0Qnjn.js").then((n) => n.n));
255
256
  function normalizeWhatsAppChannelPayloadText(text) {
256
257
  return normalizeWhatsAppPayloadTextPreservingIndentation(text);
@@ -1,2 +1,2 @@
1
- import { t as whatsappPlugin } from "./channel-dwfgnadr.js";
1
+ import { t as whatsappPlugin } from "./channel-CzEIEZqG.js";
2
2
  export { whatsappPlugin };
@@ -1,9 +1,9 @@
1
1
  import { startWebLoginWithQr as startWebLoginWithQr$1, waitForWebLogin as waitForWebLogin$1 } from "./login-qr-runtime.js";
2
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-ZWaclAbd.js";
3
3
  import { t as getActiveWebListener$1 } from "./active-listener-BEjWsCNM.js";
4
- import { t as monitorWebChannel$1 } from "./monitor-Bc6DC5jl.js";
4
+ import { t as monitorWebChannel$1 } from "./monitor-DaIAK4fT.js";
5
5
  import { t as loginWeb$1 } from "./login-6j2iP9nR.js";
6
- import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-twIi4TdN.js";
6
+ import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-CnK_PPiA.js";
7
7
  //#region extensions/whatsapp/src/channel.runtime.ts
8
8
  function getActiveWebListener(...args) {
9
9
  return getActiveWebListener$1(...args);
@@ -1,4 +1,4 @@
1
- import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupContract, l as readWhatsAppAccountLinkState, n as whatsappSetupWizardProxy, o as resolveWhatsAppGroupToolPolicy, t as createWhatsAppPluginBase } from "./shared-ByeKDmh0.js";
1
+ import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupContract, l as readWhatsAppAccountLinkState, n as whatsappSetupWizardProxy, o as resolveWhatsAppGroupToolPolicy, t as createWhatsAppPluginBase } from "./shared-CLKLJLgY.js";
2
2
  //#region extensions/whatsapp/src/channel.setup.ts
3
3
  const whatsappSetupPlugin = { ...createWhatsAppPluginBase({
4
4
  groups: {
@@ -13,7 +13,7 @@ import { t as BufferJSON } from "./session.runtime-Nsqaehbd.js";
13
13
  import { _ as resolveInboundMediaMimetype, a as addWhatsAppImagePreviewFields, c as extractContextInfo, d as extractMediaKind, f as extractMentionedJids, g as projectWhatsAppInboundMessage, h as hasInboundUserContent, i as resolveWhatsAppOutboundMentions, l as extractExternalAdReplyContext, n as addWhatsAppOutboundMentionsToContent, o as describeReplyContext, p as extractText, r as mayContainWhatsAppOutboundMention, s as extractContactContext, t as createWebSendApi, u as extractLocationData } from "./send-api-C_Zn4Ij-.js";
14
14
  import { t as resolveWhatsAppRuntimeGroupPolicy } from "./runtime-group-policy-DeSRFXEV.js";
15
15
  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-DNp6U1NN.js";
16
- import { n as maybeResolveWhatsAppApprovalReaction } from "./approval-reactions-DrZe-NmN.js";
16
+ import { n as maybeResolveWhatsAppApprovalReaction } from "./approval-reactions-DSFH6Mtx.js";
17
17
  import { t as maybeResolveWhatsAppQuestionReaction } from "./question-reactions-bbe0Qnjn.js";
18
18
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
19
19
  import { createAckReactionHandle, createStatusReactionController, logAckFailure, removeAckReactionHandleAfterReply, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
@@ -54,7 +54,7 @@ import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context
54
54
  import { buildMentionRegexes, implicitMentionKindWhen, normalizeMentionText, resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-mention-gating";
55
55
  import { channelReadyPatch, channelStoppedPatch, createTransportActivityStatusPatch } from "openclaw/plugin-sdk/gateway-runtime";
56
56
  import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
57
- import { resolveAgentIdentity, resolveIdentityNamePrefix as resolveIdentityNamePrefix$1 } from "openclaw/plugin-sdk/agent-runtime";
57
+ import { resolveAgentIdentity, resolveIdentityNamePrefix } from "openclaw/plugin-sdk/agent-runtime";
58
58
  import { normalizeGroupActivation, parseActivationCommand } from "openclaw/plugin-sdk/group-activation";
59
59
  import { formatAudioTranscriptForAgent } from "openclaw/plugin-sdk/media-understanding-runtime";
60
60
  import { hasControlCommand, isControlCommandMessage, shouldComputeCommandAuthorized } from "openclaw/plugin-sdk/command-detection";
@@ -63,7 +63,6 @@ import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
63
63
  import { resolveBatchedReplyThreadingPolicy } from "openclaw/plugin-sdk/reply-reference";
64
64
  import { LocalMediaAccessError, getDefaultLocalRoots, loadWebMedia, loadWebMediaRaw, optimizeImageToJpeg, optimizeImageToPng } from "openclaw/plugin-sdk/web-media";
65
65
  import { createChannelApiRetryRunner } from "openclaw/plugin-sdk/retry-runtime";
66
- import { resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
67
66
  //#region extensions/whatsapp/src/inbound/group-conversation.ts
68
67
  function resolveWhatsAppGroupConversationId(conversationId) {
69
68
  return resolveGroupSessionKey({
@@ -1342,6 +1341,16 @@ function createWhatsAppMessageDeliveryCoordinator(options) {
1342
1341
  const preparation = durableId ? preparedInboundByDurableId.get(durableId) : void 0;
1343
1342
  if (durableId) preparedInboundByDurableId.delete(durableId);
1344
1343
  if (context.skipRecentOutboundEcho === true) return "completed";
1344
+ if (await maybeResolveWhatsAppApprovalReaction({
1345
+ cfg: options.loadConfig?.() ?? options.cfg,
1346
+ accountId: options.accountId,
1347
+ msg,
1348
+ selfJid: self.jid,
1349
+ selfLid: self.lid,
1350
+ resolveInboundJid,
1351
+ resolveReactionTargetJids,
1352
+ logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1353
+ })) return "completed";
1345
1354
  const prepared = await preparation;
1346
1355
  if (prepared === null) return "completed";
1347
1356
  const inbound = prepared ?? await normalizeInboundMessage(msg);
@@ -1394,16 +1403,22 @@ function createWhatsAppMessageDeliveryCoordinator(options) {
1394
1403
  for (const msg of upsert.messages ?? []) {
1395
1404
  rememberBaileysMessage(msg.key?.remoteJid, msg.key?.id, msg.message);
1396
1405
  const receiveOrder = nextReceiveOrder++;
1397
- if (await maybeResolveWhatsAppApprovalReaction({
1398
- cfg: options.loadConfig?.() ?? options.cfg,
1399
- accountId: options.accountId,
1400
- msg,
1401
- selfJid: self.jid,
1402
- selfLid: self.lid,
1403
- resolveInboundJid,
1404
- resolveReactionTargetJids,
1405
- logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1406
- })) continue;
1406
+ let approvalReactionResolved = false;
1407
+ try {
1408
+ approvalReactionResolved = await maybeResolveWhatsAppApprovalReaction({
1409
+ cfg: options.loadConfig?.() ?? options.cfg,
1410
+ accountId: options.accountId,
1411
+ msg,
1412
+ selfJid: self.jid,
1413
+ selfLid: self.lid,
1414
+ resolveInboundJid,
1415
+ resolveReactionTargetJids,
1416
+ logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1417
+ });
1418
+ } catch (error) {
1419
+ inboundLogger.warn({ error: formatError(error) }, "whatsapp approval reaction resolution failed; admitting reaction for durable replay");
1420
+ }
1421
+ if (approvalReactionResolved) continue;
1407
1422
  const receivedAt = Date.now();
1408
1423
  const skipStaleAppend = shouldSkipStaleAppend(msg, upsert.type);
1409
1424
  const skipRecentOutboundEcho = shouldSkipRecentOutboundEcho(msg);
@@ -2574,21 +2589,15 @@ function resolvePeerId(msg) {
2574
2589
  }
2575
2590
  //#endregion
2576
2591
  //#region extensions/whatsapp/src/system-prompt.ts
2592
+ function resolveWhatsAppSystemPrompt(prompts, targetId) {
2593
+ if (!targetId) return;
2594
+ return (prompts?.[targetId]?.systemPrompt ?? prompts?.["*"]?.systemPrompt)?.trim() || void 0;
2595
+ }
2577
2596
  function resolveWhatsAppGroupSystemPrompt(params) {
2578
- if (!params.groupId) return;
2579
- const groups = params.accountConfig?.groups;
2580
- const specific = groups?.[params.groupId];
2581
- if (specific != null && specific.systemPrompt != null) return specific.systemPrompt.trim() || void 0;
2582
- const wildcard = groups?.["*"]?.systemPrompt;
2583
- return wildcard != null ? wildcard.trim() || void 0 : void 0;
2597
+ return resolveWhatsAppSystemPrompt(params.accountConfig?.groups, params.groupId);
2584
2598
  }
2585
2599
  function resolveWhatsAppDirectSystemPrompt(params) {
2586
- if (!params.peerId) return;
2587
- const direct = params.accountConfig?.direct;
2588
- const specific = direct?.[params.peerId];
2589
- if (specific != null && specific.systemPrompt != null) return specific.systemPrompt.trim() || void 0;
2590
- const wildcard = direct?.["*"]?.systemPrompt;
2591
- return wildcard != null ? wildcard.trim() || void 0 : void 0;
2600
+ return resolveWhatsAppSystemPrompt(params.accountConfig?.direct, params.peerId);
2592
2601
  }
2593
2602
  //#endregion
2594
2603
  //#region extensions/whatsapp/src/outbound-retry.ts
@@ -3185,7 +3194,7 @@ function logWhatsAppMediaOnlyFlushResult(result) {
3185
3194
  }
3186
3195
  function resolveWhatsAppResponsePrefix(params) {
3187
3196
  const configuredResponsePrefix = params.cfg.messages?.responsePrefix;
3188
- return params.pipelineResponsePrefix ?? (configuredResponsePrefix === "auto" ? resolveIdentityNamePrefix$1(params.cfg, params.agentId) : configuredResponsePrefix) ?? (params.isSelfChat ? resolveIdentityNamePrefix$1(params.cfg, params.agentId) : void 0);
3197
+ return params.pipelineResponsePrefix ?? (configuredResponsePrefix === "auto" ? resolveIdentityNamePrefix(params.cfg, params.agentId) : configuredResponsePrefix) ?? (params.isSelfChat ? resolveIdentityNamePrefix(params.cfg, params.agentId) : void 0);
3189
3198
  }
3190
3199
  function buildWhatsAppInboundTransportContext(msg) {
3191
3200
  return {
@@ -3552,18 +3561,6 @@ async function finalizeWhatsAppStatusReaction(params) {
3552
3561
  await params.controller.restoreInitial();
3553
3562
  }
3554
3563
  //#endregion
3555
- //#region extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts
3556
- function resolveIdentityNamePrefix(cfg, agentId) {
3557
- const identityName = resolveAgentConfig(cfg, agentId)?.identity?.name?.trim();
3558
- return identityName ? `[${identityName}]` : void 0;
3559
- }
3560
- function resolveMessagePrefix(cfg, agentId, opts) {
3561
- const configured = opts?.configured;
3562
- if (configured !== void 0) return configured;
3563
- if (opts?.hasAllowFrom === true) return "";
3564
- return resolveIdentityNamePrefix(cfg, agentId) ?? opts?.fallback ?? "[openclaw]";
3565
- }
3566
- //#endregion
3567
3564
  //#region extensions/whatsapp/src/auto-reply/monitor/message-line.ts
3568
3565
  function formatReplyTarget(replyTo) {
3569
3566
  if (!replyTo?.body) return null;
@@ -3573,17 +3570,12 @@ function formatReplyContext(msg) {
3573
3570
  return formatReplyTarget(getReplyContext(msg));
3574
3571
  }
3575
3572
  function buildInboundLine(params) {
3576
- const { cfg, msg, agentId, previousTimestamp, envelope } = params;
3577
- const messagePrefix = resolveMessagePrefix(cfg, agentId, {
3578
- configured: cfg.channels?.whatsapp?.responsePrefix,
3579
- hasAllowFrom: (cfg.channels?.whatsapp?.allowFrom?.length ?? 0) > 0
3580
- });
3573
+ const { msg, previousTimestamp, envelope } = params;
3581
3574
  const admission = requireWhatsAppInboundAdmission(msg);
3582
3575
  const conversationId = admission.conversation.id;
3583
3576
  const conversationKind = admission.conversation.kind;
3584
- const prefixStr = messagePrefix ? `${messagePrefix} ` : "";
3585
3577
  const replyContext = params.visibleReplyTo === void 0 ? formatReplyContext(msg) : formatReplyTarget(params.visibleReplyTo);
3586
- const baseLine = `${prefixStr}${msg.payload.body}${replyContext ? `\n\n${replyContext}` : ""}`;
3578
+ const baseLine = `${msg.payload.body}${replyContext ? `\n\n${replyContext}` : ""}`;
3587
3579
  const sender = getSenderIdentity(msg);
3588
3580
  return formatInboundEnvelope({
3589
3581
  channel: "WhatsApp",
@@ -3733,9 +3725,7 @@ async function processMessage(params) {
3733
3725
  groupAllowFrom: inboundPolicy.groupAllowFrom
3734
3726
  });
3735
3727
  let combinedBody = buildInboundLine({
3736
- cfg: params.cfg,
3737
3728
  msg: msgForAgent,
3738
- agentId: params.route.agentId,
3739
3729
  previousTimestamp,
3740
3730
  envelope: envelopeOptions,
3741
3731
  visibleReplyTo
@@ -10,7 +10,7 @@ import { n as resolveWebAccountId, t as getActiveWebListener } from "./active-li
10
10
  import { a as waitForWaConnection, i as newConnectionId, r as createWaSocket } from "./socket-close-B3X9uerq.js";
11
11
  import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
12
12
  import { p as extractText, s as extractContactContext, u as extractLocationData } from "./send-api-C_Zn4Ij-.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-Bc6DC5jl.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-DaIAK4fT.js";
14
14
  import { t as loginWeb } from "./login-6j2iP9nR.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, 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 };
@@ -2,7 +2,7 @@ import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./acco
2
2
  import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
3
3
  import { r as hasWebCredsSync } from "./creds-files-Drg3usj1.js";
4
4
  import { a as normalizeWhatsAppAllowFromEntries, o as normalizeWhatsAppAllowFromEntry } from "./normalize-target-CugRyONv.js";
5
- import { r as whatsappSetupAdapter } from "./shared-ByeKDmh0.js";
5
+ import { r as whatsappSetupAdapter } from "./shared-CLKLJLgY.js";
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
@@ -1,2 +1,2 @@
1
- import { t as whatsappSetupPlugin } from "./channel.setup-DckQm9ma.js";
1
+ import { t as whatsappSetupPlugin } from "./channel.setup-gIWoRLzt.js";
2
2
  export { whatsappSetupPlugin };
@@ -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-gLmc3FTV.js")).finalizeWhatsAppSetup(params),
39
+ finalize: async (params) => await (await import("./setup-finalize-CZ6fHFFU.js")).finalizeWhatsAppSetup(params),
40
40
  disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
41
41
  onAccountRecorded: (accountId, options) => {
42
42
  options?.onAccountId?.(channel, accountId);
@@ -17,7 +17,7 @@ import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
17
17
  import { createPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup";
18
18
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
19
19
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
20
- import { createDelegatedSetupWizardProxy } from "openclaw/plugin-sdk/setup-runtime";
20
+ import { createDelegatedSetupWizardProxy, setSetupChannelEnabled as setSetupChannelEnabled$1 } from "openclaw/plugin-sdk/setup-runtime";
21
21
  import { readChannelAllowFromStore } from "openclaw/plugin-sdk/channel-pairing";
22
22
  //#region extensions/whatsapp/src/channel-runtime-loader.ts
23
23
  const loadWhatsAppAuthStore = createLazyRuntimeModule(() => import("./auth-store-ZWaclAbd.js").then((n) => n.i));
@@ -27,7 +27,7 @@ async function readWhatsAppAccountLinkState(authDir) {
27
27
  }
28
28
  const loadWhatsAppChannelRuntime = createLazyRuntimeModule(async () => {
29
29
  await loadWhatsAppAuthStore();
30
- return await import("./channel.runtime-Bn3K5Ygb.js");
30
+ return await import("./channel.runtime-BFiZ9WhU.js");
31
31
  });
32
32
  //#endregion
33
33
  //#region extensions/whatsapp/src/config-accessors.ts
@@ -79,7 +79,7 @@ function applyGroupAllowFromFromStore(params) {
79
79
  if (!section || typeof section !== "object" || params.storeAllowFrom.length === 0) return params.cfg;
80
80
  let changed = false;
81
81
  const maybeApply = (prefix, holder) => {
82
- if (holder.groupPolicy !== "allowlist") return;
82
+ if (holder.groupPolicy !== "open") return;
83
83
  const allowFrom = Array.isArray(holder.allowFrom) ? holder.allowFrom : [];
84
84
  const groupAllowFrom = Array.isArray(holder.groupAllowFrom) ? holder.groupAllowFrom : [];
85
85
  if (allowFrom.length > 0 || groupAllowFrom.length > 0) return;
@@ -116,7 +116,7 @@ async function applyWhatsAppSecurityConfigFixes(params) {
116
116
  //#region extensions/whatsapp/src/shared.ts
117
117
  const WHATSAPP_CHANNEL = "whatsapp";
118
118
  async function loadWhatsAppSetupSurface() {
119
- return await import("./setup-surface-twIi4TdN.js");
119
+ return await import("./setup-surface-CnK_PPiA.js");
120
120
  }
121
121
  const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(async () => (await loadWhatsAppSetupSurface()).whatsappSetupWizard);
122
122
  const whatsappConfigAdapter = createScopedChannelConfigAdapter({
@@ -153,16 +153,7 @@ function createWhatsAppSetupWizardProxy(loadWizard) {
153
153
  resolveShouldPromptAccountIds: (params) => params.shouldPromptAccountIds,
154
154
  credentials: [],
155
155
  delegateFinalize: true,
156
- disable: (cfg) => ({
157
- ...cfg,
158
- channels: {
159
- ...cfg.channels,
160
- whatsapp: {
161
- ...cfg.channels?.whatsapp,
162
- enabled: false
163
- }
164
- }
165
- }),
156
+ disable: (cfg) => setSetupChannelEnabled$1(cfg, WHATSAPP_CHANNEL, false),
166
157
  onAccountRecorded: (accountId, options) => {
167
158
  options?.onAccountId?.(WHATSAPP_CHANNEL, accountId);
168
159
  }
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "id": "whatsapp",
3
+ "categories": [
4
+ "channels",
5
+ "tools"
6
+ ],
3
7
  "doctorContract": {
4
8
  "configRepair": true,
5
- "stateMigrations": true
9
+ "stateMigrations": [
10
+ {
11
+ "id": "whatsapp-legacy-state"
12
+ }
13
+ ]
6
14
  },
7
15
  "name": "WhatsApp",
8
16
  "description": "OpenClaw WhatsApp channel plugin for WhatsApp Web chats.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/whatsapp",
3
- "version": "2026.9.2",
3
+ "version": "2026.9.4",
4
4
  "description": "OpenClaw WhatsApp channel plugin for WhatsApp Web chats.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,7 +13,7 @@
13
13
  "typebox": "1.3.18"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.9.2"
16
+ "openclaw": ">=2026.9.4"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
@@ -65,11 +65,11 @@
65
65
  "minHostVersion": ">=2026.4.25"
66
66
  },
67
67
  "compat": {
68
- "pluginApi": ">=2026.9.2"
68
+ "pluginApi": ">=2026.9.4"
69
69
  },
70
70
  "build": {
71
71
  "bundledDist": false,
72
- "openclawVersion": "2026.9.2"
72
+ "openclawVersion": "2026.9.4"
73
73
  },
74
74
  "release": {
75
75
  "publishToClawHub": true,