Skip to content

Commit 1a214ec

Browse files
authored
Merge branch 'develop' into feature/add-client-instagram
2 parents 2470350 + 7575a1c commit 1a214ec

Some content is hidden

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

73 files changed

+4475
-952
lines changed

.env.example

+10
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ FUEL_WALLET_PRIVATE_KEY=
407407
TOKENIZER_MODEL= # Specify the tokenizer model to be used.
408408
TOKENIZER_TYPE= # Options: tiktoken (for OpenAI models) or auto (AutoTokenizer from Hugging Face for non-OpenAI models). Default: tiktoken.
409409

410+
411+
# Spheron
412+
SPHERON_PRIVATE_KEY=
413+
SPHERON_PROVIDER_PROXY_URL=
414+
SPHERON_WALLET_ADDRESS=
415+
410416
# Stargaze NFT marketplace from Cosmos (You can use https://graphql.mainnet.stargaze-apis.com/graphql)
411417
STARGAZE_ENDPOINT=
412418

@@ -415,3 +421,7 @@ GENLAYER_PRIVATE_KEY=0x000000000000000000000000000000000000000000000000000000000
415421

416422
# OpenWeather
417423
OPEN_WEATHER_API_KEY= # OpenWeather API key
424+
425+
# Allora
426+
ALLORA_API_KEY=UP-f8db7d6558ab432ca0d92716 # Allora API key
427+
ALLORA_CHAIN_SLUG=testnet # must be one of mainnet, testnet. If not specified, it will use testnet by default

agent/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"@elizaos/plugin-genlayer": "workspace:*",
7373
"@elizaos/plugin-open-weather": "workspace:*",
7474
"@elizaos/plugin-arthera": "workspace:*",
75+
"@elizaos/plugin-allora": "workspace:*",
7576
"readline": "1.3.0",
7677
"ws": "8.18.0",
7778
"yargs": "17.7.2"

agent/src/index.ts

+5-8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { DirectClient } from "@elizaos/client-direct";
3838
import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation";
3939
import { abstractPlugin } from "@elizaos/plugin-abstract";
4040
import { aptosPlugin } from "@elizaos/plugin-aptos";
41+
import { alloraPlugin } from "@elizaos/plugin-allora";
4142
import { avalanchePlugin } from "@elizaos/plugin-avalanche";
4243
import { binancePlugin } from "@elizaos/plugin-binance";
4344
import {
@@ -374,7 +375,7 @@ export function getTokenForProvider(
374375
}
375376
}
376377

