feat(whatsapp): add WhatsApp Business Cloud API adapter

Add an official, production-grade WhatsApp integration via Meta's
Business Cloud API as a complement to the existing Baileys bridge.
No bridge subprocess, no QR codes, no account-ban risk — at the cost
of a Meta Business account and a public HTTPS webhook URL.

Setup is fully wizard-driven: 'hermes whatsapp-cloud' walks through
every credential with paste-time validation (catches the #1 trap of
pasting a phone number into the Phone Number ID field), generates a
verify token, and ends with copy-paste instructions for the
cloudflared / Meta-dashboard / Business Manager pieces that can't be
automated. The wizard also points users at Meta's Business Manager
for setting the bot's display name and profile picture.

Feature set:

- Inbound: text, images (with native-vision routing), voice notes
  (STT), documents (small text inlined, larger cached), reply context.
- Outbound: text with WhatsApp-flavored markdown conversion, images,
  videos, documents, opus voice notes via ffmpeg with MP3 fallback.
- Native interactive buttons for clarify, dangerous-command approval,
  and slash-command confirmation flows — matches the Telegram /
  Discord UX, graceful degrades to plain text.
- Read receipts (blue double-checkmarks) and typing indicator,
  using Meta's combined endpoint so they fire in a single API call.
- Webhook security: X-Hub-Signature-256 HMAC verification (raw body,
  constant-time), wamid deduplication, group-shaped-message refusal
  (groups deferred to v2 — Baileys still covers them).
- Full integration with the gateway's session, cron, display-tier,
  prompt-hint, and auth-allowlist systems. Cloud and Baileys can run
  side-by-side against different phone numbers.

Also wires STT (speech-to-text) through Nous's managed audio gateway
for Nous subscribers — previously the default stt.provider=local
required a separate faster-whisper install. New subscribers now get
voice-note transcription out of the box.

Docs: 418-line user guide at website/docs/user-guide/messaging/
whatsapp-cloud.md, sidebar entry, environment-variables reference,
ADDING_A_PLATFORM.md updated with the optional interactive-UX
contract for future adapter authors.

Tests: 100 dedicated tests for the adapter, 32 for the setup wizard,
20 for the Nous subscription STT wiring, plus regression coverage
across display_config, prompt_builder, and the cron scheduler.

Known limitations (deferred until clear demand signal):
- Group chats — use the Baileys bridge if you need them.
- Message templates for 24-hour-window outside-conversation sends —
  reactive chat is unaffected; cron / delegate_task with gaps > 24h
  will fail with a clear error. The agent's system prompt warns the
  model about this so it knows to mention it when scheduling delayed
  messages.
This commit is contained in:
emozilla 2026-05-23 01:07:01 -04:00
parent a7cd254c29
commit 984e6cb5b8
26 changed files with 6368 additions and 287 deletions

View file

@ -1981,6 +1981,25 @@ def cmd_whatsapp(args):
print("⚠ Pairing may not have completed. Run 'hermes whatsapp' to try again.")
def cmd_whatsapp_cloud(args):
"""Set up WhatsApp Business Cloud API (official Meta integration).
Walks the user through the Meta-side credentials (Phone Number ID,
Access Token, App Secret, optional App/WABA IDs) plus webhook
configuration. Includes field-shape validators that catch the most
common setup mistakes (e.g. pasting a phone number into the Phone
Number ID field).
Distinct from ``hermes whatsapp`` (the Baileys bridge wizard) the
two adapters are complementary, not alternatives. See
``hermes_cli/setup_whatsapp_cloud.py``.
"""
_require_tty("whatsapp-cloud")
from hermes_cli.setup_whatsapp_cloud import run_whatsapp_cloud_setup
return run_whatsapp_cloud_setup()
def cmd_setup(args):
"""Interactive setup wizard."""
from hermes_cli.setup import run_setup_wizard
@ -9699,6 +9718,7 @@ def _coalesce_session_name_args(argv: list) -> list:
"gateway",
"setup",
"whatsapp",
"whatsapp-cloud",
"login",
"logout",
"auth",
@ -10560,7 +10580,7 @@ _BUILTIN_SUBCOMMANDS = frozenset(
"model", "pairing", "plugins", "postinstall", "profile", "proxy",
"send", "sessions", "setup",
"skills", "slack", "status", "tools", "uninstall", "update",
"version", "webhook", "whatsapp", "chat", "secrets",
"version", "webhook", "whatsapp", "whatsapp-cloud", "chat", "secrets",
# Help-ish invocations — plugin commands not being listed in
# top-level --help is an acceptable trade-off for skipping an
# expensive eager import of every bundled plugin module.
@ -11311,6 +11331,21 @@ def main():
)
whatsapp_parser.set_defaults(func=cmd_whatsapp)
# =========================================================================
# whatsapp-cloud command (official Meta Cloud API; complement to Baileys)
# =========================================================================
whatsapp_cloud_parser = subparsers.add_parser(
"whatsapp-cloud",
help="Set up WhatsApp Business Cloud API integration",
description=(
"Configure the official Meta WhatsApp Business Cloud API "
"adapter (Business account required, public webhook URL "
"required). Distinct from `hermes whatsapp` which sets up "
"the Baileys bridge for personal accounts."
),
)
whatsapp_cloud_parser.set_defaults(func=cmd_whatsapp_cloud)
# =========================================================================
# slack command
# =========================================================================