@elizaos/plugin-x 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Shaw Walters and elizaOS Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,536 @@
1
+ # Eliza Twitter/X Client
2
+
3
+ This package provides Twitter/X integration for the Eliza AI agent using the official Twitter API v2.
4
+
5
+ ## 🚨 TL;DR - Quick Setup
6
+
7
+ **Just want your bot to post tweets? Here's the fastest path:**
8
+
9
+ 1. **Get Twitter Developer account** β†’ https://developer.twitter.com
10
+ 2. **Create an app** β†’ Enable "Read and write" permissions
11
+ 3. Choose your auth mode:
12
+ - **Option A (default, legacy): OAuth 1.0a env vars**
13
+ - API Key & Secret (from "Consumer Keys")
14
+ - Access Token & Secret (from "Authentication Tokens")
15
+
16
+ - **Option B (recommended): β€œlogin + approve” OAuth 2.0 (PKCE)**
17
+ - Client ID (from "OAuth 2.0 Client ID")
18
+ - Redirect URI (loopback recommended)
19
+
20
+ 4. **Add to `.env`:**
21
+
22
+ ```bash
23
+ # Option A: legacy OAuth 1.0a (default)
24
+ TWITTER_AUTH_MODE=env
25
+ TWITTER_API_KEY=xxx
26
+ TWITTER_API_SECRET_KEY=xxx
27
+ TWITTER_ACCESS_TOKEN=xxx
28
+ TWITTER_ACCESS_TOKEN_SECRET=xxx
29
+
30
+ # Option B: OAuth 2.0 PKCE (interactive login + approve, no client secret)
31
+ # TWITTER_AUTH_MODE=oauth
32
+ # TWITTER_CLIENT_ID=xxx
33
+ # TWITTER_REDIRECT_URI=http://127.0.0.1:8080/callback
34
+
35
+ TWITTER_ENABLE_POST=true
36
+ TWITTER_POST_IMMEDIATELY=true
37
+ ```
38
+
39
+ 5. **Run:** `bun start`
40
+
41
+ Tip: if you use **OAuth 2.0 PKCE**, the plugin will print an authorization URL on first run and store tokens for you (no manual token pasting).
42
+
43
+ ## Features
44
+
45
+ - βœ… **Autonomous tweet posting** with configurable intervals
46
+ - βœ… **Timeline monitoring** and interaction
47
+ - βœ… **Mention and reply handling**
48
+ - βœ… **Search functionality**
49
+ - βœ… **Direct message support**
50
+ - βœ… **Advanced timeline algorithms** with weighted scoring
51
+ - βœ… **Comprehensive caching system**
52
+ - βœ… **Built-in rate limiting and retry mechanisms**
53
+ - βœ… **Discovery service** for autonomous content discovery and growth
54
+
55
+ ## Prerequisites
56
+
57
+ - Twitter Developer Account with API v2 access
58
+ - Either Twitter OAuth 1.0a credentials (legacy env vars) or OAuth 2.0 Client ID (PKCE)
59
+ - Node.js and bun installed
60
+
61
+ ## πŸš€ Quick Start
62
+
63
+ ### Step 1: Get Twitter Developer Access
64
+
65
+ 1. Apply for a developer account at https://developer.twitter.com
66
+ 2. Create a new app in the [Developer Portal](https://developer.twitter.com/en/portal/projects-and-apps)
67
+ 3. Ensure your app has API v2 access
68
+
69
+ ### Step 2: Configure App Permissions for Posting
70
+
71
+ **⚠️ CRITICAL: Default apps can only READ. You must enable WRITE permissions to post tweets!**
72
+
73
+ 1. In your app settings, go to **"User authentication settings"**
74
+ 2. Configure exactly as shown:
75
+
76
+ **App permissions**: `Read and write` βœ…
77
+
78
+ **Type of App**: `Web App, Automated App or Bot`
79
+
80
+ **Required URLs** (copy these exactly):
81
+
82
+ ```
83
+ Callback URI: http://localhost:3000/callback
84
+ Website URL: https://github.com/elizaos/eliza
85
+ ```
86
+
87
+ **Optional fields**:
88
+
89
+ ```
90
+ Organization name: ElizaOS
91
+ Organization URL: https://github.com/elizaos/eliza
92
+ ```
93
+
94
+ 3. Click **Save**
95
+
96
+ ### Step 3: Get the RIGHT Credentials (OAuth 1.0a)
97
+
98
+ You can use either legacy **OAuth 1.0a** env vars (default) or **OAuth 2.0 PKCE** (β€œlogin + approve”).
99
+
100
+ In your app's **"Keys and tokens"** page, you'll see several sections. Here's what to use:
101
+
102
+ ```
103
+ βœ… USE THESE when TWITTER_AUTH_MODE=env (OAuth 1.0a):
104
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
105
+ β”‚ Consumer Keys β”‚
106
+ β”‚ β”œβ”€ API Key: xxx...xxx β†’ TWITTER_API_KEY β”‚
107
+ β”‚ └─ API Key Secret: xxx...xxx β†’ TWITTER_API_SECRET_KEY β”‚
108
+ β”‚ β”‚
109
+ β”‚ Authentication Tokens β”‚
110
+ β”‚ β”œβ”€ Access Token: xxx...xxx β†’ TWITTER_ACCESS_TOKEN β”‚
111
+ β”‚ └─ Access Token Secret: xxx β†’ TWITTER_ACCESS_TOKEN_SECRET β”‚
112
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
113
+
114
+ βœ… USE THESE when TWITTER_AUTH_MODE=oauth (OAuth 2.0 PKCE):
115
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
116
+ β”‚ OAuth 2.0 Client ID and Client Secret β”‚
117
+ β”‚ β”œβ”€ Client ID: xxx...xxx β†’ TWITTER_CLIENT_ID β”‚
118
+ β”‚ └─ Client Secret: xxx...xxx ← NOT USED (do not put in env) β”‚
119
+ β”‚ β”‚
120
+ β”‚ Bearer Token ← NOT USED β”‚
121
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
122
+ ```
123
+
124
+ **After enabling write permissions, you MUST:**
125
+
126
+ 1. Click **"Regenerate"** on Access Token & Secret
127
+ 2. Copy the NEW tokens (old ones won't have write access)
128
+ 3. Look for "Created with Read and Write permissions" βœ…
129
+
130
+ ### Step 4: Configure Environment Variables
131
+
132
+ Create or edit `.env` file in your project root:
133
+
134
+ ```bash
135
+ # Auth mode (default: env)
136
+ # - env: legacy OAuth 1.0a keys/tokens
137
+ # - oauth: β€œlogin + approve” OAuth 2.0 PKCE (no client secret in plugin)
138
+ TWITTER_AUTH_MODE=env
139
+ TWITTER_DEFAULT_ACCOUNT_ID=default
140
+
141
+ # REQUIRED: OAuth 1.0a Credentials (from "Consumer Keys" section)
142
+ TWITTER_API_KEY=your_api_key_here # From "API Key"
143
+ TWITTER_API_SECRET_KEY=your_api_key_secret_here # From "API Key Secret"
144
+
145
+ # REQUIRED: OAuth 1.0a Tokens (from "Authentication Tokens" section)
146
+ TWITTER_ACCESS_TOKEN=your_access_token_here # Must have "Read and Write"
147
+ TWITTER_ACCESS_TOKEN_SECRET=your_token_secret_here # Regenerate after permission change
148
+
149
+ # ---- OR ----
150
+ # OAuth 2.0 PKCE (β€œlogin + approve”) configuration:
151
+ # TWITTER_AUTH_MODE=oauth
152
+ # TWITTER_CLIENT_ID=your_oauth2_client_id_here
153
+ # TWITTER_REDIRECT_URI=http://127.0.0.1:8080/callback
154
+ # Optional:
155
+ # TWITTER_SCOPES="tweet.read tweet.write users.read offline.access"
156
+
157
+ # Basic Configuration
158
+ TWITTER_DRY_RUN=false # Set to true to test without posting
159
+ TWITTER_ENABLE_POST=true # Enable autonomous tweet posting
160
+
161
+ # Optional: Posting Configuration
162
+ TWITTER_POST_IMMEDIATELY=true # Post on startup (great for testing)
163
+ TWITTER_POST_INTERVAL=120 # Minutes between posts (default: 120)
164
+ # For more natural timing, use MIN/MAX intervals:
165
+ TWITTER_POST_INTERVAL_MIN=90 # Minimum minutes between posts
166
+ TWITTER_POST_INTERVAL_MAX=150 # Maximum minutes between posts
167
+ ```
168
+
169
+ When using **TWITTER_AUTH_MODE=oauth**, the plugin will:
170
+
171
+ - Print an authorization URL on first run
172
+ - Capture the callback via a local loopback server **or** ask you to paste the redirected URL
173
+ - Persist tokens per `accountId` via Eliza runtime cache if available, otherwise a local token file under `~/.eliza/twitter/accounts/<accountId>/oauth2.tokens.json`
174
+
175
+ For multi-account pilots, route connector targets with `accountId`. The plugin defaults to `TWITTER_DEFAULT_ACCOUNT_ID` when no target/content account is provided. You can also provide account-scoped credentials through `TWITTER_ACCOUNTS` JSON until the shared connector account store is available.
176
+
177
+ ### Step 5: Run Your Bot
178
+
179
+ ```typescript
180
+ // Your character should include the twitter plugin
181
+ const character = {
182
+ // ... other config
183
+ plugins: [
184
+ // Required for content generation
185
+ "@elizaos/plugin-x", // X (Twitter) functionality
186
+ ],
187
+ postExamples: [
188
+ // Examples for tweet generation
189
+ "Just discovered an amazing pattern in the data...",
190
+ "The future of AI is collaborative intelligence",
191
+ // ... more examples
192
+ ],
193
+ };
194
+ ```
195
+
196
+ Then start your bot:
197
+
198
+ ```bash
199
+ bun run start
200
+ ```
201
+
202
+ ## πŸ“‹ Complete Configuration Reference
203
+
204
+ ```bash
205
+ # Required Twitter API v2 Credentials (OAuth 1.0a)
206
+ TWITTER_API_KEY= # Consumer API Key
207
+ TWITTER_API_SECRET_KEY= # Consumer API Secret
208
+ TWITTER_ACCESS_TOKEN= # Access Token (with write permissions)
209
+ TWITTER_ACCESS_TOKEN_SECRET= # Access Token Secret
210
+
211
+ # Core Configuration
212
+ TWITTER_DRY_RUN=false # Set to true for testing without posting
213
+ TWITTER_TARGET_USERS= # Comma-separated usernames to target (use "*" for all)
214
+ TWITTER_RETRY_LIMIT=5 # Maximum retry attempts for failed operations
215
+
216
+ # Feature Toggles
217
+ TWITTER_ENABLE_POST=false # Enable autonomous tweet posting
218
+ TWITTER_ENABLE_REPLIES=true # Enable mention and reply handling
219
+ TWITTER_ENABLE_ACTIONS=false # Enable timeline actions (likes, retweets, quotes)
220
+ TWITTER_ENABLE_DISCOVERY= # Enable discovery service (defaults to true if ACTIONS enabled)
221
+
222
+ # Timing Configuration (all in minutes)
223
+ # For natural behavior, set MIN/MAX intervals - the agent will randomly choose between them
224
+ # If MIN/MAX not set, falls back to the fixed interval values
225
+
226
+ # Post intervals
227
+ TWITTER_POST_INTERVAL=120 # Fixed interval between posts (default: 120, used if MIN/MAX not set)
228
+ TWITTER_POST_INTERVAL_MIN=90 # Minimum minutes between posts (default: 90)
229
+ TWITTER_POST_INTERVAL_MAX=150 # Maximum minutes between posts (default: 150)
230
+
231
+ # Engagement intervals
232
+ TWITTER_ENGAGEMENT_INTERVAL=30 # Fixed interval for interactions (default: 30, used if MIN/MAX not set)
233
+ TWITTER_ENGAGEMENT_INTERVAL_MIN=20 # Minimum minutes between engagements (default: 20)
234
+ TWITTER_ENGAGEMENT_INTERVAL_MAX=40 # Maximum minutes between engagements (default: 40)
235
+
236
+ # Discovery intervals
237
+ TWITTER_DISCOVERY_INTERVAL_MIN=15 # Minimum minutes between discovery cycles (default: 15)
238
+ TWITTER_DISCOVERY_INTERVAL_MAX=30 # Maximum minutes between discovery cycles (default: 30)
239
+
240
+ # Engagement Limits
241
+ TWITTER_MAX_ENGAGEMENTS_PER_RUN=5 # Maximum interactions per engagement cycle (default: 5)
242
+ TWITTER_MAX_TWEET_LENGTH=280 # Maximum tweet length
243
+
244
+ # Discovery Service Settings
245
+ TWITTER_MIN_FOLLOWER_COUNT=100 # Minimum followers for accounts to follow
246
+ TWITTER_MAX_FOLLOWS_PER_CYCLE=5 # Maximum accounts to follow per discovery cycle
247
+ ```
248
+
249
+ ## πŸ” Discovery Service
250
+
251
+ The Twitter Discovery Service enables autonomous content discovery and engagement, helping your agent build a following and interact with relevant content on Twitter.
252
+
253
+ ### Overview
254
+
255
+ The discovery service autonomously:
256
+
257
+ - Searches for content related to your agent's topics
258
+ - Identifies high-quality accounts to follow
259
+ - Engages with relevant tweets through likes, replies, and quotes
260
+ - Builds up your agent's timeline by following interesting accounts
261
+
262
+ ### Configuration
263
+
264
+ ```bash
265
+ # Enable discovery service (defaults to true if TWITTER_ENABLE_ACTIONS=true)
266
+ TWITTER_ENABLE_DISCOVERY=true
267
+
268
+ # Discovery interval in minutes (default: 30)
269
+ TWITTER_DISCOVERY_INTERVAL=30
270
+
271
+ # Minimum follower count for accounts to follow (default: 100)
272
+ TWITTER_MIN_FOLLOWER_COUNT=100
273
+
274
+ # Maximum accounts to follow per cycle (default: 5)
275
+ TWITTER_MAX_FOLLOWS_PER_CYCLE=5
276
+
277
+ # Maximum engagements per cycle (default: 10)
278
+ TWITTER_MAX_ENGAGEMENTS_PER_RUN=10
279
+ ```
280
+
281
+ ### How It Works
282
+
283
+ 1. **Content Discovery**: Searches for tweets containing your agent's topics
284
+ 2. **Account Scoring**: Scores accounts based on quality (follower count) and relevance
285
+ 3. **Tweet Scoring**: Scores tweets for engagement based on relevance:
286
+ - Like: score > 0.6
287
+ - Reply: score > 0.8
288
+ - Quote: score > 0.85
289
+ 4. **Memory System**: Tracks engaged tweets and followed accounts to avoid duplicates
290
+
291
+ ### Character Configuration
292
+
293
+ The discovery service uses your agent's character configuration:
294
+
295
+ ```json
296
+ {
297
+ "name": "YourAgent",
298
+ "topics": [
299
+ "artificial intelligence",
300
+ "machine learning",
301
+ "web3",
302
+ "blockchain"
303
+ ],
304
+ "bio": "AI researcher interested in decentralized systems"
305
+ }
306
+ ```
307
+
308
+ If topics aren't specified, the service extracts them from the bio.
309
+
310
+ ## 🎯 Common Use Cases
311
+
312
+ ### Just Want to Post Tweets?
313
+
314
+ ```bash
315
+ # Minimal setup for posting only
316
+ TWITTER_API_KEY=xxx
317
+ TWITTER_API_SECRET_KEY=xxx
318
+ TWITTER_ACCESS_TOKEN=xxx # Must have write permissions!
319
+ TWITTER_ACCESS_TOKEN_SECRET=xxx
320
+
321
+ TWITTER_ENABLE_POST=true
322
+ TWITTER_POST_IMMEDIATELY=true # Great for testing
323
+ TWITTER_ENABLE_REPLIES=false # Disable interactions
324
+ TWITTER_ENABLE_ACTIONS=false # Disable timeline actions
325
+ ```
326
+
327
+ ### Want Full Interaction Bot?
328
+
329
+ ```bash
330
+ # Full interaction setup
331
+ TWITTER_API_KEY=xxx
332
+ TWITTER_API_SECRET_KEY=xxx
333
+ TWITTER_ACCESS_TOKEN=xxx
334
+ TWITTER_ACCESS_TOKEN_SECRET=xxx
335
+
336
+ TWITTER_ENABLE_POST=true
337
+ TWITTER_ENABLE_REPLIES=true
338
+ TWITTER_ENABLE_ACTIONS=true # Enables likes, retweets, quotes
339
+ TWITTER_ENABLE_DISCOVERY=true # Enables growth features
340
+ ```
341
+
342
+ ### Testing Without Posting?
343
+
344
+ ```bash
345
+ # Dry run mode
346
+ TWITTER_DRY_RUN=true # Simulates all actions
347
+ TWITTER_ENABLE_POST=true
348
+ TWITTER_POST_IMMEDIATELY=true
349
+ ```
350
+
351
+ ## 🚨 Troubleshooting
352
+
353
+ ### 403 Errors When Engaging with Tweets
354
+
355
+ If you see errors like "Failed to create tweet: Request failed with code 403", this usually means:
356
+
357
+ 1. **Missing Write Permissions**: Make sure your Twitter app has "Read and write" permissions
358
+ - Go to your app settings in the Twitter Developer Portal
359
+ - Check that App permissions shows "Read and write" βœ…
360
+ - If not, change it and regenerate your Access Token & Secret
361
+
362
+ 2. **Protected Accounts**: The bot may be trying to engage with protected/private accounts
363
+ - The plugin now automatically skips these with a warning
364
+
365
+ 3. **Self-Engagement**: Trying to reply to or quote your own tweets
366
+ - Twitter API doesn't allow this and returns 403
367
+
368
+ 4. **Account Restrictions**: Your account may have restrictions
369
+ - Check if your account is in good standing
370
+ - Ensure you're not violating Twitter's automation rules
371
+
372
+ The plugin will now:
373
+
374
+ - Automatically detect and skip 403 errors with a warning
375
+ - Continue processing other tweets
376
+ - Mark failed tweets as "skip" to avoid retrying
377
+
378
+ ### Other Common Issues
379
+
380
+ ### "403 Forbidden" When Posting
381
+
382
+ This is the #1 issue! Your app has read-only permissions.
383
+
384
+ **Solution:**
385
+
386
+ 1. Go to app settings β†’ "User authentication settings"
387
+ 2. Change to "Read and write"
388
+ 3. Save settings
389
+ 4. **CRITICAL**: Regenerate your Access Token & Secret
390
+ 5. Update `.env` with NEW tokens
391
+ 6. Restart your bot
392
+
393
+ **How to verify:** In "Keys and tokens", your Access Token should show "Created with Read and Write permissions"
394
+
395
+ ### "Could not authenticate you"
396
+
397
+ This usually means your credentials don’t match your selected auth mode.
398
+
399
+ **Solution:**
400
+
401
+ - If `TWITTER_AUTH_MODE=env`:
402
+ - Use credentials from "Consumer Keys" section (API Key/Secret)
403
+ - Use credentials from "Authentication Tokens" section (Access Token/Secret)
404
+ - Do not use OAuth 2.0 Client ID/Client Secret/Bearer Token for this mode
405
+ - If `TWITTER_AUTH_MODE=oauth`:
406
+ - Use OAuth 2.0 **Client ID** (`TWITTER_CLIENT_ID`)
407
+ - Set a loopback redirect URI (`TWITTER_REDIRECT_URI`, e.g. `http://127.0.0.1:8080/callback`)
408
+ - Do not set/ship a client secret (PKCE flow)
409
+
410
+ ### Bot Not Posting Automatically
411
+
412
+ **Checklist:**
413
+
414
+ - βœ… Is `TWITTER_ENABLE_POST=true`?
415
+ - βœ… Does your character have `postExamples`?
416
+ - βœ… Check logs for "Twitter posting is ENABLED"
417
+ - βœ… Try `TWITTER_POST_IMMEDIATELY=true` for testing
418
+
419
+ ### Timeline Not Loading
420
+
421
+ **Common causes:**
422
+
423
+ - Rate limiting (check Twitter Developer Portal)
424
+ - Invalid credentials
425
+ - Account restrictions
426
+
427
+ ### "Invalid or expired token"
428
+
429
+ Your tokens may have been revoked or regenerated.
430
+
431
+ **Solution:**
432
+
433
+ 1. Go to Twitter Developer Portal
434
+ 2. Regenerate all tokens
435
+ 3. Update `.env`
436
+ 4. Restart bot
437
+
438
+ ## πŸ“š Advanced Features
439
+
440
+ ### Timeline Processing
441
+
442
+ The plugin supports two main approaches:
443
+
444
+ - **Timeline Actions**: Process home timeline for likes, retweets, and quotes
445
+ - **Targeted Interactions**: Reply to mentions and specific users
446
+
447
+ ### Target User Configuration
448
+
449
+ ```bash
450
+ # Interact with everyone (default)
451
+ TWITTER_TARGET_USERS=
452
+
453
+ # Interact with specific users only
454
+ TWITTER_TARGET_USERS=user1,user2,user3
455
+
456
+ # Interact with everyone (explicit)
457
+ TWITTER_TARGET_USERS=*
458
+ ```
459
+
460
+ ### Natural Posting Intervals
461
+
462
+ The plugin adds variance to all intervals for more human-like behavior:
463
+
464
+ - Post intervals vary by Β±20% by default
465
+ - Discovery intervals vary by Β±10 minutes
466
+ - Engagement intervals vary based on activity
467
+
468
+ ### Request Queue & Rate Limiting
469
+
470
+ The plugin includes sophisticated rate limiting:
471
+
472
+ - Automatic retry with exponential backoff
473
+ - Request queue to prevent API abuse
474
+ - Configurable retry limits
475
+ - Built-in caching to reduce API calls
476
+
477
+ ## πŸ§ͺ Development & Testing
478
+
479
+ ```bash
480
+ # Run tests
481
+ bun test
482
+
483
+ # Run with debug logging
484
+ DEBUG=eliza:* bun start
485
+
486
+ # Test without posting
487
+ TWITTER_DRY_RUN=true bun start
488
+ ```
489
+
490
+ ### Testing Checklist
491
+
492
+ 1. **Test Auth**: Check logs for successful Twitter login
493
+ 2. **Test Posting**: Set `TWITTER_POST_IMMEDIATELY=true`
494
+ 3. **Test Dry Run**: Use `TWITTER_DRY_RUN=true` first
495
+ 4. **Monitor Logs**: Look for "Twitter posting is ENABLED"
496
+
497
+ ## πŸ”’ Security Best Practices
498
+
499
+ - Store credentials in `.env` file (never commit!)
500
+ - Use `.env.local` for local development
501
+ - Regularly rotate API keys
502
+ - Monitor API usage in Developer Portal
503
+ - Enable only necessary permissions
504
+ - Review [Twitter's automation rules](https://help.twitter.com/en/rules-and-policies/twitter-automation)
505
+
506
+ ## πŸ“Š API Usage & Limits
507
+
508
+ This plugin uses Twitter API v2 endpoints efficiently:
509
+
510
+ - **Home Timeline**: Cached and refreshed periodically
511
+ - **Tweet Creation**: Rate limited automatically
512
+ - **User Lookups**: Cached to reduce calls
513
+ - **Search**: Configurable intervals
514
+
515
+ Monitor your usage at: https://developer.twitter.com/en/portal/dashboard
516
+
517
+ ## πŸ“– Additional Resources
518
+
519
+ - [Twitter API v2 Documentation](https://developer.twitter.com/en/docs/twitter-api)
520
+ - [Twitter OAuth 1.0a Guide](https://developer.twitter.com/en/docs/authentication/oauth-1-0a)
521
+ - [Twitter OAuth 2.0 (Authorization Code with PKCE)](https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code)
522
+ - [Rate Limits Reference](https://developer.twitter.com/en/docs/twitter-api/rate-limits)
523
+ - [ElizaOS Documentation](https://github.com/elizaos/eliza)
524
+
525
+ ## 🀝 Contributing
526
+
527
+ Contributions are welcome! Please:
528
+
529
+ 1. Check existing issues first
530
+ 2. Follow the code style
531
+ 3. Add tests for new features
532
+ 4. Update documentation
533
+
534
+ ## πŸ“ License
535
+
536
+ This plugin is part of the ElizaOS project. See the main repository for license information.
package/auto-enable.ts ADDED
@@ -0,0 +1,30 @@
1
+ // Auto-enable check for @elizaos/plugin-x.
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 an `x` (or legacy `twitter`) connector block is present and not explicitly disabled. */
10
+ export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
11
+ const connectors = ctx.config?.connectors as
12
+ | Record<string, unknown>
13
+ | undefined;
14
+ if (!connectors) return false;
15
+
16
+ // Either `connectors.x` or the legacy `connectors.twitter` enables the plugin.
17
+ for (const key of ["x", "twitter"] as const) {
18
+ const c = connectors[key];
19
+ if (!c || typeof c !== "object") continue;
20
+ const config = c as Record<string, unknown>;
21
+ if (config.enabled === false) continue;
22
+ // The full per-connector field check (apiKey/apiSecret/accessToken) lives
23
+ // in the central engine's isConnectorConfigured. We delegate to a simple
24
+ // "block present + not explicitly disabled" check here; the central
25
+ // engine's stricter check remains as a fallback during migration.
26
+ return true;
27
+ }
28
+
29
+ return false;
30
+ }
@@ -0,0 +1,5 @@
1
+ import { Plugin } from '@elizaos/core';
2
+
3
+ declare const XPlugin: Plugin;
4
+
5
+ export { XPlugin, XPlugin as default };