@diegoaltoworks/chatter 0.62.0 → 0.63.0
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.
|
@@ -90,6 +90,15 @@ export interface LeaseGatedConnectDeps {
|
|
|
90
90
|
waitMs?: number;
|
|
91
91
|
schedule?: (fn: () => void, ms: number) => void;
|
|
92
92
|
logger?: Logger;
|
|
93
|
+
/**
|
|
94
|
+
* Recovery for a `connect` that threw, replacing the default (release the
|
|
95
|
+
* session, re-check after `waitMs`). The channel injects one so a thrown
|
|
96
|
+
* connect backs off on the same failure counter a closed connection uses
|
|
97
|
+
* instead of re-attempting at a flat interval. Whatever it does, it must
|
|
98
|
+
* end with another attempt scheduled: a session whose lease is held with
|
|
99
|
+
* no live socket and nothing pending never recovers on its own.
|
|
100
|
+
*/
|
|
101
|
+
onConnectFailed?: (sessionId: string, error: unknown) => void;
|
|
93
102
|
}
|
|
94
103
|
/**
|
|
95
104
|
* Acquire `sessionId`'s lease before connecting — two instances must never
|
|
@@ -99,6 +108,11 @@ export interface LeaseGatedConnectDeps {
|
|
|
99
108
|
* heartbeat ever finds the lease gone (this instance went stale and another
|
|
100
109
|
* took over), the session is torn down and this re-enters the same
|
|
101
110
|
* wait-and-retry loop rather than staying connected alongside the new holder.
|
|
111
|
+
*
|
|
112
|
+
* Every failed connect attempt lands back here too, whether it threw on its
|
|
113
|
+
* first try or on a reconnect: this loop is the only way a session recovers,
|
|
114
|
+
* so an attempt that fails without leaving a socket behind (no socket, no
|
|
115
|
+
* future "close" event) must re-enter it rather than stop at a log line.
|
|
102
116
|
*/
|
|
103
117
|
export declare function acquireSessionLease(sessionId: string, deps: LeaseGatedConnectDeps): Promise<void>;
|
|
104
118
|
/** Sender-registry name for a session — the default session stays unprefixed so single-number deployments see a plain `"whatsapp"` name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAgB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEjF,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,KAAK,EAAoB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAmD,MAAM,WAAW,CAAC;AAC1F,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAKjB;gFACgF;AAChF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,uJAAuJ;IACvJ,aAAa,EAAE,MAAM,CAAC;IACtB,8JAA8J;IAC9J,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qLAAqL;IACrL,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iIAAiI;IACjI,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8KAA8K;IAC9K,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,4KAA4K;IAC5K,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtB;AAED,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE;QAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;KAAE,CAAC;IACvC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9F;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAgB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEjF,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,KAAK,EAAoB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAmD,MAAM,WAAW,CAAC;AAC1F,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAKjB;gFACgF;AAChF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,uJAAuJ;IACvJ,aAAa,EAAE,MAAM,CAAC;IACtB,8JAA8J;IAC9J,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qLAAqL;IACrL,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iIAAiI;IACjI,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8KAA8K;IAC9K,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,4KAA4K;IAC5K,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtB;AAED,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE;QAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;KAAE,CAAC;IACvC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ9F;AAiCD,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,YAAY,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,8GAA8G;IAC9G,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAwEf;AAED,4IAA4I;AAC5I,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,kPAAkP;AAClP,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,oBAAoB,CAS9E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAsS5E"}
|
|
@@ -360,11 +360,17 @@ async function shutdownWaSessions(sessions) {
|
|
|
360
360
|
})
|
|
361
361
|
);
|
|
362
362
|
}
|
|
363
|
-
|
|
363
|
+
function claimSession(sessionId, sessions) {
|
|
364
364
|
const handle = sessions.get(sessionId);
|
|
365
|
-
if (!handle) return;
|
|
365
|
+
if (!handle) return void 0;
|
|
366
366
|
sessions.delete(sessionId);
|
|
367
|
+
return handle;
|
|
368
|
+
}
|
|
369
|
+
async function loseSession(sessionId, sessions) {
|
|
370
|
+
const handle = claimSession(sessionId, sessions);
|
|
371
|
+
if (!handle) return false;
|
|
367
372
|
await shutdownWaSessions(/* @__PURE__ */ new Map([[sessionId, handle]]));
|
|
373
|
+
return true;
|
|
368
374
|
}
|
|
369
375
|
async function acquireSessionLease(sessionId, deps) {
|
|
370
376
|
const { leaseStore, instanceId, sessions, isStopped, connect } = deps;
|
|
@@ -400,7 +406,9 @@ async function acquireSessionLease(sessionId, deps) {
|
|
|
400
406
|
void leaseStore.tryAcquire(sessionId, instanceId, now(), staleMs).then((stillHeld) => {
|
|
401
407
|
if (stillHeld || isStopped()) return;
|
|
402
408
|
logger.error(`WhatsApp[${sessionId}]: lost the lease to another instance \u2014 disconnecting`);
|
|
403
|
-
void loseSession(sessionId, sessions).then(
|
|
409
|
+
void loseSession(sessionId, sessions).then((lost) => {
|
|
410
|
+
if (lost) retry();
|
|
411
|
+
});
|
|
404
412
|
}).catch((error) => logger.warn(`WhatsApp[${sessionId}]: lease heartbeat failed:`, error));
|
|
405
413
|
}, heartbeatMs);
|
|
406
414
|
if (typeof heartbeat === "object" && "unref" in heartbeat) heartbeat.unref();
|
|
@@ -412,6 +420,10 @@ async function acquireSessionLease(sessionId, deps) {
|
|
|
412
420
|
try {
|
|
413
421
|
await connect(sessionId);
|
|
414
422
|
} catch (error) {
|
|
423
|
+
if (deps.onConnectFailed) {
|
|
424
|
+
deps.onConnectFailed(sessionId, error);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
415
427
|
logger.error(`WhatsApp[${sessionId}]: connect failed right after acquiring the lease:`, error);
|
|
416
428
|
await loseSession(sessionId, sessions);
|
|
417
429
|
retry();
|
|
@@ -458,6 +470,50 @@ function createWhatsAppChannel(config) {
|
|
|
458
470
|
const authStore = config.authStore ?? createTursoWaAuthKV(deps.db);
|
|
459
471
|
senders = deps.senders;
|
|
460
472
|
await loadBaileys2();
|
|
473
|
+
const leaseDeps = {
|
|
474
|
+
leaseStore,
|
|
475
|
+
instanceId,
|
|
476
|
+
sessions,
|
|
477
|
+
isStopped: () => stopped,
|
|
478
|
+
connect,
|
|
479
|
+
now,
|
|
480
|
+
staleMs,
|
|
481
|
+
heartbeatMs,
|
|
482
|
+
waitMs,
|
|
483
|
+
schedule,
|
|
484
|
+
logger: log,
|
|
485
|
+
onConnectFailed: recoverFromFailedConnect
|
|
486
|
+
};
|
|
487
|
+
function nextRetryDelayMs(sessionId) {
|
|
488
|
+
const failures = failureCounts.get(sessionId) ?? 0;
|
|
489
|
+
failureCounts.set(sessionId, failures + 1);
|
|
490
|
+
return reconnectDelayMs(failures);
|
|
491
|
+
}
|
|
492
|
+
function attemptConnect(sessionId) {
|
|
493
|
+
void connect(sessionId).catch((error) => recoverFromFailedConnect(sessionId, error));
|
|
494
|
+
}
|
|
495
|
+
function recoverFromFailedConnect(sessionId, error) {
|
|
496
|
+
if (stopped) return;
|
|
497
|
+
const handle = claimSession(sessionId, sessions);
|
|
498
|
+
if (!handle) return;
|
|
499
|
+
const delay = nextRetryDelayMs(sessionId);
|
|
500
|
+
log.error(
|
|
501
|
+
`WhatsApp[${sessionId}]: connect attempt failed, releasing the lease and retrying in ${Math.round(delay / 1e3)}s:`,
|
|
502
|
+
error
|
|
503
|
+
);
|
|
504
|
+
schedule(
|
|
505
|
+
() => void acquireSessionLease(sessionId, leaseDeps).catch(
|
|
506
|
+
(retryError) => log.error(`WhatsApp[${sessionId}]: lease re-check failed:`, retryError)
|
|
507
|
+
),
|
|
508
|
+
delay
|
|
509
|
+
);
|
|
510
|
+
void shutdownWaSessions(/* @__PURE__ */ new Map([[sessionId, handle]])).catch(
|
|
511
|
+
(teardownError) => log.warn(
|
|
512
|
+
`WhatsApp[${sessionId}]: teardown after a failed connect failed:`,
|
|
513
|
+
teardownError
|
|
514
|
+
)
|
|
515
|
+
);
|
|
516
|
+
}
|
|
461
517
|
async function connect(sessionId) {
|
|
462
518
|
if (stopped || !sessions.has(sessionId)) return;
|
|
463
519
|
const baileys = await loadBaileys2();
|
|
@@ -476,7 +532,7 @@ function createWhatsAppChannel(config) {
|
|
|
476
532
|
log.warn(
|
|
477
533
|
`WhatsApp[${sessionId}]: no paired session found \u2014 pair it first (see docs/channels.md). Re-checking in 60s.`
|
|
478
534
|
);
|
|
479
|
-
schedule(() =>
|
|
535
|
+
schedule(() => attemptConnect(sessionId), 6e4);
|
|
480
536
|
return;
|
|
481
537
|
}
|
|
482
538
|
const { version } = await baileys.fetchLatestBaileysVersion();
|
|
@@ -542,17 +598,11 @@ function createWhatsAppChannel(config) {
|
|
|
542
598
|
return;
|
|
543
599
|
}
|
|
544
600
|
if (!stopped && sessions.has(sessionId)) {
|
|
545
|
-
const delay =
|
|
546
|
-
failureCounts.set(sessionId, (failureCounts.get(sessionId) ?? 0) + 1);
|
|
601
|
+
const delay = nextRetryDelayMs(sessionId);
|
|
547
602
|
log.warn(
|
|
548
603
|
`WhatsApp[${sessionId}]: connection closed (${statusCode ?? "?"}), reconnecting in ${Math.round(delay / 1e3)}s...`
|
|
549
604
|
);
|
|
550
|
-
schedule(
|
|
551
|
-
() => void connect(sessionId).catch(
|
|
552
|
-
(error) => log.error(`WhatsApp[${sessionId}]: reconnect failed:`, error)
|
|
553
|
-
),
|
|
554
|
-
delay
|
|
555
|
-
);
|
|
605
|
+
schedule(() => attemptConnect(sessionId), delay);
|
|
556
606
|
}
|
|
557
607
|
}
|
|
558
608
|
});
|
|
@@ -570,19 +620,9 @@ function createWhatsAppChannel(config) {
|
|
|
570
620
|
}
|
|
571
621
|
}
|
|
572
622
|
for (const sessionId of sessionIds) {
|
|
573
|
-
void acquireSessionLease(sessionId,
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
sessions,
|
|
577
|
-
isStopped: () => stopped,
|
|
578
|
-
connect,
|
|
579
|
-
now,
|
|
580
|
-
staleMs,
|
|
581
|
-
heartbeatMs,
|
|
582
|
-
waitMs,
|
|
583
|
-
schedule,
|
|
584
|
-
logger: log
|
|
585
|
-
}).catch((error) => log.error(`WhatsApp[${sessionId}]: failed to start:`, error));
|
|
623
|
+
void acquireSessionLease(sessionId, leaseDeps).catch(
|
|
624
|
+
(error) => log.error(`WhatsApp[${sessionId}]: failed to start:`, error)
|
|
625
|
+
);
|
|
586
626
|
}
|
|
587
627
|
},
|
|
588
628
|
async stop() {
|
|
@@ -295,11 +295,17 @@ async function shutdownWaSessions(sessions) {
|
|
|
295
295
|
})
|
|
296
296
|
);
|
|
297
297
|
}
|
|
298
|
-
|
|
298
|
+
function claimSession(sessionId, sessions) {
|
|
299
299
|
const handle = sessions.get(sessionId);
|
|
300
|
-
if (!handle) return;
|
|
300
|
+
if (!handle) return void 0;
|
|
301
301
|
sessions.delete(sessionId);
|
|
302
|
+
return handle;
|
|
303
|
+
}
|
|
304
|
+
async function loseSession(sessionId, sessions) {
|
|
305
|
+
const handle = claimSession(sessionId, sessions);
|
|
306
|
+
if (!handle) return false;
|
|
302
307
|
await shutdownWaSessions(/* @__PURE__ */ new Map([[sessionId, handle]]));
|
|
308
|
+
return true;
|
|
303
309
|
}
|
|
304
310
|
async function acquireSessionLease(sessionId, deps) {
|
|
305
311
|
const { leaseStore, instanceId, sessions, isStopped, connect } = deps;
|
|
@@ -335,7 +341,9 @@ async function acquireSessionLease(sessionId, deps) {
|
|
|
335
341
|
void leaseStore.tryAcquire(sessionId, instanceId, now(), staleMs).then((stillHeld) => {
|
|
336
342
|
if (stillHeld || isStopped()) return;
|
|
337
343
|
logger.error(`WhatsApp[${sessionId}]: lost the lease to another instance \u2014 disconnecting`);
|
|
338
|
-
void loseSession(sessionId, sessions).then(
|
|
344
|
+
void loseSession(sessionId, sessions).then((lost) => {
|
|
345
|
+
if (lost) retry();
|
|
346
|
+
});
|
|
339
347
|
}).catch((error) => logger.warn(`WhatsApp[${sessionId}]: lease heartbeat failed:`, error));
|
|
340
348
|
}, heartbeatMs);
|
|
341
349
|
if (typeof heartbeat === "object" && "unref" in heartbeat) heartbeat.unref();
|
|
@@ -347,6 +355,10 @@ async function acquireSessionLease(sessionId, deps) {
|
|
|
347
355
|
try {
|
|
348
356
|
await connect(sessionId);
|
|
349
357
|
} catch (error) {
|
|
358
|
+
if (deps.onConnectFailed) {
|
|
359
|
+
deps.onConnectFailed(sessionId, error);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
350
362
|
logger.error(`WhatsApp[${sessionId}]: connect failed right after acquiring the lease:`, error);
|
|
351
363
|
await loseSession(sessionId, sessions);
|
|
352
364
|
retry();
|
|
@@ -393,6 +405,50 @@ function createWhatsAppChannel(config) {
|
|
|
393
405
|
const authStore = config.authStore ?? createTursoWaAuthKV(deps.db);
|
|
394
406
|
senders = deps.senders;
|
|
395
407
|
await loadBaileys2();
|
|
408
|
+
const leaseDeps = {
|
|
409
|
+
leaseStore,
|
|
410
|
+
instanceId,
|
|
411
|
+
sessions,
|
|
412
|
+
isStopped: () => stopped,
|
|
413
|
+
connect,
|
|
414
|
+
now,
|
|
415
|
+
staleMs,
|
|
416
|
+
heartbeatMs,
|
|
417
|
+
waitMs,
|
|
418
|
+
schedule,
|
|
419
|
+
logger: log,
|
|
420
|
+
onConnectFailed: recoverFromFailedConnect
|
|
421
|
+
};
|
|
422
|
+
function nextRetryDelayMs(sessionId) {
|
|
423
|
+
const failures = failureCounts.get(sessionId) ?? 0;
|
|
424
|
+
failureCounts.set(sessionId, failures + 1);
|
|
425
|
+
return reconnectDelayMs(failures);
|
|
426
|
+
}
|
|
427
|
+
function attemptConnect(sessionId) {
|
|
428
|
+
void connect(sessionId).catch((error) => recoverFromFailedConnect(sessionId, error));
|
|
429
|
+
}
|
|
430
|
+
function recoverFromFailedConnect(sessionId, error) {
|
|
431
|
+
if (stopped) return;
|
|
432
|
+
const handle = claimSession(sessionId, sessions);
|
|
433
|
+
if (!handle) return;
|
|
434
|
+
const delay = nextRetryDelayMs(sessionId);
|
|
435
|
+
log.error(
|
|
436
|
+
`WhatsApp[${sessionId}]: connect attempt failed, releasing the lease and retrying in ${Math.round(delay / 1e3)}s:`,
|
|
437
|
+
error
|
|
438
|
+
);
|
|
439
|
+
schedule(
|
|
440
|
+
() => void acquireSessionLease(sessionId, leaseDeps).catch(
|
|
441
|
+
(retryError) => log.error(`WhatsApp[${sessionId}]: lease re-check failed:`, retryError)
|
|
442
|
+
),
|
|
443
|
+
delay
|
|
444
|
+
);
|
|
445
|
+
void shutdownWaSessions(/* @__PURE__ */ new Map([[sessionId, handle]])).catch(
|
|
446
|
+
(teardownError) => log.warn(
|
|
447
|
+
`WhatsApp[${sessionId}]: teardown after a failed connect failed:`,
|
|
448
|
+
teardownError
|
|
449
|
+
)
|
|
450
|
+
);
|
|
451
|
+
}
|
|
396
452
|
async function connect(sessionId) {
|
|
397
453
|
if (stopped || !sessions.has(sessionId)) return;
|
|
398
454
|
const baileys = await loadBaileys2();
|
|
@@ -411,7 +467,7 @@ function createWhatsAppChannel(config) {
|
|
|
411
467
|
log.warn(
|
|
412
468
|
`WhatsApp[${sessionId}]: no paired session found \u2014 pair it first (see docs/channels.md). Re-checking in 60s.`
|
|
413
469
|
);
|
|
414
|
-
schedule(() =>
|
|
470
|
+
schedule(() => attemptConnect(sessionId), 6e4);
|
|
415
471
|
return;
|
|
416
472
|
}
|
|
417
473
|
const { version } = await baileys.fetchLatestBaileysVersion();
|
|
@@ -477,17 +533,11 @@ function createWhatsAppChannel(config) {
|
|
|
477
533
|
return;
|
|
478
534
|
}
|
|
479
535
|
if (!stopped && sessions.has(sessionId)) {
|
|
480
|
-
const delay =
|
|
481
|
-
failureCounts.set(sessionId, (failureCounts.get(sessionId) ?? 0) + 1);
|
|
536
|
+
const delay = nextRetryDelayMs(sessionId);
|
|
482
537
|
log.warn(
|
|
483
538
|
`WhatsApp[${sessionId}]: connection closed (${statusCode ?? "?"}), reconnecting in ${Math.round(delay / 1e3)}s...`
|
|
484
539
|
);
|
|
485
|
-
schedule(
|
|
486
|
-
() => void connect(sessionId).catch(
|
|
487
|
-
(error) => log.error(`WhatsApp[${sessionId}]: reconnect failed:`, error)
|
|
488
|
-
),
|
|
489
|
-
delay
|
|
490
|
-
);
|
|
540
|
+
schedule(() => attemptConnect(sessionId), delay);
|
|
491
541
|
}
|
|
492
542
|
}
|
|
493
543
|
});
|
|
@@ -505,19 +555,9 @@ function createWhatsAppChannel(config) {
|
|
|
505
555
|
}
|
|
506
556
|
}
|
|
507
557
|
for (const sessionId of sessionIds) {
|
|
508
|
-
void acquireSessionLease(sessionId,
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
sessions,
|
|
512
|
-
isStopped: () => stopped,
|
|
513
|
-
connect,
|
|
514
|
-
now,
|
|
515
|
-
staleMs,
|
|
516
|
-
heartbeatMs,
|
|
517
|
-
waitMs,
|
|
518
|
-
schedule,
|
|
519
|
-
logger: log
|
|
520
|
-
}).catch((error) => log.error(`WhatsApp[${sessionId}]: failed to start:`, error));
|
|
558
|
+
void acquireSessionLease(sessionId, leaseDeps).catch(
|
|
559
|
+
(error) => log.error(`WhatsApp[${sessionId}]: failed to start:`, error)
|
|
560
|
+
);
|
|
521
561
|
}
|
|
522
562
|
},
|
|
523
563
|
async stop() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diegoaltoworks/chatter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"description": "Embeddable AI chatbot framework with RAG, authentication, and customizable widgets",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -201,14 +201,14 @@
|
|
|
201
201
|
"@biomejs/biome": "2.5.8",
|
|
202
202
|
"@commitlint/cli": "21.2.2",
|
|
203
203
|
"@commitlint/config-conventional": "21.2.2",
|
|
204
|
-
"@hono/node-server": "2.1.
|
|
204
|
+
"@hono/node-server": "2.1.1",
|
|
205
205
|
"@libsql/client": "0.17.4",
|
|
206
206
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
207
207
|
"@types/bun": "1.3.14",
|
|
208
208
|
"@types/node": "26.2.0",
|
|
209
209
|
"@whiskeysockets/baileys": "7.0.0-rc14",
|
|
210
210
|
"esbuild": "0.28.2",
|
|
211
|
-
"hono": "4.13.
|
|
211
|
+
"hono": "4.13.2",
|
|
212
212
|
"husky": "9.1.7",
|
|
213
213
|
"lint-staged": "17.3.0",
|
|
214
214
|
"openai": "7.4.0",
|