@diegoaltoworks/chatter 0.36.0 → 0.38.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.
@@ -150,6 +150,144 @@ function loadBaileys() {
150
150
  return cached;
151
151
  }
152
152
 
153
+ // src/channels/whatsapp/pairing.ts
154
+ var RESTART_REQUIRED_STATUS = 515;
155
+ var MAX_PAIRING_RECONNECTS = 12;
156
+ var PAIRING_RECONNECT_DELAY_MS = 2e3;
157
+ var PAIRING_RECONNECT_MAX_DELAY_MS = 8e3;
158
+ var RESTART_REQUIRED_DELAY_MS = 500;
159
+ function pairingReconnectDelayMs(statusCode, attempt) {
160
+ if (statusCode === RESTART_REQUIRED_STATUS) return RESTART_REQUIRED_DELAY_MS;
161
+ return Math.min(
162
+ PAIRING_RECONNECT_DELAY_MS * 2 ** Math.max(0, attempt - 1),
163
+ PAIRING_RECONNECT_MAX_DELAY_MS
164
+ );
165
+ }
166
+ function decidePairingClose(input) {
167
+ if (input.statusCode === input.loggedOutCode) return { kind: "fatal", reason: "loggedOut" };
168
+ if (input.attempts >= input.maxAttempts) return { kind: "fatal", reason: "exhausted" };
169
+ const attempt = input.attempts + 1;
170
+ return {
171
+ kind: "reconnect",
172
+ attempt,
173
+ delayMs: pairingReconnectDelayMs(input.statusCode, attempt)
174
+ };
175
+ }
176
+ function describeError(error) {
177
+ return error instanceof Error ? error.message : String(error);
178
+ }
179
+ function runPairing(deps) {
180
+ const maxAttempts = deps.maxAttempts ?? MAX_PAIRING_RECONNECTS;
181
+ const schedule = deps.schedule ?? ((fn, ms) => {
182
+ setTimeout(fn, ms);
183
+ });
184
+ return new Promise((resolve) => {
185
+ let attempts = 0;
186
+ let generation = 0;
187
+ let codeRequested = false;
188
+ let settled = false;
189
+ const settle = (result) => {
190
+ if (settled) return;
191
+ settled = true;
192
+ resolve(result);
193
+ };
194
+ const status = (message) => deps.onStatus?.(message);
195
+ const requestCode = async (sock) => {
196
+ if (settled || codeRequested || !deps.phoneNumber) return;
197
+ try {
198
+ const code = await sock.requestPairingCode(deps.phoneNumber);
199
+ codeRequested = true;
200
+ deps.onPairingCode?.(code);
201
+ } catch (error) {
202
+ settle({
203
+ ok: false,
204
+ reason: "error",
205
+ message: `Failed to request pairing code: ${describeError(error)}`
206
+ });
207
+ }
208
+ };
209
+ const handleUpdate = async (update, sock) => {
210
+ const { connection, lastDisconnect, qr } = update;
211
+ if (qr && !deps.phoneNumber && deps.onQr) {
212
+ try {
213
+ await deps.onQr(qr);
214
+ } catch (error) {
215
+ status(`QR render failed: ${describeError(error)}`);
216
+ }
217
+ }
218
+ if (connection === "open") {
219
+ settle({ ok: true, userId: sock.user?.id });
220
+ return;
221
+ }
222
+ if (connection === "close") {
223
+ const statusCode = lastDisconnect?.error?.output?.statusCode;
224
+ const action = decidePairingClose({
225
+ statusCode,
226
+ loggedOutCode: deps.loggedOutCode,
227
+ attempts,
228
+ maxAttempts
229
+ });
230
+ if (action.kind === "fatal") {
231
+ settle({
232
+ ok: false,
233
+ reason: action.reason,
234
+ message: action.reason === "loggedOut" ? "Pairing rejected (logged out). Run wa-pair again for a fresh code." : `Gave up after ${maxAttempts} reconnect attempts (last close: ${statusCode ?? "?"}). Run wa-pair again.`
235
+ });
236
+ return;
237
+ }
238
+ attempts = action.attempt;
239
+ generation += 1;
240
+ try {
241
+ sock.end?.();
242
+ } catch (error) {
243
+ status(`Failed to close the previous socket: ${describeError(error)}`);
244
+ }
245
+ status(
246
+ statusCode === RESTART_REQUIRED_STATUS ? `Registered \u2014 WhatsApp asked for a restart (515). Reconnecting to finish the link (${action.attempt}/${maxAttempts})...` : `Connection closed (${statusCode ?? "?"}) \u2014 reconnecting with the stored session (${action.attempt}/${maxAttempts})...`
247
+ );
248
+ schedule(() => void attach(), action.delayMs);
249
+ }
250
+ };
251
+ const attach = async () => {
252
+ if (settled) return;
253
+ const mine = generation;
254
+ const attempt = attempts;
255
+ let sock;
256
+ try {
257
+ sock = await deps.connect(attempt);
258
+ } catch (error) {
259
+ settle({ ok: false, reason: "error", message: describeError(error) });
260
+ return;
261
+ }
262
+ sock.ev.on("connection.update", (update) => {
263
+ if (mine !== generation || settled) return;
264
+ handleUpdate(update, sock).catch((error) => {
265
+ const message = `connection.update handler error: ${describeError(error)}`;
266
+ status(message);
267
+ settle({ ok: false, reason: "error", message });
268
+ });
269
+ });
270
+ if (deps.phoneNumber && !codeRequested) {
271
+ schedule(() => {
272
+ if (mine !== generation) return;
273
+ void requestCode(sock);
274
+ }, deps.requestCodeDelayMs ?? 3e3);
275
+ }
276
+ };
277
+ void attach();
278
+ });
279
+ }
280
+
281
+ // src/channels/whatsapp/qr.ts
282
+ function resolveQrGenerate(mod) {
283
+ if (!mod) return void 0;
284
+ if (mod.default && typeof mod.default.generate === "function") {
285
+ return mod.default.generate.bind(mod.default);
286
+ }
287
+ if (typeof mod.generate === "function") return mod.generate.bind(mod);
288
+ return void 0;
289
+ }
290
+
153
291
  // bin/wa-pair.ts
