feat: add WhatsApp quote and status primitives - #21977
Conversation
828e39d to
16cfe6e
Compare
austinpickett
left a comment
There was a problem hiding this comment.
Please fix merge conflicts and use .github/PULL_REQUEST_TEMPLATE.md
16cfe6e to
88322e2
Compare
234cc04 to
28a2131
Compare
|
@austinpickett both points from your review should be addressed now:
Would appreciate a re-review when you have a moment. Thanks! |
1a4a4aa to
9255371
Compare
9255371 to
0350ef3
Compare
|
Acknowledged — this branch has drifted into a multi-commit stack that overlaps several other open PRs and needs a clean rescope onto current I'm handling that rescope as its own focused pass rather than force a hand-resolution here, and will re-push against the PR template once it's a single coherent commit. Leaving the branch as-is in the meantime so no half-resolved state lands. |
|
Heads-up for reviewers: the reaction portion of this PR (the bounded TTL'd |
212f83c to
7345125
Compare
7345125 to
c3a2c72
Compare
c3a2c72 to
172498e
Compare
Add outbound WhatsApp primitives that the existing send path doesn't cover: emoji reactions to cached messages, private replies to status updates, reactions to statuses, and posting text statuses to an explicit recipient list. Exposed through a new `whatsapp_action` tool that is service-gated (check_fn=_check_whatsapp_action) so it only enters the schema when WhatsApp is a configured platform — it never ships on calls for users without WhatsApp. Bridge (Node): - Bounded, TTL'd WAMessage store (messageStore) so Baileys can resolve the original message object required for native quotes and reactions. - New endpoints: POST /react, /status-reply, /status-react, /post-status. - extractMessageText / extractQuoteContext helpers; thread quoted-send options through /send-media, honoring an explicit per-request upload timeout when provided and falling back to sendWithTimeout's default. Adapter (Python): - _is_status_broadcast_id helper (in WhatsAppBehaviorMixin) + status-ingest opt-in in _should_process_message, reconciled with main's broadcast-list gate (status updates dropped unless statuses.enabled && statuses.ingest). - _post_bridge_action + react_to_message / reply_to_status / react_to_status / post_text_status on the Baileys adapter. - Thread reply_to through _send_media_to_bridge and the send_* wrappers. - Surface quoted-message context (reply_to_message_id / reply_to_text) on inbound MessageEvent. Tests: bridge.test.mjs (message store, quote options, status resolution), test_whatsapp_action_tool.py, plus formatting/group-gating additions. Re-ported onto current main after the adapter was relocated to plugins/platforms/whatsapp/adapter.py and gating moved into WhatsAppBehaviorMixin; the prior 12-commit stack of stale cherry-picks is collapsed to this single feature commit.
172498e to
c5ac96d
Compare
What does this PR do?
Adds WhatsApp quote/reaction/status primitives that Baileys supports natively but Hermes was paving over with plain-text follow-ups.
quotedMessageId,quotedText,quotedRemoteJid) into HermesMessageEventreply context./send-mediaand adds bridge primitives for message reactions, private status replies, status reactions, and explicit-recipient text status posts.platforms.whatsapp.extra.statuses.enabled: trueandingest: true.whatsapp_action, a WhatsApp-specific messaging tool for owner/user-requested advanced actions:react_message,status_reply,status_react, andpost_text_status.Design notes
send_message; this keeps WhatsApp-specific semantics explicit.whatsapp_actionincludesdry_run=trueso agents can inspect the exact bridge endpoint/payload before performing external side effects.status_jid_list; there is intentionally no "all contacts" fallback.replyTois not in the bridge cache, the bridge sends the message without a quote and reportsquoted: false.node:testcan import helper functions without starting an HTTP server or socket.Operational follow-up after merge
Related Issue
No related issue — surfaced from production WhatsApp use where plain-text "@reply" fallbacks felt wrong vs the platform's native quote/reaction UX.
Fixes #
Type of Change
Changes Made
scripts/whatsapp-bridge/bridge.js— WAMessage cache; new/send-media-reply,/react,/status-reply,/status-react,/post-text-statusendpoints; side-effect-light import surface for tests.scripts/whatsapp-bridge/bridge.test.mjs— Node test suite for the new primitives.gateway/platforms/whatsapp.py— quote metadata propagation; adapter methods for reactions/status/replies.tools/whatsapp_action_tool.py— newwhatsapp_actiontool:react_message,status_reply,status_react,post_text_status, withdry_run.tests/tools/test_whatsapp_action_tool.py,tests/gateway/test_whatsapp_*.py— coverage for tool + adapter wiring.How to Test
./venv/bin/python -m pytest tests/tools/test_whatsapp_action_tool.py tests/gateway/test_whatsapp_*.py tests/gateway/test_platform_base.py -q— 188 passing on current rebase.
cd scripts/whatsapp-bridge && npm test -- --test-reporter=specfor the Node bridge primitives.node --check scripts/whatsapp-bridge/bridge.jsand./venv/bin/python -m py_compile tools/whatsapp_action_tool.py gateway/platforms/whatsapp.pyfor syntax sanity.whatsapp_actiontool withdry_run=truefirst to inspect the bridge payload, then run withdry_run=falseagainst a paired WhatsApp session.Checklist
origin/main(2026-05-25; one trivial conflict inwhatsapp.pywas an additive merge — kept upstream's new pre-flight pairing check plus this PR's bridge-found log line)gateway/platforms/*adapters andtools/*modulesNotes for reviewers
whatsapp_actionis a new tool,whatsapp.pyadditions are backward compatible (existing callers see the same methods plus new optional ones).enabled+ingest) precisely because Baileys status support is fragile and shouldn't fail-open into surprise behavior.