@elizaos/plugin-twitter 1.2.6 → 1.2.8

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/dist/index.js CHANGED
@@ -5,7 +5,10 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/index.ts
8
- import { logger as logger9 } from "@elizaos/core";
8
+ import { logger as logger10 } from "@elizaos/core";
9
+
10
+ // src/services/twitter.service.ts
11
+ import { Service, logger as logger8 } from "@elizaos/core";
9
12
 
10
13
  // src/interactions.ts
11
14
  import {
@@ -1983,6 +1986,17 @@ var parseActionResponseFromText = (text) => {
1983
1986
  return { actions };
1984
1987
  };
1985
1988
 
1989
+ // src/utils/settings.ts
1990
+ function getSetting(runtime, key, defaultValue) {
1991
+ if (runtime && typeof runtime.getSetting === "function") {
1992
+ const value = runtime.getSetting(key);
1993
+ if (value !== void 0 && value !== null) {
1994
+ return String(value);
1995
+ }
1996
+ }
1997
+ return process.env[key] ?? defaultValue;
1998
+ }
1999
+
1986
2000
  // node_modules/zod/dist/esm/v3/external.js
1987
2001
  var external_exports = {};
1988
2002
  __export(external_exports, {
@@ -6077,15 +6091,6 @@ function getTargetUsers(targetUsersConfig) {
6077
6091
  const users = parseTargetUsers(targetUsersConfig);
6078
6092
  return users.filter((u) => u !== "*");
6079
6093
  }
6080
- function getSetting(runtime, key, defaultValue) {
6081
- if (runtime && typeof runtime.getSetting === "function") {
6082
- const value = runtime.getSetting(key);
6083
- if (value !== void 0 && value !== null) {
6084
- return String(value);
6085
- }
6086
- }
6087
- return process.env[key] ?? defaultValue;
6088
- }
6089
6094
  async function validateTwitterConfig(runtime, config = {}) {
6090
6095
  try {
6091
6096
  const validatedConfig = {
@@ -6123,17 +6128,6 @@ async function validateTwitterConfig(runtime, config = {}) {
6123
6128
  }
6124
6129
  }
6125
6130
 
6126
- // src/utils/settings.ts
6127
- function getSetting2(runtime, key, defaultValue) {
6128
- if (runtime && typeof runtime.getSetting === "function") {
6129
- const value = runtime.getSetting(key);
6130
- if (value !== void 0 && value !== null) {
6131
- return String(value);
6132
- }
6133
- }
6134
- return process.env[key] ?? defaultValue;
6135
- }
6136
-
6137
6131
  // src/interactions.ts
6138
6132
  var TwitterInteractionClient = class {
6139
6133
  /**
@@ -6149,7 +6143,7 @@ var TwitterInteractionClient = class {
6149
6143
  this.client = client;
6150
6144
  this.runtime = runtime;
6151
6145
  this.state = state;
6152
- const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting2(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
6146
+ const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
6153
6147
  this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
6154
6148
  }
6155
6149
  /**
@@ -6164,7 +6158,7 @@ var TwitterInteractionClient = class {
6164
6158
  return;
6165
6159
  }
6166
6160
  const engagementIntervalMinutes = parseInt(
6167
- this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting2(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
6161
+ this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
6168
6162
  );
6169
6163
  const interactionInterval = engagementIntervalMinutes * 60 * 1e3;
6170
6164
  logger3.info(`Twitter interaction client will check every ${engagementIntervalMinutes} minutes`);
@@ -6189,11 +6183,11 @@ var TwitterInteractionClient = class {
6189
6183
  logger3.log("Checking Twitter interactions");
6190
6184
  const twitterUsername = this.client.profile?.username;
6191
6185
  try {
6192
- const repliesEnabled = (getSetting2(this.runtime, "TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
6186
+ const repliesEnabled = (getSetting(this.runtime, "TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
6193
6187
  if (repliesEnabled) {
6194
6188
  await this.handleMentions(twitterUsername);
6195
6189
  }
6196
- const targetUsersConfig = (getSetting2(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
6190
+ const targetUsersConfig = (getSetting(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
6197
6191
  if (targetUsersConfig?.trim()) {
6198
6192
  await this.handleTargetUserPosts(targetUsersConfig);
6199
6193
  }
@@ -6267,7 +6261,7 @@ var TwitterInteractionClient = class {
6267
6261
  */
6268
6262
  async processTargetUserTweets(tweets, username) {
6269
6263
  const maxEngagementsPerRun = parseInt(
6270
- getSetting2(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
6264
+ getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
6271
6265
  );
6272
6266
  let engagementCount = 0;
6273
6267
  for (const tweet of tweets) {
@@ -6464,7 +6458,7 @@ Response (YES/NO):`;
6464
6458
  );
6465
6459
  let uniqueTweetCandidates = [...mentionCandidates];
6466
6460
  uniqueTweetCandidates = uniqueTweetCandidates.sort((a, b) => a.id.localeCompare(b.id)).filter((tweet) => tweet.userId !== this.client.profile.id);
6467
- const targetUsersConfig = (getSetting2(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
6461
+ const targetUsersConfig = (getSetting(this.runtime, "TWITTER_TARGET_USERS") ?? process.env.TWITTER_TARGET_USERS) || "";
6468
6462
  if (targetUsersConfig?.trim()) {
6469
6463
  uniqueTweetCandidates = uniqueTweetCandidates.filter((tweet) => {
6470
6464
  const shouldTarget = shouldTargetUser(
@@ -6480,7 +6474,7 @@ Response (YES/NO):`;
6480
6474
  });
6481
6475
  }
6482
6476
  const maxInteractionsPerRun = parseInt(
6483
- getSetting2(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
6477
+ getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
6484
6478
  );
6485
6479
  const tweetsToProcess = uniqueTweetCandidates.slice(0, maxInteractionsPerRun);
6486
6480
  logger3.info(`Processing ${tweetsToProcess.length} of ${uniqueTweetCandidates.length} mention tweets (max: ${maxInteractionsPerRun})`);
@@ -6839,12 +6833,12 @@ var TwitterPostClient = class {
6839
6833
  this.client = client;
6840
6834
  this.state = state;
6841
6835
  this.runtime = runtime;
6842
- const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting2(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
6836
+ const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
6843
6837
  this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
6844
6838
  logger4.log("Twitter Post Client Configuration:");
6845
6839
  logger4.log(`- Dry Run Mode: ${this.isDryRun ? "Enabled" : "Disabled"}`);
6846
6840
  const postIntervalMinutes = parseInt(
6847
- this.state?.TWITTER_POST_INTERVAL || getSetting2(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6841
+ this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6848
6842
  );
6849
6843
  logger4.log(`- Post Interval: ${postIntervalMinutes} minutes`);
6850
6844
  }
@@ -6867,7 +6861,7 @@ var TwitterPostClient = class {
6867
6861
  return;
6868
6862
  }
6869
6863
  const postIntervalMinutes = parseInt(
6870
- this.state?.TWITTER_POST_INTERVAL || getSetting2(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6864
+ this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6871
6865
  );
6872
6866
  const interval = postIntervalMinutes * 60 * 1e3;
6873
6867
  logger4.info(`Next tweet scheduled in ${postIntervalMinutes} minutes`);
@@ -6878,7 +6872,7 @@ var TwitterPostClient = class {
6878
6872
  };
6879
6873
  await new Promise((resolve) => setTimeout(resolve, 1e3));
6880
6874
  const postImmediately = parseInt(
6881
- this.state?.TWITTER_POST_INTERVAL || getSetting2(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6875
+ this.state?.TWITTER_POST_INTERVAL || getSetting(this.runtime, "TWITTER_POST_INTERVAL") || process.env.TWITTER_POST_INTERVAL || "120"
6882
6876
  ) === 0;
6883
6877
  if (postImmediately) {
6884
6878
  logger4.info("TWITTER_POST_IMMEDIATELY is true, generating initial tweet now");
@@ -7094,9 +7088,9 @@ var TwitterTimelineClient = class {
7094
7088
  this.twitterClient = client.twitterClient;
7095
7089
  this.runtime = runtime;
7096
7090
  this.state = state;
7097
- const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting2(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
7091
+ const dryRunSetting = this.state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
7098
7092
  this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
7099
- const timelineMode = getSetting2(this.runtime, "TWITTER_TIMELINE_MODE") ?? process.env.TWITTER_TIMELINE_MODE;
7093
+ const timelineMode = getSetting(this.runtime, "TWITTER_TIMELINE_MODE") ?? process.env.TWITTER_TIMELINE_MODE;
7100
7094
  this.timelineType = timelineMode === "following" /* Following */ ? "following" /* Following */ : "foryou" /* ForYou */;
7101
7095
  }
7102
7096
  async start() {
@@ -7108,7 +7102,7 @@ var TwitterTimelineClient = class {
7108
7102
  return;
7109
7103
  }
7110
7104
  const engagementIntervalMinutes = parseInt(
7111
- this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting2(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
7105
+ this.state?.TWITTER_ENGAGEMENT_INTERVAL || getSetting(this.runtime, "TWITTER_ENGAGEMENT_INTERVAL") || process.env.TWITTER_ENGAGEMENT_INTERVAL || "30"
7112
7106
  );
7113
7107
  const actionInterval = engagementIntervalMinutes * 60 * 1e3;
7114
7108
  logger5.info(`Timeline client will check every ${engagementIntervalMinutes} minutes`);
@@ -7154,7 +7148,7 @@ var TwitterTimelineClient = class {
7154
7148
  const tweets = await this.getTimeline(20);
7155
7149
  logger5.info(`Fetched ${tweets.length} tweets from timeline`);
7156
7150
  const maxActionsPerCycle = parseInt(
7157
- getSetting2(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
7151
+ getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
7158
7152
  );
7159
7153
  const tweetDecisions = [];
7160
7154
  for (const tweet of tweets) {
@@ -7452,7 +7446,7 @@ var TwitterDiscoveryClient = class {
7452
7446
  this.client = client;
7453
7447
  this.twitterClient = client.twitterClient;
7454
7448
  this.runtime = runtime;
7455
- const dryRunSetting = state?.TWITTER_DRY_RUN ?? getSetting2(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
7449
+ const dryRunSetting = state?.TWITTER_DRY_RUN ?? getSetting(this.runtime, "TWITTER_DRY_RUN") ?? process.env.TWITTER_DRY_RUN;
7456
7450
  this.isDryRun = dryRunSetting === true || dryRunSetting === "true" || typeof dryRunSetting === "string" && dryRunSetting.toLowerCase() === "true";
7457
7451
  this.config = this.buildDiscoveryConfig();
7458
7452
  logger6.info("Twitter Discovery Config:", {
@@ -7487,13 +7481,13 @@ var TwitterDiscoveryClient = class {
7487
7481
  return {
7488
7482
  topics,
7489
7483
  minFollowerCount: parseInt(
7490
- getSetting2(this.runtime, "TWITTER_MIN_FOLLOWER_COUNT") || process.env.TWITTER_MIN_FOLLOWER_COUNT || "100"
7484
+ getSetting(this.runtime, "TWITTER_MIN_FOLLOWER_COUNT") || process.env.TWITTER_MIN_FOLLOWER_COUNT || "100"
7491
7485
  ),
7492
7486
  maxFollowsPerCycle: parseInt(
7493
- getSetting2(this.runtime, "TWITTER_MAX_FOLLOWS_PER_CYCLE") || process.env.TWITTER_MAX_FOLLOWS_PER_CYCLE || "5"
7487
+ getSetting(this.runtime, "TWITTER_MAX_FOLLOWS_PER_CYCLE") || process.env.TWITTER_MAX_FOLLOWS_PER_CYCLE || "5"
7494
7488
  ),
7495
7489
  maxEngagementsPerCycle: parseInt(
7496
- getSetting2(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
7490
+ getSetting(this.runtime, "TWITTER_MAX_ENGAGEMENTS_PER_RUN") || process.env.TWITTER_MAX_ENGAGEMENTS_PER_RUN || "10"
7497
7491
  ),
7498
7492
  likeThreshold: 0.6,
7499
7493
  replyThreshold: 0.8,
@@ -7522,7 +7516,7 @@ var TwitterDiscoveryClient = class {
7522
7516
  logger6.error("Discovery cycle error:", error);
7523
7517
  }
7524
7518
  const baseInterval = parseInt(
7525
- getSetting2(this.runtime, "TWITTER_DISCOVERY_INTERVAL") || process.env.TWITTER_DISCOVERY_INTERVAL || "30"
7519
+ getSetting(this.runtime, "TWITTER_DISCOVERY_INTERVAL") || process.env.TWITTER_DISCOVERY_INTERVAL || "30"
7526
7520
  );
7527
7521
  const variance = Math.random() * 20 - 10;
7528
7522
  const nextInterval = (baseInterval + variance) * 60 * 1e3;
@@ -7588,7 +7582,7 @@ var TwitterDiscoveryClient = class {
7588
7582
  const accounts = /* @__PURE__ */ new Map();
7589
7583
  for (const topic of this.config.topics.slice(0, 5)) {
7590
7584
  try {
7591
- const popularQuery = `${topic} -is:retweet -is:reply min_faves:10 lang:en`;
7585
+ const popularQuery = `${topic} -is:retweet -is:reply lang:en`;
7592
7586
  logger6.debug(`Searching popular tweets for topic: ${topic}`);
7593
7587
  const popularResults = await this.twitterClient.fetchSearchTweets(
7594
7588
  popularQuery,
@@ -7596,10 +7590,11 @@ var TwitterDiscoveryClient = class {
7596
7590
  0 /* Top */
7597
7591
  );
7598
7592
  for (const tweet of popularResults.tweets) {
7593
+ if ((tweet.likes || 0) < 10) continue;
7599
7594
  const scored = this.scoreTweet(tweet, "topic");
7600
7595
  tweets.push(scored);
7601
7596
  }
7602
- const verifiedQuery = `${topic} -is:retweet lang:en filter:verified`;
7597
+ const verifiedQuery = `${topic} -is:retweet lang:en is:verified`;
7603
7598
  logger6.debug(`Searching verified accounts for topic: ${topic}`);
7604
7599
  const verifiedResults = await this.twitterClient.fetchSearchTweets(
7605
7600
  verifiedQuery,
@@ -7634,7 +7629,7 @@ var TwitterDiscoveryClient = class {
7634
7629
  const accounts = /* @__PURE__ */ new Map();
7635
7630
  const topicQuery = this.config.topics.slice(0, 3).map((t) => `"${t}"`).join(" OR ");
7636
7631
  try {
7637
- const viralQuery = `${topicQuery} min_replies:20 min_faves:50 -is:retweet`;
7632
+ const viralQuery = `${topicQuery} -is:retweet has:mentions`;
7638
7633
  logger6.debug(`Searching viral threads with query: ${viralQuery}`);
7639
7634
  const searchResults = await this.twitterClient.fetchSearchTweets(
7640
7635
  viralQuery,
@@ -7642,6 +7637,8 @@ var TwitterDiscoveryClient = class {
7642
7637
  0 /* Top */
7643
7638
  );
7644
7639
  for (const tweet of searchResults.tweets) {
7640
+ const engagementScore = (tweet.likes || 0) + (tweet.retweets || 0) * 2;
7641
+ if (engagementScore < 50) continue;
7645
7642
  const scored = this.scoreTweet(tweet, "thread");
7646
7643
  tweets.push(scored);
7647
7644
  const account = this.scoreAccount({
@@ -7666,7 +7663,7 @@ var TwitterDiscoveryClient = class {
7666
7663
  const accounts = /* @__PURE__ */ new Map();
7667
7664
  for (const topic of this.config.topics.slice(0, 3)) {
7668
7665
  try {
7669
- const influencerQuery = `${topic} -is:retweet min_faves:100 min_retweets:20`;
7666
+ const influencerQuery = `${topic} -is:retweet (is:verified OR has:links)`;
7670
7667
  logger6.debug(`Searching for influencers in topic: ${topic}`);
7671
7668
  const results = await this.twitterClient.fetchSearchTweets(
7672
7669
  influencerQuery,
@@ -7674,6 +7671,8 @@ var TwitterDiscoveryClient = class {
7674
7671
  0 /* Top */
7675
7672
  );
7676
7673
  for (const tweet of results.tweets) {
7674
+ const engagement = (tweet.likes || 0) + (tweet.retweets || 0) * 2;
7675
+ if (engagement < 20) continue;
7677
7676
  const scored = this.scoreTweet(tweet, "topic");
7678
7677
  tweets.push(scored);
7679
7678
  const estimatedFollowers = Math.max(
@@ -8523,7 +8522,45 @@ _ClientBase._twitterClients = {};
8523
8522
  var ClientBase = _ClientBase;
8524
8523
 
8525
8524
  // src/services/twitter.service.ts
8526
- import { Service } from "@elizaos/core";
8525
+ var TwitterClientInstance = class {
8526
+ constructor(runtime, state) {
8527
+ this.client = new ClientBase(runtime, state);
8528
+ const postEnabledSetting = getSetting(runtime, "TWITTER_ENABLE_POST") ?? process.env.TWITTER_ENABLE_POST;
8529
+ logger8.debug(`TWITTER_ENABLE_POST setting value: ${JSON.stringify(postEnabledSetting)}, type: ${typeof postEnabledSetting}`);
8530
+ const postEnabled = postEnabledSetting === "true" || postEnabledSetting === true;
8531
+ if (postEnabled) {
8532
+ logger8.info("Twitter posting is ENABLED - creating post client");
8533
+ this.post = new TwitterPostClient(this.client, runtime, state);
8534
+ } else {
8535
+ logger8.info("Twitter posting is DISABLED - set TWITTER_ENABLE_POST=true to enable automatic posting");
8536
+ }
8537
+ const repliesEnabled = (getSetting(runtime, "TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
8538
+ if (repliesEnabled) {
8539
+ logger8.info("Twitter replies/interactions are ENABLED");
8540
+ this.interaction = new TwitterInteractionClient(
8541
+ this.client,
8542
+ runtime,
8543
+ state
8544
+ );
8545
+ } else {
8546
+ logger8.info("Twitter replies/interactions are DISABLED");
8547
+ }
8548
+ const actionsEnabled = (getSetting(runtime, "TWITTER_ENABLE_ACTIONS") ?? process.env.TWITTER_ENABLE_ACTIONS) === "true";
8549
+ if (actionsEnabled) {
8550
+ logger8.info("Twitter timeline actions are ENABLED");
8551
+ this.timeline = new TwitterTimelineClient(this.client, runtime, state);
8552
+ } else {
8553
+ logger8.info("Twitter timeline actions are DISABLED");
8554
+ }
8555
+ const discoveryEnabled = (getSetting(runtime, "TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) === "true" || actionsEnabled && (getSetting(runtime, "TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) !== "false";
8556
+ if (discoveryEnabled) {
8557
+ logger8.info("Twitter discovery service is ENABLED");
8558
+ this.discovery = new TwitterDiscoveryClient(this.client, runtime, state);
8559
+ } else {
8560
+ logger8.info("Twitter discovery service is DISABLED - set TWITTER_ENABLE_DISCOVERY=true to enable");
8561
+ }
8562
+ }
8563
+ };
8527
8564
  var _TwitterService = class _TwitterService extends Service {
8528
8565
  constructor() {
8529
8566
  super();
@@ -8533,9 +8570,48 @@ var _TwitterService = class _TwitterService extends Service {
8533
8570
  static async start(runtime) {
8534
8571
  const service = new _TwitterService();
8535
8572
  service.runtime = runtime;
8573
+ try {
8574
+ await validateTwitterConfig(runtime);
8575
+ logger8.log("\u2705 Twitter configuration validated successfully");
8576
+ service.twitterClient = new TwitterClientInstance(runtime, {});
8577
+ await service.twitterClient.client.init();
8578
+ if (service.twitterClient.post) {
8579
+ logger8.log("\u{1F4EE} Starting Twitter post client...");
8580
+ await service.twitterClient.post.start();
8581
+ }
8582
+ if (service.twitterClient.interaction) {
8583
+ logger8.log("\u{1F4AC} Starting Twitter interaction client...");
8584
+ await service.twitterClient.interaction.start();
8585
+ }
8586
+ if (service.twitterClient.timeline) {
8587
+ logger8.log("\u{1F4CA} Starting Twitter timeline client...");
8588
+ await service.twitterClient.timeline.start();
8589
+ }
8590
+ if (service.twitterClient.discovery) {
8591
+ logger8.log("\u{1F50D} Starting Twitter discovery client...");
8592
+ await service.twitterClient.discovery.start();
8593
+ }
8594
+ logger8.log("\u2705 Twitter service started successfully");
8595
+ } catch (error) {
8596
+ logger8.error("\u{1F6A8} Failed to start Twitter service:", error);
8597
+ throw error;
8598
+ }
8536
8599
  return service;
8537
8600
  }
8538
8601
  async stop() {
8602
+ if (this.twitterClient?.post) {
8603
+ await this.twitterClient.post.stop();
8604
+ }
8605
+ if (this.twitterClient?.interaction) {
8606
+ await this.twitterClient.interaction.stop();
8607
+ }
8608
+ if (this.twitterClient?.timeline) {
8609
+ await this.twitterClient.timeline.stop();
8610
+ }
8611
+ if (this.twitterClient?.discovery) {
8612
+ await this.twitterClient.discovery.stop();
8613
+ }
8614
+ logger8.log("Twitter service stopped");
8539
8615
  }
8540
8616
  };
8541
8617
  _TwitterService.serviceType = "twitter";
@@ -8543,27 +8619,27 @@ var TwitterService = _TwitterService;
8543
8619
 
8544
8620
  // src/actions/postTweet.ts
8545
8621
  import {
8546
- logger as logger8,
8622
+ logger as logger9,
8547
8623
  ModelType as ModelType4
8548
8624
  } from "@elizaos/core";
8549
8625
  var postTweetAction = {
8550
8626
  name: "POST_TWEET",
8551
8627
  similes: ["TWEET", "SEND_TWEET", "TWITTER_POST", "POST_ON_TWITTER", "SHARE_ON_TWITTER"],
8552
8628
  validate: async (runtime, message) => {
8553
- logger8.debug("Validating POST_TWEET action");
8629
+ logger9.debug("Validating POST_TWEET action");
8554
8630
  const text = message.content?.text?.trim();
8555
8631
  if (!text || text.length === 0) {
8556
- logger8.error("No text content for tweet");
8632
+ logger9.error("No text content for tweet");
8557
8633
  return false;
8558
8634
  }
8559
8635
  if (text.length > 280) {
8560
- logger8.warn(`Tweet too long: ${text.length} characters`);
8636
+ logger9.warn(`Tweet too long: ${text.length} characters`);
8561
8637
  }
8562
8638
  return true;
8563
8639
  },
8564
8640
  description: "Post a tweet on Twitter",
8565
8641
  handler: async (runtime, message, state, _options, callback) => {
8566
- logger8.info("Executing POST_TWEET action");
8642
+ logger9.info("Executing POST_TWEET action");
8567
8643
  try {
8568
8644
  const client = new ClientBase(runtime, {});
8569
8645
  if (!client.twitterClient) {
@@ -8610,7 +8686,7 @@ Tweet:`;
8610
8686
  tweetId = Date.now().toString();
8611
8687
  }
8612
8688
  const tweetUrl = `https://twitter.com/${client.profile.username}/status/${tweetId}`;
8613
- logger8.info(`Successfully posted tweet: ${tweetId}`);
8689
+ logger9.info(`Successfully posted tweet: ${tweetId}`);
8614
8690
  await runtime.createMemory({
8615
8691
  entityId: runtime.agentId,
8616
8692
  content: {
@@ -8637,7 +8713,7 @@ View it here: ${tweetUrl}`,
8637
8713
  throw new Error("Failed to post tweet - no response data");
8638
8714
  }
8639
8715
  } catch (error) {
8640
- logger8.error("Error posting tweet:", error);
8716
+ logger9.error("Error posting tweet:", error);
8641
8717
  if (callback) {
8642
8718
  await callback({
8643
8719
  text: `Sorry, I couldn't post the tweet. Error: ${error.message}`,
@@ -8697,91 +8773,37 @@ View it here: ${tweetUrl}`,
8697
8773
  };
8698
8774
 
8699
8775
  // src/index.ts
8700
- var TwitterClientInstance = class {
8701
- constructor(runtime, state) {
8702
- this.client = new ClientBase(runtime, state);
8703
- const getSetting3 = (key) => {
8704
- if (runtime && typeof runtime.getSetting === "function") {
8705
- return runtime.getSetting(key);
8706
- }
8707
- return void 0;
8708
- };
8709
- const postEnabledSetting = getSetting3("TWITTER_ENABLE_POST") ?? process.env.TWITTER_ENABLE_POST;
8710
- logger9.debug(`TWITTER_ENABLE_POST setting value: ${JSON.stringify(postEnabledSetting)}, type: ${typeof postEnabledSetting}`);
8711
- const postEnabled = postEnabledSetting === "true" || postEnabledSetting === true;
8712
- if (postEnabled) {
8713
- logger9.info("Twitter posting is ENABLED - creating post client");
8714
- this.post = new TwitterPostClient(this.client, runtime, state);
8715
- } else {
8716
- logger9.info("Twitter posting is DISABLED - set TWITTER_ENABLE_POST=true to enable automatic posting");
8717
- }
8718
- const repliesEnabled = (getSetting3("TWITTER_ENABLE_REPLIES") ?? process.env.TWITTER_ENABLE_REPLIES) !== "false";
8719
- if (repliesEnabled) {
8720
- logger9.info("Twitter replies/interactions are ENABLED");
8721
- this.interaction = new TwitterInteractionClient(
8722
- this.client,
8723
- runtime,
8724
- state
8725
- );
8726
- } else {
8727
- logger9.info("Twitter replies/interactions are DISABLED");
8728
- }
8729
- const actionsEnabled = (getSetting3("TWITTER_ENABLE_ACTIONS") ?? process.env.TWITTER_ENABLE_ACTIONS) === "true";
8730
- if (actionsEnabled) {
8731
- logger9.info("Twitter timeline actions are ENABLED");
8732
- this.timeline = new TwitterTimelineClient(this.client, runtime, state);
8733
- } else {
8734
- logger9.info("Twitter timeline actions are DISABLED");
8735
- }
8736
- const discoveryEnabled = (getSetting3("TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) === "true" || actionsEnabled && (getSetting3("TWITTER_ENABLE_DISCOVERY") ?? process.env.TWITTER_ENABLE_DISCOVERY) !== "false";
8737
- if (discoveryEnabled) {
8738
- logger9.info("Twitter discovery service is ENABLED");
8739
- this.discovery = new TwitterDiscoveryClient(this.client, runtime, state);
8740
- } else {
8741
- logger9.info("Twitter discovery service is DISABLED - set TWITTER_ENABLE_DISCOVERY=true to enable");
8742
- }
8743
- }
8744
- };
8745
- async function startTwitterClient(runtime) {
8746
- try {
8747
- logger9.log("\u{1F527} Initializing Twitter plugin...");
8748
- await validateTwitterConfig(runtime);
8749
- logger9.log("\u2705 Twitter configuration validated successfully");
8750
- const twitterClient = new TwitterClientInstance(runtime, {});
8751
- await twitterClient.client.init();
8752
- await runtime.registerService(TwitterService);
8753
- if (twitterClient.post) {
8754
- logger9.log("\u{1F4EE} Starting Twitter post client...");
8755
- await twitterClient.post.start();
8756
- }
8757
- if (twitterClient.interaction) {
8758
- logger9.log("\u{1F4AC} Starting Twitter interaction client...");
8759
- await twitterClient.interaction.start();
8760
- }
8761
- if (twitterClient.timeline) {
8762
- logger9.log("\u{1F4CA} Starting Twitter timeline client...");
8763
- await twitterClient.timeline.start();
8764
- }
8765
- if (twitterClient.discovery) {
8766
- logger9.log("\u{1F50D} Starting Twitter discovery client...");
8767
- await twitterClient.discovery.start();
8768
- }
8769
- logger9.log("\u2705 Twitter plugin started successfully");
8770
- } catch (error) {
8771
- logger9.error("\u{1F6A8} Failed to start Twitter plugin:", error);
8772
- throw error;
8773
- }
8774
- }
8775
8776
  var TwitterPlugin = {
8776
8777
  name: "twitter",
8777
8778
  description: "Twitter client with posting, interactions, and timeline actions",
8778
8779
  actions: [postTweetAction],
8779
8780
  services: [TwitterService],
8780
- init: startTwitterClient
8781
+ init: async (_config, runtime) => {
8782
+ logger10.log("\u{1F527} Initializing Twitter plugin...");
8783
+ const hasGetSetting = runtime && typeof runtime.getSetting === "function";
8784
+ const apiKey = hasGetSetting ? runtime.getSetting("TWITTER_API_KEY") : process.env.TWITTER_API_KEY;
8785
+ const apiSecretKey = hasGetSetting ? runtime.getSetting("TWITTER_API_SECRET_KEY") : process.env.TWITTER_API_SECRET_KEY;
8786
+ const accessToken = hasGetSetting ? runtime.getSetting("TWITTER_ACCESS_TOKEN") : process.env.TWITTER_ACCESS_TOKEN;
8787
+ const accessTokenSecret = hasGetSetting ? runtime.getSetting("TWITTER_ACCESS_TOKEN_SECRET") : process.env.TWITTER_ACCESS_TOKEN_SECRET;
8788
+ if (!apiKey || !apiSecretKey || !accessToken || !accessTokenSecret) {
8789
+ const missing = [];
8790
+ if (!apiKey) missing.push("TWITTER_API_KEY");
8791
+ if (!apiSecretKey) missing.push("TWITTER_API_SECRET_KEY");
8792
+ if (!accessToken) missing.push("TWITTER_ACCESS_TOKEN");
8793
+ if (!accessTokenSecret) missing.push("TWITTER_ACCESS_TOKEN_SECRET");
8794
+ logger10.warn(
8795
+ `Twitter API credentials not configured - Twitter functionality will be limited. Missing: ${missing.join(", ")}`
8796
+ );
8797
+ logger10.warn(
8798
+ "To enable Twitter functionality, please provide the missing credentials in your .env file"
8799
+ );
8800
+ } else {
8801
+ logger10.log("\u2705 Twitter credentials found");
8802
+ }
8803
+ }
8781
8804
  };
8782
8805
  var index_default = TwitterPlugin;
8783
8806
  export {
8784
- TwitterClientInstance,
8785
8807
  TwitterPlugin,
8786
8808
  index_default as default
8787
8809
  };