create-eliza
Version:
Initialize an Eliza project
396 lines (391 loc) • 12.7 kB
JavaScript
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import {
AgentServer,
jsonToCharacter,
loadCharacterTryPath,
promptForEnvVars
} from "./chunk-MSPVXHYX.js";
import {
require_main
} from "./chunk-ZMJ3QLUC.js";
import {
AgentRuntime,
logger,
settings,
stringToUuid
} from "./chunk-XYV3IRYW.js";
import {
Command
} from "./chunk-CKY7YPIS.js";
import {
__toESM
} from "./chunk-WCMDOJQK.js";
// src/testRunner.ts
var TestRunner = class {
runtime;
projectAgent;
stats;
constructor(runtime, projectAgent) {
this.runtime = runtime;
this.projectAgent = projectAgent;
this.stats = {
total: 0,
passed: 0,
failed: 0,
skipped: 0
};
}
/**
* Runs a test suite
* @param suite The test suite to run
*/
async runTestSuite(suite) {
logger.info(`
Running test suite: ${suite.name}`);
for (const test2 of suite.tests) {
this.stats.total++;
try {
logger.info(` Running test: ${test2.name}`);
await test2.fn(this.runtime);
this.stats.passed++;
logger.success(` \u2713 ${test2.name}`);
} catch (error) {
this.stats.failed++;
logger.error(` \u2717 ${test2.name}`);
logger.error(` ${error.message}`);
}
}
}
/**
* Runs project agent tests
*/
async runProjectTests(options) {
if (!this.projectAgent?.tests || options.skipProjectTests) {
return;
}
logger.info("\nRunning project tests...");
const testSuites = Array.isArray(this.projectAgent.tests) ? this.projectAgent.tests : [this.projectAgent.tests];
for (const suite of testSuites) {
if (!suite) {
continue;
}
if (options.filter && !suite.name.includes(options.filter)) {
this.stats.skipped++;
continue;
}
await this.runTestSuite(suite);
}
}
/**
* Runs plugin tests
*/
async runPluginTests(options) {
if (options.skipPlugins) {
return;
}
logger.info("\nRunning plugin tests...");
const plugins = this.runtime.plugins || [];
for (const plugin of plugins) {
try {
const pluginTests = plugin.tests;
if (!pluginTests) {
continue;
}
const testSuites = Array.isArray(pluginTests) ? pluginTests : [pluginTests];
for (const suite of testSuites) {
if (!suite) {
continue;
}
if (options.filter && !suite.name.includes(options.filter)) {
this.stats.skipped++;
continue;
}
await this.runTestSuite(suite);
}
} catch (error) {
logger.error(`Error running tests for plugin ${plugin.name}:`, error);
this.stats.failed++;
}
}
}
/**
* Runs all tests in the project
* @param options Test options
*/
async runTests(options = {}) {
await this.runProjectTests(options);
await this.runPluginTests(options);
return this.stats;
}
};
// src/commands/test.ts
var dotenv = __toESM(require_main(), 1);
import * as net from "node:net";
import path from "node:path";
import * as os from "node:os";
import * as fs from "node:fs";
async function checkPortAvailable(port) {
return new Promise((resolve) => {
const server = net.createServer();
server.once("error", () => {
resolve(false);
});
server.once("listening", () => {
server.close();
resolve(true);
});
server.listen(port);
});
}
async function startAgent(character, server, init, plugins = []) {
character.id ??= stringToUuid(character.name);
const runtime = new AgentRuntime({
character,
plugins
});
if (init) {
await init(runtime);
}
await runtime.initialize();
server.registerAgent(runtime);
logger.debug(`Started ${runtime.character.name} as ${runtime.agentId}`);
return runtime;
}
var runAgentTests = async (options) => {
try {
const runtimes = [];
const projectAgents = [];
const homeDir = os.homedir();
const elizaDir = path.join(homeDir, ".eliza");
const elizaDbDir = path.join(elizaDir, "db");
const envFilePath = path.join(elizaDir, ".env");
logger.info("Setting up environment...");
logger.info(`Home directory: ${homeDir}`);
logger.info(`Eliza directory: ${elizaDir}`);
logger.info(`Database directory: ${elizaDbDir}`);
logger.info(`Environment file: ${envFilePath}`);
if (!fs.existsSync(elizaDir)) {
logger.info(`Creating directory: ${elizaDir}`);
fs.mkdirSync(elizaDir, { recursive: true });
logger.info(`Created directory: ${elizaDir}`);
}
if (!fs.existsSync(elizaDbDir)) {
logger.info(`Creating database directory: ${elizaDbDir}`);
fs.mkdirSync(elizaDbDir, { recursive: true });
logger.info(`Created database directory: ${elizaDbDir}`);
}
process.env.PGLITE_DATA_DIR = elizaDbDir;
logger.info(`Using database directory: ${elizaDbDir}`);
if (fs.existsSync(envFilePath)) {
logger.info(`Loading environment variables from: ${envFilePath}`);
dotenv.config({ path: envFilePath });
logger.info("Environment variables loaded");
} else {
logger.warn(`Environment file not found: ${envFilePath}`);
}
try {
logger.info("Configuring database...");
await promptForEnvVars("pglite");
logger.info("Database configuration completed");
} catch (error) {
logger.error("Error configuring database:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
throw error;
}
const postgresUrl = process.env.POSTGRES_URL;
logger.info(`PostgreSQL URL: ${postgresUrl ? "found" : "not found"}`);
logger.info("Creating server instance...");
const server = new AgentServer({
dataDir: elizaDbDir,
postgresUrl
});
logger.info("Server instance created");
logger.info("Waiting for database initialization...");
try {
await new Promise((resolve, reject) => {
const checkInterval = setInterval(async () => {
try {
if (server.database?.isInitialized) {
clearInterval(checkInterval);
resolve();
} else {
await server.database?.init();
}
} catch (error) {
logger.error("Error during database initialization check:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
clearInterval(checkInterval);
reject(error);
}
}, 1e3);
setTimeout(() => {
clearInterval(checkInterval);
reject(new Error("Database initialization timed out after 30 seconds"));
}, 3e4);
});
logger.info("Database initialized successfully");
} catch (error) {
logger.error("Failed to initialize database:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
throw error;
}
logger.info("Setting up server properties...");
server.startAgent = async (character) => {
logger.info(`Starting agent for character ${character.name}`);
return startAgent(character, server);
};
server.loadCharacterTryPath = loadCharacterTryPath;
server.jsonToCharacter = jsonToCharacter;
logger.info("Server properties set up");
let serverPort = options.port || Number.parseInt(settings.SERVER_PORT || "3000");
logger.info("Loading project from current directory:", process.cwd());
let project;
try {
project = await (void 0)(process.cwd());
logger.info("Project loaded successfully:", JSON.stringify(project, null, 2));
if (!project || !project.agents || project.agents.length === 0) {
throw new Error("No agents found in project configuration");
}
logger.info(`Found ${project.agents.length} agents in project configuration`);
} catch (error) {
logger.error("Error loading project:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
throw error;
}
logger.info("Checking port availability...");
while (!await checkPortAvailable(serverPort)) {
logger.warn(`Port ${serverPort} is in use, trying ${serverPort + 1}`);
serverPort++;
}
logger.info(`Using port ${serverPort}`);
logger.info("Starting server...");
try {
await server.start(serverPort);
logger.info("Server started successfully");
} catch (error) {
logger.error("Error starting server:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
throw error;
}
try {
logger.info(`Found ${project.agents.length} agents in project`);
for (const agent of project.agents) {
try {
logger.info(`Starting agent: ${agent.character.name}`);
const runtime = await startAgent(
agent.character,
server,
agent.init,
agent.plugins || []
);
runtimes.push(runtime);
projectAgents.push(agent);
await new Promise((resolve) => setTimeout(resolve, 1e3));
} catch (agentError) {
logger.error(
`Error starting agent ${agent.character.name}:`,
agentError
);
if (agentError instanceof Error) {
logger.error("Error details:", agentError.message);
logger.error("Stack trace:", agentError.stack);
}
throw agentError;
}
}
if (runtimes.length === 0) {
throw new Error("Failed to start any agents from project");
}
logger.info(`Successfully started ${runtimes.length} agents from project`);
let totalFailed = 0;
for (let i = 0; i < runtimes.length; i++) {
const runtime = runtimes[i];
const projectAgent = projectAgents[i];
logger.info(`Running tests for agent: ${runtime.character.name}`);
const testRunner = new TestRunner(runtime, projectAgent);
const results = await testRunner.runTests({
filter: options.plugin,
skipPlugins: options.skipPlugins,
skipProjectTests: options.skipProjectTests
});
totalFailed += results.failed;
}
await server.stop();
process.exit(totalFailed > 0 ? 1 : 0);
} catch (error) {
logger.error("Error running tests:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
}
await server.stop();
throw error;
}
} catch (error) {
logger.error("Error in runAgentTests:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
} else {
logger.error("Unknown error type:", typeof error);
logger.error("Error value:", error);
try {
logger.error("Stringified error:", JSON.stringify(error, null, 2));
} catch (e) {
logger.error("Could not stringify error:", e);
}
}
throw error;
}
};
var test = new Command().name("test").description("Run tests for Eliza agent plugins").option(
"-p, --port <port>",
"Port to listen on",
(val) => Number.parseInt(val)
).option("-P, --plugin <name>", "Name of plugin to test").option("--skip-plugins", "Skip plugin tests").option("--skip-project-tests", "Skip project tests").action(async (options) => {
logger.info("Starting test command...");
logger.info("Command options:", options);
try {
logger.info("Running agent tests...");
await runAgentTests(options);
} catch (error) {
logger.error("Error running tests:", error);
if (error instanceof Error) {
logger.error("Error details:", error.message);
logger.error("Stack trace:", error.stack);
} else {
logger.error("Unknown error type:", typeof error);
logger.error("Error value:", error);
try {
logger.error("Stringified error:", JSON.stringify(error, null, 2));
} catch (e) {
logger.error("Could not stringify error:", e);
}
}
process.exit(1);
}
});
function registerCommand(cli) {
return cli.addCommand(test);
}
export {
test,
registerCommand
};
//# sourceMappingURL=chunk-XDZFLA4K.js.map