@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/README.md +181 -91
- package/dist/index.d.ts +126 -949
- package/dist/index.js +2021 -7284
- package/dist/index.js.map +1 -1
- package/package.json +118 -138
- package/dist/chunk-PZ5AY32C.js +0 -10
- package/dist/chunk-PZ5AY32C.js.map +0 -1
- package/dist/node-L7ZVN5QV.js +0 -40
- package/dist/node-L7ZVN5QV.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/plugin-twitter",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
38
|
-
"prettier": "3.
|
|
27
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
28
|
+
"prettier": "3.6.1",
|
|
39
29
|
"tsup": "8.5.0",
|
|
40
|
-
"
|
|
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": "
|
|
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
|
-
"
|
|
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
|
|
56
|
+
"description": "Twitter API v2 key for authentication.",
|
|
82
57
|
"required": true,
|
|
83
|
-
"sensitive":
|
|
58
|
+
"sensitive": true
|
|
84
59
|
},
|
|
85
|
-
"
|
|
60
|
+
"TWITTER_API_SECRET_KEY": {
|
|
86
61
|
"type": "string",
|
|
87
|
-
"description": "Twitter
|
|
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
|
-
"
|
|
66
|
+
"TWITTER_ACCESS_TOKEN": {
|
|
92
67
|
"type": "string",
|
|
93
|
-
"description": "
|
|
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
|
-
"
|
|
72
|
+
"TWITTER_ACCESS_TOKEN_SECRET": {
|
|
104
73
|
"type": "string",
|
|
105
|
-
"description": "
|
|
106
|
-
"required":
|
|
74
|
+
"description": "OAuth access token secret used with the access token for authentication.",
|
|
75
|
+
"required": true,
|
|
107
76
|
"sensitive": true
|
|
108
77
|
},
|
|
109
|
-
"
|
|
78
|
+
"TWITTER_TARGET_USERS": {
|
|
110
79
|
"type": "string",
|
|
111
|
-
"description": "
|
|
80
|
+
"description": "Comma-separated list of Twitter usernames the bot should interact with. Use '*' for all users.",
|
|
112
81
|
"required": false,
|
|
113
|
-
"
|
|
82
|
+
"default": "",
|
|
83
|
+
"sensitive": false
|
|
114
84
|
},
|
|
115
|
-
"
|
|
116
|
-
"type": "
|
|
117
|
-
"description": "
|
|
85
|
+
"TWITTER_RETRY_LIMIT": {
|
|
86
|
+
"type": "number",
|
|
87
|
+
"description": "Maximum number of retry attempts when a Twitter operation fails.",
|
|
118
88
|
"required": false,
|
|
119
|
-
"
|
|
89
|
+
"default": 5,
|
|
90
|
+
"sensitive": false
|
|
120
91
|
},
|
|
121
|
-
"
|
|
122
|
-
"type": "
|
|
123
|
-
"description": "
|
|
92
|
+
"TWITTER_POLL_INTERVAL": {
|
|
93
|
+
"type": "number",
|
|
94
|
+
"description": "Timeline polling interval in seconds.",
|
|
124
95
|
"required": false,
|
|
125
|
-
"
|
|
96
|
+
"default": 120,
|
|
97
|
+
"sensitive": false
|
|
126
98
|
},
|
|
127
|
-
"
|
|
128
|
-
"type": "
|
|
129
|
-
"description": "
|
|
99
|
+
"TWITTER_SEARCH_ENABLE": {
|
|
100
|
+
"type": "boolean",
|
|
101
|
+
"description": "Enable timeline monitoring and interaction processing.",
|
|
130
102
|
"required": false,
|
|
131
|
-
"
|
|
103
|
+
"default": true,
|
|
104
|
+
"sensitive": false
|
|
132
105
|
},
|
|
133
|
-
"
|
|
134
|
-
"type": "
|
|
135
|
-
"description": "
|
|
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
|
-
"
|
|
110
|
+
"default": false,
|
|
111
|
+
"sensitive": false
|
|
138
112
|
},
|
|
139
|
-
"
|
|
140
|
-
"type": "
|
|
141
|
-
"description": "
|
|
113
|
+
"TWITTER_POST_ENABLE": {
|
|
114
|
+
"type": "boolean",
|
|
115
|
+
"description": "Enable autonomous tweet posting.",
|
|
142
116
|
"required": false,
|
|
143
|
-
"
|
|
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
|
-
"
|
|
152
|
-
"type": "
|
|
153
|
-
"description": "
|
|
120
|
+
"TWITTER_POST_INTERVAL_MIN": {
|
|
121
|
+
"type": "number",
|
|
122
|
+
"description": "Minimum interval in minutes between automatically generated posts.",
|
|
154
123
|
"required": false,
|
|
155
|
-
"
|
|
124
|
+
"default": 90,
|
|
125
|
+
"sensitive": false
|
|
156
126
|
},
|
|
157
|
-
"
|
|
158
|
-
"type": "
|
|
159
|
-
"description": "
|
|
127
|
+
"TWITTER_POST_INTERVAL_MAX": {
|
|
128
|
+
"type": "number",
|
|
129
|
+
"description": "Maximum interval in minutes between automatically generated posts.",
|
|
160
130
|
"required": false,
|
|
161
|
-
"
|
|
131
|
+
"default": 180,
|
|
132
|
+
"sensitive": false
|
|
162
133
|
},
|
|
163
|
-
"
|
|
164
|
-
"type": "
|
|
165
|
-
"description": "
|
|
134
|
+
"TWITTER_POST_IMMEDIATELY": {
|
|
135
|
+
"type": "boolean",
|
|
136
|
+
"description": "Skip intervals and post immediately after generation.",
|
|
166
137
|
"required": false,
|
|
167
|
-
"
|
|
138
|
+
"default": false,
|
|
139
|
+
"sensitive": false
|
|
168
140
|
},
|
|
169
|
-
"
|
|
170
|
-
"type": "
|
|
171
|
-
"description": "
|
|
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
|
-
"
|
|
145
|
+
"default": 0.2,
|
|
146
|
+
"sensitive": false
|
|
174
147
|
},
|
|
175
|
-
"
|
|
176
|
-
"type": "
|
|
177
|
-
"description": "
|
|
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
|
-
"
|
|
155
|
+
"TWITTER_INTERACTION_INTERVAL_MAX": {
|
|
182
156
|
"type": "number",
|
|
183
|
-
"description": "Maximum
|
|
157
|
+
"description": "Maximum interval in minutes between interactions.",
|
|
184
158
|
"required": false,
|
|
185
|
-
"default":
|
|
159
|
+
"default": 30,
|
|
186
160
|
"sensitive": false
|
|
187
161
|
},
|
|
188
|
-
"
|
|
162
|
+
"TWITTER_INTERACTION_INTERVAL_VARIANCE": {
|
|
189
163
|
"type": "number",
|
|
190
|
-
"description": "
|
|
164
|
+
"description": "Random variance factor (0.0-1.0) applied to interaction intervals for natural behavior.",
|
|
191
165
|
"required": false,
|
|
192
|
-
"default":
|
|
166
|
+
"default": 0.3,
|
|
193
167
|
"sensitive": false
|
|
194
168
|
},
|
|
195
|
-
"
|
|
169
|
+
"TWITTER_TIMELINE_ALGORITHM": {
|
|
196
170
|
"type": "string",
|
|
197
|
-
"description": "
|
|
171
|
+
"description": "Timeline processing algorithm: 'weighted' (default) or 'latest'.",
|
|
198
172
|
"required": false,
|
|
173
|
+
"default": "weighted",
|
|
199
174
|
"sensitive": false
|
|
200
175
|
},
|
|
201
|
-
"
|
|
202
|
-
"type": "
|
|
203
|
-
"description": "
|
|
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":
|
|
180
|
+
"default": 3,
|
|
206
181
|
"sensitive": false
|
|
207
182
|
},
|
|
208
|
-
"
|
|
183
|
+
"TWITTER_TIMELINE_TIME_BASED_WEIGHT": {
|
|
209
184
|
"type": "number",
|
|
210
|
-
"description": "
|
|
185
|
+
"description": "Weight for time-based scoring in weighted timeline algorithm.",
|
|
211
186
|
"required": false,
|
|
212
|
-
"default":
|
|
187
|
+
"default": 2,
|
|
213
188
|
"sensitive": false
|
|
214
189
|
},
|
|
215
|
-
"
|
|
190
|
+
"TWITTER_TIMELINE_RELEVANCE_WEIGHT": {
|
|
216
191
|
"type": "number",
|
|
217
|
-
"description": "
|
|
192
|
+
"description": "Weight for relevance-based scoring in weighted timeline algorithm.",
|
|
218
193
|
"required": false,
|
|
219
|
-
"default":
|
|
194
|
+
"default": 5,
|
|
220
195
|
"sensitive": false
|
|
221
196
|
},
|
|
222
|
-
"
|
|
223
|
-
"type": "
|
|
224
|
-
"description": "
|
|
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
|
-
"
|
|
229
|
-
"type": "
|
|
230
|
-
"description": "
|
|
204
|
+
"TWITTER_MAX_INTERACTIONS_PER_RUN": {
|
|
205
|
+
"type": "number",
|
|
206
|
+
"description": "Maximum number of interactions processed per cycle.",
|
|
231
207
|
"required": false,
|
|
232
|
-
"default":
|
|
208
|
+
"default": 10,
|
|
233
209
|
"sensitive": false
|
|
234
210
|
},
|
|
235
|
-
"
|
|
211
|
+
"TWITTER_DM_ONLY": {
|
|
236
212
|
"type": "boolean",
|
|
237
|
-
"description": "
|
|
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": "
|
|
220
|
+
"description": "Enable timeline action processing and automated responses.",
|
|
250
221
|
"required": false,
|
|
222
|
+
"default": false,
|
|
251
223
|
"sensitive": false
|
|
252
224
|
},
|
|
253
|
-
"
|
|
254
|
-
"type": "
|
|
255
|
-
"description": "
|
|
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
|
-
"
|
|
260
|
-
"type": "
|
|
261
|
-
"description": "
|
|
232
|
+
"TWITTER_AUTO_RESPOND_MENTIONS": {
|
|
233
|
+
"type": "boolean",
|
|
234
|
+
"description": "Automatically respond to mentions.",
|
|
262
235
|
"required": false,
|
|
263
|
-
"default":
|
|
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
|
}
|
package/dist/chunk-PZ5AY32C.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/node-L7ZVN5QV.js
DELETED
|
@@ -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":[]}
|