@openclaw/whatsapp 2026.7.1 → 2026.7.2-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{access-control-DYE5dXna.js → access-control-DazDX3RB.js} +4 -4
- package/dist/{account-config-6PTOSfaI.js → account-config-LiT9wWH9.js} +4 -8
- package/dist/{accounts-4YgwroRU.js → accounts-CKOFMPf-.js} +2 -3
- package/dist/{action-runtime-DPahAqxV.js → action-runtime-Bf-12TIH.js} +3 -3
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{active-listener-B4SDebQ6.js → active-listener-5kHap439.js} +2 -2
- package/dist/{agent-tools-login-BX7eHgDm.js → agent-tools-login-DfyToBpG.js} +1 -4
- package/dist/api.js +17 -18
- package/dist/{approval-handler.runtime-DNWS4aYQ.js → approval-handler.runtime-CBiGQuZ5.js} +19 -13
- package/dist/approval-reactions-BGQoz25s.js +373 -0
- package/dist/{approval-resolver-DF-lu8k5.js → approval-resolver-DoeBBt22.js} +2 -1
- package/dist/{auth-store-Db-wfApd.js → auth-store-BQi9pZqQ.js} +31 -19
- package/dist/call-tool-api.js +6 -14
- package/dist/{channel-BWp7h1uY.js → channel-DbadDUDD.js} +84 -52
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-CKJHL_Wf.js → channel-react-action-PoRWfP9x.js} +7 -7
- package/dist/{channel.runtime-CAssfx9p.js → channel.runtime-BDDy4Lhz.js} +5 -5
- package/dist/{channel.setup-CURc5rEt.js → channel.setup-BZ-po8fg.js} +4 -5
- package/dist/config-schema-BZ8h1hWA.js +40 -0
- package/dist/{connection-controller-DkbrFSIn.js → connection-controller-C1rwfWb4.js} +52 -12
- package/dist/connection-controller-runtime-context-CbTsqmPT.js +14 -0
- package/dist/contract-api.js +2 -2
- package/dist/{directory-config-Dijefxc3.js → directory-config-CLBQrjtC.js} +3 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +89 -4
- package/dist/{group-session-key-BhC1RQOE.js → group-session-key-CLTZeH_F.js} +31 -3
- package/dist/{identity-Dqft3mFA.js → identity-D7L8LCuH.js} +2 -2
- package/dist/legacy-state-migrations-api.js +1 -1
- package/dist/light-runtime-api.js +4 -4
- package/dist/{login-C48y0jlx.js → login-DGIoToX8.js} +48 -8
- package/dist/{login-qr-BjId7dll.js → login-qr-X-CZHOk9.js} +6 -7
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-DD8bXohk.js → monitor-BZ8QvCeV.js} +145 -188
- package/dist/normalize-C-Z16y7Q.js +2 -0
- package/dist/{normalize-target-bVWjgftN.js → normalize-target-DSZnHkKF.js} +14 -10
- package/dist/{resolve-outbound-target-CcdugbDf.js → resolve-outbound-target-BR97fAbB.js} +1 -1
- package/dist/runtime-api.js +10 -10
- package/dist/{send-C5CpFcBG.js → send-D9Ydnn4o.js} +25 -320
- package/dist/{send-api-DLlXl8CH.js → send-api-W33lI2nR.js} +28 -88
- package/dist/{session-errors-BAj9D2La.js → session-errors-JuazczrA.js} +2 -1
- package/dist/{session-DriaHt7V.js → session-mxWFn0eS.js} +181 -19
- package/dist/session.runtime-Nsqaehbd.js +16 -0
- package/dist/{setup-core-DH-DFPLY.js → setup-core-3aSOoK2T.js} +18 -33
- package/dist/{setup-finalize-c8dl34sO.js → setup-finalize-DBf1jjBj.js} +41 -11
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DlWb0Z09.js → setup-surface-CiKGdNJv.js} +3 -3
- package/dist/{state-migrations-D_BmQUR9.js → state-migrations-CAMTrs2U.js} +1 -8
- package/dist/{targets-runtime-C-GiVn6Y.js → targets-runtime-Bsh0HR9y.js} +13 -6
- package/dist/text-runtime-BTGkMN0o.js +4 -0
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +72 -48
- package/package.json +4 -4
- package/dist/config-schema-mBX2nmn1.js +0 -47
- package/dist/connection-controller-registry-TSX_udJp.js +0 -22
- package/dist/constants.js +0 -2
- package/dist/normalize-Bxwqo-bW.js +0 -2
- package/dist/session.runtime-CyooSQvj.js +0 -12
- package/dist/socket-timing-DhbVFjah.js +0 -77
- package/dist/targets.js +0 -2
- package/dist/text-runtime-DdX6-mC_.js +0 -4
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
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
|
-
import { r as resolveUserPath } from "./text-runtime-
|
|
4
|
-
import { c as resolveComparableIdentity } from "./identity-
|
|
3
|
+
import { r as resolveUserPath } from "./text-runtime-BTGkMN0o.js";
|
|
4
|
+
import { c as resolveComparableIdentity } from "./identity-D7L8LCuH.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { resolveOAuthDir as resolveOAuthDir$1 } from "openclaw/plugin-sdk/state-paths";
|
|
7
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 { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
11
10
|
import fs from "node:fs/promises";
|
|
12
11
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
|
13
12
|
import { enqueueKeyedTask } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
13
|
+
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
14
14
|
//#region extensions/whatsapp/src/creds-persistence.ts
|
|
15
15
|
const CREDS_FILE_MODE = 384;
|
|
16
16
|
const CREDS_SAVE_FLUSH_TIMEOUT_MS = 15e3;
|
|
17
17
|
const credsSaveQueues = /* @__PURE__ */ new Map();
|
|
18
18
|
async function stringifyCreds(creds) {
|
|
19
|
-
const { BufferJSON } = await import("./session.runtime-
|
|
19
|
+
const { BufferJSON } = await import("./session.runtime-Nsqaehbd.js").then((n) => n.o);
|
|
20
20
|
return JSON.stringify(creds, BufferJSON.replacer);
|
|
21
21
|
}
|
|
22
22
|
async function writeWebCredsRawAtomically(params) {
|
|
@@ -130,8 +130,9 @@ function isValidJson(raw) {
|
|
|
130
130
|
return false;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
async function restoreCredsFromBackupIfNeeded(authDir) {
|
|
133
|
+
async function restoreCredsFromBackupIfNeeded(authDir, options) {
|
|
134
134
|
const logger = getChildLogger({ module: "web-session" });
|
|
135
|
+
let restore;
|
|
135
136
|
try {
|
|
136
137
|
const credsPath = resolveWebCredsPath(authDir);
|
|
137
138
|
const backupPath = resolveWebCredsBackupPath(authDir);
|
|
@@ -144,12 +145,21 @@ async function restoreCredsFromBackupIfNeeded(authDir) {
|
|
|
144
145
|
if (raw && isValidJson(raw)) return false;
|
|
145
146
|
const backupRaw = readCredsJsonRaw(backupPath);
|
|
146
147
|
if (!backupRaw || !isValidJson(backupRaw)) return false;
|
|
147
|
-
|
|
148
|
-
filePath: credsPath,
|
|
148
|
+
restore = {
|
|
149
149
|
content: backupRaw,
|
|
150
|
+
credsPath
|
|
151
|
+
};
|
|
152
|
+
} catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
await options?.beforeCredentialPersistence?.();
|
|
156
|
+
try {
|
|
157
|
+
await writeWebCredsRawAtomically({
|
|
158
|
+
filePath: restore.credsPath,
|
|
159
|
+
content: restore.content,
|
|
150
160
|
tempPrefix: ".creds.restore"
|
|
151
161
|
});
|
|
152
|
-
logger.warn({ credsPath }, "restored corrupted WhatsApp creds.json from backup");
|
|
162
|
+
logger.warn({ credsPath: restore.credsPath }, "restored corrupted WhatsApp creds.json from backup");
|
|
153
163
|
return true;
|
|
154
164
|
} catch {}
|
|
155
165
|
return false;
|
|
@@ -230,13 +240,13 @@ function isBaileysAuthFileName(name) {
|
|
|
230
240
|
if (!name.endsWith(".json")) return false;
|
|
231
241
|
return /^(app-state-sync|session|sender-key|pre-key)-/.test(name);
|
|
232
242
|
}
|
|
233
|
-
async function clearBaileysAuthFiles(authDir) {
|
|
243
|
+
async function clearBaileysAuthFiles(authDir, beforeCredentialPersistence) {
|
|
234
244
|
const rootStats = await fs.lstat(authDir).catch(() => null);
|
|
235
245
|
if (!rootStats?.isDirectory() || rootStats.isSymbolicLink()) return;
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
const credentialFiles = (await fs.readdir(authDir, { withFileTypes: true })).filter((entry) => entry.isFile() && isBaileysAuthFileName(entry.name));
|
|
247
|
+
if (credentialFiles.length === 0) return;
|
|
248
|
+
await beforeCredentialPersistence?.();
|
|
249
|
+
await Promise.all(credentialFiles.map(async (entry) => {
|
|
240
250
|
await fs.rm(path.join(authDir, entry.name), { force: true });
|
|
241
251
|
}));
|
|
242
252
|
}
|
|
@@ -302,14 +312,16 @@ async function logoutWeb(params) {
|
|
|
302
312
|
runtime.log(info("Skipped WhatsApp Web credential cleanup outside the managed legacy auth directory."));
|
|
303
313
|
return false;
|
|
304
314
|
}
|
|
305
|
-
await clearBaileysAuthFiles(resolvedAuthDir);
|
|
315
|
+
await clearBaileysAuthFiles(resolvedAuthDir, params.beforeCredentialPersistence);
|
|
306
316
|
} else {
|
|
307
317
|
const ownership = await classifyWebAuthDirOwnership(resolvedAuthDir);
|
|
308
|
-
if (ownership.kind === "owned")
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
318
|
+
if (ownership.kind === "owned") {
|
|
319
|
+
await params.beforeCredentialPersistence?.();
|
|
320
|
+
await fs.rm(ownership.authDir, {
|
|
321
|
+
recursive: true,
|
|
322
|
+
force: true
|
|
323
|
+
});
|
|
324
|
+
} else if (ownership.kind === "unsafe-owned") {
|
|
313
325
|
runtime.log(info("Skipped WhatsApp Web credential cleanup because the auth directory crosses a symlink boundary."));
|
|
314
326
|
return false;
|
|
315
327
|
} else {
|
package/dist/call-tool-api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
2
|
-
import {
|
|
3
|
-
import { o as resolveJidToE164 } from "./targets-runtime-
|
|
1
|
+
import { a as resolveWhatsAppAccount } from "./accounts-CKOFMPf-.js";
|
|
2
|
+
import { n as getWhatsAppConnectionController } from "./connection-controller-runtime-context-CbTsqmPT.js";
|
|
3
|
+
import { o as resolveJidToE164 } from "./targets-runtime-Bsh0HR9y.js";
|
|
4
4
|
import { createActionGate, stringEnum } from "openclaw/plugin-sdk/channel-actions";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { resolveOAuthDir } from "openclaw/plugin-sdk/state-paths";
|
|
@@ -11,6 +11,7 @@ import { Type } from "typebox";
|
|
|
11
11
|
import fs from "node:fs/promises";
|
|
12
12
|
import { mulawToPcm } from "openclaw/plugin-sdk/realtime-voice";
|
|
13
13
|
import { detectBinary } from "openclaw/plugin-sdk/setup-tools";
|
|
14
|
+
import { jsonResult as jsonResult$1 } from "openclaw/plugin-sdk/tool-results";
|
|
14
15
|
//#region extensions/whatsapp/src/agent-tools-call.ts
|
|
15
16
|
const MEOWCALLER_COMMAND = "meowcaller";
|
|
16
17
|
const SESSION_DATABASE = "wa-voip.db";
|
|
@@ -33,15 +34,6 @@ const defaultDependencies = {
|
|
|
33
34
|
detectMeowCaller: () => detectBinary(MEOWCALLER_COMMAND),
|
|
34
35
|
resolveStateDir: (accountId) => path.join(resolveOAuthDir(), "whatsapp-calls", normalizeAccountId(accountId))
|
|
35
36
|
};
|
|
36
|
-
function jsonResult$1(payload) {
|
|
37
|
-
return {
|
|
38
|
-
content: [{
|
|
39
|
-
type: "text",
|
|
40
|
-
text: JSON.stringify(payload, null, 2)
|
|
41
|
-
}],
|
|
42
|
-
details: payload
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
37
|
async function isRegularFile(filePath) {
|
|
46
38
|
try {
|
|
47
39
|
return (await fs.stat(filePath)).isFile();
|
|
@@ -101,14 +93,14 @@ async function resolveRequesterE164(params) {
|
|
|
101
93
|
cfg: params.cfg,
|
|
102
94
|
accountId: params.accountId
|
|
103
95
|
});
|
|
104
|
-
const lidLookup =
|
|
96
|
+
const lidLookup = getWhatsAppConnectionController(params.accountId)?.getCurrentSock()?.signalRepository.lidMapping;
|
|
105
97
|
return await resolveJidToE164(senderId, {
|
|
106
98
|
authDir: account.authDir,
|
|
107
99
|
lidLookup
|
|
108
100
|
});
|
|
109
101
|
}
|
|
110
102
|
async function resolveLinkedWhatsAppSelfE164(params) {
|
|
111
|
-
const controller =
|
|
103
|
+
const controller = getWhatsAppConnectionController(params.accountId);
|
|
112
104
|
if (!controller) return null;
|
|
113
105
|
const identity = controller.getSelfIdentity();
|
|
114
106
|
if (!identity) return null;
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import { r as resolveDefaultWhatsAppAccountId, t as listAccountIds } from "./account-ids-CB5SOWjc.js";
|
|
2
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
3
|
-
import { c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, n as isWhatsAppNewsletterJid, o as normalizeWhatsAppAllowFromEntry, s as normalizeWhatsAppMessagingTarget, t as isWhatsAppGroupJid } from "./normalize-target-
|
|
4
|
-
import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-
|
|
5
|
-
import { a as normalizeWhatsAppOutboundPayload,
|
|
6
|
-
import "./normalize-Bxwqo-bW.js";
|
|
2
|
+
import { a as resolveWhatsAppAccount } from "./accounts-CKOFMPf-.js";
|
|
3
|
+
import { c as normalizeWhatsAppTarget, i as looksLikeWhatsAppTargetId, n as isWhatsAppNewsletterJid, o as normalizeWhatsAppAllowFromEntry, s as normalizeWhatsAppMessagingTarget, t as isWhatsAppGroupJid } from "./normalize-target-DSZnHkKF.js";
|
|
4
|
+
import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-BR97fAbB.js";
|
|
5
|
+
import { a as normalizeWhatsAppOutboundPayload, i as sendTypingWhatsApp, n as sendPollWhatsApp, o as normalizeWhatsAppPayloadText, s as normalizeWhatsAppPayloadTextPreservingIndentation, t as sendMessageWhatsApp, u as resolveWhatsAppReactionLevel } from "./send-D9Ydnn4o.js";
|
|
7
6
|
import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
8
|
-
import
|
|
9
|
-
import "./
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
7
|
+
import "./normalize-C-Z16y7Q.js";
|
|
8
|
+
import { s as toWhatsappJid } from "./targets-runtime-Bsh0HR9y.js";
|
|
9
|
+
import "./text-runtime-BTGkMN0o.js";
|
|
10
|
+
import { t as createWhatsAppLoginTool } from "./agent-tools-login-DfyToBpG.js";
|
|
11
|
+
import { c as getWhatsAppApprovalApprovers, l as whatsappApprovalAuth, s as lookupInboundMessageMetaForTarget, t as resolveWhatsAppGroupSessionKey } from "./group-session-key-CLTZeH_F.js";
|
|
12
12
|
import { t as whatsappCommandPolicy } from "./command-policy-BIOSHySD.js";
|
|
13
|
-
import { a as resolveWhatsAppGroupRequireMention,
|
|
14
|
-
import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-
|
|
15
|
-
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-
|
|
13
|
+
import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, r as loadWhatsAppChannelRuntime, s as formatWhatsAppConfigAllowFromEntries, t as whatsappSetupAdapter } from "./setup-core-3aSOoK2T.js";
|
|
14
|
+
import { f as readWebAuthExistsForDecision, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-BQi9pZqQ.js";
|
|
15
|
+
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-CAMTrs2U.js";
|
|
16
16
|
import { createActionGate as createActionGate$1 } from "openclaw/plugin-sdk/channel-actions";
|
|
17
|
-
import {
|
|
17
|
+
import { normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-core";
|
|
18
18
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
19
|
-
import {
|
|
20
|
-
import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord as isRecord$1 } from "openclaw/plugin-sdk/status-helpers";
|
|
19
|
+
import { asString, collectIssuesForEnabledAccounts, createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord as isRecord$1, readAccountStatusSnapshot } from "openclaw/plugin-sdk/status-helpers";
|
|
21
20
|
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
22
21
|
import { buildChannelOutboundSessionRoute } from "openclaw/plugin-sdk/core";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
22
|
+
import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
23
|
+
import { sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
|
|
25
24
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
|
|
26
25
|
import { buildDmGroupAccountAllowlistAdapter } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
27
26
|
import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
27
|
+
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
28
28
|
import { createChannelApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
|
|
29
29
|
import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
30
30
|
import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver, createNativeApprovalChannelRouteGates, createNativeApprovalForwardingFallbackSuppressor } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
31
|
+
import { buildApprovalReactionPromptPayloadForRequest } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
32
|
+
import { buildTypedApprovalPresentation } from "openclaw/plugin-sdk/approval-reply-runtime";
|
|
31
33
|
import { chunkText } from "openclaw/plugin-sdk/reply-chunking";
|
|
32
34
|
import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
33
|
-
import { sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
|
|
34
35
|
//#region extensions/whatsapp/src/approval-native.ts
|
|
35
36
|
const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
|
|
36
37
|
function isWhatsAppApprovalTransportEnabled(params) {
|
|
@@ -122,10 +123,26 @@ const shouldSuppressWhatsAppForwardingFallback = createNativeApprovalForwardingF
|
|
|
122
123
|
resolveApproverDmTargets: resolveWhatsAppApproverDmTargets
|
|
123
124
|
});
|
|
124
125
|
function buildWhatsAppExecPendingPayload(params) {
|
|
125
|
-
|
|
126
|
+
const payload = buildApprovalReactionPromptPayloadForRequest(params);
|
|
127
|
+
return {
|
|
128
|
+
...payload,
|
|
129
|
+
presentation: buildTypedApprovalPresentation({
|
|
130
|
+
approvalId: params.request.id,
|
|
131
|
+
approvalKind: "exec",
|
|
132
|
+
allowedDecisions: payload.allowedDecisions
|
|
133
|
+
})
|
|
134
|
+
};
|
|
126
135
|
}
|
|
127
136
|
function buildWhatsAppPluginPendingPayload(params) {
|
|
128
|
-
|
|
137
|
+
const payload = buildApprovalReactionPromptPayloadForRequest(params);
|
|
138
|
+
return {
|
|
139
|
+
...payload,
|
|
140
|
+
presentation: buildTypedApprovalPresentation({
|
|
141
|
+
approvalId: params.request.id,
|
|
142
|
+
approvalKind: "plugin",
|
|
143
|
+
allowedDecisions: payload.allowedDecisions
|
|
144
|
+
})
|
|
145
|
+
};
|
|
129
146
|
}
|
|
130
147
|
const whatsappApprovalCapability = createChannelApprovalCapability({
|
|
131
148
|
...whatsappApprovalAuth,
|
|
@@ -201,12 +218,13 @@ const whatsappApprovalCapability = createChannelApprovalCapability({
|
|
|
201
218
|
accountId,
|
|
202
219
|
nativeSessionOnly: true
|
|
203
220
|
}),
|
|
204
|
-
shouldHandle: ({ cfg, accountId, context, request }) => Boolean(context) && shouldHandleWhatsAppApprovalRequest({
|
|
221
|
+
shouldHandle: ({ cfg, accountId, context, approvalKind, request }) => Boolean(context) && shouldHandleWhatsAppApprovalRequest({
|
|
205
222
|
cfg,
|
|
206
223
|
accountId,
|
|
224
|
+
approvalKind,
|
|
207
225
|
request
|
|
208
226
|
}),
|
|
209
|
-
load: async () => (await import("./approval-handler.runtime-
|
|
227
|
+
load: async () => (await import("./approval-handler.runtime-CBiGQuZ5.js")).whatsappApprovalNativeRuntime
|
|
210
228
|
})
|
|
211
229
|
});
|
|
212
230
|
//#endregion
|
|
@@ -262,14 +280,7 @@ const WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS = ["sendWhatsApp"];
|
|
|
262
280
|
function resolveQuoteLookupAccountId(cfg, accountId) {
|
|
263
281
|
const explicitAccountId = normalizeOptionalAccountId(accountId);
|
|
264
282
|
if (explicitAccountId) return explicitAccountId;
|
|
265
|
-
|
|
266
|
-
return resolveListedDefaultAccountId({
|
|
267
|
-
accountIds: listCombinedAccountIds({
|
|
268
|
-
configuredAccountIds: channelCfg?.accounts && typeof channelCfg.accounts === "object" ? Object.keys(channelCfg.accounts).filter(Boolean) : [],
|
|
269
|
-
fallbackAccountIdWhenEmpty: DEFAULT_ACCOUNT_ID
|
|
270
|
-
}),
|
|
271
|
-
configuredDefaultAccountId: normalizeOptionalAccountId(channelCfg?.defaultAccount)
|
|
272
|
-
});
|
|
283
|
+
return resolveDefaultWhatsAppAccountId(cfg ?? {});
|
|
273
284
|
}
|
|
274
285
|
function createWhatsAppOutboundBase({ chunker, sendMessageWhatsApp, sendPollWhatsApp, shouldLogVerbose, resolveTarget, normalizeText = normalizeWhatsAppPayloadText, skipEmptyText = true }) {
|
|
275
286
|
const resolveQuotedMessageKey = (params) => {
|
|
@@ -379,6 +390,7 @@ function createWhatsAppOutboundBase({ chunker, sendMessageWhatsApp, sendPollWhat
|
|
|
379
390
|
}
|
|
380
391
|
//#endregion
|
|
381
392
|
//#region extensions/whatsapp/src/channel-outbound.ts
|
|
393
|
+
const loadWhatsAppApprovalReactionsModule = createLazyRuntimeModule(() => import("./approval-reactions-BGQoz25s.js").then((n) => n.t));
|
|
382
394
|
function normalizeWhatsAppChannelPayloadText(text) {
|
|
383
395
|
return normalizeWhatsAppPayloadTextPreservingIndentation(text);
|
|
384
396
|
}
|
|
@@ -386,6 +398,15 @@ function normalizeWhatsAppChannelSendText(text) {
|
|
|
386
398
|
const normalized = normalizeWhatsAppChannelPayloadText(text);
|
|
387
399
|
return normalized.trim() ? normalized : "";
|
|
388
400
|
}
|
|
401
|
+
async function prepareWhatsAppApprovalPayloadForDelivery(params) {
|
|
402
|
+
return (await loadWhatsAppApprovalReactionsModule()).prepareWhatsAppApprovalPayloadForDelivery({
|
|
403
|
+
payload: params.payload,
|
|
404
|
+
presentation: params.presentation
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
async function registerDeliveredWhatsAppApprovalPayload(params) {
|
|
408
|
+
(await loadWhatsAppApprovalReactionsModule()).registerWhatsAppApprovalReactionTargetForDeliveredPayload(params);
|
|
409
|
+
}
|
|
389
410
|
const whatsappChannelOutbound = {
|
|
390
411
|
...createWhatsAppOutboundBase({
|
|
391
412
|
chunker: chunkText,
|
|
@@ -403,6 +424,8 @@ const whatsappChannelOutbound = {
|
|
|
403
424
|
normalizeText: normalizeWhatsAppChannelSendText
|
|
404
425
|
}),
|
|
405
426
|
sendTextOnlyErrorPayloads: true,
|
|
427
|
+
renderPresentation: prepareWhatsAppApprovalPayloadForDelivery,
|
|
428
|
+
afterDeliverPayload: registerDeliveredWhatsAppApprovalPayload,
|
|
406
429
|
normalizePayload: ({ payload }) => ({
|
|
407
430
|
...payload,
|
|
408
431
|
text: normalizeWhatsAppChannelPayloadText(payload.text)
|
|
@@ -441,6 +464,23 @@ const whatsappMessageAdapter = defineChannelMessageAdapter({
|
|
|
441
464
|
} }
|
|
442
465
|
});
|
|
443
466
|
//#endregion
|
|
467
|
+
//#region extensions/whatsapp/src/group-intro.ts
|
|
468
|
+
const WHATSAPP_GROUP_INTRO_HINT = "WhatsApp IDs: SenderId is the participant JID (group participant id).";
|
|
469
|
+
/**
|
|
470
|
+
* @deprecated Core never consumed the group intro hint adapter; this export
|
|
471
|
+
* remains only for the plugin API surface and is removed after the next
|
|
472
|
+
* release train together with ChannelGroupAdapter.resolveGroupIntroHint.
|
|
473
|
+
*/
|
|
474
|
+
function resolveWhatsAppGroupIntroHint() {
|
|
475
|
+
return WHATSAPP_GROUP_INTRO_HINT;
|
|
476
|
+
}
|
|
477
|
+
function resolveWhatsAppMentionStripRegexes(ctx) {
|
|
478
|
+
const selfE164 = (ctx.To ?? "").replace(/^whatsapp:/i, "");
|
|
479
|
+
if (!selfE164) return [];
|
|
480
|
+
const escaped = selfE164.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
481
|
+
return [new RegExp(escaped, "g"), new RegExp(`@${escaped}`, "g")];
|
|
482
|
+
}
|
|
483
|
+
//#endregion
|
|
444
484
|
//#region extensions/whatsapp/src/heartbeat.ts
|
|
445
485
|
async function checkWhatsAppHeartbeatReady(params) {
|
|
446
486
|
if (params.cfg.web?.enabled === false) return {
|
|
@@ -501,23 +541,16 @@ function resolveWhatsAppOutboundSessionRoute(params) {
|
|
|
501
541
|
}
|
|
502
542
|
//#endregion
|
|
503
543
|
//#region extensions/whatsapp/src/status-issues.ts
|
|
544
|
+
const WHATSAPP_ACCOUNT_STATUS_FIELDS = [
|
|
545
|
+
"statusState",
|
|
546
|
+
"linked",
|
|
547
|
+
"reconnectAttempts",
|
|
548
|
+
"lastDisconnect",
|
|
549
|
+
"lastInboundAt",
|
|
550
|
+
"lastError",
|
|
551
|
+
"healthState"
|
|
552
|
+
];
|
|
504
553
|
const RECENT_DISCONNECT_WARNING_WINDOW_MS = 900 * 1e3;
|
|
505
|
-
function readWhatsAppAccountStatus(value) {
|
|
506
|
-
if (!isRecord$1(value)) return null;
|
|
507
|
-
return {
|
|
508
|
-
accountId: value.accountId,
|
|
509
|
-
statusState: value.statusState,
|
|
510
|
-
enabled: value.enabled,
|
|
511
|
-
linked: value.linked,
|
|
512
|
-
connected: value.connected,
|
|
513
|
-
running: value.running,
|
|
514
|
-
reconnectAttempts: value.reconnectAttempts,
|
|
515
|
-
lastDisconnect: value.lastDisconnect,
|
|
516
|
-
lastInboundAt: value.lastInboundAt,
|
|
517
|
-
lastError: value.lastError,
|
|
518
|
-
healthState: value.healthState
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
554
|
function readLastDisconnect(value) {
|
|
522
555
|
if (typeof value === "string") {
|
|
523
556
|
const error = asString(value);
|
|
@@ -539,7 +572,7 @@ function isRecentDisconnect(disconnect, now = Date.now()) {
|
|
|
539
572
|
function collectWhatsAppStatusIssues(accounts) {
|
|
540
573
|
return collectIssuesForEnabledAccounts({
|
|
541
574
|
accounts,
|
|
542
|
-
readAccount:
|
|
575
|
+
readAccount: (value) => readAccountStatusSnapshot(value, WHATSAPP_ACCOUNT_STATUS_FIELDS),
|
|
543
576
|
collectIssues: ({ account, accountId, issues }) => {
|
|
544
577
|
const linked = account.linked === true;
|
|
545
578
|
const statusState = asString(account.statusState);
|
|
@@ -624,8 +657,8 @@ function collectWhatsAppStatusIssues(accounts) {
|
|
|
624
657
|
}
|
|
625
658
|
//#endregion
|
|
626
659
|
//#region extensions/whatsapp/src/channel.ts
|
|
627
|
-
const loadWhatsAppDirectoryConfig = createLazyRuntimeModule(() => import("./directory-config-
|
|
628
|
-
const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-
|
|
660
|
+
const loadWhatsAppDirectoryConfig = createLazyRuntimeModule(() => import("./directory-config-CLBQrjtC.js").then((n) => n.t));
|
|
661
|
+
const loadWhatsAppChannelReactAction = createLazyRuntimeModule(() => import("./channel-react-action-PoRWfP9x.js"));
|
|
629
662
|
function resolveWhatsAppTargetInfo(raw) {
|
|
630
663
|
const normalized = normalizeWhatsAppTarget(raw);
|
|
631
664
|
if (!normalized) return null;
|
|
@@ -651,8 +684,7 @@ const whatsappPlugin = createChatChannelPlugin({
|
|
|
651
684
|
...createWhatsAppPluginBase({
|
|
652
685
|
groups: {
|
|
653
686
|
resolveRequireMention: resolveWhatsAppGroupRequireMention,
|
|
654
|
-
resolveToolPolicy: resolveWhatsAppGroupToolPolicy
|
|
655
|
-
resolveGroupIntroHint: resolveWhatsAppGroupIntroHint
|
|
687
|
+
resolveToolPolicy: resolveWhatsAppGroupToolPolicy
|
|
656
688
|
},
|
|
657
689
|
setupWizard: whatsappSetupWizardProxy,
|
|
658
690
|
setup: whatsappSetupAdapter,
|
|
@@ -895,4 +927,4 @@ const whatsappPlugin = createChatChannelPlugin({
|
|
|
895
927
|
}
|
|
896
928
|
});
|
|
897
929
|
//#endregion
|
|
898
|
-
export {
|
|
930
|
+
export { resolveWhatsAppGroupIntroHint as n, WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS as r, whatsappPlugin as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as WhatsAppChannelConfigSchema } from "./config-schema-
|
|
1
|
+
import { t as WhatsAppChannelConfigSchema } from "./config-schema-BZ8h1hWA.js";
|
|
2
2
|
export { WhatsAppChannelConfigSchema };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as whatsappPlugin } from "./channel-
|
|
1
|
+
import { t as whatsappPlugin } from "./channel-DbadDUDD.js";
|
|
2
2
|
export { whatsappPlugin };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-
|
|
2
|
-
import { c as normalizeWhatsAppTarget, t as isWhatsAppGroupJid } from "./normalize-target-
|
|
3
|
-
import { r as resolveAuthorizedWhatsAppOutboundTarget, t as handleWhatsAppAction } from "./action-runtime-
|
|
4
|
-
import { t as sendMessageWhatsApp } from "./send-
|
|
5
|
-
import "./normalize-
|
|
1
|
+
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-CKOFMPf-.js";
|
|
2
|
+
import { c as normalizeWhatsAppTarget, t as isWhatsAppGroupJid } from "./normalize-target-DSZnHkKF.js";
|
|
3
|
+
import { r as resolveAuthorizedWhatsAppOutboundTarget, t as handleWhatsAppAction } from "./action-runtime-Bf-12TIH.js";
|
|
4
|
+
import { t as sendMessageWhatsApp } from "./send-D9Ydnn4o.js";
|
|
5
|
+
import "./normalize-C-Z16y7Q.js";
|
|
6
6
|
import { jsonResult, readStringOrNumberParam, readStringParam as readStringParam$1, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
|
|
7
7
|
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
|
8
8
|
//#region extensions/whatsapp/src/channel-react-action.ts
|
|
@@ -23,8 +23,8 @@ function readWhatsAppActionChatJid(params) {
|
|
|
23
23
|
return normalizeWhatsAppTarget(params.toolContext.currentChannelId) ?? void 0;
|
|
24
24
|
}
|
|
25
25
|
function extractBase64Payload(encoded) {
|
|
26
|
-
const
|
|
27
|
-
return
|
|
26
|
+
const payload = /^data:[^;]+;base64,(.*)$/i.exec(encoded.trim())?.[1];
|
|
27
|
+
return payload !== void 0 ? payload : encoded;
|
|
28
28
|
}
|
|
29
29
|
function estimateBase64DecodedBytes(encoded) {
|
|
30
30
|
const compact = extractBase64Payload(encoded).replace(/\s/g, "");
|
|
@@ -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-
|
|
3
|
-
import { t as getActiveWebListener$1 } from "./active-listener-
|
|
4
|
-
import { t as monitorWebChannel$1 } from "./monitor-
|
|
5
|
-
import { t as loginWeb$1 } from "./login-
|
|
6
|
-
import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-
|
|
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-BQi9pZqQ.js";
|
|
3
|
+
import { t as getActiveWebListener$1 } from "./active-listener-5kHap439.js";
|
|
4
|
+
import { t as monitorWebChannel$1 } from "./monitor-BZ8QvCeV.js";
|
|
5
|
+
import { t as loginWeb$1 } from "./login-DGIoToX8.js";
|
|
6
|
+
import { whatsappSetupWizard as whatsappSetupWizard$1 } from "./setup-surface-CiKGdNJv.js";
|
|
7
7
|
//#region extensions/whatsapp/src/channel.runtime.ts
|
|
8
8
|
function getActiveWebListener(...args) {
|
|
9
9
|
return getActiveWebListener$1(...args);
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy,
|
|
2
|
-
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-
|
|
1
|
+
import { a as resolveWhatsAppGroupRequireMention, i as whatsappSetupWizardProxy, n as createWhatsAppPluginBase, o as resolveWhatsAppGroupToolPolicy, t as whatsappSetupAdapter } from "./setup-core-3aSOoK2T.js";
|
|
2
|
+
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-CAMTrs2U.js";
|
|
3
3
|
//#region extensions/whatsapp/src/channel.setup.ts
|
|
4
4
|
async function isWhatsAppAuthConfigured(account) {
|
|
5
|
-
const { readWebAuthState } = await import("./auth-store-
|
|
5
|
+
const { readWebAuthState } = await import("./auth-store-BQi9pZqQ.js").then((n) => n.i);
|
|
6
6
|
return await readWebAuthState(account.authDir) === "linked";
|
|
7
7
|
}
|
|
8
8
|
const whatsappSetupPlugin = {
|
|
9
9
|
...createWhatsAppPluginBase({
|
|
10
10
|
groups: {
|
|
11
11
|
resolveRequireMention: resolveWhatsAppGroupRequireMention,
|
|
12
|
-
resolveToolPolicy: resolveWhatsAppGroupToolPolicy
|
|
13
|
-
resolveGroupIntroHint: resolveWhatsAppGroupIntroHint
|
|
12
|
+
resolveToolPolicy: resolveWhatsAppGroupToolPolicy
|
|
14
13
|
},
|
|
15
14
|
setupWizard: whatsappSetupWizardProxy,
|
|
16
15
|
setup: whatsappSetupAdapter,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createChannelConfigUiHints } from "openclaw/plugin-sdk/channel-core";
|
|
2
|
+
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
3
|
+
import { WhatsAppConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region extensions/whatsapp/src/config-schema.ts
|
|
6
|
+
const WhatsAppChannelConfigSchema = buildChannelConfigSchema(WhatsAppConfigSchema, { uiHints: {
|
|
7
|
+
"": {
|
|
8
|
+
label: "WhatsApp",
|
|
9
|
+
help: "WhatsApp channel provider configuration for access policy and message batching behavior. Use this section to tune responsiveness and direct-message routing safety for WhatsApp chats."
|
|
10
|
+
},
|
|
11
|
+
...createChannelConfigUiHints({
|
|
12
|
+
channelLabel: "WhatsApp",
|
|
13
|
+
dmPolicy: { channelKey: "whatsapp" }
|
|
14
|
+
}),
|
|
15
|
+
selfChatMode: {
|
|
16
|
+
label: "WhatsApp Self-Phone Mode",
|
|
17
|
+
help: "Same-phone setup (bot uses your personal WhatsApp number)."
|
|
18
|
+
},
|
|
19
|
+
debounceMs: {
|
|
20
|
+
label: "WhatsApp Message Debounce (ms)",
|
|
21
|
+
help: "Debounce window (ms) for batching rapid consecutive messages from the same sender (0 to disable)."
|
|
22
|
+
},
|
|
23
|
+
...createChannelConfigUiHints({
|
|
24
|
+
channelLabel: "WhatsApp",
|
|
25
|
+
configWrites: true
|
|
26
|
+
}),
|
|
27
|
+
"actions.calls": {
|
|
28
|
+
label: "WhatsApp Voice Calls",
|
|
29
|
+
help: "Expose the experimental requester-bound WhatsApp voice-call tool. Default: false. Requires a separately paired MeowCaller CLI."
|
|
30
|
+
},
|
|
31
|
+
...createChannelConfigUiHints({
|
|
32
|
+
channelLabel: "WhatsApp",
|
|
33
|
+
mentionPatterns: {
|
|
34
|
+
targetDescription: "WhatsApp conversation IDs",
|
|
35
|
+
policyTargetDescription: "WhatsApp conversation IDs such as 123@g.us"
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
} });
|
|
39
|
+
//#endregion
|
|
40
|
+
export { WhatsAppChannelConfigSchema as t };
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { c as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
2
|
+
import { t as WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY } from "./connection-controller-runtime-context-CbTsqmPT.js";
|
|
3
|
+
import { c as logoutWeb, f as readWebAuthExistsForDecision, r as WhatsAppAuthUnstableError } from "./auth-store-BQi9pZqQ.js";
|
|
4
|
+
import { c as resolveComparableIdentity } from "./identity-D7L8LCuH.js";
|
|
5
|
+
import { i as DEFAULT_WHATSAPP_SOCKET_TIMING, r as waitForWaConnection, t as createWaSocket } from "./session-mxWFn0eS.js";
|
|
6
|
+
import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
|
|
7
7
|
import { computeBackoff, info, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
8
|
+
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
8
9
|
import { clamp } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
9
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
+
//#region extensions/whatsapp/src/reconnect.ts
|
|
12
|
+
const DEFAULT_HEARTBEAT_SECONDS = 60;
|
|
10
13
|
const DEFAULT_RECONNECT_POLICY = {
|
|
11
14
|
initialMs: 2e3,
|
|
12
15
|
maxMs: 3e4,
|
|
@@ -17,7 +20,7 @@ const DEFAULT_RECONNECT_POLICY = {
|
|
|
17
20
|
function resolveHeartbeatSeconds(cfg, overrideSeconds) {
|
|
18
21
|
const candidate = overrideSeconds ?? cfg.web?.heartbeatSeconds;
|
|
19
22
|
if (typeof candidate === "number" && candidate > 0) return candidate;
|
|
20
|
-
return
|
|
23
|
+
return DEFAULT_HEARTBEAT_SECONDS;
|
|
21
24
|
}
|
|
22
25
|
function resolveReconnectPolicy(cfg, overrides) {
|
|
23
26
|
const reconnectOverrides = cfg.web?.reconnect ?? {};
|
|
@@ -103,6 +106,21 @@ function closeWaSocketSoon(sock, delayMs = 500) {
|
|
|
103
106
|
closeWaSocket(sock);
|
|
104
107
|
}, delayMs);
|
|
105
108
|
}
|
|
109
|
+
async function waitForLoginSocket(params) {
|
|
110
|
+
if (!params.credentialPersistenceFailure) {
|
|
111
|
+
await params.wait();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const outcome = await Promise.race([params.wait().then(() => ({ kind: "connected" })), params.credentialPersistenceFailure.then((failure) => ({
|
|
115
|
+
kind: "credential-persistence-failed",
|
|
116
|
+
failure
|
|
117
|
+
}))]);
|
|
118
|
+
if (outcome.kind === "credential-persistence-failed") throw outcome.failure.error;
|
|
119
|
+
}
|
|
120
|
+
function throwIfCredentialPersistenceFailed(getFailure) {
|
|
121
|
+
const failure = getFailure?.();
|
|
122
|
+
if (failure) throw failure.error;
|
|
123
|
+
}
|
|
106
124
|
async function waitForWhatsAppLoginResult(params) {
|
|
107
125
|
const wait = params.waitForConnection ?? waitForWaConnection;
|
|
108
126
|
const createSocket = params.createSocket ?? createWaSocket;
|
|
@@ -116,7 +134,10 @@ async function waitForWhatsAppLoginResult(params) {
|
|
|
116
134
|
currentSock = await createSocket(false, params.verbose, {
|
|
117
135
|
authDir: params.authDir,
|
|
118
136
|
...params.socketTiming,
|
|
119
|
-
onQr: params.onQr
|
|
137
|
+
onQr: params.onQr,
|
|
138
|
+
beforeCredentialPersistence: params.beforeCredentialPersistence,
|
|
139
|
+
onCredentialPersistenceError: params.onCredentialPersistenceError,
|
|
140
|
+
onCredentialPersistenceTask: params.onCredentialPersistenceTask
|
|
120
141
|
});
|
|
121
142
|
params.onSocketReplaced?.(currentSock);
|
|
122
143
|
return null;
|
|
@@ -130,8 +151,14 @@ async function waitForWhatsAppLoginResult(params) {
|
|
|
130
151
|
}
|
|
131
152
|
};
|
|
132
153
|
while (true) try {
|
|
133
|
-
await
|
|
154
|
+
await waitForLoginSocket({
|
|
155
|
+
wait: async () => await wait(currentSock, { timeout: "none" }),
|
|
156
|
+
credentialPersistenceFailure: params.credentialPersistenceFailure
|
|
157
|
+
});
|
|
158
|
+
await params.waitForCredentialPersistence?.();
|
|
159
|
+
throwIfCredentialPersistenceFailed(params.getCredentialPersistenceFailure);
|
|
134
160
|
const persistedAuth = await readWebAuthExistsForDecision(params.authDir);
|
|
161
|
+
throwIfCredentialPersistenceFailed(params.getCredentialPersistenceFailure);
|
|
135
162
|
if (persistedAuth.outcome === "unstable") return {
|
|
136
163
|
outcome: "failed",
|
|
137
164
|
message: WHATSAPP_LOGIN_AUTH_UNSTABLE_MESSAGE,
|
|
@@ -169,7 +196,8 @@ async function waitForWhatsAppLoginResult(params) {
|
|
|
169
196
|
if (!await logoutWeb({
|
|
170
197
|
authDir: params.authDir,
|
|
171
198
|
isLegacyAuthDir: params.isLegacyAuthDir,
|
|
172
|
-
runtime: params.runtime
|
|
199
|
+
runtime: params.runtime,
|
|
200
|
+
beforeCredentialPersistence: params.beforeCredentialPersistence
|
|
173
201
|
})) {
|
|
174
202
|
const existingAuth = await readWebAuthExistsForDecision(params.authDir);
|
|
175
203
|
if (existingAuth.outcome === "unstable") return {
|
|
@@ -200,6 +228,7 @@ var WhatsAppConnectionController = class {
|
|
|
200
228
|
constructor(params) {
|
|
201
229
|
this.disconnectRetryController = new AbortController();
|
|
202
230
|
this.current = null;
|
|
231
|
+
this.runtimeContextLease = null;
|
|
203
232
|
this.reconnectAttempts = 0;
|
|
204
233
|
this.lastHandledInboundAt = null;
|
|
205
234
|
this.accountId = params.accountId;
|
|
@@ -304,6 +333,7 @@ var WhatsAppConnectionController = class {
|
|
|
304
333
|
...params.cachedGroupMetadata ? { cachedGroupMetadata: params.cachedGroupMetadata } : {}
|
|
305
334
|
});
|
|
306
335
|
await waitForWaConnection(sock, { timeoutMs: this.socketTiming.connectTimeoutMs });
|
|
336
|
+
const channelRuntime = getWhatsAppRuntime().channel;
|
|
307
337
|
this.socketRef.current = sock;
|
|
308
338
|
connection = createLiveConnection({
|
|
309
339
|
connectionId: params.connectionId,
|
|
@@ -318,7 +348,16 @@ var WhatsAppConnectionController = class {
|
|
|
318
348
|
connection.listener = listener;
|
|
319
349
|
this.current = connection;
|
|
320
350
|
connection.unregisterTransportActivity = this.attachTransportActivityListener(sock);
|
|
321
|
-
|
|
351
|
+
const previousRuntimeContextLease = this.runtimeContextLease;
|
|
352
|
+
this.runtimeContextLease = registerChannelRuntimeContext({
|
|
353
|
+
channelRuntime,
|
|
354
|
+
channelId: "whatsapp",
|
|
355
|
+
accountId: this.accountId,
|
|
356
|
+
capability: WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY,
|
|
357
|
+
context: this,
|
|
358
|
+
abortSignal: this.abortSignal
|
|
359
|
+
});
|
|
360
|
+
previousRuntimeContextLease?.dispose();
|
|
322
361
|
this.startTimers(connection, {
|
|
323
362
|
onHeartbeat: params.onHeartbeat,
|
|
324
363
|
onWatchdogTimeout: params.onWatchdogTimeout
|
|
@@ -441,7 +480,8 @@ var WhatsAppConnectionController = class {
|
|
|
441
480
|
async shutdown() {
|
|
442
481
|
this.stopDisconnectRetries();
|
|
443
482
|
await this.closeCurrentConnection();
|
|
444
|
-
|
|
483
|
+
this.runtimeContextLease?.dispose();
|
|
484
|
+
this.runtimeContextLease = null;
|
|
445
485
|
}
|
|
446
486
|
startTimers(connection, hooks) {
|
|
447
487
|
if (!this.keepAlive) return;
|