@openclaw/whatsapp 2026.6.6-beta.2 → 2026.6.8-beta.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/dist/{access-control-C53zKYSN.js → access-control-BKaMOvIk.js} +2 -2
- package/dist/api.js +6 -6
- package/dist/{auth-store-B2ZibndQ.js → auth-store-e9VzLZ-S.js} +1 -1
- package/dist/{channel-DhMmokKH.js → channel-DyUm8hqs.js} +15 -2
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-v3vXe7C0.js → channel.runtime-BXkzo0j1.js} +4 -4
- package/dist/{channel.setup-Cq3cdnzK.js → channel.setup-CpyAie9O.js} +2 -2
- package/dist/{connection-controller-TvY2F126.js → connection-controller-BWBoVQr4.js} +16 -3
- package/dist/contract-api.js +1 -1
- package/dist/{identity-xoLLdqEv.js → identity-Bupuq9vF.js} +18 -18
- package/dist/light-runtime-api.js +1 -1
- package/dist/{login-BExWg_jW.js → login-Xv3ujrl0.js} +3 -3
- package/dist/{login-qr-DiZ0U-P8.js → login-qr-CaJziL93.js} +3 -3
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-CXuZBVgk.js → monitor-Ggwn3FDi.js} +587 -237
- package/dist/runtime-api.js +5 -5
- package/dist/{send-api-CFbAgIbn.js → send-api-Cp9CUH5P.js} +1 -1
- package/dist/{session-CoxlXm2K.js → session-BCKUPRkN.js} +1 -1
- package/dist/{setup-core-D0Zm67Lv.js → setup-core-Cp0NMO89.js} +2 -2
- package/dist/{setup-finalize-nTMa6s13.js → setup-finalize-DnV-KlkQ.js} +2 -2
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-vIg4EcCu.js → setup-surface-BmPcAhIF.js} +2 -2
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
|
@@ -5,14 +5,14 @@ import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
|
5
5
|
import { n as getStatusCode, r as getRegisteredWhatsAppConnectionController, t as formatError } from "./session-errors-CbsoQqoy.js";
|
|
6
6
|
import { d as markdownToWhatsApp, f as resolveJidToE164, l as isSelfChatMode, n as normalizeE164, t as convertMarkdownTables$1, u as jidToE164 } from "./text-runtime-Dk37KYHj.js";
|
|
7
7
|
import { n as cacheInboundMessageMeta, r as lookupInboundMessageMeta, t as buildQuotedMessageOptions } from "./quoted-message-CveINB35.js";
|
|
8
|
-
import { c as logoutWeb, g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-
|
|
9
|
-
import { a as getSelfIdentity, c as resolveComparableIdentity, i as getReplyContext, n as getMentionIdentities, o as getSenderIdentity, r as getPrimaryIdentityId, s as identitiesOverlap, t as getComparableIdentityValues } from "./identity-
|
|
8
|
+
import { c as logoutWeb, g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-e9VzLZ-S.js";
|
|
9
|
+
import { a as getSelfIdentity, c as resolveComparableIdentity, i as getReplyContext, n as getMentionIdentities, o as getSenderIdentity, r as getPrimaryIdentityId, s as identitiesOverlap, t as getComparableIdentityValues } from "./identity-Bupuq9vF.js";
|
|
10
10
|
import { n as resolveWhatsAppGroupsConfigPath } from "./group-config-path-BGyzT9Lg.js";
|
|
11
|
-
import { i as resolveWhatsAppInboundPolicy, r as resolveWhatsAppCommandAuthorized, t as checkInboundAccessControl } from "./access-control-
|
|
12
|
-
import { _ as extractMediaPlaceholder, a as mayContainWhatsAppOutboundMention, b as hasInboundUserContent, c as DisconnectReason, d as normalizeMessageContent, f as resolveInboundMediaMimetype, g as extractLocationData, h as extractContextInfo, i as addWhatsAppOutboundMentionsToContent, l as downloadMediaMessage, m as extractContactContext, n as listWhatsAppSendResultMessageIds, o as resolveWhatsAppOutboundMentions, p as describeReplyContext, r as normalizeWhatsAppSendResult, s as addWhatsAppImagePreviewFields, t as createWebSendApi, u as isJidGroup, v as extractMentionedJids, y as extractText } from "./send-api-
|
|
13
|
-
import { a as resolveWhatsAppSocketTiming, r as waitForWaConnection, t as createWaSocket } from "./session-
|
|
11
|
+
import { i as resolveWhatsAppInboundPolicy, r as resolveWhatsAppCommandAuthorized, t as checkInboundAccessControl } from "./access-control-BKaMOvIk.js";
|
|
12
|
+
import { _ as extractMediaPlaceholder, a as mayContainWhatsAppOutboundMention, b as hasInboundUserContent, c as DisconnectReason, d as normalizeMessageContent, f as resolveInboundMediaMimetype, g as extractLocationData, h as extractContextInfo, i as addWhatsAppOutboundMentionsToContent, l as downloadMediaMessage, m as extractContactContext, n as listWhatsAppSendResultMessageIds, o as resolveWhatsAppOutboundMentions, p as describeReplyContext, r as normalizeWhatsAppSendResult, s as addWhatsAppImagePreviewFields, t as createWebSendApi, u as isJidGroup, v as extractMentionedJids, y as extractText } from "./send-api-Cp9CUH5P.js";
|
|
13
|
+
import { a as resolveWhatsAppSocketTiming, r as waitForWaConnection, t as createWaSocket } from "./session-BCKUPRkN.js";
|
|
14
14
|
import { t as BufferJSON } from "./session.runtime-CyooSQvj.js";
|
|
15
|
-
import { c as computeBackoff, d as resolveReconnectPolicy, f as sleepWithAbort, l as newConnectionId, n as WHATSAPP_WATCHDOG_TIMEOUT_ERROR, r as WhatsAppConnectionController, s as DEFAULT_RECONNECT_POLICY, u as resolveHeartbeatSeconds } from "./connection-controller-
|
|
15
|
+
import { c as computeBackoff, d as resolveReconnectPolicy, f as sleepWithAbort, l as newConnectionId, n as WHATSAPP_WATCHDOG_TIMEOUT_ERROR, r as WhatsAppConnectionController, s as DEFAULT_RECONNECT_POLICY, u as resolveHeartbeatSeconds } from "./connection-controller-BWBoVQr4.js";
|
|
16
16
|
import { resolveAccountEntry } from "openclaw/plugin-sdk/account-core";
|
|
17
17
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
18
|
import { createChannelMessageReplyPipeline, createDurableInboundReceiveJournalFromQueue, createMessageReceiptFromOutboundResults, deliverInboundReplyWithMessageSendContext, resolveChannelMessageSourceReplyDeliveryMode } from "openclaw/plugin-sdk/channel-outbound";
|
|
@@ -47,11 +47,281 @@ import { getRuntimeConfig as getRuntimeConfig$1, getRuntimeConfigSourceSnapshot
|
|
|
47
47
|
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
48
48
|
import { buildMentionRegexes, implicitMentionKindWhen, normalizeMentionText, resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-mention-gating";
|
|
49
49
|
import { createConnectedChannelStatusPatch, createTransportActivityStatusPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
50
|
+
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
50
51
|
import { resolveAgentIdentity, resolveIdentityNamePrefix as resolveIdentityNamePrefix$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
51
52
|
import { normalizeGroupActivation, parseActivationCommand } from "openclaw/plugin-sdk/group-activation";
|
|
52
53
|
import { createInternalHookEvent, deriveInboundMessageHookContext, fireAndForgetBoundedHook, toInternalMessageReceivedContext, toPluginMessageContext, toPluginMessageReceivedEvent, triggerInternalHook } from "openclaw/plugin-sdk/hook-runtime";
|
|
53
54
|
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
|
54
55
|
import { resolveBatchedReplyThreadingPolicy } from "openclaw/plugin-sdk/reply-reference";
|
|
56
|
+
//#region extensions/whatsapp/src/inbound/message-aliases.ts
|
|
57
|
+
function normalizeQuoteSender(sender) {
|
|
58
|
+
if (!sender?.displayName && !sender?.jid && !sender?.e164) return;
|
|
59
|
+
return sender;
|
|
60
|
+
}
|
|
61
|
+
function buildQuoteFromFlatAliases(msg) {
|
|
62
|
+
if (msg.replyTo) return {
|
|
63
|
+
context: msg.replyTo,
|
|
64
|
+
id: msg.replyTo.id,
|
|
65
|
+
body: msg.replyTo.body,
|
|
66
|
+
sender: normalizeQuoteSender({
|
|
67
|
+
displayName: msg.replyTo.sender?.label ?? msg.replyToSender,
|
|
68
|
+
jid: msg.replyTo.sender?.jid ?? msg.replyToSenderJid,
|
|
69
|
+
e164: msg.replyTo.sender?.e164 ?? msg.replyToSenderE164
|
|
70
|
+
})
|
|
71
|
+
};
|
|
72
|
+
if (!msg.replyToId && !msg.replyToBody && !msg.replyToSender && !msg.replyToSenderJid && !msg.replyToSenderE164) return;
|
|
73
|
+
return {
|
|
74
|
+
id: msg.replyToId,
|
|
75
|
+
body: msg.replyToBody,
|
|
76
|
+
sender: normalizeQuoteSender({
|
|
77
|
+
displayName: msg.replyToSender,
|
|
78
|
+
jid: msg.replyToSenderJid,
|
|
79
|
+
e164: msg.replyToSenderE164
|
|
80
|
+
})
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function buildGroupFromFlatAliases(msg) {
|
|
84
|
+
const mentionJids = msg.mentions ?? msg.mentionedJids;
|
|
85
|
+
if (!msg.groupSubject && !msg.groupParticipants?.length && !mentionJids?.length) return;
|
|
86
|
+
return {
|
|
87
|
+
subject: msg.groupSubject,
|
|
88
|
+
participants: msg.groupParticipants,
|
|
89
|
+
mentions: mentionJids?.length ? { jids: mentionJids } : void 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function ensureQuote(msg) {
|
|
93
|
+
return msg.quote ??= {};
|
|
94
|
+
}
|
|
95
|
+
function ensureQuoteSender(msg) {
|
|
96
|
+
const quote = ensureQuote(msg);
|
|
97
|
+
return quote.sender ??= {};
|
|
98
|
+
}
|
|
99
|
+
function ensureGroup(msg) {
|
|
100
|
+
return msg.group ??= {};
|
|
101
|
+
}
|
|
102
|
+
function ensureGroupMentions(msg) {
|
|
103
|
+
const group = ensureGroup(msg);
|
|
104
|
+
return group.mentions ??= {};
|
|
105
|
+
}
|
|
106
|
+
function ensureMedia(msg) {
|
|
107
|
+
return msg.payload.media ??= {};
|
|
108
|
+
}
|
|
109
|
+
function setMediaField(msg, key, value) {
|
|
110
|
+
if (value === void 0 && !msg.payload.media) return;
|
|
111
|
+
ensureMedia(msg)[key] = value;
|
|
112
|
+
}
|
|
113
|
+
function defineDeprecatedAliasAccessors(msg, descriptors) {
|
|
114
|
+
Object.defineProperties(msg, Object.fromEntries(Object.entries(descriptors).map(([key, descriptor]) => [key, {
|
|
115
|
+
configurable: true,
|
|
116
|
+
enumerable: true,
|
|
117
|
+
get: descriptor.get,
|
|
118
|
+
set: descriptor.set
|
|
119
|
+
}])));
|
|
120
|
+
return msg;
|
|
121
|
+
}
|
|
122
|
+
function withDeprecatedWebInboundMessageFlatAliases(msg) {
|
|
123
|
+
return defineDeprecatedAliasAccessors(msg, {
|
|
124
|
+
id: {
|
|
125
|
+
get: () => msg.event.id,
|
|
126
|
+
set: (value) => msg.event.id = value
|
|
127
|
+
},
|
|
128
|
+
to: {
|
|
129
|
+
get: () => msg.platform.recipientJid,
|
|
130
|
+
set: (value) => msg.platform.recipientJid = value
|
|
131
|
+
},
|
|
132
|
+
body: {
|
|
133
|
+
get: () => msg.payload.body,
|
|
134
|
+
set: (value) => msg.payload.body = value
|
|
135
|
+
},
|
|
136
|
+
pushName: {
|
|
137
|
+
get: () => msg.platform.pushName,
|
|
138
|
+
set: (value) => msg.platform.pushName = value
|
|
139
|
+
},
|
|
140
|
+
timestamp: {
|
|
141
|
+
get: () => msg.event.timestamp,
|
|
142
|
+
set: (value) => msg.event.timestamp = value
|
|
143
|
+
},
|
|
144
|
+
chatId: {
|
|
145
|
+
get: () => msg.platform.chatJid,
|
|
146
|
+
set: (value) => msg.platform.chatJid = value
|
|
147
|
+
},
|
|
148
|
+
sender: {
|
|
149
|
+
get: () => msg.platform.sender,
|
|
150
|
+
set: (value) => msg.platform.sender = value
|
|
151
|
+
},
|
|
152
|
+
senderJid: {
|
|
153
|
+
get: () => msg.platform.senderJid,
|
|
154
|
+
set: (value) => msg.platform.senderJid = value
|
|
155
|
+
},
|
|
156
|
+
senderE164: {
|
|
157
|
+
get: () => msg.platform.senderE164,
|
|
158
|
+
set: (value) => msg.platform.senderE164 = value
|
|
159
|
+
},
|
|
160
|
+
senderName: {
|
|
161
|
+
get: () => msg.platform.senderName,
|
|
162
|
+
set: (value) => msg.platform.senderName = value
|
|
163
|
+
},
|
|
164
|
+
replyTo: {
|
|
165
|
+
get: () => msg.quote?.context,
|
|
166
|
+
set: (value) => ensureQuote(msg).context = value
|
|
167
|
+
},
|
|
168
|
+
replyToId: {
|
|
169
|
+
get: () => msg.quote?.id ?? msg.quote?.context?.id,
|
|
170
|
+
set: (value) => ensureQuote(msg).id = value
|
|
171
|
+
},
|
|
172
|
+
replyToBody: {
|
|
173
|
+
get: () => msg.quote?.body ?? msg.quote?.context?.body,
|
|
174
|
+
set: (value) => ensureQuote(msg).body = value
|
|
175
|
+
},
|
|
176
|
+
replyToSender: {
|
|
177
|
+
get: () => msg.quote?.context?.sender?.label ?? msg.quote?.sender?.displayName,
|
|
178
|
+
set: (value) => {
|
|
179
|
+
const sender = ensureQuoteSender(msg);
|
|
180
|
+
sender.displayName = value;
|
|
181
|
+
if (msg.quote?.context?.sender) msg.quote.context.sender.label = value;
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
replyToSenderJid: {
|
|
185
|
+
get: () => msg.quote?.context?.sender?.jid ?? msg.quote?.sender?.jid,
|
|
186
|
+
set: (value) => {
|
|
187
|
+
const jid = value;
|
|
188
|
+
ensureQuoteSender(msg).jid = jid;
|
|
189
|
+
if (msg.quote?.context?.sender) msg.quote.context.sender.jid = jid;
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
replyToSenderE164: {
|
|
193
|
+
get: () => msg.quote?.context?.sender?.e164 ?? msg.quote?.sender?.e164,
|
|
194
|
+
set: (value) => {
|
|
195
|
+
const e164 = value;
|
|
196
|
+
ensureQuoteSender(msg).e164 = e164;
|
|
197
|
+
if (msg.quote?.context?.sender) msg.quote.context.sender.e164 = e164;
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
groupSubject: {
|
|
201
|
+
get: () => msg.group?.subject,
|
|
202
|
+
set: (value) => ensureGroup(msg).subject = value
|
|
203
|
+
},
|
|
204
|
+
groupParticipants: {
|
|
205
|
+
get: () => msg.group?.participants,
|
|
206
|
+
set: (value) => ensureGroup(msg).participants = value
|
|
207
|
+
},
|
|
208
|
+
mentions: {
|
|
209
|
+
get: () => msg.group?.mentions?.jids,
|
|
210
|
+
set: (value) => ensureGroupMentions(msg).jids = value
|
|
211
|
+
},
|
|
212
|
+
mentionedJids: {
|
|
213
|
+
get: () => msg.group?.mentions?.jids,
|
|
214
|
+
set: (value) => ensureGroupMentions(msg).jids = value
|
|
215
|
+
},
|
|
216
|
+
self: {
|
|
217
|
+
get: () => msg.platform.self,
|
|
218
|
+
set: (value) => msg.platform.self = value
|
|
219
|
+
},
|
|
220
|
+
selfJid: {
|
|
221
|
+
get: () => msg.platform.selfJid,
|
|
222
|
+
set: (value) => msg.platform.selfJid = value
|
|
223
|
+
},
|
|
224
|
+
selfLid: {
|
|
225
|
+
get: () => msg.platform.selfLid,
|
|
226
|
+
set: (value) => msg.platform.selfLid = value
|
|
227
|
+
},
|
|
228
|
+
selfE164: {
|
|
229
|
+
get: () => msg.platform.selfE164,
|
|
230
|
+
set: (value) => msg.platform.selfE164 = value
|
|
231
|
+
},
|
|
232
|
+
fromMe: {
|
|
233
|
+
get: () => msg.platform.fromMe,
|
|
234
|
+
set: (value) => msg.platform.fromMe = value
|
|
235
|
+
},
|
|
236
|
+
location: {
|
|
237
|
+
get: () => msg.payload.location,
|
|
238
|
+
set: (value) => msg.payload.location = value
|
|
239
|
+
},
|
|
240
|
+
sendComposing: {
|
|
241
|
+
get: () => msg.platform.sendComposing,
|
|
242
|
+
set: (value) => msg.platform.sendComposing = value
|
|
243
|
+
},
|
|
244
|
+
reply: {
|
|
245
|
+
get: () => msg.platform.reply,
|
|
246
|
+
set: (value) => msg.platform.reply = value
|
|
247
|
+
},
|
|
248
|
+
sendMedia: {
|
|
249
|
+
get: () => msg.platform.sendMedia,
|
|
250
|
+
set: (value) => msg.platform.sendMedia = value
|
|
251
|
+
},
|
|
252
|
+
mediaPath: {
|
|
253
|
+
get: () => msg.payload.media?.path,
|
|
254
|
+
set: (value) => setMediaField(msg, "path", value)
|
|
255
|
+
},
|
|
256
|
+
mediaType: {
|
|
257
|
+
get: () => msg.payload.media?.type,
|
|
258
|
+
set: (value) => setMediaField(msg, "type", value)
|
|
259
|
+
},
|
|
260
|
+
mediaFileName: {
|
|
261
|
+
get: () => msg.payload.media?.fileName,
|
|
262
|
+
set: (value) => setMediaField(msg, "fileName", value)
|
|
263
|
+
},
|
|
264
|
+
mediaUrl: {
|
|
265
|
+
get: () => msg.payload.media?.url,
|
|
266
|
+
set: (value) => setMediaField(msg, "url", value)
|
|
267
|
+
},
|
|
268
|
+
untrustedStructuredContext: {
|
|
269
|
+
get: () => msg.payload.untrustedStructuredContext,
|
|
270
|
+
set: (value) => msg.payload.untrustedStructuredContext = value
|
|
271
|
+
},
|
|
272
|
+
isBatched: {
|
|
273
|
+
get: () => msg.event.isBatched,
|
|
274
|
+
set: (value) => msg.event.isBatched = value
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function normalizeLegacyFlatWebInboundMessage(msg) {
|
|
279
|
+
const media = msg.mediaPath || msg.mediaType || msg.mediaFileName || msg.mediaUrl ? {
|
|
280
|
+
path: msg.mediaPath,
|
|
281
|
+
type: msg.mediaType,
|
|
282
|
+
fileName: msg.mediaFileName,
|
|
283
|
+
url: msg.mediaUrl
|
|
284
|
+
} : void 0;
|
|
285
|
+
return withDeprecatedWebInboundMessageFlatAliases({
|
|
286
|
+
...msg,
|
|
287
|
+
event: {
|
|
288
|
+
id: msg.id,
|
|
289
|
+
timestamp: msg.timestamp,
|
|
290
|
+
isBatched: msg.isBatched
|
|
291
|
+
},
|
|
292
|
+
payload: {
|
|
293
|
+
body: msg.body,
|
|
294
|
+
media,
|
|
295
|
+
location: msg.location,
|
|
296
|
+
untrustedStructuredContext: msg.untrustedStructuredContext
|
|
297
|
+
},
|
|
298
|
+
platform: {
|
|
299
|
+
chatJid: msg.chatId,
|
|
300
|
+
recipientJid: msg.to,
|
|
301
|
+
sender: msg.sender,
|
|
302
|
+
senderJid: msg.senderJid,
|
|
303
|
+
senderE164: msg.senderE164,
|
|
304
|
+
senderName: msg.senderName,
|
|
305
|
+
pushName: msg.pushName,
|
|
306
|
+
self: msg.self,
|
|
307
|
+
selfJid: msg.selfJid,
|
|
308
|
+
selfLid: msg.selfLid,
|
|
309
|
+
selfE164: msg.selfE164,
|
|
310
|
+
fromMe: msg.fromMe,
|
|
311
|
+
sendComposing: msg.sendComposing,
|
|
312
|
+
reply: msg.reply,
|
|
313
|
+
sendMedia: msg.sendMedia
|
|
314
|
+
},
|
|
315
|
+
quote: buildQuoteFromFlatAliases(msg),
|
|
316
|
+
group: buildGroupFromFlatAliases(msg)
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
function normalizeWebInboundMessage(msg) {
|
|
320
|
+
if (msg.event && msg.payload && msg.platform) return withDeprecatedWebInboundMessageFlatAliases(msg);
|
|
321
|
+
if (msg.event || msg.payload || msg.platform || msg.quote || msg.group) throw new Error("WhatsApp inbound messages must be either legacy flat or canonical nested; partial nested contexts are not supported.");
|
|
322
|
+
return normalizeLegacyFlatWebInboundMessage(msg);
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
55
325
|
//#region extensions/whatsapp/src/inbound/dedupe.ts
|
|
56
326
|
const RECENT_WEB_MESSAGE_TTL_MS = 20 * 6e4;
|
|
57
327
|
const RECENT_WEB_MESSAGE_MAX = 5e3;
|
|
@@ -353,15 +623,15 @@ async function attachWebInboxToSocket(options) {
|
|
|
353
623
|
const pendingDebounceKeys = /* @__PURE__ */ new Set();
|
|
354
624
|
const activeInboundFlushes = /* @__PURE__ */ new Set();
|
|
355
625
|
const buildInboundDebounceKey = (msg) => {
|
|
356
|
-
const sender = msg.sender;
|
|
357
|
-
const senderKey = msg.chatType === "group" ? getPrimaryIdentityId(sender ?? null) ?? msg.senderJid ?? msg.senderE164 ?? msg.senderName ?? msg.from : msg.from;
|
|
626
|
+
const sender = msg.platform.sender;
|
|
627
|
+
const senderKey = msg.chatType === "group" ? getPrimaryIdentityId(sender ?? null) ?? msg.platform.senderJid ?? msg.platform.senderE164 ?? msg.platform.senderName ?? msg.from : msg.from;
|
|
358
628
|
if (!senderKey) return null;
|
|
359
|
-
const conversationKey = msg.chatType === "group" ? msg.
|
|
629
|
+
const conversationKey = msg.chatType === "group" ? msg.platform.chatJid : msg.from;
|
|
360
630
|
return `${msg.accountId}:${conversationKey}:${senderKey}`;
|
|
361
631
|
};
|
|
362
632
|
const shouldDebounceInboundMessage = (msg) => options.shouldDebounce?.(msg) ?? true;
|
|
363
633
|
const orderDebouncedInboundEntries = (entries) => entries.toSorted((a, b) => {
|
|
364
|
-
const timestampDiff = (a.timestamp ?? 0) - (b.timestamp ?? 0);
|
|
634
|
+
const timestampDiff = (a.event.timestamp ?? 0) - (b.event.timestamp ?? 0);
|
|
365
635
|
if (timestampDiff !== 0) return timestampDiff;
|
|
366
636
|
return (a.receiveOrder ?? 0) - (b.receiveOrder ?? 0);
|
|
367
637
|
});
|
|
@@ -398,15 +668,28 @@ async function attachWebInboxToSocket(options) {
|
|
|
398
668
|
return;
|
|
399
669
|
}
|
|
400
670
|
const mentioned = /* @__PURE__ */ new Set();
|
|
401
|
-
for (const entry of orderedEntries) for (const jid of entry.mentions ??
|
|
402
|
-
const combinedBody = orderedEntries.map((entry) => entry.body).filter(Boolean).join("\n");
|
|
403
|
-
const
|
|
671
|
+
for (const entry of orderedEntries) for (const jid of entry.group?.mentions?.jids ?? []) mentioned.add(jid);
|
|
672
|
+
const combinedBody = orderedEntries.map((entry) => entry.payload.body).filter(Boolean).join("\n");
|
|
673
|
+
const combinedMentions = mentioned.size > 0 ? {
|
|
674
|
+
...last.group?.mentions,
|
|
675
|
+
jids: Array.from(mentioned)
|
|
676
|
+
} : last.group?.mentions;
|
|
677
|
+
const combinedGroup = last.group || combinedMentions ? {
|
|
678
|
+
...last.group,
|
|
679
|
+
mentions: combinedMentions
|
|
680
|
+
} : void 0;
|
|
681
|
+
const combinedMessage = withDeprecatedWebInboundMessageFlatAliases({
|
|
404
682
|
...last,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
683
|
+
payload: {
|
|
684
|
+
...last.payload,
|
|
685
|
+
body: combinedBody
|
|
686
|
+
},
|
|
687
|
+
group: combinedGroup,
|
|
688
|
+
event: {
|
|
689
|
+
...last.event,
|
|
690
|
+
isBatched: true
|
|
691
|
+
}
|
|
692
|
+
});
|
|
410
693
|
await options.onMessage(combinedMessage);
|
|
411
694
|
await finalizeInboundDelivery(orderedEntries);
|
|
412
695
|
} catch (error) {
|
|
@@ -781,69 +1064,85 @@ async function attachWebInboxToSocket(options) {
|
|
|
781
1064
|
mediaFileName: enriched.mediaFileName,
|
|
782
1065
|
timestamp
|
|
783
1066
|
}, "inbound message");
|
|
784
|
-
const
|
|
785
|
-
|
|
1067
|
+
const media = enriched.mediaPath || enriched.mediaType || enriched.mediaFileName ? {
|
|
1068
|
+
path: enriched.mediaPath,
|
|
1069
|
+
type: enriched.mediaType,
|
|
1070
|
+
fileName: enriched.mediaFileName
|
|
1071
|
+
} : void 0;
|
|
1072
|
+
const groupMentions = mentionedJids ? { jids: mentionedJids } : void 0;
|
|
1073
|
+
const group = inbound.group && (inbound.groupSubject || inbound.groupParticipants?.length || groupMentions) ? {
|
|
1074
|
+
subject: inbound.groupSubject,
|
|
1075
|
+
participants: inbound.groupParticipants,
|
|
1076
|
+
mentions: groupMentions
|
|
1077
|
+
} : void 0;
|
|
1078
|
+
const inboundMessage = withDeprecatedWebInboundMessageFlatAliases({
|
|
1079
|
+
event: {
|
|
1080
|
+
id: inbound.id,
|
|
1081
|
+
timestamp
|
|
1082
|
+
},
|
|
1083
|
+
payload: {
|
|
1084
|
+
body: enriched.body,
|
|
1085
|
+
location: enriched.location ?? void 0,
|
|
1086
|
+
untrustedStructuredContext: enriched.contactContext ? [{
|
|
1087
|
+
label: "WhatsApp contact",
|
|
1088
|
+
source: "whatsapp",
|
|
1089
|
+
type: enriched.contactContext.kind,
|
|
1090
|
+
payload: enriched.contactContext
|
|
1091
|
+
}] : void 0,
|
|
1092
|
+
media
|
|
1093
|
+
},
|
|
1094
|
+
platform: {
|
|
1095
|
+
chatJid: inbound.remoteJid,
|
|
1096
|
+
recipientJid: self.e164 ?? "me",
|
|
1097
|
+
pushName: senderName,
|
|
1098
|
+
sender: resolveComparableIdentity({
|
|
1099
|
+
jid: inbound.participantJid,
|
|
1100
|
+
e164: inbound.senderE164 ?? void 0,
|
|
1101
|
+
name: senderName
|
|
1102
|
+
}),
|
|
1103
|
+
senderJid: inbound.participantJid,
|
|
1104
|
+
senderE164: inbound.senderE164 ?? void 0,
|
|
1105
|
+
senderName,
|
|
1106
|
+
self,
|
|
1107
|
+
selfJid: self.jid ?? void 0,
|
|
1108
|
+
selfLid: self.lid ?? void 0,
|
|
1109
|
+
selfE164: self.e164 ?? void 0,
|
|
1110
|
+
fromMe: Boolean(msg.key?.fromMe),
|
|
1111
|
+
sendComposing,
|
|
1112
|
+
reply,
|
|
1113
|
+
sendMedia
|
|
1114
|
+
},
|
|
786
1115
|
from: inbound.from,
|
|
787
1116
|
conversationId: inbound.from,
|
|
788
|
-
to: self.e164 ?? "me",
|
|
789
1117
|
accountId: inbound.access.resolvedAccountId,
|
|
790
1118
|
accessControlPassed: true,
|
|
791
|
-
body: enriched.body,
|
|
792
|
-
pushName: senderName,
|
|
793
|
-
timestamp,
|
|
794
1119
|
chatType: inbound.group ? "group" : "direct",
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
replyToBody: enriched.replyContext?.body,
|
|
807
|
-
replyToSender: enriched.replyContext?.sender?.label ?? void 0,
|
|
808
|
-
replyToSenderJid: enriched.replyContext?.sender?.jid ?? void 0,
|
|
809
|
-
replyToSenderE164: enriched.replyContext?.sender?.e164 ?? void 0,
|
|
810
|
-
groupSubject: inbound.groupSubject,
|
|
811
|
-
groupParticipants: inbound.groupParticipants,
|
|
812
|
-
mentions: mentionedJids ?? void 0,
|
|
813
|
-
mentionedJids: mentionedJids ?? void 0,
|
|
814
|
-
self,
|
|
815
|
-
selfJid: self.jid ?? void 0,
|
|
816
|
-
selfLid: self.lid ?? void 0,
|
|
817
|
-
selfE164: self.e164 ?? void 0,
|
|
818
|
-
fromMe: Boolean(msg.key?.fromMe),
|
|
819
|
-
location: enriched.location ?? void 0,
|
|
820
|
-
untrustedStructuredContext: enriched.contactContext ? [{
|
|
821
|
-
label: "WhatsApp contact",
|
|
822
|
-
source: "whatsapp",
|
|
823
|
-
type: enriched.contactContext.kind,
|
|
824
|
-
payload: enriched.contactContext
|
|
825
|
-
}] : void 0,
|
|
826
|
-
sendComposing,
|
|
827
|
-
reply,
|
|
828
|
-
sendMedia,
|
|
829
|
-
mediaPath: enriched.mediaPath,
|
|
830
|
-
mediaType: enriched.mediaType,
|
|
831
|
-
mediaFileName: enriched.mediaFileName,
|
|
1120
|
+
quote: enriched.replyContext ? {
|
|
1121
|
+
context: enriched.replyContext,
|
|
1122
|
+
id: enriched.replyContext.id,
|
|
1123
|
+
body: enriched.replyContext.body,
|
|
1124
|
+
sender: {
|
|
1125
|
+
displayName: enriched.replyContext.sender?.label ?? void 0,
|
|
1126
|
+
jid: enriched.replyContext.sender?.jid ?? void 0,
|
|
1127
|
+
e164: enriched.replyContext.sender?.e164 ?? void 0
|
|
1128
|
+
}
|
|
1129
|
+
} : void 0,
|
|
1130
|
+
group,
|
|
832
1131
|
dedupeKey: inbound.id ? `${options.accountId}:${inbound.remoteJid}:${inbound.id}` : void 0,
|
|
833
1132
|
durableId: durable.durableId,
|
|
834
1133
|
readReceipt: durable.readReceipt,
|
|
835
1134
|
receiveOrder: durable.receiveOrder
|
|
836
|
-
};
|
|
1135
|
+
});
|
|
837
1136
|
const debounceKey = buildInboundDebounceKey(inboundMessage);
|
|
838
1137
|
if (debounceKey) {
|
|
839
1138
|
inboundMessage.debounceKey = debounceKey;
|
|
840
1139
|
if (inboundDebounceMs > 0 && shouldDebounceInboundMessage(inboundMessage)) pendingDebounceKeys.add(debounceKey);
|
|
841
1140
|
}
|
|
842
|
-
if (inboundMessage.id) cacheInboundMessageMeta(inboundMessage.accountId, inboundMessage.
|
|
843
|
-
participant: inboundMessage.senderJid,
|
|
844
|
-
participantE164: inboundMessage.chatType === "direct" ? inboundMessage.senderE164 : void 0,
|
|
845
|
-
body: inboundMessage.body,
|
|
846
|
-
fromMe: inboundMessage.fromMe
|
|
1141
|
+
if (inboundMessage.event.id) cacheInboundMessageMeta(inboundMessage.accountId, inboundMessage.platform.chatJid, inboundMessage.event.id, {
|
|
1142
|
+
participant: inboundMessage.platform.senderJid,
|
|
1143
|
+
participantE164: inboundMessage.chatType === "direct" ? inboundMessage.platform.senderE164 : void 0,
|
|
1144
|
+
body: inboundMessage.payload.body,
|
|
1145
|
+
fromMe: inboundMessage.platform.fromMe
|
|
847
1146
|
});
|
|
848
1147
|
try {
|
|
849
1148
|
Promise.resolve(debouncer.enqueue(inboundMessage)).catch((err) => {
|
|
@@ -1008,8 +1307,13 @@ async function monitorWebInbox(options) {
|
|
|
1008
1307
|
closeInboundMonitorSocket(sock);
|
|
1009
1308
|
throw err;
|
|
1010
1309
|
}
|
|
1310
|
+
const shouldDebounce = options.shouldDebounce;
|
|
1011
1311
|
return attachWebInboxToSocket({
|
|
1012
1312
|
...options,
|
|
1313
|
+
onMessage: async (msg) => {
|
|
1314
|
+
await options.onMessage(normalizeWebInboundMessage(msg));
|
|
1315
|
+
},
|
|
1316
|
+
shouldDebounce: shouldDebounce ? (msg) => shouldDebounce(normalizeWebInboundMessage(msg)) : void 0,
|
|
1013
1317
|
sock
|
|
1014
1318
|
});
|
|
1015
1319
|
}
|
|
@@ -1043,13 +1347,13 @@ function isBotMentionedFromTargets(msg, mentionCfg, targets) {
|
|
|
1043
1347
|
for (const mention of targets.normalizedMentions) if (identitiesOverlap(targets.self, mention)) return true;
|
|
1044
1348
|
return false;
|
|
1045
1349
|
} else if (hasMentions && isSelfChat) {}
|
|
1046
|
-
const bodyClean = clean(msg.body);
|
|
1350
|
+
const bodyClean = clean(msg.payload.body);
|
|
1047
1351
|
if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean))) return true;
|
|
1048
1352
|
if (targets.self.e164) {
|
|
1049
1353
|
const selfDigits = targets.self.e164.replace(/\D/g, "");
|
|
1050
1354
|
if (selfDigits) {
|
|
1051
1355
|
if (bodyClean.replace(/[^\d]/g, "").includes(selfDigits)) return true;
|
|
1052
|
-
const bodyNoSpace = msg.body.replace(/[\s-]/g, "");
|
|
1356
|
+
const bodyNoSpace = msg.payload.body.replace(/[\s-]/g, "");
|
|
1053
1357
|
if (new RegExp(`\\+?${selfDigits}`, "i").test(bodyNoSpace)) return true;
|
|
1054
1358
|
}
|
|
1055
1359
|
}
|
|
@@ -1061,13 +1365,13 @@ function debugMention(msg, mentionCfg, authDir) {
|
|
|
1061
1365
|
wasMentioned: isBotMentionedFromTargets(msg, mentionCfg, mentionTargets),
|
|
1062
1366
|
details: {
|
|
1063
1367
|
from: msg.from,
|
|
1064
|
-
body: msg.body,
|
|
1065
|
-
bodyClean: normalizeMentionText(msg.body),
|
|
1066
|
-
mentionedJids: msg.mentions ??
|
|
1368
|
+
body: msg.payload.body,
|
|
1369
|
+
bodyClean: normalizeMentionText(msg.payload.body),
|
|
1370
|
+
mentionedJids: msg.group?.mentions?.jids ?? null,
|
|
1067
1371
|
normalizedMentionedJids: mentionTargets.normalizedMentions.length ? mentionTargets.normalizedMentions.map((identity) => getComparableIdentityValues(identity)) : null,
|
|
1068
|
-
selfJid: msg.self?.jid ?? msg.selfJid ?? null,
|
|
1069
|
-
selfLid: msg.self?.lid ?? msg.selfLid ?? null,
|
|
1070
|
-
selfE164: msg.self?.e164 ?? msg.selfE164 ?? null,
|
|
1372
|
+
selfJid: msg.platform.self?.jid ?? msg.platform.selfJid ?? null,
|
|
1373
|
+
selfLid: msg.platform.self?.lid ?? msg.platform.selfLid ?? null,
|
|
1374
|
+
selfE164: msg.platform.self?.e164 ?? msg.platform.selfE164 ?? null,
|
|
1071
1375
|
resolvedSelf: mentionTargets.self
|
|
1072
1376
|
}
|
|
1073
1377
|
};
|
|
@@ -1277,7 +1581,7 @@ async function resolveGroupActivationFor(params) {
|
|
|
1277
1581
|
//#endregion
|
|
1278
1582
|
//#region extensions/whatsapp/src/auto-reply/monitor/ack-reaction.ts
|
|
1279
1583
|
async function maybeSendAckReaction(params) {
|
|
1280
|
-
if (!params.msg.id) return null;
|
|
1584
|
+
if (!params.msg.event.id) return null;
|
|
1281
1585
|
if (resolveWhatsAppReactionLevel({
|
|
1282
1586
|
cfg: params.cfg,
|
|
1283
1587
|
accountId: params.accountId
|
|
@@ -1309,8 +1613,8 @@ async function maybeSendAckReaction(params) {
|
|
|
1309
1613
|
});
|
|
1310
1614
|
if (!shouldSendReaction()) return null;
|
|
1311
1615
|
params.info({
|
|
1312
|
-
chatId: params.msg.
|
|
1313
|
-
messageId: params.msg.id,
|
|
1616
|
+
chatId: params.msg.platform.chatJid,
|
|
1617
|
+
messageId: params.msg.event.id,
|
|
1314
1618
|
emoji
|
|
1315
1619
|
}, "sending ack reaction");
|
|
1316
1620
|
const sender = getSenderIdentity(params.msg);
|
|
@@ -1323,15 +1627,15 @@ async function maybeSendAckReaction(params) {
|
|
|
1323
1627
|
};
|
|
1324
1628
|
return createAckReactionHandle({
|
|
1325
1629
|
ackReactionValue: emoji,
|
|
1326
|
-
send: () => sendReactionWhatsApp(params.msg.
|
|
1327
|
-
remove: () => sendReactionWhatsApp(params.msg.
|
|
1630
|
+
send: () => sendReactionWhatsApp(params.msg.platform.chatJid, params.msg.event.id, emoji, reactionOptions),
|
|
1631
|
+
remove: () => sendReactionWhatsApp(params.msg.platform.chatJid, params.msg.event.id, "", reactionOptions),
|
|
1328
1632
|
onSendError: (err) => {
|
|
1329
1633
|
params.warn({
|
|
1330
1634
|
error: formatError(err),
|
|
1331
|
-
chatId: params.msg.
|
|
1332
|
-
messageId: params.msg.id
|
|
1635
|
+
chatId: params.msg.platform.chatJid,
|
|
1636
|
+
messageId: params.msg.event.id
|
|
1333
1637
|
}, "failed to send ack reaction");
|
|
1334
|
-
logVerbose(`WhatsApp ack reaction failed for chat ${params.msg.
|
|
1638
|
+
logVerbose(`WhatsApp ack reaction failed for chat ${params.msg.platform.chatJid}: ${formatError(err)}`);
|
|
1335
1639
|
}
|
|
1336
1640
|
});
|
|
1337
1641
|
}
|
|
@@ -1487,10 +1791,10 @@ function recordPendingGroupHistoryEntry(params) {
|
|
|
1487
1791
|
limit: params.groupHistoryLimit,
|
|
1488
1792
|
entry: {
|
|
1489
1793
|
sender,
|
|
1490
|
-
body: params.body ?? params.msg.body,
|
|
1491
|
-
timestamp: params.msg.timestamp,
|
|
1492
|
-
id: params.msg.id,
|
|
1493
|
-
senderJid: senderIdentity.jid ?? params.msg.senderJid
|
|
1794
|
+
body: params.body ?? params.msg.payload.body,
|
|
1795
|
+
timestamp: params.msg.event.timestamp,
|
|
1796
|
+
id: params.msg.event.id,
|
|
1797
|
+
senderJid: senderIdentity.jid ?? params.msg.platform.senderJid
|
|
1494
1798
|
}
|
|
1495
1799
|
});
|
|
1496
1800
|
}
|
|
@@ -1545,9 +1849,12 @@ async function applyGroupGating(params) {
|
|
|
1545
1849
|
};
|
|
1546
1850
|
const mentionMsg = params.mentionText !== void 0 ? {
|
|
1547
1851
|
...params.msg,
|
|
1548
|
-
|
|
1852
|
+
payload: {
|
|
1853
|
+
...params.msg.payload,
|
|
1854
|
+
body: params.mentionText
|
|
1855
|
+
}
|
|
1549
1856
|
} : params.msg;
|
|
1550
|
-
const commandBody = stripMentionsForCommand(mentionMsg.body, mentionConfig.mentionRegexes, self.e164);
|
|
1857
|
+
const commandBody = stripMentionsForCommand(mentionMsg.payload.body, mentionConfig.mentionRegexes, self.e164);
|
|
1551
1858
|
const activationCommand = parseActivationCommand(commandBody);
|
|
1552
1859
|
const owner = isOwnerSender(baseMentionConfig, params.msg);
|
|
1553
1860
|
const shouldBypassMention = owner && hasControlCommand(commandBody, params.cfg);
|
|
@@ -1591,7 +1898,7 @@ async function applyGroupGating(params) {
|
|
|
1591
1898
|
needsMentionText: true
|
|
1592
1899
|
};
|
|
1593
1900
|
}
|
|
1594
|
-
return skipGroupMessageAndStoreHistory(params, `Group message stored for context (no mention detected) in ${params.conversationId}: ${mentionMsg.body}`, params.mentionText);
|
|
1901
|
+
return skipGroupMessageAndStoreHistory(params, `Group message stored for context (no mention detected) in ${params.conversationId}: ${mentionMsg.payload.body}`, params.mentionText);
|
|
1595
1902
|
}
|
|
1596
1903
|
return { shouldProcess: true };
|
|
1597
1904
|
}
|
|
@@ -1659,6 +1966,21 @@ function elide(text, limit = 400) {
|
|
|
1659
1966
|
if (text.length <= limit) return text;
|
|
1660
1967
|
return `${text.slice(0, limit)}… (truncated ${text.length - limit} chars)`;
|
|
1661
1968
|
}
|
|
1969
|
+
function markWhatsAppVisibleDeliveryError(error) {
|
|
1970
|
+
if (typeof error === "object" && error !== null && !Array.isArray(error)) try {
|
|
1971
|
+
Object.assign(error, {
|
|
1972
|
+
sentBeforeError: true,
|
|
1973
|
+
visibleReplySent: true
|
|
1974
|
+
});
|
|
1975
|
+
return error;
|
|
1976
|
+
} catch {}
|
|
1977
|
+
const visibleError = new Error("visible WhatsApp reply delivery failed", { cause: error });
|
|
1978
|
+
Object.assign(visibleError, {
|
|
1979
|
+
sentBeforeError: true,
|
|
1980
|
+
visibleReplySent: true
|
|
1981
|
+
});
|
|
1982
|
+
return visibleError;
|
|
1983
|
+
}
|
|
1662
1984
|
function isLikelyWhatsAppCryptoError(reason) {
|
|
1663
1985
|
const formatReason = (value) => {
|
|
1664
1986
|
if (value == null) return "";
|
|
@@ -1718,21 +2040,6 @@ function createWhatsAppReplyDeliveryReceipt(results) {
|
|
|
1718
2040
|
kind: resolveWhatsAppReceiptKind(results)
|
|
1719
2041
|
});
|
|
1720
2042
|
}
|
|
1721
|
-
function markWhatsAppVisibleDeliveryError(error) {
|
|
1722
|
-
if (typeof error === "object" && error !== null && !Array.isArray(error)) try {
|
|
1723
|
-
Object.assign(error, {
|
|
1724
|
-
sentBeforeError: true,
|
|
1725
|
-
visibleReplySent: true
|
|
1726
|
-
});
|
|
1727
|
-
return error;
|
|
1728
|
-
} catch {}
|
|
1729
|
-
const visibleError = new Error("visible WhatsApp reply delivery failed", { cause: error });
|
|
1730
|
-
Object.assign(visibleError, {
|
|
1731
|
-
sentBeforeError: true,
|
|
1732
|
-
visibleReplySent: true
|
|
1733
|
-
});
|
|
1734
|
-
return visibleError;
|
|
1735
|
-
}
|
|
1736
2043
|
async function deliverWebReply(params) {
|
|
1737
2044
|
const { replyResult, msg, maxMediaBytes, textLimit, replyLogger, connectionId, skipLog } = params;
|
|
1738
2045
|
const replyStarted = Date.now();
|
|
@@ -1758,12 +2065,12 @@ async function deliverWebReply(params) {
|
|
|
1758
2065
|
const mediaList = normalizedReply.mediaUrls ?? [];
|
|
1759
2066
|
const getQuote = () => {
|
|
1760
2067
|
if (!replyResult.replyToId) return;
|
|
1761
|
-
const cached = lookupInboundMessageMeta(msg.accountId, msg.
|
|
2068
|
+
const cached = lookupInboundMessageMeta(msg.accountId, msg.platform.chatJid, replyResult.replyToId);
|
|
1762
2069
|
return buildQuotedMessageOptions({
|
|
1763
2070
|
messageId: replyResult.replyToId,
|
|
1764
|
-
remoteJid: msg.
|
|
2071
|
+
remoteJid: msg.platform.chatJid,
|
|
1765
2072
|
fromMe: cached?.fromMe ?? false,
|
|
1766
|
-
participant: cached?.participant ?? (msg.chatType === "group" ? msg.senderJid : void 0),
|
|
2073
|
+
participant: cached?.participant ?? (msg.chatType === "group" ? msg.platform.senderJid : void 0),
|
|
1767
2074
|
messageText: cached?.body ?? ""
|
|
1768
2075
|
});
|
|
1769
2076
|
};
|
|
@@ -1786,7 +2093,7 @@ async function deliverWebReply(params) {
|
|
|
1786
2093
|
for (const [index, chunk] of textChunks.entries()) {
|
|
1787
2094
|
const chunkStarted = Date.now();
|
|
1788
2095
|
const quote = getQuote();
|
|
1789
|
-
rememberSendResult(await sendWithRetry(() => msg.reply(chunk, quote), "text"));
|
|
2096
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.reply(chunk, quote), "text"));
|
|
1790
2097
|
if (!skipLog) {
|
|
1791
2098
|
const durationMs = Date.now() - chunkStarted;
|
|
1792
2099
|
whatsappOutboundLog.debug(`Sent chunk ${index + 1}/${totalChunks} to ${msg.from} (${durationMs.toFixed(0)}ms)`);
|
|
@@ -1794,10 +2101,10 @@ async function deliverWebReply(params) {
|
|
|
1794
2101
|
}
|
|
1795
2102
|
const delivery = finishDelivery();
|
|
1796
2103
|
const logPayload = {
|
|
1797
|
-
correlationId: msg.id ?? newConnectionId(),
|
|
2104
|
+
correlationId: msg.event.id ?? newConnectionId(),
|
|
1798
2105
|
connectionId: connectionId ?? null,
|
|
1799
2106
|
to: msg.from,
|
|
1800
|
-
from: msg.
|
|
2107
|
+
from: msg.platform.recipientJid,
|
|
1801
2108
|
text: elide(replyResult.text, 240),
|
|
1802
2109
|
mediaUrl: null,
|
|
1803
2110
|
mediaSizeBytes: null,
|
|
@@ -1823,29 +2130,29 @@ async function deliverWebReply(params) {
|
|
|
1823
2130
|
}
|
|
1824
2131
|
if (media.kind === "image") {
|
|
1825
2132
|
const quote = getQuote();
|
|
1826
|
-
rememberSendResult(await sendWithRetry(() => msg.sendMedia({
|
|
2133
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.sendMedia({
|
|
1827
2134
|
image: media.buffer,
|
|
1828
2135
|
caption,
|
|
1829
2136
|
mimetype: media.mimetype
|
|
1830
2137
|
}, quote), "media:image"));
|
|
1831
2138
|
} else if (media.kind === "audio") {
|
|
1832
2139
|
const quote = getQuote();
|
|
1833
|
-
rememberSendResult(await sendWithRetry(() => msg.sendMedia({
|
|
2140
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.sendMedia({
|
|
1834
2141
|
audio: media.buffer,
|
|
1835
2142
|
ptt: true,
|
|
1836
2143
|
mimetype: media.mimetype
|
|
1837
2144
|
}, quote), "media:audio"));
|
|
1838
|
-
if (caption) rememberSendResult(await sendWithRetry(() => msg.reply(caption, quote), "media:audio-text"));
|
|
2145
|
+
if (caption) rememberSendResult(await sendWithRetry(() => msg.platform.reply(caption, quote), "media:audio-text"));
|
|
1839
2146
|
} else if (media.kind === "video") {
|
|
1840
2147
|
const quote = getQuote();
|
|
1841
|
-
rememberSendResult(await sendWithRetry(() => msg.sendMedia({
|
|
2148
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.sendMedia({
|
|
1842
2149
|
video: media.buffer,
|
|
1843
2150
|
caption,
|
|
1844
2151
|
mimetype: media.mimetype
|
|
1845
2152
|
}, quote), "media:video"));
|
|
1846
2153
|
} else {
|
|
1847
2154
|
const quote = getQuote();
|
|
1848
|
-
rememberSendResult(await sendWithRetry(() => msg.sendMedia({
|
|
2155
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.sendMedia({
|
|
1849
2156
|
document: media.buffer,
|
|
1850
2157
|
fileName: media.fileName,
|
|
1851
2158
|
caption,
|
|
@@ -1854,10 +2161,10 @@ async function deliverWebReply(params) {
|
|
|
1854
2161
|
}
|
|
1855
2162
|
whatsappOutboundLog.info(`Sent media reply to ${msg.from} (${(media.buffer.length / (1024 * 1024)).toFixed(2)}MB)`);
|
|
1856
2163
|
replyLogger.info({
|
|
1857
|
-
correlationId: msg.id ?? newConnectionId(),
|
|
2164
|
+
correlationId: msg.event.id ?? newConnectionId(),
|
|
1858
2165
|
connectionId: connectionId ?? null,
|
|
1859
2166
|
to: msg.from,
|
|
1860
|
-
from: msg.
|
|
2167
|
+
from: msg.platform.recipientJid,
|
|
1861
2168
|
text: caption ?? null,
|
|
1862
2169
|
mediaUrl,
|
|
1863
2170
|
mediaSizeBytes: media.buffer.length,
|
|
@@ -1875,17 +2182,17 @@ async function deliverWebReply(params) {
|
|
|
1875
2182
|
const fallbackText = [remainingText.shift() ?? caption ?? "", "⚠️ Media failed."].filter(Boolean).join("\n");
|
|
1876
2183
|
if (!fallbackText) return;
|
|
1877
2184
|
whatsappOutboundLog.warn(`Media skipped; sent text-only to ${msg.from}`);
|
|
1878
|
-
rememberSendResult(await sendWithRetry(() => msg.reply(fallbackText, getQuote()), "media:fallback-text"));
|
|
2185
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.reply(fallbackText, getQuote()), "media:fallback-text"));
|
|
1879
2186
|
}
|
|
1880
2187
|
});
|
|
1881
|
-
for (const chunk of remainingText) rememberSendResult(await sendWithRetry(() => msg.reply(chunk, getQuote()), "media:text"));
|
|
2188
|
+
for (const chunk of remainingText) rememberSendResult(await sendWithRetry(() => msg.platform.reply(chunk, getQuote()), "media:text"));
|
|
1882
2189
|
return finishDelivery();
|
|
1883
2190
|
}
|
|
1884
2191
|
//#endregion
|
|
1885
2192
|
//#region extensions/whatsapp/src/auto-reply/monitor/inbound-context.ts
|
|
1886
2193
|
function isWhatsAppSupplementalSenderAllowed(params) {
|
|
1887
2194
|
if (params.allowFrom.includes("*")) return true;
|
|
1888
|
-
const senderValues = new Set(getComparableIdentityValues(params.sender));
|
|
2195
|
+
const senderValues = new Set(getComparableIdentityValues(resolveComparableIdentity(params.sender, params.authDir)));
|
|
1889
2196
|
if (senderValues.size === 0) return false;
|
|
1890
2197
|
for (const entry of params.allowFrom) {
|
|
1891
2198
|
const rawEntry = entry.trim();
|
|
@@ -1903,6 +2210,7 @@ function resolveVisibleWhatsAppGroupHistory(params) {
|
|
|
1903
2210
|
kind: "history",
|
|
1904
2211
|
isSenderAllowed: (entry) => isWhatsAppSupplementalSenderAllowed({
|
|
1905
2212
|
allowFrom: params.groupAllowFrom,
|
|
2213
|
+
authDir: params.authDir,
|
|
1906
2214
|
sender: entry.senderJid ? { jid: entry.senderJid } : null
|
|
1907
2215
|
})
|
|
1908
2216
|
}).items;
|
|
@@ -1912,6 +2220,7 @@ function resolveVisibleWhatsAppReplyContext(params) {
|
|
|
1912
2220
|
if (!replyTo) return null;
|
|
1913
2221
|
const senderAllowed = params.msg.chatType !== "group" || params.groupPolicy !== "allowlist" ? true : isWhatsAppSupplementalSenderAllowed({
|
|
1914
2222
|
allowFrom: params.groupAllowFrom,
|
|
2223
|
+
authDir: params.authDir,
|
|
1915
2224
|
sender: replyTo.sender
|
|
1916
2225
|
});
|
|
1917
2226
|
return filterChannelInboundQuoteContext(params.mode, {
|
|
@@ -1938,34 +2247,19 @@ function whatsAppReplyDeliveryVisibility(visibleReplySent) {
|
|
|
1938
2247
|
function whatsAppReplyDeliveryVisibilityFromDurableResult(result) {
|
|
1939
2248
|
return whatsAppReplyDeliveryVisibility(result.visibleReplySent === true);
|
|
1940
2249
|
}
|
|
1941
|
-
function markWhatsAppReplyDeliveryErrorVisible(error) {
|
|
1942
|
-
if (typeof error === "object" && error !== null && !Array.isArray(error)) try {
|
|
1943
|
-
Object.assign(error, {
|
|
1944
|
-
sentBeforeError: true,
|
|
1945
|
-
visibleReplySent: true
|
|
1946
|
-
});
|
|
1947
|
-
return error;
|
|
1948
|
-
} catch {}
|
|
1949
|
-
const visibleError = new Error("visible WhatsApp reply delivery failed", { cause: error });
|
|
1950
|
-
Object.assign(visibleError, {
|
|
1951
|
-
sentBeforeError: true,
|
|
1952
|
-
visibleReplySent: true
|
|
1953
|
-
});
|
|
1954
|
-
return visibleError;
|
|
1955
|
-
}
|
|
1956
2250
|
function markWhatsAppReplyDeliveryErrorVisibleAfterFlush(error, flushResult) {
|
|
1957
|
-
return flushResult.delivered > 0 ?
|
|
2251
|
+
return flushResult.delivered > 0 ? markWhatsAppVisibleDeliveryError(error) : error;
|
|
1958
2252
|
}
|
|
1959
2253
|
function logWhatsAppReplyDeliveryError(params) {
|
|
1960
2254
|
params.replyLogger.error({
|
|
1961
2255
|
err: normalizeErrForLog(params.err),
|
|
1962
2256
|
replyKind: params.info.kind,
|
|
1963
|
-
correlationId: params.msg.id ?? null,
|
|
2257
|
+
correlationId: params.msg.event.id ?? null,
|
|
1964
2258
|
connectionId: params.connectionId,
|
|
1965
2259
|
conversationId: params.conversationId,
|
|
1966
|
-
chatId: params.msg.
|
|
2260
|
+
chatId: params.msg.platform.chatJid ?? null,
|
|
1967
2261
|
to: params.msg.from ?? null,
|
|
1968
|
-
from: params.msg.
|
|
2262
|
+
from: params.msg.platform.recipientJid ?? null
|
|
1969
2263
|
}, "auto-reply delivery failed");
|
|
1970
2264
|
}
|
|
1971
2265
|
function resolveWhatsAppDisableBlockStreaming(cfg) {
|
|
@@ -2042,10 +2336,10 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2042
2336
|
})),
|
|
2043
2337
|
limit: params.groupHistory?.length ?? 1
|
|
2044
2338
|
}) : void 0;
|
|
2045
|
-
const media = toInboundMediaFacts(params.msg.
|
|
2046
|
-
path: params.msg.
|
|
2047
|
-
url: params.msg.
|
|
2048
|
-
contentType: params.msg.
|
|
2339
|
+
const media = toInboundMediaFacts(params.msg.payload.media?.path || params.msg.payload.media?.url ? [{
|
|
2340
|
+
path: params.msg.payload.media?.path,
|
|
2341
|
+
url: params.msg.payload.media?.url ?? params.msg.payload.media?.path,
|
|
2342
|
+
contentType: params.msg.payload.media?.type
|
|
2049
2343
|
}] : void 0, { transcribed: (_entry, index) => params.mediaTranscribedIndexes?.includes(index) === true });
|
|
2050
2344
|
return buildChannelInboundEventContext({
|
|
2051
2345
|
channel: "whatsapp",
|
|
@@ -2057,11 +2351,11 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2057
2351
|
sender: params.visibleReplyTo.sender?.label ?? void 0
|
|
2058
2352
|
} : void 0,
|
|
2059
2353
|
groupSystemPrompt: params.groupSystemPrompt,
|
|
2060
|
-
untrustedContext: params.msg.untrustedStructuredContext
|
|
2354
|
+
untrustedContext: params.msg.payload.untrustedStructuredContext
|
|
2061
2355
|
},
|
|
2062
2356
|
media,
|
|
2063
|
-
messageId: params.msg.id,
|
|
2064
|
-
timestamp: params.msg.timestamp,
|
|
2357
|
+
messageId: params.msg.event.id,
|
|
2358
|
+
timestamp: params.msg.event.timestamp,
|
|
2065
2359
|
from: params.msg.from,
|
|
2066
2360
|
sender: {
|
|
2067
2361
|
id: params.sender.id ?? params.sender.e164,
|
|
@@ -2078,15 +2372,15 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2078
2372
|
routeSessionKey: params.route.sessionKey
|
|
2079
2373
|
},
|
|
2080
2374
|
reply: {
|
|
2081
|
-
to: params.msg.
|
|
2375
|
+
to: params.msg.platform.recipientJid,
|
|
2082
2376
|
originatingTo: params.msg.from
|
|
2083
2377
|
},
|
|
2084
2378
|
message: {
|
|
2085
2379
|
body: params.combinedBody,
|
|
2086
|
-
bodyForAgent: params.bodyForAgent ?? params.msg.body,
|
|
2380
|
+
bodyForAgent: params.bodyForAgent ?? params.msg.payload.body,
|
|
2087
2381
|
inboundHistory,
|
|
2088
|
-
rawBody: params.rawBody ?? params.msg.body,
|
|
2089
|
-
commandBody: params.commandBody ?? params.msg.body
|
|
2382
|
+
rawBody: params.rawBody ?? params.msg.payload.body,
|
|
2383
|
+
commandBody: params.commandBody ?? params.msg.payload.body
|
|
2090
2384
|
},
|
|
2091
2385
|
access: {
|
|
2092
2386
|
...params.msg.wasMentioned !== void 0 ? { mentions: {
|
|
@@ -2098,16 +2392,17 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2098
2392
|
commandTurn: params.commandTurn,
|
|
2099
2393
|
extra: {
|
|
2100
2394
|
Transcript: params.transcript,
|
|
2101
|
-
GroupSubject: params.msg.
|
|
2395
|
+
GroupSubject: params.msg.group?.subject,
|
|
2102
2396
|
GroupMembers: formatGroupMembers({
|
|
2103
|
-
participants: params.msg.
|
|
2397
|
+
participants: params.msg.group?.participants,
|
|
2104
2398
|
roster: params.groupMemberRoster,
|
|
2105
2399
|
fallbackE164: params.sender.e164
|
|
2106
2400
|
}),
|
|
2107
2401
|
SenderE164: params.sender.e164,
|
|
2108
2402
|
CommandSource: params.commandSource ?? (params.commandTurn?.source === "native" || params.commandTurn?.source === "text" ? params.commandTurn.source : void 0),
|
|
2109
2403
|
ReplyThreading: params.replyThreading,
|
|
2110
|
-
|
|
2404
|
+
SuppressMessageReceivedHooks: params.suppressMessageReceivedHooks,
|
|
2405
|
+
...params.msg.payload.location ? toLocationContext(params.msg.payload.location) : {}
|
|
2111
2406
|
}
|
|
2112
2407
|
});
|
|
2113
2408
|
}
|
|
@@ -2215,12 +2510,12 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2215
2510
|
tableMode
|
|
2216
2511
|
})).providerAccepted) {
|
|
2217
2512
|
params.replyLogger.warn({
|
|
2218
|
-
correlationId: params.msg.id ?? null,
|
|
2513
|
+
correlationId: params.msg.event.id ?? null,
|
|
2219
2514
|
connectionId: params.connectionId,
|
|
2220
2515
|
conversationId: params.conversationId,
|
|
2221
|
-
chatId: params.msg.
|
|
2516
|
+
chatId: params.msg.platform.chatJid,
|
|
2222
2517
|
to: params.msg.from,
|
|
2223
|
-
from: params.msg.
|
|
2518
|
+
from: params.msg.platform.recipientJid,
|
|
2224
2519
|
replyKind: info.kind
|
|
2225
2520
|
}, "auto-reply was not accepted by WhatsApp provider");
|
|
2226
2521
|
return whatsAppReplyDeliveryVisibility(false);
|
|
@@ -2282,7 +2577,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2282
2577
|
}
|
|
2283
2578
|
});
|
|
2284
2579
|
if (durable.status === "failed") {
|
|
2285
|
-
if (durable.sentBeforeError === true) throw
|
|
2580
|
+
if (durable.sentBeforeError === true) throw markWhatsAppVisibleDeliveryError(durable.error);
|
|
2286
2581
|
throw durable.error;
|
|
2287
2582
|
}
|
|
2288
2583
|
if (durable.status === "handled_visible") {
|
|
@@ -2329,7 +2624,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2329
2624
|
logWhatsAppMediaOnlyFlushResult(flushResult);
|
|
2330
2625
|
return whatsAppReplyDeliveryVisibility(flushResult.delivered > 0);
|
|
2331
2626
|
},
|
|
2332
|
-
onReplyStart: params.msg.sendComposing,
|
|
2627
|
+
onReplyStart: params.msg.platform.sendComposing,
|
|
2333
2628
|
...statusReactionController ? {
|
|
2334
2629
|
onCompactionStart: async () => {
|
|
2335
2630
|
await statusReactionController.setCompacting();
|
|
@@ -2429,11 +2724,13 @@ function resolveMessagePrefix(cfg, agentId, opts) {
|
|
|
2429
2724
|
}
|
|
2430
2725
|
//#endregion
|
|
2431
2726
|
//#region extensions/whatsapp/src/auto-reply/monitor/message-line.ts
|
|
2432
|
-
function
|
|
2433
|
-
const replyTo = getReplyContext(msg);
|
|
2727
|
+
function formatReplyTarget(replyTo) {
|
|
2434
2728
|
if (!replyTo?.body) return null;
|
|
2435
2729
|
return `[Replying to ${replyTo.sender?.label ?? replyTo.sender?.e164 ?? "unknown sender"}${replyTo.id ? ` id:${replyTo.id}` : ""}]\n${replyTo.body}\n[/Replying]`;
|
|
2436
2730
|
}
|
|
2731
|
+
function formatReplyContext(msg) {
|
|
2732
|
+
return formatReplyTarget(getReplyContext(msg));
|
|
2733
|
+
}
|
|
2437
2734
|
function buildInboundLine(params) {
|
|
2438
2735
|
const { cfg, msg, agentId, previousTimestamp, envelope } = params;
|
|
2439
2736
|
const messagePrefix = resolveMessagePrefix(cfg, agentId, {
|
|
@@ -2441,13 +2738,13 @@ function buildInboundLine(params) {
|
|
|
2441
2738
|
hasAllowFrom: (cfg.channels?.whatsapp?.allowFrom?.length ?? 0) > 0
|
|
2442
2739
|
});
|
|
2443
2740
|
const prefixStr = messagePrefix ? `${messagePrefix} ` : "";
|
|
2444
|
-
const replyContext = formatReplyContext(msg);
|
|
2445
|
-
const baseLine = `${prefixStr}${msg.body}${replyContext ? `\n\n${replyContext}` : ""}`;
|
|
2741
|
+
const replyContext = params.visibleReplyTo === void 0 ? formatReplyContext(msg) : formatReplyTarget(params.visibleReplyTo);
|
|
2742
|
+
const baseLine = `${prefixStr}${msg.payload.body}${replyContext ? `\n\n${replyContext}` : ""}`;
|
|
2446
2743
|
const sender = getSenderIdentity(msg);
|
|
2447
2744
|
return formatInboundEnvelope({
|
|
2448
2745
|
channel: "WhatsApp",
|
|
2449
2746
|
from: msg.chatType === "group" ? msg.from : msg.from?.replace(/^whatsapp:/, ""),
|
|
2450
|
-
timestamp: msg.timestamp,
|
|
2747
|
+
timestamp: msg.event.timestamp,
|
|
2451
2748
|
body: baseLine,
|
|
2452
2749
|
chatType: msg.chatType,
|
|
2453
2750
|
sender: {
|
|
@@ -2457,13 +2754,13 @@ function buildInboundLine(params) {
|
|
|
2457
2754
|
},
|
|
2458
2755
|
previousTimestamp,
|
|
2459
2756
|
envelope,
|
|
2460
|
-
fromMe: msg.fromMe
|
|
2757
|
+
fromMe: msg.platform.fromMe
|
|
2461
2758
|
});
|
|
2462
2759
|
}
|
|
2463
2760
|
//#endregion
|
|
2464
2761
|
//#region extensions/whatsapp/src/auto-reply/monitor/status-reaction.ts
|
|
2465
2762
|
async function createWhatsAppStatusReactionController(params) {
|
|
2466
|
-
if (!params.msg.id) return null;
|
|
2763
|
+
if (!params.msg.event.id) return null;
|
|
2467
2764
|
const statusReactionsConfig = params.cfg.messages?.statusReactions;
|
|
2468
2765
|
if (statusReactionsConfig?.enabled !== true) return null;
|
|
2469
2766
|
if (resolveWhatsAppReactionLevel({
|
|
@@ -2504,8 +2801,8 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
2504
2801
|
...params.accountId ? { accountId: params.accountId } : {},
|
|
2505
2802
|
cfg: params.cfg
|
|
2506
2803
|
};
|
|
2507
|
-
const chatId = params.msg.
|
|
2508
|
-
const msgId = params.msg.id;
|
|
2804
|
+
const chatId = params.msg.platform.chatJid;
|
|
2805
|
+
const msgId = params.msg.event.id;
|
|
2509
2806
|
return createStatusReactionController({
|
|
2510
2807
|
enabled: true,
|
|
2511
2808
|
adapter: {
|
|
@@ -2584,15 +2881,15 @@ async function processMessage(params) {
|
|
|
2584
2881
|
sessionKey: params.route.sessionKey
|
|
2585
2882
|
});
|
|
2586
2883
|
let audioTranscript = params.preflightAudioTranscript ?? void 0;
|
|
2587
|
-
const hasAudioBody = params.msg.
|
|
2588
|
-
if (params.preflightAudioTranscript === void 0 && hasAudioBody && params.msg.
|
|
2884
|
+
const hasAudioBody = params.msg.payload.media?.type?.startsWith("audio/") === true && params.msg.payload.body === "<media:audio>";
|
|
2885
|
+
if (params.preflightAudioTranscript === void 0 && hasAudioBody && params.msg.payload.media?.path) try {
|
|
2589
2886
|
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
2590
2887
|
audioTranscript = await transcribeFirstAudio({
|
|
2591
2888
|
ctx: {
|
|
2592
|
-
MediaPaths: [params.msg.
|
|
2593
|
-
MediaTypes: params.msg.
|
|
2889
|
+
MediaPaths: [params.msg.payload.media?.path],
|
|
2890
|
+
MediaTypes: params.msg.payload.media?.type ? [params.msg.payload.media?.type] : void 0,
|
|
2594
2891
|
From: params.msg.from,
|
|
2595
|
-
To: params.msg.
|
|
2892
|
+
To: params.msg.platform.recipientJid,
|
|
2596
2893
|
Provider: "whatsapp",
|
|
2597
2894
|
Surface: "whatsapp",
|
|
2598
2895
|
OriginatingChannel: "whatsapp",
|
|
@@ -2606,21 +2903,33 @@ async function processMessage(params) {
|
|
|
2606
2903
|
}
|
|
2607
2904
|
const msgForAgent = audioTranscript !== void 0 ? {
|
|
2608
2905
|
...params.msg,
|
|
2609
|
-
|
|
2906
|
+
payload: {
|
|
2907
|
+
...params.msg.payload,
|
|
2908
|
+
body: audioTranscript
|
|
2909
|
+
}
|
|
2610
2910
|
} : params.msg;
|
|
2911
|
+
const visibleReplyTo = resolveVisibleWhatsAppReplyContext({
|
|
2912
|
+
msg: params.msg,
|
|
2913
|
+
authDir: account.authDir,
|
|
2914
|
+
mode: contextVisibilityMode,
|
|
2915
|
+
groupPolicy: inboundPolicy.groupPolicy,
|
|
2916
|
+
groupAllowFrom: inboundPolicy.groupAllowFrom
|
|
2917
|
+
});
|
|
2611
2918
|
let combinedBody = buildInboundLine({
|
|
2612
2919
|
cfg: params.cfg,
|
|
2613
2920
|
msg: msgForAgent,
|
|
2614
2921
|
agentId: params.route.agentId,
|
|
2615
2922
|
previousTimestamp,
|
|
2616
|
-
envelope: envelopeOptions
|
|
2923
|
+
envelope: envelopeOptions,
|
|
2924
|
+
visibleReplyTo
|
|
2617
2925
|
});
|
|
2618
2926
|
let shouldClearGroupHistory = false;
|
|
2619
2927
|
const visibleGroupHistory = params.msg.chatType === "group" ? resolveVisibleWhatsAppGroupHistory({
|
|
2620
2928
|
history: params.groupHistory ?? params.groupHistories.get(params.groupHistoryKey) ?? [],
|
|
2621
2929
|
mode: contextVisibilityMode,
|
|
2622
2930
|
groupPolicy: inboundPolicy.groupPolicy,
|
|
2623
|
-
groupAllowFrom: inboundPolicy.groupAllowFrom
|
|
2931
|
+
groupAllowFrom: inboundPolicy.groupAllowFrom,
|
|
2932
|
+
authDir: account.authDir
|
|
2624
2933
|
}) : void 0;
|
|
2625
2934
|
if (params.msg.chatType === "group") {
|
|
2626
2935
|
const history = visibleGroupHistory ?? [];
|
|
@@ -2677,35 +2986,28 @@ async function processMessage(params) {
|
|
|
2677
2986
|
info: params.replyLogger.info.bind(params.replyLogger),
|
|
2678
2987
|
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
2679
2988
|
});
|
|
2680
|
-
const correlationId = params.msg.id ?? newConnectionId();
|
|
2989
|
+
const correlationId = params.msg.event.id ?? newConnectionId();
|
|
2681
2990
|
params.replyLogger.info({
|
|
2682
2991
|
connectionId: params.connectionId,
|
|
2683
2992
|
correlationId,
|
|
2684
2993
|
from: params.msg.chatType === "group" ? conversationId : params.msg.from,
|
|
2685
|
-
to: params.msg.
|
|
2994
|
+
to: params.msg.platform.recipientJid,
|
|
2686
2995
|
body: elide(combinedBody, 240),
|
|
2687
|
-
mediaType: params.msg.
|
|
2688
|
-
mediaPath: params.msg.
|
|
2996
|
+
mediaType: params.msg.payload.media?.type ?? null,
|
|
2997
|
+
mediaPath: params.msg.payload.media?.path ?? null
|
|
2689
2998
|
}, "inbound web message");
|
|
2690
2999
|
const fromDisplay = params.msg.chatType === "group" ? conversationId : params.msg.from;
|
|
2691
|
-
const kindLabel = params.msg.
|
|
2692
|
-
whatsappInboundLog.info(`Inbound message ${fromDisplay} -> ${params.msg.
|
|
3000
|
+
const kindLabel = params.msg.payload.media?.type ? `, ${params.msg.payload.media?.type}` : "";
|
|
3001
|
+
whatsappInboundLog.info(`Inbound message ${fromDisplay} -> ${params.msg.platform.recipientJid} (${params.msg.chatType}${kindLabel}, ${combinedBody.length} chars)`);
|
|
2693
3002
|
if (shouldLogVerbose$1()) whatsappInboundLog.debug(`Inbound body: ${elide(combinedBody, 400)}`);
|
|
2694
3003
|
const sender = getSenderIdentity(params.msg);
|
|
2695
|
-
const visibleReplyTo = resolveVisibleWhatsAppReplyContext({
|
|
2696
|
-
msg: params.msg,
|
|
2697
|
-
authDir: account.authDir,
|
|
2698
|
-
mode: contextVisibilityMode,
|
|
2699
|
-
groupPolicy: inboundPolicy.groupPolicy,
|
|
2700
|
-
groupAllowFrom: inboundPolicy.groupAllowFrom
|
|
2701
|
-
});
|
|
2702
3004
|
const dmRouteTarget = resolveWhatsAppDmRouteTarget({
|
|
2703
3005
|
msg: params.msg,
|
|
2704
3006
|
senderE164: sender.e164 ?? void 0,
|
|
2705
3007
|
normalizeE164
|
|
2706
3008
|
});
|
|
2707
|
-
const shouldCheckCommandAuth = shouldComputeCommandAuthorized(params.msg.body, params.cfg);
|
|
2708
|
-
const isTextCommand = isControlCommandMessage$1(params.msg.body, params.cfg);
|
|
3009
|
+
const shouldCheckCommandAuth = shouldComputeCommandAuthorized(params.msg.payload.body, params.cfg);
|
|
3010
|
+
const isTextCommand = isControlCommandMessage$1(params.msg.payload.body, params.cfg);
|
|
2709
3011
|
const commandAuthorized = shouldCheckCommandAuth ? await resolveWhatsAppCommandAuthorized({
|
|
2710
3012
|
cfg: params.cfg,
|
|
2711
3013
|
msg: params.msg,
|
|
@@ -2715,12 +3017,12 @@ async function processMessage(params) {
|
|
|
2715
3017
|
kind: "text-slash",
|
|
2716
3018
|
source: "text",
|
|
2717
3019
|
authorized: Boolean(commandAuthorized),
|
|
2718
|
-
body: params.msg.body
|
|
3020
|
+
body: params.msg.payload.body
|
|
2719
3021
|
} : {
|
|
2720
3022
|
kind: "normal",
|
|
2721
3023
|
source: "message",
|
|
2722
3024
|
authorized: false,
|
|
2723
|
-
body: params.msg.body
|
|
3025
|
+
body: params.msg.payload.body
|
|
2724
3026
|
};
|
|
2725
3027
|
const { onModelSelected, ...replyPipeline } = createChannelMessageReplyPipeline({
|
|
2726
3028
|
cfg: params.cfg,
|
|
@@ -2734,7 +3036,7 @@ async function processMessage(params) {
|
|
|
2734
3036
|
isSelfChat: params.msg.chatType !== "group" && inboundPolicy.isSelfChat,
|
|
2735
3037
|
pipelineResponsePrefix: replyPipeline.responsePrefix
|
|
2736
3038
|
});
|
|
2737
|
-
const replyThreading = resolveBatchedReplyThreadingPolicy(account.replyToMode ?? "off", params.msg.isBatched === true);
|
|
3039
|
+
const replyThreading = resolveBatchedReplyThreadingPolicy(account.replyToMode ?? "off", params.msg.event.isBatched === true);
|
|
2738
3040
|
const conversationSystemPrompt = params.msg.chatType === "group" ? resolveWhatsAppGroupSystemPrompt({
|
|
2739
3041
|
accountConfig: account,
|
|
2740
3042
|
groupId: conversationId
|
|
@@ -2743,9 +3045,9 @@ async function processMessage(params) {
|
|
|
2743
3045
|
peerId: dmRouteTarget ?? params.msg.from
|
|
2744
3046
|
});
|
|
2745
3047
|
const ctxPayload = await buildWhatsAppInboundContext({
|
|
2746
|
-
bodyForAgent: msgForAgent.body,
|
|
3048
|
+
bodyForAgent: msgForAgent.payload.body,
|
|
2747
3049
|
combinedBody,
|
|
2748
|
-
commandBody: params.msg.body,
|
|
3050
|
+
commandBody: params.msg.payload.body,
|
|
2749
3051
|
commandAuthorized,
|
|
2750
3052
|
commandTurn,
|
|
2751
3053
|
conversationId,
|
|
@@ -2753,7 +3055,7 @@ async function processMessage(params) {
|
|
|
2753
3055
|
groupMemberRoster: params.groupMemberNames.get(params.groupHistoryKey),
|
|
2754
3056
|
groupSystemPrompt: conversationSystemPrompt,
|
|
2755
3057
|
msg: params.msg,
|
|
2756
|
-
rawBody: params.msg.body,
|
|
3058
|
+
rawBody: params.msg.payload.body,
|
|
2757
3059
|
route: params.route,
|
|
2758
3060
|
sender: {
|
|
2759
3061
|
id: getPrimaryIdentityId(sender) ?? void 0,
|
|
@@ -2763,7 +3065,8 @@ async function processMessage(params) {
|
|
|
2763
3065
|
...audioTranscript !== void 0 ? { transcript: audioTranscript } : {},
|
|
2764
3066
|
...audioTranscript !== void 0 ? { mediaTranscribedIndexes: [0] } : {},
|
|
2765
3067
|
replyThreading,
|
|
2766
|
-
visibleReplyTo: visibleReplyTo ?? void 0
|
|
3068
|
+
visibleReplyTo: visibleReplyTo ?? void 0,
|
|
3069
|
+
suppressMessageReceivedHooks: true
|
|
2767
3070
|
});
|
|
2768
3071
|
emitWhatsAppMessageReceivedHooksIfEnabled({
|
|
2769
3072
|
cfg: params.cfg,
|
|
@@ -2791,8 +3094,8 @@ async function processMessage(params) {
|
|
|
2791
3094
|
raw: params.msg,
|
|
2792
3095
|
adapter: {
|
|
2793
3096
|
ingest: () => ({
|
|
2794
|
-
id: params.msg.id ?? `${conversationId}:${Date.now()}`,
|
|
2795
|
-
timestamp: params.msg.timestamp,
|
|
3097
|
+
id: params.msg.event.id ?? `${conversationId}:${Date.now()}`,
|
|
3098
|
+
timestamp: params.msg.event.timestamp,
|
|
2796
3099
|
rawText: ctxPayload.RawBody ?? "",
|
|
2797
3100
|
textForAgent: ctxPayload.BodyForAgent,
|
|
2798
3101
|
textForCommands: ctxPayload.CommandBody,
|
|
@@ -2851,7 +3154,7 @@ async function processMessage(params) {
|
|
|
2851
3154
|
logAckFailure({
|
|
2852
3155
|
log: logVerbose$1,
|
|
2853
3156
|
channel: "whatsapp",
|
|
2854
|
-
target: `${params.msg.
|
|
3157
|
+
target: `${params.msg.platform.chatJid ?? conversationId}/${params.msg.event.id ?? "unknown"}`,
|
|
2855
3158
|
error: err
|
|
2856
3159
|
});
|
|
2857
3160
|
}
|
|
@@ -2861,6 +3164,22 @@ async function processMessage(params) {
|
|
|
2861
3164
|
//#endregion
|
|
2862
3165
|
//#region extensions/whatsapp/src/auto-reply/monitor/on-message.ts
|
|
2863
3166
|
function createWebOnMessageHandler(params) {
|
|
3167
|
+
const withDirectSenderPeer = (msg, peerId) => {
|
|
3168
|
+
if (msg.chatType === "group" || msg.platform.sender?.e164 || msg.platform.senderE164 || !peerId.startsWith("+")) return msg;
|
|
3169
|
+
const normalized = normalizeE164(peerId);
|
|
3170
|
+
if (!normalized) return msg;
|
|
3171
|
+
return withDeprecatedWebInboundMessageFlatAliases({
|
|
3172
|
+
...msg,
|
|
3173
|
+
platform: {
|
|
3174
|
+
...msg.platform,
|
|
3175
|
+
sender: {
|
|
3176
|
+
...msg.platform.sender,
|
|
3177
|
+
e164: normalized
|
|
3178
|
+
},
|
|
3179
|
+
senderE164: normalized
|
|
3180
|
+
}
|
|
3181
|
+
});
|
|
3182
|
+
};
|
|
2864
3183
|
const processForRoute = async (cfg, msg, route, groupHistoryKey, opts) => {
|
|
2865
3184
|
const processParams = {
|
|
2866
3185
|
cfg,
|
|
@@ -2888,10 +3207,12 @@ function createWebOnMessageHandler(params) {
|
|
|
2888
3207
|
if (opts?.statusReactionController !== void 0) processParams.statusReactionController = opts.statusReactionController;
|
|
2889
3208
|
return processMessage(processParams);
|
|
2890
3209
|
};
|
|
2891
|
-
return async (
|
|
3210
|
+
return async (rawMsg) => {
|
|
3211
|
+
const normalizedMsg = normalizeWebInboundMessage(rawMsg);
|
|
2892
3212
|
const cfg = params.loadConfig?.() ?? params.cfg;
|
|
3213
|
+
const peerId = resolvePeerId(normalizedMsg);
|
|
3214
|
+
const msg = withDirectSenderPeer(normalizedMsg, peerId);
|
|
2893
3215
|
const conversationId = msg.conversationId ?? msg.from;
|
|
2894
|
-
const peerId = resolvePeerId(msg);
|
|
2895
3216
|
const baseRoute = resolveAgentRoute({
|
|
2896
3217
|
cfg,
|
|
2897
3218
|
channel: "whatsapp",
|
|
@@ -2901,32 +3222,54 @@ function createWebOnMessageHandler(params) {
|
|
|
2901
3222
|
id: peerId
|
|
2902
3223
|
}
|
|
2903
3224
|
});
|
|
2904
|
-
const
|
|
2905
|
-
const
|
|
2906
|
-
channel: "whatsapp",
|
|
2907
|
-
accountId: route.accountId,
|
|
2908
|
-
peerKind: "group",
|
|
2909
|
-
peerId
|
|
2910
|
-
}) : route.sessionKey;
|
|
3225
|
+
const baseConversationRoute = msg.chatType === "group" ? resolveWhatsAppGroupSessionRoute(baseRoute) : baseRoute;
|
|
3226
|
+
const routeAccountId = baseConversationRoute.accountId ?? msg.accountId ?? params.account.accountId ?? "default";
|
|
2911
3227
|
const account = resolveWhatsAppAccount({
|
|
2912
3228
|
cfg,
|
|
2913
|
-
accountId:
|
|
3229
|
+
accountId: routeAccountId
|
|
2914
3230
|
});
|
|
2915
3231
|
const baseMentionConfig = buildMentionConfig(cfg);
|
|
2916
|
-
if (msg.from === msg.
|
|
2917
|
-
if (params.echoTracker.has(msg.body)) {
|
|
3232
|
+
if (msg.from === msg.platform.recipientJid) logVerbose(`📱 Same-phone mode detected (from === to: ${msg.from})`);
|
|
3233
|
+
if (params.echoTracker.has(msg.payload.body)) {
|
|
2918
3234
|
logVerbose("Skipping auto-reply: detected echo (message matches recently sent text)");
|
|
2919
|
-
params.echoTracker.forget(msg.body);
|
|
3235
|
+
params.echoTracker.forget(msg.payload.body);
|
|
2920
3236
|
return;
|
|
2921
3237
|
}
|
|
3238
|
+
const configuredRoute = resolveConfiguredBindingRoute({
|
|
3239
|
+
cfg,
|
|
3240
|
+
route: baseConversationRoute,
|
|
3241
|
+
channel: "whatsapp",
|
|
3242
|
+
accountId: routeAccountId,
|
|
3243
|
+
conversationId: peerId
|
|
3244
|
+
});
|
|
3245
|
+
const route = configuredRoute.route;
|
|
3246
|
+
const groupHistoryKey = msg.chatType === "group" ? buildGroupHistoryKey({
|
|
3247
|
+
channel: "whatsapp",
|
|
3248
|
+
accountId: route.accountId,
|
|
3249
|
+
peerKind: "group",
|
|
3250
|
+
peerId
|
|
3251
|
+
}) : route.sessionKey;
|
|
2922
3252
|
let preflightAudioTranscript;
|
|
2923
|
-
const hasAudioBody = msg.
|
|
3253
|
+
const hasAudioBody = msg.payload.media?.type?.startsWith("audio/") === true && msg.payload.body === "<media:audio>";
|
|
2924
3254
|
const canRunEarlyAudioPreflight = msg.chatType === "group" || msg.accessControlPassed === true;
|
|
2925
3255
|
let ackAlreadySent = false;
|
|
2926
3256
|
let ackReaction = null;
|
|
2927
3257
|
let statusReactionController = null;
|
|
3258
|
+
let recordAcceptedConfiguredGroupRoute = null;
|
|
3259
|
+
const clearPreDispatchReaction = async () => {
|
|
3260
|
+
try {
|
|
3261
|
+
if (statusReactionController) {
|
|
3262
|
+
statusReactionController.cancelPending();
|
|
3263
|
+
await statusReactionController.clear();
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
if (ackReaction && await ackReaction.ackReactionPromise) await ackReaction.remove();
|
|
3267
|
+
} catch (err) {
|
|
3268
|
+
params.replyLogger.warn({ error: String(err) }, "whatsapp: failed to clear pre-dispatch reaction after configured ACP readiness failure");
|
|
3269
|
+
}
|
|
3270
|
+
};
|
|
2928
3271
|
const runAudioPreflightOnce = async () => {
|
|
2929
|
-
if (preflightAudioTranscript !== void 0 || !canRunEarlyAudioPreflight || !hasAudioBody || !msg.
|
|
3272
|
+
if (preflightAudioTranscript !== void 0 || !canRunEarlyAudioPreflight || !hasAudioBody || !msg.payload.media?.path) return;
|
|
2930
3273
|
if (cfg.messages?.statusReactions?.enabled === true) {
|
|
2931
3274
|
statusReactionController = await createWhatsAppStatusReactionController({
|
|
2932
3275
|
cfg,
|
|
@@ -2956,10 +3299,10 @@ function createWebOnMessageHandler(params) {
|
|
|
2956
3299
|
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
2957
3300
|
preflightAudioTranscript = await transcribeFirstAudio({
|
|
2958
3301
|
ctx: {
|
|
2959
|
-
MediaPaths: [msg.
|
|
2960
|
-
MediaTypes: msg.
|
|
3302
|
+
MediaPaths: [msg.payload.media?.path],
|
|
3303
|
+
MediaTypes: msg.payload.media?.type ? [msg.payload.media?.type] : void 0,
|
|
2961
3304
|
From: msg.from,
|
|
2962
|
-
To: msg.
|
|
3305
|
+
To: msg.platform.recipientJid,
|
|
2963
3306
|
Provider: "whatsapp",
|
|
2964
3307
|
Surface: "whatsapp",
|
|
2965
3308
|
OriginatingChannel: "whatsapp",
|
|
@@ -2976,12 +3319,12 @@ function createWebOnMessageHandler(params) {
|
|
|
2976
3319
|
const sender = getSenderIdentity(msg);
|
|
2977
3320
|
const metaCtx = {
|
|
2978
3321
|
From: msg.from,
|
|
2979
|
-
To: msg.
|
|
3322
|
+
To: msg.platform.recipientJid,
|
|
2980
3323
|
SessionKey: route.sessionKey,
|
|
2981
3324
|
AccountId: route.accountId,
|
|
2982
3325
|
ChatType: msg.chatType,
|
|
2983
3326
|
ConversationLabel: conversationId,
|
|
2984
|
-
GroupSubject: msg.
|
|
3327
|
+
GroupSubject: msg.group?.subject,
|
|
2985
3328
|
SenderName: sender.name ?? void 0,
|
|
2986
3329
|
SenderId: getPrimaryIdentityId(sender) ?? void 0,
|
|
2987
3330
|
SenderE164: sender.e164 ?? void 0,
|
|
@@ -2990,7 +3333,7 @@ function createWebOnMessageHandler(params) {
|
|
|
2990
3333
|
OriginatingChannel: "whatsapp",
|
|
2991
3334
|
OriginatingTo: conversationId
|
|
2992
3335
|
};
|
|
2993
|
-
updateLastRouteInBackground({
|
|
3336
|
+
const recordGroupRoute = () => updateLastRouteInBackground({
|
|
2994
3337
|
cfg,
|
|
2995
3338
|
backgroundTasks: params.backgroundTasks,
|
|
2996
3339
|
storeAgentId: route.agentId,
|
|
@@ -3001,10 +3344,12 @@ function createWebOnMessageHandler(params) {
|
|
|
3001
3344
|
ctx: metaCtx,
|
|
3002
3345
|
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
3003
3346
|
});
|
|
3347
|
+
if (configuredRoute.bindingResolution) recordAcceptedConfiguredGroupRoute = recordGroupRoute;
|
|
3348
|
+
else recordGroupRoute();
|
|
3004
3349
|
let gating = await applyGroupGating({
|
|
3005
3350
|
cfg,
|
|
3006
3351
|
msg,
|
|
3007
|
-
deferMissingMention: hasAudioBody && Boolean(msg.
|
|
3352
|
+
deferMissingMention: hasAudioBody && Boolean(msg.payload.media?.path),
|
|
3008
3353
|
conversationId,
|
|
3009
3354
|
groupHistoryKey,
|
|
3010
3355
|
agentId: route.agentId,
|
|
@@ -3041,18 +3386,21 @@ function createWebOnMessageHandler(params) {
|
|
|
3041
3386
|
});
|
|
3042
3387
|
}
|
|
3043
3388
|
if (!gating.shouldProcess) return;
|
|
3044
|
-
}
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3389
|
+
}
|
|
3390
|
+
if (configuredRoute.bindingResolution) {
|
|
3391
|
+
const ensured = await ensureConfiguredBindingRouteReady({
|
|
3392
|
+
cfg,
|
|
3393
|
+
bindingResolution: configuredRoute.bindingResolution
|
|
3394
|
+
});
|
|
3395
|
+
if (!ensured.ok) {
|
|
3396
|
+
params.replyLogger.warn(`whatsapp: configured ACP binding unavailable for conversation ${configuredRoute.bindingResolution.record.conversation.conversationId}: ${ensured.error}`);
|
|
3397
|
+
await clearPreDispatchReaction();
|
|
3398
|
+
return;
|
|
3052
3399
|
}
|
|
3053
3400
|
}
|
|
3401
|
+
recordAcceptedConfiguredGroupRoute?.();
|
|
3054
3402
|
await runAudioPreflightOnce();
|
|
3055
|
-
if (await maybeBroadcastMessage({
|
|
3403
|
+
if (!configuredRoute.bindingResolution && await maybeBroadcastMessage({
|
|
3056
3404
|
cfg,
|
|
3057
3405
|
msg,
|
|
3058
3406
|
peerId,
|
|
@@ -3237,10 +3585,11 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3237
3585
|
})
|
|
3238
3586
|
});
|
|
3239
3587
|
const shouldDebounce = (msg) => {
|
|
3240
|
-
|
|
3241
|
-
if (
|
|
3242
|
-
if (
|
|
3243
|
-
|
|
3588
|
+
const normalized = normalizeWebInboundMessage(msg);
|
|
3589
|
+
if (normalized.payload.media?.path || normalized.payload.media?.type) return false;
|
|
3590
|
+
if (normalized.payload.location) return false;
|
|
3591
|
+
if (normalized.quote?.id || normalized.quote?.body) return false;
|
|
3592
|
+
return !isControlCommandMessage(normalized.payload.body, cfg);
|
|
3244
3593
|
};
|
|
3245
3594
|
let connection;
|
|
3246
3595
|
try {
|
|
@@ -3280,10 +3629,11 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3280
3629
|
disconnectRetryAbortSignal: controller.getDisconnectRetryAbortSignal(),
|
|
3281
3630
|
groupMetadataCache,
|
|
3282
3631
|
onMessage: async (msg) => {
|
|
3632
|
+
const normalized = normalizeWebInboundMessage(msg);
|
|
3283
3633
|
const inboundAt = Date.now();
|
|
3284
3634
|
controller.noteInbound(inboundAt);
|
|
3285
3635
|
statusController.noteInbound(inboundAt);
|
|
3286
|
-
await onMessage(
|
|
3636
|
+
await onMessage(normalized);
|
|
3287
3637
|
},
|
|
3288
3638
|
sock
|
|
3289
3639
|
});
|