@openclaw/whatsapp 2026.5.20-beta.1 → 2026.5.20

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 (37) hide show
  1. package/dist/{access-control-CBNRBEa4.js → access-control-p_vcYDW7.js} +1 -1
  2. package/dist/{accounts-DskwwYAM.js → accounts-BPYgj8Fv.js} +2 -6
  3. package/dist/{action-runtime-Up8OrLd_.js → action-runtime-D4UqEXqf.js} +2 -2
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/action-runtime.runtime.js +1 -1
  6. package/dist/{agent-tools-login-EtLHKziO.js → agent-tools-login-BDzvb3ee.js} +0 -1
  7. package/dist/api.js +9 -9
  8. package/dist/auth-presence.js +1 -1
  9. package/dist/{auth-store-C-5icsdY.js → auth-store-GTQvJznL.js} +51 -60
  10. package/dist/{channel-Ij-BWm7q.js → channel-BVMD1oZL.js} +8 -8
  11. package/dist/channel-plugin-api.js +1 -1
  12. package/dist/{channel-react-action-DEUfqgMx.js → channel-react-action-CHdR3gbn.js} +3 -3
  13. package/dist/{channel.runtime-CvfJiuex.js → channel.runtime-BBPZSziE.js} +4 -4
  14. package/dist/{channel.setup-CBHtRTDw.js → channel.setup-BDH3Mk5M.js} +2 -2
  15. package/dist/{connection-controller-CPWZZXwV.js → connection-controller-9TXWZRhx.js} +2 -2
  16. package/dist/contract-api.js +1 -1
  17. package/dist/creds-files-B1kSWtBg.js +79 -0
  18. package/dist/light-runtime-api.js +2 -2
  19. package/dist/{login-CGOtBPVS.js → login-nJwaNuC-.js} +4 -4
  20. package/dist/{login-qr-BYNpc3IS.js → login-qr-l4UaR8Dj.js} +4 -4
  21. package/dist/login-qr-runtime.js +1 -1
  22. package/dist/{monitor-DYvWelW5.js → monitor-Dw2i5QSQ.js} +11 -17
  23. package/dist/{outbound-adapter-AQXm0jeQ.js → outbound-adapter-ltiZkW9L.js} +3 -3
  24. package/dist/{outbound-base-BCEEnbqz.js → outbound-base-E84SMkd9.js} +1 -1
  25. package/dist/outbound-payload-test-api.js +1 -1
  26. package/dist/runtime-api.js +9 -9
  27. package/dist/{send-CiXxYtQ_.js → send-E_kMiuZP.js} +2 -2
  28. package/dist/{send-api-CcNZTwSs.js → send-api-CXPUXbUL.js} +1 -1
  29. package/dist/{session-Bn5i1Fqp.js → session-CPsgRMMa.js} +16 -8
  30. package/dist/{setup-core-m8ba61Dp.js → setup-core-Dm1hsI3r.js} +3 -3
  31. package/dist/{setup-finalize-Du-2MqfD.js → setup-finalize-BlTQrUj9.js} +6 -6
  32. package/dist/setup-plugin-api.js +1 -1
  33. package/dist/{setup-surface-D4sy0_LW.js → setup-surface-DqY0LqAY.js} +3 -3
  34. package/dist/test-api.js +1 -1
  35. package/package.json +4 -4
  36. package/dist/creds-files-D9VwL4Az.js +0 -19
  37. package/dist/{outbound-media-contract-Dk324Pce.js → outbound-media-contract-ioTkt8tn.js} +1 -1
@@ -1,4 +1,4 @@
1
- import { a as resolveWhatsAppAccount } from "./accounts-DskwwYAM.js";
1
+ import { a as resolveWhatsAppAccount } from "./accounts-BPYgj8Fv.js";
2
2
  import { l as isSelfChatMode, n as normalizeE164 } from "./text-runtime-Dk37KYHj.js";
3
3
  import { a as getSelfIdentity, o as getSenderIdentity } from "./identity-xoLLdqEv.js";
4
4
  import { t as resolveWhatsAppRuntimeGroupPolicy } from "./runtime-group-policy-DeSRFXEV.js";
@@ -1,6 +1,6 @@
1
1
  import { t as resolveMergedWhatsAppAccountConfig } from "./account-config-Bxl16soz.js";
2
2
  import { n as listConfiguredAccountIds, r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
3
- import { t as hasWebCredsSync } from "./creds-files-D9VwL4Az.js";
3
+ import { n as hasWebCredsRegularFileSync, r as hasWebCredsSync } from "./creds-files-B1kSWtBg.js";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, resolveUserPath } from "openclaw/plugin-sdk/account-core";
@@ -36,11 +36,7 @@ function resolveLegacyAuthDir() {
36
36
  return resolveOAuthDir();
37
37
  }
38
38
  function legacyAuthExists(authDir) {
39
- try {
40
- return fs.existsSync(path.join(authDir, "creds.json"));
41
- } catch {
42
- return false;
43
- }
39
+ return hasWebCredsRegularFileSync(authDir);
44
40
  }
