@elizaos/plugin-twitter 1.0.9 → 1.0.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-twitter",
3
- "version": "1.0.9",
3
+ "version": "1.0.13",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -18,40 +18,28 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
- "@elizaos/core": "^1.0.2",
22
- "@roamhq/wrtc": "^0.9.0",
23
- "@sinclair/typebox": "^0.34.33",
24
- "glob": "11.0.2",
21
+ "@elizaos/core": "^1.0.13",
25
22
  "headers-polyfill": "^4.0.3",
26
23
  "json-stable-stringify": "^1.3.0",
27
- "otpauth": "^9.4.0",
28
- "set-cookie-parser": "^2.7.1",
29
- "tough-cookie": "^5.1.2",
30
- "twitter-api-v2": "^1.23.2",
31
- "typescript": "^5.8.3",
32
- "undici": "^7.10.0",
33
- "undici-types": "^7.10.0",
34
- "ws": "^8.18.2"
24
+ "twitter-api-v2": "^1.23.2"
35
25
  },
36
26
  "devDependencies": {
37
- "@vitest/coverage-v8": "3.1.4",
38
- "prettier": "3.5.3",
27
+ "@vitest/coverage-v8": "3.2.4",
28
+ "prettier": "3.6.1",
39
29
  "tsup": "8.5.0",
40
- "vitest": "3.1.4"
30
+ "typescript": "^5.8.3",
31
+ "vitest": "3.2.4"
41
32
  },
42
33
  "scripts": {
43
34
  "build": "tsup",
44
35
  "dev": "tsup --watch",
45
- "test": "vitest run",
36
+ "test": "tsup && elizaos test",
46
37
  "test:coverage": "vitest run --coverage",
47
38
  "lint": "prettier --write ./src",
48
39
  "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo",
49
40
  "format": "prettier --write ./src",
50
41
  "format:check": "prettier --check ./src"
51
42
  },
52
- "peerDependencies": {
53
- "whatwg-url": "14.2.0"
54
- },
55
43
  "publishConfig": {
56
44
  "access": "public"
57
45
  },
