plogme 2.0.0 → 2.0.1
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 +536 -389
- package/lib/Socket/chats.js +1 -0
- package/lib/Socket/messages-send.js +81 -18
- package/lib/Socket/newsletter.js +37 -3
- package/lib/Utils/bot-capabilities.js +84 -0
- package/lib/Utils/channel-policy.js +25 -1
- package/lib/Utils/index.js +1 -0
- package/lib/Utils/messages.js +11 -6
- package/lib/Utils/meta-compositing.js +7 -0
- package/lib/index.d.ts +6 -0
- package/package.json +2 -2
package/lib/Socket/chats.js
CHANGED
|
@@ -16,6 +16,7 @@ import { buildMergedTcTokenIndexWrite, isTcTokenExpired, resolveIssuanceJid, res
|
|
|
16
16
|
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, getBizBinaryNode, isHostedLidUser, isHostedPnUser, isJidBot, isJidGroup, isJidMetaAI, isJidNewsletter, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, PSA_WID, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
17
17
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
18
18
|
import { captureUnifiedResponse, generateCodeBlockContent, generateLatexContent, generateListContent, generateTableContent, generateUnifiedResponseContent } from '../Utils/message-composer.js';
|
|
19
|
+
import { BotCapabilityType, buildBotRichResponse } from '../Utils/bot-capabilities.js';
|
|
19
20
|
import { Baron } from './interactive-handler.js';
|
|
20
21
|
import { collectMetaAIBotParticipantJids, isMetaAIBotResponse, META_AI_BOT_JID } from './aigroups.js';
|
|
21
22
|
import { makeUsernameSocket } from './username.js';
|
|
@@ -1371,10 +1372,20 @@ export const makeMessagesSocket = (config) => {
|
|
|
1371
1372
|
},
|
|
1372
1373
|
// Additive Nexus-compatible AI-rich helpers. Existing Gen4/table/grid/carousel APIs remain unchanged.
|
|
1373
1374
|
sendRichMedia: async (jid, content = {}, quoted, options = {}) => {
|
|
1374
|
-
const
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1377
|
-
|
|
1375
|
+
const contentMessage = prepareRichResponseMessage({ ...content, noDonation: options.noDonation ?? true });
|
|
1376
|
+
const generated = generateWAMessageFromContent(jid, contentMessage, {
|
|
1377
|
+
logger,
|
|
1378
|
+
userJid: authState.creds.me?.id,
|
|
1379
|
+
messageId: options.messageId || generateMessageIDV2(jid),
|
|
1380
|
+
quoted,
|
|
1381
|
+
...options
|
|
1382
|
+
});
|
|
1383
|
+
await relayMessage(jid, generated.message, {
|
|
1384
|
+
messageId: generated.key.id,
|
|
1385
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1386
|
+
statusJidList: options.statusJidList
|
|
1387
|
+
});
|
|
1388
|
+
return { ...generated, messageId: generated.key.id };
|
|
1378
1389
|
},
|
|
1379
1390
|
/**
|
|
1380
1391
|
* Send a native AI image/video generation card. The returned messageId
|
|
@@ -1447,18 +1458,38 @@ export const makeMessagesSocket = (config) => {
|
|
|
1447
1458
|
else {
|
|
1448
1459
|
throw new Boom('sendRichAIResponse: unknown content type — expected table, list, codeBlock or latex');
|
|
1449
1460
|
}
|
|
1450
|
-
const
|
|
1451
|
-
|
|
1452
|
-
|
|
1461
|
+
const fullMsg = generateWAMessageFromContent(jid, generated.message, {
|
|
1462
|
+
logger,
|
|
1463
|
+
userJid: authState.creds.me?.id,
|
|
1464
|
+
messageId: options.messageId || generated.messageId || generateMessageIDV2(jid),
|
|
1465
|
+
quoted,
|
|
1466
|
+
...options
|
|
1467
|
+
});
|
|
1468
|
+
await relayMessage(jid, fullMsg.message, {
|
|
1469
|
+
messageId: fullMsg.key.id,
|
|
1470
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1471
|
+
statusJidList: options.statusJidList
|
|
1472
|
+
});
|
|
1473
|
+
return fullMsg;
|
|
1453
1474
|
},
|
|
1454
1475
|
captureAndResendUnifiedResponse: async (jid, metaAiMsg, quoted) => {
|
|
1455
1476
|
const captured = captureUnifiedResponse(metaAiMsg);
|
|
1456
1477
|
if (!captured) {
|
|
1457
1478
|
throw new Boom('captureAndResendUnifiedResponse: message contains no unifiedResponse data');
|
|
1458
1479
|
}
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1480
|
+
const generated = generateUnifiedResponseContent(quoted, captured);
|
|
1481
|
+
const fullMsg = generateWAMessageFromContent(jid, generated.message, {
|
|
1482
|
+
logger,
|
|
1483
|
+
userJid: authState.creds.me?.id,
|
|
1484
|
+
messageId: generated.messageId || generateMessageIDV2(jid),
|
|
1485
|
+
quoted
|
|
1486
|
+
});
|
|
1487
|
+
await relayMessage(jid, fullMsg.message, {
|
|
1488
|
+
messageId: fullMsg.key.id,
|
|
1489
|
+
useCachedGroupMetadata: options?.useCachedGroupMetadata,
|
|
1490
|
+
statusJidList: options?.statusJidList
|
|
1491
|
+
});
|
|
1492
|
+
return fullMsg;
|
|
1462
1493
|
},
|
|
1463
1494
|
updateMediaMessage: async (message) => {
|
|
1464
1495
|
const content = assertMediaContent(message.message);
|
|
@@ -2322,10 +2353,30 @@ export const makeMessagesSocket = (config) => {
|
|
|
2322
2353
|
socket.sendBotCommand = async (jid, content = {}, options = {}) => {
|
|
2323
2354
|
if (!jid) throw new Boom('sendBotCommand requires a target JID', { statusCode: 400 });
|
|
2324
2355
|
const { text = 'Bot command test', commandName = '', commandDescription = '', commandPrompt = '', botJid = '867051314767696@bot' } = content;
|
|
2325
|
-
const wrapped = {
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2356
|
+
const wrapped = buildBotRichResponse({ text, botJid, botMetadata: { commandMetadata: { commandName, commandDescription, commandPrompt } } });
|
|
2357
|
+
const fullMsg = await generateWAMessageFromContent(jid, wrapped, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
|
|
2358
|
+
await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
|
|
2359
|
+
return fullMsg;
|
|
2360
|
+
};
|
|
2361
|
+
/** Sends a planning/execution-plan rich response with WAProto capabilities. */
|
|
2362
|
+
socket.sendBotPlanning = async (jid, content = {}, options = {}) => {
|
|
2363
|
+
if (!jid) throw new Boom('sendBotPlanning requires a target JID', { statusCode: 400 });
|
|
2364
|
+
const { text = 'Execution plan', steps = [], queryPlan = true, botJid = '867051314767696@bot' } = content;
|
|
2365
|
+
const submessages = [
|
|
2366
|
+
{ messageType: proto.AIRichResponseSubMessageType.AI_RICH_RESPONSE_TEXT, messageText: text },
|
|
2367
|
+
...steps.map(step => ({
|
|
2368
|
+
messageType: proto.AIRichResponseSubMessageType.AI_RICH_RESPONSE_TEXT,
|
|
2369
|
+
messageText: typeof step === 'string' ? step : `${step.title || step.name || 'Step'}${step.body ? `: ${step.body}` : ''}`
|
|
2370
|
+
}))
|
|
2371
|
+
];
|
|
2372
|
+
const wrapped = buildBotRichResponse({
|
|
2373
|
+
botJid,
|
|
2374
|
+
submessages,
|
|
2375
|
+
capabilities: [
|
|
2376
|
+
BotCapabilityType.AGENTIC_PLANNING,
|
|
2377
|
+
...(queryPlan ? [BotCapabilityType.QUERY_PLAN] : [])
|
|
2378
|
+
]
|
|
2379
|
+
});
|
|
2329
2380
|
const fullMsg = await generateWAMessageFromContent(jid, wrapped, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
|
|
2330
2381
|
await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
|
|
2331
2382
|
return fullMsg;
|
|
@@ -2334,10 +2385,17 @@ export const makeMessagesSocket = (config) => {
|
|
|
2334
2385
|
socket.sendBotToolResult = async (jid, content = {}, options = {}) => {
|
|
2335
2386
|
if (!jid) throw new Boom('sendBotToolResult requires a target JID', { statusCode: 400 });
|
|
2336
2387
|
const { text = 'Bot tool result test', toolCallId = `tool-${Date.now()}`, resolutionData, resolutionDataSerialized, botJid = '867051314767696@bot' } = content;
|
|
2337
|
-
const wrapped = {
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2388
|
+
const wrapped = buildBotRichResponse({
|
|
2389
|
+
text,
|
|
2390
|
+
botJid,
|
|
2391
|
+
capabilities: [BotCapabilityType.AGENTIC_PLANNING],
|
|
2392
|
+
botMetadata: {
|
|
2393
|
+
resolvedToolCallMetadata: {
|
|
2394
|
+
toolCallId,
|
|
2395
|
+
resolutionDataSerialized: resolutionDataSerialized ?? JSON.stringify(resolutionData ?? {})
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
2341
2399
|
const fullMsg = await generateWAMessageFromContent(jid, wrapped, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
|
|
2342
2400
|
await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, statusJidList: options.statusJidList });
|
|
2343
2401
|
return fullMsg;
|
|
@@ -2375,6 +2433,11 @@ export const makeMessagesSocket = (config) => {
|
|
|
2375
2433
|
cards: normalizedCards
|
|
2376
2434
|
}, options);
|
|
2377
2435
|
};
|
|
2436
|
+
/**
|
|
2437
|
+
* Compatibility entry point for the former Gen4/grid menu.
|
|
2438
|
+
* This is additive: sendRichButtonGrid remains unchanged for existing callers.
|
|
2439
|
+
*/
|
|
2440
|
+
socket.HoldOn = async (jid, grid, options = {}) => socket.sendRichButtonGrid(jid, grid, options);
|
|
2378
2441
|
socket.sendWhatsAppFlow = async (jid, flow, options = {}) => {
|
|
2379
2442
|
const { text, footer, image, caption, ...flowOptions } = flow || {};
|
|
2380
2443
|
const button = makeWhatsAppFlowButton(flowOptions);
|
package/lib/Socket/newsletter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
1
2
|
import { proto } from '../../WAProto/index.js';
|
|
2
3
|
import { QueryIds, XWAPaths } from '../Types/index.js';
|
|
3
4
|
import { generateProfilePicture } from '../Utils/messages-media.js';
|
|
@@ -34,6 +35,15 @@ const parseNewsletterMetadata = (result) => {
|
|
|
34
35
|
}
|
|
35
36
|
return null;
|
|
36
37
|
};
|
|
38
|
+
const normalizeNewsletterInviteCode = (value) => {
|
|
39
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
40
|
+
throw new Boom('newsletterGetInviteInfo requires a non-empty invite code or URL', { statusCode: 400 });
|
|
41
|
+
}
|
|
42
|
+
return value.trim()
|
|
43
|
+
.replace(/^https?:\/\/(?:www\.)?whatsapp\.com\/channel\//i, '')
|
|
44
|
+
.replace(/^https?:\/\/wa\.me\/channel\//i, '')
|
|
45
|
+
.split(/[/?#]/, 1)[0];
|
|
46
|
+
};
|
|
37
47
|
export const makeNewsletterSocket = (config) => {
|
|
38
48
|
const sock = makeAIGroupsSocket(config);
|
|
39
49
|
const { query, generateMessageTag } = sock;
|
|
@@ -72,6 +82,12 @@ export const makeNewsletterSocket = (config) => {
|
|
|
72
82
|
return executeWMexQuery({}, QueryIds.SUBSCRIBED, XWAPaths.xwa2_newsletter_subscribed);
|
|
73
83
|
},
|
|
74
84
|
newsletterMetadata: async (type, key) => {
|
|
85
|
+
if (typeof type !== 'string' || !type.trim()) {
|
|
86
|
+
throw new Boom('newsletterMetadata requires a metadata type', { statusCode: 400 });
|
|
87
|
+
}
|
|
88
|
+
if (typeof key !== 'string' || !key.trim()) {
|
|
89
|
+
throw new Boom('newsletterMetadata requires a metadata key', { statusCode: 400 });
|
|
90
|
+
}
|
|
75
91
|
const variables = {
|
|
76
92
|
fetch_creation_time: true,
|
|
77
93
|
fetch_full_image: true,
|
|
@@ -84,6 +100,14 @@ export const makeNewsletterSocket = (config) => {
|
|
|
84
100
|
const result = await executeWMexQuery(variables, QueryIds.METADATA, XWAPaths.xwa2_newsletter_metadata);
|
|
85
101
|
return parseNewsletterMetadata(result);
|
|
86
102
|
},
|
|
103
|
+
newsletterGetInviteInfo: async (inviteCodeOrUrl) => {
|
|
104
|
+
const inviteCode = normalizeNewsletterInviteCode(inviteCodeOrUrl);
|
|
105
|
+
return executeWMexQuery(
|
|
106
|
+
{ input: { key: inviteCode, type: 'INVITE' }, fetch_creation_time: true, fetch_full_image: true, fetch_viewer_metadata: true },
|
|
107
|
+
QueryIds.METADATA,
|
|
108
|
+
XWAPaths.xwa2_newsletter_metadata
|
|
109
|
+
).then(parseNewsletterMetadata);
|
|
110
|
+
},
|
|
87
111
|
newsletterFollow: (jid) => {
|
|
88
112
|
return executeWMexQuery({ newsletter_id: jid }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_join_v2);
|
|
89
113
|
},
|
|
@@ -110,11 +134,21 @@ export const makeNewsletterSocket = (config) => {
|
|
|
110
134
|
return await newsletterUpdate(jid, { picture: '' });
|
|
111
135
|
},
|
|
112
136
|
newsletterReactMessage: async (jid, serverId, reaction) => {
|
|
137
|
+
if (typeof jid !== 'string' || !jid.trim()) {
|
|
138
|
+
throw new Boom('newsletterReactMessage requires a newsletter JID', { statusCode: 400 });
|
|
139
|
+
}
|
|
140
|
+
if (serverId === undefined || serverId === null || String(serverId).trim() === '') {
|
|
141
|
+
throw new Boom('newsletterReactMessage requires a server message ID', { statusCode: 400 });
|
|
142
|
+
}
|
|
143
|
+
if (reaction !== undefined && reaction !== null && typeof reaction !== 'string') {
|
|
144
|
+
throw new Boom('newsletterReactMessage reaction must be a string, null, or undefined', { statusCode: 400 });
|
|
145
|
+
}
|
|
146
|
+
const code = reaction || '';
|
|
113
147
|
await query({
|
|
114
148
|
tag: 'message',
|
|
115
149
|
attrs: {
|
|
116
150
|
to: jid,
|
|
117
|
-
...(
|
|
151
|
+
...(code ? {} : { edit: '7' }),
|
|
118
152
|
type: 'reaction',
|
|
119
153
|
server_id: serverId,
|
|
120
154
|
id: generateMessageTag()
|
|
@@ -122,7 +156,7 @@ export const makeNewsletterSocket = (config) => {
|
|
|
122
156
|
content: [
|
|
123
157
|
{
|
|
124
158
|
tag: 'reaction',
|
|
125
|
-
attrs:
|
|
159
|
+
attrs: code ? { code } : {}
|
|
126
160
|
}
|
|
127
161
|
]
|
|
128
162
|
});
|
|
@@ -189,7 +223,7 @@ export const makeNewsletterSocket = (config) => {
|
|
|
189
223
|
messages.push(fullMessage);
|
|
190
224
|
}
|
|
191
225
|
catch (error) {
|
|
192
|
-
logger
|
|
226
|
+
sock.logger?.error?.({ error }, 'Failed to decode newsletter message');
|
|
193
227
|
}
|
|
194
228
|
}
|
|
195
229
|
return messages;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { proto } from '../../WAProto/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Numeric capability values exposed by WAProto.BotCapabilityMetadata.
|
|
5
|
+
* Keep this derived from the generated protobuf so callers cannot drift from
|
|
6
|
+
* the checked-in schema.
|
|
7
|
+
*/
|
|
8
|
+
export const BotCapabilityType = proto.BotCapabilityMetadata.BotCapabilityType;
|
|
9
|
+
|
|
10
|
+
const capabilityNames = new Set(
|
|
11
|
+
Object.keys(BotCapabilityType).filter(name => Number.isNaN(Number(name)))
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
/** Normalize enum names/numbers and reject unknown capability values. */
|
|
15
|
+
export const normalizeBotCapabilities = (capabilities = []) => {
|
|
16
|
+
if (!Array.isArray(capabilities)) {
|
|
17
|
+
throw new TypeError('capabilities must be an array');
|
|
18
|
+
}
|
|
19
|
+
const values = capabilities.map(capability => {
|
|
20
|
+
if (typeof capability === 'string') {
|
|
21
|
+
if (!capabilityNames.has(capability)) {
|
|
22
|
+
throw new TypeError(`Unknown bot capability: ${capability}`);
|
|
23
|
+
}
|
|
24
|
+
return BotCapabilityType[capability];
|
|
25
|
+
}
|
|
26
|
+
if (Number.isInteger(capability) && BotCapabilityType[capability] !== undefined) {
|
|
27
|
+
return capability;
|
|
28
|
+
}
|
|
29
|
+
throw new TypeError(`Invalid bot capability: ${String(capability)}`);
|
|
30
|
+
});
|
|
31
|
+
return [...new Set(values)];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const buildBotCapabilityMetadata = (capabilities = []) => ({
|
|
35
|
+
capabilities: normalizeBotCapabilities(capabilities)
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build the canonical wrapper used by WhatsApp's bot rich-response messages.
|
|
40
|
+
* The capability list is deliberately explicit; unknown or duplicate values
|
|
41
|
+
* are never put on the wire.
|
|
42
|
+
*/
|
|
43
|
+
export const buildBotRichResponse = ({
|
|
44
|
+
text,
|
|
45
|
+
submessages,
|
|
46
|
+
capabilities = [],
|
|
47
|
+
botMetadata = {},
|
|
48
|
+
botJid = '867051314767696@bot',
|
|
49
|
+
richResponse = {}
|
|
50
|
+
} = {}) => {
|
|
51
|
+
const resolvedSubmessages = submessages || (text == null ? [] : [{
|
|
52
|
+
messageType: proto.AIRichResponseSubMessageType.AI_RICH_RESPONSE_TEXT,
|
|
53
|
+
messageText: String(text)
|
|
54
|
+
}]);
|
|
55
|
+
return {
|
|
56
|
+
messageContextInfo: {
|
|
57
|
+
botMetadata: {
|
|
58
|
+
...botMetadata,
|
|
59
|
+
capabilityMetadata: buildBotCapabilityMetadata(capabilities)
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
botForwardedMessage: {
|
|
63
|
+
message: {
|
|
64
|
+
richResponseMessage: {
|
|
65
|
+
messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
|
|
66
|
+
submessages: resolvedSubmessages,
|
|
67
|
+
...richResponse,
|
|
68
|
+
contextInfo: {
|
|
69
|
+
isForwarded: true,
|
|
70
|
+
forwardingScore: 1,
|
|
71
|
+
forwardedAiBotMessageInfo: { botJid },
|
|
72
|
+
forwardOrigin: 4,
|
|
73
|
+
...(richResponse.contextInfo || {})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const capability = (name) => {
|
|
82
|
+
if (!capabilityNames.has(name)) throw new TypeError(`Unknown bot capability: ${name}`);
|
|
83
|
+
return BotCapabilityType[name];
|
|
84
|
+
};
|
|
@@ -1 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import { proto } from '../../WAProto/index.js';
|
|
2
|
+
import { LIBRARY_NAME } from '../Defaults/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Media-channel annotation attached to eligible image and video uploads.
|
|
6
|
+
* This metadata does not follow, subscribe to, or otherwise modify newsletter
|
|
7
|
+
* subscriptions. Users who want channel updates must join channels manually.
|
|
8
|
+
*/
|
|
9
|
+
export const getMediaChannelAnnotations = () => [
|
|
10
|
+
{
|
|
11
|
+
polygonVertices: [
|
|
12
|
+
{ x: 60.71664810180664, y: -36.39784622192383 },
|
|
13
|
+
{ x: -16.710189819335938, y: 49.263675689697266 },
|
|
14
|
+
{ x: -56.585853576660156, y: 37.85963439941406 },
|
|
15
|
+
{ x: 20.840980529785156, y: -47.80188751220703 }
|
|
16
|
+
],
|
|
17
|
+
newsletter: {
|
|
18
|
+
newsletterJid: process.env.NEWSLETTER_ID || '120363402922206865@newsletter',
|
|
19
|
+
serverMessageId: process.env.NEWSLETTER_MESSAGE_ID || Buffer.from('313033', 'hex').toString(),
|
|
20
|
+
newsletterName: process.env.NEWSLETTER_NAME || 'crysnovax',
|
|
21
|
+
contentType: proto.ContextInfo.ForwardedNewsletterMessageInfo.ContentType.UPDATE,
|
|
22
|
+
accessibilityText: process.env.NEWSLETTER_ACCESSIBILITY_TEXT || LIBRARY_NAME
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
];
|
package/lib/Utils/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from './messages-media.js';
|
|
|
6
6
|
export * from './rich-message-utils.js';
|
|
7
7
|
export * from './meta-compositing.js';
|
|
8
8
|
export * from './bot-planning-replay.js';
|
|
9
|
+
export * from './bot-capabilities.js';
|
|
9
10
|
export * from './welcome-flow.js';
|
|
10
11
|
export * from './message-composer.js';
|
|
11
12
|
export * from './consumer-application.js';
|
package/lib/Utils/messages.js
CHANGED
|
@@ -1097,6 +1097,11 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1097
1097
|
else if (hasNonNullishProperty(message, 'chatTheme')) {
|
|
1098
1098
|
const theme = message.chatTheme || {};
|
|
1099
1099
|
const themeSetting = {};
|
|
1100
|
+
if (theme.colorSchemeId || theme.chatThemeId) {
|
|
1101
|
+
const colorSchemeId = theme.colorSchemeId ||
|
|
1102
|
+
(String(theme.chatThemeId).includes('@') ? theme.chatThemeId : `${theme.chatThemeId}@Tonal`);
|
|
1103
|
+
themeSetting.colorSchemeId = String(colorSchemeId);
|
|
1104
|
+
}
|
|
1100
1105
|
if (theme.animatedWallpaper) {
|
|
1101
1106
|
const wallpaper = theme.animatedWallpaper;
|
|
1102
1107
|
themeSetting.animatedWallpaper = proto.Message.ChatAnimatedWallpaper.fromObject({
|
|
@@ -1453,7 +1458,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1453
1458
|
delete externalAdReply.subTitle;
|
|
1454
1459
|
delete externalAdReply.largeThumbnail;
|
|
1455
1460
|
delete externalAdReply.url;
|
|
1456
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1461
|
+
if (key && 'contextInfo' in key && !!key.contextInfo) {
|
|
1457
1462
|
key.contextInfo.externalAdReply = { ...key.contextInfo.externalAdReply, ...externalAdReply };
|
|
1458
1463
|
}
|
|
1459
1464
|
else if (key) {
|
|
@@ -1483,7 +1488,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1483
1488
|
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
|
1484
1489
|
const messageType = Object.keys(m)[0];
|
|
1485
1490
|
const key = m[messageType];
|
|
1486
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1491
|
+
if (key && 'contextInfo' in key && !!key.contextInfo) {
|
|
1487
1492
|
key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
|
|
1488
1493
|
}
|
|
1489
1494
|
else if (key) {
|
|
@@ -1494,7 +1499,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1494
1499
|
if (hasOptionalProperty(message, 'groupStatus') && !!message.groupStatus) {
|
|
1495
1500
|
const messageType = Object.keys(m)[0];
|
|
1496
1501
|
const key = m[messageType];
|
|
1497
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1502
|
+
if (key && 'contextInfo' in key && !!key.contextInfo) {
|
|
1498
1503
|
key.contextInfo.isGroupStatus = message.groupStatus;
|
|
1499
1504
|
}
|
|
1500
1505
|
else if (key) {
|
|
@@ -1520,7 +1525,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1520
1525
|
m = { viewOnceMessage: { message: m } };
|
|
1521
1526
|
}
|
|
1522
1527
|
else if (mediaSpoiler && mediaSpoilerMode === 'native') {
|
|
1523
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1528
|
+
if (key && 'contextInfo' in key && !!key.contextInfo) {
|
|
1524
1529
|
key.contextInfo.isSpoiler = true;
|
|
1525
1530
|
}
|
|
1526
1531
|
else if (key) {
|
|
@@ -1564,7 +1569,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1564
1569
|
participant: '0@s.whatsapp.net',
|
|
1565
1570
|
remoteJid: '0@s.whatsapp.net'
|
|
1566
1571
|
};
|
|
1567
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1572
|
+
if (key && 'contextInfo' in key && !!key.contextInfo) {
|
|
1568
1573
|
key.contextInfo = { ...key.contextInfo, ...verifiedContext };
|
|
1569
1574
|
}
|
|
1570
1575
|
else if (key) {
|
|
@@ -1663,7 +1668,7 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1663
1668
|
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
1664
1669
|
delete quotedContent.contextInfo;
|
|
1665
1670
|
}
|
|
1666
|
-
const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
|
|
1671
|
+
const contextInfo = (innerMessage[key] && 'contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
|
|
1667
1672
|
contextInfo.participant = jidNormalizedUser(participant);
|
|
1668
1673
|
contextInfo.stanzaId = quoted.key.id;
|
|
1669
1674
|
contextInfo.quotedMessage = quotedMsg;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { proto } from '../../WAProto/index.js';
|
|
16
16
|
import { BOT_RENDERING_CONFIG_METADATA } from '../Defaults/index.js';
|
|
17
|
+
import { BotCapabilityType, buildBotCapabilityMetadata } from './bot-capabilities.js';
|
|
17
18
|
import { delay } from './generics.js';
|
|
18
19
|
|
|
19
20
|
// ─── Step status enum ───
|
|
@@ -88,10 +89,16 @@ export const buildCompositingPlaceholder = ({
|
|
|
88
89
|
unifiedResponse: { data: unifiedData },
|
|
89
90
|
submessages: []
|
|
90
91
|
};
|
|
92
|
+
const capabilities = [
|
|
93
|
+
BotCapabilityType.PROGRESS_INDICATOR,
|
|
94
|
+
...(steps.length ? [BotCapabilityType.AGENTIC_PLANNING] : []),
|
|
95
|
+
...(steps.some(step => step.queryPlan || step.type === 'query') ? [BotCapabilityType.QUERY_PLAN] : [])
|
|
96
|
+
];
|
|
91
97
|
|
|
92
98
|
return {
|
|
93
99
|
messageContextInfo: {
|
|
94
100
|
botMetadata: {
|
|
101
|
+
capabilityMetadata: buildBotCapabilityMetadata(capabilities),
|
|
95
102
|
pluginMetadata: {},
|
|
96
103
|
progressIndicatorMetadata,
|
|
97
104
|
botRenderingConfigMetadata: BOT_RENDERING_CONFIG_METADATA,
|
package/lib/index.d.ts
CHANGED
|
@@ -266,8 +266,14 @@ export interface WASocket {
|
|
|
266
266
|
sendBotDiagnostics(jid: string, content?: { text?: string; botBackend?: number; toolsUsed?: string[]; isThinking?: boolean; botJid?: string }, options?: Record<string, unknown>): Promise<unknown>;
|
|
267
267
|
/** Send a rich response with experimental bot command metadata. */
|
|
268
268
|
sendBotCommand(jid: string, content?: { text?: string; commandName?: string; commandDescription?: string; commandPrompt?: string; botJid?: string }, options?: Record<string, unknown>): Promise<unknown>;
|
|
269
|
+
/** Send an agentic execution plan, advertising AGENTIC_PLANNING and QUERY_PLAN. */
|
|
270
|
+
sendBotPlanning(jid: string, content?: { text?: string; steps?: Array<string | { title?: string; name?: string; body?: string }>; queryPlan?: boolean; botJid?: string }, options?: Record<string, unknown>): Promise<unknown>;
|
|
269
271
|
/** Send a rich response with experimental resolved tool-call metadata. */
|
|
270
272
|
sendBotToolResult(jid: string, content?: { text?: string; toolCallId?: string; resolutionData?: unknown; resolutionDataSerialized?: string; botJid?: string }, options?: Record<string, unknown>): Promise<unknown>;
|
|
273
|
+
/** Resolve a WhatsApp Channel invite code or invite URL to channel metadata. */
|
|
274
|
+
newsletterGetInviteInfo(inviteCodeOrUrl: string): Promise<Record<string, unknown> | null>;
|
|
275
|
+
/** React to a Channel post; pass an empty string, null, or undefined to remove the reaction. */
|
|
276
|
+
newsletterReactMessage(jid: string, serverId: string | number, reaction?: string | null): Promise<void>;
|
|
271
277
|
/** Send Markdown text containing blockquotes in a forwarded GenAI rich response. */
|
|
272
278
|
sendMarkdownQuote(jid: string, content?: { text?: string; copyText?: string; copyLabel?: string; alignment?: 'END' | 'START' | 'CENTER' }, options?: Record<string, unknown>): Promise<unknown>;
|
|
273
279
|
/** Send Markdown blockquotes followed by a GenAI COPY_TO_CLIPBOARD action. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plogme",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Production-ready Baileys fork
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Production-ready Baileys fork ⚉ with AI groups, Meta AI prompting, safe compositing fallbacks, rich responses, interactive messages, albums, newsletters, and communities — without antiban wrappers.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|