@openclaw/whatsapp 2026.5.7-beta.1 → 2026.5.9-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/{action-runtime-BqYZmBX_.js → action-runtime-flTHnBac.js} +1 -1
  3. package/dist/action-runtime.runtime.js +1 -1
  4. package/dist/api.js +115 -7
  5. package/dist/{auth-store-BNZmNP-s.js → auth-store-CG0eSZ0D.js} +17 -39
  6. package/dist/{channel-CTr3YjO8.js → channel-Dnv-QeNE.js} +34 -7
  7. package/dist/channel-plugin-api.js +1 -1
  8. package/dist/{channel-react-action-BuSTzmDX.js → channel-react-action-LOuxBqX6.js} +1 -1
  9. package/dist/{channel.runtime-C3i9Svfj.js → channel.runtime-CCZpOzbU.js} +5 -5
  10. package/dist/{channel.setup-BYtkDwHe.js → channel.setup-CV0OjAwl.js} +3 -3
  11. package/dist/{connection-controller-BCIuChXD.js → connection-controller-d8D2iUBj.js} +6 -197
  12. package/dist/contract-api.js +1 -1
  13. package/dist/legacy-state-migrations-api.js +1 -1
  14. package/dist/light-runtime-api.js +2 -2
  15. package/dist/{login-DSUTCcJ7.js → login-B_u009k0.js} +3 -2
  16. package/dist/{login-qr-dfs8tfGo.js → login-qr-C0b7I7hu.js} +3 -2
  17. package/dist/login-qr-runtime.js +1 -1
  18. package/dist/{monitor-C5_C_RGJ.js → monitor-5u0dVXnB.js} +93 -683
  19. package/dist/{outbound-adapter-CbR17Ehj.js → outbound-adapter-BoHBD2S7.js} +3 -3
  20. package/dist/{outbound-base-BmzhutvF.js → outbound-base-CCx7atwc.js} +6 -1
  21. package/dist/{outbound-media-contract-BPdOq7Hb.js → outbound-media-contract-Dzi1ILTd.js} +36 -40
  22. package/dist/outbound-payload-test-api.js +1 -1
  23. package/dist/runtime-api.js +8 -7
  24. package/dist/{send-CxctcFGT.js → send-CLBN7TZv.js} +1 -1
  25. package/dist/send-api-DoycpOvC.js +697 -0
  26. package/dist/session-BXC3R43P.js +198 -0
  27. package/dist/setup-plugin-api.js +1 -1
  28. package/dist/{setup-surface-CF3l3gEZ.js → setup-surface-RbOpXjSR.js} +2 -2
  29. package/dist/{shared-CTSTwprn.js → shared-h4cwNeYT.js} +2 -2
  30. package/dist/{state-migrations-DnCdvoYD.js → state-migrations-Bm0S67yH.js} +2 -1
  31. package/dist/test-api.js +1 -1
  32. package/package.json +5 -5
  33. package/dist/{access-control-CTj7P7WP.js → access-control-hFVqAWSd.js} +1 -1
  34. /package/dist/{active-listener-N7GFKsuN.js → active-listener-DTbKS-j-.js} +0 -0
  35. /package/dist/{audio-preflight.runtime-Bcdsl_ri.js → audio-preflight.runtime-MmkB-pgX.js} +0 -0
  36. /package/dist/{reply-resolver.runtime-BRCgoO4C.js → reply-resolver.runtime-rIVWohXr.js} +0 -0
  37. /package/dist/{session.runtime-C1eSE_KK.js → session.runtime-CVhtXjTk.js} +0 -0
@@ -1,2 +1,2 @@
1
- import { t as handleWhatsAppAction } from "./action-runtime-BqYZmBX_.js";
1
+ import { t as handleWhatsAppAction } from "./action-runtime-flTHnBac.js";
2
2
  export { handleWhatsAppAction };
@@ -1,7 +1,7 @@
1
1
  import { a as resolveWhatsAppAccount } from "./accounts-BDqgpFEB.js";
2
2
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CQ3Y1i0g.js";
3
3
  import { t as resolveWhatsAppReactionLevel } from "./reaction-level-CRVEVAfi.js";
4
- import { r as sendReactionWhatsApp } from "./send-CxctcFGT.js";
4
+ import { r as sendReactionWhatsApp } from "./send-CLBN7TZv.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-BqYZmBX_.js";
1
+ import { t as handleWhatsAppAction } from "./action-runtime-flTHnBac.js";
2
2
  export { handleWhatsAppAction };
package/dist/api.js CHANGED
@@ -4,20 +4,128 @@ import { a as normalizeWhatsAppAllowFromEntries, c as normalizeWhatsAppTarget, i
4
4
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CQ3Y1i0g.js";
5
5
  import "./reaction-level-CRVEVAfi.js";
6
6
  import { a as markdownToWhatsApp, i as jidToE164, n as assertWebChannel, o as resolveJidToE164, r as isSelfChatMode, s as toWhatsappJid, t as text_runtime_exports } from "./text-runtime-DFFwk5z6.js";
7
- import "./send-CxctcFGT.js";
8
- import { t as whatsappPlugin } from "./channel-CTr3YjO8.js";
9
- import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-base-BmzhutvF.js";
7
+ import "./send-CLBN7TZv.js";
8
+ import { t as whatsappPlugin } from "./channel-Dnv-QeNE.js";
9
+ import { n as WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-base-CCx7atwc.js";
10
10
  import { t as whatsappCommandPolicy } from "./command-policy-O8sRnqUV.js";
11
- import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint } from "./shared-CTSTwprn.js";
11
+ import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint } from "./shared-h4cwNeYT.js";
12
12
  import "./config-schema-Dmo66Ubb.js";
13
- import { t as whatsappSetupPlugin } from "./channel.setup-BYtkDwHe.js";
13
+ import { t as whatsappSetupPlugin } from "./channel.setup-CV0OjAwl.js";
14
14
  import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-DLGCIbfl.js";
15
15
  import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-BNCbgnmy.js";
16
- import { t as __testing } from "./access-control-CTj7P7WP.js";
16
+ import { t as __testing } from "./access-control-hFVqAWSd.js";
17
+ import { p as extractText, t as createWebSendApi } from "./send-api-DoycpOvC.js";
18
+ import { r as waitForWaConnection, t as createWaSocket } from "./session-BXC3R43P.js";
17
19
  import "openclaw/plugin-sdk/channel-actions";
