@openclaw/whatsapp 2026.6.8 → 2026.6.9
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-BKaMOvIk.js → access-control-BnFVCHHH.js} +161 -50
- package/dist/{action-runtime-Cyp5GNIT.js → action-runtime-ClQLHIwf.js} +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/api.js +10 -9
- package/dist/{approval-handler.runtime-BVmOu6x1.js → approval-handler.runtime-DLjPf_Mx.js} +1 -1
- package/dist/{auth-store-e9VzLZ-S.js → auth-store-RyuCPHE0.js} +3 -3
- package/dist/{channel-DyUm8hqs.js → channel-CNA0E9wp.js} +8 -9
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-zvbaCnGe.js → channel-react-action-CdYJKJWb.js} +3 -4
- package/dist/{channel.runtime-BXkzo0j1.js → channel.runtime-ZKS2C0Cw.js} +4 -4
- package/dist/{channel.setup-CpyAie9O.js → channel.setup-BfcLCLNn.js} +2 -2
- package/dist/{connection-controller-BWBoVQr4.js → connection-controller-BDuM0Kc7.js} +52 -27
- package/dist/contract-api.js +1 -1
- package/dist/{identity-Bupuq9vF.js → identity-Cm6bKAtk.js} +1 -1
- package/dist/light-runtime-api.js +1 -1
- package/dist/{login-Xv3ujrl0.js → login-B503Fwb8.js} +4 -3
- package/dist/{login-qr-CaJziL93.js → login-qr-AgwdQyj_.js} +16 -4
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-Ggwn3FDi.js → monitor-C5_QBO1-.js} +338 -263
- package/dist/{quoted-message-CveINB35.js → quoted-message-DVOfpEja.js} +1 -1
- package/dist/runtime-api.js +7 -7
- package/dist/{send-DSlVXKL_.js → send-A9EqsNyz.js} +3 -1
- package/dist/{send-api-Cp9CUH5P.js → send-api-89SE5WKV.js} +19 -6
- package/dist/{session-BCKUPRkN.js → session-BW8RcCcb.js} +3 -20
- package/dist/{setup-core-Cp0NMO89.js → setup-core-DVEkfMVh.js} +7 -3
- package/dist/{setup-finalize-DnV-KlkQ.js → setup-finalize-DJepnx7S.js} +2 -2
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BmPcAhIF.js → setup-surface-ByAUWXyq.js} +2 -2
- package/dist/socket-timing-DvMNkIge.js +65 -0
- package/dist/{text-runtime-Dk37KYHj.js → text-runtime-BBSmIBHN.js} +6 -4
- package/node_modules/@protobufjs/aspromise/LICENSE +26 -0
- package/node_modules/@protobufjs/aspromise/README.md +13 -0
- package/node_modules/{protobufjs/src/util/aspromise.d.ts → @protobufjs/aspromise/index.d.ts} +13 -13
- package/node_modules/{protobufjs/src/util/aspromise.js → @protobufjs/aspromise/index.js} +52 -52
- package/node_modules/@protobufjs/aspromise/package.json +21 -0
- package/node_modules/@protobufjs/aspromise/tests/index.js +130 -0
- package/node_modules/@protobufjs/base64/LICENSE +26 -0
- package/node_modules/@protobufjs/base64/README.md +19 -0
- package/node_modules/{protobufjs/src/util/base64.d.ts → @protobufjs/base64/index.d.ts} +32 -32
- package/node_modules/{protobufjs/src/util/base64.js → @protobufjs/base64/index.js} +139 -146
- package/node_modules/@protobufjs/base64/package.json +21 -0
- package/node_modules/@protobufjs/base64/tests/index.js +46 -0
- package/node_modules/@protobufjs/codegen/LICENSE +26 -0
- package/node_modules/@protobufjs/codegen/README.md +49 -0
- package/node_modules/{protobufjs/src/util/codegen.d.ts → @protobufjs/codegen/index.d.ts} +31 -31
- package/node_modules/{protobufjs/src/util/codegen.js → @protobufjs/codegen/index.js} +112 -113
- package/node_modules/@protobufjs/codegen/package.json +13 -0
- package/node_modules/@protobufjs/codegen/tests/index.js +13 -0
- package/node_modules/@protobufjs/eventemitter/CHANGELOG.md +8 -0
- package/node_modules/@protobufjs/eventemitter/LICENSE +26 -0
- package/node_modules/@protobufjs/eventemitter/README.md +22 -0
- package/node_modules/{protobufjs/src/util/eventemitter.d.ts → @protobufjs/eventemitter/index.d.ts} +45 -45
- package/node_modules/{protobufjs/src/util/eventemitter.js → @protobufjs/eventemitter/index.js} +86 -86
- package/node_modules/@protobufjs/eventemitter/package.json +21 -0
- package/node_modules/@protobufjs/eventemitter/tests/index.js +83 -0
- package/node_modules/@protobufjs/fetch/CHANGELOG.md +8 -0
- package/node_modules/@protobufjs/fetch/LICENSE +26 -0
- package/node_modules/@protobufjs/fetch/README.md +13 -0
- package/node_modules/{protobufjs/src/util/fetch.d.ts → @protobufjs/fetch/index.d.ts} +56 -56
- package/node_modules/{protobufjs/src/util/fetch.js → @protobufjs/fetch/index.js} +112 -112
- package/node_modules/@protobufjs/fetch/package.json +27 -0
- package/node_modules/@protobufjs/fetch/tests/data/file.txt +1 -0
- package/node_modules/@protobufjs/fetch/tests/index.js +158 -0
- package/node_modules/@protobufjs/fetch/util/fs.js +11 -0
- package/node_modules/@protobufjs/float/LICENSE +26 -0
- package/node_modules/@protobufjs/float/README.md +102 -0
- package/node_modules/@protobufjs/float/bench/index.js +87 -0
- package/node_modules/@protobufjs/float/bench/suite.js +46 -0
- package/node_modules/{protobufjs/src/util/float.js → @protobufjs/float/index.js} +335 -335
- package/node_modules/@protobufjs/float/package.json +26 -0
- package/node_modules/@protobufjs/float/tests/index.js +100 -0
- package/node_modules/@protobufjs/inquire/CHANGELOG.md +8 -0
- package/node_modules/@protobufjs/inquire/LICENSE +26 -0
- package/node_modules/@protobufjs/inquire/README.md +13 -0
- package/node_modules/{protobufjs/src/util/inquire.d.ts → @protobufjs/inquire/index.d.ts} +10 -10
- package/node_modules/{protobufjs/src/util/inquire.js → @protobufjs/inquire/index.js} +38 -38
- package/node_modules/@protobufjs/inquire/package.json +21 -0
- package/node_modules/@protobufjs/inquire/tests/data/array.js +1 -0
- package/node_modules/@protobufjs/inquire/tests/data/emptyArray.js +1 -0
- package/node_modules/@protobufjs/inquire/tests/data/emptyObject.js +1 -0
- package/node_modules/@protobufjs/inquire/tests/data/object.js +1 -0
- package/node_modules/@protobufjs/inquire/tests/index.js +20 -0
- package/node_modules/@protobufjs/path/LICENSE +26 -0
- package/node_modules/@protobufjs/path/README.md +19 -0
- package/node_modules/{protobufjs/src/util/path.d.ts → @protobufjs/path/index.d.ts} +22 -22
- package/node_modules/{protobufjs/src/util/path.js → @protobufjs/path/index.js} +65 -72
- package/node_modules/@protobufjs/path/package.json +21 -0
- package/node_modules/@protobufjs/path/tests/index.js +60 -0
- package/node_modules/@protobufjs/pool/.npmignore +3 -0
- package/node_modules/@protobufjs/pool/LICENSE +26 -0
- package/node_modules/@protobufjs/pool/README.md +13 -0
- package/node_modules/{protobufjs/src/util/pool.d.ts → @protobufjs/pool/index.d.ts} +32 -32
- package/node_modules/{protobufjs/src/util/pool.js → @protobufjs/pool/index.js} +48 -48
- package/node_modules/@protobufjs/pool/package.json +21 -0
- package/node_modules/@protobufjs/pool/tests/index.js +33 -0
- package/node_modules/@protobufjs/utf8/LICENSE +26 -0
- package/node_modules/@protobufjs/utf8/README.md +20 -0
- package/node_modules/{protobufjs/src/util/utf8.d.ts → @protobufjs/utf8/index.d.ts} +24 -24
- package/node_modules/{protobufjs/src/util/utf8.js → @protobufjs/utf8/index.js} +104 -130
- package/node_modules/@protobufjs/utf8/package.json +21 -0
- package/node_modules/@protobufjs/utf8/tests/data/surrogate_pair_bug.txt +207 -0
- package/node_modules/@protobufjs/utf8/tests/data/utf8.txt +216 -0
- package/node_modules/@protobufjs/utf8/tests/index.js +74 -0
- package/node_modules/@types/node/LICENSE +21 -0
- package/node_modules/@types/node/README.md +15 -0
- package/node_modules/@types/node/assert/strict.d.ts +59 -0
- package/node_modules/@types/node/assert.d.ts +950 -0
- package/node_modules/@types/node/async_hooks.d.ts +711 -0
- package/node_modules/@types/node/buffer.buffer.d.ts +466 -0
- package/node_modules/@types/node/buffer.d.ts +1765 -0
- package/node_modules/@types/node/child_process.d.ts +1366 -0
- package/node_modules/@types/node/cluster.d.ts +432 -0
- package/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
- package/node_modules/@types/node/console.d.ts +93 -0
- package/node_modules/@types/node/constants.d.ts +14 -0
- package/node_modules/@types/node/crypto.d.ts +4058 -0
- package/node_modules/@types/node/dgram.d.ts +537 -0
- package/node_modules/@types/node/diagnostics_channel.d.ts +552 -0
- package/node_modules/@types/node/dns/promises.d.ts +497 -0
- package/node_modules/@types/node/dns.d.ts +876 -0
- package/node_modules/@types/node/domain.d.ts +150 -0
- package/node_modules/@types/node/events.d.ts +1008 -0
- package/node_modules/@types/node/fs/promises.d.ts +1468 -0
- package/node_modules/@types/node/fs.d.ts +4780 -0
- package/node_modules/@types/node/globals.d.ts +150 -0
- package/node_modules/@types/node/globals.typedarray.d.ts +101 -0
- package/node_modules/@types/node/http.d.ts +2147 -0
- package/node_modules/@types/node/http2.d.ts +2485 -0
- package/node_modules/@types/node/https.d.ts +400 -0
- package/node_modules/@types/node/index.d.ts +117 -0
- package/node_modules/@types/node/inspector/promises.d.ts +35 -0
- package/node_modules/@types/node/inspector.d.ts +264 -0
- package/node_modules/@types/node/inspector.generated.d.ts +4406 -0
- package/node_modules/@types/node/module.d.ts +755 -0
- package/node_modules/@types/node/net.d.ts +970 -0
- package/node_modules/@types/node/os.d.ts +498 -0
- package/node_modules/@types/node/package.json +155 -0
- package/node_modules/@types/node/path/posix.d.ts +8 -0
- package/node_modules/@types/node/path/win32.d.ts +8 -0
- package/node_modules/@types/node/path.d.ts +178 -0
- package/node_modules/@types/node/perf_hooks.d.ts +612 -0
- package/node_modules/@types/node/process.d.ts +2204 -0
- package/node_modules/@types/node/punycode.d.ts +89 -0
- package/node_modules/@types/node/querystring.d.ts +139 -0
- package/node_modules/@types/node/quic.d.ts +897 -0
- package/node_modules/@types/node/readline/promises.d.ts +158 -0
- package/node_modules/@types/node/readline.d.ts +507 -0
- package/node_modules/@types/node/repl.d.ts +420 -0
- package/node_modules/@types/node/sea.d.ts +47 -0
- package/node_modules/@types/node/sqlite.d.ts +1068 -0
- package/node_modules/@types/node/stream/consumers.d.ts +114 -0
- package/node_modules/@types/node/stream/iter.d.ts +301 -0
- package/node_modules/@types/node/stream/promises.d.ts +211 -0
- package/node_modules/@types/node/stream/web.d.ts +300 -0
- package/node_modules/@types/node/stream.d.ts +1774 -0
- package/node_modules/@types/node/string_decoder.d.ts +27 -0
- package/node_modules/@types/node/test/reporters.d.ts +59 -0
- package/node_modules/@types/node/test.d.ts +2279 -0
- package/node_modules/@types/node/timers/promises.d.ts +93 -0
- package/node_modules/@types/node/timers.d.ts +149 -0
- package/node_modules/@types/node/tls.d.ts +1193 -0
- package/node_modules/@types/node/trace_events.d.ts +103 -0
- package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +462 -0
- package/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
- package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
- package/node_modules/@types/node/ts5.6/index.d.ts +119 -0
- package/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
- package/node_modules/@types/node/ts5.7/index.d.ts +119 -0
- package/node_modules/@types/node/tty.d.ts +225 -0
- package/node_modules/@types/node/url.d.ts +556 -0
- package/node_modules/@types/node/util/types.d.ts +558 -0
- package/node_modules/@types/node/util.d.ts +1677 -0
- package/node_modules/@types/node/v8.d.ts +980 -0
- package/node_modules/@types/node/vm.d.ts +1136 -0
- package/node_modules/@types/node/wasi.d.ts +131 -0
- package/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
- package/node_modules/@types/node/web-globals/blob.d.ts +23 -0
- package/node_modules/@types/node/web-globals/console.d.ts +9 -0
- package/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
- package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
- package/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
- package/node_modules/@types/node/web-globals/events.d.ts +106 -0
- package/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
- package/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
- package/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
- package/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
- package/node_modules/@types/node/web-globals/performance.d.ts +45 -0
- package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
- package/node_modules/@types/node/web-globals/streams.d.ts +115 -0
- package/node_modules/@types/node/web-globals/timers.d.ts +44 -0
- package/node_modules/@types/node/web-globals/url.d.ts +24 -0
- package/node_modules/@types/node/worker_threads.d.ts +671 -0
- package/node_modules/@types/node/zlib/iter.d.ts +131 -0
- package/node_modules/@types/node/zlib.d.ts +589 -0
- package/node_modules/protobufjs/README.md +556 -263
- package/node_modules/protobufjs/dist/light/protobuf.js +1569 -1919
- 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 +906 -1132
- 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 +1576 -1993
- 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/ext/descriptor/README.md +70 -3
- package/node_modules/protobufjs/ext/descriptor/index.d.ts +193 -0
- package/node_modules/protobufjs/ext/descriptor/index.js +1185 -1
- package/node_modules/protobufjs/ext/descriptor/test.js +54 -0
- package/node_modules/protobufjs/index.d.ts +720 -834
- package/node_modules/protobufjs/package.json +44 -20
- package/node_modules/protobufjs/src/converter.js +36 -60
- package/node_modules/protobufjs/src/decoder.js +53 -124
- package/node_modules/protobufjs/src/encoder.js +2 -10
- package/node_modules/protobufjs/src/enum.js +3 -8
- package/node_modules/protobufjs/src/field.js +11 -13
- package/node_modules/protobufjs/src/index-light.js +1 -1
- package/node_modules/protobufjs/src/mapfield.js +0 -1
- package/node_modules/protobufjs/src/message.js +11 -5
- package/node_modules/protobufjs/src/method.js +4 -5
- package/node_modules/protobufjs/src/namespace.js +3 -10
- package/node_modules/protobufjs/src/object.js +20 -20
- package/node_modules/protobufjs/src/oneof.js +0 -3
- package/node_modules/protobufjs/src/parse.js +16 -78
- package/node_modules/protobufjs/src/reader.js +31 -136
- package/node_modules/protobufjs/src/reader_buffer.js +3 -24
- package/node_modules/protobufjs/src/root.js +3 -7
- package/node_modules/protobufjs/src/roots.js +1 -1
- package/node_modules/protobufjs/src/service.js +6 -13
- package/node_modules/protobufjs/src/tokenize.js +1 -6
- package/node_modules/protobufjs/src/type.js +30 -44
- package/node_modules/protobufjs/src/typescript.jsdoc +15 -0
- package/node_modules/protobufjs/src/util/minimal.js +12 -36
- package/node_modules/protobufjs/src/util.js +17 -6
- package/node_modules/protobufjs/src/verifier.js +6 -6
- package/node_modules/protobufjs/src/wrappers.js +1 -0
- package/node_modules/protobufjs/src/writer.js +16 -42
- package/node_modules/protobufjs/src/writer_buffer.js +1 -18
- package/node_modules/protobufjs/tsconfig.json +5 -3
- package/node_modules/undici-types/LICENSE +21 -0
- package/node_modules/undici-types/README.md +6 -0
- package/node_modules/undici-types/agent.d.ts +32 -0
- package/node_modules/undici-types/api.d.ts +43 -0
- package/node_modules/undici-types/balanced-pool.d.ts +30 -0
- package/node_modules/undici-types/cache-interceptor.d.ts +179 -0
- package/node_modules/undici-types/cache.d.ts +36 -0
- package/node_modules/undici-types/client-stats.d.ts +15 -0
- package/node_modules/undici-types/client.d.ts +123 -0
- package/node_modules/undici-types/connector.d.ts +36 -0
- package/node_modules/undici-types/content-type.d.ts +21 -0
- package/node_modules/undici-types/cookies.d.ts +30 -0
- package/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
- package/node_modules/undici-types/dispatcher.d.ts +279 -0
- package/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
- package/node_modules/undici-types/errors.d.ts +177 -0
- package/node_modules/undici-types/eventsource.d.ts +66 -0
- package/node_modules/undici-types/fetch.d.ts +211 -0
- package/node_modules/undici-types/formdata.d.ts +108 -0
- package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
- package/node_modules/undici-types/global-origin.d.ts +7 -0
- package/node_modules/undici-types/h2c-client.d.ts +73 -0
- package/node_modules/undici-types/handlers.d.ts +15 -0
- package/node_modules/undici-types/header.d.ts +160 -0
- package/node_modules/undici-types/index.d.ts +91 -0
- package/node_modules/undici-types/interceptors.d.ts +80 -0
- package/node_modules/undici-types/mock-agent.d.ts +68 -0
- package/node_modules/undici-types/mock-call-history.d.ts +111 -0
- package/node_modules/undici-types/mock-client.d.ts +27 -0
- package/node_modules/undici-types/mock-errors.d.ts +12 -0
- package/node_modules/undici-types/mock-interceptor.d.ts +94 -0
- package/node_modules/undici-types/mock-pool.d.ts +27 -0
- package/node_modules/undici-types/package.json +55 -0
- package/node_modules/undici-types/patch.d.ts +29 -0
- package/node_modules/undici-types/pool-stats.d.ts +19 -0
- package/node_modules/undici-types/pool.d.ts +41 -0
- package/node_modules/undici-types/proxy-agent.d.ts +29 -0
- package/node_modules/undici-types/readable.d.ts +68 -0
- package/node_modules/undici-types/retry-agent.d.ts +8 -0
- package/node_modules/undici-types/retry-handler.d.ts +125 -0
- package/node_modules/undici-types/round-robin-pool.d.ts +41 -0
- package/node_modules/undici-types/snapshot-agent.d.ts +109 -0
- package/node_modules/undici-types/socks5-proxy-agent.d.ts +25 -0
- package/node_modules/undici-types/util.d.ts +18 -0
- package/node_modules/undici-types/utility.d.ts +7 -0
- package/node_modules/undici-types/webidl.d.ts +347 -0
- package/node_modules/undici-types/websocket.d.ts +188 -0
- package/npm-shrinkwrap.json +95 -6
- package/package.json +4 -4
- package/node_modules/protobufjs/ext/README.md +0 -81
- package/node_modules/protobufjs/ext/descriptor.d.ts +0 -86
- package/node_modules/protobufjs/ext/descriptor.generated.d.ts +0 -409
- package/node_modules/protobufjs/ext/descriptor.js +0 -1266
- package/node_modules/protobufjs/ext/textformat.d.ts +0 -19
- package/node_modules/protobufjs/ext/textformat.generated.d.ts +0 -11
- package/node_modules/protobufjs/ext/textformat.js +0 -1235
- package/node_modules/protobufjs/google/protobuf/compiler/plugin.json +0 -126
- package/node_modules/protobufjs/google/protobuf/compiler/plugin.proto +0 -47
- package/node_modules/protobufjs/src/typescript.js +0 -25
- /package/node_modules/{protobufjs/src/util/float.d.ts → @protobufjs/float/index.d.ts} +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-DgViSyJx.js";
|
|
2
|
-
import {
|
|
3
|
-
import { a as normalizeWhatsAppOutboundPayload, c as prepareWhatsAppOutboundMedia, d as maybeResolveWhatsAppApprovalReaction, g as resolveWhatsAppReactionLevel, l as sendWhatsAppOutboundWithRetry, r as sendReactionWhatsApp, s as normalizeWhatsAppPayloadTextPreservingIndentation } from "./send-DSlVXKL_.js";
|
|
2
|
+
import { a as normalizeWhatsAppOutboundPayload, c as prepareWhatsAppOutboundMedia, d as maybeResolveWhatsAppApprovalReaction, g as resolveWhatsAppReactionLevel, l as sendWhatsAppOutboundWithRetry, r as sendReactionWhatsApp, s as normalizeWhatsAppPayloadTextPreservingIndentation } from "./send-A9EqsNyz.js";
|
|
4
3
|
import { n as getWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
5
4
|
import { n as getStatusCode, r as getRegisteredWhatsAppConnectionController, t as formatError } from "./session-errors-CbsoQqoy.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { a as resolveWhatsAppSocketTiming, i as resolveWhatsAppSocketOperationTimeoutMs, n as createWhatsAppSocketOperationTimeoutAdapter, o as withWhatsAppSocketOperationTimeout, r as isWhatsAppSocketOperationTimeoutError } from "./socket-timing-DvMNkIge.js";
|
|
6
|
+
import { d as markdownToWhatsApp, f as resolveJidToE164, l as isSelfChatMode, n as normalizeE164, t as convertMarkdownTables$1, u as jidToE164 } from "./text-runtime-BBSmIBHN.js";
|
|
7
|
+
import { n as cacheInboundMessageMeta, r as lookupInboundMessageMeta, t as buildQuotedMessageOptions } from "./quoted-message-DVOfpEja.js";
|
|
8
|
+
import { g as readWebSelfId, o as getWebAuthAgeMs, r as WhatsAppAuthUnstableError, v as readWebSelfIdentityForDecision } from "./auth-store-RyuCPHE0.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-Cm6bKAtk.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
|
|
13
|
-
import {
|
|
11
|
+
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-BnFVCHHH.js";
|
|
12
|
+
import { _ as extractLocationData, a as mayContainWhatsAppOutboundMention, b as extractText, c as DisconnectReason, d as normalizeMessageContent, f as resolveInboundMediaMimetype, g as extractExternalAdReplyContext, 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 extractMediaPlaceholder, x as hasInboundUserContent, y as extractMentionedJids } from "./send-api-89SE5WKV.js";
|
|
13
|
+
import { r as waitForWaConnection, t as createWaSocket } from "./session-BW8RcCcb.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-BDuM0Kc7.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";
|
|
@@ -23,11 +23,11 @@ import { getChildLogger } from "openclaw/plugin-sdk/logging-core";
|
|
|
23
23
|
import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
24
24
|
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";
|
|
25
25
|
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
|
|
26
|
+
import { asDateTimestampMs, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
26
27
|
import { LocalMediaAccessError, getDefaultLocalRoots, loadWebMedia as loadWebMedia$1, loadWebMediaRaw, optimizeImageToJpeg, optimizeImageToPng } from "openclaw/plugin-sdk/web-media";
|
|
27
28
|
import { chunkMarkdownTextWithMode } from "openclaw/plugin-sdk/reply-chunking";
|
|
28
29
|
import { isReasoningReplyPayload, resolveSendableOutboundReplyParts, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
|
|
29
30
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, DEFAULT_MAIN_KEY, buildAgentMainSessionKey, buildAgentSessionKey, buildGroupHistoryKey, deriveLastRoutePolicy, normalizeAccountId as normalizeAccountId$1, normalizeAgentId, resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
30
|
-
import { asDateTimestampMs, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
31
31
|
import { recordInboundSession } from "openclaw/plugin-sdk/conversation-runtime";
|
|
32
32
|
import { loadSessionStore, resolveStorePath, updateLastRoute, updateSessionStore } from "openclaw/plugin-sdk/session-store-runtime";
|
|
33
33
|
import { buildChannelInboundEventContext, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundEnvelope as formatInboundEnvelope$1, formatLocationText, hasVisibleInboundReplyDispatch, resolveInboundSessionEnvelopeContext, runChannelInboundEvent, toInboundMediaFacts, toLocationContext } from "openclaw/plugin-sdk/channel-inbound";
|
|
@@ -110,7 +110,7 @@ function setMediaField(msg, key, value) {
|
|
|
110
110
|
if (value === void 0 && !msg.payload.media) return;
|
|
111
111
|
ensureMedia(msg)[key] = value;
|
|
112
112
|
}
|
|
113
|
-
function
|
|
113
|
+
function defineDeprecatedAccessors(msg, descriptors) {
|
|
114
114
|
Object.defineProperties(msg, Object.fromEntries(Object.entries(descriptors).map(([key, descriptor]) => [key, {
|
|
115
115
|
configurable: true,
|
|
116
116
|
enumerable: true,
|
|
@@ -119,8 +119,62 @@ function defineDeprecatedAliasAccessors(msg, descriptors) {
|
|
|
119
119
|
}])));
|
|
120
120
|
return msg;
|
|
121
121
|
}
|
|
122
|
+
function defineDeprecatedAliasAccessors(msg, descriptors) {
|
|
123
|
+
defineDeprecatedAccessors(msg, descriptors);
|
|
124
|
+
return msg;
|
|
125
|
+
}
|
|
126
|
+
function defineDeprecatedAdmissionTopLevelAccessors(msg) {
|
|
127
|
+
let fallbackConversationId = msg.conversationId || msg.from;
|
|
128
|
+
let fallbackAccountId = msg.accountId;
|
|
129
|
+
let fallbackAccessControlPassed = msg.accessControlPassed;
|
|
130
|
+
let fallbackChatType = msg.chatType;
|
|
131
|
+
const conversationId = () => msg.admission?.conversation.id ?? fallbackConversationId;
|
|
132
|
+
const setConversationId = (value) => {
|
|
133
|
+
const next = value;
|
|
134
|
+
fallbackConversationId = next;
|
|
135
|
+
if (msg.admission) {
|
|
136
|
+
msg.admission.conversation.id = next;
|
|
137
|
+
msg.admission.conversation.groupSessionId = resolveWhatsAppGroupConversationId(next);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
return defineDeprecatedAccessors(msg, {
|
|
141
|
+
from: {
|
|
142
|
+
get: conversationId,
|
|
143
|
+
set: setConversationId
|
|
144
|
+
},
|
|
145
|
+
conversationId: {
|
|
146
|
+
get: conversationId,
|
|
147
|
+
set: setConversationId
|
|
148
|
+
},
|
|
149
|
+
accountId: {
|
|
150
|
+
get: () => msg.admission?.accountId ?? fallbackAccountId,
|
|
151
|
+
set: (value) => {
|
|
152
|
+
const next = value;
|
|
153
|
+
fallbackAccountId = next;
|
|
154
|
+
if (msg.admission) {
|
|
155
|
+
msg.admission.accountId = next;
|
|
156
|
+
msg.admission.account.accountId = next;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
accessControlPassed: {
|
|
161
|
+
get: () => msg.admission ? msg.admission.ingress.decision === "allow" : fallbackAccessControlPassed,
|
|
162
|
+
set: (value) => {
|
|
163
|
+
fallbackAccessControlPassed = value;
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
chatType: {
|
|
167
|
+
get: () => msg.admission?.conversation.kind ?? fallbackChatType,
|
|
168
|
+
set: (value) => {
|
|
169
|
+
const next = value;
|
|
170
|
+
fallbackChatType = next;
|
|
171
|
+
if (msg.admission) msg.admission.conversation.kind = next;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
122
176
|
function withDeprecatedWebInboundMessageFlatAliases(msg) {
|
|
123
|
-
return defineDeprecatedAliasAccessors(msg, {
|
|
177
|
+
return defineDeprecatedAliasAccessors(defineDeprecatedAdmissionTopLevelAccessors(msg), {
|
|
124
178
|
id: {
|
|
125
179
|
get: () => msg.event.id,
|
|
126
180
|
set: (value) => msg.event.id = value
|
|
@@ -284,6 +338,7 @@ function normalizeLegacyFlatWebInboundMessage(msg) {
|
|
|
284
338
|
} : void 0;
|
|
285
339
|
return withDeprecatedWebInboundMessageFlatAliases({
|
|
286
340
|
...msg,
|
|
341
|
+
admission: msg.admission ?? buildDeprecatedFlatWhatsAppInboundAdmission(msg),
|
|
287
342
|
event: {
|
|
288
343
|
id: msg.id,
|
|
289
344
|
timestamp: msg.timestamp,
|
|
@@ -571,6 +626,7 @@ function recordAcceptedInboundActivity(accountId) {
|
|
|
571
626
|
});
|
|
572
627
|
}
|
|
573
628
|
function isRetryableSendDisconnectError(err) {
|
|
629
|
+
if (isWhatsAppSocketOperationTimeoutError(err)) return false;
|
|
574
630
|
return /closed|reset|timed\s*out|disconnect|no active socket/i.test(formatError(err));
|
|
575
631
|
}
|
|
576
632
|
function shouldClearSocketRefAfterSendFailure(err) {
|
|
@@ -588,6 +644,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
588
644
|
const shouldRetryDisconnect = () => options.shouldRetryDisconnect?.() === true;
|
|
589
645
|
const disconnectRetryPolicy = options.disconnectRetryPolicy ?? DEFAULT_RECONNECT_POLICY;
|
|
590
646
|
const sendRetryMaxAttempts = disconnectRetryPolicy.maxAttempts > 0 ? disconnectRetryPolicy.maxAttempts : DEFAULT_RECONNECT_POLICY.maxAttempts;
|
|
647
|
+
const sendOperationTimeoutMs = resolveWhatsAppSocketOperationTimeoutMs(options.socketTiming.defaultQueryTimeoutMs);
|
|
591
648
|
let onCloseResolve = null;
|
|
592
649
|
const onClose = new Promise((resolve) => {
|
|
593
650
|
onCloseResolve = resolve;
|
|
@@ -600,7 +657,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
600
657
|
};
|
|
601
658
|
const presence = options.selfChatMode ? "unavailable" : "available";
|
|
602
659
|
try {
|
|
603
|
-
await sock.sendPresenceUpdate(presence);
|
|
660
|
+
await createWhatsAppSocketOperationTimeoutAdapter(sock, sendOperationTimeoutMs).sendPresenceUpdate(presence);
|
|
604
661
|
logWhatsAppVerbose(options.verbose, `Sent global '${presence}' presence on connect`);
|
|
605
662
|
} catch (err) {
|
|
606
663
|
logWhatsAppVerbose(options.verbose, `Failed to send '${presence}' presence on connect: ${String(err)}`);
|
|
@@ -623,11 +680,11 @@ async function attachWebInboxToSocket(options) {
|
|
|
623
680
|
const pendingDebounceKeys = /* @__PURE__ */ new Set();
|
|
624
681
|
const activeInboundFlushes = /* @__PURE__ */ new Set();
|
|
625
682
|
const buildInboundDebounceKey = (msg) => {
|
|
683
|
+
const admission = requireWhatsAppInboundAdmission(msg);
|
|
626
684
|
const sender = msg.platform.sender;
|
|
627
|
-
const senderKey =
|
|
685
|
+
const senderKey = admission.conversation.kind === "group" ? getPrimaryIdentityId(sender ?? null) ?? msg.platform.senderJid ?? msg.platform.senderE164 ?? msg.platform.senderName ?? admission.sender.id : admission.conversation.id;
|
|
628
686
|
if (!senderKey) return null;
|
|
629
|
-
|
|
630
|
-
return `${msg.accountId}:${conversationKey}:${senderKey}`;
|
|
687
|
+
return `${admission.accountId}:${admission.conversation.id}:${senderKey}`;
|
|
631
688
|
};
|
|
632
689
|
const shouldDebounceInboundMessage = (msg) => options.shouldDebounce?.(msg) ?? true;
|
|
633
690
|
const orderDebouncedInboundEntries = (entries) => entries.toSorted((a, b) => {
|
|
@@ -723,12 +780,19 @@ async function attachWebInboxToSocket(options) {
|
|
|
723
780
|
messageId
|
|
724
781
|
});
|
|
725
782
|
};
|
|
783
|
+
const trackLateAcceptedSend = (jid, promise) => {
|
|
784
|
+
promise.then((result) => {
|
|
785
|
+
rememberOutboundMessage(jid, result);
|
|
786
|
+
}, () => {});
|
|
787
|
+
};
|
|
726
788
|
const sendTrackedMessage = async (jid, content, sendOptions) => {
|
|
727
789
|
let lastErr = /* @__PURE__ */ new Error(RECONNECT_IN_PROGRESS_ERROR);
|
|
728
790
|
for (let attempt = 1;; attempt++) {
|
|
729
791
|
const currentSock = getCurrentSock();
|
|
730
792
|
if (currentSock) try {
|
|
731
|
-
const result =
|
|
793
|
+
const result = await createWhatsAppSocketOperationTimeoutAdapter(currentSock, sendOperationTimeoutMs, { onSendMessageTimeout: ({ jid: timedOutJid, promise }) => {
|
|
794
|
+
trackLateAcceptedSend(timedOutJid, promise);
|
|
795
|
+
} }).sendMessage(jid, content, sendOptions);
|
|
732
796
|
rememberOutboundMessage(jid, result);
|
|
733
797
|
return result;
|
|
734
798
|
} catch (err) {
|
|
@@ -747,6 +811,14 @@ async function attachWebInboxToSocket(options) {
|
|
|
747
811
|
}
|
|
748
812
|
}
|
|
749
813
|
};
|
|
814
|
+
const sendApiSocketOperations = {
|
|
815
|
+
sendMessage: (jid, content, sendOptions) => sendTrackedMessage(jid, content, sendOptions),
|
|
816
|
+
sendPresenceUpdate: async (presenceLocal, jid) => {
|
|
817
|
+
const currentSock = getCurrentSock();
|
|
818
|
+
if (!currentSock) throw new Error(RECONNECT_IN_PROGRESS_ERROR);
|
|
819
|
+
return await createWhatsAppSocketOperationTimeoutAdapter(currentSock, sendOperationTimeoutMs).sendPresenceUpdate(presenceLocal, jid);
|
|
820
|
+
}
|
|
821
|
+
};
|
|
750
822
|
const summarizeGroupMeta = async (meta) => {
|
|
751
823
|
const participantEntries = await Promise.all(meta.participants?.map(async (p) => {
|
|
752
824
|
const mapped = await resolveInboundJid(p.id);
|
|
@@ -858,6 +930,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
858
930
|
from,
|
|
859
931
|
selfE164: self.e164 ?? null,
|
|
860
932
|
senderE164,
|
|
933
|
+
senderJid: participantJid,
|
|
861
934
|
group,
|
|
862
935
|
pushName: msg.pushName ?? void 0,
|
|
863
936
|
isFromMe: Boolean(msg.key?.fromMe),
|
|
@@ -890,12 +963,12 @@ async function attachWebInboxToSocket(options) {
|
|
|
890
963
|
if (!target || options.sendReadReceipts === false) return;
|
|
891
964
|
const { id, remoteJid, participant } = target;
|
|
892
965
|
try {
|
|
893
|
-
await (getCurrentSock() ?? sock).readMessages([{
|
|
966
|
+
await withWhatsAppSocketOperationTimeout("readMessages", (getCurrentSock() ?? sock).readMessages([{
|
|
894
967
|
remoteJid,
|
|
895
968
|
id,
|
|
896
969
|
participant,
|
|
897
970
|
fromMe: false
|
|
898
|
-
}]);
|
|
971
|
+
}]), sendOperationTimeoutMs);
|
|
899
972
|
const suffix = participant ? ` (participant ${participant})` : "";
|
|
900
973
|
logWhatsAppVerbose(options.verbose, `Marked message ${id} as read for ${remoteJid}${suffix}`);
|
|
901
974
|
} catch (err) {
|
|
@@ -905,14 +978,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
905
978
|
const maybeLogSkippedSelfChatReadReceipt = (inbound, target) => {
|
|
906
979
|
if (target?.id && inbound.access.isSelfChat && options.verbose) logWhatsAppVerbose(options.verbose, `Self-chat mode: skipping read receipt for ${target.id}`);
|
|
907
980
|
};
|
|
908
|
-
const
|
|
909
|
-
if (inbound.access.isSelfChat) {
|
|
910
|
-
maybeLogSkippedSelfChatReadReceipt(inbound, target);
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
await maybeMarkInboundAsRead(target);
|
|
914
|
-
};
|
|
915
|
-
const maybeMarkReadReceiptForSkippedAppend = async (inbound, target) => {
|
|
981
|
+
const maybeMarkNonSelfChatReadReceipt = async (inbound, target) => {
|
|
916
982
|
if (inbound.access.isSelfChat) {
|
|
917
983
|
maybeLogSkippedSelfChatReadReceipt(inbound, target);
|
|
918
984
|
return;
|
|
@@ -943,7 +1009,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
943
1009
|
const readReceipt = stored?.metadata?.readReceipt ?? buildReadReceiptTarget(inbound);
|
|
944
1010
|
const deliveryReadReceipt = inbound.access.isSelfChat ? void 0 : readReceipt;
|
|
945
1011
|
if (!stored && shouldSkipStaleAppend(msg, upsertType)) {
|
|
946
|
-
await
|
|
1012
|
+
await maybeMarkNonSelfChatReadReceipt(inbound, readReceipt);
|
|
947
1013
|
return;
|
|
948
1014
|
}
|
|
949
1015
|
let durableId = stored?.id ?? (inbound.id ? createWhatsAppDurableInboundMessageId({
|
|
@@ -957,7 +1023,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
957
1023
|
receivedAt: inbound.messageTimestampMs
|
|
958
1024
|
});
|
|
959
1025
|
if (accepted.kind === "completed") {
|
|
960
|
-
await
|
|
1026
|
+
await maybeMarkNonSelfChatReadReceipt(inbound, accepted.record.metadata?.readReceipt ?? deliveryReadReceipt);
|
|
961
1027
|
return;
|
|
962
1028
|
}
|
|
963
1029
|
if (accepted.kind === "pending" && accepted.record.attempts === 0) return;
|
|
@@ -970,7 +1036,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
970
1036
|
const enriched = await enrichInboundMessage(msg);
|
|
971
1037
|
if (!enriched) {
|
|
972
1038
|
await completeUndeliverableDurableInbound(durableId, durableMetadata);
|
|
973
|
-
await
|
|
1039
|
+
await maybeMarkNonSelfChatReadReceipt(inbound, deliveryReadReceipt);
|
|
974
1040
|
return;
|
|
975
1041
|
}
|
|
976
1042
|
const dedupeKey = inbound.id ? `${options.accountId}:${inbound.remoteJid}:${inbound.id}` : "";
|
|
@@ -978,7 +1044,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
978
1044
|
if (dedupeClaim !== "claimed") {
|
|
979
1045
|
if (dedupeClaim === "duplicate") {
|
|
980
1046
|
await completeUndeliverableDurableInbound(durableId, durableMetadata);
|
|
981
|
-
await
|
|
1047
|
+
await maybeMarkNonSelfChatReadReceipt(inbound, deliveryReadReceipt);
|
|
982
1048
|
}
|
|
983
1049
|
return;
|
|
984
1050
|
}
|
|
@@ -1001,6 +1067,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1001
1067
|
const location = extractLocationData(msg.message ?? void 0);
|
|
1002
1068
|
const locationText = location ? formatLocationText(location) : void 0;
|
|
1003
1069
|
const contactContext = extractContactContext(msg.message ?? void 0);
|
|
1070
|
+
const externalAdReplyContext = extractExternalAdReplyContext(msg.message ?? void 0);
|
|
1004
1071
|
let body = extractText(msg.message ?? void 0);
|
|
1005
1072
|
if (locationText) body = [body, locationText].filter(Boolean).join("\n").trim();
|
|
1006
1073
|
if (!body) {
|
|
@@ -1028,6 +1095,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1028
1095
|
body,
|
|
1029
1096
|
location: location ?? void 0,
|
|
1030
1097
|
contactContext,
|
|
1098
|
+
externalAdReplyContext,
|
|
1031
1099
|
replyContext,
|
|
1032
1100
|
mediaPath,
|
|
1033
1101
|
mediaType,
|
|
@@ -1037,10 +1105,9 @@ async function attachWebInboxToSocket(options) {
|
|
|
1037
1105
|
const enqueueInboundMessage = async (msg, inbound, enriched, durable) => {
|
|
1038
1106
|
const chatJid = inbound.remoteJid;
|
|
1039
1107
|
const sendComposing = async () => {
|
|
1040
|
-
|
|
1041
|
-
if (!currentSock) return;
|
|
1108
|
+
if (!getCurrentSock()) return;
|
|
1042
1109
|
try {
|
|
1043
|
-
await
|
|
1110
|
+
await sendApiSocketOperations.sendPresenceUpdate("composing", chatJid);
|
|
1044
1111
|
} catch (err) {
|
|
1045
1112
|
logWhatsAppVerbose(options.verbose, `Presence update failed: ${String(err)}`);
|
|
1046
1113
|
}
|
|
@@ -1075,7 +1142,19 @@ async function attachWebInboxToSocket(options) {
|
|
|
1075
1142
|
participants: inbound.groupParticipants,
|
|
1076
1143
|
mentions: groupMentions
|
|
1077
1144
|
} : void 0;
|
|
1145
|
+
const untrustedStructuredContext = [...enriched.contactContext ? [{
|
|
1146
|
+
label: "WhatsApp contact",
|
|
1147
|
+
source: "whatsapp",
|
|
1148
|
+
type: enriched.contactContext.kind,
|
|
1149
|
+
payload: enriched.contactContext
|
|
1150
|
+
}] : [], ...enriched.externalAdReplyContext ? [{
|
|
1151
|
+
label: "WhatsApp external ad reply",
|
|
1152
|
+
source: "whatsapp",
|
|
1153
|
+
type: "external_ad_reply",
|
|
1154
|
+
payload: enriched.externalAdReplyContext
|
|
1155
|
+
}] : []];
|
|
1078
1156
|
const inboundMessage = withDeprecatedWebInboundMessageFlatAliases({
|
|
1157
|
+
admission: inbound.access.admission,
|
|
1079
1158
|
event: {
|
|
1080
1159
|
id: inbound.id,
|
|
1081
1160
|
timestamp
|
|
@@ -1083,12 +1162,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1083
1162
|
payload: {
|
|
1084
1163
|
body: enriched.body,
|
|
1085
1164
|
location: enriched.location ?? void 0,
|
|
1086
|
-
untrustedStructuredContext:
|
|
1087
|
-
label: "WhatsApp contact",
|
|
1088
|
-
source: "whatsapp",
|
|
1089
|
-
type: enriched.contactContext.kind,
|
|
1090
|
-
payload: enriched.contactContext
|
|
1091
|
-
}] : void 0,
|
|
1165
|
+
untrustedStructuredContext: untrustedStructuredContext.length > 0 ? untrustedStructuredContext : void 0,
|
|
1092
1166
|
media
|
|
1093
1167
|
},
|
|
1094
1168
|
platform: {
|
|
@@ -1112,11 +1186,6 @@ async function attachWebInboxToSocket(options) {
|
|
|
1112
1186
|
reply,
|
|
1113
1187
|
sendMedia
|
|
1114
1188
|
},
|
|
1115
|
-
from: inbound.from,
|
|
1116
|
-
conversationId: inbound.from,
|
|
1117
|
-
accountId: inbound.access.resolvedAccountId,
|
|
1118
|
-
accessControlPassed: true,
|
|
1119
|
-
chatType: inbound.group ? "group" : "direct",
|
|
1120
1189
|
quote: enriched.replyContext ? {
|
|
1121
1190
|
context: enriched.replyContext,
|
|
1122
1191
|
id: enriched.replyContext.id,
|
|
@@ -1138,12 +1207,15 @@ async function attachWebInboxToSocket(options) {
|
|
|
1138
1207
|
inboundMessage.debounceKey = debounceKey;
|
|
1139
1208
|
if (inboundDebounceMs > 0 && shouldDebounceInboundMessage(inboundMessage)) pendingDebounceKeys.add(debounceKey);
|
|
1140
1209
|
}
|
|
1141
|
-
if (inboundMessage.event.id)
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1210
|
+
if (inboundMessage.event.id) {
|
|
1211
|
+
const admission = requireWhatsAppInboundAdmission(inboundMessage);
|
|
1212
|
+
cacheInboundMessageMeta(admission.accountId, inboundMessage.platform.chatJid, inboundMessage.event.id, {
|
|
1213
|
+
participant: inboundMessage.platform.senderJid,
|
|
1214
|
+
participantE164: admission.conversation.kind === "direct" ? inboundMessage.platform.senderE164 : void 0,
|
|
1215
|
+
body: inboundMessage.payload.body,
|
|
1216
|
+
fromMe: inboundMessage.platform.fromMe
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1147
1219
|
try {
|
|
1148
1220
|
Promise.resolve(debouncer.enqueue(inboundMessage)).catch((err) => {
|
|
1149
1221
|
inboundLogger.error({ error: String(err) }, "failed handling inbound web message");
|
|
@@ -1254,14 +1326,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1254
1326
|
}
|
|
1255
1327
|
})();
|
|
1256
1328
|
const sendApi = createWebSendApi({
|
|
1257
|
-
sock:
|
|
1258
|
-
sendMessage: (jid, content, optionsLocal) => sendTrackedMessage(jid, content, optionsLocal),
|
|
1259
|
-
sendPresenceUpdate: async (presenceLocal, jid) => {
|
|
1260
|
-
const currentSock = getCurrentSock();
|
|
1261
|
-
if (!currentSock) throw new Error(RECONNECT_IN_PROGRESS_ERROR);
|
|
1262
|
-
return currentSock.sendPresenceUpdate(presenceLocal, jid);
|
|
1263
|
-
}
|
|
1264
|
-
},
|
|
1329
|
+
sock: sendApiSocketOperations,
|
|
1265
1330
|
defaultAccountId: options.accountId,
|
|
1266
1331
|
resolveOutboundMentions: ({ jid, text }) => resolveOutboundMentionsForGroup(jid, text),
|
|
1267
1332
|
authDir: options.authDir
|
|
@@ -1296,7 +1361,7 @@ async function attachWebInboxToSocket(options) {
|
|
|
1296
1361
|
};
|
|
1297
1362
|
}
|
|
1298
1363
|
async function monitorWebInbox(options) {
|
|
1299
|
-
const socketTiming = resolveWhatsAppSocketTiming(options.cfg);
|
|
1364
|
+
const socketTiming = options.socketTiming ?? resolveWhatsAppSocketTiming(options.cfg);
|
|
1300
1365
|
const sock = await createWaSocket(false, options.verbose, {
|
|
1301
1366
|
authDir: options.authDir,
|
|
1302
1367
|
...socketTiming
|
|
@@ -1308,12 +1373,14 @@ async function monitorWebInbox(options) {
|
|
|
1308
1373
|
throw err;
|
|
1309
1374
|
}
|
|
1310
1375
|
const shouldDebounce = options.shouldDebounce;
|
|
1376
|
+
const normalizeAdmittedWebInboundMessage = (msg) => requireAdmittedWhatsAppInboundMessage(normalizeWebInboundMessage(msg));
|
|
1311
1377
|
return attachWebInboxToSocket({
|
|
1312
1378
|
...options,
|
|
1313
1379
|
onMessage: async (msg) => {
|
|
1314
|
-
await options.onMessage(
|
|
1380
|
+
await options.onMessage(normalizeAdmittedWebInboundMessage(msg));
|
|
1315
1381
|
},
|
|
1316
|
-
shouldDebounce: shouldDebounce ? (msg) => shouldDebounce(
|
|
1382
|
+
shouldDebounce: shouldDebounce ? (msg) => shouldDebounce(normalizeAdmittedWebInboundMessage(msg)) : void 0,
|
|
1383
|
+
socketTiming,
|
|
1317
1384
|
sock
|
|
1318
1385
|
});
|
|
1319
1386
|
}
|
|
@@ -1340,7 +1407,7 @@ function resolveMentionTargets(msg, authDir) {
|
|
|
1340
1407
|
function isBotMentionedFromTargets(msg, mentionCfg, targets) {
|
|
1341
1408
|
const clean = (text) => normalizeMentionText(text);
|
|
1342
1409
|
const explicitSelfChatOverride = typeof mentionCfg.isSelfChat === "boolean";
|
|
1343
|
-
const isGroupConversation =
|
|
1410
|
+
const isGroupConversation = requireWhatsAppInboundAdmission(msg).conversation.kind === "group";
|
|
1344
1411
|
const isSelfChat = explicitSelfChatOverride ? Boolean(mentionCfg.isSelfChat) : isSelfChatMode(targets.self.e164, mentionCfg.allowFrom) && !isGroupConversation;
|
|
1345
1412
|
const hasMentions = targets.normalizedMentions.length > 0;
|
|
1346
1413
|
if (hasMentions && !isSelfChat) {
|
|
@@ -1364,7 +1431,7 @@ function debugMention(msg, mentionCfg, authDir) {
|
|
|
1364
1431
|
return {
|
|
1365
1432
|
wasMentioned: isBotMentionedFromTargets(msg, mentionCfg, mentionTargets),
|
|
1366
1433
|
details: {
|
|
1367
|
-
from: msg.
|
|
1434
|
+
from: requireWhatsAppInboundAdmission(msg).conversation.id,
|
|
1368
1435
|
body: msg.payload.body,
|
|
1369
1436
|
bodyClean: normalizeMentionText(msg.payload.body),
|
|
1370
1437
|
mentionedJids: msg.group?.mentions?.jids ?? null,
|
|
@@ -1582,9 +1649,11 @@ async function resolveGroupActivationFor(params) {
|
|
|
1582
1649
|
//#region extensions/whatsapp/src/auto-reply/monitor/ack-reaction.ts
|
|
1583
1650
|
async function maybeSendAckReaction(params) {
|
|
1584
1651
|
if (!params.msg.event.id) return null;
|
|
1652
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
1653
|
+
const accountId = admission.accountId;
|
|
1585
1654
|
if (resolveWhatsAppReactionLevel({
|
|
1586
1655
|
cfg: params.cfg,
|
|
1587
|
-
accountId
|
|
1656
|
+
accountId
|
|
1588
1657
|
}).level === "off") return null;
|
|
1589
1658
|
const ackConfig = params.cfg.channels?.whatsapp?.ackReaction;
|
|
1590
1659
|
const emoji = resolveWhatsAppAckEmoji({
|
|
@@ -1594,18 +1663,19 @@ async function maybeSendAckReaction(params) {
|
|
|
1594
1663
|
});
|
|
1595
1664
|
const directEnabled = ackConfig?.direct ?? true;
|
|
1596
1665
|
const groupMode = ackConfig?.group ?? "mentions";
|
|
1597
|
-
const
|
|
1598
|
-
const
|
|
1666
|
+
const isGroup = admission.conversation.kind === "group";
|
|
1667
|
+
const conversationIdForCheck = admission.conversation.id;
|
|
1668
|
+
const activation = isGroup ? await resolveGroupActivationFor({
|
|
1599
1669
|
cfg: params.cfg,
|
|
1600
|
-
accountId
|
|
1670
|
+
accountId,
|
|
1601
1671
|
agentId: params.agentId,
|
|
1602
1672
|
sessionKey: params.sessionKey,
|
|
1603
1673
|
conversationId: conversationIdForCheck
|
|
1604
1674
|
}) : null;
|
|
1605
1675
|
const shouldSendReaction = () => shouldAckReactionForWhatsApp({
|
|
1606
1676
|
emoji,
|
|
1607
|
-
isDirect:
|
|
1608
|
-
isGroup
|
|
1677
|
+
isDirect: admission.conversation.kind === "direct",
|
|
1678
|
+
isGroup,
|
|
1609
1679
|
directEnabled,
|
|
1610
1680
|
groupMode,
|
|
1611
1681
|
wasMentioned: params.msg.wasMentioned === true,
|
|
@@ -1622,7 +1692,7 @@ async function maybeSendAckReaction(params) {
|
|
|
1622
1692
|
verbose: params.verbose,
|
|
1623
1693
|
fromMe: false,
|
|
1624
1694
|
...sender.jid ? { participant: sender.jid } : {},
|
|
1625
|
-
|
|
1695
|
+
accountId,
|
|
1626
1696
|
cfg: params.cfg
|
|
1627
1697
|
};
|
|
1628
1698
|
return createAckReactionHandle({
|
|
@@ -1642,12 +1712,13 @@ async function maybeSendAckReaction(params) {
|
|
|
1642
1712
|
//#endregion
|
|
1643
1713
|
//#region extensions/whatsapp/src/auto-reply/monitor/broadcast.ts
|
|
1644
1714
|
function buildBroadcastRouteKeys(params) {
|
|
1715
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
1645
1716
|
const sessionKey = buildAgentSessionKey({
|
|
1646
1717
|
agentId: params.agentId,
|
|
1647
1718
|
channel: "whatsapp",
|
|
1648
1719
|
accountId: params.route.accountId,
|
|
1649
1720
|
peer: {
|
|
1650
|
-
kind:
|
|
1721
|
+
kind: admission.conversation.kind,
|
|
1651
1722
|
id: params.peerId
|
|
1652
1723
|
},
|
|
1653
1724
|
dmScope: params.cfg.session?.dmScope,
|
|
@@ -1674,7 +1745,8 @@ async function maybeBroadcastMessage(params) {
|
|
|
1674
1745
|
whatsappInboundLog.info(`Broadcasting message to ${broadcastAgents.length} agents (${strategy})`);
|
|
1675
1746
|
const agentIds = params.cfg.agents?.list?.map((agent) => normalizeAgentId(agent.id));
|
|
1676
1747
|
const hasKnownAgents = (agentIds?.length ?? 0) > 0;
|
|
1677
|
-
const
|
|
1748
|
+
const isGroupConversation = requireWhatsAppInboundAdmission(params.msg).conversation.kind === "group";
|
|
1749
|
+
const groupHistorySnapshot = isGroupConversation ? params.groupHistories.get(params.groupHistoryKey) ?? [] : void 0;
|
|
1678
1750
|
const processForAgent = async (agentId) => {
|
|
1679
1751
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
1680
1752
|
if (hasKnownAgents && !agentIds?.includes(normalizedAgentId)) {
|
|
@@ -1693,7 +1765,7 @@ async function maybeBroadcastMessage(params) {
|
|
|
1693
1765
|
agentId: normalizedAgentId,
|
|
1694
1766
|
...routeKeys
|
|
1695
1767
|
};
|
|
1696
|
-
const agentRoute =
|
|
1768
|
+
const agentRoute = isGroupConversation ? resolveWhatsAppGroupSessionRoute(baseAgentRoute) : baseAgentRoute;
|
|
1697
1769
|
try {
|
|
1698
1770
|
const opts = {
|
|
1699
1771
|
groupHistory: groupHistorySnapshot,
|
|
@@ -1710,7 +1782,7 @@ async function maybeBroadcastMessage(params) {
|
|
|
1710
1782
|
};
|
|
1711
1783
|
if (strategy === "sequential") for (const agentId of broadcastAgents) await processForAgent(agentId);
|
|
1712
1784
|
else await Promise.allSettled(broadcastAgents.map(processForAgent));
|
|
1713
|
-
if (
|
|
1785
|
+
if (isGroupConversation) params.groupHistories.set(params.groupHistoryKey, []);
|
|
1714
1786
|
return true;
|
|
1715
1787
|
}
|
|
1716
1788
|
//#endregion
|
|
@@ -1812,26 +1884,28 @@ function skipGroupMessageAndStoreHistory(params, verboseMessage, body) {
|
|
|
1812
1884
|
async function applyGroupGating(params) {
|
|
1813
1885
|
const sender = getSenderIdentity(params.msg);
|
|
1814
1886
|
const self = getSelfIdentity(params.msg, params.authDir);
|
|
1887
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
1888
|
+
const conversationId = admission.conversation.id;
|
|
1815
1889
|
const inboundPolicy = resolveWhatsAppInboundPolicy({
|
|
1816
1890
|
cfg: params.cfg,
|
|
1817
|
-
accountId:
|
|
1891
|
+
accountId: admission.accountId,
|
|
1818
1892
|
selfE164: self.e164 ?? null
|
|
1819
1893
|
});
|
|
1820
|
-
const conversationGroupPolicy = inboundPolicy.resolveConversationGroupPolicy(
|
|
1894
|
+
const conversationGroupPolicy = inboundPolicy.resolveConversationGroupPolicy(conversationId);
|
|
1821
1895
|
if (conversationGroupPolicy.allowlistEnabled && !conversationGroupPolicy.allowed) {
|
|
1822
1896
|
const accountId = inboundPolicy.account.accountId;
|
|
1823
|
-
if (shouldWarnForGroupDrop(`${accountId}:${
|
|
1897
|
+
if (shouldWarnForGroupDrop(`${accountId}:${conversationId}`)) {
|
|
1824
1898
|
const groupsPath = resolveWhatsAppGroupsConfigPath({
|
|
1825
1899
|
cfg: params.cfg,
|
|
1826
1900
|
accountId
|
|
1827
1901
|
});
|
|
1828
1902
|
params.replyLogger.warn({
|
|
1829
|
-
conversationId
|
|
1903
|
+
conversationId,
|
|
1830
1904
|
accountId,
|
|
1831
1905
|
groupsPath
|
|
1832
|
-
}, `WhatsApp group ${
|
|
1906
|
+
}, `WhatsApp group ${conversationId} not in ${groupsPath} — inbound dropped. Add the group JID to ${groupsPath} (or add "*" there to admit all groups). Sender authorization still applies.`);
|
|
1833
1907
|
}
|
|
1834
|
-
params.logVerbose(`Dropping message from unregistered WhatsApp group ${
|
|
1908
|
+
params.logVerbose(`Dropping message from unregistered WhatsApp group ${conversationId}. Add the group JID to channels.whatsapp.groups, or add "*" there to admit all groups. Sender authorization still applies.`);
|
|
1835
1909
|
return { shouldProcess: false };
|
|
1836
1910
|
}
|
|
1837
1911
|
noteGroupMember(params.groupMemberNames, params.groupHistoryKey, sender.e164 ?? void 0, sender.name ?? void 0);
|
|
@@ -1842,7 +1916,7 @@ async function applyGroupGating(params) {
|
|
|
1842
1916
|
const mentionConfig = {
|
|
1843
1917
|
...buildMentionConfig(params.cfg, params.agentId, {
|
|
1844
1918
|
provider: "whatsapp",
|
|
1845
|
-
conversationId
|
|
1919
|
+
conversationId,
|
|
1846
1920
|
providerPolicy: params.providerMentionPatterns
|
|
1847
1921
|
}),
|
|
1848
1922
|
allowFrom: inboundPolicy.configuredAllowFrom
|
|
@@ -1858,10 +1932,10 @@ async function applyGroupGating(params) {
|
|
|
1858
1932
|
const activationCommand = parseActivationCommand(commandBody);
|
|
1859
1933
|
const owner = isOwnerSender(baseMentionConfig, params.msg);
|
|
1860
1934
|
const shouldBypassMention = owner && hasControlCommand(commandBody, params.cfg);
|
|
1861
|
-
if (activationCommand.hasCommand && !owner) return skipGroupMessageAndStoreHistory(params, `Ignoring /activation from non-owner in group ${
|
|
1935
|
+
if (activationCommand.hasCommand && !owner) return skipGroupMessageAndStoreHistory(params, `Ignoring /activation from non-owner in group ${conversationId}`);
|
|
1862
1936
|
const mentionDebug = debugMention(mentionMsg, mentionConfig, params.authDir);
|
|
1863
1937
|
params.replyLogger.debug({
|
|
1864
|
-
conversationId
|
|
1938
|
+
conversationId,
|
|
1865
1939
|
wasMentioned: mentionDebug.wasMentioned,
|
|
1866
1940
|
...mentionDebug.details
|
|
1867
1941
|
}, "group mention debug");
|
|
@@ -1871,7 +1945,7 @@ async function applyGroupGating(params) {
|
|
|
1871
1945
|
accountId: inboundPolicy.account.accountId,
|
|
1872
1946
|
agentId: params.agentId,
|
|
1873
1947
|
sessionKey: params.sessionKey,
|
|
1874
|
-
conversationId
|
|
1948
|
+
conversationId
|
|
1875
1949
|
}) !== "always";
|
|
1876
1950
|
const replyContext = getReplyContext(params.msg, params.authDir);
|
|
1877
1951
|
const mentionDecision = resolveInboundMentionDecision({
|
|
@@ -1892,13 +1966,13 @@ async function applyGroupGating(params) {
|
|
|
1892
1966
|
params.msg.wasMentioned = effectiveWasMentioned;
|
|
1893
1967
|
if (!shouldBypassMention && requireMention && mentionDecision.shouldSkip) {
|
|
1894
1968
|
if (params.deferMissingMention === true) {
|
|
1895
|
-
params.logVerbose(`Deferring group mention skip until audio preflight completes in ${
|
|
1969
|
+
params.logVerbose(`Deferring group mention skip until audio preflight completes in ${conversationId}`);
|
|
1896
1970
|
return {
|
|
1897
1971
|
shouldProcess: false,
|
|
1898
1972
|
needsMentionText: true
|
|
1899
1973
|
};
|
|
1900
1974
|
}
|
|
1901
|
-
return skipGroupMessageAndStoreHistory(params, `Group message stored for context (no mention detected) in ${
|
|
1975
|
+
return skipGroupMessageAndStoreHistory(params, `Group message stored for context (no mention detected) in ${conversationId}: ${mentionMsg.payload.body}`, params.mentionText);
|
|
1902
1976
|
}
|
|
1903
1977
|
return { shouldProcess: true };
|
|
1904
1978
|
}
|
|
@@ -1935,11 +2009,13 @@ function updateLastRouteInBackground(params) {
|
|
|
1935
2009
|
//#endregion
|
|
1936
2010
|
//#region extensions/whatsapp/src/auto-reply/monitor/peer.ts
|
|
1937
2011
|
function resolvePeerId(msg) {
|
|
1938
|
-
|
|
2012
|
+
const admission = requireWhatsAppInboundAdmission(msg);
|
|
2013
|
+
if (admission.conversation.kind === "group") return admission.conversation.id;
|
|
1939
2014
|
const sender = getSenderIdentity(msg);
|
|
1940
2015
|
if (sender.e164) return normalizeE164(sender.e164) ?? sender.e164;
|
|
1941
|
-
|
|
1942
|
-
|
|
2016
|
+
const conversationId = admission.conversation.id;
|
|
2017
|
+
if (conversationId.includes("@")) return jidToE164(conversationId) ?? conversationId;
|
|
2018
|
+
return normalizeE164(conversationId) ?? conversationId;
|
|
1943
2019
|
}
|
|
1944
2020
|
//#endregion
|
|
1945
2021
|
//#region extensions/whatsapp/src/system-prompt.ts
|
|
@@ -2042,6 +2118,9 @@ function createWhatsAppReplyDeliveryReceipt(results) {
|
|
|
2042
2118
|
}
|
|
2043
2119
|
async function deliverWebReply(params) {
|
|
2044
2120
|
const { replyResult, msg, maxMediaBytes, textLimit, replyLogger, connectionId, skipLog } = params;
|
|
2121
|
+
const admission = requireWhatsAppInboundAdmission(msg);
|
|
2122
|
+
const conversationId = admission.conversation.id;
|
|
2123
|
+
const isGroupConversation = admission.conversation.kind === "group";
|
|
2045
2124
|
const replyStarted = Date.now();
|
|
2046
2125
|
const sendResults = [];
|
|
2047
2126
|
const rememberSendResult = (result) => {
|
|
@@ -2055,7 +2134,7 @@ async function deliverWebReply(params) {
|
|
|
2055
2134
|
};
|
|
2056
2135
|
};
|
|
2057
2136
|
if (isReasoningReplyPayload(replyResult)) {
|
|
2058
|
-
whatsappOutboundLog.debug(`Suppressed reasoning payload to ${
|
|
2137
|
+
whatsappOutboundLog.debug(`Suppressed reasoning payload to ${conversationId}`);
|
|
2059
2138
|
return finishDelivery();
|
|
2060
2139
|
}
|
|
2061
2140
|
const tableMode = params.tableMode ?? "code";
|
|
@@ -2065,12 +2144,12 @@ async function deliverWebReply(params) {
|
|
|
2065
2144
|
const mediaList = normalizedReply.mediaUrls ?? [];
|
|
2066
2145
|
const getQuote = () => {
|
|
2067
2146
|
if (!replyResult.replyToId) return;
|
|
2068
|
-
const cached = lookupInboundMessageMeta(
|
|
2147
|
+
const cached = lookupInboundMessageMeta(admission.accountId, msg.platform.chatJid, replyResult.replyToId);
|
|
2069
2148
|
return buildQuotedMessageOptions({
|
|
2070
2149
|
messageId: replyResult.replyToId,
|
|
2071
2150
|
remoteJid: msg.platform.chatJid,
|
|
2072
2151
|
fromMe: cached?.fromMe ?? false,
|
|
2073
|
-
participant: cached?.participant ?? (
|
|
2152
|
+
participant: cached?.participant ?? (isGroupConversation ? msg.platform.senderJid : void 0),
|
|
2074
2153
|
messageText: cached?.body ?? ""
|
|
2075
2154
|
});
|
|
2076
2155
|
};
|
|
@@ -2080,7 +2159,7 @@ async function deliverWebReply(params) {
|
|
|
2080
2159
|
send: fn,
|
|
2081
2160
|
maxAttempts,
|
|
2082
2161
|
onRetry: ({ attempt, maxAttempts: retryMaxAttempts, backoffMs, errorText }) => {
|
|
2083
|
-
logVerbose(`Retrying ${label} to ${
|
|
2162
|
+
logVerbose(`Retrying ${label} to ${conversationId} after failure (${attempt}/${retryMaxAttempts - 1}) in ${backoffMs}ms: ${errorText}`);
|
|
2084
2163
|
}
|
|
2085
2164
|
});
|
|
2086
2165
|
} catch (error) {
|
|
@@ -2096,14 +2175,14 @@ async function deliverWebReply(params) {
|
|
|
2096
2175
|
rememberSendResult(await sendWithRetry(() => msg.platform.reply(chunk, quote), "text"));
|
|
2097
2176
|
if (!skipLog) {
|
|
2098
2177
|
const durationMs = Date.now() - chunkStarted;
|
|
2099
|
-
whatsappOutboundLog.debug(`Sent chunk ${index + 1}/${totalChunks} to ${
|
|
2178
|
+
whatsappOutboundLog.debug(`Sent chunk ${index + 1}/${totalChunks} to ${conversationId} (${durationMs.toFixed(0)}ms)`);
|
|
2100
2179
|
}
|
|
2101
2180
|
}
|
|
2102
2181
|
const delivery = finishDelivery();
|
|
2103
2182
|
const logPayload = {
|
|
2104
2183
|
correlationId: msg.event.id ?? newConnectionId(),
|
|
2105
2184
|
connectionId: connectionId ?? null,
|
|
2106
|
-
to:
|
|
2185
|
+
to: conversationId,
|
|
2107
2186
|
from: msg.platform.recipientJid,
|
|
2108
2187
|
text: elide(replyResult.text, 240),
|
|
2109
2188
|
mediaUrl: null,
|
|
@@ -2159,11 +2238,11 @@ async function deliverWebReply(params) {
|
|
|
2159
2238
|
mimetype: media.mimetype
|
|
2160
2239
|
}, quote), "media:document"));
|
|
2161
2240
|
}
|
|
2162
|
-
whatsappOutboundLog.info(`Sent media reply to ${
|
|
2241
|
+
whatsappOutboundLog.info(`Sent media reply to ${conversationId} (${(media.buffer.length / (1024 * 1024)).toFixed(2)}MB)`);
|
|
2163
2242
|
replyLogger.info({
|
|
2164
2243
|
correlationId: msg.event.id ?? newConnectionId(),
|
|
2165
2244
|
connectionId: connectionId ?? null,
|
|
2166
|
-
to:
|
|
2245
|
+
to: conversationId,
|
|
2167
2246
|
from: msg.platform.recipientJid,
|
|
2168
2247
|
text: caption ?? null,
|
|
2169
2248
|
mediaUrl,
|
|
@@ -2173,15 +2252,19 @@ async function deliverWebReply(params) {
|
|
|
2173
2252
|
}, "auto-reply sent (media)");
|
|
2174
2253
|
},
|
|
2175
2254
|
onError: async ({ error, mediaUrl, caption, isFirst }) => {
|
|
2176
|
-
whatsappOutboundLog.error(`Failed sending web media to ${
|
|
2255
|
+
whatsappOutboundLog.error(`Failed sending web media to ${conversationId}: ${formatError(error)}`);
|
|
2177
2256
|
replyLogger.warn({
|
|
2178
2257
|
err: error,
|
|
2179
2258
|
mediaUrl
|
|
2180
2259
|
}, "failed to send web media reply");
|
|
2181
|
-
if (!isFirst)
|
|
2182
|
-
|
|
2260
|
+
if (!isFirst) {
|
|
2261
|
+
whatsappOutboundLog.warn(`Trailing media failed; sent warning to ${conversationId}`);
|
|
2262
|
+
rememberSendResult(await sendWithRetry(() => msg.platform.reply("⚠️ Media unavailable.", getQuote()), "media:fallback-unavailable"));
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
const fallbackText = [caption ?? "", "⚠️ Media failed."].filter(Boolean).join("\n");
|
|
2183
2266
|
if (!fallbackText) return;
|
|
2184
|
-
whatsappOutboundLog.warn(`Media skipped; sent text-only to ${
|
|
2267
|
+
whatsappOutboundLog.warn(`Media skipped; sent text-only to ${conversationId}`);
|
|
2185
2268
|
rememberSendResult(await sendWithRetry(() => msg.platform.reply(fallbackText, getQuote()), "media:fallback-text"));
|
|
2186
2269
|
}
|
|
2187
2270
|
});
|
|
@@ -2218,7 +2301,7 @@ function resolveVisibleWhatsAppGroupHistory(params) {
|
|
|
2218
2301
|
function resolveVisibleWhatsAppReplyContext(params) {
|
|
2219
2302
|
const replyTo = getReplyContext(params.msg, params.authDir);
|
|
2220
2303
|
if (!replyTo) return null;
|
|
2221
|
-
const senderAllowed = params.msg.
|
|
2304
|
+
const senderAllowed = requireWhatsAppInboundAdmission(params.msg).conversation.kind !== "group" || params.groupPolicy !== "allowlist" ? true : isWhatsAppSupplementalSenderAllowed({
|
|
2222
2305
|
allowFrom: params.groupAllowFrom,
|
|
2223
2306
|
authDir: params.authDir,
|
|
2224
2307
|
sender: replyTo.sender
|
|
@@ -2251,14 +2334,15 @@ function markWhatsAppReplyDeliveryErrorVisibleAfterFlush(error, flushResult) {
|
|
|
2251
2334
|
return flushResult.delivered > 0 ? markWhatsAppVisibleDeliveryError(error) : error;
|
|
2252
2335
|
}
|
|
2253
2336
|
function logWhatsAppReplyDeliveryError(params) {
|
|
2337
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2254
2338
|
params.replyLogger.error({
|
|
2255
2339
|
err: normalizeErrForLog(params.err),
|
|
2256
2340
|
replyKind: params.info.kind,
|
|
2257
2341
|
correlationId: params.msg.event.id ?? null,
|
|
2258
2342
|
connectionId: params.connectionId,
|
|
2259
|
-
conversationId:
|
|
2343
|
+
conversationId: admission.conversation.id,
|
|
2260
2344
|
chatId: params.msg.platform.chatJid ?? null,
|
|
2261
|
-
to:
|
|
2345
|
+
to: admission.conversation.id,
|
|
2262
2346
|
from: params.msg.platform.recipientJid ?? null
|
|
2263
2347
|
}, "auto-reply delivery failed");
|
|
2264
2348
|
}
|
|
@@ -2327,7 +2411,10 @@ function resolveWhatsAppResponsePrefix(params) {
|
|
|
2327
2411
|
return params.pipelineResponsePrefix ?? (configuredResponsePrefix === void 0 && params.isSelfChat ? resolveIdentityNamePrefix$1(params.cfg, params.agentId) : void 0);
|
|
2328
2412
|
}
|
|
2329
2413
|
async function buildWhatsAppInboundContext(params) {
|
|
2330
|
-
const
|
|
2414
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2415
|
+
const conversationId = admission.conversation.id;
|
|
2416
|
+
const conversationKind = admission.conversation.kind;
|
|
2417
|
+
const inboundHistory = conversationKind === "group" ? buildInboundHistoryFromEntries({
|
|
2331
2418
|
entries: (params.groupHistory ?? []).map((entry) => ({
|
|
2332
2419
|
sender: entry.sender,
|
|
2333
2420
|
body: entry.body,
|
|
@@ -2356,15 +2443,15 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2356
2443
|
media,
|
|
2357
2444
|
messageId: params.msg.event.id,
|
|
2358
2445
|
timestamp: params.msg.event.timestamp,
|
|
2359
|
-
from:
|
|
2446
|
+
from: conversationId,
|
|
2360
2447
|
sender: {
|
|
2361
2448
|
id: params.sender.id ?? params.sender.e164,
|
|
2362
2449
|
name: params.sender.name
|
|
2363
2450
|
},
|
|
2364
2451
|
conversation: {
|
|
2365
|
-
kind:
|
|
2366
|
-
id:
|
|
2367
|
-
label:
|
|
2452
|
+
kind: conversationKind,
|
|
2453
|
+
id: conversationId,
|
|
2454
|
+
label: conversationId
|
|
2368
2455
|
},
|
|
2369
2456
|
route: {
|
|
2370
2457
|
agentId: params.route.agentId,
|
|
@@ -2373,7 +2460,7 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2373
2460
|
},
|
|
2374
2461
|
reply: {
|
|
2375
2462
|
to: params.msg.platform.recipientJid,
|
|
2376
|
-
originatingTo:
|
|
2463
|
+
originatingTo: conversationId
|
|
2377
2464
|
},
|
|
2378
2465
|
message: {
|
|
2379
2466
|
body: params.combinedBody,
|
|
@@ -2384,7 +2471,7 @@ async function buildWhatsAppInboundContext(params) {
|
|
|
2384
2471
|
},
|
|
2385
2472
|
access: {
|
|
2386
2473
|
...params.msg.wasMentioned !== void 0 ? { mentions: {
|
|
2387
|
-
canDetectMention:
|
|
2474
|
+
canDetectMention: conversationKind === "group",
|
|
2388
2475
|
wasMentioned: params.msg.wasMentioned
|
|
2389
2476
|
} } : {},
|
|
2390
2477
|
commands: { authorized: params.commandAuthorized }
|
|
@@ -2434,10 +2521,12 @@ function normalizeCommandTurnFromContext(value) {
|
|
|
2434
2521
|
};
|
|
2435
2522
|
}
|
|
2436
2523
|
function resolveWhatsAppDmRouteTarget(params) {
|
|
2437
|
-
|
|
2524
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2525
|
+
const conversationId = admission.conversation.id;
|
|
2526
|
+
if (admission.conversation.kind === "group") return;
|
|
2438
2527
|
if (params.senderE164) return params.normalizeE164(params.senderE164) ?? void 0;
|
|
2439
|
-
if (
|
|
2440
|
-
return params.normalizeE164(
|
|
2528
|
+
if (conversationId.includes("@")) return jidToE164(conversationId) ?? void 0;
|
|
2529
|
+
return params.normalizeE164(conversationId) ?? void 0;
|
|
2441
2530
|
}
|
|
2442
2531
|
function updateWhatsAppMainLastRoute(params) {
|
|
2443
2532
|
const shouldUpdateMainLastRoute = !params.pinnedMainDmRecipient || params.pinnedMainDmRecipient === params.dmRouteTarget;
|
|
@@ -2462,6 +2551,9 @@ function updateWhatsAppMainLastRoute(params) {
|
|
|
2462
2551
|
if (params.dmRouteTarget && inboundLastRouteSessionKey === params.route.mainSessionKey && params.pinnedMainDmRecipient) logVerbose$1(`Skipping main-session last route update for ${params.dmRouteTarget} (pinned owner ${params.pinnedMainDmRecipient})`);
|
|
2463
2552
|
}
|
|
2464
2553
|
async function dispatchWhatsAppBufferedReply(params) {
|
|
2554
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2555
|
+
const conversationId = admission.conversation.id;
|
|
2556
|
+
const conversationKind = admission.conversation.kind;
|
|
2465
2557
|
const statusReactionController = params.statusReactionController ?? null;
|
|
2466
2558
|
const statusReactionTiming = {
|
|
2467
2559
|
...DEFAULT_TIMING,
|
|
@@ -2476,7 +2568,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2476
2568
|
accountId: params.route.accountId
|
|
2477
2569
|
});
|
|
2478
2570
|
const mediaLocalRoots = getAgentScopedMediaLocalRoots(params.cfg, params.route.agentId);
|
|
2479
|
-
const sourceReplyChatType = typeof params.context.ChatType === "string" ? params.context.ChatType :
|
|
2571
|
+
const sourceReplyChatType = typeof params.context.ChatType === "string" ? params.context.ChatType : conversationKind;
|
|
2480
2572
|
const sourceReplyCommandSource = params.context.CommandSource === "native" || params.context.CommandSource === "text" ? params.context.CommandSource : void 0;
|
|
2481
2573
|
const sourceReplyCommandTurn = normalizeCommandTurnFromContext(params.context.CommandTurn);
|
|
2482
2574
|
const sourceReplyCommandAuthorized = typeof params.context.CommandAuthorized === "boolean" ? params.context.CommandAuthorized : void 0;
|
|
@@ -2512,9 +2604,9 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2512
2604
|
params.replyLogger.warn({
|
|
2513
2605
|
correlationId: params.msg.event.id ?? null,
|
|
2514
2606
|
connectionId: params.connectionId,
|
|
2515
|
-
conversationId
|
|
2607
|
+
conversationId,
|
|
2516
2608
|
chatId: params.msg.platform.chatJid,
|
|
2517
|
-
to:
|
|
2609
|
+
to: conversationId,
|
|
2518
2610
|
from: params.msg.platform.recipientJid,
|
|
2519
2611
|
replyKind: info.kind
|
|
2520
2612
|
}, "auto-reply was not accepted by WhatsApp provider");
|
|
@@ -2527,7 +2619,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2527
2619
|
combinedBodySessionKey: params.route.sessionKey,
|
|
2528
2620
|
logVerboseMessage: shouldLog
|
|
2529
2621
|
});
|
|
2530
|
-
const fromDisplay =
|
|
2622
|
+
const fromDisplay = conversationId;
|
|
2531
2623
|
if (shouldLogVerbose$1()) logVerbose$1(`Reply body: ${normalizedDeliveryPayload.text != null ? reply.text : "<media>"}${reply.hasMedia ? " (media)" : ""} -> ${fromDisplay}`);
|
|
2532
2624
|
return whatsAppReplyDeliveryVisibility(true);
|
|
2533
2625
|
};
|
|
@@ -2569,7 +2661,7 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2569
2661
|
ctxPayload: params.context,
|
|
2570
2662
|
payload: normalizedDeliveryPayload,
|
|
2571
2663
|
info,
|
|
2572
|
-
to:
|
|
2664
|
+
to: conversationId,
|
|
2573
2665
|
formatting: {
|
|
2574
2666
|
textLimit,
|
|
2575
2667
|
tableMode,
|
|
@@ -2639,14 +2731,13 @@ async function dispatchWhatsAppBufferedReply(params) {
|
|
|
2639
2731
|
err,
|
|
2640
2732
|
info,
|
|
2641
2733
|
connectionId: params.connectionId,
|
|
2642
|
-
conversationId: params.conversationId,
|
|
2643
2734
|
msg: params.msg,
|
|
2644
2735
|
replyLogger: params.replyLogger
|
|
2645
2736
|
});
|
|
2646
2737
|
}
|
|
2647
2738
|
},
|
|
2648
2739
|
replyOptions: {
|
|
2649
|
-
suppressTyping: sourceRepliesAreToolOnly &&
|
|
2740
|
+
suppressTyping: sourceRepliesAreToolOnly && conversationKind === "group" && !params.msg.wasMentioned,
|
|
2650
2741
|
disableBlockStreaming,
|
|
2651
2742
|
...sourceReplyDeliveryMode ? { sourceReplyDeliveryMode } : {},
|
|
2652
2743
|
onModelSelected: params.onModelSelected,
|
|
@@ -2737,16 +2828,19 @@ function buildInboundLine(params) {
|
|
|
2737
2828
|
configured: cfg.channels?.whatsapp?.messagePrefix,
|
|
2738
2829
|
hasAllowFrom: (cfg.channels?.whatsapp?.allowFrom?.length ?? 0) > 0
|
|
2739
2830
|
});
|
|
2831
|
+
const admission = requireWhatsAppInboundAdmission(msg);
|
|
2832
|
+
const conversationId = admission.conversation.id;
|
|
2833
|
+
const conversationKind = admission.conversation.kind;
|
|
2740
2834
|
const prefixStr = messagePrefix ? `${messagePrefix} ` : "";
|
|
2741
2835
|
const replyContext = params.visibleReplyTo === void 0 ? formatReplyContext(msg) : formatReplyTarget(params.visibleReplyTo);
|
|
2742
2836
|
const baseLine = `${prefixStr}${msg.payload.body}${replyContext ? `\n\n${replyContext}` : ""}`;
|
|
2743
2837
|
const sender = getSenderIdentity(msg);
|
|
2744
2838
|
return formatInboundEnvelope({
|
|
2745
2839
|
channel: "WhatsApp",
|
|
2746
|
-
from:
|
|
2840
|
+
from: conversationKind === "group" ? conversationId : conversationId.replace(/^whatsapp:/, ""),
|
|
2747
2841
|
timestamp: msg.event.timestamp,
|
|
2748
2842
|
body: baseLine,
|
|
2749
|
-
chatType:
|
|
2843
|
+
chatType: conversationKind,
|
|
2750
2844
|
sender: {
|
|
2751
2845
|
name: sender.name ?? void 0,
|
|
2752
2846
|
e164: sender.e164 ?? void 0,
|
|
@@ -2763,9 +2857,11 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
2763
2857
|
if (!params.msg.event.id) return null;
|
|
2764
2858
|
const statusReactionsConfig = params.cfg.messages?.statusReactions;
|
|
2765
2859
|
if (statusReactionsConfig?.enabled !== true) return null;
|
|
2860
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2861
|
+
const accountId = admission.accountId;
|
|
2766
2862
|
if (resolveWhatsAppReactionLevel({
|
|
2767
2863
|
cfg: params.cfg,
|
|
2768
|
-
accountId
|
|
2864
|
+
accountId
|
|
2769
2865
|
}).level === "off") return null;
|
|
2770
2866
|
const ackConfig = params.cfg.channels?.whatsapp?.ackReaction;
|
|
2771
2867
|
const ackEmoji = resolveWhatsAppAckEmoji({
|
|
@@ -2776,18 +2872,19 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
2776
2872
|
if (!ackEmoji) return null;
|
|
2777
2873
|
const directEnabled = ackConfig?.direct ?? true;
|
|
2778
2874
|
const groupMode = ackConfig?.group ?? "mentions";
|
|
2779
|
-
const
|
|
2780
|
-
const
|
|
2875
|
+
const isGroup = admission.conversation.kind === "group";
|
|
2876
|
+
const conversationIdForCheck = admission.conversation.id;
|
|
2877
|
+
const activation = isGroup ? await resolveGroupActivationFor({
|
|
2781
2878
|
cfg: params.cfg,
|
|
2782
|
-
accountId
|
|
2879
|
+
accountId,
|
|
2783
2880
|
agentId: params.agentId,
|
|
2784
2881
|
sessionKey: params.sessionKey,
|
|
2785
2882
|
conversationId: conversationIdForCheck
|
|
2786
2883
|
}) : null;
|
|
2787
2884
|
if (!shouldAckReactionForWhatsApp({
|
|
2788
2885
|
emoji: ackEmoji,
|
|
2789
|
-
isDirect:
|
|
2790
|
-
isGroup
|
|
2886
|
+
isDirect: admission.conversation.kind === "direct",
|
|
2887
|
+
isGroup,
|
|
2791
2888
|
directEnabled,
|
|
2792
2889
|
groupMode,
|
|
2793
2890
|
wasMentioned: params.msg.wasMentioned === true,
|
|
@@ -2798,7 +2895,7 @@ async function createWhatsAppStatusReactionController(params) {
|
|
|
2798
2895
|
verbose: params.verbose,
|
|
2799
2896
|
fromMe: false,
|
|
2800
2897
|
...sender.jid ? { participant: sender.jid } : {},
|
|
2801
|
-
|
|
2898
|
+
accountId,
|
|
2802
2899
|
cfg: params.cfg
|
|
2803
2900
|
};
|
|
2804
2901
|
const chatId = params.msg.platform.chatJid;
|
|
@@ -2862,11 +2959,14 @@ function resolvePinnedMainDmRecipient(params) {
|
|
|
2862
2959
|
});
|
|
2863
2960
|
}
|
|
2864
2961
|
async function processMessage(params) {
|
|
2865
|
-
const
|
|
2962
|
+
const admission = requireWhatsAppInboundAdmission(params.msg);
|
|
2963
|
+
if (admission.ingress.admission !== "dispatch" && admission.ingress.admission !== "observe") return false;
|
|
2964
|
+
const conversationId = admission.conversation.id;
|
|
2965
|
+
const conversationKind = admission.conversation.kind;
|
|
2866
2966
|
const self = getSelfIdentity(params.msg);
|
|
2867
2967
|
const inboundPolicy = resolveWhatsAppInboundPolicy({
|
|
2868
2968
|
cfg: params.cfg,
|
|
2869
|
-
accountId: params.route.accountId ??
|
|
2969
|
+
accountId: params.route.accountId ?? admission.accountId,
|
|
2870
2970
|
selfE164: self.e164 ?? null
|
|
2871
2971
|
});
|
|
2872
2972
|
const account = inboundPolicy.account;
|
|
@@ -2888,7 +2988,7 @@ async function processMessage(params) {
|
|
|
2888
2988
|
ctx: {
|
|
2889
2989
|
MediaPaths: [params.msg.payload.media?.path],
|
|
2890
2990
|
MediaTypes: params.msg.payload.media?.type ? [params.msg.payload.media?.type] : void 0,
|
|
2891
|
-
From:
|
|
2991
|
+
From: conversationId,
|
|
2892
2992
|
To: params.msg.platform.recipientJid,
|
|
2893
2993
|
Provider: "whatsapp",
|
|
2894
2994
|
Surface: "whatsapp",
|
|
@@ -2924,14 +3024,14 @@ async function processMessage(params) {
|
|
|
2924
3024
|
visibleReplyTo
|
|
2925
3025
|
});
|
|
2926
3026
|
let shouldClearGroupHistory = false;
|
|
2927
|
-
const visibleGroupHistory =
|
|
3027
|
+
const visibleGroupHistory = conversationKind === "group" ? resolveVisibleWhatsAppGroupHistory({
|
|
2928
3028
|
history: params.groupHistory ?? params.groupHistories.get(params.groupHistoryKey) ?? [],
|
|
2929
3029
|
mode: contextVisibilityMode,
|
|
2930
3030
|
groupPolicy: inboundPolicy.groupPolicy,
|
|
2931
3031
|
groupAllowFrom: inboundPolicy.groupAllowFrom,
|
|
2932
3032
|
authDir: account.authDir
|
|
2933
3033
|
}) : void 0;
|
|
2934
|
-
if (
|
|
3034
|
+
if (conversationKind === "group") {
|
|
2935
3035
|
const history = visibleGroupHistory ?? [];
|
|
2936
3036
|
if (history.length > 0) combinedBody = buildHistoryContextFromEntries({
|
|
2937
3037
|
entries: history.map((m) => ({
|
|
@@ -2969,9 +3069,7 @@ async function processMessage(params) {
|
|
|
2969
3069
|
msg: params.msg,
|
|
2970
3070
|
agentId: params.route.agentId,
|
|
2971
3071
|
sessionKey: params.route.sessionKey,
|
|
2972
|
-
|
|
2973
|
-
verbose: params.verbose,
|
|
2974
|
-
accountId: account.accountId
|
|
3072
|
+
verbose: params.verbose
|
|
2975
3073
|
}) : null);
|
|
2976
3074
|
if (statusReactionController && !params.statusReactionController) statusReactionController.setQueued();
|
|
2977
3075
|
let ackReaction = params.ackReaction ?? null;
|
|
@@ -2980,9 +3078,7 @@ async function processMessage(params) {
|
|
|
2980
3078
|
msg: params.msg,
|
|
2981
3079
|
agentId: params.route.agentId,
|
|
2982
3080
|
sessionKey: params.route.sessionKey,
|
|
2983
|
-
conversationId,
|
|
2984
3081
|
verbose: params.verbose,
|
|
2985
|
-
accountId: account.accountId,
|
|
2986
3082
|
info: params.replyLogger.info.bind(params.replyLogger),
|
|
2987
3083
|
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
2988
3084
|
});
|
|
@@ -2990,15 +3086,15 @@ async function processMessage(params) {
|
|
|
2990
3086
|
params.replyLogger.info({
|
|
2991
3087
|
connectionId: params.connectionId,
|
|
2992
3088
|
correlationId,
|
|
2993
|
-
from:
|
|
3089
|
+
from: conversationId,
|
|
2994
3090
|
to: params.msg.platform.recipientJid,
|
|
2995
3091
|
body: elide(combinedBody, 240),
|
|
2996
3092
|
mediaType: params.msg.payload.media?.type ?? null,
|
|
2997
3093
|
mediaPath: params.msg.payload.media?.path ?? null
|
|
2998
3094
|
}, "inbound web message");
|
|
2999
|
-
const fromDisplay =
|
|
3095
|
+
const fromDisplay = conversationId;
|
|
3000
3096
|
const kindLabel = params.msg.payload.media?.type ? `, ${params.msg.payload.media?.type}` : "";
|
|
3001
|
-
whatsappInboundLog.info(`Inbound message ${fromDisplay} -> ${params.msg.platform.recipientJid} (${
|
|
3097
|
+
whatsappInboundLog.info(`Inbound message ${fromDisplay} -> ${params.msg.platform.recipientJid} (${conversationKind}${kindLabel}, ${combinedBody.length} chars)`);
|
|
3002
3098
|
if (shouldLogVerbose$1()) whatsappInboundLog.debug(`Inbound body: ${elide(combinedBody, 400)}`);
|
|
3003
3099
|
const sender = getSenderIdentity(params.msg);
|
|
3004
3100
|
const dmRouteTarget = resolveWhatsAppDmRouteTarget({
|
|
@@ -3033,16 +3129,16 @@ async function processMessage(params) {
|
|
|
3033
3129
|
const responsePrefix = resolveWhatsAppResponsePrefix({
|
|
3034
3130
|
cfg: params.cfg,
|
|
3035
3131
|
agentId: params.route.agentId,
|
|
3036
|
-
isSelfChat:
|
|
3132
|
+
isSelfChat: conversationKind !== "group" && inboundPolicy.isSelfChat,
|
|
3037
3133
|
pipelineResponsePrefix: replyPipeline.responsePrefix
|
|
3038
3134
|
});
|
|
3039
3135
|
const replyThreading = resolveBatchedReplyThreadingPolicy(account.replyToMode ?? "off", params.msg.event.isBatched === true);
|
|
3040
|
-
const conversationSystemPrompt =
|
|
3136
|
+
const conversationSystemPrompt = conversationKind === "group" ? resolveWhatsAppGroupSystemPrompt({
|
|
3041
3137
|
accountConfig: account,
|
|
3042
3138
|
groupId: conversationId
|
|
3043
3139
|
}) : resolveWhatsAppDirectSystemPrompt({
|
|
3044
3140
|
accountConfig: account,
|
|
3045
|
-
peerId: dmRouteTarget ??
|
|
3141
|
+
peerId: dmRouteTarget ?? conversationId
|
|
3046
3142
|
});
|
|
3047
3143
|
const ctxPayload = await buildWhatsAppInboundContext({
|
|
3048
3144
|
bodyForAgent: msgForAgent.payload.body,
|
|
@@ -3050,7 +3146,6 @@ async function processMessage(params) {
|
|
|
3050
3146
|
commandBody: params.msg.payload.body,
|
|
3051
3147
|
commandAuthorized,
|
|
3052
3148
|
commandTurn,
|
|
3053
|
-
conversationId,
|
|
3054
3149
|
groupHistory: visibleGroupHistory,
|
|
3055
3150
|
groupMemberRoster: params.groupMemberNames.get(params.groupHistoryKey),
|
|
3056
3151
|
groupSystemPrompt: conversationSystemPrompt,
|
|
@@ -3101,6 +3196,26 @@ async function processMessage(params) {
|
|
|
3101
3196
|
textForCommands: ctxPayload.CommandBody,
|
|
3102
3197
|
raw: params.msg
|
|
3103
3198
|
}),
|
|
3199
|
+
preflight: () => {
|
|
3200
|
+
const reason = admission.ingress.reasonCode;
|
|
3201
|
+
if (admission.ingress.admission === "dispatch") return { admission: {
|
|
3202
|
+
kind: "dispatch",
|
|
3203
|
+
reason
|
|
3204
|
+
} };
|
|
3205
|
+
if (admission.ingress.admission === "observe") return { admission: {
|
|
3206
|
+
kind: "observeOnly",
|
|
3207
|
+
reason
|
|
3208
|
+
} };
|
|
3209
|
+
if (admission.ingress.admission === "skip") return { admission: {
|
|
3210
|
+
kind: "handled",
|
|
3211
|
+
reason
|
|
3212
|
+
} };
|
|
3213
|
+
return { admission: {
|
|
3214
|
+
kind: "drop",
|
|
3215
|
+
reason,
|
|
3216
|
+
recordHistory: false
|
|
3217
|
+
} };
|
|
3218
|
+
},
|
|
3104
3219
|
resolveTurn: () => ({
|
|
3105
3220
|
channel: "whatsapp",
|
|
3106
3221
|
accountId: params.route.accountId,
|
|
@@ -3124,7 +3239,6 @@ async function processMessage(params) {
|
|
|
3124
3239
|
cfg: params.cfg,
|
|
3125
3240
|
connectionId: params.connectionId,
|
|
3126
3241
|
context: ctxPayload,
|
|
3127
|
-
conversationId,
|
|
3128
3242
|
deliverReply: deliverWebReply,
|
|
3129
3243
|
groupHistories: params.groupHistories,
|
|
3130
3244
|
groupHistoryKey: params.groupHistoryKey,
|
|
@@ -3164,11 +3278,12 @@ async function processMessage(params) {
|
|
|
3164
3278
|
//#endregion
|
|
3165
3279
|
//#region extensions/whatsapp/src/auto-reply/monitor/on-message.ts
|
|
3166
3280
|
function createWebOnMessageHandler(params) {
|
|
3281
|
+
const hasExplicitlyPassedInboundAccess = (msg) => msg.admission ? msg.admission.ingress.decision === "allow" : msg.accessControlPassed === true;
|
|
3167
3282
|
const withDirectSenderPeer = (msg, peerId) => {
|
|
3168
|
-
if (msg.
|
|
3283
|
+
if (requireWhatsAppInboundAdmission(msg).conversation.kind === "group" || msg.platform.sender?.e164 || msg.platform.senderE164 || !peerId.startsWith("+")) return msg;
|
|
3169
3284
|
const normalized = normalizeE164(peerId);
|
|
3170
3285
|
if (!normalized) return msg;
|
|
3171
|
-
return withDeprecatedWebInboundMessageFlatAliases({
|
|
3286
|
+
return requireAdmittedWhatsAppInboundMessage(withDeprecatedWebInboundMessageFlatAliases({
|
|
3172
3287
|
...msg,
|
|
3173
3288
|
platform: {
|
|
3174
3289
|
...msg.platform,
|
|
@@ -3178,7 +3293,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3178
3293
|
},
|
|
3179
3294
|
senderE164: normalized
|
|
3180
3295
|
}
|
|
3181
|
-
});
|
|
3296
|
+
}));
|
|
3182
3297
|
};
|
|
3183
3298
|
const processForRoute = async (cfg, msg, route, groupHistoryKey, opts) => {
|
|
3184
3299
|
const processParams = {
|
|
@@ -3208,28 +3323,32 @@ function createWebOnMessageHandler(params) {
|
|
|
3208
3323
|
return processMessage(processParams);
|
|
3209
3324
|
};
|
|
3210
3325
|
return async (rawMsg) => {
|
|
3211
|
-
const
|
|
3326
|
+
const canRunDirectEarlyAudioPreflight = hasExplicitlyPassedInboundAccess(rawMsg);
|
|
3327
|
+
const normalizedMsg = requireAdmittedWhatsAppInboundMessage(normalizeWebInboundMessage(rawMsg));
|
|
3212
3328
|
const cfg = params.loadConfig?.() ?? params.cfg;
|
|
3213
3329
|
const peerId = resolvePeerId(normalizedMsg);
|
|
3214
3330
|
const msg = withDirectSenderPeer(normalizedMsg, peerId);
|
|
3215
|
-
const
|
|
3331
|
+
const admission = requireWhatsAppInboundAdmission(msg);
|
|
3332
|
+
if (admission.ingress.admission !== "dispatch" && admission.ingress.admission !== "observe") return;
|
|
3333
|
+
const conversationId = admission.conversation.id;
|
|
3334
|
+
const conversationKind = admission.conversation.kind;
|
|
3216
3335
|
const baseRoute = resolveAgentRoute({
|
|
3217
3336
|
cfg,
|
|
3218
3337
|
channel: "whatsapp",
|
|
3219
|
-
accountId:
|
|
3338
|
+
accountId: admission.accountId,
|
|
3220
3339
|
peer: {
|
|
3221
|
-
kind:
|
|
3340
|
+
kind: conversationKind,
|
|
3222
3341
|
id: peerId
|
|
3223
3342
|
}
|
|
3224
3343
|
});
|
|
3225
|
-
const baseConversationRoute =
|
|
3226
|
-
const routeAccountId = baseConversationRoute.accountId ??
|
|
3344
|
+
const baseConversationRoute = conversationKind === "group" ? resolveWhatsAppGroupSessionRoute(baseRoute) : baseRoute;
|
|
3345
|
+
const routeAccountId = baseConversationRoute.accountId ?? admission.accountId;
|
|
3227
3346
|
const account = resolveWhatsAppAccount({
|
|
3228
3347
|
cfg,
|
|
3229
3348
|
accountId: routeAccountId
|
|
3230
3349
|
});
|
|
3231
3350
|
const baseMentionConfig = buildMentionConfig(cfg);
|
|
3232
|
-
if (
|
|
3351
|
+
if (conversationId === msg.platform.recipientJid) logVerbose(`📱 Same-phone mode detected (from === to: ${conversationId})`);
|
|
3233
3352
|
if (params.echoTracker.has(msg.payload.body)) {
|
|
3234
3353
|
logVerbose("Skipping auto-reply: detected echo (message matches recently sent text)");
|
|
3235
3354
|
params.echoTracker.forget(msg.payload.body);
|
|
@@ -3243,7 +3362,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3243
3362
|
conversationId: peerId
|
|
3244
3363
|
});
|
|
3245
3364
|
const route = configuredRoute.route;
|
|
3246
|
-
const groupHistoryKey =
|
|
3365
|
+
const groupHistoryKey = conversationKind === "group" ? buildGroupHistoryKey({
|
|
3247
3366
|
channel: "whatsapp",
|
|
3248
3367
|
accountId: route.accountId,
|
|
3249
3368
|
peerKind: "group",
|
|
@@ -3251,7 +3370,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3251
3370
|
}) : route.sessionKey;
|
|
3252
3371
|
let preflightAudioTranscript;
|
|
3253
3372
|
const hasAudioBody = msg.payload.media?.type?.startsWith("audio/") === true && msg.payload.body === "<media:audio>";
|
|
3254
|
-
const canRunEarlyAudioPreflight =
|
|
3373
|
+
const canRunEarlyAudioPreflight = conversationKind === "group" || canRunDirectEarlyAudioPreflight;
|
|
3255
3374
|
let ackAlreadySent = false;
|
|
3256
3375
|
let ackReaction = null;
|
|
3257
3376
|
let statusReactionController = null;
|
|
@@ -3259,13 +3378,37 @@ function createWebOnMessageHandler(params) {
|
|
|
3259
3378
|
const clearPreDispatchReaction = async () => {
|
|
3260
3379
|
try {
|
|
3261
3380
|
if (statusReactionController) {
|
|
3262
|
-
statusReactionController
|
|
3263
|
-
|
|
3381
|
+
const controller = statusReactionController;
|
|
3382
|
+
statusReactionController = null;
|
|
3383
|
+
controller.cancelPending();
|
|
3384
|
+
await controller.clear();
|
|
3264
3385
|
return;
|
|
3265
3386
|
}
|
|
3266
3387
|
if (ackReaction && await ackReaction.ackReactionPromise) await ackReaction.remove();
|
|
3267
3388
|
} catch (err) {
|
|
3268
|
-
params.replyLogger.warn({ error: String(err) }, "whatsapp: failed to clear pre-dispatch reaction after
|
|
3389
|
+
params.replyLogger.warn({ error: String(err) }, "whatsapp: failed to clear pre-dispatch reaction after pre-dispatch rejection");
|
|
3390
|
+
}
|
|
3391
|
+
};
|
|
3392
|
+
const transcribeAudioOnce = async () => {
|
|
3393
|
+
if (preflightAudioTranscript !== void 0 || !hasAudioBody || !msg.payload.media?.path) return;
|
|
3394
|
+
try {
|
|
3395
|
+
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
3396
|
+
preflightAudioTranscript = await transcribeFirstAudio({
|
|
3397
|
+
ctx: {
|
|
3398
|
+
MediaPaths: [msg.payload.media?.path],
|
|
3399
|
+
MediaTypes: msg.payload.media?.type ? [msg.payload.media?.type] : void 0,
|
|
3400
|
+
From: conversationId,
|
|
3401
|
+
To: msg.platform.recipientJid,
|
|
3402
|
+
Provider: "whatsapp",
|
|
3403
|
+
Surface: "whatsapp",
|
|
3404
|
+
OriginatingChannel: "whatsapp",
|
|
3405
|
+
OriginatingTo: conversationId,
|
|
3406
|
+
AccountId: route.accountId
|
|
3407
|
+
},
|
|
3408
|
+
cfg
|
|
3409
|
+
}) ?? null;
|
|
3410
|
+
} catch {
|
|
3411
|
+
preflightAudioTranscript = null;
|
|
3269
3412
|
}
|
|
3270
3413
|
};
|
|
3271
3414
|
const runAudioPreflightOnce = async () => {
|
|
@@ -3276,9 +3419,7 @@ function createWebOnMessageHandler(params) {
|
|
|
3276
3419
|
msg,
|
|
3277
3420
|
agentId: route.agentId,
|
|
3278
3421
|
sessionKey: route.sessionKey,
|
|
3279
|
-
|
|
3280
|
-
verbose: params.verbose,
|
|
3281
|
-
accountId: route.accountId
|
|
3422
|
+
verbose: params.verbose
|
|
3282
3423
|
});
|
|
3283
3424
|
if (statusReactionController) await statusReactionController.setQueued();
|
|
3284
3425
|
} else {
|
|
@@ -3287,42 +3428,22 @@ function createWebOnMessageHandler(params) {
|
|
|
3287
3428
|
msg,
|
|
3288
3429
|
agentId: route.agentId,
|
|
3289
3430
|
sessionKey: route.sessionKey,
|
|
3290
|
-
conversationId,
|
|
3291
3431
|
verbose: params.verbose,
|
|
3292
|
-
accountId: route.accountId,
|
|
3293
3432
|
info: params.replyLogger.info.bind(params.replyLogger),
|
|
3294
3433
|
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
3295
3434
|
});
|
|
3296
3435
|
ackAlreadySent = ackReaction !== null;
|
|
3297
3436
|
}
|
|
3298
|
-
|
|
3299
|
-
const { transcribeFirstAudio } = await import("./audio-preflight.runtime-C_glQhZY.js");
|
|
3300
|
-
preflightAudioTranscript = await transcribeFirstAudio({
|
|
3301
|
-
ctx: {
|
|
3302
|
-
MediaPaths: [msg.payload.media?.path],
|
|
3303
|
-
MediaTypes: msg.payload.media?.type ? [msg.payload.media?.type] : void 0,
|
|
3304
|
-
From: msg.from,
|
|
3305
|
-
To: msg.platform.recipientJid,
|
|
3306
|
-
Provider: "whatsapp",
|
|
3307
|
-
Surface: "whatsapp",
|
|
3308
|
-
OriginatingChannel: "whatsapp",
|
|
3309
|
-
OriginatingTo: conversationId,
|
|
3310
|
-
AccountId: route.accountId
|
|
3311
|
-
},
|
|
3312
|
-
cfg
|
|
3313
|
-
}) ?? null;
|
|
3314
|
-
} catch {
|
|
3315
|
-
preflightAudioTranscript = null;
|
|
3316
|
-
}
|
|
3437
|
+
await transcribeAudioOnce();
|
|
3317
3438
|
};
|
|
3318
|
-
if (
|
|
3439
|
+
if (conversationKind === "group") {
|
|
3319
3440
|
const sender = getSenderIdentity(msg);
|
|
3320
3441
|
const metaCtx = {
|
|
3321
|
-
From:
|
|
3442
|
+
From: conversationId,
|
|
3322
3443
|
To: msg.platform.recipientJid,
|
|
3323
3444
|
SessionKey: route.sessionKey,
|
|
3324
3445
|
AccountId: route.accountId,
|
|
3325
|
-
ChatType:
|
|
3446
|
+
ChatType: conversationKind,
|
|
3326
3447
|
ConversationLabel: conversationId,
|
|
3327
3448
|
GroupSubject: msg.group?.subject,
|
|
3328
3449
|
SenderName: sender.name ?? void 0,
|
|
@@ -3344,13 +3465,11 @@ function createWebOnMessageHandler(params) {
|
|
|
3344
3465
|
ctx: metaCtx,
|
|
3345
3466
|
warn: params.replyLogger.warn.bind(params.replyLogger)
|
|
3346
3467
|
});
|
|
3347
|
-
|
|
3348
|
-
else recordGroupRoute();
|
|
3468
|
+
recordAcceptedConfiguredGroupRoute = recordGroupRoute;
|
|
3349
3469
|
let gating = await applyGroupGating({
|
|
3350
3470
|
cfg,
|
|
3351
3471
|
msg,
|
|
3352
3472
|
deferMissingMention: hasAudioBody && Boolean(msg.payload.media?.path),
|
|
3353
|
-
conversationId,
|
|
3354
3473
|
groupHistoryKey,
|
|
3355
3474
|
agentId: route.agentId,
|
|
3356
3475
|
sessionKey: route.sessionKey,
|
|
@@ -3370,7 +3489,6 @@ function createWebOnMessageHandler(params) {
|
|
|
3370
3489
|
cfg,
|
|
3371
3490
|
msg,
|
|
3372
3491
|
...typeof preflightAudioTranscript === "string" ? { mentionText: preflightAudioTranscript } : {},
|
|
3373
|
-
conversationId,
|
|
3374
3492
|
groupHistoryKey,
|
|
3375
3493
|
agentId: route.agentId,
|
|
3376
3494
|
sessionKey: route.sessionKey,
|
|
@@ -3385,7 +3503,10 @@ function createWebOnMessageHandler(params) {
|
|
|
3385
3503
|
replyLogger: params.replyLogger
|
|
3386
3504
|
});
|
|
3387
3505
|
}
|
|
3388
|
-
if (!gating.shouldProcess)
|
|
3506
|
+
if (!gating.shouldProcess) {
|
|
3507
|
+
await clearPreDispatchReaction();
|
|
3508
|
+
return;
|
|
3509
|
+
}
|
|
3389
3510
|
}
|
|
3390
3511
|
if (configuredRoute.bindingResolution) {
|
|
3391
3512
|
const ensured = await ensureConfiguredBindingRouteReady({
|
|
@@ -3398,8 +3519,14 @@ function createWebOnMessageHandler(params) {
|
|
|
3398
3519
|
return;
|
|
3399
3520
|
}
|
|
3400
3521
|
}
|
|
3401
|
-
recordAcceptedConfiguredGroupRoute
|
|
3522
|
+
if (recordAcceptedConfiguredGroupRoute && !configuredRoute.bindingResolution) {
|
|
3523
|
+
recordAcceptedConfiguredGroupRoute();
|
|
3524
|
+
recordAcceptedConfiguredGroupRoute = null;
|
|
3525
|
+
}
|
|
3402
3526
|
await runAudioPreflightOnce();
|
|
3527
|
+
const hasBroadcastTargets = !configuredRoute.bindingResolution && Array.isArray(cfg.broadcast?.[peerId]) && cfg.broadcast[peerId].length > 0;
|
|
3528
|
+
if (hasBroadcastTargets && statusReactionController) await clearPreDispatchReaction();
|
|
3529
|
+
if (hasBroadcastTargets && !canRunEarlyAudioPreflight) await transcribeAudioOnce();
|
|
3403
3530
|
if (!configuredRoute.bindingResolution && await maybeBroadcastMessage({
|
|
3404
3531
|
cfg,
|
|
3405
3532
|
msg,
|
|
@@ -3408,11 +3535,12 @@ function createWebOnMessageHandler(params) {
|
|
|
3408
3535
|
groupHistoryKey,
|
|
3409
3536
|
groupHistories: params.groupHistories,
|
|
3410
3537
|
...preflightAudioTranscript !== void 0 ? { preflightAudioTranscript } : {},
|
|
3411
|
-
...ackAlreadySent &&
|
|
3412
|
-
...ackReaction &&
|
|
3413
|
-
...statusReactionController &&
|
|
3538
|
+
...ackAlreadySent && conversationKind !== "group" ? { ackAlreadySent: true } : {},
|
|
3539
|
+
...ackReaction && conversationKind !== "group" ? { ackReaction } : {},
|
|
3540
|
+
...statusReactionController && conversationKind !== "group" ? { ackAlreadySent: true } : {},
|
|
3414
3541
|
processMessage: (m, r, k, opts) => processForRoute(cfg, m, r, k, opts)
|
|
3415
3542
|
})) return;
|
|
3543
|
+
recordAcceptedConfiguredGroupRoute?.();
|
|
3416
3544
|
await processForRoute(cfg, msg, route, groupHistoryKey, {
|
|
3417
3545
|
...preflightAudioTranscript !== void 0 ? { preflightAudioTranscript } : {},
|
|
3418
3546
|
...ackAlreadySent ? { ackAlreadySent: true } : {},
|
|
@@ -3480,29 +3608,6 @@ function resolveExplicitWhatsAppDebounceOverride(params) {
|
|
|
3480
3608
|
function isRetryableAuthUnstableError(error) {
|
|
3481
3609
|
return error instanceof WhatsAppAuthUnstableError || typeof error === "object" && error !== null && "code" in error && error.code === "whatsapp-auth-unstable";
|
|
3482
3610
|
}
|
|
3483
|
-
async function clearTerminalWebAuthState(params) {
|
|
3484
|
-
try {
|
|
3485
|
-
const cleared = await logoutWeb({
|
|
3486
|
-
authDir: params.account.authDir,
|
|
3487
|
-
isLegacyAuthDir: params.account.isLegacyAuthDir,
|
|
3488
|
-
runtime: params.runtime
|
|
3489
|
-
});
|
|
3490
|
-
params.log.warn({
|
|
3491
|
-
accountId: params.account.accountId,
|
|
3492
|
-
cleared,
|
|
3493
|
-
healthState: params.healthState,
|
|
3494
|
-
status: params.statusLabel
|
|
3495
|
-
}, "web reconnect: cleared cached auth after terminal close");
|
|
3496
|
-
} catch (error) {
|
|
3497
|
-
params.log.warn({
|
|
3498
|
-
accountId: params.account.accountId,
|
|
3499
|
-
error: formatError(error),
|
|
3500
|
-
healthState: params.healthState,
|
|
3501
|
-
status: params.statusLabel
|
|
3502
|
-
}, "web reconnect: failed clearing cached auth after terminal close");
|
|
3503
|
-
params.runtime.error(`WhatsApp Web cleanup failed after terminal close (status ${params.statusLabel}). Run \`${formatCliCommand("openclaw channels logout --channel whatsapp")}\`, then relink with \`${formatCliCommand("openclaw channels login --channel whatsapp")}\`.`);
|
|
3504
|
-
}
|
|
3505
|
-
}
|
|
3506
3611
|
const DEFAULT_TRANSPORT_TIMEOUT_MS = 300 * 1e3;
|
|
3507
3612
|
async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSocket, keepAlive = true, replyResolver, runtime = defaultRuntime, abortSignal, tuning = {}) {
|
|
3508
3613
|
const activeReplyResolver = replyResolver ?? (await loadReplyResolverRuntime()).getReplyFromConfig;
|
|
@@ -3519,8 +3624,6 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3519
3624
|
module: "web-reconnect",
|
|
3520
3625
|
runId
|
|
3521
3626
|
});
|
|
3522
|
-
const statusController = createWebChannelStatusController(tuning.statusSink);
|
|
3523
|
-
statusController.emit();
|
|
3524
3627
|
const baseCfg = getRuntimeConfig$1();
|
|
3525
3628
|
const sourceCfg = getRuntimeConfigSourceSnapshot();
|
|
3526
3629
|
const { cfg, account } = resolveWebMonitorConfigSnapshot({
|
|
@@ -3571,6 +3674,8 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3571
3674
|
sleep,
|
|
3572
3675
|
isNonRetryableStatus: isNonRetryableWebCloseStatus
|
|
3573
3676
|
});
|
|
3677
|
+
const statusController = createWebChannelStatusController(tuning.statusSink);
|
|
3678
|
+
statusController.emit();
|
|
3574
3679
|
try {
|
|
3575
3680
|
while (true) {
|
|
3576
3681
|
if (stopRequested()) break;
|
|
@@ -3621,6 +3726,7 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3621
3726
|
mediaMaxMb: account.mediaMaxMb,
|
|
3622
3727
|
selfChatMode: account.selfChatMode,
|
|
3623
3728
|
sendReadReceipts: account.sendReadReceipts,
|
|
3729
|
+
socketTiming,
|
|
3624
3730
|
debounceMs: inboundDebounceMs,
|
|
3625
3731
|
shouldDebounce,
|
|
3626
3732
|
socketRef: controller.socketRef,
|
|
@@ -3696,25 +3802,9 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3696
3802
|
reconnectAttempts: setupDecision.reconnectAttempts,
|
|
3697
3803
|
maxAttempts: reconnectPolicy.maxAttempts
|
|
3698
3804
|
}, "web reconnect: setup status error; max attempts reached");
|
|
3699
|
-
if (setupDecision.healthState === "logged-out") {
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
runtime,
|
|
3703
|
-
statusLabel: setupDecision.normalized.statusLabel,
|
|
3704
|
-
healthState: setupDecision.healthState,
|
|
3705
|
-
log: reconnectLogger
|
|
3706
|
-
});
|
|
3707
|
-
runtime.error(`WhatsApp session logged out during setup. Run \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` to relink.`);
|
|
3708
|
-
} else if (setupDecision.healthState === "conflict") {
|
|
3709
|
-
await clearTerminalWebAuthState({
|
|
3710
|
-
account,
|
|
3711
|
-
runtime,
|
|
3712
|
-
statusLabel: setupDecision.normalized.statusLabel,
|
|
3713
|
-
healthState: setupDecision.healthState,
|
|
3714
|
-
log: reconnectLogger
|
|
3715
|
-
});
|
|
3716
|
-
runtime.error(`WhatsApp Web connection closed during setup (status ${setupDecision.normalized.statusLabel}: session conflict). Resolve conflicting WhatsApp Web sessions, then relink with \`${formatCliCommand("openclaw channels login --channel whatsapp")}\`. Stopping web monitoring.`);
|
|
3717
|
-
} else runtime.error(`WhatsApp Web connection closed during setup (status ${setupDecision.normalized.statusLabel}) after ${setupDecision.reconnectAttempts}/${reconnectPolicy.maxAttempts} attempts. Relink with \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` if the issue persists.`);
|
|
3805
|
+
if (setupDecision.healthState === "logged-out") runtime.error(`WhatsApp session logged out during setup. Run \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` to relink.`);
|
|
3806
|
+
else if (setupDecision.healthState === "conflict") runtime.error(`WhatsApp Web connection closed during setup (status ${setupDecision.normalized.statusLabel}: session conflict). Resolve conflicting WhatsApp Web sessions, then restart the channel. To force a fresh QR, run \`${formatCliCommand("openclaw channels logout --channel whatsapp")}\` before \`${formatCliCommand("openclaw channels login --channel whatsapp")}\`. Stopping web monitoring.`);
|
|
3807
|
+
else runtime.error(`WhatsApp Web connection closed during setup (status ${setupDecision.normalized.statusLabel}) after ${setupDecision.reconnectAttempts}/${reconnectPolicy.maxAttempts} attempts. Relink with \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` if the issue persists.`);
|
|
3718
3808
|
await controller.shutdown();
|
|
3719
3809
|
break;
|
|
3720
3810
|
}
|
|
@@ -3874,29 +3964,14 @@ async function monitorWebChannel(verbose, listenerFactory = attachWebInboxToSock
|
|
|
3874
3964
|
reconnectAttempts: decision.reconnectAttempts,
|
|
3875
3965
|
healthState: decision.healthState
|
|
3876
3966
|
});
|
|
3877
|
-
if (decision.healthState === "logged-out") {
|
|
3878
|
-
|
|
3879
|
-
account,
|
|
3880
|
-
runtime,
|
|
3881
|
-
statusLabel: decision.normalized.statusLabel,
|
|
3882
|
-
healthState: decision.healthState,
|
|
3883
|
-
log: reconnectLogger
|
|
3884
|
-
});
|
|
3885
|
-
runtime.error(`WhatsApp session logged out. Run \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` to relink.`);
|
|
3886
|
-
} else if (decision.healthState === "conflict") {
|
|
3887
|
-
await clearTerminalWebAuthState({
|
|
3888
|
-
account,
|
|
3889
|
-
runtime,
|
|
3890
|
-
statusLabel: decision.normalized.statusLabel,
|
|
3891
|
-
healthState: decision.healthState,
|
|
3892
|
-
log: reconnectLogger
|
|
3893
|
-
});
|
|
3967
|
+
if (decision.healthState === "logged-out") runtime.error(`WhatsApp session logged out. Run \`${formatCliCommand("openclaw channels login --channel whatsapp")}\` to relink.`);
|
|
3968
|
+
else if (decision.healthState === "conflict") {
|
|
3894
3969
|
reconnectLogger.warn({
|
|
3895
3970
|
connectionId: connection.connectionId,
|
|
3896
3971
|
status: decision.normalized.statusLabel,
|
|
3897
3972
|
error: decision.normalized.errorText
|
|
3898
3973
|
}, "web reconnect: non-retryable close status; stopping monitor");
|
|
3899
|
-
runtime.error(`WhatsApp Web connection closed (status ${decision.normalized.statusLabel}: session conflict). Resolve conflicting WhatsApp Web sessions, then
|
|
3974
|
+
runtime.error(`WhatsApp Web connection closed (status ${decision.normalized.statusLabel}: session conflict). Resolve conflicting WhatsApp Web sessions, then restart the channel. To force a fresh QR, run \`${formatCliCommand("openclaw channels logout --channel whatsapp")}\` before \`${formatCliCommand("openclaw channels login --channel whatsapp")}\`. Stopping web monitoring.`);
|
|
3900
3975
|
} else {
|
|
3901
3976
|
reconnectLogger.warn({
|
|
3902
3977
|
connectionId: connection.connectionId,
|