Skip to content

Commit 563ba9e

Browse files
committed
Can't build rabbi-trader error
1 parent e5c374c commit 563ba9e

File tree

120 files changed

+11911
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+11911
-54
lines changed

packages/client-twitter/src/index.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { TwitterInteractionClient } from "./interactions.ts";
99
import { TwitterPostClient } from "./post.ts";
1010
import { TwitterSearchClient } from "./search.ts";
1111
import { TwitterSpaceClient } from "./spaces.ts";
12+
import { TwitterSourceClient } from "./source.ts";
1213

1314
/**
1415
* A manager that orchestrates all specialized Twitter logic:
@@ -24,7 +25,7 @@ class TwitterManager {
2425
search: TwitterSearchClient;
2526
interaction: TwitterInteractionClient;
2627
space?: TwitterSpaceClient;
27-
28+
source: TwitterSourceClient;
2829
constructor(runtime: IAgentRuntime, twitterConfig: TwitterConfig) {
2930
// Pass twitterConfig to the base client
3031
this.client = new ClientBase(runtime, twitterConfig);
@@ -44,7 +45,7 @@ class TwitterManager {
4445

4546
// Mentions and interactions
4647
this.interaction = new TwitterInteractionClient(this.client, runtime);
47-
48+
this.source = new TwitterSourceClient(this.client, runtime);
4849
// Optional Spaces logic (enabled if TWITTER_SPACES_ENABLE is true)
4950
if (twitterConfig.TWITTER_SPACES_ENABLE) {
5051
this.space = new TwitterSpaceClient(this.client, runtime);
@@ -64,16 +65,18 @@ export const TwitterClientInterface: Client = {
6465
await manager.client.init();
6566

6667
// Start the posting loop
67-
await manager.post.start();
68+
//await manager.post.start();
6869

6970
// Start the search logic if it exists
7071
if (manager.search) {
71-
await manager.search.start();
72+
//await manager.search.start();
7273
}
73-
74+
7475
// Start interactions (mentions, replies)
75-
await manager.interaction.start();
76-
76+
//await manager.interaction.start();
77+
console.log("Starting source monitoring");
78+
await manager.source.start();
79+
console.log("Source monitoring started");
7780
// If Spaces are enabled, start the periodic check
7881
if (manager.space) {
7982
manager.space.startPeriodicSpaceCheck();

packages/client-twitter/src/interactions.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ export class TwitterInteractionClient {
379379

380380
// get usernames into str
381381
const validTargetUsersStr = this.client.twitterConfig.TWITTER_TARGET_USERS.join(",");
382-
382+
/*
383383
const shouldRespondContext = composeContext({
384384
state,
385385
template:
@@ -477,7 +477,7 @@ export class TwitterInteractionClient {
477477
} catch (error) {
478478
elizaLogger.error(`Error sending response tweet: ${error}`);
479479
}
480-
}
480+
}*/
481481
}
482482