18
20
  import "openclaw/plugin-sdk/account-resolution";
19
21
  import "openclaw/plugin-sdk/core";
20
22
  import "openclaw/plugin-sdk/account-id";
23
+ //#region extensions/whatsapp/src/qa-driver.runtime.ts
24
+ function normalizeObservedMessage(message, authDir) {
25
+ if (message.key.fromMe) return null;
26
+ const text = extractText(message.message ?? void 0);
27
+ if (!text) return null;
28
+ const fromJid = message.key.remoteJid ?? void 0;
29
+ return {
30
+ fromJid,
31
+ fromPhoneE164: fromJid ? jidToE164(fromJid, { authDir }) : null,
32
+ messageId: message.key.id ?? void 0,
33
+ observedAt: (/* @__PURE__ */ new Date()).toISOString(),
34
+ text
35
+ };
36
+ }
37
+ function closeSocket(sock) {
38
+ const maybeEnd = sock.end;
39
+ if (typeof maybeEnd === "function") {
40
+ maybeEnd.call(sock);
41
+ return;
42
+ }
43
+ const maybeClose = sock.ws?.close;
44
+ if (typeof maybeClose === "function") maybeClose.call(sock.ws);
45
+ }
46
+ async function startWhatsAppQaDriverSession(params) {
47
+ const sock = await createWaSocket(false, false, { authDir: params.authDir });
48
+ const observedMessages = [];
49
+ const waiters = [];
50
+ let closed = false;
51
+ const removeWaiter = (waiter) => {
52
+ const index = waiters.indexOf(waiter);
53
+ if (index >= 0) waiters.splice(index, 1);
54
+ clearTimeout(waiter.timeout);
55
+ };
56
+ const observe = (message) => {
57
+ observedMessages.push(message);
58
+ for (const waiter of waiters.slice()) {
59
+ if (!waiter.predicate(message)) continue;
60
+ removeWaiter(waiter);
61
+ waiter.resolve(message);
62
+ }
63
+ };
64
+ const onMessagesUpsert = (event) => {
65
+ for (const rawMessage of event.messages ?? []) {
66
+ const observed = normalizeObservedMessage(rawMessage, params.authDir);
67
+ if (observed) observe(observed);
68
+ }
69
+ };
70
+ const removeMessageListener = () => {
71
+ sock.ev.off?.("messages.upsert", onMessagesUpsert);
72
+ };
73
+ const closeSessionResources = (waiterError) => {
74
+ if (closed) return;
75
+ closed = true;
76
+ for (const waiter of waiters.slice()) {
77
+ removeWaiter(waiter);
78
+ if (waiterError) waiter.reject(waiterError);
79
+ }
80
+ removeMessageListener();
81
+ closeSocket(sock);
82
+ };
83
+ sock.ev.on("messages.upsert", onMessagesUpsert);
84
+ let connectionTimeout;
85
+ try {
86
+ await Promise.race([waitForWaConnection(sock), new Promise((_, reject) => {
87
+ connectionTimeout = setTimeout(() => reject(/* @__PURE__ */ new Error("timed out waiting for WhatsApp QA driver session")), params.connectionTimeoutMs ?? 45e3);
88
+ connectionTimeout.unref?.();
89
+ })]);
90
+ } catch (error) {
91
+ closeSessionResources(error instanceof Error ? error : /* @__PURE__ */ new Error("failed starting WhatsApp QA driver session"));
92
+ throw error;
93
+ } finally {
94
+ if (connectionTimeout) clearTimeout(connectionTimeout);
95
+ }
96
+ const sendApi = createWebSendApi({
97
+ sock,
98
+ defaultAccountId: "qa-driver"
99
+ });
100
+ return {
101
+ async close() {
102
+ closeSessionResources(/* @__PURE__ */ new Error("WhatsApp QA driver session closed"));
103
+ },
104
+ getObservedMessages() {
105
+ return [...observedMessages];
106
+ },
107
+ async sendText(to, text) {
108
+ return { messageId: (await sendApi.sendMessage(to, text)).messageId };
109
+ },
110
+ async waitForMessage(params) {
111
+ const existing = observedMessages.find(params.match);
112
+ if (existing) return existing;
113
+ return await new Promise((resolve, reject) => {
114
+ const waiter = {
115
+ predicate: params.match,
116
+ resolve,
117
+ reject,
118
+ timeout: setTimeout(() => {
119
+ removeWaiter(waiter);
120
+ reject(/* @__PURE__ */ new Error("timed out waiting for WhatsApp QA driver message"));
121
+ }, params.timeoutMs)
122
+ };
123
+ waiters.push(waiter);
124
+ });
125
+ }
126
+ };
127
+ }
128
+ //#endregion
21
129
  var CONFIG_DIR = text_runtime_exports.CONFIG_DIR;
22
130
  var DEFAULT_LOG_DIR = text_runtime_exports.DEFAULT_LOG_DIR;
23
131
  var DEFAULT_LOG_FILE = text_runtime_exports.DEFAULT_LOG_FILE;
@@ -145,4 +253,4 @@ var summarizeStringEntries = text_runtime_exports.summarizeStringEntries;
145
253
  var toPinoLikeLogger = text_runtime_exports.toPinoLikeLogger;
146
254
  var truncateUtf16Safe = text_runtime_exports.truncateUtf16Safe;
147
255
  var withTimeout = text_runtime_exports.withTimeout;
