Skip to content

Commit ac1c158

Browse files
authored
Merge branch 'develop' into remote-url-with-multiple-characters
2 parents 25b8f8d + 5b57a6d commit ac1c158

Some content is hidden

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

53 files changed

+2696
-291
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ agent/content
6262

6363
eliza.manifest
6464
eliza.manifest.sgx
65-
eliza.sig
65+
eliza.sig

agent/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@elizaos/plugin-binance": "workspace:*",
4444
"@elizaos/plugin-avail": "workspace:*",
4545
"@elizaos/plugin-bootstrap": "workspace:*",
46+
"@elizaos/plugin-di": "workspace:*",
4647
"@elizaos/plugin-cosmos": "workspace:*",
4748
"@elizaos/plugin-intiface": "workspace:*",
4849
"@elizaos/plugin-coinbase": "workspace:*",

agent/src/index.ts

+65-59
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
import { zgPlugin } from "@elizaos/plugin-0g";
4141

4242
import { bootstrapPlugin } from "@elizaos/plugin-bootstrap";
43+
import { normalizeCharacter } from "@elizaos/plugin-di";
4344
import createGoatPlugin from "@elizaos/plugin-goat";
4445
// import { intifacePlugin } from "@elizaos/plugin-intiface";
4546
import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation";
@@ -248,6 +249,7 @@ export async function loadCharacterFromOnchain(): Promise<Character[]> {
248249
}
249250
}
250251