377-
function initializeDatabase(dataDir: string) {
378+
async function initializeDatabase(dataDir: string) {
378379
if (process.env.POSTGRES_URL) {
379380
elizaLogger.info("Initializing PostgreSQL connection...");
380381
const db = new PostgresDatabaseAdapter({
@@ -514,11 +515,7 @@ export async function createAgent(
514515
cache: ICacheManager,
515516
token: string
516517
): Promise<AgentRuntime> {
517-
elizaLogger.success(
518-
elizaLogger.successesTitle,
519-
"Creating runtime for character",
520-
character.name
521-
);
518+
elizaLogger.log(`Creating runtime for character ${character.name}`);
522519

523520
nodePlugin ??= createNodePlugin();
524521

@@ -669,6 +666,7 @@ export async function createAgent(
669666
getSecret(character, "ARTHERA_PRIVATE_KEY")?.startsWith("0x")
670667
? artheraPlugin
671668
: null,
669+
getSecret(character, "ALLORA_API_KEY") ? alloraPlugin : null,
672670
].filter(Boolean),
673671
providers: [],
674672
actions: [],
@@ -767,10 +765,9 @@ async function startAgent(
767765
fs.mkdirSync(dataDir, { recursive: true });
768766
}
769767

770-
db = initializeDatabase(dataDir) as IDatabaseAdapter &
768+
db = await initializeDatabase(dataDir) as IDatabaseAdapter &
771769
IDatabaseCacheAdapter;
772770

773-
await db.init();
774771

775772
const cache = initializeCache(
776773
process.env.CACHE_STORE ?? CacheStore.DATABASE,

docs/docs/packages/plugins.md

+30
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,36 @@ cargo run --ip-addr <ip>:<port>
742742
docker run --init -p 127.0.0.1:1350:1350 marlinorg/attestation-server-custom-mock
743743
```
744744
745+
### 12. Allora Plugin (`@elizaos/allora-plugin`)
746+
747+
The [Allora Network](https://allora.network) plugin seamlessly empowers Eliza agents with real-time, advanced, self-improving AI inferences, delivering high-performance insights without introducing any additional complexity.
748+
749+
#### Setup and Configuration
750+
751+
1. Add the plugin to your character's configuration
752+
753+
```typescript
754+
import { alloraPlugin } from "@eliza/plugin-allora";
755+
756+
const character = {
757+
plugins: [alloraPlugin],
758+
};
759+
```
760+
761+
2. Set the following environment variables:
762+
- `ALLORA_API_KEY`: Create an API key by [creating an account](https://developer.upshot.xyz/signup).
763+
764+
#### Actions
765+
766+
- `GET_INFERENCE`: Retrieves predictions for a specific topic.
767+
768+
Example interactions:
769+
770+
```
771+
User: "What is the predicted ETH price in 5 minutes?"
772+
Agent: "I'll get the inference now..."
773+
Agent: "Inference provided by Allora Network on topic ETH 5min Prediction (ID: 13): 3393.364326646801085508"
774+
745775
### Writing Custom Plugins
746776

747777
Create a new plugin by implementing the Plugin interface:

packages/adapter-sqlite/src/index.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,19 @@ export class SqliteDatabaseAdapter
215215
const content = JSON.stringify(memory.content);
216216
const createdAt = memory.createdAt ?? Date.now();
217217

218+
let embeddingValue: Float32Array = new Float32Array(384);
219+
// If embedding is not available, we just load an array with a length of 384
220+
if (memory?.embedding && memory?.embedding?.length > 0) {
221+
embeddingValue = new Float32Array(memory.embedding);
222+
}
223+
218224
// Insert the memory with the appropriate 'unique' value
219225
const sql = `INSERT OR REPLACE INTO memories (id, type, content, embedding, userId, roomId, agentId, \`unique\`, createdAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
220226
this.db.prepare(sql).run(
221227
memory.id ?? v4(),
222228
tableName,
223229
content,
224-
new Float32Array(memory.embedding!), // Store as Float32Array
230+
embeddingValue,
225231
memory.userId,
226232
memory.roomId,
227233
memory.agentId,
@@ -707,4 +713,4 @@ export class SqliteDatabaseAdapter
707713
return false;
708714
}
709715
}
710-
}
716+
}

packages/client-telegram/src/messageManager.ts

+5-15
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Result: [RESPOND]
5252
{{user1}}: stfu bot
5353
Result: [STOP]
5454
55-
{{user1}}: Hey {{agent}}, can you help me with something
55+
{{user1}}: Hey {{agentName}}, can you help me with something
5656
Result: [RESPOND]
5757
5858
{{user1}}: {{agentName}} stfu plz
@@ -63,7 +63,7 @@ Result: [STOP]
6363
{{user1}}: no. i need help from someone else
6464
Result: [IGNORE]
6565
66-
{{user1}}: Hey {{agent}}, can I ask you a question
66+
{{user1}}: Hey {{agentName}}, can I ask you a question
6767
{{agentName}}: Sure, what is it
6868
{{user1}}: can you ask claude to create a basic react module that demonstrates a counter
6969
Result: [RESPOND]
@@ -103,28 +103,22 @@ The goal is to decide whether {{agentName}} should respond to the last message.
103103
104104
{{recentMessages}}
105105
106-
Thread of Tweets You Are Replying To:
107-
108-
{{formattedConversation}}
109-
110106
# INSTRUCTIONS: Choose the option that best describes {{agentName}}'s response to the last message. Ignore messages if they are addressed to someone else.
111107
` + shouldRespondFooter;
112108

113109
const telegramMessageHandlerTemplate =
114110
// {{goals}}
115-
`# Action Examples
111+
`
116112
{{actionExamples}}
117113
(Action examples are for reference only. Do not use the information from them in your response.)
118114
119115
# Knowledge
120116
{{knowledge}}
121117
122-
# Task: Generate dialog and actions for the character {{agentName}}.
123-
About {{agentName}}:
118+
# About {{agentName}}:
124119
{{bio}}
125120
{{lore}}
126121
127-
Examples of {{agentName}}'s dialog and actions:
128122
{{characterMessageExamples}}
129123
130124
{{providers}}
@@ -140,11 +134,7 @@ Note that {{agentName}} is capable of reading/seeing/hearing various forms of me
140134
141135
{{recentMessages}}
142136
143-
# Task: Generate a post/reply in the voice, style and perspective of {{agentName}} (@{{twitterUserName}}) while using the thread of tweets as additional context:
144-
Current Post:
145-
{{currentPost}}
146-
Thread of Tweets You Are Replying To:
147-
137+
# Task: Generate a reply in the voice, style and perspective of {{agentName}} while using the thread above as additional context. You are replying on Telegram.
148138
{{formattedConversation}}
149139
` + messageCompletionFooter;
150140

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { ClientBase } from '../src/base';
3+
import { IAgentRuntime } from '@elizaos/core';
4+
import { TwitterConfig } from '../src/environment';
5+
6+
describe('Twitter Client Base', () => {
7+
let mockRuntime: IAgentRuntime;
8+
let mockConfig: TwitterConfig;
9+
10+
beforeEach(() => {
11+
mockRuntime = {
12+
env: {
13+
TWITTER_USERNAME: 'testuser',
14+
TWITTER_DRY_RUN: 'true',
15+
TWITTER_POST_INTERVAL_MIN: '5',
16+
TWITTER_POST_INTERVAL_MAX: '10',
17+
TWITTER_ACTION_INTERVAL: '5',
18+
TWITTER_ENABLE_ACTION_PROCESSING: 'true',
19+
TWITTER_POST_IMMEDIATELY: 'false',
20+
TWITTER_SEARCH_ENABLE: 'false'
21+
},
22+
getEnv: function (key: string) {
23+
return this.env[key] || null;
24+
},
25+
getSetting: function (key: string) {
26+
return this.env[key] || null;
27+
},
28+
character: {
29+
style: {
30+
all: ['Test style 1', 'Test style 2'],
31+
post: ['Post style 1', 'Post style 2']
32+
}
33+
}
34+
} as unknown as IAgentRuntime;
35+
36+
mockConfig = {
37+
TWITTER_USERNAME: 'testuser',
38+
TWITTER_DRY_RUN: true,
39+
TWITTER_SEARCH_ENABLE: false,
40+
TWITTER_SPACES_ENABLE: false,
41+
TWITTER_TARGET_USERS: [],
42+
TWITTER_MAX_TWEETS_PER_DAY: 10,
43+
TWITTER_MAX_TWEET_LENGTH: 280,
44+
POST_INTERVAL_MIN: 5,
45+
POST_INTERVAL_MAX: 10,
46+
ACTION_INTERVAL: 5,
47+
ENABLE_ACTION_PROCESSING: true,
48+
POST_IMMEDIATELY: false
49+
};
50+
});
51+
52+
it('should create instance with correct configuration', () => {
53+
const client = new ClientBase(mockRuntime, mockConfig);
54+
expect(client).toBeDefined();
55+
expect(client.twitterConfig).toBeDefined();
56+
expect(client.twitterConfig.TWITTER_USERNAME).toBe('testuser');
57+
expect(client.twitterConfig.TWITTER_DRY_RUN).toBe(true);
58+
});
59+
60+
it('should initialize with correct tweet length limit', () => {
61+
const client = new ClientBase(mockRuntime, mockConfig);
62+
expect(client.twitterConfig.TWITTER_MAX_TWEET_LENGTH).toBe(280);
63+
});
64+
65+
it('should initialize with correct post intervals', () => {
66+
const client = new ClientBase(mockRuntime, mockConfig);
67+
expect(client.twitterConfig.POST_INTERVAL_MIN).toBe(5);
68+
expect(client.twitterConfig.POST_INTERVAL_MAX).toBe(10);
69+
});
70+
71+
it('should initialize with correct action settings', () => {
72+
const client = new ClientBase(mockRuntime, mockConfig);
73+
expect(client.twitterConfig.ACTION_INTERVAL).toBe(5);
74+
expect(client.twitterConfig.ENABLE_ACTION_PROCESSING).toBe(true);
75+
});
76+
});

0 commit comments

Comments
 (0)