148
- export { CONFIG_DIR, DEFAULT_LOG_DIR, DEFAULT_LOG_FILE, DEFAULT_WEB_MEDIA_BYTES, DEFAULT_WHATSAPP_MEDIA_MAX_MB, FILE_REF_EXTENSIONS_WITH_TLD, SYSTEM_MARK, WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, __test__, asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, assertWebChannel, bindAbortRelay, buildTimeoutAbortSignal, chunkItems, chunkMarkdownIR, clamp, clampInt, clampNumber, convertMarkdownTables, createScopedExpiringIdCache, diagnosticLogger, displayPath, displayString, ensureDir, escapeRegExp, fetchWithTimeout, findCodeRegions, getChildLogger, getDefaultRedactPatterns, getDiagnosticSessionStateCountForTest, getLogger, getResolvedLoggerSettings, hasAnyWhatsAppAuth, hasNonEmptyString, hasOrphanReasoningCloseBoundary, hasSystemMark, isAutoLinkedFileRef, isFileLogLevelEnabled, isInsideCode, isRecord, isSelfChatMode, isWhatsAppGroupJid, isWhatsAppUserTarget, jidToE164, listEnabledWhatsAppAccounts, listAccountIds as listWhatsAppAccountIds, listWhatsAppAuthDirs, listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig, localeLowercasePreservingWhitespace, logActiveRuns, logDebug, logError, logInfo, logLaneDequeue, logLaneEnqueue, logMessageProcessed, logMessageQueued, logRunAttempt, logSessionStateChange, logSuccess, logToolLoopAction, logWarn, logWebhookError, logWebhookProcessed, logWebhookReceived, looksLikeWhatsAppTargetId, lowercasePreservingWhitespace, markdownToIR, markdownToIRWithMeta, markdownToWhatsApp, normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeE164, normalizeFastMode, normalizeHyphenSlug, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeStringifiedOptionalString, normalizeTrimmedStringList, normalizeWhatsAppAllowFromEntries, normalizeWhatsAppMessagingTarget, normalizeWhatsAppTarget, parseInlineDirectives, pathExists, prefixSystemMessage, readStringField, readStringValue, redactIdentifier, redactSensitiveLines, redactSensitiveText, redactToolDetail, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers, resetDiagnosticStateForTest, resetLogger, resolveConfigDir, resolveDefaultWhatsAppAccountId, resolveGlobalMap, resolveGlobalSingleton, resolveHomeDir, resolveJidToE164, resolvePrimaryStringValue, resolveReactionLevel, resolveRedactOptions, resolveStuckSessionWarnMs, resolveUserPath, resolveWhatsAppAccount, resolveWhatsAppAuthDir, resolveWhatsAppGroupIntroHint, resolveWhatsAppGroupRequireMention, resolveWhatsAppGroupToolPolicy, resolveWhatsAppMediaMaxBytes, resolveWhatsAppOutboundTarget, safeParseJson, sanitizeAssistantVisibleText, sanitizeAssistantVisibleTextWithOptions, sanitizeAssistantVisibleTextWithProfile, sanitizeReplyDirectiveId, sanitizeTerminalText, setLoggerOverride, sha256HexPrefix, shortenHomeInString, shortenHomePath, sleep, sliceMarkdownIR, sliceUtf16Safe, startDiagnosticHeartbeat, stopDiagnosticHeartbeat, stripAssistantInternalScaffolding, stripDowngradedToolCallText, stripInlineDirectiveTagsForDelivery, stripInlineDirectiveTagsForDisplay, stripInlineDirectiveTagsFromMessageForDisplay, stripMarkdown, stripMinimaxToolCallXml, stripReasoningTagsFromText, stripToolCallXmlTags, summarizeStringEntries, toPinoLikeLogger, toWhatsappJid, truncateUtf16Safe, __testing as whatsappAccessControlTesting, whatsappCommandPolicy, whatsappPlugin, whatsappSetupPlugin, withTimeout };
256
+ export { CONFIG_DIR, DEFAULT_LOG_DIR, DEFAULT_LOG_FILE, DEFAULT_WEB_MEDIA_BYTES, DEFAULT_WHATSAPP_MEDIA_MAX_MB, FILE_REF_EXTENSIONS_WITH_TLD, SYSTEM_MARK, WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS, __test__, asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, assertWebChannel, bindAbortRelay, buildTimeoutAbortSignal, chunkItems, chunkMarkdownIR, clamp, clampInt, clampNumber, convertMarkdownTables, createScopedExpiringIdCache, diagnosticLogger, displayPath, displayString, ensureDir, escapeRegExp, fetchWithTimeout, findCodeRegions, getChildLogger, getDefaultRedactPatterns, getDiagnosticSessionStateCountForTest, getLogger, getResolvedLoggerSettings, hasAnyWhatsAppAuth, hasNonEmptyString, hasOrphanReasoningCloseBoundary, hasSystemMark, isAutoLinkedFileRef, isFileLogLevelEnabled, isInsideCode, isRecord, isSelfChatMode, isWhatsAppGroupJid, isWhatsAppUserTarget, jidToE164, listEnabledWhatsAppAccounts, listAccountIds as listWhatsAppAccountIds, listWhatsAppAuthDirs, listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig, localeLowercasePreservingWhitespace, logActiveRuns, logDebug, logError, logInfo, logLaneDequeue, logLaneEnqueue, logMessageProcessed, logMessageQueued, logRunAttempt, logSessionStateChange, logSuccess, logToolLoopAction, logWarn, logWebhookError, logWebhookProcessed, logWebhookReceived, looksLikeWhatsAppTargetId, lowercasePreservingWhitespace, markdownToIR, markdownToIRWithMeta, markdownToWhatsApp, normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeE164, normalizeFastMode, normalizeHyphenSlug, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeStringifiedOptionalString, normalizeTrimmedStringList, normalizeWhatsAppAllowFromEntries, normalizeWhatsAppMessagingTarget, normalizeWhatsAppTarget, parseInlineDirectives, pathExists, prefixSystemMessage, readStringField, readStringValue, redactIdentifier, redactSensitiveLines, redactSensitiveText, redactToolDetail, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers, resetDiagnosticStateForTest, resetLogger, resolveConfigDir, resolveDefaultWhatsAppAccountId, resolveGlobalMap, resolveGlobalSingleton, resolveHomeDir, resolveJidToE164, resolvePrimaryStringValue, resolveReactionLevel, resolveRedactOptions, resolveStuckSessionWarnMs, resolveUserPath, resolveWhatsAppAccount, resolveWhatsAppAuthDir, resolveWhatsAppGroupIntroHint, resolveWhatsAppGroupRequireMention, resolveWhatsAppGroupToolPolicy, resolveWhatsAppMediaMaxBytes, resolveWhatsAppOutboundTarget, safeParseJson, sanitizeAssistantVisibleText, sanitizeAssistantVisibleTextWithOptions, sanitizeAssistantVisibleTextWithProfile, sanitizeReplyDirectiveId, sanitizeTerminalText, setLoggerOverride, sha256HexPrefix, shortenHomeInString, shortenHomePath, sleep, sliceMarkdownIR, sliceUtf16Safe, startDiagnosticHeartbeat, startWhatsAppQaDriverSession, stopDiagnosticHeartbeat, stripAssistantInternalScaffolding, stripDowngradedToolCallText, stripInlineDirectiveTagsForDelivery, stripInlineDirectiveTagsForDisplay, stripInlineDirectiveTagsFromMessageForDisplay, stripMarkdown, stripMinimaxToolCallXml, stripReasoningTagsFromText, stripToolCallXmlTags, summarizeStringEntries, toPinoLikeLogger, toWhatsappJid, truncateUtf16Safe, __testing as whatsappAccessControlTesting, whatsappCommandPolicy, whatsappPlugin, whatsappSetupPlugin, withTimeout };
@@ -6,45 +6,27 @@ import path from "node:path";
6
6
  import { resolveOAuthDir as resolveOAuthDir$1 } from "openclaw/plugin-sdk/state-paths";
