Skip to content

Commit bea5567

Browse files
authored
Merge pull request #365 from normand1/dn/token-provider-tests
feat: [Issue-185] Token Provider Tests
2 parents 95c3055 + 329db11 commit bea5567

20 files changed

+380
-86
lines changed

.nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v23.1.0

package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"docker:run": "bash ./scripts/docker.sh run",
1919
"docker:bash": "bash ./scripts/docker.sh bash",
2020
"docker:start": "bash ./scripts/docker.sh start",
21-
"docker": "pnpm docker:build && pnpm docker:run && pnpm docker:bash"
21+
"docker": "pnpm docker:build && pnpm docker:run && pnpm docker:bash",
22+
"test": "pnpm --dir packages/core test"
2223
},
2324
"devDependencies": {
2425
"concurrently": "^9.1.0",
@@ -27,7 +28,9 @@
2728
"only-allow": "^1.2.1",
2829
"prettier": "^3.3.3",
2930
"typedoc": "^0.26.11",
30-
"typescript": "5.6.3"
31+
"typescript": "5.6.3",
32+
"vite": "^5.4.11",
33+
"vitest": "^2.1.5"
3134
},
3235
"pnpm": {
3336
"overrides": {

packages/core/.env.test

+4
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
TEST_DATABASE_CLIENT=sqlite
22
NODE_ENV=test
3+
MAIN_WALLET_ADDRESS=TEST_MAIN_WALLET_ADDRESS_VALUE
4+
OPENAI_API_KEY=TEST_OPENAI_API_KEY_VALUE
5+
RPC_URL=https://api.mainnet-beta.solana.com
6+
WALLET_PUBLIC_KEY=2weMjPLLybRMMva1fM3U31goWWrCpF59CHWNhnCJ9Vyh

packages/core/.gitignore

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

packages/core/jest.config.js

-25
This file was deleted.

packages/core/package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"watch": "tsc --watch",
1212
"dev": "tsup --format esm --dts --watch",
1313
"build:docs": "cd docs && pnpm run build",
14-
"test": "jest --runInBand",
15-
"test:watch": "jest --runInBand --watch"
14+
"test": "vitest run",
15+
"test:watch": "vitest"
1616
},
1717
"author": "",
1818
"license": "MIT",
@@ -48,7 +48,8 @@
4848
"ts-node": "10.9.2",
4949
"tslib": "2.8.0",
5050
"tsup": "^8.3.5",
51-
"typescript": "5.6.3"
51+
"typescript": "5.6.3",
52+
"@solana/web3.js": "1.95.4"
5253
},
5354
"dependencies": {
5455
"@ai-sdk/anthropic": "^0.0.53",

packages/core/src/runtime.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
type Memory,
4343
} from "./types.ts";
4444
import { stringToUuid } from "./uuid.ts";
45+
import { v4 as uuidv4 } from 'uuid';
4546

