@elizaos/plugin-whatsapp 2.0.0-alpha.9 → 2.0.0-beta.1

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.
Files changed (54) hide show
  1. package/README.md +283 -0
  2. package/auto-enable.ts +21 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/accounts.d.ts +205 -0
  5. package/dist/accounts.d.ts.map +1 -0
  6. package/dist/actions/index.d.ts +1 -0
  7. package/dist/actions/index.d.ts.map +1 -0
  8. package/dist/api/whatsapp-routes.d.ts +53 -0
  9. package/dist/api/whatsapp-routes.d.ts.map +1 -0
  10. package/dist/baileys/auth.d.ts +10 -0
  11. package/dist/baileys/auth.d.ts.map +1 -0
  12. package/dist/baileys/connection.d.ts +19 -0
  13. package/dist/baileys/connection.d.ts.map +1 -0
  14. package/dist/baileys/message-adapter.d.ts +14 -0
  15. package/dist/baileys/message-adapter.d.ts.map +1 -0
  16. package/dist/baileys/qr-code.d.ts +6 -0
  17. package/dist/baileys/qr-code.d.ts.map +1 -0
  18. package/dist/client.d.ts +99 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/clients/baileys-client.d.ts +18 -0
  21. package/dist/clients/baileys-client.d.ts.map +1 -0
  22. package/dist/clients/factory.d.ts +6 -0
  23. package/dist/clients/factory.d.ts.map +1 -0
  24. package/dist/clients/interface.d.ts +10 -0
  25. package/dist/clients/interface.d.ts.map +1 -0
  26. package/dist/config.d.ts +135 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/connector-account-provider.d.ts +19 -0
  29. package/dist/connector-account-provider.d.ts.map +1 -0
  30. package/dist/index.d.ts +14 -2
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +2352 -840
  33. package/dist/index.js.map +21 -19
  34. package/dist/normalize.d.ts +69 -0
  35. package/dist/normalize.d.ts.map +1 -0
  36. package/dist/pairing-service.d.ts +41 -0
  37. package/dist/pairing-service.d.ts.map +1 -0
  38. package/dist/runtime-service.d.ts +116 -0
  39. package/dist/runtime-service.d.ts.map +1 -0
  40. package/dist/services/whatsapp-pairing.d.ts +41 -0
  41. package/dist/services/whatsapp-pairing.d.ts.map +1 -0
  42. package/dist/setup-routes.d.ts +26 -0
  43. package/dist/setup-routes.d.ts.map +1 -0
  44. package/dist/types.d.ts +370 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/utils/config-detector.d.ts +3 -0
  47. package/dist/utils/config-detector.d.ts.map +1 -0
  48. package/dist/utils/index.d.ts +3 -0
  49. package/dist/utils/index.d.ts.map +1 -0
  50. package/dist/utils/validators.d.ts +10 -0
  51. package/dist/utils/validators.d.ts.map +1 -0
  52. package/dist/workflow-credential-provider.d.ts +21 -0
  53. package/dist/workflow-credential-provider.d.ts.map +1 -0
  54. package/package.json +137 -131
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # plugin-whatsapp
2
+
3
+ WhatsApp plugin for ElizaOS. Supports both WhatsApp Cloud API and Baileys (QR authentication), enabling agents to send and receive messages, media, reactions, and interactive content via WhatsApp.
4
+
5
+ ## Features
6
+
7
+ - **Text Messages**: Send and receive text messages with URL preview
8
+ - **Media Messages**: Send images, videos, audio, documents, and stickers
9
+ - **Reactions**: Send and remove emoji reactions on messages
10
+ - **Interactive Messages**: Send button and list messages for rich interactions
11
+ - **Location Messages**: Share location data with name and address
12
+ - **Template Messages**: Send pre-approved message templates
13
+ - **Webhooks**: Handle incoming messages and status updates
14
+ - **Baileys QR Auth**: Connect personal WhatsApp accounts with QR login + session persistence
15
+ - **Message Status**: Track sent, delivered, read, and failed statuses
16
+ - **Media Downloads**: Retrieve media URLs for incoming messages
17
+
18
+ ## Installation
19
+
20
+ ### TypeScript
21
+
22
+ ```bash
23
+ npm install @elizaos/plugin-whatsapp
24
+ ```
25
+ ## Configuration
26
+
27
+ ### Environment Variables
28
+
29
+ | Variable | Required | Description |
30
+ |----------|----------|-------------|
31
+ | `WHATSAPP_ACCESS_TOKEN` | Yes | WhatsApp Business API access token |
32
+ | `WHATSAPP_PHONE_NUMBER_ID` | Yes | Phone number ID from WhatsApp Business API |
33
+ | `WHATSAPP_WEBHOOK_VERIFY_TOKEN` | No | Token for webhook verification |
34
+ | `WHATSAPP_BUSINESS_ACCOUNT_ID` | No | Business account ID |
35
+ | `WHATSAPP_API_VERSION` | No | Graph API version (default: v24.0) |
36
+ | `WHATSAPP_AUTH_METHOD` | No | `cloudapi` or `baileys` (auto-detected if omitted) |
37
+ | `WHATSAPP_AUTH_DIR` | No | Path for Baileys multi-file auth state |
38
+ | `WHATSAPP_SESSION_PATH` | No | Alternative to `WHATSAPP_AUTH_DIR` for Baileys auth state |
39
+ | `WHATSAPP_PRINT_QR` | No | Print QR in terminal for Baileys auth (default: true) |
40
+ | `WHATSAPP_DM_POLICY` | No | DM handling policy: `open`, `allowlist`, `pairing`, or `disabled` |
41
+ | `WHATSAPP_GROUP_POLICY` | No | Group handling policy: `open`, `allowlist`, or `disabled` |
42
+ | `WHATSAPP_ALLOW_FROM` | No | Comma-separated allowlist for DM senders (when DM policy is `allowlist`) |
43
+ | `WHATSAPP_GROUP_ALLOW_FROM` | No | Comma-separated allowlist for group senders (when group policy is `allowlist`) |
44
+
45
+ ### TypeScript Configuration
46
+
47
+ The plugin self-registers `WhatsAppConnectorService` on the elizaOS runtime and reads its config from runtime settings / environment variables — no manual construction is required. Just register the default export on your character/agent:
48
+
49
+ ```typescript
50
+ import whatsappPlugin from "@elizaos/plugin-whatsapp";
51
+
52
+ export const character = {
53
+ // ...
54
+ plugins: [whatsappPlugin],
55
+ };
56
+ ```
57
+
58
+ The service picks up `WHATSAPP_ACCESS_TOKEN` + `WHATSAPP_PHONE_NUMBER_ID` (Cloud API) or `WHATSAPP_AUTH_DIR` (Baileys / QR) automatically. See the env-var table above.
59
+
60
+ To access the service at runtime (e.g. to send a message from your own code):
61
+
62
+ ```typescript
63
+ import type { WhatsAppConnectorService } from "@elizaos/plugin-whatsapp";
64
+
65
+ const service = runtime.getService<WhatsAppConnectorService>("whatsapp");
66
+ await service?.sendMessage({ type: "text", to: "+14155552671", content: "hello" });
67
+ ```
68
+
69
+ ## Usage
70
+
71
+ ### Sending Messages
72
+
73
+ The TypeScript snippets below use two variables:
74
+
75
+ - `service` — the registered `WhatsAppConnectorService`, obtained via `runtime.getService<WhatsAppConnectorService>("whatsapp")`. This is the recommended path: it routes through the same auth + policy stack the agent uses for incoming messages.
76
+ - `client` — the underlying low-level client (`IWhatsAppClient`), used only for advanced media APIs not exposed on the service. Construct one with the exported `ClientFactory.create({ accessToken, phoneNumberId })` (Cloud API) or `ClientFactory.create({ authDir })` (Baileys) — the concrete `WhatsAppClient` / `BaileysClient` classes are internal.
77
+
78
+ #### Text Message
79
+
80
+ **TypeScript**:
81
+ ```typescript
82
+ const service = runtime.getService<WhatsAppConnectorService>("whatsapp");
83
+ await service?.sendMessage({ type: "text", to: "1234567890", content: "Hello, World!" });
84
+ ```
85
+
86
+ **Python**:
87
+
88
+ **Rust**:
89
+
90
+ #### Image Message
91
+
92
+ **TypeScript**:
93
+ ```typescript
94
+ await client.sendImage('1234567890', 'https://example.com/image.jpg', 'Caption');
95
+ ```
96
+
97
+ **Python**:
98
+
99
+ **Rust**:
100
+
101
+ #### Interactive Button Message
102
+
103
+ **TypeScript**:
104
+ ```typescript
105
+ await client.sendButtonMessage(
106
+ '1234567890',
107
+ 'Choose an option:',
108
+ [
109
+ { id: 'opt1', title: 'Option 1' },
110
+ { id: 'opt2', title: 'Option 2' },
111
+ { id: 'opt3', title: 'Option 3' },
112
+ ],
113
+ 'Header Text',
114
+ 'Footer Text'
115
+ );
116
+ ```
117
+
118
+ **Python**:
119
+
120
+ **Rust**:
121
+
122
+ ### Sending Reactions
123
+
124
+ **TypeScript**:
125
+ ```typescript
126
+ await client.sendReaction({
127
+ to: '1234567890',
128
+ messageId: 'wamid.xxx',
129
+ emoji: '👍',
130
+ });
131
+
132
+ // Remove reaction
133
+ await client.removeReaction('1234567890', 'wamid.xxx');
134
+ ```
135
+
136
+ **Python**:
137
+
138
+ **Rust**:
139
+
140
+ ### Handling Webhooks
141
+
142
+ **TypeScript**:
143
+ ```typescript
144
+ import express from 'express';
145
+
146
+ const app = express();
147
+
148
+ const service = runtime.getService<WhatsAppConnectorService>("whatsapp");
149
+
150
+ // Verification endpoint
151
+ app.get('/webhook', (req, res) => {
152
+ const mode = String(req.query['hub.mode'] ?? '');
153
+ const token = String(req.query['hub.verify_token'] ?? '');
154
+ const challenge = String(req.query['hub.challenge'] ?? '');
155
+
156
+ const reply = service?.verifyWebhook(mode, token, challenge);
157
+ if (reply) {
158
+ res.status(200).send(reply);
159
+ } else {
160
+ res.sendStatus(403);
161
+ }
162
+ });
163
+
164
+ // Message handling endpoint
165
+ app.post('/webhook', express.json(), async (req, res) => {
166
+ await service?.handleWebhook(req.body);
167
+ res.sendStatus(200);
168
+ });
169
+ ```
170
+
171
+ **Python**:
172
+
173
+ **Rust**:
174
+
175
+ ### Event Handling
176
+
177
+ **TypeScript** (using event emitter pattern):
178
+ ```typescript
179
+ // Events are emitted by the webhook handler
180
+ webhookHandler.onMessage((message) => {
181
+ console.log('Message received:', message);
182
+ });
183
+
184
+ webhookHandler.onStatus((status) => {
185
+ console.log('Status update:', status);
186
+ });
187
+ ```
188
+
189
+ **Python**:
190
+
191
+ **Rust**:
192
+
193
+ ## Actions
194
+
195
+ WhatsApp messaging is exposed through the canonical message connector actions.
196
+ Use `source: "whatsapp"` when a request needs to target WhatsApp explicitly.
197
+ Media, templates, and interactive messages remain available through the service
198
+ and low-level client APIs shown above; they are not advertised as separate
199
+ executable action names.
200
+
201
+ | Primary action | Operation | Description |
202
+ |----------------|-----------|-------------|
203
+ | `MESSAGE` | `send` | Send a message to a phone number, contact, user, group, or room |
204
+ | `MESSAGE` | `read` | Read recent WhatsApp conversation messages |
205
+ | `MESSAGE` | `search` | Search WhatsApp conversation history |
206
+ | `MESSAGE` | `react` | Send or remove a reaction on a message |
207
+ | `MESSAGE` | `get_user` | Resolve a WhatsApp contact or user |
208
+
209
+ ## Event Types
210
+
211
+ | Event | Description |
212
+ |-------|-------------|
213
+ | `MESSAGE_RECEIVED` | New message received |
214
+ | `MESSAGE_SENT` | Message was sent |
215
+ | `MESSAGE_DELIVERED` | Message was delivered |
216
+ | `MESSAGE_READ` | Message was read |
217
+ | `MESSAGE_FAILED` | Message delivery failed |
218
+ | `REACTION_RECEIVED` | Reaction received on a message |
219
+ | `REACTION_SENT` | Reaction was sent |
220
+ | `INTERACTIVE_REPLY` | User replied to interactive message |
221
+ | `WEBHOOK_VERIFIED` | Webhook was verified |
222
+
223
+ ## Common Reactions
224
+
225
+ The plugin provides constants for common reaction emojis:
226
+
227
+ | Name | Emoji |
228
+ |------|-------|
229
+ | `THUMBS_UP` | 👍 |
230
+ | `THUMBS_DOWN` | 👎 |
231
+ | `HEART` | ❤️ |
232
+ | `LAUGHING` | 😂 |
233
+ | `SURPRISED` | 😮 |
234
+ | `SAD` | 😢 |
235
+ | `PRAYING` | 🙏 |
236
+ | `CLAPPING` | 👏 |
237
+ | `FIRE` | 🔥 |
238
+ | `CELEBRATION` | 🎉 |
239
+
240
+ ## API Reference
241
+
242
+ ### WhatsAppClient / WhatsAppService
243
+
244
+ | Method | Description |
245
+ |--------|-------------|
246
+ | `sendTextMessage(to, text)` | Send a text message |
247
+ | `sendImage(to, url, caption?)` | Send an image |
248
+ | `sendVideo(to, url, caption?)` | Send a video |
249
+ | `sendAudio(to, url)` | Send audio |
250
+ | `sendDocument(to, url, filename?, caption?)` | Send a document |
251
+ | `sendLocation(to, lat, lng, name?, address?)` | Send a location |
252
+ | `sendReaction(params)` | Send a reaction |
253
+ | `removeReaction(to, messageId)` | Remove a reaction |
254
+ | `sendButtonMessage(to, body, buttons, header?, footer?)` | Send button message |
255
+ | `sendListMessage(to, body, buttonText, sections, header?, footer?)` | Send list message |
256
+ | `markMessageAsRead(messageId)` | Mark a message as read |
257
+ | `getMediaUrl(mediaId)` | Get download URL for media |
258
+ | `verifyWebhook(token)` | Verify webhook token |
259
+
260
+ ## Troubleshooting
261
+
262
+ ### Common Issues
263
+
264
+ 1. **Message not delivered**: Ensure the phone number is in international format without `+` prefix (e.g., `1234567890`).
265
+
266
+ 2. **Webhook not verified**: Check that your `WHATSAPP_WEBHOOK_VERIFY_TOKEN` matches the token configured in the Meta Developer Portal.
267
+
268
+ 3. **Media upload fails**: Ensure media URLs are publicly accessible and the file format is supported by WhatsApp.
269
+
270
+ 4. **Rate limiting**: WhatsApp has rate limits on the number of messages. Implement exponential backoff for retries.
271
+
272
+ ### Error Codes
273
+
274
+ | Code | Description |
275
+ |------|-------------|
276
+ | 130429 | Rate limit reached |
277
+ | 131000 | Something went wrong |
278
+ | 131030 | Invalid recipient |
279
+ | 131051 | Message type is not supported |
280
+
281
+ ## License
282
+
283
+ MIT
package/auto-enable.ts ADDED
@@ -0,0 +1,21 @@
1
+ // Auto-enable check for @elizaos/plugin-whatsapp.
2
+ //
3
+ // Plugin manifest entry-point — referenced by package.json's
4
+ // `elizaos.plugin.autoEnableModule`. Keep this module light: env reads only,
5
+ // no service init, no transitive imports of the full plugin runtime. The
6
+ // auto-enable engine loads dozens of these per boot.
7
+ import type { PluginAutoEnableContext } from "@elizaos/core";
8
+
9
+ /** Enable when a `whatsapp` connector block is present and not explicitly disabled. */
10
+ export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
11
+ const c = (ctx.config?.connectors as Record<string, unknown> | undefined)
12
+ ?.whatsapp;
13
+ if (!c || typeof c !== "object") return false;
14
+ const config = c as Record<string, unknown>;
15
+ if (config.enabled === false) return false;
16
+ // The full per-connector field check (token/phoneNumberId) lives in the
17
+ // central engine's isConnectorConfigured. We delegate to a simple "block
18
+ // present + not explicitly disabled" check here; the central engine's
19
+ // stricter check remains as a fallback during migration.
20
+ return true;
21
+ }