@openclaw/whatsapp 2026.9.1 → 2026.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/api.js +3 -3
  2. package/dist/{approval-handler.runtime-C2cpkbpY.js → approval-handler.runtime-DGJEaoqh.js} +1 -1
  3. package/dist/{approval-reactions-DrZe-NmN.js → approval-reactions-DSFH6Mtx.js} +20 -53
  4. package/dist/{channel-DebjeuFC.js → channel-BeBrHPVa.js} +3 -7
  5. package/dist/channel-plugin-api.js +1 -1
  6. package/dist/{channel.runtime-B90_wffD.js → channel.runtime-qi6Zbi9p.js} +2 -2
  7. package/dist/{channel.setup-D1-jE0aE.js → channel.setup-DhuZ51Kg.js} +1 -1
  8. package/dist/{monitor-DyPdOPRx.js → monitor-DNGfO3k0.js} +77 -49
  9. package/dist/runtime-api.js +1 -1
  10. package/dist/{setup-finalize-C5QtbrWV.js → setup-finalize-Bp-4QnVw.js} +1 -1
  11. package/dist/setup-plugin-api.js +1 -1
  12. package/dist/{setup-surface-WsAzq337.js → setup-surface-B5UnuLT_.js} +1 -1
  13. package/dist/{shared-BzKxoeKY.js → shared-D6cUWXiq.js} +7 -3
  14. package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
  15. package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
  16. package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
  17. package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
  18. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  19. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  20. package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
  21. package/node_modules/typebox/build/system/memory/create.mjs +3 -4
  22. package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
  23. package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
  24. package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
  25. package/node_modules/typebox/build/system/memory/update.mjs +3 -2
  26. package/node_modules/typebox/package.json +1 -1
  27. package/openclaw.plugin.json +5 -2
  28. package/package.json +5 -5
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-DebjeuFC.js";
8
- import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-BzKxoeKY.js";
7
+ import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, t as whatsappPlugin } from "./channel-BeBrHPVa.js";
8
+ import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy } from "./shared-D6cUWXiq.js";
9
9
  import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
10
- import { t as whatsappSetupPlugin } from "./channel.setup-D1-jE0aE.js";
10
+ import { t as whatsappSetupPlugin } from "./channel.setup-DhuZ51Kg.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-BzKxoeKY.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-D6cUWXiq.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";
@@ -82,7 +82,7 @@ const whatsappApproval = createApproverRestrictedNativeApprovalCapabilityFromFor
82
82
  approvalKind,
83
83
  request
84
84
  }),
85
- load: async () => (await import("./approval-handler.runtime-C2cpkbpY.js")).whatsappApprovalNativeRuntime
85
+ load: async () => (await import("./approval-handler.runtime-DGJEaoqh.js")).whatsappApprovalNativeRuntime
86
86
  })
87
87
  });
