@openclaw/whatsapp 2026.7.2-beta.3 → 2026.7.2-beta.4
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-tjy_em01.js → access-control-CRz_v6bR.js} +4 -5
- package/dist/{accounts-ejK8sXPU.js → accounts-CxPuEFi-.js} +1 -1
- package/dist/{action-runtime-p0V390gA.js → action-runtime-CHU7xb6o.js} +2 -2
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{active-listener-BbdlXooT.js → active-listener-BEjWsCNM.js} +1 -1
- package/dist/api.js +12 -15
- package/dist/{approval-handler.runtime-BO1oJ-b8.js → approval-handler.runtime-C4ddB7Kc.js} +4 -4
- package/dist/{approval-reactions-CrZFAyf-.js → approval-reactions-P2HXjmln.js} +3 -3
- package/dist/{auth-store-BQi9pZqQ.js → auth-store-DirYMTbo.js} +4 -3
- package/dist/call-tool-api.js +4 -4
- package/dist/{channel-B2I4Opzb.js → channel-B9xjrOGG.js} +28 -19
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-CPRQE-s3.js → channel-react-action-CBW-PA8q.js} +10 -13
- package/dist/{channel.runtime-CjkhQzk8.js → channel.runtime-DdKuhlNu.js} +5 -5
- package/dist/{channel.setup-BMWE9LmN.js → channel.setup-DXUCPHel.js} +3 -6
- package/dist/{config-schema-BZ8h1hWA.js → config-schema-C6IeKIC0.js} +6 -0
- package/dist/{connection-controller-HGaffeFb.js → connection-controller-BVRExqrB.js} +8 -10
- package/dist/{connection-controller-runtime-context-9mEeAvu1.js → connection-controller-runtime-context-DG0tuYuw.js} +3 -3
- package/dist/contract-api.js +1 -1
- package/dist/{directory-config-BZ775eGX.js → directory-config-BTbJkV1W.js} +5 -5
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-CwzVXKoE.js +10 -0
- package/dist/doctor-contract-api.js +35 -79
- package/dist/{group-session-key-Dh8WZun_.js → group-session-key-DJSdYfnb.js} +9 -4
- package/dist/{identity-D7L8LCuH.js → identity-BM4_wZeM.js} +2 -2
- package/dist/light-runtime-api.js +2 -2
- package/dist/{login-ifOXCBjo.js → login-BKUm7KSk.js} +6 -7
- package/dist/{login-qr-DUHzVH_Y.js → login-qr-DagJvMbg.js} +7 -8
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-_jqDKBXj.js → monitor-CBVNJ2lb.js} +206 -232
- package/dist/{question-reactions-C0qJ6wGA.js → question-reactions-CaOrSYzU.js} +1 -1
- package/dist/runtime-BLlToOi6.js +21 -0
- package/dist/runtime-api.js +10 -10
- package/dist/runtime-setter-api.js +1 -1
- package/dist/{send-SB-4JrVZ.js → send-DhJVN30g.js} +38 -84
- package/dist/{send-api-BG0MgoFI.js → send-api-CpHwbor_.js} +39 -33
- package/dist/{setup-finalize-Cc-4iWGj.js → setup-finalize-9XzKdFq6.js} +3 -3
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DhnXEZir.js → setup-surface-Kv3mPki2.js} +3 -3
- package/dist/{setup-core-BbIgEl2M.js → shared-CuqHFnKd.js} +78 -56
- package/dist/{socket-close-jNGyZY4T.js → socket-close-BoSHhQNJ.js} +5 -6
- package/dist/{targets-runtime-Bsh0HR9y.js → targets-runtime-CKFrhoX4.js} +142 -29
- package/dist/text-runtime-CU_IlbK5.js +4 -0
- package/node_modules/@protobufjs/utf8/CHANGELOG.md +8 -0
- package/node_modules/@protobufjs/utf8/index.js +29 -18
- package/node_modules/@protobufjs/utf8/package.json +2 -2
- package/node_modules/@protobufjs/utf8/tests/index.js +5 -0
- package/node_modules/@thi.ng/bitstream/package.json +4 -4
- package/node_modules/@thi.ng/errors/package.json +4 -4
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +16 -6
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/audio-type/package.json +3 -2
- package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/browser/index.js +11 -4
- package/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/browser/index.min.js +1 -1
- package/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +3 -3
- package/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.js +11 -4
- package/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.min.js +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.min.js.map +3 -3
- package/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.js +11 -4
- package/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.min.js +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +3 -3
- package/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.js +11 -4
- package/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.min.js +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.min.js.map +3 -3
- package/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/index.js +11 -4
- package/node_modules/lru-cache/dist/esm/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/index.min.js +1 -1
- package/node_modules/lru-cache/dist/esm/index.min.js.map +3 -3
- package/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.js +11 -4
- package/node_modules/lru-cache/dist/esm/node/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.min.js +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.min.js.map +3 -3
- package/node_modules/lru-cache/package.json +1 -1
- package/node_modules/music-metadata/lib/common/Util.d.ts +1 -1
- package/node_modules/music-metadata/lib/common/Util.js +7 -1
- package/node_modules/music-metadata/lib/id3v2/FrameHeader.js +23 -3
- package/node_modules/music-metadata/lib/id3v2/FrameParser.js +2 -2
- package/node_modules/music-metadata/lib/id3v2/ID3v2Token.js +1 -1
- package/node_modules/music-metadata/lib/mp4/AtomToken.js +38 -13
- package/node_modules/music-metadata/lib/mpeg/MpegParser.js +1 -1
- package/node_modules/music-metadata/package.json +6 -6
- package/node_modules/p-queue/dist/index.js +17 -6
- package/node_modules/p-queue/package.json +1 -1
- package/node_modules/protobufjs/dist/light/protobuf.js +145 -188
- package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
- package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
- package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
- package/node_modules/protobufjs/dist/minimal/protobuf.js +33 -76
- package/node_modules/protobufjs/dist/minimal/protobuf.js.map +1 -1
- package/node_modules/protobufjs/dist/minimal/protobuf.min.js +3 -3
- package/node_modules/protobufjs/dist/minimal/protobuf.min.js.map +1 -1
- package/node_modules/protobufjs/dist/protobuf.js +168 -208
- package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
- package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
- package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
- package/node_modules/protobufjs/index.d.ts +0 -8
- package/node_modules/protobufjs/package.json +2 -3
- package/node_modules/protobufjs/src/parse.js +3 -0
- package/node_modules/protobufjs/src/util/minimal.js +0 -3
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/npm-shrinkwrap.json +41 -45
- package/openclaw.plugin.json +139 -179
- package/package.json +21 -11
- package/dist/doctor-By3SB4lm.js +0 -48
- package/dist/runtime-BfAdAEYT.js +0 -8
- package/dist/text-runtime-BTGkMN0o.js +0 -4
- package/node_modules/@protobufjs/inquire/CHANGELOG.md +0 -8
- package/node_modules/@protobufjs/inquire/LICENSE +0 -26
- package/node_modules/@protobufjs/inquire/README.md +0 -13
- package/node_modules/@protobufjs/inquire/index.d.ts +0 -10
- package/node_modules/@protobufjs/inquire/index.js +0 -38
- package/node_modules/@protobufjs/inquire/package.json +0 -21
- package/node_modules/@protobufjs/inquire/tests/data/array.js +0 -1
- package/node_modules/@protobufjs/inquire/tests/data/emptyArray.js +0 -1
- package/node_modules/@protobufjs/inquire/tests/data/emptyObject.js +0 -1
- package/node_modules/@protobufjs/inquire/tests/data/object.js +0 -1
- package/node_modules/@protobufjs/inquire/tests/index.js +0 -20
|
@@ -1,42 +1,40 @@
|
|
|
1
|
-
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-
|
|
2
|
-
import { a as normalizeWhatsAppOutboundPayload, c as prepareWhatsAppOutboundMedia, r as sendReactionWhatsApp, s as normalizeWhatsAppPayloadTextPreservingIndentation, u as resolveWhatsAppReactionLevel } from "./send-
|
|
3
|
-
import {
|
|
4
|
-
import { r as getWhatsAppConnectionController } from "./connection-controller-runtime-context-
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import { a as cacheInboundMessageMeta, i as buildQuotedMessageOptions, n as resolveWhatsAppGroupSessionRoute, o as lookupInboundMessageMeta, r as resolveWhatsAppLegacyGroupSessionKey } from "./group-session-key-
|
|
8
|
-
import { 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-
|
|
1
|
+
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-CxPuEFi-.js";
|
|
2
|
+
import { a as normalizeWhatsAppOutboundPayload, c as prepareWhatsAppOutboundMedia, r as sendReactionWhatsApp, s as normalizeWhatsAppPayloadTextPreservingIndentation, u as resolveWhatsAppReactionLevel } from "./send-DhJVN30g.js";
|
|
3
|
+
import { i as getWhatsAppRuntime } from "./runtime-BLlToOi6.js";
|
|
4
|
+
import { r as getWhatsAppConnectionController } from "./connection-controller-runtime-context-DG0tuYuw.js";
|
|
5
|
+
import { a as markdownToWhatsAppChunks, c as toWhatsappJid, l as toWhatsappJidWithLid, n as isSelfChatMode, o as resolveEquivalentWhatsAppDirectChatJids, r as jidToE164, s as resolveJidToE164 } from "./targets-runtime-CKFrhoX4.js";
|
|
6
|
+
import { t as normalizeE164 } from "./text-runtime-CU_IlbK5.js";
|
|
7
|
+
import { a as cacheInboundMessageMeta, i as buildQuotedMessageOptions, n as resolveWhatsAppGroupSessionRoute, o as lookupInboundMessageMeta, r as resolveWhatsAppLegacyGroupSessionKey } from "./group-session-key-DJSdYfnb.js";
|
|
8
|
+
import { g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-DirYMTbo.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-BM4_wZeM.js";
|
|
10
10
|
import { n as resolveWhatsAppGroupsConfigPath } from "./group-config-path-BGyzT9Lg.js";
|
|
11
|
-
import { a as waitForWaConnection, c as isWhatsAppSocketOperationTimeoutError, d as withWhatsAppSocketOperationTimeout, l as resolveWhatsAppSocketOperationTimeoutMs, r as createWaSocket, s as createWhatsAppSocketOperationTimeoutAdapter, u as resolveWhatsAppSocketTiming } from "./socket-close-
|
|
11
|
+
import { a as waitForWaConnection, c as isWhatsAppSocketOperationTimeoutError, d as withWhatsAppSocketOperationTimeout, l as resolveWhatsAppSocketOperationTimeoutMs, r as createWaSocket, s as createWhatsAppSocketOperationTimeoutAdapter, u as resolveWhatsAppSocketTiming } from "./socket-close-BoSHhQNJ.js";
|
|
12
12
|
import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
|
|
13
13
|
import { t as BufferJSON } from "./session.runtime-Nsqaehbd.js";
|
|
14
|
-
import { c as requireWhatsAppInboundAdmission, i as resolveWhatsAppInboundPolicy, l as resolveWhatsAppGroupConversationId, o as buildDeprecatedFlatWhatsAppInboundAdmission, r as resolveWhatsAppCommandAuthorized, s as requireAdmittedWhatsAppInboundMessage, t as checkInboundAccessControl } from "./access-control-
|
|
15
|
-
import { _ as
|
|
16
|
-
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-
|
|
17
|
-
import { n as maybeResolveWhatsAppApprovalReaction } from "./approval-reactions-
|
|
18
|
-
import { t as maybeResolveWhatsAppQuestionReaction } from "./question-reactions-
|
|
14
|
+
import { c as requireWhatsAppInboundAdmission, i as resolveWhatsAppInboundPolicy, l as resolveWhatsAppGroupConversationId, o as buildDeprecatedFlatWhatsAppInboundAdmission, r as resolveWhatsAppCommandAuthorized, s as requireAdmittedWhatsAppInboundMessage, t as checkInboundAccessControl } from "./access-control-CRz_v6bR.js";
|
|
15
|
+
import { _ as extractMediaKind, a as mayContainWhatsAppOutboundMention, b as hasInboundUserContent, c as DisconnectReason, d as normalizeMessageContent, f as describeReplyContext, g as extractLocationData, h as extractExternalAdReplyContext, i as addWhatsAppOutboundMentionsToContent, l as downloadMediaMessage, m as extractContextInfo, n as listWhatsAppSendResultMessageIds, o as resolveWhatsAppOutboundMentions, p as extractContactContext, r as normalizeWhatsAppSendResult, s as addWhatsAppImagePreviewFields, t as createWebSendApi, u as isJidGroup, v as extractMentionedJids, x as resolveInboundMediaMimetype, y as extractText } from "./send-api-CpHwbor_.js";
|
|
16
|
+
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-BVRExqrB.js";
|
|
17
|
+
import { n as maybeResolveWhatsAppApprovalReaction } from "./approval-reactions-P2HXjmln.js";
|
|
18
|
+
import { t as maybeResolveWhatsAppQuestionReaction } from "./question-reactions-CaOrSYzU.js";
|
|
19
19
|
import { resolveAccountEntry } from "openclaw/plugin-sdk/account-core";
|
|
20
20
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
21
21
|
import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
|
|
22
|
-
import {
|
|
22
|
+
import { createAckReactionHandle, createStatusReactionController, logAckFailure, removeAckReactionHandleAfterReply, shouldAckReactionForWhatsApp } from "openclaw/plugin-sdk/channel-feedback";
|
|
23
23
|
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
24
24
|
import { getChildLogger } from "openclaw/plugin-sdk/logging-core";
|
|
25
25
|
import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
26
26
|
import { createSubsystemLogger, defaultRuntime, formatDurationPrecise, getChildLogger as getChildLogger$1, logVerbose, logVerbose as logVerbose$1, registerUnhandledRejectionHandler, shouldLogVerbose, shouldLogVerbose as shouldLogVerbose$1, warn } from "openclaw/plugin-sdk/runtime-env";
|
|
27
27
|
import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
|
|
28
|
-
import {
|
|
28
|
+
import { bindIngressLifecycleToReplyOptions, createChannelIngressMonitor, createChannelMessageReplyPipeline, createMessageReceiptFromOutboundResults, deliverInboundReplyWithMessageSendContext, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
29
29
|
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
|
|
30
30
|
import { isReasoningReplyPayload, resolveSendableOutboundReplyParts, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
|
|
31
31
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
32
|
-
import { LocalMediaAccessError, getDefaultLocalRoots, loadWebMedia as loadWebMedia$1, loadWebMediaRaw, optimizeImageToJpeg, optimizeImageToPng } from "openclaw/plugin-sdk/web-media";
|
|
33
32
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
34
|
-
import {
|
|
33
|
+
import { buildChannelInboundEventContext, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundEnvelope as formatInboundEnvelope$1, formatInboundMediaUnavailableText, formatLocationText, formatMediaPlaceholderText, hasVisibleInboundReplyDispatch, resolveInboundSessionEnvelopeContext, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFacts, toLocationContext } from "openclaw/plugin-sdk/channel-inbound";
|
|
35
34
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, DEFAULT_MAIN_KEY, buildAgentMainSessionKey, buildAgentSessionKey, buildGroupHistoryKey, deriveLastRoutePolicy, normalizeAccountId as normalizeAccountId$1, normalizeAgentId, resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
36
35
|
import { asDateTimestampMs, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
37
36
|
import { createHash } from "node:crypto";
|
|
38
37
|
import { getSessionEntry, patchSessionEntry, resolveStorePath, resolveStorePath as resolveStorePath$1, updateLastRoute } from "openclaw/plugin-sdk/session-store-runtime";
|
|
39
|
-
import { buildChannelInboundEventContext, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundEnvelope as formatInboundEnvelope$1, formatInboundMediaUnavailableText, formatLocationText, hasVisibleInboundReplyDispatch, resolveInboundSessionEnvelopeContext, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFacts, toLocationContext } from "openclaw/plugin-sdk/channel-inbound";
|
|
40
38
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
41
39
|
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
|
|
42
40
|
import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
@@ -57,6 +55,7 @@ import { hasControlCommand, isControlCommandMessage, shouldComputeCommandAuthori
|
|
|
57
55
|
import { createInternalHookEvent, deriveInboundMessageHookContext, fireAndForgetBoundedHook, toInternalMessageReceivedContext, toPluginMessageContext, toPluginMessageReceivedEvent, triggerInternalHook } from "openclaw/plugin-sdk/hook-runtime";
|
|
58
56
|
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
|
59
57
|
import { resolveBatchedReplyThreadingPolicy } from "openclaw/plugin-sdk/reply-reference";
|
|
58
|
+
import { LocalMediaAccessError, getDefaultLocalRoots, loadWebMedia, loadWebMediaRaw, optimizeImageToJpeg, optimizeImageToPng } from "openclaw/plugin-sdk/web-media";
|
|
60
59
|
import { createChannelApiRetryRunner } from "openclaw/plugin-sdk/retry-runtime";
|
|
61
60
|
//#region extensions/whatsapp/src/inbound/message-aliases.ts
|
|
62
61
|
function normalizeQuoteSender(sender) {
|
|
@@ -441,6 +440,8 @@ const WHATSAPP_DURABLE_INBOUND_PENDING_MAX_ENTRIES = 450;
|
|
|
441
440
|
const WHATSAPP_DURABLE_INBOUND_COMPLETED_MAX_ENTRIES = 5e3;
|
|
442
441
|
const WHATSAPP_DURABLE_INBOUND_PENDING_TTL_MS = 720 * 60 * 60 * 1e3;
|
|
443
442
|
const WHATSAPP_DURABLE_INBOUND_COMPLETED_TTL_MS = 10080 * 60 * 1e3;
|
|
443
|
+
const WHATSAPP_DURABLE_INBOUND_PRUNE_INTERVAL_MS = 3600 * 1e3;
|
|
444
|
+
const WHATSAPP_DURABLE_INBOUND_PAYLOAD_VERSION = 1;
|
|
444
445
|
function hashNamespacePart(value) {
|
|
445
446
|
return createHash("sha256").update(value).digest("hex").slice(0, 24);
|
|
446
447
|
}
|
|
@@ -470,14 +471,6 @@ function createWhatsAppDurableInboundQueue(accountId) {
|
|
|
470
471
|
async function enqueueWhatsAppDurableInbound(params) {
|
|
471
472
|
const facts = inspectWhatsAppIngressMessage(params.message);
|
|
472
473
|
const receivedAt = params.receivedAt ?? Date.now();
|
|
473
|
-
await params.queue.prune({
|
|
474
|
-
pendingTtlMs: WHATSAPP_DURABLE_INBOUND_PENDING_TTL_MS,
|
|
475
|
-
completedTtlMs: WHATSAPP_DURABLE_INBOUND_COMPLETED_TTL_MS,
|
|
476
|
-
failedTtlMs: WHATSAPP_DURABLE_INBOUND_PENDING_TTL_MS,
|
|
477
|
-
pendingMaxEntries: WHATSAPP_DURABLE_INBOUND_PENDING_MAX_ENTRIES,
|
|
478
|
-
completedMaxEntries: WHATSAPP_DURABLE_INBOUND_COMPLETED_MAX_ENTRIES,
|
|
479
|
-
failedMaxEntries: WHATSAPP_DURABLE_INBOUND_PENDING_MAX_ENTRIES
|
|
480
|
-
});
|
|
481
474
|
return await params.queue.enqueue(facts.eventId, {
|
|
482
475
|
message: serializeWhatsAppDurableInboundMessage(params.message),
|
|
483
476
|
upsertType: params.upsertType,
|
|
@@ -496,29 +489,52 @@ function resolveWhatsAppIngressNonRetryableFailure(error) {
|
|
|
496
489
|
message: error.message
|
|
497
490
|
} : null;
|
|
498
491
|
}
|
|
499
|
-
/**
|
|
500
|
-
function
|
|
501
|
-
return
|
|
492
|
+
/** Shared monitor with per-conversation lanes and completion at reply-lane adoption. */
|
|
493
|
+
function createWhatsAppIngressMonitor(params) {
|
|
494
|
+
return createChannelIngressMonitor({
|
|
502
495
|
queue: params.queue,
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
496
|
+
inspect: (message) => inspectWhatsAppIngressMessage(message),
|
|
497
|
+
payload: {
|
|
498
|
+
version: WHATSAPP_DURABLE_INBOUND_PAYLOAD_VERSION,
|
|
499
|
+
serialize: (message, { receivedAt }) => ({
|
|
500
|
+
message: serializeWhatsAppDurableInboundMessage(message),
|
|
501
|
+
receivedAt
|
|
502
|
+
}),
|
|
503
|
+
deserialize: (payload) => deserializeWhatsAppDurableInboundMessage(payload.message),
|
|
504
|
+
encode: ({ body }) => body,
|
|
505
|
+
decode: (payload) => ({
|
|
506
|
+
version: WHATSAPP_DURABLE_INBOUND_PAYLOAD_VERSION,
|
|
507
|
+
body: payload
|
|
508
|
+
}),
|
|
509
|
+
createClaimError: (kind) => new WhatsAppIngressPermanentError(kind === "invalid-version" ? "invalid-payload" : "event-id-mismatch", kind === "invalid-version" ? "WhatsApp ingress row has an invalid payload version" : "WhatsApp ingress row identity does not match its transport message key")
|
|
506
510
|
},
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
511
|
+
deliver: (message, lifecycle, claim) => params.dispatch(message, claim.payload, lifecycle),
|
|
512
|
+
pollIntervalMs: params.pollIntervalMs,
|
|
513
|
+
retention: {
|
|
514
|
+
pruneIntervalMs: WHATSAPP_DURABLE_INBOUND_PRUNE_INTERVAL_MS,
|
|
515
|
+
pendingTtlMs: WHATSAPP_DURABLE_INBOUND_PENDING_TTL_MS,
|
|
516
|
+
pendingMaxEntries: WHATSAPP_DURABLE_INBOUND_PENDING_MAX_ENTRIES,
|
|
517
|
+
completedTtlMs: WHATSAPP_DURABLE_INBOUND_COMPLETED_TTL_MS,
|
|
518
|
+
completedMaxEntries: WHATSAPP_DURABLE_INBOUND_COMPLETED_MAX_ENTRIES,
|
|
519
|
+
failedTtlMs: WHATSAPP_DURABLE_INBOUND_PENDING_TTL_MS,
|
|
520
|
+
failedMaxEntries: WHATSAPP_DURABLE_INBOUND_PENDING_MAX_ENTRIES
|
|
521
|
+
},
|
|
522
|
+
drain: {
|
|
523
|
+
resolveNonRetryableFailure: resolveWhatsAppIngressNonRetryableFailure,
|
|
524
|
+
deriveLaneKey: (record) => {
|
|
525
|
+
try {
|
|
526
|
+
return inspectWhatsAppIngressMessage(deserializeWhatsAppDurableInboundMessage(record.payload.message)).laneKey;
|
|
527
|
+
} catch {
|
|
528
|
+
return record.id;
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
...params.onLog ? { onLog: params.onLog } : {}
|
|
514
532
|
},
|
|
515
|
-
...params.onLog ? { onLog: params.onLog } : {},
|
|
516
533
|
...params.abortSignal ? { abortSignal: params.abortSignal } : {},
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
534
|
+
admissionMode: "while-running",
|
|
535
|
+
createStoppedError: () => /* @__PURE__ */ new Error("WhatsApp ingress monitor is stopped."),
|
|
536
|
+
...params.onError ? { onError: params.onError } : {},
|
|
537
|
+
...params.onActivityChange ? { onActivityChange: params.onActivityChange } : {}
|
|
522
538
|
});
|
|
523
539
|
}
|
|
524
540
|
//#endregion
|
|
@@ -738,6 +754,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
738
754
|
const pendingDebounceKeys = /* @__PURE__ */ new Set();
|
|
739
755
|
const activeInboundFlushes = /* @__PURE__ */ new Set();
|
|
740
756
|
const pendingMessageHandlers = /* @__PURE__ */ new Set();
|
|
757
|
+
let durableIngressActive = false;
|
|
741
758
|
const debounceWorkWaiters = /* @__PURE__ */ new Set();
|
|
742
759
|
const notifyDebounceWork = () => {
|
|
743
760
|
if (debounceWorkWaiters.size === 0) return;
|
|
@@ -759,7 +776,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
759
776
|
};
|
|
760
777
|
let nextReceiveOrder = 0;
|
|
761
778
|
const publishPendingWorkState = (at = Date.now()) => {
|
|
762
|
-
options.onPendingWorkChanged?.(pendingMessageHandlers.size + pendingDebounceKeys.size + activeInboundFlushes.size, at);
|
|
779
|
+
options.onPendingWorkChanged?.(pendingMessageHandlers.size + pendingDebounceKeys.size + activeInboundFlushes.size + (durableIngressActive ? 1 : 0), at);
|
|
763
780
|
};
|
|
764
781
|
const buildInboundDebounceKey = (msg) => {
|
|
765
782
|
const admission = requireWhatsAppInboundAdmission(msg);
|
|
@@ -1192,17 +1209,19 @@ async function attachWebInboxToSocket(options) {
|
|
|
1192
1209
|
const locationText = location ? formatLocationText(location) : void 0;
|
|
1193
1210
|
const contactContext = extractContactContext(msg.message ?? void 0);
|
|
1194
1211
|
const externalAdReplyContext = extractExternalAdReplyContext(msg.message ?? void 0);
|
|
1195
|
-
|
|
1212
|
+
let mediaKind = extractMediaKind(msg.message ?? void 0);
|
|
1196
1213
|
let body = extractText(msg.message ?? void 0);
|
|
1197
1214
|
if (locationText) body = [body, locationText].filter(Boolean).join("\n").trim();
|
|
1198
|
-
if (!body)
|
|
1199
|
-
|
|
1200
|
-
if (!body) return null;
|
|
1201
|
-
}
|
|
1215
|
+
if (!body && !mediaKind) return null;
|
|
1216
|
+
body = body ?? "";
|
|
1202
1217
|
const commandBody = body;
|
|
1203
1218
|
const replyContext = describeReplyContext(msg.message);
|
|
1204
1219
|
let mediaPath;
|
|
1205
|
-
let mediaType;
|
|
1220
|
+
let mediaType = mediaKind ? resolveInboundMediaMimetype(msg.message) : void 0;
|
|
1221
|
+
const nativeMedia = mediaKind ? {
|
|
1222
|
+
contentType: mediaType,
|
|
1223
|
+
kind: mediaKind
|
|
1224
|
+
} : void 0;
|
|
1206
1225
|
let mediaFileName;
|
|
1207
1226
|
const maxBytes = (typeof options.mediaMaxMb === "number" && options.mediaMaxMb > 0 ? options.mediaMaxMb : 50) * 1024 * 1024;
|
|
1208
1227
|
const saveInboundMedia = async (inboundMedia) => {
|
|
@@ -1217,12 +1236,13 @@ async function attachWebInboxToSocket(options) {
|
|
|
1217
1236
|
logWhatsAppVerbose(options.verbose, `Inbound media download failed: ${String(err)}`);
|
|
1218
1237
|
body = formatInboundMediaUnavailableText({
|
|
1219
1238
|
body,
|
|
1220
|
-
mediaPlaceholder,
|
|
1221
1239
|
notice: "[whatsapp attachment unavailable]"
|
|
1222
1240
|
});
|
|
1223
1241
|
}
|
|
1224
|
-
if (!mediaPath && replyContext) try {
|
|
1242
|
+
if (!mediaPath && !mediaKind && replyContext?.media) try {
|
|
1225
1243
|
await saveInboundMedia(await downloadQuotedInboundMedia(msg, sock, maxBytes));
|
|
1244
|
+
mediaKind = replyContext.media.kind ?? void 0;
|
|
1245
|
+
mediaType = mediaType ?? replyContext.media.contentType ?? void 0;
|
|
1226
1246
|
} catch (err) {
|
|
1227
1247
|
logWhatsAppVerbose(options.verbose, `Quoted media download failed: ${String(err)}`);
|
|
1228
1248
|
body = formatInboundMediaUnavailableText({
|
|
@@ -1239,7 +1259,9 @@ async function attachWebInboxToSocket(options) {
|
|
|
1239
1259
|
replyContext,
|
|
1240
1260
|
mediaPath,
|
|
1241
1261
|
mediaType,
|
|
1242
|
-
mediaFileName
|
|
1262
|
+
mediaFileName,
|
|
1263
|
+
mediaKind,
|
|
1264
|
+
nativeMedia
|
|
1243
1265
|
};
|
|
1244
1266
|
};
|
|
1245
1267
|
const enqueueInboundMessage = async (msg, inbound, enriched, durable) => {
|
|
@@ -1274,10 +1296,11 @@ async function attachWebInboxToSocket(options) {
|
|
|
1274
1296
|
mediaFileName: enriched.mediaFileName,
|
|
1275
1297
|
timestamp
|
|
1276
1298
|
}, "inbound message");
|
|
1277
|
-
const media = enriched.mediaPath || enriched.mediaType || enriched.mediaFileName ? {
|
|
1299
|
+
const media = enriched.mediaPath || enriched.mediaType || enriched.mediaFileName || enriched.mediaKind ? {
|
|
1278
1300
|
path: enriched.mediaPath,
|
|
1279
1301
|
type: enriched.mediaType,
|
|
1280
|
-
fileName: enriched.mediaFileName
|
|
1302
|
+
fileName: enriched.mediaFileName,
|
|
1303
|
+
kind: enriched.mediaKind
|
|
1281
1304
|
} : void 0;
|
|
1282
1305
|
const groupMentions = mentionedJids ? { jids: mentionedJids } : void 0;
|
|
1283
1306
|
const group = inbound.group && (inbound.groupSubject || inbound.groupParticipants?.length || groupMentions) ? {
|
|
@@ -1285,17 +1308,26 @@ async function attachWebInboxToSocket(options) {
|
|
|
1285
1308
|
participants: inbound.groupParticipants,
|
|
1286
1309
|
mentions: groupMentions
|
|
1287
1310
|
} : void 0;
|
|
1288
|
-
const untrustedStructuredContext = [
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1311
|
+
const untrustedStructuredContext = [
|
|
1312
|
+
...enriched.nativeMedia ? [{
|
|
1313
|
+
label: "WhatsApp media",
|
|
1314
|
+
source: "whatsapp",
|
|
1315
|
+
type: "media",
|
|
1316
|
+
payload: enriched.nativeMedia
|
|
1317
|
+
}] : [],
|
|
1318
|
+
...enriched.contactContext ? [{
|
|
1319
|
+
label: "WhatsApp contact",
|
|
1320
|
+
source: "whatsapp",
|
|
1321
|
+
type: enriched.contactContext.kind,
|
|
1322
|
+
payload: enriched.contactContext
|
|
1323
|
+
}] : [],
|
|
1324
|
+
...enriched.externalAdReplyContext ? [{
|
|
1325
|
+
label: "WhatsApp external ad reply",
|
|
1326
|
+
source: "whatsapp",
|
|
1327
|
+
type: "external_ad_reply",
|
|
1328
|
+
payload: enriched.externalAdReplyContext
|
|
1329
|
+
}] : []
|
|
1330
|
+
];
|
|
1299
1331
|
const inboundMessage = withDeprecatedWebInboundMessageFlatAliases({
|
|
1300
1332
|
admission: inbound.access.admission,
|
|
1301
1333
|
event: {
|
|
@@ -1334,6 +1366,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1334
1366
|
context: enriched.replyContext,
|
|
1335
1367
|
id: enriched.replyContext.id,
|
|
1336
1368
|
body: enriched.replyContext.body,
|
|
1369
|
+
media: enriched.replyContext.media,
|
|
1337
1370
|
sender: {
|
|
1338
1371
|
displayName: enriched.replyContext.sender?.label ?? void 0,
|
|
1339
1372
|
jid: enriched.replyContext.sender?.jid ?? void 0,
|
|
@@ -1360,12 +1393,13 @@ async function attachWebInboxToSocket(options) {
|
|
|
1360
1393
|
participant: inboundMessage.platform.senderJid,
|
|
1361
1394
|
participantE164: admission.conversation.kind === "direct" ? inboundMessage.platform.senderE164 : void 0,
|
|
1362
1395
|
body: inboundMessage.payload.body,
|
|
1396
|
+
media: enriched.nativeMedia,
|
|
1363
1397
|
fromMe: inboundMessage.platform.fromMe
|
|
1364
1398
|
});
|
|
1365
1399
|
}
|
|
1366
1400
|
await debouncer.enqueue(inboundMessage);
|
|
1367
1401
|
};
|
|
1368
|
-
const
|
|
1402
|
+
const processDurableInboundMessage = async (msg, context) => {
|
|
1369
1403
|
rememberBaileysMessage(msg.key?.remoteJid, msg.key?.id, msg.message);
|
|
1370
1404
|
if (context.skipRecentOutboundEcho === true) return "completed";
|
|
1371
1405
|
const preparation = context.eventId ? preparedInboundByDurableId.get(context.eventId) : void 0;
|
|
@@ -1401,81 +1435,28 @@ async function attachWebInboxToSocket(options) {
|
|
|
1401
1435
|
});
|
|
1402
1436
|
return "deferred";
|
|
1403
1437
|
};
|
|
1404
|
-
|
|
1405
|
-
let durableDrainRequested = false;
|
|
1406
|
-
let durableDrainClosed = false;
|
|
1407
|
-
const requestDurableInboundDrain = () => {
|
|
1408
|
-
if (durableDrainClosed) return Promise.resolve();
|
|
1409
|
-
durableDrainRequested = true;
|
|
1410
|
-
if (!durableDrainPass) {
|
|
1411
|
-
let passFailed = false;
|
|
1412
|
-
const task = (async () => {
|
|
1413
|
-
await durableInboundDrain.recoverStaleClaims();
|
|
1414
|
-
while (durableDrainRequested) {
|
|
1415
|
-
durableDrainRequested = false;
|
|
1416
|
-
if ((await durableInboundDrain.drainOnce()).started > 0) {
|
|
1417
|
-
await durableInboundDrain.waitForIdle();
|
|
1418
|
-
durableDrainRequested = true;
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
})().catch((error) => {
|
|
1422
|
-
passFailed = true;
|
|
1423
|
-
throw error;
|
|
1424
|
-
});
|
|
1425
|
-
durableDrainPass = task;
|
|
1426
|
-
pendingMessageHandlers.add(task);
|
|
1427
|
-
publishPendingWorkState();
|
|
1428
|
-
task.finally(() => {
|
|
1429
|
-
if (durableDrainPass === task) durableDrainPass = void 0;
|
|
1430
|
-
pendingMessageHandlers.delete(task);
|
|
1431
|
-
publishPendingWorkState();
|
|
1432
|
-
if (durableDrainRequested && !passFailed) requestDurableInboundDrain().catch((error) => {
|
|
1433
|
-
inboundLogger.error({ error: formatError(error) }, "whatsapp durable inbound drain failed");
|
|
1434
|
-
});
|
|
1435
|
-
}).catch(() => void 0);
|
|
1436
|
-
}
|
|
1437
|
-
return durableDrainPass;
|
|
1438
|
-
};
|
|
1439
|
-
const requestDrainAfterLaneSettlement = () => {
|
|
1440
|
-
requestDurableInboundDrain().catch((error) => {
|
|
1441
|
-
inboundLogger.error({ error: formatError(error) }, "whatsapp durable inbound drain failed");
|
|
1442
|
-
});
|
|
1443
|
-
};
|
|
1444
|
-
const continueDrainAfterLaneSettlement = (lifecycle) => ({
|
|
1445
|
-
abortSignal: lifecycle.abortSignal,
|
|
1446
|
-
onAdopted: async () => {
|
|
1447
|
-
await lifecycle.onAdopted();
|
|
1448
|
-
requestDrainAfterLaneSettlement();
|
|
1449
|
-
},
|
|
1450
|
-
onDeferred: lifecycle.onDeferred,
|
|
1451
|
-
onAdoptionFinalizing: lifecycle.onAdoptionFinalizing,
|
|
1452
|
-
onAbandoned: async () => {
|
|
1453
|
-
await lifecycle.onAbandoned();
|
|
1454
|
-
requestDrainAfterLaneSettlement();
|
|
1455
|
-
}
|
|
1456
|
-
});
|
|
1457
|
-
const durableInboundDrain = createWhatsAppIngressDrain({
|
|
1438
|
+
const durableInboundMonitor = createWhatsAppIngressMonitor({
|
|
1458
1439
|
queue: durableInboundQueue,
|
|
1459
1440
|
dispatch: async (msg, payload, lifecycle) => {
|
|
1460
1441
|
const remoteJid = msg.key?.remoteJid;
|
|
1461
1442
|
const id = msg.key?.id;
|
|
1462
|
-
return { kind: await
|
|
1443
|
+
return { kind: await processDurableInboundMessage(msg, {
|
|
1463
1444
|
...payload,
|
|
1464
1445
|
...remoteJid && id ? { eventId: createWhatsAppDurableInboundMessageId({
|
|
1465
1446
|
remoteJid,
|
|
1466
1447
|
id
|
|
1467
1448
|
}) } : {},
|
|
1468
|
-
lifecycle
|
|
1449
|
+
lifecycle
|
|
1469
1450
|
}) };
|
|
1470
1451
|
},
|
|
1471
|
-
|
|
1452
|
+
pollIntervalMs: WHATSAPP_INGRESS_DRAIN_INTERVAL_MS,
|
|
1453
|
+
onLog: (message) => inboundLogger.warn({ message }, "whatsapp ingress drain"),
|
|
1454
|
+
onError: (error) => inboundLogger.error({ error: formatError(error) }, "whatsapp durable inbound drain failed"),
|
|
1455
|
+
onActivityChange: (active) => {
|
|
1456
|
+
durableIngressActive = active;
|
|
1457
|
+
publishPendingWorkState();
|
|
1458
|
+
}
|
|
1472
1459
|
});
|
|
1473
|
-
const durableDrainTimer = setInterval(() => {
|
|
1474
|
-
requestDurableInboundDrain().catch((error) => {
|
|
1475
|
-
inboundLogger.error({ error: formatError(error) }, "whatsapp durable inbound drain failed");
|
|
1476
|
-
});
|
|
1477
|
-
}, WHATSAPP_INGRESS_DRAIN_INTERVAL_MS);
|
|
1478
|
-
durableDrainTimer.unref?.();
|
|
1479
1460
|
const handleMessagesUpsert = async (upsert) => {
|
|
1480
1461
|
if (upsert.type !== "notify" && upsert.type !== "append") return;
|
|
1481
1462
|
for (const msg of upsert.messages ?? []) {
|
|
@@ -1559,9 +1540,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1559
1540
|
throw error;
|
|
1560
1541
|
}
|
|
1561
1542
|
else finishPreparation(void 0);
|
|
1562
|
-
|
|
1563
|
-
inboundLogger.error({ error: formatError(error) }, "whatsapp durable inbound drain failed");
|
|
1564
|
-
});
|
|
1543
|
+
durableInboundMonitor.requestDrain();
|
|
1565
1544
|
}
|
|
1566
1545
|
}
|
|
1567
1546
|
};
|
|
@@ -1588,7 +1567,6 @@ async function attachWebInboxToSocket(options) {
|
|
|
1588
1567
|
};
|
|
1589
1568
|
const drainInboundBeforeSocketClose = async () => {
|
|
1590
1569
|
groupMetadataCacheClosed = true;
|
|
1591
|
-
clearInterval(durableDrainTimer);
|
|
1592
1570
|
for (;;) {
|
|
1593
1571
|
await drainDebouncedInboundMessages();
|
|
1594
1572
|
if (pendingMessageHandlers.size === 0) break;
|
|
@@ -1597,12 +1575,12 @@ async function attachWebInboxToSocket(options) {
|
|
|
1597
1575
|
if (pendingMessageHandlers.size === 0 && pendingDebounceKeys.size === 0 && activeInboundFlushes.size === 0) break;
|
|
1598
1576
|
}
|
|
1599
1577
|
await drainDebouncedInboundMessages();
|
|
1600
|
-
|
|
1601
|
-
await
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
durableInboundDrain.dispose();
|
|
1578
|
+
for (;;) {
|
|
1579
|
+
await durableInboundMonitor.waitForIdle();
|
|
1580
|
+
if (pendingDebounceKeys.size === 0 && activeInboundFlushes.size === 0) break;
|
|
1581
|
+
await drainDebouncedInboundMessages();
|
|
1605
1582
|
}
|
|
1583
|
+
await durableInboundMonitor.stop();
|
|
1606
1584
|
};
|
|
1607
1585
|
const drainInboundBeforeSocketCloseWithTimeout = async () => {
|
|
1608
1586
|
let timeout = null;
|
|
@@ -1615,8 +1593,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1615
1593
|
})]);
|
|
1616
1594
|
} finally {
|
|
1617
1595
|
if (timeout) clearTimeout(timeout);
|
|
1618
|
-
|
|
1619
|
-
durableInboundDrain.dispose();
|
|
1596
|
+
durableInboundMonitor.stop();
|
|
1620
1597
|
}
|
|
1621
1598
|
};
|
|
1622
1599
|
const handleConnectionUpdate = (update) => {
|
|
@@ -1675,10 +1652,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1675
1652
|
const detachGroupParticipantsUpdate = attachSockListener("group-participants.update", ((update) => {
|
|
1676
1653
|
forgetFullGroupMetadata(update.id);
|
|
1677
1654
|
}));
|
|
1678
|
-
|
|
1679
|
-
inboundLogger.error({ error: String(err) }, "failed replaying durable WhatsApp inbound");
|
|
1680
|
-
inboundConsoleLog.error(`Failed replaying durable WhatsApp inbound: ${String(err)}`);
|
|
1681
|
-
});
|
|
1655
|
+
durableInboundMonitor.start();
|
|
1682
1656
|
(async () => {
|
|
1683
1657
|
try {
|
|
1684
1658
|
const groups = await sock.groupFetchAllParticipating();
|
|
@@ -1736,7 +1710,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1736
1710
|
};
|
|
1737
1711
|
}
|
|
1738
1712
|
async function monitorWebInbox(options) {
|
|
1739
|
-
const socketTiming = options.socketTiming ?? resolveWhatsAppSocketTiming(
|
|
1713
|
+
const socketTiming = options.socketTiming ?? resolveWhatsAppSocketTiming();
|
|
1740
1714
|
const recentMessageKeys = options.recentMessageKeys ?? /* @__PURE__ */ new Map();
|
|
1741
1715
|
const baileysGroupMetaCache = options.baileysGroupMetaCache ?? /* @__PURE__ */ new Map();
|
|
1742
1716
|
const sock = await createWaSocket(false, options.verbose, {
|
|
@@ -1794,12 +1768,13 @@ function isBotMentionedFromTargets(msg, mentionCfg, targets) {
|
|
|
1794
1768
|
const isGroupConversation = requireWhatsAppInboundAdmission(msg).conversation.kind === "group";
|
|
1795
1769
|
const isSelfChat = explicitSelfChatOverride ? Boolean(mentionCfg.isSelfChat) : isSelfChatMode(targets.self.e164, mentionCfg.allowFrom) && !isGroupConversation;
|
|
1796
1770
|
const hasMentions = targets.normalizedMentions.length > 0;
|
|
1797
|
-
|
|
1771
|
+
const hasNativeMentionsOutsideSelfChat = hasMentions && !isSelfChat;
|
|
1772
|
+
if (hasNativeMentionsOutsideSelfChat) {
|
|
1798
1773
|
for (const mention of targets.normalizedMentions) if (identitiesOverlap(targets.self, mention)) return true;
|
|
1799
|
-
return false;
|
|
1800
1774
|
} else if (hasMentions && isSelfChat) {}
|
|
1801
1775
|
const bodyClean = clean(msg.payload.body);
|
|
1802
1776
|
if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean))) return true;
|
|
1777
|
+
if (hasNativeMentionsOutsideSelfChat) return false;
|
|
1803
1778
|
if (targets.self.e164) {
|
|
1804
1779
|
const selfDigits = targets.self.e164.replace(/\D/g, "");
|
|
1805
1780
|
if (selfDigits) {
|
|
@@ -1980,8 +1955,7 @@ function formatWhatsAppInboundListeningLog(account) {
|
|
|
1980
1955
|
const DEFAULT_WHATSAPP_ACK_REACTION = "👀";
|
|
1981
1956
|
function resolveWhatsAppAckEmoji(params) {
|
|
1982
1957
|
if (!params.ackConfig) return "";
|
|
1983
|
-
|
|
1984
|
-
return resolveAgentIdentityEmoji(params.cfg, params.agentId) ?? DEFAULT_WHATSAPP_ACK_REACTION;
|
|
1958
|
+
return (typeof params.ackConfig === "string" ? params.ackConfig : params.ackConfig.emoji)?.trim() || resolveAgentIdentityEmoji(params.cfg, params.agentId) || DEFAULT_WHATSAPP_ACK_REACTION;
|
|
1985
1959
|
}
|
|
1986
1960
|
function resolveAgentIdentityEmoji(cfg, agentId) {
|
|
1987
1961
|
return resolveAgentIdentity(cfg, agentId)?.emoji?.trim() || void 0;
|
|
@@ -2034,6 +2008,12 @@ async function resolveGroupActivationFor(params) {
|
|
|
2034
2008
|
return normalizeGroupActivation(activation) ?? defaultActivation;
|
|
2035
2009
|
}
|
|
2036
2010
|
//#endregion
|
|
2011
|
+
//#region extensions/whatsapp/src/auto-reply/monitor/reaction-participant.ts
|
|
2012
|
+
function resolveReactionParticipant(msg) {
|
|
2013
|
+
const sender = getSenderIdentity(msg);
|
|
2014
|
+
return sender.jid ?? sender.lid ?? void 0;
|
|
2015
|
+
}
|
|
2016
|
+
//#endregion
|
|
2037
2017
|
//#region extensions/whatsapp/src/auto-reply/monitor/ack-reaction.ts
|
|
2038
2018
|
async function maybeSendAckReaction(params) {
|
|
2039
2019
|
if (!params.msg.event.id) return null;
|
|
@@ -2043,14 +2023,16 @@ async function maybeSendAckReaction(params) {
|
|
|
2043
2023
|
cfg: params.cfg,
|
|
2044
2024
|
accountId
|
|
2045
2025
|
}).level === "off") return null;
|
|
2046
|
-
const ackConfig = params.cfg.
|
|
2026
|
+
const ackConfig = params.cfg.messages?.ackReaction;
|
|
2027
|
+
const scope = params.cfg.messages?.ackReactionScope ?? "group-mentions";
|
|
2028
|
+
if (scope === "off" || scope === "none") return null;
|
|
2047
2029
|
const emoji = resolveWhatsAppAckEmoji({
|
|
2048
2030
|
cfg: params.cfg,
|
|
2049
2031
|
agentId: params.agentId,
|
|
2050
2032
|
ackConfig
|
|
2051
2033
|
});
|
|
2052
|
-
const directEnabled =
|
|
2053
|
-
const groupMode =
|
|
2034
|
+
const directEnabled = scope === "all" || scope === "direct";
|
|
2035
|
+
const groupMode = scope === "all" || scope === "group-all" ? "always" : scope === "direct" ? "never" : "mentions";
|
|
2054
2036
|
const isGroup = admission.conversation.kind === "group";
|
|
2055
2037
|
const conversationIdForCheck = admission.conversation.id;
|
|
2056
2038
|
const activation = isGroup ? await resolveGroupActivationFor({
|
|
@@ -2075,11 +2057,11 @@ async function maybeSendAckReaction(params) {
|
|
|
2075
2057
|
messageId: params.msg.event.id,
|
|
2076
2058
|
emoji
|
|
2077
2059
|
}, "sending ack reaction");
|
|
2078
|
-
const
|
|
2060
|
+
const participant = resolveReactionParticipant(params.msg);
|
|
2079
2061
|
const reactionOptions = {
|
|
2080
2062
|
verbose: params.verbose,
|
|
2081
2063
|
fromMe: false,
|
|
2082
|
-
...
|
|
2064
|
+
...participant ? { participant } : {},
|
|
2083
2065
|
accountId,
|
|
2084
2066
|
cfg: params.cfg
|
|
2085
2067
|
};
|
|
@@ -2249,7 +2231,13 @@ function recordPendingGroupHistoryEntry(params) {
|
|
|
2249
2231
|
body: params.body ?? params.msg.payload.body,
|
|
2250
2232
|
timestamp: params.msg.event.timestamp,
|
|
2251
2233
|
id: params.msg.event.id,
|
|
2252
|
-
senderJid: senderIdentity.jid ?? params.msg.platform.senderJid
|
|
2234
|
+
senderJid: senderIdentity.jid ?? params.msg.platform.senderJid,
|
|
2235
|
+
...params.body === void 0 && params.msg.payload.media ? { media: [{
|
|
2236
|
+
path: params.msg.payload.media.path,
|
|
2237
|
+
url: params.msg.payload.media.url ?? params.msg.payload.media.path,
|
|
2238
|
+
contentType: params.msg.payload.media.type,
|
|
2239
|
+
kind: params.msg.payload.media.kind ?? void 0
|
|
2240
|
+
}] } : {}
|
|
2253
2241
|
}
|
|
2254
2242
|
});
|
|
2255
2243
|
}
|
|
@@ -2585,7 +2573,7 @@ async function deliverWebReply(params) {
|
|
|
2585
2573
|
const tableMode = params.tableMode ?? "code";
|
|
2586
2574
|
const chunkMode = params.chunkMode ?? "length";
|
|
2587
2575
|
const normalizedReply = params.normalizedReplyResult ?? normalizeWhatsAppOutboundPayload(replyResult, { normalizeText: normalizeWhatsAppPayloadTextPreservingIndentation });
|
|
2588
|
-
const textChunks =
|
|
2576
|
+
const textChunks = markdownToWhatsAppChunks(normalizedReply.text ?? "", textLimit, tableMode, chunkMode);
|
|
2589
2577
|
const mediaList = normalizedReply.mediaUrls ?? [];
|
|
2590
2578
|
const getQuote = () => {
|
|
2591
2579
|
if (!replyResult.replyToId) return;
|
|
@@ -2595,7 +2583,8 @@ async function deliverWebReply(params) {
|
|
|
2595
2583
|
remoteJid: msg.platform.chatJid,
|
|
2596
2584
|
fromMe: cached?.fromMe ?? false,
|
|
2597
2585
|
participant: cached?.participant ?? (isGroupConversation ? msg.platform.senderJid : void 0),
|
|
2598
|
-
messageText: cached?.body ?? ""
|
|
2586
|
+
messageText: cached?.body ?? "",
|
|
2587
|
+
media: cached?.media
|
|
2599
2588
|
});
|
|
2600
2589
|
};
|
|
2601
2590
|
const sendWithRetry = async (fn, label) => {
|
|
@@ -2643,7 +2632,7 @@ async function deliverWebReply(params) {
|
|
|
2643
2632
|
mediaUrls: mediaList,
|
|
2644
2633
|
caption: remainingText.shift() || "",
|
|
2645
2634
|
send: async ({ mediaUrl, caption }) => {
|
|
2646
|
-
const media = await prepareWhatsAppOutboundMedia(await loadWebMedia
|
|
2635
|
+
const media = await prepareWhatsAppOutboundMedia(await loadWebMedia(mediaUrl, {
|
|
2647
2636
|
maxBytes: maxMediaBytes,
|
|
2648
2637
|
localRoots: params.mediaLocalRoots
|
|
2649
2638
|
}), mediaUrl);
|
|
@@ -2749,8 +2738,10 @@ function resolveVisibleWhatsAppGroupHistory(params) {
|
|
|
2749
2738
|
function resolveVisibleWhatsAppReplyContext(params) {
|
|
2750
2739
|
const replyTo = getReplyContext(params.msg, params.authDir);
|
|
2751
2740
|
if (!replyTo) return null;
|
|
2741
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2742
|
+
const previewBody = [replyTo.body, formatMediaPlaceholderText(replyTo.media ? [replyTo.media] : [])].filter(Boolean).join("\n");
|
|
2752
2743
|
const senderAllowed = resolveInboundSupplementalSenderAllowed({
|
|
2753
|
-
isGroup:
|
|
2744
|
+
isGroup: admission.conversation.kind === "group",
|
|
2754
2745
|
groupPolicy: params.groupPolicy,
|
|
2755
2746
|
allowFrom: params.groupAllowFrom,
|
|
2756
2747
|
isSenderAllowed: (allowFrom) => isWhatsAppSupplementalSenderAllowed({
|
|
@@ -2759,12 +2750,16 @@ function resolveVisibleWhatsAppReplyContext(params) {
|
|
|
2759
2750
|
sender: replyTo.sender
|
|
2760
2751
|
})
|
|
2761
2752
|
});
|
|
2762
|
-
|
|
2753
|
+
const visible = filterChannelInboundQuoteContext(params.mode, {
|
|
2763
2754
|
id: replyTo.id,
|
|
2764
|
-
body:
|
|
2755
|
+
body: previewBody,
|
|
2765
2756
|
sender: replyTo.sender?.label ?? void 0,
|
|
2766
2757
|
senderAllowed
|
|
2767
|
-
})
|
|
2758
|
+
});
|
|
2759
|
+
return visible ? {
|
|
2760
|
+
...replyTo,
|
|
2761
|
+
body: visible.body ?? ""
|
|
2762
|
+
} : null;
|
|
2768
2763
|
}
|
|
2769
2764
|
//#endregion
|
|
2770
2765
|
//#region extensions/whatsapp/src/auto-reply/monitor/inbound-dispatch.ts
|
|
@@ -2873,7 +2868,7 @@ function logWhatsAppMediaOnlyFlushResult(result) {
|
|
|
2873
2868
|
}
|
|
2874
2869
|
function resolveWhatsAppResponsePrefix(params) {
|
|
2875
2870
|
const configuredResponsePrefix = params.cfg.messages?.responsePrefix;
|
|
2876
|
-
return params.pipelineResponsePrefix ?? (configuredResponsePrefix ===
|
|
2871
|
+
return params.pipelineResponsePrefix ?? (configuredResponsePrefix === "auto" ? resolveIdentityNamePrefix$1(params.cfg, params.agentId) : configuredResponsePrefix) ?? (params.isSelfChat ? resolveIdentityNamePrefix$1(params.cfg, params.agentId) : void 0);
|
|
2877
2872
|
}
|
|
2878
2873
|
async function buildWhatsAppInboundContext(params) {
|
|
2879
2874
|
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
@@ -2885,14 +2880,16 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2885
2880
|
sender: entry.sender,
|
|
2886
2881
|
body: entry.body,
|
|
2887
2882
|
timestamp: entry.timestamp,
|
|
2888
|
-
messageId: entry.id
|
|
2883
|
+
messageId: entry.id,
|
|
2884
|
+
media: entry.media
|
|
2889
2885
|
})),
|
|
2890
2886
|
limit: params.groupHistory?.length ?? 1
|
|
2891
2887
|
}) : void 0;
|
|
2892
|
-
const media = toInboundMediaFacts(params.msg.payload.media
|
|
2888
|
+
const media = toInboundMediaFacts(params.msg.payload.media ? [{
|
|
2893
2889
|
path: params.msg.payload.media?.path,
|
|
2894
2890
|
url: params.msg.payload.media?.url ?? params.msg.payload.media?.path,
|
|
2895
|
-
contentType: params.msg.payload.media?.type
|
|
2891
|
+
contentType: params.msg.payload.media?.type,
|
|
2892
|
+
kind: params.msg.payload.media?.kind
|
|
2896
2893
|
}] : void 0, { transcribed: (_entry, index) => params.mediaTranscribedIndexes?.includes(index) === true });
|
|
2897
2894
|
return buildChannelInboundEventContext({
|
|
2898
2895
|
channel: "whatsapp",
|
|
@@ -2935,6 +2932,7 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2935
2932
|
rawBody: params.rawBody ?? params.msg.payload.body,
|
|
2936
2933
|
commandBody: params.command?.body ?? params.msg.payload.body
|
|
2937
2934
|
},
|
|
2935
|
+
sessionTranscript: { historyLimit: conversationKind === "group" ? params.groupHistoryLimit ?? params.groupHistory?.length ?? 0 : 0 },
|
|
2938
2936
|
access: {
|
|
2939
2937
|
...wasMentioned !== void 0 ? { mentions: {
|
|
2940
2938
|
canDetectMention: conversationKind === "group",
|
|
@@ -2995,11 +2993,6 @@ function createWhatsAppReplyPlan(params) {
|
|
|
2995
2993
|
const conversationId = admission.conversation.id;
|
|
2996
2994
|
const conversationKind = admission.conversation.kind;
|
|
2997
2995
|
const statusReactionController = params.statusReactionController ?? null;
|
|
2998
|
-
const statusReactionTiming = {
|
|
2999
|
-
...DEFAULT_TIMING,
|
|
3000
|
-
...params.cfg.messages?.statusReactions?.timing
|
|
3001
|
-
};
|
|
3002
|
-
const removeAckAfterReply = params.cfg.messages?.removeAckAfterReply ?? false;
|
|
3003
2996
|
const textLimit = params.maxMediaTextChunkLimit ?? resolveTextChunkLimit(params.cfg, "whatsapp");
|
|
3004
2997
|
const chunkMode = resolveChunkMode(params.cfg, "whatsapp", params.route.accountId);
|
|
3005
2998
|
const tableMode = resolveMarkdownTableMode$1({
|
|
@@ -3192,10 +3185,7 @@ function createWhatsAppReplyPlan(params) {
|
|
|
3192
3185
|
if (!didQueueVisibleReply) {
|
|
3193
3186
|
if (statusReactionController) finalizeWhatsAppStatusReaction({
|
|
3194
3187
|
controller: statusReactionController,
|
|
3195
|
-
outcome: "error"
|
|
3196
|
-
hasFinalResponse: false,
|
|
3197
|
-
removeAckAfterReply,
|
|
3198
|
-
timing: statusReactionTiming
|
|
3188
|
+
outcome: "error"
|
|
3199
3189
|
});
|
|
3200
3190
|
if (params.shouldClearGroupHistory) params.groupHistories.set(params.groupHistoryKey, []);
|
|
3201
3191
|
logVerbose$1("Skipping auto-reply: silent token or no text/media returned from resolver");
|
|
@@ -3203,10 +3193,7 @@ function createWhatsAppReplyPlan(params) {
|
|
|
3203
3193
|
}
|
|
3204
3194
|
if (statusReactionController) finalizeWhatsAppStatusReaction({
|
|
3205
3195
|
controller: statusReactionController,
|
|
3206
|
-
outcome: didDeliverVisibleReply ? "done" : "error"
|
|
3207
|
-
hasFinalResponse: didDeliverVisibleReply,
|
|
3208
|
-
removeAckAfterReply,
|
|
3209
|
-
timing: statusReactionTiming
|
|
3196
|
+
outcome: didDeliverVisibleReply ? "done" : "error"
|
|
3210
3197
|
});
|
|
3211
3198
|
if (params.shouldClearGroupHistory) params.groupHistories.set(params.groupHistoryKey, []);
|
|
3212
3199
|
return didDeliverVisibleReply;
|
|
@@ -3214,29 +3201,8 @@ function createWhatsAppReplyPlan(params) {
|
|
|
3214
3201
|
};
|
|
3215
3202
|
}
|
|
3216
3203
|
async function finalizeWhatsAppStatusReaction(params) {
|
|
3217
|
-
if (params.outcome === "done")
|
|
3218
|
-
|
|
3219
|
-
if (params.removeAckAfterReply) {
|
|
3220
|
-
await new Promise((resolve) => {
|
|
3221
|
-
setTimeout(resolve, params.timing.doneHoldMs);
|
|
3222
|
-
});
|
|
3223
|
-
await params.controller.clear();
|
|
3224
|
-
} else await params.controller.restoreInitial();
|
|
3225
|
-
return;
|
|
3226
|
-
}
|
|
3227
|
-
await params.controller.setError();
|
|
3228
|
-
if (params.hasFinalResponse) {
|
|
3229
|
-
if (params.removeAckAfterReply) {
|
|
3230
|
-
await new Promise((resolve) => {
|
|
3231
|
-
setTimeout(resolve, params.timing.errorHoldMs);
|
|
3232
|
-
});
|
|
3233
|
-
await params.controller.clear();
|
|
3234
|
-
} else await params.controller.restoreInitial();
|
|
3235
|
-
return;
|
|
3236
|
-
}
|
|
3237
|
-
if (params.removeAckAfterReply) await new Promise((resolve) => {
|
|
3238
|
-
setTimeout(resolve, params.timing.errorHoldMs);
|
|
3239
|
-
});
|
|
3204
|
+
if (params.outcome === "done") await params.controller.setDone();
|
|
3205
|
+
else await params.controller.setError();
|
|
3240
3206
|
await params.controller.restoreInitial();
|
|
3241
3207
|
}
|
|
3242
3208
|
//#endregion
|
|
@@ -3250,7 +3216,7 @@ function resolveIdentityNamePrefix(cfg, agentId) {
|
|
|
3250
3216
|
return identityName ? `[${identityName}]` : void 0;
|
|
3251
3217
|
}
|
|
3252
3218
|
function resolveMessagePrefix(cfg, agentId, opts) {
|
|
3253
|
-
const configured = opts?.configured
|
|
3219
|
+
const configured = opts?.configured;
|
|
3254
3220
|
if (configured !== void 0) return configured;
|
|
3255
3221
|
if (opts?.hasAllowFrom === true) return "";
|
|
3256
3222
|
return resolveIdentityNamePrefix(cfg, agentId) ?? opts?.fallback ?? "[openclaw]";
|
|
@@ -3267,7 +3233,7 @@ function formatReplyContext(msg) {
|
|
|
3267
3233
|
function buildInboundLine(params) {
|
|
3268
3234
|
const { cfg, msg, agentId, previousTimestamp, envelope } = params;
|
|
3269
3235
|
const messagePrefix = resolveMessagePrefix(cfg, agentId, {
|
|
3270
|
-
configured: cfg.channels?.whatsapp?.
|
|
3236
|
+
configured: cfg.channels?.whatsapp?.responsePrefix,
|
|
3271
3237
|
hasAllowFrom: (cfg.channels?.whatsapp?.allowFrom?.length ?? 0) > 0
|
|
3272
3238
|
});
|
|
3273
3239
|
const admission = requireWhatsAppInboundAdmission(msg);
|
|
@@ -3297,23 +3263,24 @@ function buildInboundLine(params) {
|
|
|
3297
3263
|
//#region extensions/whatsapp/src/auto-reply/monitor/status-reaction.ts
|
|
3298
3264
|
async function createWhatsAppStatusReactionController(params) {
|
|
3299
3265
|
if (!params.msg.event.id) return null;
|
|
3300
|
-
|
|
3301
|
-
if (statusReactionsConfig?.enabled !== true) return null;
|
|
3266
|
+
if ((params.cfg.messages?.statusReactions)?.enabled !== true) return null;
|
|
3302
3267
|
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
3303
3268
|
const accountId = admission.accountId;
|
|
3304
3269
|
if (resolveWhatsAppReactionLevel({
|
|
3305
3270
|
cfg: params.cfg,
|
|
3306
3271
|
accountId
|
|
3307
3272
|
}).level === "off") return null;
|
|
3308
|
-
const ackConfig = params.cfg.
|
|
3273
|
+
const ackConfig = params.cfg.messages?.ackReaction;
|
|
3274
|
+
const scope = params.cfg.messages?.ackReactionScope ?? "group-mentions";
|
|
3275
|
+
if (scope === "off" || scope === "none") return null;
|
|
3309
3276
|
const ackEmoji = resolveWhatsAppAckEmoji({
|
|
3310
3277
|
cfg: params.cfg,
|
|
3311
3278
|
agentId: params.agentId,
|
|
3312
3279
|
ackConfig
|
|
3313
3280
|
});
|
|
3314
3281
|
if (!ackEmoji) return null;
|
|
3315
|
-
const directEnabled =
|
|
3316
|
-
const groupMode =
|
|
3282
|
+
const directEnabled = scope === "all" || scope === "direct";
|
|
3283
|
+
const groupMode = scope === "all" || scope === "group-all" ? "always" : scope === "direct" ? "never" : "mentions";
|
|
3317
3284
|
const isGroup = admission.conversation.kind === "group";
|
|
3318
3285
|
const conversationIdForCheck = admission.conversation.id;
|
|
3319
3286
|
const activation = isGroup ? await resolveGroupActivationFor({
|
|
@@ -3332,11 +3299,11 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
3332
3299
|
wasMentioned: (params.msg.groupMention?.wasMentioned ?? params.msg.wasMentioned) === true,
|
|
3333
3300
|
groupActivated: activation === "always"
|
|
3334
3301
|
})) return null;
|
|
3335
|
-
const
|
|
3302
|
+
const participant = resolveReactionParticipant(params.msg);
|
|
3336
3303
|
const reactionOptions = {
|
|
3337
3304
|
verbose: params.verbose,
|
|
3338
3305
|
fromMe: false,
|
|
3339
|
-
...
|
|
3306
|
+
...participant ? { participant } : {},
|
|
3340
3307
|
accountId,
|
|
3341
3308
|
cfg: params.cfg
|
|
3342
3309
|
};
|
|
@@ -3353,8 +3320,7 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
3353
3320
|
}
|
|
3354
3321
|
},
|
|
3355
3322
|
initialEmoji: ackEmoji,
|
|
3356
|
-
emojis:
|
|
3357
|
-
timing: statusReactionsConfig.timing,
|
|
3323
|
+
emojis: void 0,
|
|
3358
3324
|
onError: (err) => {
|
|
3359
3325
|
logVerbose(`WhatsApp status-reaction error for chat ${chatId}/${msgId}: ${String(err)}`);
|
|
3360
3326
|
}
|
|
@@ -3423,13 +3389,16 @@ async function processMessage(params) {
|
|
|
3423
3389
|
sessionKey: params.route.sessionKey
|
|
3424
3390
|
});
|
|
3425
3391
|
let audioTranscript = params.preflightAudioTranscript ?? void 0;
|
|
3426
|
-
const hasAudioBody = params.msg.payload.media?.type?.startsWith("audio/") === true && params.msg.payload.body
|
|
3392
|
+
const hasAudioBody = (params.msg.payload.media?.kind === "audio" || params.msg.payload.media?.type?.startsWith("audio/") === true) && !params.msg.payload.body.trim();
|
|
3427
3393
|
if (params.preflightAudioTranscript === void 0 && hasAudioBody && params.msg.payload.media?.path) try {
|
|
3428
3394
|
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
3429
3395
|
audioTranscript = await transcribeFirstAudio({
|
|
3430
3396
|
ctx: {
|
|
3431
|
-
|
|
3432
|
-
|
|
3397
|
+
media: [{
|
|
3398
|
+
path: params.msg.payload.media.path,
|
|
3399
|
+
contentType: params.msg.payload.media.type,
|
|
3400
|
+
kind: params.msg.payload.media.kind ?? void 0
|
|
3401
|
+
}],
|
|
3433
3402
|
From: conversationId,
|
|
3434
3403
|
To: params.msg.platform.recipientJid,
|
|
3435
3404
|
Provider: "whatsapp",
|
|
@@ -3441,7 +3410,7 @@ async function processMessage(params) {
|
|
|
3441
3410
|
cfg: params.cfg
|
|
3442
3411
|
});
|
|
3443
3412
|
} catch {
|
|
3444
|
-
if (shouldLogVerbose$1()) logVerbose$1("whatsapp: audio preflight transcription failed,
|
|
3413
|
+
if (shouldLogVerbose$1()) logVerbose$1("whatsapp: audio preflight transcription failed, keeping structured audio");
|
|
3445
3414
|
}
|
|
3446
3415
|
const msgForAgent = audioTranscript !== void 0 ? {
|
|
3447
3416
|
...params.msg,
|
|
@@ -3479,7 +3448,8 @@ async function processMessage(params) {
|
|
|
3479
3448
|
entries: history.map((m) => ({
|
|
3480
3449
|
sender: m.sender,
|
|
3481
3450
|
body: m.body,
|
|
3482
|
-
timestamp: m.timestamp
|
|
3451
|
+
timestamp: m.timestamp,
|
|
3452
|
+
media: m.media
|
|
3483
3453
|
})),
|
|
3484
3454
|
currentMessage: combinedBody,
|
|
3485
3455
|
excludeLast: false,
|
|
@@ -3488,7 +3458,7 @@ async function processMessage(params) {
|
|
|
3488
3458
|
channel: "WhatsApp",
|
|
3489
3459
|
from: conversationId,
|
|
3490
3460
|
timestamp: entry.timestamp,
|
|
3491
|
-
body: entry.body,
|
|
3461
|
+
body: [entry.body, formatMediaPlaceholderText(entry.media ?? [])].filter(Boolean).join("\n"),
|
|
3492
3462
|
chatType: "group",
|
|
3493
3463
|
senderLabel: entry.sender,
|
|
3494
3464
|
envelope: envelopeOptions
|
|
@@ -3582,6 +3552,7 @@ async function processMessage(params) {
|
|
|
3582
3552
|
authorized: commandAuthorized
|
|
3583
3553
|
},
|
|
3584
3554
|
groupHistory: visibleGroupHistory,
|
|
3555
|
+
groupHistoryLimit: params.groupHistoryLimit,
|
|
3585
3556
|
groupMemberRoster: params.groupMemberNames.get(params.groupHistoryKey),
|
|
3586
3557
|
groupSystemPrompt: conversationSystemPrompt,
|
|
3587
3558
|
msg: params.msg,
|
|
@@ -3704,7 +3675,7 @@ async function processMessage(params) {
|
|
|
3704
3675
|
});
|
|
3705
3676
|
const didSendReply = turnResult.dispatched ? finalizeReply?.(turnResult.dispatchResult) ?? false : false;
|
|
3706
3677
|
removeAckReactionHandleAfterReply({
|
|
3707
|
-
removeAfterReply:
|
|
3678
|
+
removeAfterReply: false,
|
|
3708
3679
|
ackReaction,
|
|
3709
3680
|
onError: (err) => {
|
|
3710
3681
|
logAckFailure({
|
|
@@ -3744,6 +3715,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3744
3715
|
route,
|
|
3745
3716
|
groupHistoryKey,
|
|
3746
3717
|
groupHistories: params.groupHistories,
|
|
3718
|
+
groupHistoryLimit: params.groupHistoryLimit,
|
|
3747
3719
|
groupMemberNames: params.groupMemberNames,
|
|
3748
3720
|
connectionId: params.connectionId,
|
|
3749
3721
|
verbose: params.verbose,
|
|
@@ -3811,7 +3783,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3811
3783
|
peerId
|
|
3812
3784
|
}) : route.sessionKey;
|
|
3813
3785
|
let preflightAudioTranscript;
|
|
3814
|
-
const hasAudioBody = msg.payload.media?.type?.startsWith("audio/") === true && msg.payload.body
|
|
3786
|
+
const hasAudioBody = (msg.payload.media?.kind === "audio" || msg.payload.media?.type?.startsWith("audio/") === true) && !msg.payload.body.trim();
|
|
3815
3787
|
const canRunEarlyAudioPreflight = conversationKind === "group" || canRunDirectEarlyAudioPreflight;
|
|
3816
3788
|
let ackAlreadySent = false;
|
|
3817
3789
|
let ackReaction = null;
|
|
@@ -3837,8 +3809,11 @@ function createWebOnMessageHandler(params) {
|
|
|
3837
3809
|
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
3838
3810
|
preflightAudioTranscript = await transcribeFirstAudio({
|
|
3839
3811
|
ctx: {
|
|
3840
|
-
|
|
3841
|
-
|
|
3812
|
+
media: [{
|
|
3813
|
+
path: msg.payload.media.path,
|
|
3814
|
+
contentType: msg.payload.media.type,
|
|
3815
|
+
kind: msg.payload.media.kind ?? void 0
|
|
3816
|
+
}],
|
|
3842
3817
|
From: conversationId,
|
|
3843
3818
|
To: msg.platform.recipientJid,
|
|
3844
3819
|
Provider: "whatsapp",
|
|
@@ -4009,8 +3984,7 @@ function resolveWebMonitorConfigSnapshot(params) {
|
|
|
4009
3984
|
...params.cfg.channels,
|
|
4010
3985
|
whatsapp: {
|
|
4011
3986
|
...params.cfg.channels?.whatsapp,
|
|
4012
|
-
|
|
4013
|
-
messagePrefix: account.messagePrefix,
|
|
3987
|
+
responsePrefix: account.messagePrefix,
|
|
4014
3988
|
allowFrom: account.allowFrom,
|
|
4015
3989
|
groupAllowFrom: account.groupAllowFrom,
|
|
4016
3990
|
groupPolicy: account.groupPolicy,
|
|
@@ -4075,7 +4049,7 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
4075
4049
|
const maxMediaBytes = resolveWhatsAppMediaMaxBytes(account);
|
|
4076
4050
|
const heartbeatSeconds = resolveHeartbeatSeconds(cfg, tuning.heartbeatSeconds);
|
|
4077
4051
|
const reconnectPolicy = resolveReconnectPolicy(cfg, tuning.reconnect);
|
|
4078
|
-
const socketTiming = resolveWhatsAppSocketTiming(
|
|
4052
|
+
const socketTiming = resolveWhatsAppSocketTiming(tuning.socketTiming);
|
|
4079
4053
|
const baseMentionConfig = buildMentionConfig(cfg);
|
|
4080
4054
|
const groupHistoryLimit = account.historyLimit ?? cfg.channels?.whatsapp?.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT;
|
|
4081
4055
|
const groupHistories = /* @__PURE__ */ new Map();
|
|
@@ -4474,4 +4448,4 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
4474
4448
|
}
|
|
4475
4449
|
}
|
|
4476
4450
|
//#endregion
|
|
4477
|
-
export { loadWebMediaRaw as a, monitorWebInbox as c, loadWebMedia
|
|
4451
|
+
export { loadWebMediaRaw as a, monitorWebInbox as c, loadWebMedia as i, resetWebInboundDedupe as l, LocalMediaAccessError as n, optimizeImageToJpeg as o, getDefaultLocalRoots as r, optimizeImageToPng as s, monitorWebChannel as t };
|