7
7
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
8
8
  import { defaultRuntime, getChildLogger, info, success } from "openclaw/plugin-sdk/runtime-env";
9
+ import { replaceFileAtomic } from "openclaw/plugin-sdk/security-runtime";
9
10
  import fs$1 from "node:fs/promises";
10
- import { randomUUID } from "node:crypto";
11
11
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
12
12
  //#region extensions/whatsapp/src/creds-persistence.ts
13
13
  const CREDS_FILE_MODE = 384;
14
14
  const CREDS_SAVE_FLUSH_TIMEOUT_MS = 15e3;
15
15
  const credsSaveQueues = /* @__PURE__ */ new Map();
16
16
  async function stringifyCreds(creds) {
17
- const { BufferJSON } = await import("./session.runtime-C1eSE_KK.js").then((n) => n.a);
17
+ const { BufferJSON } = await import("./session.runtime-CVhtXjTk.js").then((n) => n.a);
18
18
  return JSON.stringify(creds, BufferJSON.replacer);
19
19
  }
20
- async function syncDirectory(dirPath) {
21
- let handle;
22
- try {
23
- handle = await fs$1.open(dirPath, "r");
24
- await handle.sync();
25
- } catch {} finally {
26
- await handle?.close().catch(() => {});
27
- }
28
- }
29
20
  async function writeCredsJsonAtomically(authDir, creds) {
30
- const credsPath = resolveWebCredsPath(authDir);
31
- const tempPath = path.join(authDir, `.creds.${process.pid}.${randomUUID()}.tmp`);
32
- const json = await stringifyCreds(creds);
33
- let handle;
34
- try {
35
- handle = await fs$1.open(tempPath, "w", CREDS_FILE_MODE);
36
- await handle.writeFile(json, { encoding: "utf-8" });
37
- await handle.sync();
38
- await handle.close();
39
- handle = void 0;
40
- await fs$1.rename(tempPath, credsPath);
41
- await fs$1.chmod(credsPath, CREDS_FILE_MODE).catch(() => {});
42
- await syncDirectory(path.dirname(credsPath));
43
- } catch (error) {
44
- await handle?.close().catch(() => {});
45
- await fs$1.rm(tempPath, { force: true }).catch(() => {});
46
- throw error;
47
- }
21
+ await replaceFileAtomic({
22
+ filePath: resolveWebCredsPath(authDir),
23
+ content: await stringifyCreds(creds),
24
+ dirMode: 448,
25
+ mode: CREDS_FILE_MODE,
26
+ tempPrefix: ".creds",
27
+ syncTempFile: true,
28
+ syncParentDir: true
29
+ });
48
30
  }
