@codexverified/baileys 2.17.17 → 2.18.18

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
@@ -10,7 +10,7 @@
10
10
 
11
11
  <img src="https://raw.githubusercontent.com/codexverified/CODEX-AI/main/assets/rolling-circle.svg" width="90" alt="CodexVerified rolling circle" />
12
12
 
13
- [![Version](https://img.shields.io/badge/version-2.14.14-00FFF0?style=for-the-badge&labelColor=07111F)](https://www.npmjs.com/package/@codexverified/baileys)
13
+ [![Version](https://img.shields.io/badge/version-2.18.18-00FFF0?style=for-the-badge&labelColor=07111F)](https://www.npmjs.com/package/@codexverified/baileys)
14
14
  [![Developer CODEX](https://img.shields.io/badge/Developer-CODEX-B88CFF?style=for-the-badge&logo=telegram&labelColor=07111F)](https://t.me/codexverified)
15
15
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20-7CFFB2?style=for-the-badge&logo=node.js&logoColor=white&labelColor=07111F)](https://nodejs.org/)
16
16
  [![Powered by codexverified/baileys](https://img.shields.io/badge/powered%20by-codexverified%2Fbaileys-25D366?style=for-the-badge&logo=whatsapp&logoColor=white&labelColor=07111F)](https://www.npmjs.com/package/@codexverified/baileys)
@@ -58,13 +58,14 @@ The package is maintained by **Codex** under the **CodexVerified** organization.
58
58
  - [Comparison references](#comparison-references)
59
59
  - [Additional functional compatibility helpers](#additional-functional-compatibility-helpers)
60
60
  - [AI generation primitive](#ai-generation-primitive)
61
+ - [New AIRich metadata helpers](#new-airich-metadata-helpers)
61
62
 
62
63
  ## At a glance
63
64
 
64
65
  | Property | Value |
65
66
  | --- | --- |
66
67
  | Package | `@codexverified/baileys` |
67
- | Version | `2.17.17` |
68
+ | Version | `2.18.18` |
68
69
  | Runtime | Node.js 20 or newer |
69
70
  | Module format | ESM, with CommonJS compatibility where supported |
70
71
  | Type declarations | Included at `lib/index.d.ts` |
@@ -78,7 +79,7 @@ The package is maintained by **Codex** under the **CodexVerified** organization.
78
79
  | Method | Command | Notes |
79
80
  | --- | --- | --- |
80
81
  | From npm | `npm install @codexverified/baileys` | Standard install when published under your organization |
81
- | From local archive | `npm install ./codex-baileys-2.17.17.tgz` | Place the `.tgz` beside your application |
82
+ | From local archive | `npm install ./codex-baileys-2.18.18.tgz` | Place the `.tgz` beside your application |
82
83
  | Source audit (no scripts) | `npm install --ignore-scripts` | Skips install hooks for local review |
83
84
 
84
85
  Both npm and archive installs use the same import name:
@@ -859,6 +860,81 @@ await sock.sendMiniApp(jid, {
859
860
 
860
861
  The package also exports `BotCapabilityType`, `normalizeBotCapabilities`, `buildBotCapabilityMetadata`, and `buildBotRichResponse` for applications that need to construct compatible bot metadata.
861
862
 
863
+
864
+ ## New AIRich metadata helpers
865
+
866
+ The package includes experimental helpers for protocol-backed rich clients. Rendering depends on the recipient's WhatsApp client version; these helpers do not call Meta AI or any private backend.
867
+
868
+ ```js
869
+ await sock.sendA2UIMessage(jid, {
870
+ type: 'im_a2ui',
871
+ data: {
872
+ version: 'v0.9',
873
+ createSurface: {
874
+ surfaceId: 'custom-card',
875
+ catalogId: 'https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json',
876
+ components: [{ id: 'root', component: 'Column', children: ['title'] }]
877
+ }
878
+ }
879
+ })
880
+
881
+ await sock.sendRichMap(jid, {
882
+ centerLatitude: 6.5244,
883
+ centerLongitude: 3.3792,
884
+ annotations: [{ latitude: 6.53, longitude: 3.38, title: 'Lagos', body: 'Nigeria' }],
885
+ showInfoList: true
886
+ })
887
+
888
+ await sock.sendBotPromptSuggestions(jid, {
889
+ text: 'Choose a follow-up',
890
+ suggestions: ['Summarize this', 'Translate this', 'Explain further'],
891
+ selectedPromptId: 'translate'
892
+ })
893
+
894
+ await sock.sendBotSources(jid, {
895
+ text: 'Relevant sources:',
896
+ sources: [{
897
+ provider: 2,
898
+ url: 'https://example.com/docs',
899
+ query: 'baileys proto',
900
+ title: 'Documentation',
901
+ citationNumber: 1
902
+ }]
903
+ })
904
+
905
+ await sock.sendRichDynamicMedia(jid, {
906
+ type: 'IMAGE',
907
+ url: 'https://example.com/image.jpg',
908
+ version: 1
909
+ })
910
+
911
+ await sock.sendBotPttTranscript(jid, {
912
+ text: 'Voice transcript',
913
+ transcript: 'Hello, this text came from a voice message.'
914
+ })
915
+
916
+ await sock.sendSocialEntity(jid, {
917
+ platform: 'YOUTUBE',
918
+ username: 'example',
919
+ title: 'Example creator',
920
+ imageUrl: 'https://example.com/avatar.png',
921
+ entityUrl: 'https://www.youtube.com/@example',
922
+ isVerified: true,
923
+ resultText: 'See results'
924
+ })
925
+
926
+ await sock.sendInstagramProfile(jid, {
927
+ username: 'example',
928
+ title: 'Example profile',
929
+ imageUrl: 'https://example.com/avatar.png',
930
+ entityUrl: 'https://www.instagram.com/example',
931
+ isVerified: true,
932
+ resultText: 'See results'
933
+ })
934
+ ```
935
+
936
+ The map, prompt, source, dynamic-media, transcript, A2UI, and social/entity payloads are serialized from the generated `WAProto` structures. Validate URLs, button identifiers, and any user-supplied metadata in your own application before sending.
937
+
862
938
  <div align="center">
863
939
 
864
940
  <sub>Thanks for reading my README.</sub>
@@ -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, prepareA2UICommandMenu, prepareAIRichCommandMenu, prepareVideoGridMessage, prepareVerticalAlbumMessage, prepareHtmlMessage, prepareRichHtmlMessage } from '../Utils/rich-message-utils.js';
15
+ import { prepareRichResponseMessage, prepareRichGenerationMessage, prepareRichTextMessage, prepareRichImageMessage, prepareRichLinkMessage, prepareA2UICommandMenu, prepareAIRichCommandMenu, prepareVideoGridMessage, prepareVerticalAlbumMessage, prepareHtmlMessage, prepareRichHtmlMessage, prepareA2UIMessage, prepareBotPromptSuggestionsMessage, prepareBotPttTranscriptMessage, prepareBotSourcesMessage, prepareInstagramProfileMessage, prepareRichDynamicMediaMessage, prepareRichMapMessage, prepareSocialEntityMessage } from '../Utils/rich-message-utils.js';
16
16
  import { generateSlotMachineHtml } from '../Utils/games/slot-machine.js';
17
17
  import { generateMiniAppHtml } from '../Utils/games/miniapp.js';
18
18
  import { generateWebsitePreviewHtml, generateLinkPreviewHtml } from '../Utils/website-preview.js';
@@ -1307,7 +1307,7 @@ export const makeMessagesSocket = (config) => {
1307
1307
  ]
1308
1308
  });
1309
1309
  const fullMsg = await generateWAMessageFromContent(jid, wrapped, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
1310
- await relayRichMessage(jid, fullMsg, options);
1310
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1311
1311
  return fullMsg;
1312
1312
  },
1313
1313
  sendBotToolResult: async (jid, content = {}, options = {}) => {
@@ -1322,6 +1322,111 @@ export const makeMessagesSocket = (config) => {
1322
1322
  await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
1323
1323
  return fullMsg;
1324
1324
  },
1325
+ sendA2UIMessage: async (jid, content = {}, options = {}) => {
1326
+ if (!jid) throw new Boom('sendA2UIMessage requires a target JID', { statusCode: 400 });
1327
+ const { image, ...payload } = content || {};
1328
+ let imageMessage;
1329
+ if (image) {
1330
+ const prepared = await prepareWAMessageMedia({ image }, { upload: waUploadToServer });
1331
+ imageMessage = prepared.imageMessage;
1332
+ }
1333
+ const wrapped = prepareA2UIMessage({ ...payload, imageMessage });
1334
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1335
+ logger,
1336
+ userJid: authState.creds.me?.id,
1337
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id || jid),
1338
+ ...options,
1339
+ });
1340
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options, forceRichEdit: true });
1341
+ if (config.emitOwnEvents) process.nextTick(async () => { await messageMutex.mutex(() => upsertMessage(fullMsg, 'append')); });
1342
+ return fullMsg;
1343
+ },
1344
+ sendBotPromptSuggestions: async (jid, content = {}, options = {}) => {
1345
+ if (!jid) throw new Boom('sendBotPromptSuggestions requires a target JID', { statusCode: 400 });
1346
+ const wrapped = prepareBotPromptSuggestionsMessage(content);
1347
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1348
+ logger,
1349
+ userJid: authState.creds.me?.id,
1350
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id),
1351
+ ...options
1352
+ });
1353
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1354
+ return fullMsg;
1355
+ },
1356
+ sendBotPttTranscript: async (jid, content = {}, options = {}) => {
1357
+ if (!jid) throw new Boom('sendBotPttTranscript requires a target JID', { statusCode: 400 });
1358
+ const wrapped = prepareBotPttTranscriptMessage(content);
1359
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1360
+ logger,
1361
+ userJid: authState.creds.me?.id,
1362
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id),
1363
+ ...options
1364
+ });
1365
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1366
+ return fullMsg;
1367
+ },
1368
+ sendBotSources: async (jid, content = {}, options = {}) => {
1369
+ if (!jid) throw new Boom('sendBotSources requires a target JID', { statusCode: 400 });
1370
+ const wrapped = prepareBotSourcesMessage(content);
1371
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1372
+ logger,
1373
+ userJid: authState.creds.me?.id,
1374
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id),
1375
+ ...options
1376
+ });
1377
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1378
+ return fullMsg;
1379
+ },
1380
+ sendInstagramProfile: async (jid, content = {}, options = {}) => {
1381
+ if (!jid) throw new Boom('sendInstagramProfile requires a target JID', { statusCode: 400 });
1382
+ const wrapped = prepareInstagramProfileMessage(content);
1383
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1384
+ logger,
1385
+ userJid: authState.creds.me?.id,
1386
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id || jid),
1387
+ ...options
1388
+ });
1389
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1390
+ if (config.emitOwnEvents) process.nextTick(async () => { await messageMutex.mutex(() => upsertMessage(fullMsg, 'append')); });
1391
+ return fullMsg;
1392
+ },
1393
+ sendRichDynamicMedia: async (jid, content = {}, options = {}) => {
1394
+ if (!jid) throw new Boom('sendRichDynamicMedia requires a target JID', { statusCode: 400 });
1395
+ const wrapped = prepareRichDynamicMediaMessage(content);
1396
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1397
+ logger,
1398
+ userJid: authState.creds.me?.id,
1399
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id),
1400
+ ...options
1401
+ });
1402
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1403
+ return fullMsg;
1404
+ },
1405
+ sendRichMap: async (jid, content = {}, options = {}) => {
1406
+ if (!jid) throw new Boom('sendRichMap requires a target JID', { statusCode: 400 });
1407
+ const wrapped = prepareRichMapMessage(content);
1408
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1409
+ logger,
1410
+ userJid: authState.creds.me?.id,
1411
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id),
1412
+ ...options
1413
+ });
1414
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1415
+ return fullMsg;
1416
+ },
1417
+ sendSocialEntity: async (jid, content = {}, options = {}) => {
1418
+ if (!jid) throw new Boom('sendSocialEntity requires a target JID', { statusCode: 400 });
1419
+ const wrapped = prepareSocialEntityMessage(content);
1420
+ const fullMsg = await generateWAMessageFromContent(jid, wrapped, {
1421
+ logger,
1422
+ userJid: authState.creds.me?.id,
1423
+ messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id || jid),
1424
+ ...options,
1425
+ });
1426
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1427
+ if (config.emitOwnEvents) process.nextTick(async () => { await messageMutex.mutex(() => upsertMessage(fullMsg, 'append')); });
1428
+ return fullMsg;
1429
+ },
1325
1430
  /** Send the large A2UI command menu with an uploaded image header, rows, and URL buttons. */
