@codexverified/baileys 2.13.13 → 2.14.14

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/README.md CHANGED
@@ -40,7 +40,7 @@ The package is maintained by **Codex** under the **CodexVerified** organization.
40
40
  | Property | Value |
41
41
  | --- | --- |
42
42
  | Package | `@codexverified/baileys` |
43
- | Version | `2.13.13` |
43
+ | Version | `2.14.14` |
44
44
  | Runtime | Node.js 20 or newer |
45
45
  | Module format | ESM, with CommonJS compatibility where supported |
46
46
  | Type declarations | Included at `lib/index.d.ts` |
@@ -54,7 +54,7 @@ The package is maintained by **Codex** under the **CodexVerified** organization.
54
54
  | Method | Command | Notes |
55
55
  | --- | --- | --- |
56
56
  | From npm | `npm install @codexverified/baileys` | Standard install when published under your organization |
57
- | From local archive | `npm install ./codex-baileys-2.13.13.tgz` | Place the `.tgz` beside your application |
57
+ | From local archive | `npm install ./codex-baileys-2.14.14.tgz` | Place the `.tgz` beside your application |
58
58
  | Source audit (no scripts) | `npm install --ignore-scripts` | Skips install hooks for local review |
59
59
 
60
60
  Both npm and archive installs use the same import name:
@@ -623,3 +623,57 @@ await sock.relayMessage(jid, preparedMessage, {
623
623
  ```
624
624
 
625
625
  The `participant` option targets recipient-only delivery in a one-to-one chat. `retryParticipants` or `participants` identifies a device for retry resend, while `isSecret`, `protected`, and `me` restrict delivery to the corresponding device classes. These options do not bypass WhatsApp permissions or authorization checks.
626
+
627
+ | Added helper | Purpose |
628
+ | --- | --- |
629
+ | `sendAlbumMessage` | Sends two or more image/video items as an album. |
630
+ | `sendRichTextCopy`, `sendMarkdownQuote`, `sendQuoteCopy` | Rich Markdown responses with optional copy-to-clipboard actions. |
631
+ | `sendBotDiagnostics`, `sendBotCommand`, `sendBotToolResult` | Experimental bot metadata envelopes for diagnostics, commands, and resolved tool calls. |
632
+
633
+ ### Usage
634
+
635
+ ```ts
636
+ await sock.sendAlbumMessage(jid, [
637
+ { type: 'image', data: { url: './one.jpg' } },
638
+ { type: 'image', data: { url: './two.jpg' } }
639
+ ], { caption: 'Album caption' })
640
+ ```
641
+
642
+ ```ts
643
+ await sock.sendRichTextCopy(jid, {
644
+ text: '**Install command**\n\nnpm install @codexverified/baileys',
645
+ copyText: 'npm install @codexverified/baileys',
646
+ copyLabel: 'Copy command'
647
+ })
648
+
649
+ await sock.sendMarkdownQuote(jid, {
650
+ text: 'Instruction:\n\n> Use this exact configuration.'
651
+ })
652
+ ```
653
+
654
+ Bot metadata helpers are experimental and should not be used as authorization or security controls.
655
+
656
+ ```ts
657
+ await sock.sendBotCommand(jid, {
658
+ text: 'Run deployment',
659
+ commandName: 'deploy',
660
+ commandDescription: 'Deploy the current build',
661
+ commandPrompt: 'Deploy the current build'
662
+ })
663
+ ```
664
+
665
+
666
+ ### Interactive rich HTML
667
+
668
+ The compatibility update also exposes `sendRichHtmlMessage`, which uses the interactive GenAI HTML primitive and supports embedded tabs. Only pass trusted, sanitized HTML; this is not a general-purpose HTML sanitizer.
669
+
670
+ ```ts
671
+ await sock.sendRichHtmlMessage(jid, {
672
+ title: 'CODEX TECHNOLOGY',
673
+ html: '<h1>Hello</hi>',
674
+ url: 'https://codex-ai.site',
675
+ trustedSources: ['codex-ai.site']
676
+ })
677
+ ```
678
+
679
+ Multiple tabs can be supplied with `tabs`; each tab may provide its own `html`, `url`, and `trustedSources`. The structure is experimental and depends on WhatsApp client support.
@@ -12,7 +12,7 @@ import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, getBizBinar
12
12
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
13
  import { captureUnifiedResponse, generateButtonGridContent, generateCodeBlockContent, generateLatexContent, generateListContent, generateRichMenuContent, generateTableContent, generateUnifiedResponseContent } from '../Utils/message-composer.js';
14
14
  import { Baron } from './interactive-handler.js';
15
- import { prepareRichResponseMessage, prepareRichGenerationMessage, prepareRichTextMessage, prepareRichImageMessage, prepareRichLinkMessage, prepareHtmlMessage } from '../Utils/rich-message-utils.js';
15
+ import { prepareRichResponseMessage, prepareRichGenerationMessage, prepareRichTextMessage, prepareRichImageMessage, prepareRichLinkMessage, prepareHtmlMessage, prepareRichHtmlMessage } from '../Utils/rich-message-utils.js';
16
16
  import { generateSlotMachineHtml } from '../Utils/games/slot-machine.js';
17
17
  import { generateWebsitePreviewHtml, generateLinkPreviewHtml } from '../Utils/website-preview.js';
18
18
  import { isViewOnceMessage, downloadViewOnceMedia, createRegularMessageFromViewOnce, parseViewOnceInfo } from '../Utils/view-once-utils.js';
@@ -1224,6 +1224,45 @@ export const makeMessagesSocket = (config) => {
1224
1224
  const recipients = normalizeStatusJidList(options.statusJidList || content?.statusJidList);
1225
1225
  return sock.sendMessage(STATUS_JID, { ...content, status: true }, { ...options, broadcast: true, statusJidList: recipients });
1226
1226
  },
1227
+ sendRichTextCopy: async (jid, content = {}, options = {}) => {
1228
+ if (!jid) throw new Boom('sendRichTextCopy requires a target JID', { statusCode: 400 });
1229
+ if (!content.copyText) throw new Boom('sendRichTextCopy requires copyText content', { statusCode: 400 });
1230
+ const fullMsg = await generateWAMessageFromContent(jid, prepareRichQuoteMessage(content), { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
1231
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
1232
+ return fullMsg;
1233
+ },
1234
+ sendMarkdownQuote: async (jid, content = {}, options = {}) => {
1235
+ if (!jid) throw new Boom('sendMarkdownQuote requires a target JID', { statusCode: 400 });
1236
+ const fullMsg = await generateWAMessageFromContent(jid, prepareRichQuoteMessage(content), { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
1237
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
1238
+ return fullMsg;
1239
+ },
1240
+ sendQuoteCopy: async (jid, content = {}, options = {}) => {
1241
+ if (!jid) throw new Boom('sendQuoteCopy requires a target JID', { statusCode: 400 });
1242
+ if (!content.copyText) throw new Boom('sendQuoteCopy requires copyText content', { statusCode: 400 });
1243
+ return socket.sendRichTextCopy(jid, content, options);
1244
+ },
1245
+ sendAlbumMessage: async (jid, medias = [], options = {}) => {
1246
+ if (!jid) throw new Boom('sendAlbumMessage requires a target JID', { statusCode: 400 });
1247
+ if (!Array.isArray(medias) || medias.length < 2) throw new Boom('sendAlbumMessage requires at least two media items', { statusCode: 400 });
1248
+ const album = medias.map((media, index) => { const normalized = media?.type && media?.data ? { [media.type]: media.data } : { ...media }; if (index === 0 && options.caption && !normalized.caption) normalized.caption = options.caption; return normalized; });
1249
+ return socket.sendMessage(jid, { album }, options);
1250
+ },
1251
+ sendBotDiagnostics: async (jid, content = {}, options = {}) => {
1252
+ if (!jid) throw new Boom('sendBotDiagnostics requires a target JID', { statusCode: 400 });
1253
+ const { text = 'Bot diagnostics test', botBackend = 0, toolsUsed = [], isThinking = false, botJid = '867051314767696@bot' } = content;
1254
+ return socket.sendRichGeneration(jid, { text, botMetadata: { botInfrastructureDiagnostics: { botBackend, toolsUsed, isThinking } }, botJid }, undefined, options);
1255
+ },
1256
+ sendBotCommand: async (jid, content = {}, options = {}) => {
1257
+ if (!jid) throw new Boom('sendBotCommand requires a target JID', { statusCode: 400 });
1258
+ const { text = 'Bot command test', commandName = '', commandDescription = '', commandPrompt = '', botJid = '867051314767696@bot' } = content;
1259
+ return socket.sendRichGeneration(jid, { text, botMetadata: { commandMetadata: { commandName, commandDescription, commandPrompt } }, botJid }, undefined, options);
1260
+ },
1261
+ sendBotToolResult: async (jid, content = {}, options = {}) => {
1262
+ if (!jid) throw new Boom('sendBotToolResult requires a target JID', { statusCode: 400 });
1263
+ const { text = 'Bot tool result test', toolCallId = 'tool-' + Date.now(), resolutionData, resolutionDataSerialized, botJid = '867051314767696@bot' } = content;
1264
+ return socket.sendRichGeneration(jid, { text, botMetadata: { resolvedToolCallMetadata: { toolCallId, resolutionDataSerialized: resolutionDataSerialized ?? JSON.stringify(resolutionData ?? {}) } }, botJid }, undefined, options);
1265
+ },
1227
1266
  richMenu: async (jid, content = {}, options = {}) => {
1228
1267
  if (!jid) throw new Boom('richMenu requires a target JID', { statusCode: 400 });
1229
1268
  const message = generateRichMenuContent(content, options.quoted, options);
@@ -2228,6 +2267,15 @@ export const makeMessagesSocket = (config) => {
2228
2267
  return fullMsg;
2229
2268
  };
2230
2269
 
2270
+ /** Sends an interactive GenAI HTML screen with embedded tabs. */
2271
+ socket.sendRichHtmlMessage = async (jid, content = {}, options = {}) => {
2272
+ if (!jid) throw new Boom('sendRichHtmlMessage requires a target JID', { statusCode: 400 });
2273
+ if (!content.html && !(Array.isArray(content.tabs) && content.tabs.length)) throw new Boom('sendRichHtmlMessage requires html or tabs content', { statusCode: 400 });
2274
+ const wrapped = prepareRichHtmlMessage(content);
2275
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
2276
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
2277
+ return fullMsg;
2278
+ };
2231
2279
  socket.sendSlotMachine = async (jid, options = {}, sendOptions = {}) => {
2232
2280
  return socket.sendHtmlMessage(jid, { html: generateSlotMachineHtml(options) }, sendOptions);
2233
2281
  };
@@ -474,6 +474,23 @@ export const prepareCopyToClipboardMessage = (options = {}) => {
474
474
  };
475
475
 
476
476
  /** Build a plain rich-text forwarded response. */
477
+ /** Builds Markdown text with an optional GenAI COPY_TO_CLIPBOARD action section. */
478
+ export const prepareRichQuoteMessage = (options = {}) => {
479
+ const { text = '', copyText, copyLabel = copyText, alignment = 'END' } = options;
480
+ const sections = [{ __typename: 'GenAIUnifiedResponseSection', view_model: { __typename: 'GenAISingleLayoutViewModel', primitive: { __typename: 'GenAIMarkdownTextUXPrimitive', text: String(text), inline_entities: [] } } }];
481
+ if (copyText) sections.push({ __typename: 'GenAIUnifiedResponseSection', view_model: { __typename: 'GenAIAddonActionLayoutViewModel', addon_action_type: 'COPY_TO_CLIPBOARD', addon_action_alignment: alignment, primitives: [{ __typename: 'GenAIMarkdownTextUXPrimitive', text: String(copyLabel || copyText), inline_entities: [] }] } });
482
+ const unified = { response_id: randomUUID(), sections };
483
+ const richResponseMessage = proto.AIRichResponseMessage.create({ submessages: [], messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD, unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) }, contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 } });
484
+ return wrapToBotForwardedMessage(richResponseMessage);
485
+ };
486
+ export const prepareRichHtmlMessage = (options = {}) => {
487
+ const { html = '', trustedSources = [], url = '', title = 'Preview', tabHeader = 'HTML', tabs } = options;
488
+ const tabItems = Array.isArray(tabs) && tabs.length ? tabs : [{ id: 'tab_0', tab_header: tabHeader, html }];
489
+ const embeddedTabs = tabItems.map((tab, index) => ({ id: tab.id || `tab_${index}`, tab_header: tab.tab_header || tab.title || `HTML ${index + 1}`, sections: [{ __typename: 'GenAIUnifiedResponseSection', view_model: { __typename: 'GenAISingleLayoutViewModel', primitive: { __typename: 'GenAIaeacdsnwHtmlPrimitive', payload: String(tab.html ?? tab.payload ?? html).trim(), url: tab.url || url, trusted_sources: tab.trustedSources || trustedSources } } }], step_entries: [] }));
490
+ const unified = { response_id: randomUUID(), sections: [{ view_model: { primitive: { text: `> ${title}`, __typename: 'GenAIMarkdownTextUXPrimitive' }, __typename: 'GenAISingleLayoutViewModel' } }], embedded_screens: [{ title, content: [{ __typename: 'FOAIDNixelButtonSheets', tabs: embeddedTabs }] }] };
491
+ const richResponseMessage = proto.AIRichResponseMessage.create({ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD, submessages: [{ messageType: RichSubMessageType.TEXT, messageText: `> ${title}` }], unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) }, contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 } });
492
+ return wrapToBotForwardedMessage(richResponseMessage);
493
+ };
477
494
  export const prepareRichTextMessage = ({ text = '' } = {}) => prepareRichResponseMessage({ contentText: String(text), noDonation: true });
478
495
 
479
496
  /** Build a rich image forwarded response using a GenAI image primitive. */
@@ -543,3 +560,4 @@ export const buildImaginePrimitive = ({
543
560
  ...(estimatedMs !== undefined ? { estimated_ms: Number(estimatedMs) } : {})
544
561
  };
545
562
  };
563
+
package/lib/index.d.ts CHANGED
@@ -295,6 +295,20 @@ export interface WASocket {
295
295
  /** Alias supporting multiple status recipients. */
296
296
  sendStatusMentions(content: Record<string, unknown>, jids?: string[], options?: Record<string, unknown>): Promise<unknown>;
297
297
  /** Send an experimental Gen4 / Meta-AI-style rich menu card. */
298
+ /** Send ordinary Markdown/text followed by a GenAI COPY_TO_CLIPBOARD action. */
299
+ sendRichTextCopy(jid: string, content: { text?: string; copyText: string; copyLabel?: string; alignment?: 'END' | 'START' | 'CENTER' }, options?: Record<string, unknown>): Promise<unknown>;
300
+ /** Send Markdown content as a rich quote response. */
301
+ sendMarkdownQuote(jid: string, content?: { text?: string }, options?: Record<string, unknown>): Promise<unknown>;
302
+ /** Send a quote plus a COPY_TO_CLIPBOARD action. */
303
+ sendQuoteCopy(jid: string, content: { text?: string; copyText: string; copyLabel?: string; alignment?: 'END' | 'START' | 'CENTER' }, options?: Record<string, unknown>): Promise<unknown>;
304
+ /** Send an experimental album containing at least two image/video items. */
305
+ sendAlbumMessage(jid: string, medias: Array<Record<string, unknown>>, options?: Record<string, unknown>): Promise<unknown>;
306
+ /** Send experimental bot diagnostic metadata. */
307
+ sendBotDiagnostics(jid: string, content?: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
308
+ /** Send experimental bot command metadata. */
309
+ sendBotCommand(jid: string, content?: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
310
+ /** Send experimental resolved tool-call metadata. */
311
+ sendBotToolResult(jid: string, content?: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
298
312
  richMenu(jid: string, content?: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
299
313
  /** Send a rich button-card grid. */
300
314
  sendRichButtonGrid(jid: string, grid: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
@@ -332,6 +346,8 @@ export interface WASocket {
332
346
  /** Send LaTeX expressions using Codecogs PNG URLs. */
333
347
  sendLatexImage(jid: string, options?: { text?: string; expressions?: Array<Record<string, unknown> | string>; headerText?: string; footer?: string }): Promise<unknown>;
334
348
  /** Render and send HTML as a rich response. */
349
+ /** Send an interactive GenAI HTML screen with optional embedded tabs. */
350
+ sendRichHtmlMessage(jid: string, content: { html?: string; title?: string; url?: string; trustedSources?: string[]; tabHeader?: string; tabs?: Array<{ id?: string; tab_header?: string; title?: string; html?: string; payload?: string; url?: string; trustedSources?: string[] }> }, options?: Record<string, unknown>): Promise<unknown>;
335
351
  sendHtmlMessage(jid: string, content: { html: string; trustedSources?: string[] }, options?: Record<string, unknown>): Promise<unknown>;
336
352
  /** Send the built-in HTML slot-machine payload. */
337
353
  sendSlotMachine(jid: string, options?: { title?: string; startingCredits?: number }, sendOptions?: Record<string, unknown>): Promise<unknown>;
@@ -406,3 +422,4 @@ export declare function wrapSocket(socket: WASocket, config?: unknown): WASocket
406
422
  declare function makeWASocket(config: SocketConfig): WASocket;
407
423
  export { makeWASocket };
408
424
  export default makeWASocket;
425
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexverified/baileys",
3
- "version": "2.13.13",
3
+ "version": "2.14.14",
4
4
  "description": "CODEX TECHNOLOGY a premium Baileys developed and built by Dev Codex, with Meta compositing, bot planning replay, welcome flow, rich messages, interactive messages, albums, and more.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",