88
88
  function buildWhatsAppPendingPayload(params, approvalKind) {
@@ -229,10 +229,6 @@ function createWhatsAppOutboundBase({ sendMessageWhatsApp, sendPollWhatsApp, sho
229
229
  return {
230
230
  ...outbound,
231
231
  sendPayload: async (ctx) => {
232
- if (ctx.payload.isError === true) return {
233
- channel: "whatsapp",
234
- messageId: ""
235
- };
236
232
  const payload = normalizeWhatsAppOutboundPayload(ctx.payload, { normalizeText });
237
233
  if (!payload.text && !(payload.mediaUrl || payload.mediaUrls?.length)) {
238
234
  if (ctx.payload.interactive || ctx.payload.presentation || ctx.payload.channelData) throw new Error("WhatsApp sendPayload does not support structured-only payloads without text or media.");
@@ -254,7 +250,7 @@ function createWhatsAppOutboundBase({ sendMessageWhatsApp, sendPollWhatsApp, sho
254
250
  }
255
251
  //#endregion
256
252
  //#region extensions/whatsapp/src/channel-outbound.ts
257
- const loadWhatsAppApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DrZe-NmN.js").then((n) => n.t));
253
+ const loadWhatsAppApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-DSFH6Mtx.js").then((n) => n.t));
258
254
  const loadWhatsAppQuestionReactionsModule = createLazyRuntimeModule(() => import("./question-reactions-bbe0Qnjn.js").then((n) => n.n));
259
255
  function normalizeWhatsAppChannelPayloadText(text) {
260
256
  return normalizeWhatsAppPayloadTextPreservingIndentation(text);
@@ -1,2 +1,2 @@
1
- import { t as whatsappPlugin } from "./channel-DebjeuFC.js";
1
+ import { t as whatsappPlugin } from "./channel-BeBrHPVa.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-DyPdOPRx.js";
4
+ import { t as monitorWebChannel$1 } from "./monitor-DNGfO3k0.js";
5
5
  import { t as loginWeb$1 } from "./login-6j2iP9nR.js";
6
- import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-WsAzq337.js";
6
+ import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-B5UnuLT_.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-BzKxoeKY.js";
1
+ import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupContract, l as readWhatsAppAccountLinkState, n as whatsappSetupWizardProxy, o as resolveWhatsAppGroupToolPolicy, t as createWhatsAppPluginBase } from "./shared-D6cUWXiq.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";
@@ -40,12 +40,12 @@ import { createHash } from "node:crypto";
40
40
  import { resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
41
41
  import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
42
42
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-runtime";
43
- import { createInboundDebouncer, resolveInboundDebounceMs } from "openclaw/plugin-sdk/channel-inbound-debounce";
44
43
  import { drainPendingDeliveries } from "openclaw/plugin-sdk/delivery-queue-runtime";
45
44
  import { DEFAULT_GROUP_HISTORY_LIMIT, buildHistoryContextFromEntries, buildInboundHistoryFromEntries, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
46
45
  import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
47
46
  import { fanInChannelIngressLifecycles, resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
48
47
  import { getSessionEntry, patchSessionEntry, resolveGroupSessionKey, resolveStorePath, resolveStorePath as resolveStorePath$1, updateLastRoute } from "openclaw/plugin-sdk/session-store-runtime";
48
+ import { createInboundDebouncer, resolveInboundDebounceMs } from "openclaw/plugin-sdk/channel-inbound-debounce";
49
49
  import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
50
50
  import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
51
51
  import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
@@ -529,10 +529,10 @@ function createWhatsAppGroupMetadataCacheOwner(params) {
529
529
  const listen = (event, listener) => {
530
530
  detachListeners.push(params.listen(event, listener));
531
531
  };
532
- listen("groups.upsert", ((groups) => {
532
+ listen("groups.upsert", (groups) => {
533
533
  for (const group of groups) if (group.id) rememberFullUpdate(group.id, group);
534
- }));
535
- listen("groups.update", ((updates) => {
534
+ });
535
+ listen("groups.update", (updates) => {
536
536
  for (const update of updates) {
537
537
  if (!update.id) continue;
538
538
  if (typeof update.subject === "string" && Array.isArray(update.participants)) {
@@ -541,10 +541,10 @@ function createWhatsAppGroupMetadataCacheOwner(params) {
541
541
  }
542
542
  forgetFullMetadata(update.id);
543
543
  }
544
- }));
545
- listen("group-participants.update", ((update) => {
544
+ });
545
+ listen("group-participants.update", (update) => {
546
546
  forgetFullMetadata(update.id);
547
- }));
547
+ });
548
548
  (async () => {
549
549
  try {
550
550
  const groups = await params.sock.groupFetchAllParticipating();
@@ -578,13 +578,7 @@ function createWhatsAppGroupMetadataCacheOwner(params) {
578
578
  //#region extensions/whatsapp/src/inbound/lifecycle.ts
579
579
  function attachEmitterListener(emitter, event, listener) {
580
580
  emitter.on(event, listener);
581
- return () => {
582
- if (typeof emitter.off === "function") {
583
- emitter.off(event, listener);
584
- return;
585
- }
586
- if (typeof emitter.removeListener === "function") emitter.removeListener(event, listener);
587
- };
581
+ return () => emitter.off(event, listener);
588
582
  }
589
583
  function closeInboundMonitorSocket(sock) {
590
584
  if (typeof sock.end === "function") {
@@ -606,7 +600,6 @@ function resolveWhatsAppIngressLifecycle(message) {
606
600
  //#endregion
607
601
  //#region extensions/whatsapp/src/inbound/message-debounce.ts
608
602
  function createWhatsAppInboundMessageDebouncer(options) {
609
- const debounceMs = Math.max(0, Math.trunc(options.debounceMs ?? 0));
610
603
  const pendingKeys = /* @__PURE__ */ new Map();
611
604
  const activeFlushes = /* @__PURE__ */ new Set();
612
605
  const workWaiters = /* @__PURE__ */ new Set();
@@ -636,7 +629,8 @@ function createWhatsAppInboundMessageDebouncer(options) {
636
629
  return timestampDiff !== 0 ? timestampDiff : (a.receiveOrder ?? 0) - (b.receiveOrder ?? 0);
637
630
  });
638
631
  const debouncer = createInboundDebouncer({
639
- debounceMs,
632
+ debounceMs: options.resolveDebounceMs(),
633
+ resolveDebounceMs: (entry) => entry.debounceMs,
640
634
  buildKey: (msg) => msg.debounceKey ?? buildKey(msg),
641
635
  shouldDebounce,
642
636
  onFlush: (entries, createFlush) => {
@@ -702,11 +696,15 @@ function createWhatsAppInboundMessageDebouncer(options) {
702
696
  },
703
697
  onError: options.onError
704
698
  });
705
- const enqueue = async (message) => {
699
+ const enqueue = async (input) => {
700
+ const message = {
701
+ ...input,
702
+ debounceMs: options.resolveDebounceMs()
703
+ };
706
704
  const key = buildKey(message);
707
705
  if (key) {
708
706
  message.debounceKey = key;
709
- if (debounceMs > 0 && shouldDebounce(message)) {
707
+ if (message.debounceMs > 0 && shouldDebounce(message)) {
710
708
  message.debounceKeyTracked = true;
711
709
  trackKey(key);
712
710
  options.onPendingWorkChanged();
@@ -1184,7 +1182,11 @@ function createWhatsAppMessageDeliveryCoordinator(options) {
1184
1182
  await maybeMarkInboundAsRead(target);
1185
1183
  };
1186
1184
  const messageDebouncer = createWhatsAppInboundMessageDebouncer({
1187
- debounceMs: options.debounceMs,
1185
+ resolveDebounceMs: () => resolveInboundDebounceMs({
1186
+ cfg: options.loadConfig?.() ?? options.cfg,
1187
+ channel: "whatsapp",
1188
+ overrideMs: options.debounceMs
1189
+ }),
1188
1190
  onMessage: options.onMessage,
1189
1191
  shouldDebounce: options.shouldDebounce,
1190
1192
  markRead: maybeMarkInboundAsRead,
@@ -1340,6 +1342,16 @@ function createWhatsAppMessageDeliveryCoordinator(options) {
1340
1342
  const preparation = durableId ? preparedInboundByDurableId.get(durableId) : void 0;
1341
1343
  if (durableId) preparedInboundByDurableId.delete(durableId);
1342
1344
  if (context.skipRecentOutboundEcho === true) return "completed";
1345
+ if (await maybeResolveWhatsAppApprovalReaction({
1346
+ cfg: options.loadConfig?.() ?? options.cfg,
1347
+ accountId: options.accountId,
1348
+ msg,
1349
+ selfJid: self.jid,
1350
+ selfLid: self.lid,
1351
+ resolveInboundJid,
1352
+ resolveReactionTargetJids,
1353
+ logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1354
+ })) return "completed";
1343
1355
  const prepared = await preparation;
1344
1356
  if (prepared === null) return "completed";
1345
1357
  const inbound = prepared ?? await normalizeInboundMessage(msg);
@@ -1392,16 +1404,22 @@ function createWhatsAppMessageDeliveryCoordinator(options) {
1392
1404
  for (const msg of upsert.messages ?? []) {
1393
1405
  rememberBaileysMessage(msg.key?.remoteJid, msg.key?.id, msg.message);
1394
1406
  const receiveOrder = nextReceiveOrder++;
1395
- if (await maybeResolveWhatsAppApprovalReaction({
1396
- cfg: options.loadConfig?.() ?? options.cfg,
1397
- accountId: options.accountId,
1398
- msg,
1399
- selfJid: self.jid,
1400
- selfLid: self.lid,
1401
- resolveInboundJid,
1402
- resolveReactionTargetJids,
1403
- logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1404
- })) continue;
1407
+ let approvalReactionResolved = false;
1408
+ try {
1409
+ approvalReactionResolved = await maybeResolveWhatsAppApprovalReaction({
1410
+ cfg: options.loadConfig?.() ?? options.cfg,
1411
+ accountId: options.accountId,
1412
+ msg,
1413
+ selfJid: self.jid,
1414
+ selfLid: self.lid,
1415
+ resolveInboundJid,
1416
+ resolveReactionTargetJids,
1417
+ logVerboseMessage: (message) => logWhatsAppVerbose$1(options.verbose, message)
1418
+ });
1419
+ } catch (error) {
1420
+ inboundLogger.warn({ error: formatError(error) }, "whatsapp approval reaction resolution failed; admitting reaction for durable replay");
1421
+ }
1422
+ if (approvalReactionResolved) continue;
1405
1423
  const receivedAt = Date.now();
1406
1424
  const skipStaleAppend = shouldSkipStaleAppend(msg, upsert.type);
1407
1425
  const skipRecentOutboundEcho = shouldSkipRecentOutboundEcho(msg);
@@ -2415,7 +2433,11 @@ async function applyGroupGating(params) {
2415
2433
  const conversationGroupPolicy = inboundPolicy.resolveConversationGroupPolicy(conversationId);
2416
2434
  if (conversationGroupPolicy.allowlistEnabled && !conversationGroupPolicy.allowed) {
2417
2435
  const accountId = inboundPolicy.account.accountId;
2418
- if (shouldWarnForGroupDrop(`${accountId}:${conversationId}`)) {
2436
+ if (shouldWarnForGroupDrop(JSON.stringify([
2437
+ accountId,
2438
+ conversationId,
2439
+ "group registry"
2440
+ ]))) {
2419
2441
  const groupsPath = resolveWhatsAppGroupsConfigPath({
2420
2442
  cfg: params.cfg,
2421
2443
  accountId
@@ -2504,6 +2526,22 @@ async function applyGroupGating(params) {
2504
2526
  needsMentionText: true
2505
2527
  };
2506
2528
  }
2529
+ const accountId = inboundPolicy.account.accountId;
2530
+ if (shouldWarnForGroupDrop(JSON.stringify([
2531
+ accountId,
2532
+ conversationId,
2533
+ "no mention"
2534
+ ]))) {
2535
+ const groupsPath = resolveWhatsAppGroupsConfigPath({
2536
+ cfg: params.cfg,
2537
+ accountId
2538
+ });
2539
+ params.replyLogger.warn({
2540
+ conversationId,
2541
+ accountId,
2542
+ groupsPath
2543
+ }, `WhatsApp group ${conversationId}: skipping messages without a mention. Mention patterns can be derived from the agent identity name. Use /activation always for this session, or set ${groupsPath}[${JSON.stringify(conversationId)}].requireMention=false for the default. Preserve existing groups entries; when adding the first groups map, include "*": {} to keep other chats admitted.`);
2544
+ }
2507
2545
  const pendingHistoryBody = params.mentionText === void 0 ? void 0 : formatAudioTranscriptForAgent(params.mentionText);
2508
2546
  return skipGroupMessageAndStoreHistory(params, `Group message stored for context (no mention detected) in ${conversationId}: ${mentionMsg.payload.body}`, pendingHistoryBody);
2509
2547
  }
@@ -2552,21 +2590,15 @@ function resolvePeerId(msg) {
2552
2590
  }
2553
2591
  //#endregion
2554
2592
  //#region extensions/whatsapp/src/system-prompt.ts
2593
+ function resolveWhatsAppSystemPrompt(prompts, targetId) {
2594
+ if (!targetId) return;
2595
+ return (prompts?.[targetId]?.systemPrompt ?? prompts?.["*"]?.systemPrompt)?.trim() || void 0;
2596
+ }
2555
2597
  function resolveWhatsAppGroupSystemPrompt(params) {
2556
- if (!params.groupId) return;
2557
- const groups = params.accountConfig?.groups;
2558
- const specific = groups?.[params.groupId];
2559
- if (specific != null && specific.systemPrompt != null) return specific.systemPrompt.trim() || void 0;
2560
- const wildcard = groups?.["*"]?.systemPrompt;
2561
- return wildcard != null ? wildcard.trim() || void 0 : void 0;
2598
+ return resolveWhatsAppSystemPrompt(params.accountConfig?.groups, params.groupId);
2562
2599
  }
2563
2600
  function resolveWhatsAppDirectSystemPrompt(params) {
2564
- if (!params.peerId) return;
2565
- const direct = params.accountConfig?.direct;
2566
- const specific = direct?.[params.peerId];
2567
- if (specific != null && specific.systemPrompt != null) return specific.systemPrompt.trim() || void 0;
2568
- const wildcard = direct?.["*"]?.systemPrompt;
2569
- return wildcard != null ? wildcard.trim() || void 0 : void 0;
2601
+ return resolveWhatsAppSystemPrompt(params.accountConfig?.direct, params.peerId);
2570
2602
  }
2571
2603
  //#endregion
2572
2604
  //#region extensions/whatsapp/src/outbound-retry.ts
@@ -3071,7 +3103,7 @@ function resolveWhatsAppDurableReplyToId(params) {
3071
3103
  }
3072
3104
  function resolveWhatsAppDeliverablePayload(payload, info) {
3073
3105
  if (payload.isReasoning === true || payload.isCompactionNotice === true) return null;
3074
- if (payload.isError === true) return null;
3106
+ if (payload.isError === true && info.kind !== "final") return null;
3075
3107
  if (info.kind === "tool") {
3076
3108
  if (!resolveSendableOutboundReplyParts(payload).hasMedia) return null;
3077
3109
  return {
@@ -4348,10 +4380,6 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
4348
4380
  while (true) {
4349
4381
  if (stopRequested()) break;
4350
4382
  const connectionId = newConnectionId();
4351
- const inboundDebounceMs = resolveInboundDebounceMs({
4352
- cfg,
4353
- channel: "whatsapp"
4354
- });
4355
4383
  const shouldDebounce = (msg) => shouldDebounceTextInbound({
4356
4384
  text: msg.payload.commandBody ?? msg.payload.body,
4357
4385
  cfg,
@@ -4396,7 +4424,7 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
4396
4424
  selfChatMode: account.selfChatMode,
4397
4425
  sendReadReceipts: account.sendReadReceipts,
4398
4426
  socketTiming,
4399
- debounceMs: inboundDebounceMs,
4427
+ debounceMs: tuning.debounceMs,
4400
4428
  appendReplyWindow: connectionLocal.openedAfterRecentInbound ? {
4401
4429
  afterMs: connectionLocal.startedAt - reconnectCatchUpWindowMs,
4402
4430
  untilMs: connectionLocal.startedAt + reconnectCatchUpWindowMs,
@@ -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-DyPdOPRx.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-DNGfO3k0.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-BzKxoeKY.js";
5
+ import { r as whatsappSetupAdapter } from "./shared-D6cUWXiq.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-D1-jE0aE.js";
1
+ import { t as whatsappSetupPlugin } from "./channel.setup-DhuZ51Kg.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-C5QtbrWV.js")).finalizeWhatsAppSetup(params),
39
+ finalize: async (params) => await (await import("./setup-finalize-Bp-4QnVw.js")).finalizeWhatsAppSetup(params),
40
40
  disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
41
41
  onAccountRecorded: (accountId, options) => {
42
42
  options?.onAccountId?.(channel, accountId);
@@ -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-B90_wffD.js");
30
+ return await import("./channel.runtime-qi6Zbi9p.js");
31
31
  });
32
32
  //#endregion
33
33
  //#region extensions/whatsapp/src/config-accessors.ts
@@ -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-WsAzq337.js");
119
+ return await import("./setup-surface-B5UnuLT_.js");
120
120
  }
121
121
  const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(async () => (await loadWhatsAppSetupSurface()).whatsappSetupWizard);
122
122
  const whatsappConfigAdapter = createScopedChannelConfigAdapter({
@@ -252,7 +252,11 @@ function createWhatsAppPluginBase(params) {
252
252
  "channels.whatsapp.accounts",
253
253
  "channels.whatsapp.selfChatMode"
254
254
  ],
255
- noopPrefixes: ["channels.whatsapp"]
255
+ noopPrefixes: [
256
+ "channels.whatsapp",
257
+ "messages.inbound",
258
+ "messages.ackReactionScope"
259
+ ]
256
260
  },
257
261
  gatewayMethodDescriptors: [{ name: "web.login.start" }, { name: "web.login.wait" }],
258
262
  configSchema: WhatsAppChannelConfigSchema,
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Returns true if the value is a json pointer
3
- * @specification
4
- * @source ajv-formats
3
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
4
+ * @source https://github.com/ajv-validator/ajv-formats
5
5
  */
6
6
  export declare function IsJsonPointer(value: string): boolean;
@@ -1,8 +1,8 @@
1
1
  const JsonPointer = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
2
2
  /**
3
3
  * Returns true if the value is a json pointer
4
- * @specification
5
- * @source ajv-formats
4
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
5
+ * @source https://github.com/ajv-validator/ajv-formats
6
6
  */
7
7
  export function IsJsonPointer(value) {
8
8
  return JsonPointer.test(value);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Returns true if the value is a json pointer uri fragment
3
- * @specification
4
- * @source ajv-formats
3
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
4
+ * @source https://github.com/ajv-validator/ajv-formats
5
5
  */
6
6
  export declare function IsJsonPointerUriFragment(value: string): boolean;
@@ -1,8 +1,8 @@
1
1
  const JsonPointerUriFragment = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
2
2
  /**
3
3
  * Returns true if the value is a json pointer uri fragment
4
- * @specification
5
- * @source ajv-formats
4
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
5
+ * @source https://github.com/ajv-validator/ajv-formats
6
6
  */
7
7
  export function IsJsonPointerUriFragment(value) {
8
8
  return JsonPointerUriFragment.test(value);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Returns true if the value is a relative json pointer
3
- * @specification
4
- * @source ajv-formats
3
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
4
+ * @source https://github.com/ajv-validator/ajv-formats
5
5
  */
6
6
  export declare function IsRelativeJsonPointer(value: string): boolean;
@@ -1,8 +1,8 @@
1
1
  const RelativeJsonPointer = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
2
2
  /**
3
3
  * Returns true if the value is a relative json pointer
4
- * @specification
5
- * @source ajv-formats
4
+ * @specification https://datatracker.ietf.org/doc/html/rfc6901
5
+ * @source https://github.com/ajv-validator/ajv-formats
6
6
  */
7
7
  export function IsRelativeJsonPointer(value) {
8
8
  return RelativeJsonPointer.test(value);
@@ -1,11 +1,12 @@
1
1
  // deno-lint-ignore-file ban-types no-explicit-any
2
2
  // deno-fmt-ignore-file
3
3
  import { Metrics } from './metrics.mjs';
4
+ import { Freeze } from './freeze.mjs';
4
5
  /**
5
6
  * Performs an Object assign using the Left and Right object types. We track this operation as it
6
7
  * creates a new GC handle per assignment.
7
8
  */
8
9
  export function Assign(left, right) {
9
10
  Metrics.assign += 1;
10
- return { ...left, ...right };
11
+ return Freeze({ ...left, ...right });
11
12
  }
@@ -1,7 +1,7 @@
1
1
  // deno-lint-ignore-file no-explicit-any
2
- // deno-fmt-ignore-file
3
2
  import { Settings } from '../settings/index.mjs';
4
3
  import { Metrics } from './metrics.mjs';
4
+ import { Freeze } from './freeze.mjs';
5
5
  function MergeHidden(left, right) {
6
6
  for (const key of Object.keys(right)) {
7
7
  Object.defineProperty(left, key, {
@@ -23,8 +23,7 @@ function Merge(left, right) {
23
23
  */
24
24
  export function Create(hidden, enumerable, options = {}) {
25
25
  Metrics.create += 1;
26
- const settings = Settings.Get();
27
26
  const withOptions = Merge(enumerable, options);
28
- const withHidden = settings.enumerableKind ? Merge(withOptions, hidden) : MergeHidden(withOptions, hidden);
29
- return settings.immutableTypes ? Object.freeze(withHidden) : withHidden;
27
+ const withHidden = Settings.Get().enumerableKind ? Merge(withOptions, hidden) : MergeHidden(withOptions, hidden);
28
+ return Freeze(withHidden);
30
29
  }
@@ -1,7 +1,7 @@
1
1
  // deno-lint-ignore-file no-explicit-any
2
- // deno-fmt-ignore-file
3
2
  import { Guard } from '../../guard/index.mjs';
4
3
  import { Metrics } from './metrics.mjs';
4
+ import { Freeze } from './freeze.mjs';
5
5
  import { Clone } from './clone.mjs';
6
6
  /** Discards multiple property keys from the given object value */
7
7
  export function Discard(value, propertyKeys) {
@@ -14,5 +14,5 @@ export function Discard(value, propertyKeys) {
14
14
  descriptor.value = Clone(descriptor.value);
15
15
  Object.defineProperty(result, key, descriptor);
16
16
  }
17
- return result;
17
+ return Freeze(result);
18
18
  }
@@ -0,0 +1,4 @@
1
+ type ObjectLike = Record<PropertyKey, any>;
2
+ /** Conditionally freezes the value if `immutableTypes` is true, otherwise no action. */
3
+ export declare function Freeze(value: ObjectLike): ObjectLike;
4
+ export {};
@@ -0,0 +1,6 @@
1
+ // deno-lint-ignore-file no-explicit-any
2
+ import { Settings } from '../settings/index.mjs';
3
+ /** Conditionally freezes the value if `immutableTypes` is true, otherwise no action. */
4
+ export function Freeze(value) {
5
+ return Settings.Get().immutableTypes ? Object.freeze(value) : value;
6
+ }
@@ -1,6 +1,7 @@
1
- // deno-fmt-ignore-file
1
+ // deno-lint-ignore-file no-explicit-any
2
2
  import { Settings } from '../settings/index.mjs';
3
3
  import { Metrics } from './metrics.mjs';
4
+ import { Freeze } from './freeze.mjs';
4
5
  import { Clone } from './clone.mjs';
5
6
  /**
6
7
  * Updates a value with new properties while preserving property enumerability. Use this function to modify
@@ -28,5 +29,5 @@ export function Update(current, hidden, enumerable) {
28
29
  value: enumerable[key]
29
30
  });
30
31
  }
31
- return result;
32
+ return Freeze(result);
32
33
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typebox",
3
3
  "description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
4
- "version": "1.3.17",
4
+ "version": "1.3.18",
5
5
  "keywords": [
6
6
  "typescript",
7
7
  "jsonschema"
@@ -2,11 +2,14 @@
2
2
  "id": "whatsapp",
3
3
  "doctorContract": {
4
4
  "configRepair": true,
5
- "stateMigrations": true
5
+ "stateMigrations": [
6
+ {
7
+ "id": "whatsapp-legacy-state"
8
+ }
9
+ ]
6
10
  },
7
11
  "name": "WhatsApp",
8
12
  "description": "OpenClaw WhatsApp channel plugin for WhatsApp Web chats.",
9
- "icon": "https://cdn.simpleicons.org/whatsapp",
10
13
  "skills": [
11
14
  "./skills"
12
15
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/whatsapp",
3
- "version": "2026.9.1",
3
+ "version": "2026.9.3",
4
4
  "description": "OpenClaw WhatsApp channel plugin for WhatsApp Web chats.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,10 +10,10 @@
10
10
  "dependencies": {
11
11
  "audio-decode": "2.2.3",
12
12
  "baileys": "7.0.0-rc14",
13
- "typebox": "1.3.17"
13
+ "typebox": "1.3.18"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.9.1"
16
+ "openclaw": ">=2026.9.3"
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.1"
68
+ "pluginApi": ">=2026.9.3"
69
69
  },
70
70
  "build": {
71
71
  "bundledDist": false,
72
- "openclawVersion": "2026.9.1"
72
+ "openclawVersion": "2026.9.3"
73
73
  },
74
74
  "release": {
75
75
  "publishToClawHub": true,