45
41
  function resolveWhatsAppAuthDir(params) {
46
42
  const accountId = params.accountId.trim() || DEFAULT_ACCOUNT_ID;
@@ -1,7 +1,7 @@
1
- import { a as resolveWhatsAppAccount } from "./accounts-DskwwYAM.js";
1
+ import { a as resolveWhatsAppAccount } from "./accounts-BPYgj8Fv.js";
2
2
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CV-iBmSG.js";
3
3
  import { t as resolveWhatsAppReactionLevel } from "./reaction-level-BqMOEBeq.js";
4
- import { r as sendReactionWhatsApp } from "./send-CiXxYtQ_.js";
4
+ import { r as sendReactionWhatsApp } from "./send-E_kMiuZP.js";
5
5
  import { ToolAuthorizationError, createActionGate, jsonResult, readReactionParams, readStringParam } from "openclaw/plugin-sdk/channel-actions";
6
6
  //#region extensions/whatsapp/src/action-runtime-target-auth.ts
7
7
  function resolveAuthorizedWhatsAppOutboundTarget(params) {
@@ -1,2 +1,2 @@
1
- import { t as handleWhatsAppAction } from "./action-runtime-Up8OrLd_.js";
1
+ import { t as handleWhatsAppAction } from "./action-runtime-D4UqEXqf.js";
2
2
  export { handleWhatsAppAction };
@@ -1,2 +1,2 @@
1
- import { t as handleWhatsAppAction } from "./action-runtime-Up8OrLd_.js";
1
+ import { t as handleWhatsAppAction } from "./action-runtime-D4UqEXqf.js";
2
2
  export { handleWhatsAppAction };
@@ -10,7 +10,6 @@ function createWhatsAppLoginTool() {
10
10
  return {
11
11
  label: "WhatsApp Login",
12
12
  name: "whatsapp_login",
13
- ownerOnly: true,
14
13
  description: "Generate a WhatsApp QR code for linking, or wait for the scan to complete.",
15
14
  parameters: Type.Object({
16
15
  action: Type.Unsafe({
package/dist/api.js CHANGED
@@ -1,21 +1,21 @@
1
1
  import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
2
- import { a as resolveWhatsAppAccount, i as listWhatsAppAuthDirs, n as hasAnyWhatsAppAuth, o as resolveWhatsAppAuthDir, r as listEnabledWhatsAppAccounts, s as resolveWhatsAppMediaMaxBytes, t as DEFAULT_WHATSAPP_MEDIA_MAX_MB } from "./accounts-DskwwYAM.js";
2
+ import { a as resolveWhatsAppAccount, i as listWhatsAppAuthDirs, n as hasAnyWhatsAppAuth, o as resolveWhatsAppAuthDir, r as listEnabledWhatsAppAccounts, s as resolveWhatsAppMediaMaxBytes, t as DEFAULT_WHATSAPP_MEDIA_MAX_MB } from "./accounts-BPYgj8Fv.js";
3
3
  import { a as normalizeWhatsAppAllowFromEntries, c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, r as isWhatsAppUserTarget, 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 "./reaction-level-BqMOEBeq.js";
6
6
  import { c as assertWebChannel, d as markdownToWhatsApp, f as resolveJidToE164, l as isSelfChatMode, m as toWhatsappJidWithLid, n as normalizeE164, p as toWhatsappJid, r as resolveUserPath, u as jidToE164 } from "./text-runtime-Dk37KYHj.js";
7
- import "./send-CiXxYtQ_.js";
8
- import { t as whatsappPlugin } from "./channel-Ij-BWm7q.js";
9
- import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-base-BCEEnbqz.js";
7
+ import "./send-E_kMiuZP.js";
8
+ import { t as whatsappPlugin } from "./channel-BVMD1oZL.js";
9
+ import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-base-E84SMkd9.js";
10
10
  import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
11
- import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy, s as resolveWhatsAppGroupIntroHint } from "./setup-core-m8ba61Dp.js";
11
+ import { a as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupToolPolicy, s as resolveWhatsAppGroupIntroHint } from "./setup-core-Dm1hsI3r.js";
12
12
  import "./config-schema-CsNDlDpL.js";
13
- import { t as whatsappSetupPlugin } from "./channel.setup-CBHtRTDw.js";
13
+ import { t as whatsappSetupPlugin } from "./channel.setup-BDH3Mk5M.js";
14
14
  import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-HU41RHGI.js";
15
15
  import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-CfLFAK54.js";
16
- import { n as testing } from "./access-control-CBNRBEa4.js";
17
- import { p as extractText, t as createWebSendApi } from "./send-api-CcNZTwSs.js";
18
- import { r as waitForWaConnection, t as createWaSocket } from "./session-Bn5i1Fqp.js";
16
+ import { n as testing } from "./access-control-p_vcYDW7.js";
17
+ import { p as extractText, t as createWebSendApi } from "./send-api-CXPUXbUL.js";
18
+ import { r as waitForWaConnection, t as createWaSocket } from "./session-CPsgRMMa.js";
19
19
  import "openclaw/plugin-sdk/channel-actions";
20
20
  import "openclaw/plugin-sdk/account-resolution";
21
21
  import "openclaw/plugin-sdk/core";
@@ -1,4 +1,4 @@
1
- import { t as hasWebCredsSync } from "./creds-files-D9VwL4Az.js";
1
+ import { r as hasWebCredsSync } from "./creds-files-B1kSWtBg.js";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { resolveOAuthDir } from "openclaw/plugin-sdk/state-paths";
@@ -1,14 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { n as resolveWebCredsBackupPath, r as resolveWebCredsPath } from "./creds-files-D9VwL4Az.js";
2
+ import { a as readWebCredsJsonRawSync, c as statWebCredsFileSync, i as readWebCredsJsonRaw, o as resolveWebCredsBackupPath, s as resolveWebCredsPath, t as assertWebCredsPathRegularFileOrMissing } from "./creds-files-B1kSWtBg.js";
3
3
  import { r as resolveUserPath } from "./text-runtime-Dk37KYHj.js";
4
4
  import { c as resolveComparableIdentity } from "./identity-xoLLdqEv.js";
5
- import fs from "node:fs";
6
5
  import path from "node:path";
7
6
  import { resolveOAuthDir as resolveOAuthDir$1 } from "openclaw/plugin-sdk/state-paths";
7
+ import { replaceFileAtomic } from "openclaw/plugin-sdk/security-runtime";
8
8
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
9
9
  import { defaultRuntime, getChildLogger, info, success } from "openclaw/plugin-sdk/runtime-env";
10
- import { replaceFileAtomic } from "openclaw/plugin-sdk/security-runtime";
11
- import fs$1 from "node:fs/promises";
10
+ import fs from "node:fs/promises";
12
11
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
13
12
  //#region extensions/whatsapp/src/creds-persistence.ts
14
13
  const CREDS_FILE_MODE = 384;
@@ -18,15 +17,26 @@ async function stringifyCreds(creds) {
18
17
  const { BufferJSON } = await import("./session.runtime-C6uBkEaI.js").then((n) => n.a);
19
18
  return JSON.stringify(creds, BufferJSON.replacer);
20
19
  }
21
- async function writeCredsJsonAtomically(authDir, creds) {
20
+ async function writeWebCredsRawAtomically(params) {
21
+ await assertWebCredsPathRegularFileOrMissing(params.filePath);
22
22
  await replaceFileAtomic({
23
- filePath: resolveWebCredsPath(authDir),
24
- content: await stringifyCreds(creds),
23
+ filePath: params.filePath,
24
+ content: params.content,
25
25
  dirMode: 448,
26
26
  mode: CREDS_FILE_MODE,
27
- tempPrefix: ".creds",
27
+ tempPrefix: params.tempPrefix,
28
28
  syncTempFile: true,
29
- syncParentDir: true
29
+ syncParentDir: true,
30
+ beforeRename: async ({ filePath }) => {
31
+ await assertWebCredsPathRegularFileOrMissing(filePath);
32
+ }
33
+ });
34
+ }
35
+ async function writeCredsJsonAtomically(authDir, creds) {
36
+ await writeWebCredsRawAtomically({
37
+ filePath: resolveWebCredsPath(authDir),
38
+ content: await stringifyCreds(creds),
39
+ tempPrefix: ".creds"
30
40
  });
31
41
  }
32
42
  function enqueueCredsSave(authDir, saveCreds, onError) {
@@ -94,14 +104,7 @@ function resolveDefaultWebAuthDir() {
94
104
  }
95
105
  const WA_WEB_AUTH_DIR = resolveDefaultWebAuthDir();
96
106
  function readCredsJsonRaw(filePath) {
97
- try {
98
- if (!fs.existsSync(filePath)) return null;
99
- const stats = fs.statSync(filePath);
100
- if (!stats.isFile() || stats.size <= 1) return null;
101
- return fs.readFileSync(filePath, "utf-8");
102
- } catch {
103
- return null;
104
- }
107
+ return readWebCredsJsonRawSync(filePath);
105
108
  }
106
109
  async function waitForWebAuthBarrier(authDir, context) {
107
110
  const result = await waitForCredsSaveQueueWithTimeout(authDir);
@@ -116,6 +119,11 @@ async function restoreCredsFromBackupIfNeeded(authDir) {
116
119
  try {
117
120
  const credsPath = resolveWebCredsPath(authDir);
118
121
  const backupPath = resolveWebCredsBackupPath(authDir);
122
+ try {
123
+ await assertWebCredsPathRegularFileOrMissing(credsPath);
124
+ } catch {
125
+ return false;
126
+ }
119
127
  const raw = readCredsJsonRaw(credsPath);
120
128
  if (raw) {
121
129
  JSON.parse(raw);
@@ -123,13 +131,10 @@ async function restoreCredsFromBackupIfNeeded(authDir) {
123
131
  }
124
132
  const backupRaw = readCredsJsonRaw(backupPath);
125
133
  if (!backupRaw) return false;
126
- if (!(await fs$1.lstat(backupPath).catch(() => null))?.isFile()) return false;
127
134
  JSON.parse(backupRaw);
128
- await replaceFileAtomic({
135
+ await writeWebCredsRawAtomically({
129
136
  filePath: credsPath,
130
137
  content: backupRaw,
131
- dirMode: 448,
132
- mode: 384,
133
138
  tempPrefix: ".creds.restore"
134
139
  });
135
140
  logger.warn({ credsPath }, "restored corrupted WhatsApp creds.json from backup");
@@ -138,17 +143,9 @@ async function restoreCredsFromBackupIfNeeded(authDir) {
138
143
  return false;
139
144
  }
140
145
  async function webAuthExists(authDir = resolveDefaultWebAuthDir()) {
141
- const resolvedAuthDir = resolveUserPath(authDir);
142
- const credsPath = resolveWebCredsPath(resolvedAuthDir);
143
- try {
144
- await fs$1.access(resolvedAuthDir);
145
- } catch {
146
- return false;
147
- }
146
+ const raw = await readWebCredsJsonRaw(resolveWebCredsPath(resolveUserPath(authDir)));
147
+ if (!raw) return false;
148
148
  try {
149
- const stats = await fs$1.stat(credsPath);
150
- if (!stats.isFile() || stats.size <= 1) return false;
151
- const raw = await fs$1.readFile(credsPath, "utf-8");
152
149
  JSON.parse(raw);
153
150
  return true;
154
151
  } catch {
@@ -222,25 +219,25 @@ function isBaileysAuthFileName(name) {
222
219
  return /^(app-state-sync|session|sender-key|pre-key)-/.test(name);
223
220
  }
224
221
  async function clearBaileysAuthFiles(authDir) {
225
- const rootStats = await fs$1.lstat(authDir).catch(() => null);
222
+ const rootStats = await fs.lstat(authDir).catch(() => null);
226
223
  if (!rootStats?.isDirectory() || rootStats.isSymbolicLink()) return;
227
- const entries = await fs$1.readdir(authDir, { withFileTypes: true });
224
+ const entries = await fs.readdir(authDir, { withFileTypes: true });
228
225
  await Promise.all(entries.map(async (entry) => {
229
226
  if (!entry.isFile()) return;
230
227
  if (!isBaileysAuthFileName(entry.name)) return;
231
- await fs$1.rm(path.join(authDir, entry.name), { force: true });
228
+ await fs.rm(path.join(authDir, entry.name), { force: true });
232
229
  }));
233
230
  }
234
231
  async function shouldClearOnLogout(authDir, isLegacyAuthDir) {
235
232
  try {
236
- const stats = await fs$1.lstat(authDir);
233
+ const stats = await fs.lstat(authDir);
237
234
  if (!stats.isDirectory() || stats.isSymbolicLink()) return false;
238
- if (isLegacyAuthDir) return (await fs$1.readdir(authDir, { withFileTypes: true })).some((entry) => {
235
+ if (isLegacyAuthDir) return (await fs.readdir(authDir, { withFileTypes: true })).some((entry) => {
239
236
  if (!entry.isFile()) return false;
240
237
  return isBaileysAuthFileName(entry.name);
241
238
  });
242
- if ((await fs$1.lstat(resolveWebCredsPath(authDir)).catch(() => null))?.isFile()) return true;
243
- return (await fs$1.lstat(resolveWebCredsBackupPath(authDir)).catch(() => null))?.isFile() === true;
239
+ if ((await fs.lstat(resolveWebCredsPath(authDir)).catch(() => null))?.isFile()) return true;
240
+ return (await fs.lstat(resolveWebCredsBackupPath(authDir)).catch(() => null))?.isFile() === true;
244
241
  } catch (error) {
245
242
  const codeValue = error && typeof error === "object" && "code" in error ? error.code : void 0;
246
243
  return (typeof codeValue === "string" ? codeValue : "") !== "ENOENT";
@@ -255,7 +252,7 @@ async function pathHasSymlinkComponent(baseDir, targetPath) {
255
252
  let currentPath = baseDir;
256
253
  for (const segment of relativePath.split(path.sep)) {
257
254
  currentPath = path.join(currentPath, segment);
258
- const stats = await fs$1.lstat(currentPath).catch(() => null);
255
+ const stats = await fs.lstat(currentPath).catch(() => null);
259
256
  if (!stats || stats.isSymbolicLink()) return true;
260
257
  }
261
258
  return false;
@@ -264,14 +261,14 @@ async function isLegacyWebAuthDir(authDir) {
264
261
  const legacyAuthDir = path.resolve(resolveOAuthDir$1());
265
262
  const resolvedAuthDir = path.resolve(authDir);
266
263
  if (resolvedAuthDir !== legacyAuthDir) return false;
267
- const stats = await fs$1.lstat(resolvedAuthDir).catch(() => null);
264
+ const stats = await fs.lstat(resolvedAuthDir).catch(() => null);
268
265
  return stats?.isDirectory() === true && !stats.isSymbolicLink();
269
266
  }
270
267
  async function classifyWebAuthDirOwnership(authDir) {
271
268
  const whatsappAuthBase = path.resolve(resolveOAuthDir$1(), "whatsapp");
272
269
  const resolvedAuthDir = path.resolve(authDir);
273
270
  if (!isPathInsideDirectory(whatsappAuthBase, resolvedAuthDir)) return { kind: "external" };
274
- const [baseRealPath, authDirRealPath] = await Promise.all([fs$1.realpath(whatsappAuthBase).catch(() => null), fs$1.realpath(resolvedAuthDir).catch(() => null)]);
271
+ const [baseRealPath, authDirRealPath] = await Promise.all([fs.realpath(whatsappAuthBase).catch(() => null), fs.realpath(resolvedAuthDir).catch(() => null)]);
275
272
  if (!baseRealPath || !authDirRealPath) return { kind: "unsafe-owned" };
276
273
  if (!isPathInsideDirectory(baseRealPath, authDirRealPath)) return { kind: "unsafe-owned" };
277
274
  if (await pathHasSymlinkComponent(whatsappAuthBase, resolvedAuthDir)) return { kind: "unsafe-owned" };
@@ -296,7 +293,7 @@ async function logoutWeb(params) {
296
293
  await clearBaileysAuthFiles(resolvedAuthDir);
297
294
  } else {
298
295
  const ownership = await classifyWebAuthDirOwnership(resolvedAuthDir);
299
- if (ownership.kind === "owned") await fs$1.rm(ownership.authDir, {
296
+ if (ownership.kind === "owned") await fs.rm(ownership.authDir, {
300
297
  recursive: true,
301
298
  force: true
302
299
  });
@@ -313,9 +310,8 @@ async function logoutWeb(params) {
313
310
  }
314
311
  function readWebSelfId(authDir = resolveDefaultWebAuthDir()) {
315
312
  try {
316
- const credsPath = resolveWebCredsPath(resolveUserPath(authDir));
317
- if (!fs.existsSync(credsPath)) return emptyWebSelfId();
318
- const raw = fs.readFileSync(credsPath, "utf-8");
313
+ const raw = readCredsJsonRaw(resolveWebCredsPath(resolveUserPath(authDir)));
314
+ if (!raw) return emptyWebSelfId();
319
315
  const parsed = JSON.parse(raw);
320
316
  const identity = resolveComparableIdentity({
321
317
  jid: parsed?.me?.id ?? null,
@@ -332,19 +328,18 @@ function readWebSelfId(authDir = resolveDefaultWebAuthDir()) {
332
328
  }
333
329
  async function readWebSelfIdentity(authDir = resolveDefaultWebAuthDir(), fallback) {
334
330
  const resolvedAuthDir = resolveUserPath(authDir);
335
- try {
336
- const raw = await fs$1.readFile(resolveWebCredsPath(resolvedAuthDir), "utf-8");
331
+ const raw = await readWebCredsJsonRaw(resolveWebCredsPath(resolvedAuthDir));
332
+ if (raw) try {
337
333
  const parsed = JSON.parse(raw);
338
334
  return resolveComparableIdentity({
339
335
  jid: parsed?.me?.id ?? null,
340
336
  lid: parsed?.me?.lid ?? null
341
337
  }, resolvedAuthDir);
342
- } catch {
343
- return resolveComparableIdentity({
344
- jid: fallback?.id ?? null,
345
- lid: fallback?.lid ?? null
346
- }, resolvedAuthDir);
347
- }
338
+ } catch {}
339
+ return resolveComparableIdentity({
340
+ jid: fallback?.id ?? null,
341
+ lid: fallback?.lid ?? null
342
+ }, resolvedAuthDir);
348
343
  }
349
344
  async function readWebSelfIdentityForDecision(authDir = resolveDefaultWebAuthDir(), fallback) {
350
345
  const resolvedAuthDir = resolveUserPath(authDir);
@@ -359,12 +354,8 @@ async function readWebSelfIdentityForDecision(authDir = resolveDefaultWebAuthDir
359
354
  * Helpful for heartbeats/observability to spot stale credentials.
360
355
  */
361
356
  function getWebAuthAgeMs(authDir = resolveDefaultWebAuthDir()) {
362
- try {
363
- const stats = fs.statSync(resolveWebCredsPath(resolveUserPath(authDir)));
364
- return Date.now() - stats.mtimeMs;
365
- } catch {
366
- return null;
367
- }
357
+ const stats = statWebCredsFileSync(resolveWebCredsPath(resolveUserPath(authDir)));
358
+ return stats ? Math.max(0, Date.now() - stats.mtimeMs) : null;
368
359
  }
369
360
  function logWebSelfId(authDir = resolveDefaultWebAuthDir(), runtime = defaultRuntime, includeChannelPrefix = false) {
370
361
  const { e164, jid, lid } = readWebSelfId(authDir);
@@ -381,4 +372,4 @@ async function pickWebChannel(pref, authDir = resolveDefaultWebAuthDir()) {
381
372
  return choice;
382
373
  }
383
374
  //#endregion
384
- export { waitForCredsSaveQueue as C, enqueueCredsSave as S, writeCredsJsonAtomically as T, readWebSelfIdentity as _, formatWhatsAppWebAuthStatusState as a, restoreCredsFromBackupIfNeeded as b, logoutWeb as c, readWebAuthExistsBestEffort as d, readWebAuthExistsForDecision as f, readWebSelfId as g, readWebAuthState as h, auth_store_exports as i, pickWebChannel as l, readWebAuthSnapshotBestEffort as m, WHATSAPP_AUTH_UNSTABLE_CODE as n, getWebAuthAgeMs as o, readWebAuthSnapshot as p, WhatsAppAuthUnstableError as r, logWebSelfId as s, WA_WEB_AUTH_DIR as t, readCredsJsonRaw as u, readWebSelfIdentityForDecision as v, waitForCredsSaveQueueWithTimeout as w, webAuthExists as x, resolveDefaultWebAuthDir as y };
375
+ export { waitForCredsSaveQueue as C, writeWebCredsRawAtomically as E, enqueueCredsSave as S, writeCredsJsonAtomically as T, readWebSelfIdentity as _, formatWhatsAppWebAuthStatusState as a, restoreCredsFromBackupIfNeeded as b, logoutWeb as c, readWebAuthExistsBestEffort as d, readWebAuthExistsForDecision as f, readWebSelfId as g, readWebAuthState as h, auth_store_exports as i, pickWebChannel as l, readWebAuthSnapshotBestEffort as m, WHATSAPP_AUTH_UNSTABLE_CODE as n, getWebAuthAgeMs as o, readWebAuthSnapshot as p, WhatsAppAuthUnstableError as r, logWebSelfId as s, WA_WEB_AUTH_DIR as t, readCredsJsonRaw as u, readWebSelfIdentityForDecision as v, waitForCredsSaveQueueWithTimeout as w, webAuthExists as x, resolveDefaultWebAuthDir as y };
@@ -1,17 +1,17 @@
1
1
  import { t as listAccountIds } from "./account-ids-CB5SOWjc.js";
2
- import { a as resolveWhatsAppAccount } from "./accounts-DskwwYAM.js";
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-Dk324Pce.js";
6
+ import { r as normalizeWhatsAppPayloadTextPreservingIndentation } from "./outbound-media-contract-ioTkt8tn.js";
7
7
  import "./normalize-Bxwqo-bW.js";
8
- import { i as sendTypingWhatsApp, n as sendPollWhatsApp, t as sendMessageWhatsApp } from "./send-CiXxYtQ_.js";
9
- import { t as createWhatsAppLoginTool } from "./agent-tools-login-EtLHKziO.js";
10
- import { t as createWhatsAppOutboundBase } from "./outbound-base-BCEEnbqz.js";
8
+ import { i as sendTypingWhatsApp, n as sendPollWhatsApp, t as sendMessageWhatsApp } from "./send-E_kMiuZP.js";
9
+ import { t as createWhatsAppLoginTool } from "./agent-tools-login-BDzvb3ee.js";
10
+ import { t as createWhatsAppOutboundBase } from "./outbound-base-E84SMkd9.js";
11
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-m8ba61Dp.js";
14
- import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-C-5icsdY.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-Dm1hsI3r.js";
14
+ import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-GTQvJznL.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
17
  import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord } from "openclaw/plugin-sdk/status-helpers";
@@ -323,7 +323,7 @@ function collectWhatsAppStatusIssues(accounts) {
323
323
  //#endregion
324
324
  //#region extensions/whatsapp/src/channel.ts
325
325
  const loadWhatsAppDirectoryConfig = createLazyRuntimeModule(() => import("./directory-config-CfLFAK54.js").then((n) => n.t));
326
- const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-DEUfqgMx.js"));
326
+ const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-CHdR3gbn.js"));
327
327
  function parseWhatsAppExplicitTarget(raw) {
328
328
  const normalized = normalizeWhatsAppTarget(raw);
329
329
  if (!normalized) return null;
@@ -1,2 +1,2 @@
1
- import { t as whatsappPlugin } from "./channel-Ij-BWm7q.js";
1
+ import { t as whatsappPlugin } from "./channel-BVMD1oZL.js";
2
2
  export { whatsappPlugin };
@@ -1,8 +1,8 @@
1
- import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-DskwwYAM.js";
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-Up8OrLd_.js";
3
+ import { r as resolveAuthorizedWhatsAppOutboundTarget, t as handleWhatsAppAction } from "./action-runtime-D4UqEXqf.js";
4
4
  import "./normalize-Bxwqo-bW.js";
5
- import { t as sendMessageWhatsApp } from "./send-CiXxYtQ_.js";
5
+ import { t as sendMessageWhatsApp } from "./send-E_kMiuZP.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-C-5icsdY.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";
3
3
  import { t as getActiveWebListener$1 } from "./active-listener-B4SDebQ6.js";
4
- import { t as monitorWebChannel$1 } from "./monitor-DYvWelW5.js";
5
- import { t as loginWeb$1 } from "./login-CGOtBPVS.js";
6
- import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-D4sy0_LW.js";
4
+ import { t as monitorWebChannel$1 } from "./monitor-Dw2i5QSQ.js";
5
+ import { t as loginWeb$1 } from "./login-nJwaNuC-.js";
6
+ import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-DqY0LqAY.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-m8ba61Dp.js";
1
+ import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, s as resolveWhatsAppGroupIntroHint, t as whatsappSetupAdapter } from "./setup-core-Dm1hsI3r.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-C-5icsdY.js").then((n) => n.i);
5
+ const { readWebAuthState } = await import("./auth-store-GTQvJznL.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-C-5icsdY.js";
4
- import { r as waitForWaConnection, t as createWaSocket } from "./session-Bn5i1Fqp.js";
3
+ import { c as logoutWeb } from "./auth-store-GTQvJznL.js";
4
+ import { r as waitForWaConnection, t as createWaSocket } from "./session-CPsgRMMa.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";
@@ -5,7 +5,7 @@ import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecret
5
5
  import { r as isLegacyGroupSessionKey$1, t as canonicalizeLegacySessionKey$1 } from "./session-contract-DMTm6Q_L.js";
6
6
  import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-CfLFAK54.js";
7
7
  import { t as resolveWhatsAppRuntimeGroupPolicy$1 } from "./runtime-group-policy-DeSRFXEV.js";
8
- import { n as testing } from "./access-control-CBNRBEa4.js";
8
+ import { n as testing } from "./access-control-p_vcYDW7.js";
9
9
  //#region extensions/whatsapp/contract-api.ts
10
10
  const canonicalizeLegacySessionKey = canonicalizeLegacySessionKey$1;
11
11
  const isLegacyGroupSessionKey = isLegacyGroupSessionKey$1;
@@ -0,0 +1,79 @@
1
+ import path from "node:path";
2
+ import { assertNoSymlinkParents, assertNoSymlinkParentsSync, readRegularFile, readRegularFileSync, statRegularFile, statRegularFileSync } from "openclaw/plugin-sdk/security-runtime";
3
+ //#region extensions/whatsapp/src/creds-files.ts
4
+ function resolveWebCredsPath(authDir) {
5
+ return path.join(authDir, "creds.json");
6
+ }
7
+ function resolveWebCredsBackupPath(authDir) {
8
+ return path.join(authDir, "creds.json.bak");
9
+ }
10
+ function resolveWebCredsParentCheck(filePath) {
11
+ const dir = path.resolve(path.dirname(filePath));
12
+ return {
13
+ rootDir: path.parse(dir).root,
14
+ targetPath: dir,
15
+ allowMissing: true,
16
+ allowRootChildSymlink: true,
17
+ requireDirectories: true,
18
+ messagePrefix: "WhatsApp credential file path"
19
+ };
20
+ }
21
+ async function assertWebCredsParentPathSafe(filePath) {
22
+ await assertNoSymlinkParents(resolveWebCredsParentCheck(filePath));
23
+ }
24
+ function assertWebCredsParentPathSafeSync(filePath) {
25
+ assertNoSymlinkParentsSync(resolveWebCredsParentCheck(filePath));
26
+ }
27
+ async function assertWebCredsPathRegularFileOrMissing(filePath) {
28
+ try {
29
+ await assertWebCredsParentPathSafe(filePath);
30
+ await statRegularFile(filePath);
31
+ } catch (error) {
32
+ throw new Error(`WhatsApp credential file path is unsafe; creds.json must be a regular file or missing: ${filePath}`, { cause: error });
33
+ }
34
+ }
35
+ function readWebCredsJsonRawSync(filePath) {
36
+ try {
37
+ assertWebCredsParentPathSafeSync(filePath);
38
+ const { buffer, stat } = readRegularFileSync({ filePath });
39
+ return stat.size > 1 ? buffer.toString("utf-8") : null;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+ async function readWebCredsJsonRaw(filePath) {
45
+ try {
46
+ await assertWebCredsParentPathSafe(filePath);
47
+ const { buffer, stat } = await readRegularFile({ filePath });
48
+ return stat.size > 1 ? buffer.toString("utf-8") : null;
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+ function statWebCredsFileSync(filePath) {
54
+ try {
55
+ assertWebCredsParentPathSafeSync(filePath);
56
+ const result = statRegularFileSync(filePath);
57
+ if (result.missing || result.stat.size <= 1) return null;
58
+ return {
59
+ mtimeMs: result.stat.mtimeMs,
60
+ size: result.stat.size
61
+ };
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+ function hasWebCredsRegularFileSync(authDir) {
67
+ try {
68
+ const credsPath = resolveWebCredsPath(authDir);
69
+ assertWebCredsParentPathSafeSync(credsPath);
70
+ return !statRegularFileSync(credsPath).missing;
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+ function hasWebCredsSync(authDir) {
76
+ return statWebCredsFileSync(resolveWebCredsPath(authDir)) !== null;
77
+ }
78
+ //#endregion
79
+ export { readWebCredsJsonRawSync as a, statWebCredsFileSync as c, readWebCredsJsonRaw as i, hasWebCredsRegularFileSync as n, resolveWebCredsBackupPath as o, hasWebCredsSync as r, resolveWebCredsPath as s, assertWebCredsPathRegularFileOrMissing as t };
@@ -1,5 +1,5 @@
1
1
  import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
2
- import { t as createWhatsAppLoginTool } from "./agent-tools-login-EtLHKziO.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-C-5icsdY.js";
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";
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
- import { a as resolveWhatsAppAccount } from "./accounts-DskwwYAM.js";
3
- import { b as restoreCredsFromBackupIfNeeded } from "./auth-store-C-5icsdY.js";
4
- import { a as renderQrTerminal, i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-Bn5i1Fqp.js";
5
- import { a as closeWaSocketSoon, o as waitForWhatsAppLoginResult } from "./connection-controller-CPWZZXwV.js";
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";
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
- import { a as resolveWhatsAppAccount } from "./accounts-DskwwYAM.js";
2
- import { f as readWebAuthExistsForDecision, g as readWebSelfId, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-C-5icsdY.js";
3
- import { i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-Bn5i1Fqp.js";
4
- import { i as closeWaSocket, o as waitForWhatsAppLoginResult, t as WHATSAPP_LOGGED_OUT_QR_MESSAGE } from "./connection-controller-CPWZZXwV.js";
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";
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-BYNpc3IS.js");
4
+ loginQrModulePromise ??= import("./login-qr-l4UaR8Dj.js");
5
5
  return loginQrModulePromise;
6
6
  }
7
7
  async function startWebLoginWithQr(...args) {
@@ -1,26 +1,26 @@
1
- import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-DskwwYAM.js";
1
+ import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-BPYgj8Fv.js";
2
2
  import { t as isWhatsAppGroupJid } from "./normalize-target-bVWjgftN.js";
3
3
  import { t as resolveWhatsAppReactionLevel } from "./reaction-level-BqMOEBeq.js";
4
- import { i as prepareWhatsAppOutboundMedia, o as sendWhatsAppOutboundWithRetry, r as normalizeWhatsAppPayloadTextPreservingIndentation, t as normalizeWhatsAppOutboundPayload } from "./outbound-media-contract-Dk324Pce.js";
4
+ import { i as prepareWhatsAppOutboundMedia, o as sendWhatsAppOutboundWithRetry, r as normalizeWhatsAppPayloadTextPreservingIndentation, t as normalizeWhatsAppOutboundPayload } from "./outbound-media-contract-ioTkt8tn.js";
5
5
  import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
6
6
  import { d as markdownToWhatsApp, f as resolveJidToE164, l as isSelfChatMode, n as normalizeE164, t as convertMarkdownTables$1, u as jidToE164 } from "./text-runtime-Dk37KYHj.js";
7
- import { r as sendReactionWhatsApp } from "./send-CiXxYtQ_.js";
7
+ import { r as sendReactionWhatsApp } from "./send-E_kMiuZP.js";
8
8
  import { n as cacheInboundMessageMeta, r as lookupInboundMessageMeta, t as buildQuotedMessageOptions } from "./quoted-message-CveINB35.js";
9
- import { c as logoutWeb, g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-C-5icsdY.js";
9
+ import { c as logoutWeb, g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-GTQvJznL.js";
10
10
  import { a as getSelfIdentity, c as resolveComparableIdentity, i as getReplyContext, n as getMentionIdentities, o as getSenderIdentity, r as getPrimaryIdentityId, s as identitiesOverlap, t as getComparableIdentityValues } from "./identity-xoLLdqEv.js";
11
- import { i as resolveWhatsAppInboundPolicy, r as resolveWhatsAppCommandAuthorized, t as checkInboundAccessControl } from "./access-control-CBNRBEa4.js";
12
- import { a as mayContainWhatsAppOutboundMention, c as extractContactContext, d as extractMediaPlaceholder, f as extractMentionedJids, i as addWhatsAppOutboundMentionsToContent, l as extractContextInfo, m as hasInboundUserContent, n as listWhatsAppSendResultMessageIds, o as resolveWhatsAppOutboundMentions, p as extractText, r as normalizeWhatsAppSendResult, s as describeReplyContext, t as createWebSendApi, u as extractLocationData } from "./send-api-CcNZTwSs.js";
13
- import { i as resolveWhatsAppSocketTiming, r as waitForWaConnection, t as createWaSocket } from "./session-Bn5i1Fqp.js";
14
- import { c as computeBackoff, d as resolveReconnectPolicy, f as sleepWithAbort, l as newConnectionId, n as WHATSAPP_WATCHDOG_TIMEOUT_ERROR, r as WhatsAppConnectionController, s as DEFAULT_RECONNECT_POLICY, u as resolveHeartbeatSeconds } from "./connection-controller-CPWZZXwV.js";
11
+ import { i as resolveWhatsAppInboundPolicy, r as resolveWhatsAppCommandAuthorized, t as checkInboundAccessControl } from "./access-control-p_vcYDW7.js";
12
+ import { a as mayContainWhatsAppOutboundMention, c as extractContactContext, d as extractMediaPlaceholder, f as extractMentionedJids, i as addWhatsAppOutboundMentionsToContent, l as extractContextInfo, m as hasInboundUserContent, n as listWhatsAppSendResultMessageIds, o as resolveWhatsAppOutboundMentions, p as extractText, r as normalizeWhatsAppSendResult, s as describeReplyContext, t as createWebSendApi, u as extractLocationData } from "./send-api-CXPUXbUL.js";
13
+ import { i as resolveWhatsAppSocketTiming, r as waitForWaConnection, t as createWaSocket } from "./session-CPsgRMMa.js";
14
+ import { c as computeBackoff, d as resolveReconnectPolicy, f as sleepWithAbort, l as newConnectionId, n as WHATSAPP_WATCHDOG_TIMEOUT_ERROR, r as WhatsAppConnectionController, s as DEFAULT_RECONNECT_POLICY, u as resolveHeartbeatSeconds } from "./connection-controller-9TXWZRhx.js";
15
15
  import { resolveAccountEntry } from "openclaw/plugin-sdk/account-core";
16
16
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
17
+ import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
17
18
  import { DEFAULT_TIMING, createAckReactionHandle, createStatusReactionController, logAckFailure, removeAckReactionHandleAfterReply, shouldAckReactionForWhatsApp } from "openclaw/plugin-sdk/channel-feedback";
18
19
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
19
20
  import { getChildLogger } from "openclaw/plugin-sdk/logging-core";
20
21
  import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
21
22
  import { createSubsystemLogger, defaultRuntime, formatDurationPrecise, getChildLogger as getChildLogger$1, logVerbose, logVerbose as logVerbose$1, registerUnhandledRejectionHandler, shouldLogVerbose, shouldLogVerbose as shouldLogVerbose$1, warn } from "openclaw/plugin-sdk/runtime-env";
22
23
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
23
- import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
24
24
  import { LocalMediaAccessError, getDefaultLocalRoots, loadWebMedia as loadWebMedia$1, loadWebMediaRaw, optimizeImageToJpeg, optimizeImageToPng } from "openclaw/plugin-sdk/web-media";
25
25
  import { createChannelMessageReplyPipeline, createMessageReceiptFromOutboundResults, deliverInboundReplyWithMessageSendContext, resolveChannelMessageSourceReplyDeliveryMode } from "openclaw/plugin-sdk/channel-message";
26
26
  import { chunkMarkdownTextWithMode } from "openclaw/plugin-sdk/reply-chunking";
@@ -3074,10 +3074,7 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
3074
3074
  channel: "whatsapp",
3075
3075
  accountId: account.accountId
3076
3076
  });
3077
- enqueueSystemEvent(`WhatsApp gateway connected${selfE164 ? ` as ${selfE164}` : ""}.`, {
3078
- sessionKey: connectRoute.sessionKey,
3079
- trusted: true
3080
- });
3077
+ enqueueSystemEvent(`WhatsApp gateway connected${selfE164 ? ` as ${selfE164}` : ""}.`, { sessionKey: connectRoute.sessionKey });
3081
3078
  const normalizedAccountId = normalizeReconnectAccountId(account.accountId);
3082
3079
  drainPendingDeliveries({
3083
3080
  drainKey: `whatsapp:${normalizedAccountId}`,
@@ -3145,10 +3142,7 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
3145
3142
  reconnectAttempts: decision.reconnectAttempts,
3146
3143
  error: decision.normalized.errorText
3147
3144
  }, "web reconnect: connection closed");
3148
- enqueueSystemEvent(`WhatsApp gateway disconnected (status ${decision.normalized.statusLabel})`, {
3149
- sessionKey: connectRoute.sessionKey,
3150
- trusted: true
3151
- });
3145
+ enqueueSystemEvent(`WhatsApp gateway disconnected (status ${decision.normalized.statusLabel})`, { sessionKey: connectRoute.sessionKey });
3152
3146
  if (decision.action === "stop") {
3153
3147
  await controller.closeCurrentConnection();
3154
3148
  statusController.noteClose({
@@ -1,12 +1,12 @@
1
1
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CV-iBmSG.js";
2
- import { n as normalizeWhatsAppPayloadText } from "./outbound-media-contract-Dk324Pce.js";
3
- import { t as createWhatsAppOutboundBase } from "./outbound-base-BCEEnbqz.js";
2
+ import { n as normalizeWhatsAppPayloadText } from "./outbound-media-contract-ioTkt8tn.js";
3
+ import { t as createWhatsAppOutboundBase } from "./outbound-base-E84SMkd9.js";
4
4
  import { shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
5
5
  import { chunkText } from "openclaw/plugin-sdk/reply-chunking";
6
6
  //#region extensions/whatsapp/src/outbound-adapter.ts
7
7
  let whatsAppSendModulePromise;
8
8
  function loadWhatsAppSendModule() {
9
- whatsAppSendModulePromise ??= import("./send-CiXxYtQ_.js").then((n) => n.a);
9
+ whatsAppSendModulePromise ??= import("./send-E_kMiuZP.js").then((n) => n.a);
10
10
  return whatsAppSendModulePromise;
11
11
  }
12
12
  function normalizeOutboundText(text) {
@@ -1,4 +1,4 @@
1
- import { n as normalizeWhatsAppPayloadText, t as normalizeWhatsAppOutboundPayload } from "./outbound-media-contract-Dk324Pce.js";
1
+ import { n as normalizeWhatsAppPayloadText, t as normalizeWhatsAppOutboundPayload } from "./outbound-media-contract-ioTkt8tn.js";
2
2
  import { p as toWhatsappJid } from "./text-runtime-Dk37KYHj.js";
3
3
  import { i as lookupInboundMessageMetaForTarget } from "./quoted-message-CveINB35.js";
4
4
  import { DEFAULT_ACCOUNT_ID, listCombinedAccountIds, normalizeOptionalAccountId, resolveListedDefaultAccountId } from "openclaw/plugin-sdk/account-core";
@@ -1,2 +1,2 @@
1
- import { t as whatsappOutbound } from "./outbound-adapter-AQXm0jeQ.js";
1
+ import { t as whatsappOutbound } from "./outbound-adapter-ltiZkW9L.js";
2
2
  export { whatsappOutbound };
@@ -1,16 +1,16 @@
1
- import { n as resolveWebCredsBackupPath, r as resolveWebCredsPath, t as hasWebCredsSync } from "./creds-files-D9VwL4Az.js";
2
- import { n as whatsAppActionRuntime, t as handleWhatsAppAction } from "./action-runtime-Up8OrLd_.js";
1
+ import { o as resolveWebCredsBackupPath, r as hasWebCredsSync, s as resolveWebCredsPath } from "./creds-files-B1kSWtBg.js";
2
+ import { n as whatsAppActionRuntime, t as handleWhatsAppAction } from "./action-runtime-D4UqEXqf.js";
3
3
  import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
4
- import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-CiXxYtQ_.js";
4
+ import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-E_kMiuZP.js";
5
5
  import { startWebLoginWithQr, waitForWebLogin } from "./login-qr-runtime.js";
6
- import { t as createWhatsAppLoginTool } from "./agent-tools-login-EtLHKziO.js";
6
+ import { t as createWhatsAppLoginTool } from "./agent-tools-login-BDzvb3ee.js";
7
7
  import { n as setWhatsAppRuntime } from "./runtime-CboC4QhQ.js";
8
- import { C as waitForCredsSaveQueue, T as writeCredsJsonAtomically, _ as readWebSelfIdentity, a as formatWhatsAppWebAuthStatusState, b as restoreCredsFromBackupIfNeeded, c as logoutWeb, d as readWebAuthExistsBestEffort, f as readWebAuthExistsForDecision, g as readWebSelfId, h as readWebAuthState, l as pickWebChannel, m as readWebAuthSnapshotBestEffort, n as WHATSAPP_AUTH_UNSTABLE_CODE, o as getWebAuthAgeMs, p as readWebAuthSnapshot, r as WhatsAppAuthUnstableError, s as logWebSelfId, t as WA_WEB_AUTH_DIR, u as readCredsJsonRaw, v as readWebSelfIdentityForDecision, w as waitForCredsSaveQueueWithTimeout, x as webAuthExists, y as resolveDefaultWebAuthDir } from "./auth-store-C-5icsdY.js";
8
+ import { C as waitForCredsSaveQueue, T as writeCredsJsonAtomically, _ as readWebSelfIdentity, a as formatWhatsAppWebAuthStatusState, b as restoreCredsFromBackupIfNeeded, c as logoutWeb, d as readWebAuthExistsBestEffort, f as readWebAuthExistsForDecision, g as readWebSelfId, h as readWebAuthState, l as pickWebChannel, m as readWebAuthSnapshotBestEffort, n as WHATSAPP_AUTH_UNSTABLE_CODE, o as getWebAuthAgeMs, p as readWebAuthSnapshot, r as WhatsAppAuthUnstableError, s as logWebSelfId, t as WA_WEB_AUTH_DIR, u as readCredsJsonRaw, v as readWebSelfIdentityForDecision, w as waitForCredsSaveQueueWithTimeout, x as webAuthExists, y as resolveDefaultWebAuthDir } from "./auth-store-GTQvJznL.js";
9
9
  import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-HU41RHGI.js";
10
- import { c as extractContactContext, d as extractMediaPlaceholder, p as extractText, u as extractLocationData } from "./send-api-CcNZTwSs.js";
11
- import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-Bn5i1Fqp.js";
10
+ import { c as extractContactContext, d as extractMediaPlaceholder, p as extractText, u as extractLocationData } from "./send-api-CXPUXbUL.js";
11
+ import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-CPsgRMMa.js";
12
12
  import { n as resolveWebAccountId, t as getActiveWebListener } from "./active-listener-B4SDebQ6.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-DYvWelW5.js";
14
- import { t as loginWeb } from "./login-CGOtBPVS.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-Dw2i5QSQ.js";
14
+ import { t as loginWeb } from "./login-nJwaNuC-.js";
15
15
  import { HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, SILENT_REPLY_TOKEN, stripHeartbeatToken } from "openclaw/plugin-sdk/reply-runtime";
16
16
  export { DEFAULT_WEB_MEDIA_BYTES, HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, LocalMediaAccessError, SILENT_REPLY_TOKEN, WA_WEB_AUTH_DIR, WHATSAPP_AUTH_UNSTABLE_CODE, WhatsAppAuthUnstableError, createWaSocket, createWhatsAppLoginTool, extractContactContext, extractLocationData, extractMediaPlaceholder, extractText, formatError, formatWhatsAppWebAuthStatusState, getActiveWebListener, getDefaultLocalRoots, getStatusCode, getWebAuthAgeMs, handleWhatsAppAction, hasWebCredsSync, loadWebMedia, loadWebMediaRaw, logWebSelfId, loginWeb, logoutWeb, monitorWebChannel, monitorWebInbox, newConnectionId, optimizeImageToJpeg, optimizeImageToPng, pickWebChannel, readCredsJsonRaw, readWebAuthExistsBestEffort, readWebAuthExistsForDecision, readWebAuthSnapshot, readWebAuthSnapshotBestEffort, readWebAuthState, readWebSelfId, readWebSelfIdentity, readWebSelfIdentityForDecision, resetWebInboundDedupe, resolveDefaultWebAuthDir, resolveWebAccountId, resolveWebCredsBackupPath, resolveWebCredsPath, restoreCredsFromBackupIfNeeded, sendMessageWhatsApp, sendPollWhatsApp, sendReactionWhatsApp, sendTypingWhatsApp, setWhatsAppRuntime, startWebLoginWithQr, stripHeartbeatToken, waitForCredsSaveQueue, waitForCredsSaveQueueWithTimeout, waitForWaConnection, waitForWebLogin, webAuthExists, whatsAppActionRuntime, writeCredsJsonAtomically };
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
3
- import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-DskwwYAM.js";
3
+ import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-BPYgj8Fv.js";
4
4
  import { n as isWhatsAppNewsletterJid } from "./normalize-target-bVWjgftN.js";
5
5
  import { t as getRegisteredWhatsAppConnectionController } from "./connection-controller-registry-TSX_udJp.js";
6
- import { a as resolveWhatsAppOutboundMediaUrls, i as prepareWhatsAppOutboundMedia, n as normalizeWhatsAppPayloadText, s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-Dk324Pce.js";
6
+ import { a as resolveWhatsAppOutboundMediaUrls, i as prepareWhatsAppOutboundMedia, n as normalizeWhatsAppPayloadText, s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-ioTkt8tn.js";
7
7
  import "./normalize-Bxwqo-bW.js";
8
8
  import { d as markdownToWhatsApp, p as toWhatsappJid } from "./text-runtime-Dk37KYHj.js";
9
9
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
@@ -1,5 +1,5 @@
1
1
  import { n as isWhatsAppNewsletterJid } from "./normalize-target-bVWjgftN.js";
2
- import { s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-Dk324Pce.js";
2
+ import { s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-ioTkt8tn.js";
3
3
  import "./normalize-Bxwqo-bW.js";
4
4
  import { m as toWhatsappJidWithLid, p as toWhatsappJid, u as jidToE164 } from "./text-runtime-Dk37KYHj.js";
5
5
  import { t as buildQuotedMessageOptions } from "./quoted-message-CveINB35.js";
@@ -1,8 +1,7 @@
1
- import { n as resolveWebCredsBackupPath, r as resolveWebCredsPath } from "./creds-files-D9VwL4Az.js";
1
+ import { o as resolveWebCredsBackupPath, s as resolveWebCredsPath, t as assertWebCredsPathRegularFileOrMissing } from "./creds-files-B1kSWtBg.js";
2
2
  import { n as getStatusCode } from "./session-errors-BAj9D2La.js";
3
- import { S as enqueueCredsSave, T as writeCredsJsonAtomically, b as restoreCredsFromBackupIfNeeded, u as readCredsJsonRaw, w as waitForCredsSaveQueueWithTimeout, y as resolveDefaultWebAuthDir } from "./auth-store-C-5icsdY.js";
3
+ import { E as writeWebCredsRawAtomically, S as enqueueCredsSave, T as writeCredsJsonAtomically, b as restoreCredsFromBackupIfNeeded, u as readCredsJsonRaw, w as waitForCredsSaveQueueWithTimeout, y as resolveDefaultWebAuthDir } from "./auth-store-GTQvJznL.js";
4
4
  import { i as makeWASocket, n as fetchLatestBaileysVersion, o as useMultiFileAuthState, r as makeCacheableSignalKeyStore, t as DisconnectReason } from "./session.runtime-C6uBkEaI.js";
5
- import fs from "node:fs";
6
5
  import { VERSION, formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
7
6
  import { danger, getChildLogger, success, toPinoLikeLogger } from "openclaw/plugin-sdk/runtime-env";
8
7
  import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
@@ -32,6 +31,9 @@ function resolveWhatsAppSocketTiming(cfg, overrides) {
32
31
  const LOGGED_OUT_STATUS = DisconnectReason?.loggedOut ?? 401;
33
32
  const WHATSAPP_WEBSOCKET_PROXY_TARGET = "https://mmg.whatsapp.net/";
34
33
  const CREDS_FLUSH_TIMEOUT_MESSAGE = "Queued WhatsApp creds save did not finish before auth bootstrap; skipping repair and continuing with primary creds.";
34
+ async function rejectUnsafeWebCredsPath(authDir) {
35
+ await assertWebCredsPathRegularFileOrMissing(resolveWebCredsPath(authDir));
36
+ }
35
37
  function enqueueSaveCreds(authDir, saveCreds, logger) {
36
38
  enqueueCredsSave(authDir, () => safeSaveCreds(authDir, saveCreds, logger), (err) => {
37
39
  logger.warn({ error: String(err) }, "WhatsApp creds save queue error");
@@ -44,10 +46,11 @@ async function safeSaveCreds(authDir, saveCreds, logger) {
44
46
  const raw = readCredsJsonRaw(credsPath);
45
47
  if (raw) try {
46
48
  JSON.parse(raw);
47
- fs.copyFileSync(credsPath, backupPath);
48
- try {
49
- fs.chmodSync(backupPath, 384);
50
- } catch {}
49
+ await writeWebCredsRawAtomically({
50
+ filePath: backupPath,
51
+ content: raw,
52
+ tempPrefix: ".creds.backup"
53
+ });
51
54
  } catch {}
52
55
  } catch {}
53
56
  try {
@@ -67,10 +70,15 @@ async function printTerminalQr(qr) {
67
70
  async function createWaSocket(printQr, verbose, opts = {}) {
68
71
  const logger = toPinoLikeLogger(getChildLogger({ module: "baileys" }, { level: verbose ? "info" : "silent" }), verbose ? "info" : "silent");
69
72
  const authDir = resolveUserPath(opts.authDir ?? resolveDefaultWebAuthDir());
73
+ await rejectUnsafeWebCredsPath(authDir);
70
74
  await ensureDir(authDir);
71
75
  const sessionLogger = getChildLogger({ module: "web-session" });
72
76
  if (await waitForCredsSaveQueueWithTimeout(authDir) === "timed_out") sessionLogger.warn({ authDir }, CREDS_FLUSH_TIMEOUT_MESSAGE);
73
- else await restoreCredsFromBackupIfNeeded(authDir);
77
+ else {
78
+ await rejectUnsafeWebCredsPath(authDir);
79
+ await restoreCredsFromBackupIfNeeded(authDir);
80
+ }
81
+ await rejectUnsafeWebCredsPath(authDir);
74
82
  const { state } = await useMultiFileAuthState(authDir);
75
83
  const saveCreds = async () => {
76
84
  await writeCredsJsonAtomically(authDir, state.creds);
@@ -1,5 +1,5 @@
1
1
  import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
2
- import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-DskwwYAM.js";
2
+ import { a as resolveWhatsAppAccount, n as hasAnyWhatsAppAuth } from "./accounts-BPYgj8Fv.js";
3
3
  import { a as normalizeWhatsAppAllowFromEntries } from "./normalize-target-bVWjgftN.js";
4
4
  import { t as WhatsAppChannelConfigSchema } from "./config-schema-CsNDlDpL.js";
5
5
  import { n as whatsappDoctor } from "./doctor-By3SB4lm.js";
@@ -125,10 +125,10 @@ function resolveWhatsAppConfigPath(params) {
125
125
  return `${resolveWhatsAppGroupScopeBasePath(params)}.${params.field}`;
126
126
  }
127
127
  async function loadWhatsAppChannelRuntime() {
128
- return await import("./channel.runtime-CvfJiuex.js");
128
+ return await import("./channel.runtime-BBPZSziE.js");
129
129
  }
130
130
  async function loadWhatsAppSetupSurface() {
131
- return await import("./setup-surface-D4sy0_LW.js");
131
+ return await import("./setup-surface-DqY0LqAY.js");
132
132
  }
133
133
  const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(async () => (await loadWhatsAppSetupSurface()).whatsappSetupWizard);
134
134
  const whatsappConfigAdapter = createScopedChannelConfigAdapter({
@@ -1,9 +1,9 @@
1
1
  import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
2
- import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-DskwwYAM.js";
2
+ import { r as hasWebCredsSync } from "./creds-files-B1kSWtBg.js";
3
+ import { a as resolveWhatsAppAccount, o as resolveWhatsAppAuthDir } from "./accounts-BPYgj8Fv.js";
3
4
  import { a as normalizeWhatsAppAllowFromEntries, o as normalizeWhatsAppAllowFromEntry } from "./normalize-target-bVWjgftN.js";
4
- import { t as whatsappSetupAdapter } from "./setup-core-m8ba61Dp.js";
5
- import path from "node:path";
6
- import { DEFAULT_ACCOUNT_ID, createSetupTranslator, pathExists, splitSetupEntries } from "openclaw/plugin-sdk/setup";
5
+ import { t as whatsappSetupAdapter } from "./setup-core-Dm1hsI3r.js";
6
+ import { DEFAULT_ACCOUNT_ID, createSetupTranslator, splitSetupEntries } from "openclaw/plugin-sdk/setup";
7
7
  import { formatCliCommand, formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
8
8
  //#region extensions/whatsapp/src/setup-finalize.ts
9
9
  const t = createSetupTranslator();
@@ -89,7 +89,7 @@ async function detectWhatsAppLinked(cfg, accountId) {
89
89
  cfg,
90
90
  accountId
91
91
  });
92
- return await pathExists(path.join(authDir, "creds.json"));
92
+ return hasWebCredsSync(authDir);
93
93
  }
94
94
  async function promptWhatsAppOwnerAllowFrom(params) {
95
95
  const { prompter, existingAllowFrom } = params;
@@ -280,7 +280,7 @@ async function finalizeWhatsAppSetup(params) {
280
280
  message: linked ? t("wizard.whatsapp.relinkPrompt") : t("wizard.whatsapp.linkNowPrompt"),
281
281
  initialValue: !linked
282
282
  })) try {
283
- const { loginWeb } = await import("./login-CGOtBPVS.js").then((n) => n.n);
283
+ const { loginWeb } = await import("./login-nJwaNuC-.js").then((n) => n.n);
284
284
  await loginWeb(false, void 0, params.runtime, accountId);
285
285
  } catch (error) {
286
286
  params.runtime.error(`WhatsApp login failed: ${String(error)}`);
@@ -1,2 +1,2 @@
1
- import { t as whatsappSetupPlugin } from "./channel.setup-CBHtRTDw.js";
1
+ import { t as whatsappSetupPlugin } from "./channel.setup-BDH3Mk5M.js";
2
2
  export { whatsappSetupPlugin };
@@ -1,6 +1,6 @@
1
1
  import { t as listAccountIds } from "./account-ids-CB5SOWjc.js";
2
- import { o as resolveWhatsAppAuthDir } from "./accounts-DskwwYAM.js";
3
- import { a as formatWhatsAppWebAuthStatusState, h as readWebAuthState } from "./auth-store-C-5icsdY.js";
2
+ import { o as resolveWhatsAppAuthDir } from "./accounts-BPYgj8Fv.js";
3
+ import { a as formatWhatsAppWebAuthStatusState, h as readWebAuthState } from "./auth-store-GTQvJznL.js";
4
4
  import { DEFAULT_ACCOUNT_ID, createSetupTranslator, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
5
5
  //#region extensions/whatsapp/src/setup-surface.ts
6
6
  const t = createSetupTranslator();
@@ -36,7 +36,7 @@ const whatsappSetupWizard = {
36
36
  },
37
37
  resolveShouldPromptAccountIds: ({ shouldPromptAccountIds }) => shouldPromptAccountIds,
38
38
  credentials: [],
39
- finalize: async (params) => await (await import("./setup-finalize-Du-2MqfD.js")).finalizeWhatsAppSetup(params),
39
+ finalize: async (params) => await (await import("./setup-finalize-BlTQrUj9.js")).finalizeWhatsAppSetup(params),
40
40
  disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
41
41
  onAccountRecorded: (accountId, options) => {
42
42
  options?.onAccountId?.(channel, accountId);
package/dist/test-api.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as resolveWhatsAppRuntimeGroupPolicy } from "./runtime-group-policy-DeSRFXEV.js";
2
- import { t as whatsappOutbound } from "./outbound-adapter-AQXm0jeQ.js";
2
+ import { t as whatsappOutbound } from "./outbound-adapter-ltiZkW9L.js";
3
3
  export { resolveWhatsAppRuntimeGroupPolicy, whatsappOutbound };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/whatsapp",
3
- "version": "2026.5.20-beta.1",
3
+ "version": "2026.5.20",
4
4
  "description": "OpenClaw WhatsApp channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,7 +19,7 @@
19
19
  "openclaw": "workspace:*"
20
20
  },
21
21
  "peerDependencies": {
22
- "openclaw": ">=2026.5.20-beta.1"
22
+ "openclaw": ">=2026.5.20"
23
23
  },
24
24
  "peerDependenciesMeta": {
25
25
  "openclaw": {
@@ -62,10 +62,10 @@
62
62
  "minHostVersion": ">=2026.4.25"
63
63
  },
64
64
  "compat": {
65
- "pluginApi": ">=2026.5.20-beta.1"
65
+ "pluginApi": ">=2026.5.20"
66
66
  },
67
67
  "build": {
68
- "openclawVersion": "2026.5.20-beta.1"
68
+ "openclawVersion": "2026.5.20"
69
69
  },
70
70
  "release": {
71
71
  "publishToClawHub": true,
@@ -1,19 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- //#region extensions/whatsapp/src/creds-files.ts
4
- function resolveWebCredsPath(authDir) {
5
- return path.join(authDir, "creds.json");
6
- }
7
- function resolveWebCredsBackupPath(authDir) {
8
- return path.join(authDir, "creds.json.bak");
9
- }
10
- function hasWebCredsSync(authDir) {
11
- try {
12
- const stats = fs.statSync(resolveWebCredsPath(authDir));
13
- return stats.isFile() && stats.size > 1;
14
- } catch {
15
- return false;
16
- }
17
- }
18
- //#endregion
19
- export { resolveWebCredsBackupPath as n, resolveWebCredsPath as r, hasWebCredsSync as t };
@@ -1,10 +1,10 @@
1
1
  import { t as formatError } from "./session-errors-BAj9D2La.js";
2
2
  import { a as sanitizeAssistantVisibleTextWithProfile, i as sanitizeAssistantVisibleText, o as sleep, s as stripToolCallXmlTags } from "./text-runtime-Dk37KYHj.js";
3
3
  import path from "node:path";
4
+ import { writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
4
5
  import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
5
6
  import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg } from "openclaw/plugin-sdk/media-runtime";
6
7
  import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime";
7
- import { writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
8
8
  import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
9
9
  //#region extensions/whatsapp/src/document-filename.ts
10
10
  const WHATSAPP_DEFAULT_DOCUMENT_FILE_NAME = "file";