UNPKG

create-eliza

Version:

Initialize an Eliza project

396 lines (391 loc) 12.7 kB
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