4647
/**
4748
* Represents the runtime environment for an agent, handling message processing,
@@ -227,9 +228,9 @@ export class AgentRuntime implements IAgentRuntime {
227228
this.databaseAdapter = opts.databaseAdapter;
228229
// use the character id if it exists, otherwise use the agentId if it is passed in, otherwise use the character name
229230
this.agentId =
230-
opts.character.id ??
231-
opts.agentId ??
232-
stringToUuid(opts.character.name);
231+
opts.character?.id ??
232+
opts?.agentId ??
233+
stringToUuid(opts.character?.name ?? uuidv4());
233234

234235
elizaLogger.success("Agent ID", this.agentId);
235236

@@ -283,7 +284,7 @@ export class AgentRuntime implements IAgentRuntime {
283284

284285
this.token = opts.token;
285286

286-
[...(opts.character.plugins || []), ...(opts.plugins || [])].forEach(
287+
[...(opts.character?.plugins || []), ...(opts.plugins || [])].forEach(
287288
(plugin) => {
288289
plugin.actions?.forEach((action) => {
289290
this.registerAction(action);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { type UUID } from "@ai16z/eliza/src/types.ts";
2+
3+
export const SERVER_URL = "http://localhost:7998";
4+
export const SUPABASE_URL = "https://pronvzrzfwsptkojvudd.supabase.co";
5+
export const SUPABASE_ANON_KEY =
6+
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InByb252enJ6ZndzcHRrb2p2dWRkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDY4NTYwNDcsImV4cCI6MjAyMjQzMjA0N30.I6_-XrqssUb2SWYg5DjsUqSodNS3_RPoET3-aPdqywM";
7+
export const TEST_EMAIL = "testuser123@gmail.com";
8+
export const TEST_PASSWORD = "testuser123@gmail.com";
9+
export const TEST_EMAIL_2 = "testuser234@gmail.com";
10+
export const TEST_PASSWORD_2 = "testuser234@gmail.com";
11+
12+
export const zeroUuid = "00000000-0000-0000-0000-000000000000" as UUID;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { SqliteDatabaseAdapter, loadVecExtensions } from "@ai16z/adapter-sqlite";
2+
import { SqlJsDatabaseAdapter } from "@ai16z/adapter-sqljs";
3+
import { SupabaseDatabaseAdapter } from "@ai16z/adapter-supabase";
4+
import { DatabaseAdapter } from "../database.ts";
5+
import { AgentRuntime } from "../runtime.ts";
6+
import {
7+
Action,
8+
Evaluator,
9+
ModelProviderName,
10+
Provider,
11+
} from "../types.ts";
12+
import {
13+
SUPABASE_ANON_KEY,
14+
SUPABASE_URL,
15+
TEST_EMAIL,
16+
TEST_PASSWORD,
17+
zeroUuid,
18+
} from "./constants.ts";
19+
import { User } from "./types.ts";
20+
import { getEndpoint } from "../models.ts";
21+
22+
export async function createRuntime({
23+
env,
24+
conversationLength,
25+
evaluators = [],
26+
actions = [],
27+
providers = [],
28+
}: {
29+
env?: Record<string, string> | NodeJS.ProcessEnv;
30+
conversationLength?: number;
31+
evaluators?: Evaluator[];
32+
actions?: Action[];
33+
providers?: Provider[];
34+
}) {
35+
let adapter: DatabaseAdapter;
36+
let user: User;
37+
let session: {
38+
user: User;
39+
};
40+
41+
switch (env?.TEST_DATABASE_CLIENT as string) {
42+
case "sqljs":
43+
{
44+
const module = await import("sql.js");
45+
46+
const initSqlJs = module.default;
47+
48+
// SQLite adapter
49+
const SQL = await initSqlJs({});
50+
const db = new SQL.Database();
51+
52+
adapter = new SqlJsDatabaseAdapter(db);
53+
54+
// Load sqlite-vss
55+
loadVecExtensions((adapter as SqlJsDatabaseAdapter).db);
56+
// Create a test user and session
57+
session = {
58+
user: {
59+
id: zeroUuid,
60+
email: "test@example.com",
61+
},
62+
};
63+
}
64+
break;
65+
case "supabase": {
66+
const module = await import("@supabase/supabase-js");
67+
68+
const { createClient } = module;
69+
70+
const supabase = createClient(
71+
env?.SUPABASE_URL ?? SUPABASE_URL,
72+
env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY
73+
);
74+
75+
const { data } = await supabase.auth.signInWithPassword({
76+
email: TEST_EMAIL!,
77+
password: TEST_PASSWORD!,
78+
});
79+
80+
user = data.user as User;
81+
session = data.session as unknown as { user: User };
82+
83+
if (!session) {
84+
const response = await supabase.auth.signUp({
85+
email: TEST_EMAIL!,
86+
password: TEST_PASSWORD!,
87+
});
88+
89+
// Change the name of the user
90+
const { error } = await supabase
91+
.from("accounts")
92+
.update({ name: "Test User" })
93+
.eq("id", response.data.user?.id);
94+
95+
if (error) {
96+
throw new Error(
97+
"Create runtime error: " + JSON.stringify(error)
98+
);
99+
}
100+
101+
user = response.data.user as User;
102+
session = response.data.session as unknown as { user: User };
103+
}
104+
105+
adapter = new SupabaseDatabaseAdapter(
106+
env?.SUPABASE_URL ?? SUPABASE_URL,
107+
env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY
108+
);
109+
}
110+
case "sqlite":
111+
default:
112+
{
113+
const module = await import("better-sqlite3");
114+
115+
const Database = module.default;
116+
117+
// SQLite adapter
118+
adapter = new SqliteDatabaseAdapter(new Database(":memory:"));
119+
120+
// Load sqlite-vss
121+
await loadVecExtensions((adapter as SqliteDatabaseAdapter).db);
122+
// Create a test user and session
123+
session = {
124+
user: {
125+
id: zeroUuid,
126+
email: "test@example.com",
127+
},
128+
};
129+
}
130+
break;
131+
}
132+
133+
const runtime = new AgentRuntime({
134+
serverUrl: getEndpoint(ModelProviderName.OPENAI),
135+
conversationLength,
136+
token: env!.OPENAI_API_KEY!,
137+
modelProvider: ModelProviderName.OPENAI,
138+
actions: actions ?? [],
139+
evaluators: evaluators ?? [],
140+
providers: providers ?? [],
141+
databaseAdapter: adapter,
142+
});
143+
144+
return { user, session, runtime };
145+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import dotenv from "dotenv";
2+
import path from "path";
3+
4+
// Load test environment variables
5+
const envPath = path.resolve(__dirname, "../../.env.test");
6+
console.log('Current directory:', __dirname);
7+
console.log('Trying to load env from:', envPath);
8+
const result = dotenv.config({ path: envPath });
9+
if (result.error) {
10+
console.error('Error loading .env.test:', result.error);
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface User {
2+
id: string;
3+
email?: string;
4+
phone?: string;
5+
role?: string;
6+
}

packages/core/src/tests/env.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { describe, it, expect } from 'vitest';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
describe('Environment Setup', () => {
6+
it('should verify .env.test file exists', () => {
7+
const possiblePaths = [
8+
path.join(process.cwd(), '.env.test'),
9+
path.join(process.cwd(), 'packages/core/.env.test'),
10+
path.join(__dirname, '../../.env.test'),
11+
path.join(__dirname, '../.env.test'),
12+
path.join(__dirname, '.env.test'),
13+
];
14+
15+
console.log('Current working directory:', process.cwd());
16+
console.log('__dirname:', __dirname);
17+
18+
const existingPaths = possiblePaths.filter(p => {
19+
const exists = fs.existsSync(p);
20+
console.log(`Path ${p} exists: ${exists}`);
21+
return exists;
22+
});
23+
24+
expect(existingPaths.length).toBeGreaterThan(0);
25+
});
26+
});

packages/core/src/tests/goals.test.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ import {
1919
State,
2020
} from "../types";
2121

22+
import { describe, test, expect, beforeEach, vi } from 'vitest';
23+
2224
// Mock the database adapter
2325
export const mockDatabaseAdapter = {
24-
getGoals: jest.fn(),
25-
updateGoal: jest.fn(),
26-
createGoal: jest.fn(),
26+
getGoals: vi.fn(),
27+
updateGoal: vi.fn(),
28+
createGoal: vi.fn(),
2729
};
2830
const services = new Map<ServiceType, Service>();
2931
// Mock the runtime
@@ -178,7 +180,7 @@ const sampleGoal: Goal = {
178180

179181
describe("getGoals", () => {
180182
it("retrieves goals successfully", async () => {
181-
(mockDatabaseAdapter.getGoals as jest.Mock).mockResolvedValue([
183+
(mockDatabaseAdapter.getGoals).mockResolvedValue([
182184
sampleGoal,
183185
]);
184186

@@ -197,7 +199,7 @@ describe("getGoals", () => {
197199
});
198200

199201
it("handles failure to retrieve goals", async () => {
200-
(mockDatabaseAdapter.getGoals as jest.Mock).mockRejectedValue(
202+
(mockDatabaseAdapter.getGoals).mockRejectedValue(
201203
new Error("Failed to retrieve goals")
202204
);
203205

@@ -223,7 +225,7 @@ describe("formatGoalsAsString", () => {
223225

224226
describe("updateGoal", () => {
225227
it("updates a goal successfully", async () => {
226-
(mockDatabaseAdapter.updateGoal as jest.Mock).mockResolvedValue(
228+
(mockDatabaseAdapter.updateGoal).mockResolvedValue(
227229
undefined
228230
);
229231

@@ -234,7 +236,7 @@ describe("updateGoal", () => {
234236
});
235237

236238
it("handles failure to update a goal", async () => {
237-
(mockDatabaseAdapter.updateGoal as jest.Mock).mockRejectedValue(
239+
(mockDatabaseAdapter.updateGoal).mockRejectedValue(
238240
new Error("Failed to update goal")
239241
);
240242

@@ -246,7 +248,7 @@ describe("updateGoal", () => {
246248

247249
describe("createGoal", () => {
248250
it("creates a goal successfully", async () => {
249-
(mockDatabaseAdapter.createGoal as jest.Mock).mockResolvedValue(
251+
(mockDatabaseAdapter.createGoal).mockResolvedValue(
250252
undefined
251253
);
252254

@@ -257,7 +259,7 @@ describe("createGoal", () => {
257259
});
258260

259261
it("handles failure to create a goal", async () => {
260-
(mockDatabaseAdapter.createGoal as jest.Mock).mockRejectedValue(
262+
(mockDatabaseAdapter.createGoal).mockRejectedValue(
261263
new Error("Failed to create goal")
262264
);
263265

0 commit comments

Comments
 (0)