@openclaw/whatsapp 2026.7.2-beta.1 → 2026.7.2-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{access-control-DazDX3RB.js → access-control-tjy_em01.js} +1 -1
- package/dist/{accounts-CKOFMPf-.js → accounts-ejK8sXPU.js} +43 -3
- package/dist/action-runtime-api.js +1 -1
- package/dist/{action-runtime-Bf-12TIH.js → action-runtime-p0V390gA.js} +2 -2
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{active-listener-5kHap439.js → active-listener-BbdlXooT.js} +1 -1
- package/dist/api.js +10 -10
- package/dist/{approval-handler.runtime-CBiGQuZ5.js → approval-handler.runtime-BO1oJ-b8.js} +3 -3
- package/dist/{approval-reactions-BGQoz25s.js → approval-reactions-CrZFAyf-.js} +2 -2
- package/dist/call-tool-api.js +2 -2
- package/dist/{channel-D_1cK7-w.js → channel-B2I4Opzb.js} +30 -28
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-PoRWfP9x.js → channel-react-action-CPRQE-s3.js} +3 -3
- package/dist/{channel.runtime-BPrKzcYd.js → channel.runtime-CjkhQzk8.js} +4 -4
- package/dist/{channel.setup-eX64WZDx.js → channel.setup-BMWE9LmN.js} +2 -2
- package/dist/{connection-controller-C1rwfWb4.js → connection-controller-HGaffeFb.js} +183 -22
- package/dist/{connection-controller-runtime-context-CbTsqmPT.js → connection-controller-runtime-context-9mEeAvu1.js} +10 -1
- package/dist/contract-api.js +1 -1
- package/dist/directory-config-BZ775eGX.js +196 -0
- package/dist/directory-contract-api.js +1 -1
- package/dist/{group-session-key-CLTZeH_F.js → group-session-key-Dh8WZun_.js} +1 -1
- package/dist/legacy-state-migrations-api.js +1 -1
- package/dist/light-runtime-api.js +1 -1
- package/dist/{login-DGIoToX8.js → login-ifOXCBjo.js} +3 -3
- package/dist/{login-qr-X-CZHOk9.js → login-qr-DUHzVH_Y.js} +4 -4
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-BKtA0lzq.js → monitor-_jqDKBXj.js} +586 -382
- package/dist/question-reactions-C0qJ6wGA.js +142 -0
- package/dist/runtime-api.js +7 -7
- package/dist/{send-D9Ydnn4o.js → send-SB-4JrVZ.js} +2 -3
- package/dist/{send-api-W33lI2nR.js → send-api-BG0MgoFI.js} +3 -3
- package/dist/{setup-core-BXDFGqky.js → setup-core-BbIgEl2M.js} +3 -3
- package/dist/{setup-finalize-DzOHXnPj.js → setup-finalize-Cc-4iWGj.js} +3 -3
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-5EUmMLHS.js → setup-surface-DhnXEZir.js} +2 -2
- package/dist/{session-mxWFn0eS.js → socket-close-jNGyZY4T.js} +221 -1
- package/dist/{state-migrations-D_BmQUR9.js → state-migrations-CAMTrs2U.js} +1 -8
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
- package/dist/account-config-LiT9wWH9.js +0 -43
- package/dist/constants.js +0 -2
- package/dist/directory-config-CLBQrjtC.js +0 -37
- package/dist/targets.js +0 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
2
|
-
import { t as WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY } from "./connection-controller-runtime-context-
|
|
3
|
-
import { c as logoutWeb, f as readWebAuthExistsForDecision, r as WhatsAppAuthUnstableError } from "./auth-store-BQi9pZqQ.js";
|
|
2
|
+
import { n as WHATSAPP_CONNECTION_OWNER_PENDING_CAPABILITY, t as WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY } from "./connection-controller-runtime-context-9mEeAvu1.js";
|
|
3
|
+
import { c as logoutWeb, f as readWebAuthExistsForDecision, r as WhatsAppAuthUnstableError, w as waitForCredsSaveQueueWithTimeout } from "./auth-store-BQi9pZqQ.js";
|
|
4
4
|
import { c as resolveComparableIdentity } from "./identity-D7L8LCuH.js";
|
|
5
|
-
import {
|
|
5
|
+
import { a as waitForWaConnection, m as acquireWhatsAppGatewayConnectionOwner, o as DEFAULT_WHATSAPP_SOCKET_TIMING, r as createWaSocket, t as closeWhatsAppSocketAndWait } from "./socket-close-jNGyZY4T.js";
|
|
6
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
8
|
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
@@ -89,17 +89,28 @@ function createLiveConnection(params) {
|
|
|
89
89
|
openedAfterRecentInbound: params.openedAfterRecentInbound,
|
|
90
90
|
backgroundTasks: /* @__PURE__ */ new Set(),
|
|
91
91
|
closePromise,
|
|
92
|
-
resolveClose: resolveClosePromise
|
|
92
|
+
resolveClose: resolveClosePromise,
|
|
93
|
+
socketClosed: false
|
|
93
94
|
};
|
|
94
95
|
}
|
|
96
|
+
async function closeWebSocketBestEffort(sock) {
|
|
97
|
+
try {
|
|
98
|
+
await sock.ws?.close?.();
|
|
99
|
+
} catch {}
|
|
100
|
+
}
|
|
95
101
|
function closeWaSocket(sock) {
|
|
96
102
|
try {
|
|
97
103
|
if (typeof sock?.end === "function") {
|
|
98
|
-
sock.end(/* @__PURE__ */ new Error("OpenClaw WhatsApp socket close"));
|
|
104
|
+
Promise.resolve(sock.end(/* @__PURE__ */ new Error("OpenClaw WhatsApp socket close"))).catch(async () => await closeWebSocketBestEffort(sock));
|
|
99
105
|
return;
|
|
100
106
|
}
|
|
101
|
-
sock
|
|
102
|
-
} catch {
|
|
107
|
+
if (sock) closeWebSocketBestEffort(sock);
|
|
108
|
+
} catch {
|
|
109
|
+
if (sock) closeWebSocketBestEffort(sock);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function stoppedControllerError() {
|
|
113
|
+
return /* @__PURE__ */ new Error("WhatsApp connection controller is shutting down");
|
|
103
114
|
}
|
|
104
115
|
function closeWaSocketSoon(sock, delayMs = 500) {
|
|
105
116
|
setTimeout(() => {
|
|
@@ -229,6 +240,15 @@ var WhatsAppConnectionController = class {
|
|
|
229
240
|
this.disconnectRetryController = new AbortController();
|
|
230
241
|
this.current = null;
|
|
231
242
|
this.runtimeContextLease = null;
|
|
243
|
+
this.pendingOwnerContextLease = null;
|
|
244
|
+
this.connectionOwnerLease = null;
|
|
245
|
+
this.retainedOwnerReleaseLease = null;
|
|
246
|
+
this.connectionOwnerLeasePromise = null;
|
|
247
|
+
this.connectionSetupPromise = null;
|
|
248
|
+
this.pendingSocketCleanup = null;
|
|
249
|
+
this.shuttingDown = false;
|
|
250
|
+
this.ownerAcquireAbortController = new AbortController();
|
|
251
|
+
this.setupAbortController = new AbortController();
|
|
232
252
|
this.reconnectAttempts = 0;
|
|
233
253
|
this.lastHandledInboundAt = null;
|
|
234
254
|
this.accountId = params.accountId;
|
|
@@ -249,11 +269,17 @@ var WhatsAppConnectionController = class {
|
|
|
249
269
|
...params.socketTiming
|
|
250
270
|
};
|
|
251
271
|
this.socketRef = { current: null };
|
|
252
|
-
|
|
253
|
-
|
|
272
|
+
const abortSignal = params.abortSignal;
|
|
273
|
+
if (abortSignal) this.abortPromise = new Promise((resolve) => {
|
|
274
|
+
const stop = () => {
|
|
275
|
+
resolve("aborted");
|
|
276
|
+
this.stopDisconnectRetries();
|
|
277
|
+
this.ownerAcquireAbortController.abort(abortSignal.reason);
|
|
278
|
+
this.setupAbortController.abort(abortSignal.reason);
|
|
279
|
+
};
|
|
280
|
+
if (abortSignal.aborted) stop();
|
|
281
|
+
else abortSignal.addEventListener("abort", stop, { once: true });
|
|
254
282
|
});
|
|
255
|
-
if (params.abortSignal?.aborted) this.stopDisconnectRetries();
|
|
256
|
-
else params.abortSignal?.addEventListener("abort", () => this.stopDisconnectRetries(), { once: true });
|
|
257
283
|
}
|
|
258
284
|
getActiveListener() {
|
|
259
285
|
return this.current?.listener ?? null;
|
|
@@ -322,7 +348,23 @@ var WhatsAppConnectionController = class {
|
|
|
322
348
|
this.current.unregisterUnhandled = unregister;
|
|
323
349
|
}
|
|
324
350
|
async openConnection(params) {
|
|
351
|
+
if (this.shuttingDown) throw stoppedControllerError();
|
|
352
|
+
if (this.connectionSetupPromise) throw new Error("WhatsApp connection setup is already in progress");
|
|
353
|
+
const setupPromise = this.openConnectionOwned(params);
|
|
354
|
+
this.connectionSetupPromise = setupPromise;
|
|
355
|
+
try {
|
|
356
|
+
return await setupPromise;
|
|
357
|
+
} finally {
|
|
358
|
+
if (this.connectionSetupPromise === setupPromise) this.connectionSetupPromise = null;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async openConnectionOwned(params) {
|
|
362
|
+
await this.ensureConnectionOwnership();
|
|
363
|
+
this.throwIfSetupStopped();
|
|
364
|
+
await this.finishPendingSocketCleanup();
|
|
365
|
+
this.throwIfSetupStopped();
|
|
325
366
|
if (this.current) await this.closeCurrentConnection();
|
|
367
|
+
this.throwIfSetupStopped();
|
|
326
368
|
let sock = null;
|
|
327
369
|
let connection = null;
|
|
328
370
|
try {
|
|
@@ -332,8 +374,9 @@ var WhatsAppConnectionController = class {
|
|
|
332
374
|
...params.getMessage ? { getMessage: params.getMessage } : {},
|
|
333
375
|
...params.cachedGroupMetadata ? { cachedGroupMetadata: params.cachedGroupMetadata } : {}
|
|
334
376
|
});
|
|
335
|
-
|
|
336
|
-
|
|
377
|
+
this.throwIfSetupStopped();
|
|
378
|
+
await this.waitForSetupStep(waitForWaConnection(sock, { timeoutMs: this.socketTiming.connectTimeoutMs }));
|
|
379
|
+
this.throwIfSetupStopped();
|
|
337
380
|
this.socketRef.current = sock;
|
|
338
381
|
connection = createLiveConnection({
|
|
339
382
|
connectionId: params.connectionId,
|
|
@@ -341,16 +384,24 @@ var WhatsAppConnectionController = class {
|
|
|
341
384
|
listener: {},
|
|
342
385
|
openedAfterRecentInbound: this.isOpeningAfterRecentInbound()
|
|
343
386
|
});
|
|
344
|
-
const
|
|
387
|
+
const listenerTask = params.createListener({
|
|
345
388
|
sock,
|
|
346
389
|
connection
|
|
347
390
|
});
|
|
391
|
+
let listener;
|
|
392
|
+
try {
|
|
393
|
+
listener = await this.waitForSetupStep(listenerTask);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
if (this.setupAbortController.signal.aborted) listenerTask.then((lateListener) => lateListener.close?.()).catch(() => {});
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
348
398
|
connection.listener = listener;
|
|
399
|
+
this.throwIfSetupStopped();
|
|
349
400
|
this.current = connection;
|
|
350
401
|
connection.unregisterTransportActivity = this.attachTransportActivityListener(sock);
|
|
351
402
|
const previousRuntimeContextLease = this.runtimeContextLease;
|
|
352
403
|
this.runtimeContextLease = registerChannelRuntimeContext({
|
|
353
|
-
channelRuntime,
|
|
404
|
+
channelRuntime: getWhatsAppRuntime().channel,
|
|
354
405
|
channelId: "whatsapp",
|
|
355
406
|
accountId: this.accountId,
|
|
356
407
|
capability: WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY,
|
|
@@ -358,16 +409,38 @@ var WhatsAppConnectionController = class {
|
|
|
358
409
|
abortSignal: this.abortSignal
|
|
359
410
|
});
|
|
360
411
|
previousRuntimeContextLease?.dispose();
|
|
412
|
+
this.pendingOwnerContextLease?.dispose();
|
|
413
|
+
this.pendingOwnerContextLease = null;
|
|
361
414
|
this.startTimers(connection, {
|
|
362
415
|
onHeartbeat: params.onHeartbeat,
|
|
363
416
|
onWatchdogTimeout: params.onWatchdogTimeout
|
|
364
417
|
});
|
|
365
418
|
return connection;
|
|
366
419
|
} catch (err) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
420
|
+
try {
|
|
421
|
+
if (connection && this.current === connection) await this.closeCurrentConnection();
|
|
422
|
+
else {
|
|
423
|
+
try {
|
|
424
|
+
await connection?.listener.close?.();
|
|
425
|
+
} catch {}
|
|
426
|
+
if (this.socketRef.current === sock) this.socketRef.current = null;
|
|
427
|
+
if (sock) {
|
|
428
|
+
const cleanup = connection ?? {
|
|
429
|
+
sock,
|
|
430
|
+
socketClosed: false
|
|
431
|
+
};
|
|
432
|
+
await this.finishSocketCleanup(cleanup);
|
|
433
|
+
}
|
|
434
|
+
if (connection?.unregisterUnhandled) connection.unregisterUnhandled();
|
|
435
|
+
connection?.unregisterTransportActivity?.();
|
|
436
|
+
}
|
|
437
|
+
} catch (closeError) {
|
|
438
|
+
if (sock && (!connection || this.current !== connection)) this.pendingSocketCleanup = connection ?? {
|
|
439
|
+
sock,
|
|
440
|
+
socketClosed: false
|
|
441
|
+
};
|
|
442
|
+
throw new AggregateError([err, closeError], "WhatsApp connection setup and close failed", { cause: err });
|
|
443
|
+
}
|
|
371
444
|
throw err;
|
|
372
445
|
}
|
|
373
446
|
}
|
|
@@ -460,6 +533,7 @@ var WhatsAppConnectionController = class {
|
|
|
460
533
|
const connection = this.current;
|
|
461
534
|
if (!connection) return;
|
|
462
535
|
this.current = null;
|
|
536
|
+
this.pendingSocketCleanup = connection;
|
|
463
537
|
if (this.socketRef.current === connection.sock) this.socketRef.current = null;
|
|
464
538
|
connection.unregisterUnhandled?.();
|
|
465
539
|
connection.unregisterTransportActivity?.();
|
|
@@ -472,16 +546,103 @@ var WhatsAppConnectionController = class {
|
|
|
472
546
|
try {
|
|
473
547
|
await connection.listener.close?.();
|
|
474
548
|
} catch {}
|
|
475
|
-
|
|
549
|
+
await this.finishSocketCleanup(connection);
|
|
550
|
+
if (this.pendingSocketCleanup === connection) this.pendingSocketCleanup = null;
|
|
476
551
|
}
|
|
477
552
|
async waitBeforeRetry(delayMs) {
|
|
478
553
|
await this.sleep(delayMs, this.abortSignal);
|
|
479
554
|
}
|
|
480
555
|
async shutdown() {
|
|
556
|
+
this.shuttingDown = true;
|
|
557
|
+
const stoppedError = stoppedControllerError();
|
|
558
|
+
this.ownerAcquireAbortController.abort(stoppedError);
|
|
559
|
+
this.setupAbortController.abort(stoppedError);
|
|
481
560
|
this.stopDisconnectRetries();
|
|
561
|
+
await this.connectionSetupPromise?.catch(() => {});
|
|
562
|
+
await this.connectionOwnerLeasePromise?.catch(() => {});
|
|
482
563
|
await this.closeCurrentConnection();
|
|
483
|
-
this.
|
|
484
|
-
|
|
564
|
+
await this.finishPendingSocketCleanup();
|
|
565
|
+
try {
|
|
566
|
+
this.runtimeContextLease?.dispose();
|
|
567
|
+
} finally {
|
|
568
|
+
this.runtimeContextLease = null;
|
|
569
|
+
try {
|
|
570
|
+
this.pendingOwnerContextLease?.dispose();
|
|
571
|
+
} finally {
|
|
572
|
+
this.pendingOwnerContextLease = null;
|
|
573
|
+
if (this.connectionOwnerLease) {
|
|
574
|
+
await this.connectionOwnerLease.release();
|
|
575
|
+
this.connectionOwnerLease = null;
|
|
576
|
+
}
|
|
577
|
+
if (this.retainedOwnerReleaseLease) {
|
|
578
|
+
await this.retainedOwnerReleaseLease.release();
|
|
579
|
+
this.retainedOwnerReleaseLease = null;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
async finishSocketCleanup(cleanup) {
|
|
585
|
+
if (!cleanup.socketClosed) {
|
|
586
|
+
await closeWhatsAppSocketAndWait(cleanup.sock, "OpenClaw WhatsApp socket close");
|
|
587
|
+
cleanup.socketClosed = true;
|
|
588
|
+
}
|
|
589
|
+
if (await waitForCredsSaveQueueWithTimeout(this.authDir) === "timed_out") throw new Error("WhatsApp credential persistence did not drain before owner release");
|
|
590
|
+
}
|
|
591
|
+
async finishPendingSocketCleanup() {
|
|
592
|
+
const cleanup = this.pendingSocketCleanup;
|
|
593
|
+
if (!cleanup) return;
|
|
594
|
+
await this.finishSocketCleanup(cleanup);
|
|
595
|
+
if (this.pendingSocketCleanup === cleanup) this.pendingSocketCleanup = null;
|
|
596
|
+
}
|
|
597
|
+
throwIfSetupStopped() {
|
|
598
|
+
if (this.shuttingDown || this.setupAbortController.signal.aborted) throw stoppedControllerError();
|
|
599
|
+
}
|
|
600
|
+
async waitForSetupStep(task) {
|
|
601
|
+
this.throwIfSetupStopped();
|
|
602
|
+
const signal = this.setupAbortController.signal;
|
|
603
|
+
let onAbort;
|
|
604
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
605
|
+
onAbort = () => reject(stoppedControllerError());
|
|
606
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
607
|
+
});
|
|
608
|
+
try {
|
|
609
|
+
return await Promise.race([task, aborted]);
|
|
610
|
+
} finally {
|
|
611
|
+
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
async ensureConnectionOwnership() {
|
|
615
|
+
if (this.retainedOwnerReleaseLease) {
|
|
616
|
+
await this.retainedOwnerReleaseLease.release();
|
|
617
|
+
this.retainedOwnerReleaseLease = null;
|
|
618
|
+
}
|
|
619
|
+
if (this.connectionOwnerLease) return;
|
|
620
|
+
if (!this.connectionOwnerLeasePromise) this.connectionOwnerLeasePromise = (async () => {
|
|
621
|
+
const ownerLease = await acquireWhatsAppGatewayConnectionOwner(this.authDir, this.ownerAcquireAbortController.signal);
|
|
622
|
+
try {
|
|
623
|
+
if (this.shuttingDown) throw stoppedControllerError();
|
|
624
|
+
this.pendingOwnerContextLease = registerChannelRuntimeContext({
|
|
625
|
+
channelRuntime: getWhatsAppRuntime().channel,
|
|
626
|
+
channelId: "whatsapp",
|
|
627
|
+
accountId: this.accountId,
|
|
628
|
+
capability: WHATSAPP_CONNECTION_OWNER_PENDING_CAPABILITY,
|
|
629
|
+
context: true,
|
|
630
|
+
abortSignal: this.abortSignal
|
|
631
|
+
});
|
|
632
|
+
this.connectionOwnerLease = ownerLease;
|
|
633
|
+
} catch (error) {
|
|
634
|
+
try {
|
|
635
|
+
await ownerLease.release();
|
|
636
|
+
} catch (releaseError) {
|
|
637
|
+
this.retainedOwnerReleaseLease = ownerLease;
|
|
638
|
+
throw new AggregateError([error, releaseError], "WhatsApp connection ownership setup and release failed", { cause: error });
|
|
639
|
+
}
|
|
640
|
+
throw error;
|
|
641
|
+
}
|
|
642
|
+
})().finally(() => {
|
|
643
|
+
this.connectionOwnerLeasePromise = null;
|
|
644
|
+
});
|
|
645
|
+
await this.connectionOwnerLeasePromise;
|
|
485
646
|
}
|
|
486
647
|
startTimers(connection, hooks) {
|
|
487
648
|
if (!this.keepAlive) return;
|
|
@@ -2,6 +2,7 @@ import { t as getOptionalWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
|
2
2
|
import { getChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
3
3
|
//#region extensions/whatsapp/src/connection-controller-runtime-context.ts
|
|
4
4
|
const WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY = "connection-controller";
|
|
5
|
+
const WHATSAPP_CONNECTION_OWNER_PENDING_CAPABILITY = "connection-owner-pending";
|
|
5
6
|
function getWhatsAppConnectionController(accountId) {
|
|
6
7
|
return getChannelRuntimeContext({
|
|
7
8
|
channelRuntime: getOptionalWhatsAppRuntime()?.channel,
|
|
@@ -10,5 +11,13 @@ function getWhatsAppConnectionController(accountId) {
|
|
|
10
11
|
capability: "connection-controller"
|
|
11
12
|
}) ?? null;
|
|
12
13
|
}
|
|
14
|
+
function hasPendingWhatsAppConnectionOwner(accountId) {
|
|
15
|
+
return Boolean(getChannelRuntimeContext({
|
|
16
|
+
channelRuntime: getOptionalWhatsAppRuntime()?.channel,
|
|
17
|
+
channelId: "whatsapp",
|
|
18
|
+
accountId,
|
|
19
|
+
capability: WHATSAPP_CONNECTION_OWNER_PENDING_CAPABILITY
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
13
22
|
//#endregion
|
|
14
|
-
export {
|
|
23
|
+
export { hasPendingWhatsAppConnectionOwner as i, WHATSAPP_CONNECTION_OWNER_PENDING_CAPABILITY as n, getWhatsAppConnectionController as r, WHATSAPP_CONNECTION_CONTROLLER_CAPABILITY as t };
|
package/dist/contract-api.js
CHANGED
|
@@ -2,7 +2,7 @@ import { c as normalizeWhatsAppTarget$1, t as isWhatsAppGroupJid$1 } from "./nor
|
|
|
2
2
|
import { t as whatsappCommandPolicy$1 } from "./command-policy-BIOSHySD.js";
|
|
3
3
|
import { t as resolveLegacyGroupSessionKey$1 } from "./group-session-contract-DDnZSsJ1.js";
|
|
4
4
|
import { r as isLegacyGroupSessionKey$1, t as canonicalizeLegacySessionKey$1 } from "./session-contract-DMTm6Q_L.js";
|
|
5
|
-
import { a as resolveWhatsAppRuntimeGroupPolicy$1, n as testing } from "./access-control-
|
|
5
|
+
import { a as resolveWhatsAppRuntimeGroupPolicy$1, n as testing } from "./access-control-tjy_em01.js";
|
|
6
6
|
//#region extensions/whatsapp/contract-api.ts
|
|
7
7
|
const canonicalizeLegacySessionKey = canonicalizeLegacySessionKey$1;
|
|
8
8
|
const isLegacyGroupSessionKey = isLegacyGroupSessionKey$1;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
+
import { c as resolveMergedWhatsAppAccountConfig, o as resolveWhatsAppAuthDir } from "./accounts-ejK8sXPU.js";
|
|
3
|
+
import { c as normalizeWhatsAppTarget, t as isWhatsAppGroupJid } from "./normalize-target-DSZnHkKF.js";
|
|
4
|
+
import { i as hasPendingWhatsAppConnectionOwner, r as getWhatsAppConnectionController } from "./connection-controller-runtime-context-9mEeAvu1.js";
|
|
5
|
+
import "./normalize-C-Z16y7Q.js";
|
|
6
|
+
import { f as readWebAuthExistsForDecision, w as waitForCredsSaveQueueWithTimeout } from "./auth-store-BQi9pZqQ.js";
|
|
7
|
+
import { n as resolveWebAccountId } from "./active-listener-BbdlXooT.js";
|
|
8
|
+
import { a as waitForWaConnection, h as acquireWhatsAppStandaloneConnectionOwner, n as createWaDirectorySocket, p as WhatsAppConnectionOwnerBusyError, t as closeWhatsAppSocketAndWait } from "./socket-close-jNGyZY4T.js";
|
|
9
|
+
import { listResolvedDirectoryGroupEntriesFromMapKeys, listResolvedDirectoryUserEntriesFromAllowFrom } from "openclaw/plugin-sdk/directory-config-runtime";
|
|
10
|
+
//#region extensions/whatsapp/src/directory-config.ts
|
|
11
|
+
var directory_config_exports = /* @__PURE__ */ __exportAll({
|
|
12
|
+
WHATSAPP_DIRECTORY_UNAVAILABLE_CODE: () => WHATSAPP_DIRECTORY_UNAVAILABLE_CODE,
|
|
13
|
+
WhatsAppDirectoryUnavailableError: () => WhatsAppDirectoryUnavailableError,
|
|
14
|
+
listWhatsAppDirectoryGroupsFromConfig: () => listWhatsAppDirectoryGroupsFromConfig,
|
|
15
|
+
listWhatsAppDirectoryGroupsLive: () => listWhatsAppDirectoryGroupsLive,
|
|
16
|
+
listWhatsAppDirectoryPeersFromConfig: () => listWhatsAppDirectoryPeersFromConfig
|
|
17
|
+
});
|
|
18
|
+
function resolveWhatsAppDirectoryAccount(cfg, accountId) {
|
|
19
|
+
return resolveMergedWhatsAppAccountConfig({
|
|
20
|
+
cfg,
|
|
21
|
+
accountId
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async function listWhatsAppDirectoryPeersFromConfig(params) {
|
|
25
|
+
return listResolvedDirectoryUserEntriesFromAllowFrom({
|
|
26
|
+
...params,
|
|
27
|
+
resolveAccount: resolveWhatsAppDirectoryAccount,
|
|
28
|
+
resolveAllowFrom: (account) => account.allowFrom,
|
|
29
|
+
normalizeId: (entry) => {
|
|
30
|
+
const normalized = normalizeWhatsAppTarget(entry);
|
|
31
|
+
if (!normalized || isWhatsAppGroupJid(normalized)) return null;
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function listWhatsAppDirectoryGroupsFromConfig(params) {
|
|
37
|
+
return listResolvedDirectoryGroupEntriesFromMapKeys({
|
|
38
|
+
...params,
|
|
39
|
+
resolveAccount: resolveWhatsAppDirectoryAccount,
|
|
40
|
+
resolveGroups: (account) => account.groups
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const WHATSAPP_DIRECTORY_UNAVAILABLE_CODE = "whatsapp_directory_unavailable";
|
|
44
|
+
var WhatsAppDirectoryUnavailableError = class extends Error {
|
|
45
|
+
constructor(reason, message, options) {
|
|
46
|
+
super(message, options);
|
|
47
|
+
this.reason = reason;
|
|
48
|
+
this.code = WHATSAPP_DIRECTORY_UNAVAILABLE_CODE;
|
|
49
|
+
this.name = "WhatsAppDirectoryUnavailableError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
async function fetchLiveGroups(sock, params) {
|
|
53
|
+
const groups = await sock.groupFetchAllParticipating();
|
|
54
|
+
const query = params.query?.trim().toLowerCase() ?? "";
|
|
55
|
+
const limit = typeof params.limit === "number" && params.limit > 0 ? params.limit : void 0;
|
|
56
|
+
const entries = Object.entries(groups).map(([jid, metadata]) => ({
|
|
57
|
+
kind: "group",
|
|
58
|
+
id: jid,
|
|
59
|
+
name: metadata?.subject?.trim() || void 0
|
|
60
|
+
})).filter((entry) => {
|
|
61
|
+
if (!query) return true;
|
|
62
|
+
return entry.id.toLowerCase().includes(query) || entry.name?.toLowerCase().includes(query);
|
|
63
|
+
}).toSorted((left, right) => left.id.localeCompare(right.id));
|
|
64
|
+
return limit ? entries.slice(0, limit) : entries;
|
|
65
|
+
}
|
|
66
|
+
function unavailable(reason, message, cause) {
|
|
67
|
+
return new WhatsAppDirectoryUnavailableError(reason, message, cause ? { cause } : void 0);
|
|
68
|
+
}
|
|
69
|
+
const pendingStandaloneCleanups = /* @__PURE__ */ new Map();
|
|
70
|
+
const STANDALONE_CLEANUP_RETRY_MS = 1e3;
|
|
71
|
+
async function completeStandaloneCleanup(cleanup) {
|
|
72
|
+
if (cleanup.sock && !cleanup.socketClosed) {
|
|
73
|
+
await closeWhatsAppSocketAndWait(cleanup.sock, "OpenClaw WhatsApp standalone directory socket close");
|
|
74
|
+
cleanup.socketClosed = true;
|
|
75
|
+
}
|
|
76
|
+
if (cleanup.sock) {
|
|
77
|
+
if (await waitForCredsSaveQueueWithTimeout(cleanup.authDir) === "timed_out") throw new Error("WhatsApp credential persistence did not drain before socket release");
|
|
78
|
+
}
|
|
79
|
+
await cleanup.ownerLease.release();
|
|
80
|
+
if (pendingStandaloneCleanups.get(cleanup.authDir) === cleanup) pendingStandaloneCleanups.delete(cleanup.authDir);
|
|
81
|
+
if (cleanup.retryTimer) {
|
|
82
|
+
clearTimeout(cleanup.retryTimer);
|
|
83
|
+
cleanup.retryTimer = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function runStandaloneCleanup(cleanup) {
|
|
87
|
+
if (cleanup.inFlight) return cleanup.inFlight;
|
|
88
|
+
const task = completeStandaloneCleanup(cleanup).finally(() => {
|
|
89
|
+
if (cleanup.inFlight === task) cleanup.inFlight = null;
|
|
90
|
+
});
|
|
91
|
+
cleanup.inFlight = task;
|
|
92
|
+
return task;
|
|
93
|
+
}
|
|
94
|
+
function scheduleStandaloneCleanupRetry(cleanup) {
|
|
95
|
+
if (cleanup.retryTimer) return;
|
|
96
|
+
cleanup.retryTimer = setTimeout(() => {
|
|
97
|
+
cleanup.retryTimer = null;
|
|
98
|
+
runStandaloneCleanup(cleanup).catch(() => {
|
|
99
|
+
scheduleStandaloneCleanupRetry(cleanup);
|
|
100
|
+
});
|
|
101
|
+
}, STANDALONE_CLEANUP_RETRY_MS);
|
|
102
|
+
cleanup.retryTimer.unref?.();
|
|
103
|
+
}
|
|
104
|
+
function retainStandaloneCleanup(cleanup) {
|
|
105
|
+
pendingStandaloneCleanups.set(cleanup.authDir, cleanup);
|
|
106
|
+
scheduleStandaloneCleanupRetry(cleanup);
|
|
107
|
+
}
|
|
108
|
+
async function finishStandaloneCleanupOrThrow(cleanup, operationError) {
|
|
109
|
+
try {
|
|
110
|
+
await runStandaloneCleanup(cleanup);
|
|
111
|
+
} catch (cleanupError) {
|
|
112
|
+
retainStandaloneCleanup(cleanup);
|
|
113
|
+
throw cleanupUnavailable(operationError === void 0 ? cleanupError : new AggregateError([operationError, cleanupError], "WhatsApp live group lookup and cleanup failed", { cause: operationError }));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function cleanupUnavailable(error) {
|
|
117
|
+
return unavailable("cleanup_failed", "WhatsApp live group lookup could not safely close its standalone connection.", error);
|
|
118
|
+
}
|
|
119
|
+
async function finishPriorStandaloneCleanup(authDir) {
|
|
120
|
+
const cleanup = pendingStandaloneCleanups.get(authDir);
|
|
121
|
+
if (!cleanup) return;
|
|
122
|
+
try {
|
|
123
|
+
await runStandaloneCleanup(cleanup);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
scheduleStandaloneCleanupRetry(cleanup);
|
|
126
|
+
throw cleanupUnavailable(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function listGroupsThroughStandaloneOwner(params) {
|
|
130
|
+
const account = resolveWhatsAppDirectoryAccount(params.cfg, params.accountId);
|
|
131
|
+
const authDir = resolveWhatsAppAuthDir({
|
|
132
|
+
cfg: params.cfg,
|
|
133
|
+
accountId: account.accountId
|
|
134
|
+
}).authDir;
|
|
135
|
+
await finishPriorStandaloneCleanup(authDir);
|
|
136
|
+
let ownerLease;
|
|
137
|
+
try {
|
|
138
|
+
ownerLease = await acquireWhatsAppStandaloneConnectionOwner(authDir);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof WhatsAppConnectionOwnerBusyError) throw unavailable("connection_owner_busy", "WhatsApp live groups are unavailable because the account is owned by another process.", error);
|
|
141
|
+
throw unavailable("connection_failed", "WhatsApp live groups are unavailable because connection ownership failed.", error);
|
|
142
|
+
}
|
|
143
|
+
const cleanup = {
|
|
144
|
+
authDir,
|
|
145
|
+
inFlight: null,
|
|
146
|
+
ownerLease,
|
|
147
|
+
retryTimer: null,
|
|
148
|
+
sock: null,
|
|
149
|
+
socketClosed: true
|
|
150
|
+
};
|
|
151
|
+
let groups;
|
|
152
|
+
try {
|
|
153
|
+
let authState;
|
|
154
|
+
try {
|
|
155
|
+
authState = await readWebAuthExistsForDecision(authDir);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
throw unavailable("auth_unstable", "WhatsApp live groups are unavailable because linked credentials could not be read.", error);
|
|
158
|
+
}
|
|
159
|
+
if (authState.outcome === "unstable") throw unavailable("auth_unstable", "WhatsApp live groups are unavailable while linked credentials are changing.");
|
|
160
|
+
if (!authState.exists) throw unavailable("not_linked", "WhatsApp live groups are unavailable because this account is not linked.");
|
|
161
|
+
try {
|
|
162
|
+
cleanup.sock = await createWaDirectorySocket(authDir);
|
|
163
|
+
cleanup.socketClosed = false;
|
|
164
|
+
await waitForWaConnection(cleanup.sock, { timeoutMs: 3e4 });
|
|
165
|
+
} catch (error) {
|
|
166
|
+
throw unavailable("connection_failed", "WhatsApp live groups are unavailable because the standalone connection failed.", error);
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
groups = await fetchLiveGroups(cleanup.sock, params);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
throw unavailable("lookup_failed", "WhatsApp live group lookup failed.", error);
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
await finishStandaloneCleanupOrThrow(cleanup, error);
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
await finishStandaloneCleanupOrThrow(cleanup);
|
|
178
|
+
return groups;
|
|
179
|
+
}
|
|
180
|
+
async function listWhatsAppDirectoryGroupsLive(params) {
|
|
181
|
+
const accountId = resolveWebAccountId({
|
|
182
|
+
cfg: params.cfg,
|
|
183
|
+
accountId: params.accountId
|
|
184
|
+
});
|
|
185
|
+
const controller = getWhatsAppConnectionController(accountId);
|
|
186
|
+
if (!controller && !hasPendingWhatsAppConnectionOwner(accountId)) return await listGroupsThroughStandaloneOwner(params);
|
|
187
|
+
const sock = controller?.getCurrentSock();
|
|
188
|
+
if (!sock) throw unavailable("active_owner_unavailable", "WhatsApp live groups are unavailable while the gateway connection is offline.");
|
|
189
|
+
try {
|
|
190
|
+
return await fetchLiveGroups(sock, params);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw unavailable("lookup_failed", "WhatsApp live group lookup failed.", error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
export { listWhatsAppDirectoryGroupsFromConfig as n, listWhatsAppDirectoryPeersFromConfig as r, directory_config_exports as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-
|
|
1
|
+
import { n as listWhatsAppDirectoryGroupsFromConfig, r as listWhatsAppDirectoryPeersFromConfig } from "./directory-config-BZ775eGX.js";
|
|
2
2
|
//#region extensions/whatsapp/directory-contract-api.ts
|
|
3
3
|
const whatsappDirectoryContractPlugin = {
|
|
4
4
|
id: "whatsapp",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount } from "./accounts-ejK8sXPU.js";
|
|
2
2
|
import { c as normalizeWhatsAppTarget } from "./normalize-target-DSZnHkKF.js";
|
|
3
3
|
import "./normalize-C-Z16y7Q.js";
|
|
4
4
|
import { r as jidToE164 } from "./targets-runtime-Bsh0HR9y.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-
|
|
1
|
+
import { t as detectWhatsAppLegacyStateMigrations } from "./state-migrations-CAMTrs2U.js";
|
|
2
2
|
export { detectWhatsAppLegacyStateMigrations };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as createWhatsAppLoginTool } from "./agent-tools-login-DfyToBpG.js";
|
|
2
2
|
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, y as resolveDefaultWebAuthDir } from "./auth-store-BQi9pZqQ.js";
|
|
3
|
+
import { t as getActiveWebListener } from "./active-listener-BbdlXooT.js";
|
|
3
4
|
import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
|
|
4
|
-
import { t as getActiveWebListener } from "./active-listener-5kHap439.js";
|
|
5
5
|
export { WA_WEB_AUTH_DIR, createWhatsAppLoginTool, formatError, getActiveWebListener, getStatusCode, getWebAuthAgeMs, logWebSelfId, logoutWeb, pickWebChannel, readWebSelfId, resolveDefaultWebAuthDir, webAuthExists };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
2
|
+
import { a as resolveWhatsAppAccount } from "./accounts-ejK8sXPU.js";
|
|
3
3
|
import { b as restoreCredsFromBackupIfNeeded } from "./auth-store-BQi9pZqQ.js";
|
|
4
|
-
import {
|
|
5
|
-
import { a as closeWaSocketSoon, o as waitForWhatsAppLoginResult } from "./connection-controller-
|
|
4
|
+
import { f as renderQrTerminal, r as createWaSocket, u as resolveWhatsAppSocketTiming } from "./socket-close-jNGyZY4T.js";
|
|
5
|
+
import { a as closeWaSocketSoon, o as waitForWhatsAppLoginResult } from "./connection-controller-HGaffeFb.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,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount } from "./accounts-
|
|
1
|
+
import { a as resolveWhatsAppAccount } from "./accounts-ejK8sXPU.js";
|
|
2
2
|
import { c as logoutWeb, f as readWebAuthExistsForDecision, g as readWebSelfId, n as WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store-BQi9pZqQ.js";
|
|
3
|
-
import {
|
|
3
|
+
import { t as getActiveWebListener } from "./active-listener-BbdlXooT.js";
|
|
4
|
+
import { r as createWaSocket, u as resolveWhatsAppSocketTiming } from "./socket-close-jNGyZY4T.js";
|
|
4
5
|
import { t as formatError } from "./session-errors-JuazczrA.js";
|
|
5
|
-
import { t as
|
|
6
|
-
import { i as closeWaSocket, o as waitForWhatsAppLoginResult, t as WHATSAPP_LOGGED_OUT_QR_MESSAGE } from "./connection-controller-C1rwfWb4.js";
|
|
6
|
+
import { i as closeWaSocket, o as waitForWhatsAppLoginResult, t as WHATSAPP_LOGGED_OUT_QR_MESSAGE } from "./connection-controller-HGaffeFb.js";
|
|
7
7
|
import { logInfo } from "openclaw/plugin-sdk/logging-core";
|
|
8
8
|
import { danger, defaultRuntime, info, success } from "openclaw/plugin-sdk/runtime-env";
|
|
9
9
|
import { renderQrPngDataUrl } from "openclaw/plugin-sdk/media-runtime";
|
package/dist/login-qr-runtime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
2
2
|
//#region extensions/whatsapp/login-qr-runtime.ts
|
|
3
|
-
const loadLoginQrModule = createLazyRuntimeModule(() => import("./login-qr-
|
|
3
|
+
const loadLoginQrModule = createLazyRuntimeModule(() => import("./login-qr-DUHzVH_Y.js"));
|
|
4
4
|
async function startWebLoginWithQr(...args) {
|
|
5
5
|
const { startWebLoginWithQr: startWebLoginWithQrLocal } = await loadLoginQrModule();
|
|
6
6
|
return await startWebLoginWithQrLocal(...args);
|