483483
async buildConversationThread(

packages/client-twitter/src/source.ts

+166-45
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1-
import { elizaLogger } from "@elizaos/core";
1+
import { elizaLogger, stringToUuid, getEmbeddingZeroVector } from "@elizaos/core";
22
import { ClientBase } from "./base";
33
import { IAgentRuntime } from "@elizaos/core";
4-
import { Tweet } from "./types";
5-
import { SearchMode } from "./search";
4+
import { SearchMode, Tweet } from "agent-twitter-client";
5+
import { buildConversationThread } from "./utils";
66

77
export class TwitterSourceClient {
88
client: ClientBase;
99
runtime: IAgentRuntime;
1010
private isProcessing: boolean = false;
1111
private lastCheckedTweetId: string | null = null;
1212
private targetAccounts: string[];
13-
13+
1414
constructor(client: ClientBase, runtime: IAgentRuntime) {
1515
this.client = client;
1616
this.runtime = runtime;
17-
TWITTER_SOURCE_ACCOUNTS:
18-
runtime.getSetting("TWITTER_SOURCE_ACCOUNTS") ||
17+
const accountString = runtime.getSetting("TWITTER_SOURCE_ACCOUNTS") ||
1918
process.env.TWITTER_SOURCE_ACCOUNTS ||
20-
"", // Add this line
21-
19+
"";
20+
21+
this.targetAccounts = accountString
22+
.split(',')
23+
.map(account => account.trim().replace('@', '')) // Remove @ if present
24+
.filter(account => account.length > 0);
2225
// Log configuration
2326
elizaLogger.log("Twitter Source Client Configuration:");
24-
elizaLogger.log(`- Monitoring accounts: ${this.targetAccounts.join(', ')}`);
27+
console.log(this.targetAccounts);
28+
//elizaLogger.log(`- Monitoring accounts: ${this.targetAccounts.join(', ')}`);
2529
elizaLogger.log(`- Poll interval: ${this.client.twitterConfig.TWITTER_POLL_INTERVAL} seconds`);
2630
}
2731

@@ -30,12 +34,15 @@ export class TwitterSourceClient {
3034
this.monitorSourceAccounts();
3135
setTimeout(
3236
handleSourceMonitorLoop,
33-
this.client.twitterConfig.TWITTER_POLL_INTERVAL * 1000
37+
this.client.twitterConfig.TWITTER_POLL_INTERVAL * 10
3438
);
39+
//const aixbtUserId = stringToUuid('aixbt_agent');
40+
//const memories = this.runtime.messageManager.getMemoriesByRoomIds([aixbtUserId]);
41+
// console.log("LATEST aixbt memory:", memories[0]);
3542
};
36-
3743
handleSourceMonitorLoop();
38-
elizaLogger.log("Source monitoring loop started");
44+
45+
// elizaLogger.log("Source monitoring loop started");
3946
}
4047

4148
private async monitorSourceAccounts() {
@@ -48,44 +55,119 @@ export class TwitterSourceClient {
4855

4956
try {
5057
for (const username of this.targetAccounts) {
51-
elizaLogger.log(`Checking tweets from ${username}`);
52-
58+
elizaLogger.log(`Checking tweets from source account ${username}`);
59+
const aixbtUserId = stringToUuid('aixbt_agent');
60+
const memories = await this.runtime.messageManager.getMemories({
61+
roomId: aixbtUserId,
62+
count: 1,
63+
unique: true
64+
});
65+
66+
if (memories.length > 0) {
67+
elizaLogger.log('Latest aiXBT memory:', {
68+
id: memories[0].id,
69+
text: memories[0].content.text,
70+
timestamp: new Date(memories[0].createdAt).toISOString()
71+
});
72+
} else {
73+
elizaLogger.log('No memories found for aiXBT');
74+
}
5375
try {
54-
const userTweets = (
55-
await this.client.twitterClient.fetchSearchTweets(
76+
// Fetch both tweets and replies from the user
77+
const [userTweetsResponse, userRepliesResponse] = await Promise.all([
78+
// Fetch regular tweets
79+
this.client.twitterClient.fetchSearchTweets(
5680
`from:${username}`,
57-
5, // Fetch last 5 tweets
81+
20,
5882
SearchMode.Latest
59-
)
60-
).tweets;
83+
).catch(error => {
84+
elizaLogger.error(`Error fetching tweets for ${username}:`, error);
85+
return { tweets: [] };
86+
}),
87+
// Fetch replies
88+
this.client.twitterClient.fetchSearchTweets(
89+
`from:${username} is:reply`,
90+
20,
91+
SearchMode.Latest
92+
).catch(error => {
93+
elizaLogger.error(`Error fetching replies for ${username}:`, error);
94+
return { tweets: [] };
95+
})
96+
]);
97+
98+
// Combine tweets and replies
99+
const allTweets = [...(userTweetsResponse?.tweets || []), ...(userRepliesResponse?.tweets || [])];
61100

62-
// Filter for unprocessed, non-reply tweets
63-
const validTweets = userTweets.filter((tweet) => {
64-
const isUnprocessed = !this.lastCheckedTweetId ||
65-
parseInt(tweet.id) > parseInt(this.lastCheckedTweetId);
66-
const isRecent = Date.now() - tweet.timestamp * 1000 <
67-
2 * 60 * 60 * 1000; // Last 2 hours
101+
// Filter for unprocessed tweets
102+
const validTweets = allTweets.filter((tweet) => {
103+
if (!tweet || !tweet.id || !tweet.timestamp) {
104+
elizaLogger.warn("Invalid tweet object found:", tweet);
105+
return false;
106+
}
68107

69-
return isUnprocessed && !tweet.isReply && !tweet.isRetweet && isRecent;
108+
try {
109+
const isUnprocessed = !this.lastCheckedTweetId ||
110+
parseInt(tweet.id) > parseInt(this.lastCheckedTweetId);
111+
const isRecent = Date.now() - tweet.timestamp * 1000 <
112+
2 * 60 * 60 * 1000; // Last 2 hours
113+
114+
return isUnprocessed && !tweet.isRetweet && isRecent;
115+
} catch (error) {
116+
elizaLogger.error(`Error filtering tweet ${tweet.id}:`, error);
117+
return false;
118+
}
70119
});
71120

72121
if (validTweets.length > 0) {
73-
elizaLogger.log(`Found ${validTweets.length} new tweets from ${username}`);
122+
elizaLogger.log(`Found ${validTweets.length} new tweets/replies from ${username}`);
123+
124+
// For replies, fetch the conversation thread
125+
for (const tweet of validTweets) {
126+
if (tweet.isReply) {
127+
try {
128+
const thread = await buildConversationThread(tweet, this.client);
129+
// Create a clean version of the thread without circular references
130+
tweet.conversationThread = thread.map(t => ({
131+
id: t.id,
132+
text: t.text,
133+
username: t.username,
134+
timestamp: t.timestamp,
135+
isReply: t.isReply,
136+
isRetweet: t.isRetweet,
137+
inReplyToStatusId: t.inReplyToStatusId,
138+
permanentUrl: t.permanentUrl
139+
}));
140+
} catch (error) {
141+
elizaLogger.error(`Error fetching conversation thread for tweet ${tweet.id}:`, error);
142+
tweet.conversationThread = [];
143+
}
144+
}
145+
}
146+
74147
await this.processTweets(validTweets);
75148

76149
// Update last checked ID
77-
const latestTweetId = Math.max(...validTweets.map(t => parseInt(t.id))).toString();
78-
this.lastCheckedTweetId = latestTweetId;
79-
80-
// Cache the latest checked ID
81-
await this.client.cacheManager.set(
82-
`twitter/source/${username}/lastChecked`,
83-
{ id: latestTweetId, timestamp: Date.now() }
84-
);
150+
const validIds = validTweets
151+
.filter(t => t.id)
152+
.map(t => parseInt(t.id))
153+
.filter(id => !isNaN(id));
154+
155+
if (validIds.length > 0) {
156+
const latestTweetId = Math.max(...validIds).toString();
157+
this.lastCheckedTweetId = latestTweetId;
158+
159+
// Cache the latest checked ID
160+
await this.client.cacheManager.set(
161+
`twitter/source/${username}/lastChecked`,
162+
{ id: latestTweetId, timestamp: Date.now() }
163+
).catch(error => {
164+
elizaLogger.error(`Error caching latest tweet ID for ${username}:`, error);
165+
});
166+
}
85167
}
86168

87169
} catch (error) {
88-
elizaLogger.error(`Error fetching tweets for ${username}:`, error);
170+
elizaLogger.error(`Error processing tweets for ${username}:`, error);
89171
continue;
90172
}
91173
}
@@ -97,25 +179,64 @@ export class TwitterSourceClient {
97179
private async processTweets(tweets: Tweet[]) {
98180
for (const tweet of tweets) {
99181
try {
182+
if (!tweet.id || !tweet.text || !tweet.timestamp) {
183+
elizaLogger.warn("Skipping invalid tweet:", tweet);
184+
continue;
185+
}
186+
187+
// Serialize conversation thread to avoid circular references
188+
/*const serializedThread = tweet.conversationThread?.map(t => ({
189+
id: t.id,
190+
text: t.text,
191+
username: t.username,
192+
timestamp: t.timestamp,
193+
isReply: t.isReply,
194+
isRetweet: t.isRetweet,
195+
inReplyToStatusId: t.inReplyToStatusId,
196+
permanentUrl: t.permanentUrl
197+
}));*/
198+
199+
const roomId = stringToUuid(tweet.conversationId);
200+
elizaLogger.log("Creating new memory:", {
201+
id: tweet.id + "-" + this.runtime.agentId,
202+
text: tweet.text,
203+
source: "twitter",
204+
url: tweet.permanentUrl,
205+
inReplyTo: tweet.inReplyToStatusId,
206+
createdAt: new Date(tweet.timestamp * 1000).toISOString(),
207+
roomId: roomId,
208+
userId: tweet.userId === this.twitterUserId ? this.runtime.agentId : tweet.userId
209+
});
100210
// Create memory entry for the tweet
101-
await this.runtime.messageManager.createMemory({
102-
id: stringToUuid(tweet.id + "-source-" + this.runtime.agentId),
103-
userId: this.runtime.agentId,
211+
this.runtime.messageManager.createMemory({
212+
id: stringToUuid(
213+
tweet.id + "-" + this.runtime.agentId
214+
),
104215
agentId: this.runtime.agentId,
105216
content: {
106217
text: tweet.text,
218+
source: "twitter",
107219
url: tweet.permanentUrl,
108-
source: "twitter_source",
109-
sourceUser: tweet.username
220+
inReplyTo: tweet.inReplyToStatusId
221+
? stringToUuid(
222+
tweet.inReplyToStatusId +
223+
"-" +
224+
this.runtime.agentId
225+
)
226+
: undefined,
110227
},
111-
roomId: stringToUuid("twitter-source-" + this.runtime.agentId),
228+
createdAt: tweet.timestamp * 1000,
229+
roomId,
230+
userId:
231+
tweet.userId === this.twitterUserId
232+
? this.runtime.agentId
233+
: stringToUuid(tweet.userId),
112234
embedding: getEmbeddingZeroVector(),
113-
createdAt: tweet.timestamp,
114235
});
115236

116-
elizaLogger.log(`Processed tweet from ${tweet.username}: ${tweet.id}`);
237+
elizaLogger.log(`Processed ${tweet.isReply ? 'reply' : 'tweet'} from ${tweet.username}: ${tweet.id}`);
117238
} catch (error) {
118-
elizaLogger.error(`Error processing tweet ${tweet.id}:`, error);
239+
elizaLogger.error(`Error processing tweet ${tweet.id}:`, error?.message || error);
119240
}
120241
}
121242
}

packages/core/src/memory.ts

+1
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ export class MemoryManager implements IMemoryManager {
202202
if (result && result.agentId !== this.runtime.agentId) return null;
203203
return result;
204204
}
205+
205206

206207
/**
207208
* Removes a memory from the database by its ID.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@elizaos/plugin-rabbi-trader",
3+
"version": "0.1.5-alpha.5",
4+
"main": "dist/index.js",
5+
"type": "module",
6+
"types": "dist/index.d.ts",
7+
"dependencies": {
8+
"@elizaos/core": "workspace:*",
9+
"@elizaos/client-twitter":"workspace:*",
10+
"@elizaos/plugin-solana":"workspace:*",
11+
"@elizaos/plugin-trustdb":"workspace:*",
12+
"@solana/web3.js": "^1.87.6",
13+
"zod":"3.23.8",
14+
"@goat-sdk/core": "0.3.8",
15+
"@goat-sdk/plugin-erc20": "0.1.7",
16+
"@goat-sdk/wallet-viem": "0.1.3",
17+
"node-cache": "^5.1.2",
18+
"bignumber": "1.1.0",
19+
"bignumber.js": "9.1.2",
20+
"@goat-sdk/plugin-coingecko":"0.1.4",
21+
"tsup": "8.3.5",
22+
"ws": "^8.0.0"
23+
},
24+
"scripts": {
25+
"build": "tsup --format esm --dts",
26+
"dev": "tsup --format esm --dts --watch"
27+
},
28+
"peerDependencies": {
29+
"whatwg-url": "7.1.0"
30+
}
31+
}

0 commit comments

Comments
 (0)