Skip to content

Commit dce8bae

Browse files
allow custom actions
1 parent 0905d97 commit dce8bae

8 files changed

+149
-48
lines changed

README.md

+63-44
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,35 @@ _As seen powering [@DegenSpartanAI](https://x.com/degenspartanai) and [@MarcAInd
1717

1818
# Getting Started
1919

20-
## Install Node.js
20+
**Prerequisites (MUST):**
2121

22-
https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
22+
- [Node.js 22+](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
23+
- [pnpm](https://pnpm.io/installation)
2324

24-
## Using pnpm
25-
26-
We use pnpm to manage our dependencies. It is faster and more efficient than npm, and it supports workspaces.
27-
https://pnpm.io/installation
28-
29-
## Edit the .env file
25+
### Edit the .env file
3026

3127
- Copy .env.example to .env and fill in the appropriate values
3228
- Edit the TWITTER environment variables to add your bot's username and password
3329

34-
## Edit the character file
30+
### Edit the character file
3531

3632
- Check out the file `src/core/defaultCharacter.ts` - you can modify this
37-
- You can also load characters with the `node --loader ts-node/esm src/index.ts --characters="path/to/your/character.json"` and run multiple bots at the same time.
33+
- You can also load characters with the `pnpm start --characters="path/to/your/character.json"` and run multiple bots at the same time.
34+
35+
After setting up the .env file and character file, you can start the bot with the following command:
36+
37+
```
38+
pnpm i
39+
pnpm start
40+
```
41+
42+
# Customising Eliza
43+
44+
### Adding custom actions
45+
46+
To avoid git clashes in the core directory, we recommend adding custom actions to a `custom_actions` directory and then adding them to the `elizaConfig.yaml` file. See the `elizaConfig.example.yaml` file for an example.
47+
48+
## Running with different models
3849

3950
### Run with Llama
4051

@@ -48,10 +59,6 @@ You can run Grok models by setting the `XAI_MODEL` environment variable to `grok
4859

4960
You can run OpenAI models by setting the `XAI_MODEL` environment variable to `gpt-4o-mini` or `gpt-4o`
5061

51-
# Requires Node 20+
52-
53-
If you are getting strange issues when starting up, make sure you're using Node 20+. Some APIs are not compatible with previous versions. You can check your node version with `node -v`. If you need to install a new version of node, we recommend using [nvm](https://github.com/nvm-sh/nvm).
54-
5562
## Additional Requirements
5663

5764
You may need to install Sharp. If you see an error when starting up, try installing it with the following command:
@@ -66,20 +73,55 @@ You will need to add environment variables to your .env file to connect to vario
6673

6774
```
6875
# Required environment variables
69-
# Start Discord
7076
DISCORD_APPLICATION_ID=
7177
DISCORD_API_TOKEN= # Bot token
78+
OPENAI_API_KEY=sk-* # OpenAI API key, starting with sk-
79+
ELEVENLABS_XI_API_KEY= # API key from elevenlabs
7280
73-
# Start Twitter
81+
# ELEVENLABS SETTINGS
82+
ELEVENLABS_MODEL_ID=eleven_multilingual_v2
83+
ELEVENLABS_VOICE_ID=21m00Tcm4TlvDq8ikWAM
84+
ELEVENLABS_VOICE_STABILITY=0.5
85+
ELEVENLABS_VOICE_SIMILARITY_BOOST=0.9
86+
ELEVENLABS_VOICE_STYLE=0.66
87+
ELEVENLABS_VOICE_USE_SPEAKER_BOOST=false
88+
ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=4
89+
ELEVENLABS_OUTPUT_FORMAT=pcm_16000
90+
91+
TWITTER_DRY_RUN=false
7492
TWITTER_USERNAME= # Account username
7593
TWITTER_PASSWORD= # Account password
7694
TWITTER_EMAIL= # Account email
7795
TWITTER_COOKIES= # Account cookies
96+
97+
X_SERVER_URL=
98+
XAI_API_KEY=
99+
XAI_MODEL=
100+
101+
102+
# For asking Claude stuff
103+
ANTHROPIC_API_KEY=
104+
105+
WALLET_SECRET_KEY=EXAMPLE_WALLET_SECRET_KEY
106+
WALLET_PUBLIC_KEY=EXAMPLE_WALLET_PUBLIC_KEY
107+
108+
BIRDEYE_API_KEY=
109+
110+
SOL_ADDRESS=So11111111111111111111111111111111111111112
111+
SLIPPAGE=1
112+
RPC_URL=https://api.mainnet-beta.solana.com
113+
HELIUS_API_KEY=
114+
115+
116+
## Telegram
117+
TELEGRAM_BOT_TOKEN=
118+
119+
TOGETHER_API_KEY=
78120
```
79121

80-
# Local Setup
122+
# Local Inference Setup
81123

82-
## CUDA Setup
124+
### CUDA Setup
83125

84126
If you have an NVIDIA GPU, you can install CUDA to speed up local inference dramatically.
85127

@@ -90,37 +132,14 @@ npx --no node-llama-cpp source download --gpu cuda
90132

91133
Make sure that you've installed the CUDA Toolkit, including cuDNN and cuBLAS.
92134

93-
## Running locally
135+
### Running locally
94136

95137
Add XAI_MODEL and set it to one of the above options from [Run with
96138
Llama](#run-with-llama) - you can leave X_SERVER_URL and XAI_API_KEY blank, it
97139
downloads the model from huggingface and queries it locally
98140

99-
# Cloud Setup (with OpenAI)
100-
101-
In addition to the environment variables above, you will need to add the following:
102-
103-
```
104-
# OpenAI handles the bulk of the work with chat, TTS, image recognition, etc.
105-
OPENAI_API_KEY=sk-* # OpenAI API key, starting with sk-
106-
107-
# The agent can also ask Claude for help if you have an API key
108-
ANTHROPIC_API_KEY=
109-
110-
# For Elevenlabs voice generation on Discord voice
111-
ELEVENLABS_XI_API_KEY= # API key from elevenlabs
112-
113-
# ELEVENLABS SETTINGS
114-
ELEVENLABS_MODEL_ID=eleven_multilingual_v2
115-
ELEVENLABS_VOICE_ID=21m00Tcm4TlvDq8ikWAM
116-
ELEVENLABS_VOICE_STABILITY=0.5
117-
ELEVENLABS_VOICE_SIMILARITY_BOOST=0.9
118-
ELEVENLABS_VOICE_STYLE=0.66
119-
ELEVENLABS_VOICE_USE_SPEAKER_BOOST=false
120-
ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=4
121-
ELEVENLABS_OUTPUT_FORMAT=pcm_16000
122-
```
141+
# Clients
123142

124-
# Discord Bot
143+
## Discord Bot
125144

126145
For help with setting up your Discord Bot, check out here: https://discordjs.guide/preparations/setting-up-a-bot-application.html

core/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
node_modules
22
dist
3+
elizaConfig.yaml
4+
custom_actions/

core/elizaConfig.example.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Load custom actions from the actions directory
2+
3+
# Close this into a elizaConfig.yaml file that is ignored by git
4+
5+
# Paths are relative to the core/src directory
6+
7+
actions:
8+
- name: askClaude
9+
path: ./actions/askClaude.ts
10+
- name: epicAction
11+
path: ./custom_actions/epicAction.ts

core/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,10 @@
124124
"html-escaper": "3.0.3",
125125
"html-to-text": "9.0.5",
126126
"import-meta-resolve": "4.1.0",
127+
"install": "^0.13.0",
127128
"jieba-wasm": "2.2.0",
128129
"js-sha1": "0.7.0",
130+
"js-yaml": "^4.1.0",
129131
"json5": "2.2.3",
130132
"kuromoji": "0.1.2",
131133
"libsodium-wrappers": "0.7.15",

core/src/cli/config.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import fs from "fs";
2+
import yaml from "js-yaml";
3+
import path from "path";
4+
import { fileURLToPath } from "url";
5+
import { Action } from "../core/types";
6+
7+
const ROOT_DIR = path.resolve(fileURLToPath(import.meta.url), "../../../src");
8+
9+
interface ActionConfig {
10+
name: string;
11+
path: string;
12+
}
13+
14+
export function loadActionConfigs(configPath: string): ActionConfig[] {
15+
if (!fs.existsSync(configPath)) {
16+
console.error(`Config file not found at path: ${configPath}`);
17+
return [];
18+
}
19+
20+
const configFile = fs.readFileSync(configPath, "utf8");
21+
const parsedConfig = yaml.load(configFile) as { actions: ActionConfig[] };
22+
return parsedConfig?.actions || [];
23+
}
24+
25+
export async function loadCustomActions(
26+
actionConfigs: ActionConfig[]
27+
): Promise<Action[]> {
28+
const actions = [];
29+
30+
for (const config of actionConfigs) {
31+
const resolvedPath = path.resolve(ROOT_DIR, config.path);
32+
console.log(`Importing action from: ${resolvedPath}`); // Debugging log
33+
34+
try {
35+
const actionModule = await import(resolvedPath);
36+
actions.push(actionModule[config.name]);
37+
} catch (error) {
38+
console.error(
39+
`Failed to import action from ${resolvedPath}:`,
40+
error
41+
);
42+
}
43+
}
44+
return actions;
45+
}

core/src/cli/index.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Database from "better-sqlite3";
1313
import { AgentRuntime } from "../core/runtime.ts";
1414
import { defaultActions } from "../core/actions.ts";
1515
import { Arguments } from "../types/index.ts";
16+
import { loadActionConfigs, loadCustomActions } from "./config.ts";
1617

1718
export async function initializeClients(
1819
character: Character,
@@ -113,11 +114,15 @@ export function initializeDatabase() {
113114
}
114115
}
115116

116-
export function createAgentRuntime(
117+
export async function createAgentRuntime(
117118
character: Character,
118119
db: any,
119-
token: string
120+
token: string,
121+
configPath: string = "./elizaConfig.yaml"
120122
) {
123+
const actionConfigs = loadActionConfigs(configPath);
124+
const customActions = await loadCustomActions(actionConfigs);
125+
121126
return new AgentRuntime({
122127
databaseAdapter: db,
123128
token,
@@ -126,13 +131,18 @@ export function createAgentRuntime(
126131
character,
127132
providers: [Provider.timeProvider, Provider.boredomProvider],
128133
actions: [
134+
// Default actions
129135
...defaultActions,
130-
Action.askClaude,
136+
137+
// Custom actions
131138
Action.followRoom,
132139
Action.unfollowRoom,
133140
Action.unmuteRoom,
134141
Action.muteRoom,
135142
Action.imageGeneration,
143+
144+
// imported from elizaConfig.yaml
145+
...customActions,
136146
],
137147
});
138148
}

core/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async function startAgent(character: Character) {
3333
const token = getTokenForProvider(character.modelProvider, character);
3434
const db = initializeDatabase();
3535

36-
const runtime = createAgentRuntime(character, db, token);
36+
const runtime = await createAgentRuntime(character, db, token);
3737
const directRuntime = createDirectRuntime(character, db, token);
3838

3939
const clients = await initializeClients(character, runtime);

pnpm-lock.yaml

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)