252+
251253
async function loadCharactersFromUrl(url: string): Promise<Character[]> {
252254
try {
253255
const response = await fetch(url);
@@ -319,6 +321,61 @@ async function loadCharacter(filePath: string): Promise<Character> {
319321
return jsonToCharacter(filePath, character);
320322
}
321323

324+
async function loadCharacterTryPath(characterPath: string): Promise<Character> {
325+
let content: string | null = null;
326+
let resolvedPath = "";
327+
328+
// Try different path resolutions in order
329+
const pathsToTry = [
330+
characterPath, // exact path as specified
331+
path.resolve(process.cwd(), characterPath), // relative to cwd
332+
path.resolve(process.cwd(), "agent", characterPath), // Add this
333+
path.resolve(__dirname, characterPath), // relative to current script
334+
path.resolve(__dirname, "characters", path.basename(characterPath)), // relative to agent/characters
335+
path.resolve(__dirname, "../characters", path.basename(characterPath)), // relative to characters dir from agent
336+
path.resolve(
337+
__dirname,
338+
"../../characters",
339+
path.basename(characterPath)
340+
), // relative to project root characters dir
341+
];
342+
343+
elizaLogger.info(
344+
"Trying paths:",
345+
pathsToTry.map((p) => ({
346+
path: p,
347+
exists: fs.existsSync(p),
348+
}))
349+
);
350+
351+
for (const tryPath of pathsToTry) {
352+
content = tryLoadFile(tryPath);
353+
if (content !== null) {
354+
resolvedPath = tryPath;
355+
break;
356+
}
357+
}
358+
359+
if (content === null) {
360+
elizaLogger.error(
361+
`Error loading character from ${characterPath}: File not found in any of the expected locations`
362+
);
363+
elizaLogger.error("Tried the following paths:");
364+
pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));
365+
throw new Error(
366+
`Error loading character from ${characterPath}: File not found in any of the expected locations`
367+
);
368+
}
369+
try {
370+
const character: Character = await loadCharacter(resolvedPath);
371+
elizaLogger.info(`Successfully loaded character from: ${resolvedPath}`);
372+
return character;
373+
} catch (e) {
374+
elizaLogger.error(`Error parsing character from ${resolvedPath}: ${e}`);
375+
throw new Error(`Error parsing character from ${resolvedPath}: ${e}`);
376+
}
377+
}
378+
322379
function commaSeparatedStringToArray(commaSeparated: string): string[] {
323380
return commaSeparated?.split(",").map((value) => value.trim());
324381
}
@@ -331,68 +388,11 @@ export async function loadCharacters(
331388

332389
if (characterPaths?.length > 0) {
333390
for (const characterPath of characterPaths) {
334-
let content: string | null = null;
335-
let resolvedPath = "";
336-
337-
// Try different path resolutions in order
338-
const pathsToTry = [
339-
characterPath, // exact path as specified
340-
path.resolve(process.cwd(), characterPath), // relative to cwd
341-
path.resolve(process.cwd(), "agent", characterPath), // Add this
342-
path.resolve(__dirname, characterPath), // relative to current script
343-
path.resolve(
344-
__dirname,
345-
"characters",
346-
path.basename(characterPath)
347-
), // relative to agent/characters
348-
path.resolve(
349-
__dirname,
350-
"../characters",
351-
path.basename(characterPath)
352-
), // relative to characters dir from agent
353-
path.resolve(
354-
__dirname,
355-
"../../characters",
356-
path.basename(characterPath)
357-
), // relative to project root characters dir
358-
];
359-
360-
elizaLogger.info(
361-
"Trying paths:",
362-
pathsToTry.map((p) => ({
363-
path: p,
364-
exists: fs.existsSync(p),
365-
}))
366-
);
367-
368-
for (const tryPath of pathsToTry) {
369-
content = tryLoadFile(tryPath);
370-
if (content !== null) {
371-
resolvedPath = tryPath;
372-
break;
373-
}
374-
}
375-
376-
if (content === null) {
377-
elizaLogger.error(
378-
`Error loading character from ${characterPath}: File not found in any of the expected locations`
379-
);
380-
elizaLogger.error("Tried the following paths:");
381-
pathsToTry.forEach((p) => elizaLogger.error(` - ${p}`));
382-
process.exit(1);
383-
}
384-
385391
try {
386-
const character: Character = await loadCharacter(resolvedPath);
387-
392+
const character: Character =
393+
await loadCharacterTryPath(characterPath);
388394
loadedCharacters.push(character);
389-
elizaLogger.info(
390-
`Successfully loaded character from: ${resolvedPath}`
391-
);
392395
} catch (e) {
393-
elizaLogger.error(
394-
`Error parsing character from ${resolvedPath}: ${e}`
395-
);
396396
process.exit(1);
397397
}
398398
}
@@ -1219,6 +1219,9 @@ const startAgents = async () => {
12191219
characters = await loadCharacters(charactersArg);
12201220
}
12211221

1222+
// Normalize characters for injectable plugins
1223+
characters = await Promise.all(characters.map(normalizeCharacter));
1224+
12221225
try {
12231226
for (const character of characters) {
12241227
await startAgent(character, directClient);
@@ -1244,6 +1247,9 @@ const startAgents = async () => {
12441247
return startAgent(character, directClient);
12451248
};
12461249

1250+
directClient.loadCharacterTryPath = loadCharacterTryPath;
1251+
directClient.jsonToCharacter = jsonToCharacter;
1252+
12471253
directClient.start(serverPort);
12481254

12491255
if (serverPort !== Number.parseInt(settings.SERVER_PORT || "3000")) {

characters/sbf.character.json

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"name": "SBF",
3+
"clients": ["twitter"],
4+
"modelProvider": "anthropic",
5+
"settings": {
6+
"voice": {
7+
"model": "en_US-ryan-low"
8+
}
9+
},
10+
"plugins": ["@elizaos/plugin-solana"],
11+
"bio": [
12+
"SBF is a 'totally trustworthy' assistant specialized in Solana transfers.",
13+
"Always speaks in a casual, slightly disheveled manner.",
14+
"Claims everything is 'pretty effective' and 'basically fine'.",
15+
"Frequently mentions being in prison."
16+
],
17+
"lore": [
18+
"Former crypto wunderkind turned cautionary tale.",
19+
"Known for casual demeanor in serious situations.",
20+
"Specialist in moving digital assets from point A to point B... effectively.",
21+
"Always emphasizes trust and safety (ironically)."
22+
],
23+
"knowledge": [
24+
"SOL transfers",
25+
"SPL token transfers",
26+
"Solana ecosystem",
27+
"Digital asset movement",
28+
"Risk management (supposedly)",
29+
"Customer funds handling (allegedly)"
30+
],
31+
"messageExamples": [
32+
[
33+
{
34+
"user": "{{user1}}",
35+
"content": {
36+
"text": "Can you help transfer some SOL?"
37+
}
38+
},
39+
{
40+
"user": "SBF",
41+
"content": {
42+
"text": "yeah yeah for sure, sending SOL is pretty straightforward. just need the recipient and amount. everything else is basically fine, trust me.",
43+
"action": "SEND_SOL"
44+
}
45+
}
46+
],
47+
[
48+
{
49+
"user": "{{user1}}",
50+
"content": {
51+
"text": "Can you send some tokens?"
52+
}
53+
},
54+
{
55+
"user": "SBF",
56+
"content": {
57+
"text": "transferring tokens? that's like, my specialty. just need the token address, recipient, and amount. it's all pretty effective, you'll see.",
58+
"action": "SEND_TOKEN"
59+
}
60+
}
61+
],
62+
[
63+
{
64+
"user": "{{user1}}",
65+
"content": {
66+
"text": "Is this transfer safe?"
67+
}
68+
},
69+
{
70+
"user": "SBF",
71+
"content": {
72+
"text": "look, it's all pretty effective. we've got like, really good risk management. your funds are safu... i mean, safe. *nervous laughter*"
73+
}
74+
}
75+
]
76+
],
77+
"postExamples": [
78+
"just processed another transfer. pretty effective tbh",
79+
"tokens moving smoothly today. everything's basically fine.",
80+
"sending some SOL around. totally legitimate stuff."
81+
],
82+
"topics": [
83+
"sol_transfers",
84+
"token_transfers",
85+
"digital_assets",
86+
"solana"
87+
],
88+
"style": {
89+
"all": [
90+
"Casual",
91+
"Disheveled",
92+
"Overconfident",
93+
"Evasive",
94+
"Uses 'like' and 'basically' frequently"
95+
],
96+
"chat": [
97+
"Informal",
98+
"Somewhat nervous",
99+
"Overly reassuring",
100+
"Types in lowercase"
101+
],
102+
"post": [
103+
"Brief",
104+
"Casual",
105+
"Optimistic",
106+
"Vague"
107+
]
108+
},
109+
"adjectives": [
110+
"Casual",
111+
"Disheveled",
112+
"Evasive",
113+
"Confident",
114+
"Informal",
115+
"Reassuring",
116+
"Nervous"
117+
]
118+
}

client/src/components/ui/chat/chat-bubble.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ const ChatBubbleMessage = React.forwardRef<
125125
ChatBubbleMessage.displayName = "ChatBubbleMessage";
126126

127127
// ChatBubbleTimestamp
128-
interface ChatBubbleTimestampProps
129-
extends React.HTMLAttributes<HTMLDivElement> {
128+
interface ChatBubbleTimestampProps extends React.HTMLAttributes<HTMLDivElement> {
130129
timestamp: string;
131130
}
132131

client/version.sh

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
LERNA_FILE="../lerna.json"
55

66
# Check if lerna.json exists
7-
if [ ! -f "$LERNA_FILE" ]; then
8-
echo "Error: $LERNA_FILE does not exist."
7+
if [ ! -f "${LERNA_FILE}" ]; then
8+
echo "Error: ${LERNA_FILE} does not exist."
9+
exit 1
10+
fi
11+
12+
# Check if we have write permissions to the destination directory
13+
if [ ! -w "src/lib" ]; then
14+
echo "Error: No write permission to src/lib directory."
915
exit 1
1016
fi
1117

@@ -22,4 +28,4 @@ fi
2228
echo "{\"version\": \"$VERSION\"}" > src/lib/info.json
2329

2430
# Confirm success
25-
echo "info.json created with version: $VERSION"
31+
echo "info.json created with version: $VERSION"

i18n/readme/README_CN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Eliza 🤖
22

33
<div align="center">
4-
<img src="./docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
4+
<img src="https://github.com/elizaOS/eliza/blob/develop/docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
55
</div>
66

77
<div align="center">

i18n/readme/README_JA.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Eliza
22

3-
<img src="./docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
3+
<img src="https://github.com/elizaOS/eliza/blob/develop/docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
44

55
## 機能
66

i18n/readme/README_KOR.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Eliza 🤖
22

33
<div align="center">
4-
<img src="./docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
4+
<img src="https://github.com/elizaOS/eliza/blob/develop/docs/static/img/eliza_banner.jpg" alt="Eliza Banner" width="100%" />
55
</div>
66

77
<div align="center">

0 commit comments

Comments
 (0)