* feat(whatsapp): subscribe to inbound reaction events Subscribe to Baileys `messages.reaction` events and surface them as system events for the agent session. Follows the same pattern used by Signal and Slack: listen → parse → route → enqueueSystemEvent. - Add `WebInboundReaction` type and `onReaction` callback to monitor - Parse emoji, sender JID, target message ID from Baileys event - Route via `resolveAgentRoute` and enqueue as system event - Handle self-reaction attribution (reactionKey.fromMe → selfJid) - Skip reaction removals (empty emoji) and status/broadcast JIDs - Outer + inner try/catch for resilience against malformed events - 13 unit tests (monitor-level + system event wiring) - Changelog entry and docs updates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * revert changelog entry to avoid merge conflicts The inbound reaction feature is internal plumbing, not user-facing enough to warrant a changelog entry that will conflict with active PRs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(whatsapp): handle reaction removals and improve sender detection - Emit reaction events with isRemoval flag instead of skipping them - Fall back to chatJid for DM sender when reaction.key is missing - Add chatType and accountId to reaction logs for observability - Update tests to reflect new removal handling behavior Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(whatsapp): gate reactions by DM/group access controls Address Codex review - reactions now respect the same access controls as messages (dmPolicy, allowlists, etc). Self-reactions bypass the check since they're our own actions, not inbound events. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: remove unused senderName field from reaction type Baileys reaction events don't include push names, so this field was dead interface pollution. (Cursor review) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(whatsapp): update reaction docs + suppress pairing for reactions - Update docs: reaction removals now emit events with isRemoval=true - Pass no-op sendMessage to access control to prevent pairing messages being sent when unknown users react (pairing is for messages, not reactions) (Cursor review) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Nick Sullivan <nick@technick.ai> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
23 lines
1.1 KiB
Markdown
23 lines
1.1 KiB
Markdown
---
|
|
summary: "Reaction semantics shared across channels"
|
|
read_when:
|
|
- Working on reactions in any channel
|
|
---
|
|
|
|
# Reaction tooling
|
|
|
|
Shared reaction semantics across channels:
|
|
|
|
- `emoji` is required when adding a reaction.
|
|
- `emoji=""` removes the bot's reaction(s) when supported.
|
|
- `remove: true` removes the specified emoji when supported (requires `emoji`).
|
|
|
|
Channel notes:
|
|
|
|
- **Discord/Slack**: empty `emoji` removes all of the bot's reactions on the message; `remove: true` removes just that emoji.
|
|
- **Google Chat**: empty `emoji` removes the app's reactions on the message; `remove: true` removes just that emoji.
|
|
- **Telegram**: empty `emoji` removes the bot's reactions; `remove: true` also removes reactions but still requires a non-empty `emoji` for tool validation.
|
|
- **WhatsApp**: empty `emoji` removes the bot reaction; `remove: true` maps to empty emoji (still requires `emoji`).
|
|
- **Signal**: inbound reaction notifications emit system events when `channels.signal.reactionNotifications` is enabled.
|
|
- **WhatsApp**: inbound reaction notifications are always surfaced as system events (no configuration required).
|