49
31
  function enqueueCredsSave(authDir, saveCreds, onError) {
50
32
  const next = (credsSaveQueues.get(authDir) ?? Promise.resolve()).then(() => saveCreds()).catch((error) => {
@@ -106,7 +88,6 @@ async function waitForWebAuthBarrier(authDir, context) {
106
88
  }
107
89
  async function restoreCredsFromBackupIfNeeded(authDir) {
108
90
  const logger = getChildLogger({ module: "web-session" });
109
- let tempRestorePath = null;
110
91
  try {
111
92
  const credsPath = resolveWebCredsPath(authDir);
112
93
  const backupPath = resolveWebCredsBackupPath(authDir);
@@ -119,19 +100,16 @@ async function restoreCredsFromBackupIfNeeded(authDir) {
119
100
  if (!backupRaw) return false;
120
101
  if (!(await fs$1.lstat(backupPath).catch(() => null))?.isFile()) return false;
121
102
  JSON.parse(backupRaw);
122
- tempRestorePath = path.join(authDir, `.creds.restore-${randomUUID()}.tmp`);
123
- await fs$1.writeFile(tempRestorePath, backupRaw, {
124
- encoding: "utf-8",
103
+ await replaceFileAtomic({
104
+ filePath: credsPath,
105
+ content: backupRaw,
106
+ dirMode: 448,
125
107
  mode: 384,
126
- flag: "wx"
108
+ tempPrefix: ".creds.restore"
127
109
  });
128
- await fs$1.rename(tempRestorePath, credsPath);
129
- tempRestorePath = null;
130
110
  logger.warn({ credsPath }, "restored corrupted WhatsApp creds.json from backup");
131
111
  return true;
132
- } catch {} finally {
133
- if (tempRestorePath) await fs$1.rm(tempRestorePath, { force: true }).catch(() => {});
134
- }
112
+ } catch {}
135
113
  return false;
136
114
  }
137
115
  async function webAuthExists(authDir = resolveDefaultWebAuthDir()) {
@@ -4,16 +4,16 @@ import { c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, n as isWh
4
4
  import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-CQ3Y1i0g.js";
5
5
  import { t as resolveWhatsAppReactionLevel } from "./reaction-level-CRVEVAfi.js";
6
6
  import "./normalize-Y3eBdM8a.js";
7
- import { r as normalizeWhatsAppPayloadTextPreservingIndentation } from "./outbound-media-contract-BPdOq7Hb.js";
8
- import { i as sendTypingWhatsApp, n as sendPollWhatsApp, t as sendMessageWhatsApp } from "./send-CxctcFGT.js";
7
+ import { r as normalizeWhatsAppPayloadTextPreservingIndentation } from "./outbound-media-contract-Dzi1ILTd.js";
8
+ import { i as sendTypingWhatsApp, n as sendPollWhatsApp, t as sendMessageWhatsApp } from "./send-CLBN7TZv.js";
9
9
  import { t as createWhatsAppLoginTool } from "./agent-tools-login-DpRxLNRB.js";
10
- import { t as createWhatsAppOutboundBase } from "./outbound-base-BmzhutvF.js";
10
+ import { t as createWhatsAppOutboundBase } from "./outbound-base-CCx7atwc.js";
11
11
  import { t as getWhatsAppRuntime } from "./runtime-6fZ67abR.js";
12
12
  import { t as whatsappCommandPolicy } from "./command-policy-O8sRnqUV.js";
13
- import { a as resolveWhatsAppGroupToolPolicy, c as formatWhatsAppConfigAllowFromEntries, i as resolveWhatsAppGroupRequireMention, n as loadWhatsAppChannelRuntime, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, s as resolveWhatsAppMentionStripRegexes, t as createWhatsAppPluginBase } from "./shared-CTSTwprn.js";
14
- import { d as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-BNZmNP-s.js";
13
+ import { a as resolveWhatsAppGroupToolPolicy, c as formatWhatsAppConfigAllowFromEntries, i as resolveWhatsAppGroupRequireMention, n as loadWhatsAppChannelRuntime, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, s as resolveWhatsAppMentionStripRegexes, t as createWhatsAppPluginBase } from "./shared-h4cwNeYT.js";
14
+ import { d as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-CG0eSZ0D.js";
15
15
  import { t as whatsappSetupAdapter } from "./setup-core-DZKvpzbH.js";
16
- import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-DnCdvoYD.js";
16
+ import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-Bm0S67yH.js";
17
17
  import { createActionGate as createActionGate$1 } from "openclaw/plugin-sdk/channel-actions";
18
18
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
19
19
  import { buildChannelOutboundSessionRoute } from "openclaw/plugin-sdk/core";
@@ -23,6 +23,7 @@ import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
23
23
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
24
24
  import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord } from "openclaw/plugin-sdk/status-helpers";
25
25
  import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
26
+ import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
26
27
  import { chunkText } from "openclaw/plugin-sdk/reply-chunking";
27
28
  //#region extensions/whatsapp/src/approval-auth.ts
28
29
  function normalizeWhatsAppApproverId(value) {
@@ -120,6 +121,31 @@ const whatsappChannelOutbound = {
120
121
  text: normalizeWhatsAppChannelPayloadText(payload.text)
121
122
  })
122
123
  };
124
+ function toWhatsAppMessageSendResult(result, replyToId) {
125
+ const source = result;
126
+ const receipt = result.receipt ?? createMessageReceiptFromOutboundResults({
127
+ results: result.messageId ? [{
128
+ channel: "whatsapp",
129
+ messageId: result.messageId,
130
+ toJid: source.toJid
131
+ }] : [],
132
+ kind: "text",
133
+ ...replyToId ? { replyToId } : {}
134
+ });
135
+ return {
136
+ messageId: result.messageId || receipt.primaryPlatformMessageId,
137
+ receipt
138
+ };
139
+ }
140
+ const whatsappMessageAdapter = defineChannelMessageAdapter({
141
+ id: "whatsapp",
142
+ durableFinal: { capabilities: {
143
+ text: true,
144
+ replyTo: true,
145
+ messageSendingHooks: true
146
+ } },
147
+ send: { text: async (ctx) => toWhatsAppMessageSendResult(await whatsappChannelOutbound.sendText({ ...ctx }), ctx.replyToId) }
148
+ });
123
149
  //#endregion
124
150
  //#region extensions/whatsapp/src/heartbeat.ts
125
151
  async function checkWhatsAppHeartbeatReady(params) {
@@ -297,7 +323,7 @@ function collectWhatsAppStatusIssues(accounts) {
297
323
  //#endregion
298
324
  //#region extensions/whatsapp/src/channel.ts
299
325
  const loadWhatsAppDirectoryConfig = createLazyRuntimeModule(() => import("./directory-config-BNCbgnmy.js").then((n) => n.t));
300
- const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-BuSTzmDX.js"));
326
+ const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-LOuxBqX6.js"));
301
327
  function parseWhatsAppExplicitTarget(raw) {
302
328
  const normalized = normalizeWhatsAppTarget(raw);
303
329
  if (!normalized) return null;
@@ -365,6 +391,7 @@ const whatsappPlugin = createChatChannelPlugin({
365
391
  hint: "<E.164|group JID|newsletter JID>"
366
392
  }
367
393
  },
394
+ message: whatsappMessageAdapter,
368
395
  directory: {
369
396
  self: async ({ cfg, accountId }) => {
370
397
  const account = resolveWhatsAppAccount({
@@ -1,2 +1,2 @@
1
- import { t as whatsappPlugin } from "./channel-CTr3YjO8.js";
1
+ import { t as whatsappPlugin } from "./channel-Dnv-QeNE.js";
2
2
  export { whatsappPlugin };
@@ -1,5 +1,5 @@
1
1
  import { c as normalizeWhatsAppTarget, t as isWhatsAppGroupJid } from "./normalize-target-nXxC_hxG.js";
2
- import { t as handleWhatsAppAction } from "./action-runtime-BqYZmBX_.js";
2
+ import { t as handleWhatsAppAction } from "./action-runtime-flTHnBac.js";
3
3
  import "./normalize-Y3eBdM8a.js";
4
4
  import { readStringOrNumberParam, readStringParam as readStringParam$1, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
5
5
  //#region extensions/whatsapp/src/channel-react-action.ts
@@ -1,9 +1,9 @@
1
1
  import { startWebLoginWithQr as startWebLoginWithQr$1, waitForWebLogin as waitForWebLogin$1 } from "./login-qr-runtime.js";
2
- import { a as getWebAuthAgeMs$1, b as webAuthExists$1, d as readWebAuthExistsForDecision$1, f as readWebAuthSnapshot$1, h as readWebSelfId$1, m as readWebAuthState$1, o as logWebSelfId$1, p as readWebAuthSnapshotBestEffort$1, s as logoutWeb$1, u as readWebAuthExistsBestEffort$1 } from "./auth-store-BNZmNP-s.js";
3
- import { t as getActiveWebListener$1 } from "./active-listener-N7GFKsuN.js";
4
- import { t as monitorWebChannel$1 } from "./monitor-C5_C_RGJ.js";
5
- import { t as loginWeb$1 } from "./login-DSUTCcJ7.js";
6
- import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-CF3l3gEZ.js";
2
+ import { a as getWebAuthAgeMs$1, b as webAuthExists$1, d as readWebAuthExistsForDecision$1, f as readWebAuthSnapshot$1, h as readWebSelfId$1, m as readWebAuthState$1, o as logWebSelfId$1, p as readWebAuthSnapshotBestEffort$1, s as logoutWeb$1, u as readWebAuthExistsBestEffort$1 } from "./auth-store-CG0eSZ0D.js";
3
+ import { t as getActiveWebListener$1 } from "./active-listener-DTbKS-j-.js";
4
+ import { t as monitorWebChannel$1 } from "./monitor-5u0dVXnB.js";
5
+ import { t as loginWeb$1 } from "./login-B_u009k0.js";
6
+ import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-RbOpXjSR.js";
7
7
  //#region extensions/whatsapp/src/channel.runtime.ts
8
8
  function getActiveWebListener(...args) {
9
9
  return getActiveWebListener$1(...args);
@@ -1,7 +1,7 @@
1
- import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, t as createWhatsAppPluginBase } from "./shared-CTSTwprn.js";
2
- import { m as readWebAuthState } from "./auth-store-BNZmNP-s.js";
1
+ import { a as resolveWhatsAppGroupToolPolicy, i as resolveWhatsAppGroupRequireMention, o as resolveWhatsAppGroupIntroHint, r as whatsappSetupWizardProxy, t as createWhatsAppPluginBase } from "./shared-h4cwNeYT.js";
2
+ import { m as readWebAuthState } from "./auth-store-CG0eSZ0D.js";
3
3
  import { t as whatsappSetupAdapter } from "./setup-core-DZKvpzbH.js";
4
- import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-DnCdvoYD.js";
4
+ import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-Bm0S67yH.js";
5
5
  //#region extensions/whatsapp/src/channel.setup.ts
6
6
  const whatsappSetupPlugin = {
7
7
  ...createWhatsAppPluginBase({
@@ -1,17 +1,11 @@
1
- import { n as resolveWebCredsBackupPath, r as resolveWebCredsPath } from "./creds-files-_2V8jzQa.js";
2
1
  import { n as registerWhatsAppConnectionController, r as unregisterWhatsAppConnectionController } from "./connection-controller-registry-D_iIGz5m.js";
3
2
  import { n as getStatusCode, t as formatError } from "./session-errors-CSuKZPub.js";
4
- import { C as waitForCredsSaveQueueWithTimeout, l as readCredsJsonRaw, s as logoutWeb, v as resolveDefaultWebAuthDir, w as writeCredsJsonAtomically, x as enqueueCredsSave, y as restoreCredsFromBackupIfNeeded } from "./auth-store-BNZmNP-s.js";
5
- import { i as makeWASocket, n as fetchLatestBaileysVersion, o as useMultiFileAuthState, r as makeCacheableSignalKeyStore, t as DisconnectReason$1 } from "./session.runtime-C1eSE_KK.js";
6
- import fs from "node:fs";
7
- import { clamp, ensureDir, resolveUserPath } from "openclaw/plugin-sdk/text-runtime";
8
- import { VERSION, formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
9
- import { computeBackoff, danger, getChildLogger as getChildLogger$1, info, sleepWithAbort, success, toPinoLikeLogger } from "openclaw/plugin-sdk/runtime-env";
10
- import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
11
- import { randomUUID } from "node:crypto";
3
+ import { s as logoutWeb } from "./auth-store-CG0eSZ0D.js";
4
+ import { r as waitForWaConnection, t as createWaSocket } from "./session-BXC3R43P.js";
5
+ import { clamp } from "openclaw/plugin-sdk/text-runtime";
6
+ import { computeBackoff, info, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
12
7
  import { DisconnectReason } from "@whiskeysockets/baileys";
13
- import { HttpsProxyAgent } from "https-proxy-agent";
14
- import { resolveEnvHttpProxyUrl, shouldUseEnvHttpProxyForUrl } from "openclaw/plugin-sdk/fetch-runtime";
8
+ import { randomUUID } from "node:crypto";
15
9
  const DEFAULT_RECONNECT_POLICY = {
16
10
  initialMs: 2e3,
17
11
  maxMs: 3e4,
@@ -39,191 +33,6 @@ function resolveReconnectPolicy(cfg, overrides) {
39
33
  merged.maxAttempts = Math.max(0, Math.floor(merged.maxAttempts));
40
34
  return merged;
41
35
  }
42
- function newConnectionId$1() {
43
- return randomUUID();
44
- }
45
- //#endregion
46
- //#region extensions/whatsapp/src/socket-timing.ts
47
- const DEFAULT_WHATSAPP_SOCKET_TIMING = {
48
- keepAliveIntervalMs: 25e3,
49
- connectTimeoutMs: 6e4,
50
- defaultQueryTimeoutMs: 6e4
51
- };
52
- function positiveInteger(value) {
53
- return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
54
- }
55
- function resolveWhatsAppSocketTiming(cfg, overrides) {
56
- const configured = cfg.web?.whatsapp;
57
- return {
58
- keepAliveIntervalMs: positiveInteger(overrides?.keepAliveIntervalMs) ?? positiveInteger(configured?.keepAliveIntervalMs) ?? DEFAULT_WHATSAPP_SOCKET_TIMING.keepAliveIntervalMs,
59
- connectTimeoutMs: positiveInteger(overrides?.connectTimeoutMs) ?? positiveInteger(configured?.connectTimeoutMs) ?? DEFAULT_WHATSAPP_SOCKET_TIMING.connectTimeoutMs,
60
- defaultQueryTimeoutMs: positiveInteger(overrides?.defaultQueryTimeoutMs) ?? positiveInteger(configured?.defaultQueryTimeoutMs) ?? DEFAULT_WHATSAPP_SOCKET_TIMING.defaultQueryTimeoutMs
61
- };
62
- }
63
- //#endregion
64
- //#region extensions/whatsapp/src/session.ts
65
- const LOGGED_OUT_STATUS$1 = DisconnectReason$1?.loggedOut ?? 401;
66
- const WHATSAPP_WEBSOCKET_PROXY_TARGET = "https://mmg.whatsapp.net/";
67
- const CREDS_FLUSH_TIMEOUT_MESSAGE = "Queued WhatsApp creds save did not finish before auth bootstrap; skipping repair and continuing with primary creds.";
68
- function enqueueSaveCreds(authDir, saveCreds, logger) {
69
- enqueueCredsSave(authDir, () => safeSaveCreds(authDir, saveCreds, logger), (err) => {
70
- logger.warn({ error: String(err) }, "WhatsApp creds save queue error");
71
- });
72
- }
73
- async function safeSaveCreds(authDir, saveCreds, logger) {
74
- try {
75
- const credsPath = resolveWebCredsPath(authDir);
76
- const backupPath = resolveWebCredsBackupPath(authDir);
77
- const raw = readCredsJsonRaw(credsPath);
78
- if (raw) try {
79
- JSON.parse(raw);
80
- fs.copyFileSync(credsPath, backupPath);
81
- try {
82
- fs.chmodSync(backupPath, 384);
83
- } catch {}
84
- } catch {}
85
- } catch {}
86
- try {
87
- await Promise.resolve(saveCreds());
88
- } catch (err) {
89
- logger.warn({ error: String(err) }, "failed saving WhatsApp creds");
90
- }
91
- }
92
- async function printTerminalQr(qr) {
93
- const output = await renderQrTerminal(qr, { small: true });
94
- process.stdout.write(output.endsWith("\n") ? output : `${output}\n`);
95
- }
96
- /**
97
- * Create a Baileys socket backed by the multi-file auth store we keep on disk.
98
- * Consumers can opt into QR printing for interactive login flows.
99
- */
100
- async function createWaSocket(printQr, verbose, opts = {}) {
101
- const logger = toPinoLikeLogger(getChildLogger$1({ module: "baileys" }, { level: verbose ? "info" : "silent" }), verbose ? "info" : "silent");
102
- const authDir = resolveUserPath(opts.authDir ?? resolveDefaultWebAuthDir());
103
- await ensureDir(authDir);
104
- const sessionLogger = getChildLogger$1({ module: "web-session" });
105
- if (await waitForCredsSaveQueueWithTimeout(authDir) === "timed_out") sessionLogger.warn({ authDir }, CREDS_FLUSH_TIMEOUT_MESSAGE);
106
- else await restoreCredsFromBackupIfNeeded(authDir);
107
- const { state } = await useMultiFileAuthState(authDir);
108
- const saveCreds = async () => {
109
- await writeCredsJsonAtomically(authDir, state.creds);
110
- };
111
- const { version } = await fetchLatestBaileysVersion();
112
- const agent = await resolveEnvProxyAgent(sessionLogger);
113
- const fetchAgent = await resolveEnvFetchDispatcher(sessionLogger, agent);
114
- const socketTiming = {
115
- keepAliveIntervalMs: opts.keepAliveIntervalMs ?? DEFAULT_WHATSAPP_SOCKET_TIMING.keepAliveIntervalMs,
116
- connectTimeoutMs: opts.connectTimeoutMs ?? DEFAULT_WHATSAPP_SOCKET_TIMING.connectTimeoutMs,
117
- defaultQueryTimeoutMs: opts.defaultQueryTimeoutMs ?? DEFAULT_WHATSAPP_SOCKET_TIMING.defaultQueryTimeoutMs
118
- };
119
- const sock = makeWASocket({
120
- auth: {
121
- creds: state.creds,
122
- keys: makeCacheableSignalKeyStore(state.keys, logger)
123
- },
124
- version,
125
- logger,
126
- printQRInTerminal: false,
127
- browser: [
128
- "openclaw",
129
- "cli",
130
- VERSION
131
- ],
132
- syncFullHistory: false,
133
- markOnlineOnConnect: false,
134
- ...socketTiming,
135
- agent,
136
- fetchAgent
137
- });
138
- sock.ev.on("creds.update", () => enqueueSaveCreds(authDir, saveCreds, sessionLogger));
139
- sock.ev.on("connection.update", async (update) => {
140
- try {
141
- const { connection, lastDisconnect, qr } = update;
142
- if (qr) {
143
- opts.onQr?.(qr);
144
- if (printQr) {
145
- console.log("Open the WhatsApp app, go to Linked Devices, then scan this QR:");
146
- printTerminalQr(qr).catch((err) => {
147
- sessionLogger.warn({ error: String(err) }, "failed rendering WhatsApp QR");
148
- });
149
- }
150
- }
151
- if (connection === "close") {
152
- if (getStatusCode(lastDisconnect?.error) === LOGGED_OUT_STATUS$1) console.error(danger(`WhatsApp session logged out. Run: ${formatCliCommand("openclaw channels login")}`));
153
- }
154
- if (connection === "open" && verbose) console.log(success("WhatsApp Web connected."));
155
- } catch (err) {
156
- sessionLogger.error({ error: String(err) }, "connection.update handler error");
157
- }
158
- });
159
- if (sock.ws && typeof sock.ws.on === "function") sock.ws.on("error", (err) => {
160
- sessionLogger.error({ error: String(err) }, "WebSocket error");
161
- });
162
- return sock;
163
- }
164
- async function resolveEnvProxyAgent(logger) {
165
- if (!shouldUseEnvHttpProxyForUrl(WHATSAPP_WEBSOCKET_PROXY_TARGET)) return;
166
- const proxyUrl = resolveEnvHttpProxyUrl("https");
167
- if (!proxyUrl) return;
168
- try {
169
- const agent = new HttpsProxyAgent(proxyUrl);
170
- logger.info("Using ambient env proxy for WhatsApp WebSocket connection");
171
- return agent;
172
- } catch (error) {
173
- logger.warn({ error: String(error) }, "Failed to initialize env proxy agent for WhatsApp WebSocket connection");
174
- return;
175
- }
176
- }
177
- async function resolveEnvFetchDispatcher(logger, agent) {
178
- const proxyUrl = resolveProxyUrlFromAgent(agent);
179
- const envProxyUrl = resolveEnvHttpsProxyUrl();
180
- if (!proxyUrl && !envProxyUrl) return;
181
- try {
182
- const { EnvHttpProxyAgent, ProxyAgent } = await import("undici");
183
- return proxyUrl ? new ProxyAgent({
184
- allowH2: false,
185
- uri: proxyUrl
186
- }) : new EnvHttpProxyAgent({ allowH2: false });
187
- } catch (error) {
188
- logger.warn({ error: String(error) }, "Failed to initialize env proxy dispatcher for WhatsApp media uploads");
189
- return;
190
- }
191
- }
192
- function resolveProxyUrlFromAgent(agent) {
193
- if (typeof agent !== "object" || agent === null || !("proxy" in agent)) return;
194
- const proxy = agent.proxy;
195
- if (proxy instanceof URL) return proxy.toString();
196
- return typeof proxy === "string" && proxy.length > 0 ? proxy : void 0;
197
- }
198
- function resolveEnvHttpsProxyUrl(env = process.env) {
199
- const lowerHttpsProxy = normalizeEnvProxyValue(env.https_proxy);
200
- const lowerHttpProxy = normalizeEnvProxyValue(env.http_proxy);
201
- const httpsProxy = lowerHttpsProxy !== void 0 ? lowerHttpsProxy : normalizeEnvProxyValue(env.HTTPS_PROXY);
202
- const httpProxy = lowerHttpProxy !== void 0 ? lowerHttpProxy : normalizeEnvProxyValue(env.HTTP_PROXY);
203
- return httpsProxy ?? httpProxy ?? void 0;
204
- }
205
- function normalizeEnvProxyValue(value) {
206
- if (typeof value !== "string") return;
207
- const trimmed = value.trim();
208
- return trimmed.length > 0 ? trimmed : null;
209
- }
210
- async function waitForWaConnection(sock) {
211
- return new Promise((resolve, reject) => {
212
- const evWithOff = sock.ev;
213
- const handler = (...args) => {
214
- const update = args[0] ?? {};
215
- if (update.connection === "open") {
216
- evWithOff.off?.("connection.update", handler);
217
- resolve();
218
- }
219
- if (update.connection === "close") {
220
- evWithOff.off?.("connection.update", handler);
221
- reject(update.lastDisconnect ?? /* @__PURE__ */ new Error("Connection closed"));
222
- }
223
- };
224
- sock.ev.on("connection.update", handler);
225
- });
226
- }
227
36
  function newConnectionId() {
228
37
  return randomUUID();
229
38
  }
@@ -593,4 +402,4 @@ var WhatsAppConnectionController = class {
593
402
  }
594
403
  };
595
404
  //#endregion
596
- export { waitForWhatsAppLoginResult as a, waitForWaConnection as c, DEFAULT_RECONNECT_POLICY as d, computeBackoff as f, sleepWithAbort as g, resolveReconnectPolicy as h, closeWaSocketSoon as i, resolveWhatsAppSocketTiming as l, resolveHeartbeatSeconds as m, WhatsAppConnectionController as n, createWaSocket as o, newConnectionId$1 as p, closeWaSocket as r, newConnectionId as s, WHATSAPP_LOGGED_OUT_QR_MESSAGE as t, renderQrTerminal as u };
405
+ export { waitForWhatsAppLoginResult as a, newConnectionId as c, sleepWithAbort as d, closeWaSocketSoon as i, resolveHeartbeatSeconds as l, WhatsAppConnectionController as n, DEFAULT_RECONNECT_POLICY as o, closeWaSocket as r, computeBackoff as s, WHATSAPP_LOGGED_OUT_QR_MESSAGE as t, resolveReconnectPolicy as u };
@@ -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-B0efQf9P.js";
6
6
  import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-BNCbgnmy.js";
7
7
  import { t as resolveWhatsAppRuntimeGroupPolicy$1 } from "./runtime-group-policy-Gp1lQ0at.js";
8
- import { t as __testing } from "./access-control-CTj7P7WP.js";
8
+ import { t as __testing } from "./access-control-hFVqAWSd.js";
9
9
  //#region extensions/whatsapp/contract-api.ts
10
10
  const canonicalizeLegacySessionKey = canonicalizeLegacySessionKey$1;
11
11
  const isLegacyGroupSessionKey = isLegacyGroupSessionKey$1;
@@ -1,2 +1,2 @@
1
- import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-DnCdvoYD.js";
1
+ import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-Bm0S67yH.js";
2
2
  export { detectWhatsAppLegacyStateMigrations };
@@ -1,5 +1,5 @@
1
1
  import { n as getStatusCode, t as formatError } from "./session-errors-CSuKZPub.js";
2
2
  import { t as createWhatsAppLoginTool } from "./agent-tools-login-DpRxLNRB.js";
3
- import { a as getWebAuthAgeMs, b as webAuthExists, c as pickWebChannel, h as readWebSelfId, o as logWebSelfId, s as logoutWeb, t as WA_WEB_AUTH_DIR } from "./auth-store-BNZmNP-s.js";
4
- import { t as getActiveWebListener } from "./active-listener-N7GFKsuN.js";
3
+ import { a as getWebAuthAgeMs, b as webAuthExists, c as pickWebChannel, h as readWebSelfId, o as logWebSelfId, s as logoutWeb, t as WA_WEB_AUTH_DIR } from "./auth-store-CG0eSZ0D.js";
4
+ import { t as getActiveWebListener } from "./active-listener-DTbKS-j-.js";
5
5
  export { WA_WEB_AUTH_DIR, createWhatsAppLoginTool, formatError, getActiveWebListener, getStatusCode, getWebAuthAgeMs, logWebSelfId, logoutWeb, pickWebChannel, readWebSelfId, webAuthExists };
@@ -1,7 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-RkAeH_Qm.js";
2
2
  import { a as resolveWhatsAppAccount } from "./accounts-BDqgpFEB.js";
3
- import { y as restoreCredsFromBackupIfNeeded } from "./auth-store-BNZmNP-s.js";
4
- import { a as waitForWhatsAppLoginResult, i as closeWaSocketSoon, l as resolveWhatsAppSocketTiming, o as createWaSocket, u as renderQrTerminal } from "./connection-controller-BCIuChXD.js";
3
+ import { y as restoreCredsFromBackupIfNeeded } from "./auth-store-CG0eSZ0D.js";
4
+ import { a as renderQrTerminal, i as resolveWhatsAppSocketTiming, t as createWaSocket } from "./session-BXC3R43P.js";
5
+ import { a as waitForWhatsAppLoginResult, i as closeWaSocketSoon } from "./connection-controller-d8D2iUBj.js";
5
6
  import { logInfo } from "openclaw/plugin-sdk/text-runtime";
6
7
  import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
7
8
  import { danger, defaultRuntime, success } from "openclaw/plugin-sdk/runtime-env";