1326
1431
  /** Sends the manually serialized AIRich command card shown in the screenshot. */
1327
1432
  sendAIRichCommandMenu: async (jid, content = {}, options = {}) => {
@@ -1333,7 +1438,7 @@ export const makeMessagesSocket = (config) => {
1333
1438
  messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id || jid),
1334
1439
  ...options,
1335
1440
  });
1336
- await relayRichMessage(jid, fullMsg, options);
1441
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1337
1442
  if (config.emitOwnEvents) {
1338
1443
  process.nextTick(async () => {
1339
1444
  await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
@@ -2431,7 +2536,7 @@ export const makeMessagesSocket = (config) => {
2431
2536
  messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id || jid),
2432
2537
  ...options
2433
2538
  });
2434
- await relayRichMessage(jid, fullMsg, options);
2539
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
2435
2540
  if (config.emitOwnEvents) {
2436
2541
  process.nextTick(async () => {
2437
2542
  await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
@@ -504,7 +504,7 @@ export const wrapToBotForwardedMessage = (richResponseMessage) => ({
504
504
  */
505
505
  /** Build the A2UI interactive command menu used by the full-size card layout. */
506
506
  /** Build the manually serialized AIRich command menu shown in the screenshot. */
507
- export const prepareAIRichCommandMenu = ({ image, title = 'CODY AI', subtitle = '', code = '', rows = [], buttons = [], footer = 'Developed by - CODY AI', latexImage, latexExpression = '' } = {}) => {
507
+ export const prepareAIRichCommandMenu = ({ image, title = 'CODEX AI', subtitle = '', code = '', rows = [], buttons = [], footer = 'Developed by - CODEX AI', latexImage, latexExpression = '' } = {}) => {
508
508
  if (!image) throw new Error('AIRich command menu requires an image URL');
509
509
  if (!Array.isArray(rows)) throw new Error('AIRich command-menu rows must be an array');
510
510
  if (!Array.isArray(buttons)) throw new Error('AIRich command-menu buttons must be an array');
@@ -531,7 +531,7 @@ export const prepareAIRichCommandMenu = ({ image, title = 'CODY AI', subtitle =
531
531
  return wrapToBotForwardedMessage(richResponseMessage);
532
532
  };
533
533
 
534
- export const prepareA2UICommandMenu = ({ imageMessage, title = 'CODY AI', rows = [], buttons = [], fallback = '' } = {}) => {
534
+ export const prepareA2UICommandMenu = ({ imageMessage, title = 'CODEX AI', rows = [], buttons = [], fallback = '' } = {}) => {
535
535
  if (!Array.isArray(rows)) throw new Error('A2UI command-menu rows must be an array');
536
536
  if (!Array.isArray(buttons)) throw new Error('A2UI command-menu buttons must be an array');
537
537
  const safeRows = rows.map((row, index) => ({
@@ -556,7 +556,7 @@ export const prepareA2UICommandMenu = ({ imageMessage, title = 'CODY AI', rows =
556
556
  { id: `command_${index}`, component: 'Text', text: row.title },
557
557
  { id: `description_${index}`, component: 'Text', text: row.description }
558
558
  ]),
559
- { id: 'footer', component: 'Text', text: 'Developed by - CODY AI', variant: 'caption' }
559
+ { id: 'footer', component: 'Text', text: 'Developed by - CODEX AI', variant: 'caption' }
560
560
  ];
561
561
  if (safeButtons.length) {
562
562
  components.push({ id: 'buttonRow', component: 'Row', justify: 'spaceEvenly', children: safeButtons.flatMap((button, index) => [`buttonLabel_${index}`, `button_${index}`]) });
@@ -748,4 +748,321 @@ export const buildImaginePrimitive = ({
748
748
  };
749
749
  };
750
750
 
751
-
751
+ export const prepareSocialEntityMessage = ({
752
+ username = '',
753
+ platform = 'GENERIC',
754
+ title = 'CODEX AI',
755
+ subtitle = '⚉',
756
+ imageUrl = '',
757
+ entityId,
758
+ entityUrl = '',
759
+ entityType,
760
+ fullName = 'NOT found',
761
+ isVerified = false,
762
+ resultText = 'See results',
763
+ botJid = '867051314767696@bot',
764
+ responseId
765
+ } = {}) => {
766
+ const normalizedPlatform = String(platform || 'GENERIC').toUpperCase();
767
+ const profileUrl = entityUrl || (username ? `https://www.${normalizedPlatform.toLowerCase()}.com/${encodeURIComponent(username)}` : '');
768
+ const resolvedType = entityType || (normalizedPlatform === 'INSTAGRAM' ? 'IG_PROFILE' : 'SOCIAL_PROFILE');
769
+ const displayName = username || fullName || 'Profile';
770
+ const sections = [
771
+ {
772
+ view_model: {
773
+ primitives: [{
774
+ title,
775
+ subtitle,
776
+ ...(imageUrl ? { image: { url: imageUrl, mime_type: 'image/png' } } : {}),
777
+ entity_id: String(entityId ?? username ?? ''),
778
+ entity_url: profileUrl,
779
+ entity_type: 'WEBSITE',
780
+ action_type: 'OPEN_URL',
781
+ is_verified: !!isVerified,
782
+ __typename: 'GenAICompactEntityPrimitive'
783
+ }],
784
+ __typename: 'GenAIActionRowLayoutViewModel'
785
+ }
786
+ },
787
+ {
788
+ view_model: {
789
+ primitives: [{ type: 'HORIZONTAL_LINE', __typename: 'GenAIDividerPrimitive' }],
790
+ __typename: 'GenAIVStackLayoutViewModel'
791
+ }
792
+ },
793
+ {
794
+ view_model: {
795
+ primitives: [
796
+ { __typename: 'GenAISpacerPrimitive' },
797
+ {
798
+ text: `# {{social_entity_1}}${resultText}\0{{/social_entity_1}} `,
799
+ inline_entities: [{
800
+ key: 'social_entity_1',
801
+ metadata: {
802
+ __typename: 'GenAISocialEntityItem',
803
+ entity_id: String(entityId ?? username ?? ''),
804
+ entity_name: displayName,
805
+ entity_full_name: fullName,
806
+ platform: String(platform || 'GENERIC').toUpperCase(),
807
+ entity_picture_url: imageUrl,
808
+ entity_url: profileUrl,
809
+ entity_type: resolvedType,
810
+ platform: normalizedPlatform,
811
+ is_verified: !!isVerified
812
+ }
813
+ }],
814
+ __typename: 'GenAIMarkdownTextUXPrimitive'
815
+ },
816
+ { __typename: 'GenAISpacerPrimitive' }
817
+ ],
818
+ __typename: 'GenAIActionRowLayoutViewModel'
819
+ }
820
+ }
821
+ ];
822
+ return {
823
+ botForwardedMessage: {
824
+ message: {
825
+ richResponseMessage: {
826
+ messageType: 1,
827
+ submessages: [],
828
+ unifiedResponse: {
829
+ response_id: responseId || randomUUID(),
830
+ data: Buffer.from(JSON.stringify({ sections })).toString('base64')
831
+ },
832
+ contextInfo: {
833
+ isForwarded: true,
834
+ forwardOrigin: 4,
835
+ forwardedAiBotMessageInfo: { botJid }
836
+ }
837
+ }
838
+ }
839
+ }
840
+ };
841
+ };
842
+
843
+ /** Dedicated Instagram profile card using the universal social-entity wire format. */
844
+
845
+ export const prepareInstagramProfileMessage = (content = {}) => prepareSocialProfileMessage({
846
+ ...content,
847
+ platform: 'INSTAGRAM',
848
+ entityType: 'IG_PROFILE',
849
+ entityUrl: content.entityUrl || (content.username ? `https://www.instagram.com/${encodeURIComponent(content.username)}` : undefined)
850
+ });
851
+
852
+ export const prepareSocialProfileMessage = (options = {}) => {
853
+ const {
854
+ username,
855
+ platform = 'instagram',
856
+ title = 'CODEX AI',
857
+ subtitle = '⚉',
858
+ imageUrl = '',
859
+ entityId = username,
860
+ entityUrl = `https://www.${platform}.com/${username || ''}`,
861
+ entityType = platform === 'instagram' ? 'IG_PROFILE' : `${String(platform).toUpperCase()}_PROFILE`,
862
+ fullName = 'NOT found',
863
+ isVerified = false,
864
+ resultText = 'See results'
865
+ } = options;
866
+ if (!username || typeof username !== 'string') {
867
+ throw new Boom('sendSocialProfile requires a username', { statusCode: 400 });
868
+ }
869
+ const image = imageUrl ? { url: imageUrl, mime_type: 'image/png' } : undefined;
870
+ const sections = [
871
+ {
872
+ view_model: {
873
+ primitives: [{
874
+ title,
875
+ subtitle,
876
+ ...(image ? { image } : {}),
877
+ entity_id: String(entityId || username),
878
+ entity_url: entityUrl,
879
+ entity_type: 'WEBSITE',
880
+ action_type: 'OPEN_URL',
881
+ is_verified: Boolean(isVerified),
882
+ __typename: 'GenAICompactEntityPrimitive'
883
+ }],
884
+ __typename: 'GenAIActionRowLayoutViewModel'
885
+ }
886
+ },
887
+ {
888
+ view_model: {
889
+ primitives: [{ type: 'HORIZONTAL_LINE', __typename: 'GenAIDividerPrimitive' }],
890
+ __typename: 'GenAIVStackLayoutViewModel'
891
+ }
892
+ },
893
+ {
894
+ view_model: {
895
+ primitives: [
896
+ { __typename: 'GenAISpacerPrimitive' },
897
+ {
898
+ text: `# {{social_entity_1}}${resultText}\0{{/social_entity_1}} `,
899
+ inline_entities: [{
900
+ key: 'social_entity_1',
901
+ metadata: {
902
+ __typename: 'GenAISocialEntityItem',
903
+ entity_id: username,
904
+ entity_name: username,
905
+ entity_full_name: fullName,
906
+ platform: String(platform || 'GENERIC').toUpperCase(),
907
+ entity_picture_url: imageUrl,
908
+ entity_url: entityUrl,
909
+ entity_type: entityType,
910
+ is_verified: Boolean(isVerified)
911
+ }
912
+ }],
913
+ __typename: 'GenAIMarkdownTextUXPrimitive'
914
+ },
915
+ { __typename: 'GenAISpacerPrimitive' }
916
+ ],
917
+ __typename: 'GenAIActionRowLayoutViewModel'
918
+ }
919
+ }
920
+ ];
921
+ const richResponseMessage = proto.AIRichResponseMessage.create({
922
+ submessages: [],
923
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
924
+ unifiedResponse: { data: Buffer.from(JSON.stringify({ sections })) },
925
+ contextInfo: { isForwarded: true, forwardOrigin: 4 }
926
+ });
927
+ return wrapToBotForwardedMessage(richResponseMessage);
928
+ };
929
+
930
+
931
+ /**
932
+ * Builds a generic unified-response envelope without reducing its sections to
933
+ * plain text. This is the extension point for newer WhatsApp primitives that
934
+ * are present in WAProto but do not yet have a dedicated convenience helper.
935
+ */
936
+
937
+ export const prepareRichMapMessage = ({ centerLatitude, centerLongitude, latitudeDelta, longitudeDelta, annotations = [], showInfoList = false, verificationMetadata } = {}) => {
938
+ if (!Number.isFinite(Number(centerLatitude)) || !Number.isFinite(Number(centerLongitude))) {
939
+ throw new Boom('prepareRichMapMessage requires centerLatitude and centerLongitude', { statusCode: 400 });
940
+ }
941
+ const submessages = [{
942
+ messageType: RichSubMessageType.MAP,
943
+ mapMetadata: {
944
+ centerLatitude: Number(centerLatitude),
945
+ centerLongitude: Number(centerLongitude),
946
+ ...(latitudeDelta == null ? {} : { latitudeDelta: Number(latitudeDelta) }),
947
+ ...(longitudeDelta == null ? {} : { longitudeDelta: Number(longitudeDelta) }),
948
+ showInfoList: Boolean(showInfoList),
949
+ annotations: (Array.isArray(annotations) ? annotations : []).map((annotation, index) => ({
950
+ annotationNumber: annotation.annotationNumber ?? index + 1,
951
+ latitude: Number(annotation.latitude),
952
+ longitude: Number(annotation.longitude),
953
+ title: String(annotation.title || ''),
954
+ body: String(annotation.body || '')
955
+ }))
956
+ }
957
+ }];
958
+ const richResponseMessage = proto.AIRichResponseMessage.create({
959
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
960
+ submessages,
961
+ unifiedResponse: { data: Buffer.from(JSON.stringify(toUnified(submessages, randomUUID()))) },
962
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
963
+ });
964
+ return wrapToBotForwardedMessage(richResponseMessage, verificationMetadata);
965
+ };
966
+
967
+ /** Build a rich response carrying BotSuggestedPromptMetadata from WAProto. */
968
+
969
+ export const prepareBotPromptSuggestionsMessage = ({ text = '', suggestions = [], selectedPromptIndex, selectedPromptId, verificationMetadata } = {}) => {
970
+ if (!Array.isArray(suggestions) || suggestions.length === 0) {
971
+ throw new Boom('prepareBotPromptSuggestionsMessage requires at least one suggestion', { statusCode: 400 });
972
+ }
973
+ const envelope = wrapToBotForwardedMessage(proto.AIRichResponseMessage.create({
974
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
975
+ submessages: [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }],
976
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
977
+ }), verificationMetadata);
978
+ envelope.messageContextInfo.botMetadata.suggestedPromptMetadata = {
979
+ suggestedPrompts: suggestions.map(String),
980
+ ...(selectedPromptIndex == null ? {} : { selectedPromptIndex: Number(selectedPromptIndex) }),
981
+ ...(selectedPromptId == null ? {} : { selectedPromptId: String(selectedPromptId) })
982
+ };
983
+ return envelope;
984
+ };
985
+
986
+ /** Build a rich response carrying BotSourcesMetadata for citations/search results. */
987
+
988
+ export const prepareBotSourcesMessage = ({ text = '', sources = [], verificationMetadata } = {}) => {
989
+ if (!Array.isArray(sources) || sources.length === 0) {
990
+ throw new Boom('prepareBotSourcesMessage requires at least one source', { statusCode: 400 });
991
+ }
992
+ const envelope = wrapToBotForwardedMessage(proto.AIRichResponseMessage.create({
993
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
994
+ submessages: [{ messageType: RichSubMessageType.TEXT, messageText: String(text) }],
995
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
996
+ }), verificationMetadata);
997
+ envelope.messageContextInfo.botMetadata.richResponseSourcesMetadata = {
998
+ sources: sources.map((source, index) => ({
999
+ provider: source.provider ?? proto.BotSourcesMetadata.BotSourceItem.SourceProvider.OTHER,
1000
+ thumbnailCdnUrl: source.thumbnailCdnUrl || source.thumbnailUrl || '',
1001
+ sourceProviderUrl: source.sourceProviderUrl || source.url || '',
1002
+ sourceQuery: source.sourceQuery || source.query || '',
1003
+ faviconCdnUrl: source.faviconCdnUrl || source.faviconUrl || '',
1004
+ citationNumber: source.citationNumber ?? index + 1,
1005
+ sourceTitle: source.sourceTitle || source.title || ''
1006
+ }))
1007
+ };
1008
+ return envelope;
1009
+ };
1010
+
1011
+ /** Build an AIRich dynamic image/GIF submessage from WAProto metadata. */
1012
+
1013
+ export const prepareRichDynamicMediaMessage = ({ url = '', type = 'IMAGE', version = 1, loopCount, verificationMetadata } = {}) => {
1014
+ if (!url || typeof url !== 'string') throw new Boom('prepareRichDynamicMediaMessage requires a URL', { statusCode: 400 });
1015
+ const dynamicTypes = proto.AIRichResponseDynamicMetadata.AIRichResponseDynamicMetadataType;
1016
+ const normalizedType = String(type).toUpperCase();
1017
+ const dynamicMetadata = {
1018
+ type: normalizedType === 'GIF'
1019
+ ? dynamicTypes.AI_RICH_RESPONSE_DYNAMIC_METADATA_TYPE_GIF
1020
+ : dynamicTypes.AI_RICH_RESPONSE_DYNAMIC_METADATA_TYPE_IMAGE,
1021
+ version: Number(version),
1022
+ url,
1023
+ ...(loopCount == null ? {} : { loopCount: Number(loopCount) })
1024
+ };
1025
+ const submessages = [{ messageType: RichSubMessageType.DYNAMIC, dynamicMetadata }];
1026
+ const richResponseMessage = proto.AIRichResponseMessage.create({
1027
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1028
+ submessages,
1029
+ unifiedResponse: { data: Buffer.from(JSON.stringify(toUnified(submessages, randomUUID()))) },
1030
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
1031
+ });
1032
+ return wrapToBotForwardedMessage(richResponseMessage, verificationMetadata);
1033
+ };
1034
+
1035
+ /** Build a rich response carrying the exact BotPttPromptMetadata transcript field. */
1036
+
1037
+ export const prepareBotPttTranscriptMessage = ({ text = '', transcript = '', verificationMetadata } = {}) => {
1038
+ if (!transcript || typeof transcript !== 'string') {
1039
+ throw new Boom('prepareBotPttTranscriptMessage requires a transcript', { statusCode: 400 });
1040
+ }
1041
+ const envelope = wrapToBotForwardedMessage(proto.AIRichResponseMessage.create({
1042
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
1043
+ submessages: [{ messageType: RichSubMessageType.TEXT, messageText: String(text || transcript) }],
1044
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
1045
+ }), verificationMetadata);
1046
+ envelope.messageContextInfo.botMetadata.pttPromptMetadata = { transcript };
1047
+ return envelope;
1048
+ };
1049
+
1050
+ export const prepareA2UIMessage = ({ imageMessage, bloksWidget = {}, nativeFlowMessage, fallback = '', ...interactiveFields } = {}) => ({
1051
+ interactiveMessage: {
1052
+ ...interactiveFields,
1053
+ ...(imageMessage ? { header: { imageMessage, hasMediaAttachment: true } } : {}),
1054
+ bloksWidget: {
1055
+ type: bloksWidget.type || 'im_a2ui',
1056
+ data: typeof bloksWidget.data === 'string' ? bloksWidget.data : JSON.stringify(bloksWidget.data || {}),
1057
+ ...(bloksWidget.fallback || fallback ? { fallback: String(bloksWidget.fallback || fallback) } : {})
1058
+ },
1059
+ ...(nativeFlowMessage ? {
1060
+ nativeFlowMessage: {
1061
+ ...nativeFlowMessage,
1062
+ ...(nativeFlowMessage.buttons ? { buttons: nativeFlowMessage.buttons } : {})
1063
+ }
1064
+ } : {})
1065
+ }
1066
+ });
1067
+
1068
+ /** Build the A2UI interactive command menu used by the full-size card layout. */
package/lib/index.d.ts CHANGED
@@ -121,6 +121,83 @@ export interface AIPromptOptions {
121
121
  [key: string]: unknown;
122
122
  }
123
123
 
124
+ export interface SocialEntityContent {
125
+ username?: string;
126
+ platform?: string;
127
+ title?: string;
128
+ subtitle?: string;
129
+ imageUrl?: string;
130
+ entityId?: string | number;
131
+ entityUrl?: string;
132
+ entityType?: string;
133
+ fullName?: string;
134
+ isVerified?: boolean;
135
+ resultText?: string;
136
+ botJid?: string;
137
+ responseId?: string;
138
+ }
139
+
140
+ export interface RichMapAnnotation {
141
+ annotationNumber?: number;
142
+ latitude: number;
143
+ longitude: number;
144
+ title?: string;
145
+ body?: string;
146
+ }
147
+
148
+ export interface RichMapContent {
149
+ centerLatitude: number;
150
+ centerLongitude: number;
151
+ latitudeDelta?: number;
152
+ longitudeDelta?: number;
153
+ annotations?: RichMapAnnotation[];
154
+ showInfoList?: boolean;
155
+ verificationMetadata?: Record<string, unknown>;
156
+ }
157
+
158
+ export interface BotPromptSuggestionsContent {
159
+ text?: string;
160
+ suggestions: string[];
161
+ selectedPromptIndex?: number;
162
+ selectedPromptId?: string;
163
+ verificationMetadata?: Record<string, unknown>;
164
+ }
165
+
166
+ export interface BotSourceContent {
167
+ provider?: number;
168
+ thumbnailCdnUrl?: string;
169
+ thumbnailUrl?: string;
170
+ sourceProviderUrl?: string;
171
+ url?: string;
172
+ sourceQuery?: string;
173
+ query?: string;
174
+ faviconCdnUrl?: string;
175
+ faviconUrl?: string;
176
+ citationNumber?: number;
177
+ sourceTitle?: string;
178
+ title?: string;
179
+ }
180
+
181
+ export interface BotSourcesContent {
182
+ text?: string;
183
+ sources: BotSourceContent[];
184
+ verificationMetadata?: Record<string, unknown>;
185
+ }
186
+
187
+ export interface RichDynamicMediaContent {
188
+ url: string;
189
+ type?: 'IMAGE' | 'GIF' | string;
190
+ version?: number;
191
+ loopCount?: number;
192
+ verificationMetadata?: Record<string, unknown>;
193
+ }
194
+
195
+ export interface BotPttTranscriptContent {
196
+ transcript: string;
197
+ text?: string;
198
+ verificationMetadata?: Record<string, unknown>;
199
+ }
200
+
124
201
  export interface RelayMessageOptions {
125
202
  messageId?: string;
126
203
  /** Recipient-only delivery: skip the sender’s own devices in a one-to-one chat. */
@@ -305,6 +382,22 @@ export interface WASocket {
305
382
  sendQuoteCopy(jid: string, content: { text?: string; copyText: string; copyLabel?: string; alignment?: 'END' | 'START' | 'CENTER' }, options?: Record<string, unknown>): Promise<unknown>;
306
383
  /** Send a full-width stacked AIRich album with at least two image/video URL items. */
307
384
  sendAlbumMessage(jid: string, medias: Array<Record<string, unknown>>, options?: Record<string, unknown>): Promise<unknown>;
385
+ /** Send a provider-neutral AIRich social/entity result card. */
386
+ sendSocialEntity(jid: string, content?: SocialEntityContent, options?: Record<string, unknown>): Promise<unknown>;
387
+ /** Send a protocol-backed AIRich map with optional numbered annotations. */
388
+ sendRichMap(jid: string, content: RichMapContent, options?: Record<string, unknown>): Promise<unknown>;
389
+ /** Send BotSuggestedPromptMetadata with a rich-response text fallback. */
390
+ sendBotPromptSuggestions(jid: string, content: BotPromptSuggestionsContent, options?: Record<string, unknown>): Promise<unknown>;
391
+ /** Send BotSourcesMetadata for citation-aware bot responses. */
392
+ sendBotSources(jid: string, content: BotSourcesContent, options?: Record<string, unknown>): Promise<unknown>;
393
+ /** Send an experimental AIRich dynamic image/GIF submessage. */
394
+ sendRichDynamicMedia(jid: string, content: RichDynamicMediaContent, options?: Record<string, unknown>): Promise<unknown>;
395
+ /** Send BotPttPromptMetadata containing a caller-provided transcript. */
396
+ sendBotPttTranscript(jid: string, content: BotPttTranscriptContent, options?: Record<string, unknown>): Promise<unknown>;
397
+ /** Send the primary Instagram profile result using the universal social/entity format. */
398
+ sendInstagramProfile(jid: string, content: SocialEntityContent, options?: Record<string, unknown>): Promise<unknown>;
399
+ /** Send arbitrary A2UI/interactive payloads with immediate relay/edit rendering. */
400
+ sendA2UIMessage(jid: string, content?: A2UIMessageContent, options?: Record<string, unknown>): Promise<unknown>;
308
401
  /** Send the large A2UI command/function menu with an image header and URL buttons. */
309
402
  sendA2UICommandMenu(jid: string, content?: { image?: unknown; title?: string; rows?: Array<[string, string, string?] | { title?: string; description?: string; id?: string }>; buttons?: Array<{ text?: string; label?: string; url?: string }>; fallback?: string }, options?: Record<string, unknown>): Promise<unknown>;
310
403
  /** Send the manually serialized AIRich command card with image, Markdown, widget CTAs, and footer actions. */
@@ -451,4 +544,5 @@ export declare function buildBotRichResponse(options?: Record<string, unknown>):
451
544
  export declare function prepareVerticalAlbumMessage(options?: { items?: Array<Record<string, unknown>>; verificationMetadata?: Record<string, unknown> }): Record<string, unknown>;
452
545
  export declare function prepareAIRichCommandMenu(options?: { image?: string; title?: string; subtitle?: string; code?: string; rows?: Array<[string, string] | Record<string, unknown>>; buttons?: Array<Record<string, unknown>>; footer?: string; latexImage?: string; latexExpression?: string }): Record<string, unknown>;
453
546
  export declare function prepareVideoGridMessage(options?: { videos?: Array<string | Record<string, unknown>>; verificationMetadata?: Record<string, unknown> }): Record<string, unknown>;
547
+
454
548
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexverified/baileys",
3
- "version": "2.17.17",
3
+ "version": "2.18.18",
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",