154
292
  var args = process.argv.slice(2);
155
293
  function flagValue(name) {
@@ -199,10 +337,36 @@ var db = (0, import_client.createClient)({
199
337
  url: process.env.TURSO_URL,
200
338
  authToken: process.env.TURSO_AUTH_TOKEN || ""
201
339
  });
202
- var MAX_RECONNECTS = 12;
203
- var codeRequested = false;
204
- var reconnects = 0;
205
- var didReset = false;
340
+ var printedQrFallbackHelp = false;
341
+ function printQrFallback(qr) {
342
+ if (!printedQrFallbackHelp) {
343
+ printedQrFallbackHelp = true;
344
+ console.log(
345
+ "\nCouldn't render a QR image here. Raw code below (rarely scannable as text\ndirectly, but confirms pairing is alive) \u2014 re-run with --code <phoneNumber>\nfor pairing-code mode instead:\n"
346
+ );
347
+ }
348
+ console.log(qr);
349
+ }
350
+ async function renderQr(qr) {
351
+ const qrcodeTerminal = await import("qrcode-terminal").catch(() => void 0);
352
+ const generate = resolveQrGenerate(qrcodeTerminal);
353
+ if (!generate) {
354
+ if (!printedQrFallbackHelp) {
355
+ console.error(
356
+ "\u274C QR mode requires the optional peer dependency 'qrcode-terminal' (not installed, or its exports weren't recognized). Install it with `bun add qrcode-terminal`, or re-run with --code <phoneNumber> for pairing-code mode instead."
357
+ );
358
+ }
359
+ printQrFallback(qr);
360
+ return;
361
+ }
362
+ console.log("\nScan this QR code: WhatsApp -> Settings -> Linked Devices -> Link a Device.\n");
363
+ try {
364
+ generate(qr, { small: true });
365
+ } catch (error) {
366
+ console.error(`\u274C QR render failed: ${error.message}`);
367
+ printQrFallback(qr);
368
+ }
369
+ }
206
370
  async function start() {
207
371
  const baileys = await loadBaileys().catch((error) => {
208
372
  console.error(`\u274C ${error.message}`);
@@ -213,106 +377,73 @@ async function start() {
213
377
  initAuthCreds: baileys.initAuthCreds,
214
378
  appStateSyncKeyFromObject: (value) => baileys.proto.Message.AppStateSyncKeyData.fromObject(value)
215
379
  };
216
- const { state, saveCreds, clear } = await useTursoAuthState(
217
- db,
218
- sessionSecret,
219
- sessionId,
220
- runtime
221
- );
222
- if (reset && !didReset) {
223
- didReset = true;
380
+ if (reset) {
381
+ const { clear } = await useTursoAuthState(db, sessionSecret, sessionId, runtime);
224
382
  await clear();
225
383
  console.log(`Session "${sessionId}" wiped. Pairing fresh...`);
226
- return start();
227
- }
228
- if (state.creds.registered && !codeRequested) {
229
- console.log(
230
- `Already paired. Session "${sessionId}" is connected-ready. Run with --reset to re-pair.`
231
- );
232
- process.exit(0);
233
384
  }
234
385
  const { version } = await baileys.fetchLatestBaileysVersion();
235
- const noop = () => void 0;
236
- const logger = {
237
- level: "silent",
238
- trace: noop,
239
- debug: noop,
240
- info: noop,
241
- warn: noop,
242
- error: noop,
243
- fatal: noop
244
- };
245
- logger.child = () => logger;
246
- const sock = baileys.makeWASocket({
247
- version,
248
- auth: {
249
- creds: state.creds,
250
- // biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
251
- keys: baileys.makeCacheableSignalKeyStore(state.keys, logger)
252
- },
253
- // biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
254
- logger,
255
- markOnlineOnConnect: false
256
- });
257
- sock.ev.on("creds.update", saveCreds);
258
- sock.ev.on("connection.update", async (update) => {
259
- const { connection, lastDisconnect, qr } = update;
260
- if (qr && !phoneNumber) {
261
- const qrcodeTerminal = await import("qrcode-terminal").catch(() => void 0);
262
- if (!qrcodeTerminal) {
263
- console.error(
264
- "\u274C QR mode requires the optional peer dependency 'qrcode-terminal'. Install it with `bun add qrcode-terminal`, or re-run with --code <phoneNumber> for pairing-code mode instead."
265
- );
266
- process.exit(1);
267
- }
268
- console.log(
269
- "\nScan this QR code: WhatsApp -> Settings -> Linked Devices -> Link a Device.\n"
270
- );
271
- qrcodeTerminal.default.generate(qr, { small: true });
272
- }
273
- if (connection === "open") {
386
+ const connect = async (attempt) => {
387
+ const { state, saveCreds } = await useTursoAuthState(
388
+ db,
389
+ sessionSecret,
390
+ sessionId,
391
+ runtime
392
+ );
393
+ if (attempt === 0 && state.creds.registered) {
274
394
  console.log(
275
- `
276
- \u2705 Paired session "${sessionId}" as ${sock.user?.id}. Session saved (encrypted).`
395
+ `Already paired. Session "${sessionId}" is connected-ready. Run with --reset to re-pair.`
277
396
  );
278
- console.log("The running server will pick this session up on its next connect.");
279
397
  process.exit(0);
280
398
  }
281
- if (connection === "close") {
282
- const statusCode = lastDisconnect?.error?.output?.statusCode;
283
- if (codeRequested && reconnects < MAX_RECONNECTS) {
284
- reconnects++;
285
- console.log(
286
- `Connection closed (${statusCode ?? "?"}) - reconnecting (code STILL VALID, keep going on the phone) (${reconnects}/${MAX_RECONNECTS})...`
287
- );
288
- setTimeout(() => void start(), 2e3);
289
- return;
290
- }
291
- if (statusCode === baileys.DisconnectReason.loggedOut) {
292
- console.error("\u274C Pairing rejected (logged out). Run wa-pair again for a fresh code.");
293
- } else {
294
- console.error(`\u274C Connection closed (${statusCode ?? "?"}). Run wa-pair again.`);
295
- }
296
- process.exit(1);
297
- }
399
+ const noop = () => void 0;
400
+ const logger = {
401
+ level: "silent",
402
+ trace: noop,
403
+ debug: noop,
404
+ info: noop,
405
+ warn: noop,
406
+ error: noop,
407
+ fatal: noop
408
+ };
409
+ logger.child = () => logger;
410
+ const sock = baileys.makeWASocket({
411
+ version,
412
+ auth: {
413
+ creds: state.creds,
414
+ // biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
415
+ keys: baileys.makeCacheableSignalKeyStore(state.keys, logger)
416
+ },
417
+ // biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
418
+ logger,
419
+ markOnlineOnConnect: false
420
+ });
421
+ sock.ev.on("creds.update", saveCreds);
422
+ return sock;
423
+ };
424
+ const result = await runPairing({
425
+ connect,
426
+ loggedOutCode: baileys.DisconnectReason.loggedOut,
427
+ phoneNumber,
428
+ onQr: renderQr,
429
+ onPairingCode: (code) => {
430
+ console.log("\n==============================================");
431
+ console.log(` Pairing code for +${phoneNumber}: ${code}`);
432
+ console.log("==============================================");
433
+ console.log("On the phone: WhatsApp -> Settings -> Linked Devices ->");
434
+ console.log("Link a Device -> 'Link with phone number instead' -> enter the code.");
435
+ console.log("Waiting for confirmation (leave this running)...");
436
+ },
437
+ onStatus: (message) => console.log(message)
298
438
  });
299
- if (phoneNumber && !codeRequested && !state.creds.registered) {
300
- setTimeout(async () => {
301
- try {
302
- const code = await sock.requestPairingCode(phoneNumber);
303
- codeRequested = true;
304
- console.log("\n==============================================");
305
- console.log(` Pairing code for +${phoneNumber}: ${code}`);
306
- console.log("==============================================");
307
- console.log("On the phone: WhatsApp -> Settings -> Linked Devices ->");
308
- console.log("Link a Device -> 'Link with phone number instead' -> enter the code.");
309
- console.log("Waiting for confirmation (leave this running)...");
310
- } catch (error) {
311
- console.error("\u274C Failed to request pairing code:", error);
312
- process.exit(1);
313
- }
314
- }, 3e3);
439
+ if (!result.ok) {
440
+ console.error(`\u274C ${result.message}`);
441
+ process.exit(1);
315
442
  }
443
+ console.log(`
444
+ \u2705 Paired session "${sessionId}" as ${result.userId}. Session saved (encrypted).`);
445
+ console.log("The running server will pick this session up on its next connect.");
446
+ process.exit(0);
316
447
  }
317
448
  start().catch((error) => {
318
449
  console.error("\u274C Unexpected error:", error);
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Pairing loop for the `wa-pair` CLI — the transport-independent half, kept
3
+ * out of the bin so it can be unit-tested against a faked socket.
4
+ *
5
+ * Both pairing modes close the socket mid-flow as a matter of course:
6
+ *
7
+ * - QR mode: the moment a scan registers the device, WhatsApp ALWAYS closes
8
+ * with 515 ("restart required"). The link only completes if the client comes
9
+ * straight back with the SAME credentials it just registered — the phone is
10
+ * sitting on "linking" waiting for exactly that. Exiting there (or wiping
11
+ * creds and starting over) fails the pairing every time.
12
+ * - Pairing-code mode: the socket bounces while the code is being typed.
13
+ *
14
+ * So a close during pairing is normal, not fatal: reconnect with stored creds,
15
+ * bounded, until `open` confirms the link. Only an explicit logout or running
16
+ * out of attempts ends the run.
17
+ */
18
+ /** Baileys' "restart required" — emitted immediately after a QR scan registers the device. */
19
+ export declare const RESTART_REQUIRED_STATUS = 515;
20
+ /** Bounded so a genuinely broken pairing terminates instead of looping forever. */
21
+ export declare const MAX_PAIRING_RECONNECTS = 12;
22
+ /**
23
+ * Backoff between pairing attempts. Deliberately tighter than the transport's
24
+ * 5s→10min ladder (`reconnectDelayMs`): that one protects a long-lived
25
+ * connection from hammering WhatsApp during an outage, whereas here a human is
26
+ * holding a phone that gives the link a limited window — a 515 restart has to
27
+ * be answered at once, and other bounces within seconds.
28
+ */
29
+ export declare function pairingReconnectDelayMs(statusCode: number | undefined, attempt: number): number;
30
+ export type PairingCloseAction = {
31
+ kind: "reconnect";
32
+ attempt: number;
33
+ delayMs: number;
34
+ } | {
35
+ kind: "fatal";
36
+ reason: "loggedOut" | "exhausted";
37
+ };
38
+ export interface PairingCloseInput {
39
+ statusCode?: number;
40
+ /** `DisconnectReason.loggedOut` from the loaded Baileys build. */
41
+ loggedOutCode: number;
42
+ /** Reconnects already spent. */
43
+ attempts: number;
44
+ maxAttempts: number;
45
+ }
46
+ /**
47
+ * Pure: what to do about a `connection: "close"` during pairing. A logout is
48
+ * final (the credentials just got revoked — retrying re-revokes them); every
49
+ * other close is transient until the attempt budget runs out.
50
+ */
51
+ export declare function decidePairingClose(input: PairingCloseInput): PairingCloseAction;
52
+ /** The slice of a Baileys socket the pairing loop uses. */
53
+ export interface PairingSocket {
54
+ ev: {
55
+ on: (event: "connection.update", listener: (update: PairingConnectionUpdate) => void) => void;
56
+ };
57
+ user?: {
58
+ id?: string;
59
+ } | null;
60
+ requestPairingCode: (phoneNumber: string) => Promise<string>;
61
+ /** Closes a superseded socket so it stops writing to the session. */
62
+ end?: (error?: Error) => void;
63
+ }
64
+ export interface PairingConnectionUpdate {
65
+ connection?: string;
66
+ qr?: string;
67
+ lastDisconnect?: {
68
+ error?: unknown;
69
+ } | null;
70
+ }
71
+ export type PairingResult = {
72
+ ok: true;
73
+ userId?: string;
74
+ } | {
75
+ ok: false;
76
+ reason: "loggedOut" | "exhausted" | "error";
77
+ message: string;
78
+ };
79
+ export interface PairingRunDeps {
80
+ /**
81
+ * Opens a socket for `attempt` (0 = first). MUST reuse the stored
82
+ * credentials — a reconnect that starts from blank creds shows a fresh QR
83
+ * instead of finishing the link the phone is waiting on.
84
+ */
85
+ connect: (attempt: number) => PairingSocket | Promise<PairingSocket>;
86
+ loggedOutCode: number;
87
+ /** Digits-only number for pairing-code mode; omit for QR mode. */
88
+ phoneNumber?: string;
89
+ maxAttempts?: number;
90
+ /** Delay before asking for a pairing code, giving the socket time to handshake. */
91
+ requestCodeDelayMs?: number;
92
+ /** Overridable for tests; defaults to `setTimeout`. */
93
+ schedule?: (fn: () => void, ms: number) => void;
94
+ /** Renders the QR (QR mode only). A throw is reported, never swallowed. */
95
+ onQr?: (qr: string) => void | Promise<void>;
96
+ onPairingCode?: (code: string) => void;
97
+ /** Progress lines for the operator (reconnect notices, QR render failures). */
98
+ onStatus?: (message: string) => void;
99
+ }
100
+ /**
101
+ * Runs one pairing to a verdict: resolves `{ ok: true }` when the connection
102
+ * reaches `open` (the link is live), or `{ ok: false }` on logout, attempt
103
+ * exhaustion, or a connect/pairing-code failure. Never rejects.
104
+ */
105
+ export declare function runPairing(deps: PairingRunDeps): Promise<PairingResult>;
106
+ //# sourceMappingURL=pairing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/pairing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pairing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing.test.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/pairing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `qrcode-terminal` is a plain CJS module (`module.exports = { generate, ... }`).
3
+ * Loading it via dynamic `import()` gets interop-wrapped differently depending
4
+ * on the runtime and how the caller itself is bundled: some expose the
5
+ * function only under `.default`, others expose it as a named export too (or
6
+ * only). Resolve every shape here so `wa-pair` never depends on one bundler's
7
+ * interop guess.
8
+ */
9
+ export type QrGenerateFn = (qr: string, options?: {
10
+ small?: boolean;
11
+ }, callback?: (output: string) => void) => void;
12
+ export interface QrTerminalModule {
13
+ default?: {
14
+ generate?: QrGenerateFn;
15
+ };
16
+ generate?: QrGenerateFn;
17
+ }
18
+ /**
19
+ * `generate` reads `this.error` internally (the module's configured error
20
+ * correction level), so it must stay bound to the object it came from —
21
+ * returning it detached, as a bare function reference, throws the moment it
22
+ * runs (`this.error` is `undefined` instead of the module's setting).
23
+ */
24
+ export declare function resolveQrGenerate(mod: QrTerminalModule | undefined): QrGenerateFn | undefined;
25
+ //# sourceMappingURL=qr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,YAAY,GAAG,CACzB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KAChC,IAAI,CAAC;AAEV,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAO7F"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=qr.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.test.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/qr.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegoaltoworks/chatter",
3
- "version": "0.36.0",
3
+ "version": "0.38.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",