@@ -63,204 +51,196 @@
63
51
  "agentConfig": {
64
52
  "pluginType": "elizaos:plugin:1.0.0",
65
53
  "pluginParameters": {
66
- "TWITTER_SPACES_ENABLE": {
67
- "type": "boolean",
68
- "description": "Flag indicating whether the agent is allowed to join Twitter Spaces.",
69
- "required": false,
70
- "sensitive": false
71
- },
72
- "MAX_RETRIES": {
73
- "type": "number",
74
- "description": "Maximum number of times the system will attempt to log in to Twitter before giving up",
75
- "required": false,
76
- "default": 3,
77
- "sensitive": false
78
- },
79
- "TWITTER_USERNAME": {
54
+ "TWITTER_API_KEY": {
80
55
  "type": "string",
81
- "description": "Twitter account username used for authentication",
56
+ "description": "Twitter API v2 key for authentication.",
82
57
  "required": true,
83
- "sensitive": false
58
+ "sensitive": true
84
59
  },
85
- "TWITTER_PASSWORD": {
60
+ "TWITTER_API_SECRET_KEY": {
86
61
  "type": "string",
87
- "description": "Twitter account password used for authentication",
62
+ "description": "Twitter API v2 secret key paired with the API key for authentication.",
88
63
  "required": true,
89
64
  "sensitive": true
90
65
  },
91
- "TWITTER_EMAIL": {
66
+ "TWITTER_ACCESS_TOKEN": {
92
67
  "type": "string",
93
- "description": "Email address associated with the Twitter account; used during login/verification",
68
+ "description": "OAuth access token for Twitter API v2 requests.",
94
69
  "required": true,
95
- "sensitive": false
96
- },
97
- "TWITTER_2FA_SECRET": {
98
- "type": "string",
99
- "description": "Time-based one-time password (2FA) secret used for two-factor authentication during login",
100
- "required": false,
101
70
  "sensitive": true
102
71
  },
103
- "TWITTER_COOKIES_AUTH_TOKEN": {
72
+ "TWITTER_ACCESS_TOKEN_SECRET": {
104
73
  "type": "string",
105
- "description": "Pre-existing Twitter auth_token cookie value used to bypass manual login",
106
- "required": false,
74
+ "description": "OAuth access token secret used with the access token for authentication.",
75
+ "required": true,
107
76
  "sensitive": true
108
77
  },
109
- "TWITTER_COOKIES_CT0": {
78
+ "TWITTER_TARGET_USERS": {
110
79
  "type": "string",
111
- "description": "Pre-existing Twitter ct0 (CSRF) cookie value used to bypass manual login",
80
+ "description": "Comma-separated list of Twitter usernames the bot should interact with. Use '*' for all users.",
112
81
  "required": false,
113
- "sensitive": true
82
+ "default": "",
83
+ "sensitive": false
114
84
  },
115
- "TWITTER_COOKIES_GUEST_ID": {
116
- "type": "string",
117
- "description": "Pre-existing Twitter guest_id cookie value used to bypass manual login",
85
+ "TWITTER_RETRY_LIMIT": {
86
+ "type": "number",
87
+ "description": "Maximum number of retry attempts when a Twitter operation fails.",
118
88
  "required": false,
119
- "sensitive": true
89
+ "default": 5,
90
+ "sensitive": false
120
91
  },
121
- "TWITTER_API_KEY": {
122
- "type": "string",
123
- "description": "Twitter API key used to authenticate with the Twitter API during tests.",
92
+ "TWITTER_POLL_INTERVAL": {
93
+ "type": "number",
94
+ "description": "Timeline polling interval in seconds.",
124
95
  "required": false,
125
- "sensitive": true
96
+ "default": 120,
97
+ "sensitive": false
126
98
  },
127
- "TWITTER_API_SECRET_KEY": {
128
- "type": "string",
129
- "description": "Twitter API secret key paired with the API key for authentication.",
99
+ "TWITTER_SEARCH_ENABLE": {
100
+ "type": "boolean",
101
+ "description": "Enable timeline monitoring and interaction processing.",
130
102
  "required": false,
131
- "sensitive": true
103
+ "default": true,
104
+ "sensitive": false
132
105
  },
133
- "TWITTER_ACCESS_TOKEN": {
134
- "type": "string",
135
- "description": "OAuth access token used for Twitter API requests in the tests.",
106
+ "TWITTER_DRY_RUN": {
107
+ "type": "boolean",
108
+ "description": "When true, all Twitter actions are simulated and nothing is actually posted.",
136
109
  "required": false,
137
- "sensitive": true
110
+ "default": false,
111
+ "sensitive": false
138
112
  },
139
- "TWITTER_ACCESS_TOKEN_SECRET": {
140
- "type": "string",
141
- "description": "OAuth access token secret used with the access token for authentication.",
113
+ "TWITTER_POST_ENABLE": {
114
+ "type": "boolean",
115
+ "description": "Enable autonomous tweet posting.",
142
116
  "required": false,
143
- "sensitive": true
144
- },
145
- "OPENAI_API_KEY": {
146
- "type": "string",
147
- "description": "OpenAI API key supplied to the SttTtsPlugin for GPT/STT/TTS functionality.",
148
- "required": true,
149
- "sensitive": true
117
+ "default": false,
118
+ "sensitive": false
150
119
  },
151
- "ELEVENLABS_API_KEY": {
152
- "type": "string",
153
- "description": "ElevenLabs API key for TTS provided to the SttTtsPlugin. Used if ELEVENLABS_XI_API_KEY is not set.",
120
+ "TWITTER_POST_INTERVAL_MIN": {
121
+ "type": "number",
122
+ "description": "Minimum interval in minutes between automatically generated posts.",
154
123
  "required": false,
155
- "sensitive": true
124
+ "default": 90,
125
+ "sensitive": false
156
126
  },
157
- "ELEVENLABS_XI_API_KEY": {
158
- "type": "string",
159
- "description": "Alternative ElevenLabs (Xi) API key for TTS; used as a fallback if ELEVENLABS_API_KEY is not provided.",
127
+ "TWITTER_POST_INTERVAL_MAX": {
128
+ "type": "number",
129
+ "description": "Maximum interval in minutes between automatically generated posts.",
160
130
  "required": false,
161
- "sensitive": true
131
+ "default": 180,
132
+ "sensitive": false
162
133
  },
163
- "PROXY_URL": {
164
- "type": "string",
165
- "description": "URL of the proxy server (may include credentials) through which HTTP requests are routed.",
134
+ "TWITTER_POST_IMMEDIATELY": {
135
+ "type": "boolean",
136
+ "description": "Skip intervals and post immediately after generation.",
166
137
  "required": false,
167
- "sensitive": true
138
+ "default": false,
139
+ "sensitive": false
168
140
  },
169
- "TWITTER_COOKIES": {
170
- "type": "string",
171
- "description": "Serialized Twitter session cookies; referenced for cookie-based authentication.",
141
+ "TWITTER_POST_INTERVAL_VARIANCE": {
142
+ "type": "number",
143
+ "description": "Random variance factor (0.0-1.0) applied to posting intervals for natural behavior.",
172
144
  "required": false,
173
- "sensitive": true
145
+ "default": 0.2,
146
+ "sensitive": false
174
147
  },
175
- "TWITTER_DRY_RUN": {
176
- "type": "boolean",
177
- "description": "When true, all Twitter actions are simulated and nothing is actually posted.",
148
+ "TWITTER_INTERACTION_INTERVAL_MIN": {
149
+ "type": "number",
150
+ "description": "Minimum interval in minutes between interactions.",
178
151
  "required": false,
152
+ "default": 15,
179
153
  "sensitive": false
180
154
  },
181
- "TWITTER_RETRY_LIMIT": {
155
+ "TWITTER_INTERACTION_INTERVAL_MAX": {
182
156
  "type": "number",
183
- "description": "Maximum number of retry attempts when a Twitter action fails.",
157
+ "description": "Maximum interval in minutes between interactions.",
184
158
  "required": false,
185
- "default": 5,
159
+ "default": 30,
186
160
  "sensitive": false
187
161
  },
188
- "TWITTER_POLL_INTERVAL": {
162
+ "TWITTER_INTERACTION_INTERVAL_VARIANCE": {
189
163
  "type": "number",
190
- "description": "Polling interval in seconds between checks for new Twitter events.",
164
+ "description": "Random variance factor (0.0-1.0) applied to interaction intervals for natural behavior.",
191
165
  "required": false,
192
- "default": 120,
166
+ "default": 0.3,
193
167
  "sensitive": false
194
168
  },
195
- "TWITTER_TARGET_USERS": {
169
+ "TWITTER_TIMELINE_ALGORITHM": {
196
170
  "type": "string",
197
- "description": "Comma-separated list of Twitter usernames the bot should interact with. Supports '*' wildcard.",
171
+ "description": "Timeline processing algorithm: 'weighted' (default) or 'latest'.",
198
172
  "required": false,
173
+ "default": "weighted",
199
174
  "sensitive": false
200
175
  },
201
- "TWITTER_ENABLE_POST_GENERATION": {
202
- "type": "boolean",
203
- "description": "Toggle to enable or disable automatic tweet/post generation.",
176
+ "TWITTER_TIMELINE_USER_BASED_WEIGHT": {
177
+ "type": "number",
178
+ "description": "Weight for user-based scoring in weighted timeline algorithm.",
204
179
  "required": false,
205
- "default": true,
180
+ "default": 3,
206
181
  "sensitive": false
207
182
  },
208
- "TWITTER_POST_INTERVAL_MIN": {
183
+ "TWITTER_TIMELINE_TIME_BASED_WEIGHT": {
209
184
  "type": "number",
210
- "description": "Minimum interval in minutes between automatically generated posts.",
185
+ "description": "Weight for time-based scoring in weighted timeline algorithm.",
211
186
  "required": false,
212
- "default": 90,
187
+ "default": 2,
213
188
  "sensitive": false
214
189
  },
215
- "TWITTER_POST_INTERVAL_MAX": {
190
+ "TWITTER_TIMELINE_RELEVANCE_WEIGHT": {
216
191
  "type": "number",
217
- "description": "Maximum interval in minutes between automatically generated posts.",
192
+ "description": "Weight for relevance-based scoring in weighted timeline algorithm.",
218
193
  "required": false,
219
- "default": 180,
194
+ "default": 5,
220
195
  "sensitive": false
221
196
  },
222
- "TWITTER_POST_IMMEDIATELY": {
223
- "type": "boolean",
224
- "description": "If true, posts are published immediately after generation, bypassing interval checks.",
197
+ "TWITTER_MAX_TWEET_LENGTH": {
198
+ "type": "number",
199
+ "description": "Maximum tweet length (supports long-form tweets up to 4000 characters).",
225
200
  "required": false,
201
+ "default": 4000,
226
202
  "sensitive": false
227
203
  },
228
- "TWITTER_INTERACTION_ENABLE": {
229
- "type": "boolean",
230
- "description": "Controls whether mention and interaction handling is enabled. Defaults to true when not explicitly set to false.",
204
+ "TWITTER_MAX_INTERACTIONS_PER_RUN": {
205
+ "type": "number",
206
+ "description": "Maximum number of interactions processed per cycle.",
231
207
  "required": false,
232
- "default": true,
208
+ "default": 10,
233
209
  "sensitive": false
234
210
  },
235
- "TWITTER_TIMELINE_ENABLE": {
211
+ "TWITTER_DM_ONLY": {
236
212
  "type": "boolean",
237
- "description": "Enables fetching and caching of the Twitter timeline.",
213
+ "description": "Only process direct messages, ignore public interactions.",
238
214
  "required": false,
215
+ "default": false,
239
216
  "sensitive": false
240
217
  },
241
- "TWITTER_API_SECRET": {
242
- "type": "string",
243
- "description": "Twitter API secret credential (referenced in comments for future API-based auth).",
244
- "required": false,
245
- "sensitive": true
246
- },
247
218
  "TWITTER_ENABLE_ACTION_PROCESSING": {
248
219
  "type": "boolean",
249
- "description": "Flag to enable or disable processing of Twitter actions",
220
+ "description": "Enable timeline action processing and automated responses.",
250
221
  "required": false,
222
+ "default": false,
251
223
  "sensitive": false
252
224
  },
253
- "TWITTER_TIMELINE_MODE": {
254
- "type": "string",
255
- "description": "Specifies which Twitter timeline to monitor: 'foryou' (home) or 'following'.",
225
+ "TWITTER_ACTION_INTERVAL": {
226
+ "type": "number",
227
+ "description": "Interval in minutes between timeline action processing cycles.",
256
228
  "required": false,
229
+ "default": 240,
257
230
  "sensitive": false
258
231
  },
259
- "TWITTER_TIMELINE_POLL_INTERVAL": {
260
- "type": "number",
261
- "description": "Polling interval (in seconds) between timeline checks.",
232
+ "TWITTER_AUTO_RESPOND_MENTIONS": {
233
+ "type": "boolean",
234
+ "description": "Automatically respond to mentions.",
262
235
  "required": false,
263
- "default": 120,
236
+ "default": true,
237
+ "sensitive": false
238
+ },
239
+ "TWITTER_AUTO_RESPOND_REPLIES": {
240
+ "type": "boolean",
241
+ "description": "Automatically respond to replies.",
242
+ "required": false,
243
+ "default": true,
264
244
  "sensitive": false
265
245
  }
266
246
  }
@@ -1,10 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
- export {
8
- __export
9
- };
10
- //# sourceMappingURL=chunk-PZ5AY32C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,40 +0,0 @@
1
- import "./chunk-PZ5AY32C.js";
2
-
3
- // src/client/platform/node/randomize-ciphers.ts
4
- import { randomBytes } from "crypto";
5
- import tls from "tls";
6
- var ORIGINAL_CIPHERS = tls.DEFAULT_CIPHERS;
7
- var TOP_N_SHUFFLE = 8;
8
- var shuffleArray = (array) => {
9
- for (let i = array.length - 1; i > 0; i--) {
10
- const j = randomBytes(4).readUint32LE() % array.length;
11
- [array[i], array[j]] = [array[j], array[i]];
12
- }
13
- return array;
14
- };
15
- var randomizeCiphers = () => {
16
- do {
17
- const cipherList = ORIGINAL_CIPHERS.split(":");
18
- const shuffled = shuffleArray(cipherList.slice(0, TOP_N_SHUFFLE));
19
- const retained = cipherList.slice(TOP_N_SHUFFLE);
20
- tls.DEFAULT_CIPHERS = [...shuffled, ...retained].join(":");
21
- } while (tls.DEFAULT_CIPHERS === ORIGINAL_CIPHERS);
22
- };
23
-
24
- // src/client/platform/node/index.ts
25
- var NodePlatform = class {
26
- /**
27
- * Asynchronously randomizes ciphers.
28
- *
29
- * @returns {Promise<void>} A promise that resolves once the ciphers are randomized.
30
- */
31
- randomizeCiphers() {
32
- randomizeCiphers();
33
- return Promise.resolve();
34
- }
35
- };
36
- var platform = new NodePlatform();
37
- export {
38
- platform
39
- };
40
- //# sourceMappingURL=node-L7ZVN5QV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client/platform/node/randomize-ciphers.ts","../src/client/platform/node/index.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport tls from 'node:tls';\n\nconst ORIGINAL_CIPHERS = tls.DEFAULT_CIPHERS;\n\n// How many ciphers from the top of the list to shuffle.\n// The remaining ciphers are left in the original order.\nconst TOP_N_SHUFFLE = 8;\n\n// Modified variation of https://stackoverflow.com/a/12646864\nconst shuffleArray = (array: unknown[]) => {\n for (let i = array.length - 1; i > 0; i--) {\n const j = randomBytes(4).readUint32LE() % array.length;\n [array[i], array[j]] = [array[j], array[i]];\n }\n\n return array;\n};\n\n// https://github.com/imputnet/cobalt/pull/574\nexport const randomizeCiphers = () => {\n do {\n const cipherList = ORIGINAL_CIPHERS.split(':');\n const shuffled = shuffleArray(cipherList.slice(0, TOP_N_SHUFFLE));\n const retained = cipherList.slice(TOP_N_SHUFFLE);\n\n tls.DEFAULT_CIPHERS = [...shuffled, ...retained].join(':');\n } while (tls.DEFAULT_CIPHERS === ORIGINAL_CIPHERS);\n};\n","import type { PlatformExtensions } from '../platform-interface';\nimport { randomizeCiphers } from './randomize-ciphers';\n\n/**\n * Asynchronously randomizes the order of ciphers used by the Node.js platform.\n * @returns {Promise<void>} A Promise that resolves once the ciphers have been randomized.\n */\nclass NodePlatform implements PlatformExtensions {\n /**\n * Asynchronously randomizes ciphers.\n *\n * @returns {Promise<void>} A promise that resolves once the ciphers are randomized.\n */\n randomizeCiphers(): Promise<void> {\n randomizeCiphers();\n return Promise.resolve();\n }\n}\n\nexport const platform = new NodePlatform();\n"],"mappings":";;;AAAA,SAAS,mBAAmB;AAC5B,OAAO,SAAS;AAEhB,IAAM,mBAAmB,IAAI;AAI7B,IAAM,gBAAgB;AAGtB,IAAM,eAAe,CAAC,UAAqB;AACzC,WAAS,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;AACzC,UAAM,IAAI,YAAY,CAAC,EAAE,aAAa,IAAI,MAAM;AAChD,KAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,EAC5C;AAEA,SAAO;AACT;AAGO,IAAM,mBAAmB,MAAM;AACpC,KAAG;AACD,UAAM,aAAa,iBAAiB,MAAM,GAAG;AAC7C,UAAM,WAAW,aAAa,WAAW,MAAM,GAAG,aAAa,CAAC;AAChE,UAAM,WAAW,WAAW,MAAM,aAAa;AAE/C,QAAI,kBAAkB,CAAC,GAAG,UAAU,GAAG,QAAQ,EAAE,KAAK,GAAG;AAAA,EAC3D,SAAS,IAAI,oBAAoB;AACnC;;;ACrBA,IAAM,eAAN,MAAiD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/C,mBAAkC;AAChC,qBAAiB;AACjB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;AAEO,IAAM,WAAW,IAAI,aAAa;","names":[]}