UNPKG

create-eliza

Version:

Initialize an Eliza project

384 lines (372 loc) 12.3 kB
import { createRequire } from 'module'; const require = createRequire(import.meta.url); import { copyTemplate, installPlugin, rawConfigSchema } from "./chunk-ZVIQTJYY.js"; import { getAvailableDatabases, listPluginsByType } from "./chunk-XYEF7RCR.js"; import { buildProject } from "./chunk-KMSIPPQV.js"; import { runBunCommand } from "./chunk-FPOBH723.js"; import { execa } from "./chunk-HKIJL32E.js"; import { source_default } from "./chunk-BY3DNMXE.js"; import { handleError } from "./chunk-252SDPU3.js"; import { logger, z } from "./chunk-2ORHBMCI.js"; import { require_prompts } from "./chunk-OGSHIQ3J.js"; import { Command } from "./chunk-S757QXWN.js"; import { __toESM } from "./chunk-WCMDOJQK.js"; // src/commands/init.ts import { existsSync, readFileSync } from "node:fs"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; // src/utils/templates.ts function createDatabaseTemplate(database) { if (database === "sqlite") { return `import { Database } from "better-sqlite3" import { SqliteDatabaseAdapter } from "@elizaos/plugin-sqlite" // Initialize database export const db = new Database("./eliza.db") export const adapter = new SqliteDatabaseAdapter(db) `; } return `import { ${database}Adapter } from "@elizaos/adapter-${database}" if (!process.env.DATABASE_URL) { throw new Error("DATABASE_URL not found in environment") } // Initialize adapter export const adapter = new ${database}Adapter(process.env.DATABASE_URL) `; } function createPluginsTemplate(plugins) { return `// Auto-generated - do not edit ${plugins.map((plugin) => `import { ${getPluginName(plugin)} } from "${plugin}"`).join("\n")} export const availablePlugins = { ${plugins.map((plugin) => ` "${plugin}": ${getPluginName(plugin)},`).join("\n")} } // Helper type export type PluginName = keyof typeof availablePlugins `; } function createEnvTemplate(database) { if (database === "sqlite") { return "# No configuration needed for SQLite"; } return `# Database Configuration DATABASE_URL=your_${database}_url_here # Add any other secrets needed by your plugins below `; } function getPluginName(plugin) { return plugin.split("/").pop()?.replace(/-/g, ""); } // src/commands/init.ts var import_prompts = __toESM(require_prompts(), 1); var initOptionsSchema = z.object({ dir: z.string().default("."), yes: z.boolean().default(false), type: z.enum(["project", "plugin"]).default("project") }); async function setupEnvironment(targetDir, database) { const envPath = path.join(targetDir, ".env"); const envExamplePath = path.join(targetDir, ".env.example"); await fs.writeFile(envExamplePath, createEnvTemplate(database)); if (!existsSync(envPath)) { await fs.copyFile(envExamplePath, envPath); logger.info("Created .env file"); } const homeEnvDir = path.join(os.homedir(), ".eliza"); const homeEnvPath = path.join(homeEnvDir, ".env"); if (!existsSync(homeEnvDir)) { await fs.mkdir(homeEnvDir, { recursive: true }); } if (!existsSync(homeEnvPath)) { await fs.writeFile(homeEnvPath, createEnvTemplate(database)); logger.info("Created global .env file in ~/.eliza"); } } async function selectPlugins() { const clients = await listPluginsByType("client"); const plugins = await listPluginsByType("plugin"); const result = await (0, import_prompts.default)([ { type: "multiselect", name: "clients", message: "Select client plugins to install", choices: clients.map((name) => ({ title: name, value: name })) }, { type: "multiselect", name: "plugins", message: "Select additional plugins", choices: plugins.map((name) => ({ title: name, value: name })) } ]); return [...result.clients, ...result.plugins]; } async function installDependencies(targetDir, database, selectedPlugins) { logger.info("Installing dependencies..."); try { await execa("npm", ["install", "-g", "bun"], { stdio: "inherit" }); } catch (_error) { logger.warn( "Failed to install bun globally. Continuing with installation..." ); } try { await runBunCommand(["install"], targetDir); logger.success("Installed base dependencies"); } catch (error) { logger.warn(`Initial dependency installation error: ${error.message}`); } logger.info("Installing @elizaos/core using latest version..."); try { await runBunCommand(["add", "@elizaos/core@latest"], targetDir); logger.success("Successfully installed @elizaos/core@latest"); } catch (error) { logger.error(`Failed to install @elizaos/core@latest: ${error.message}`); } logger.info(`Installing database adapter for ${database}...`); try { await runBunCommand( ["add", `@elizaos/adapter-${database}@latest`], targetDir ); logger.success( `Successfully installed @elizaos/adapter-${database}@latest` ); } catch (error) { logger.error( `Failed to install @elizaos/adapter-${database}: ${error.message}` ); } if (selectedPlugins.length > 0) { logger.info(`Installing selected plugins: ${selectedPlugins.join(", ")}`); for (const plugin of selectedPlugins) { try { await installPlugin(plugin, targetDir); } catch (pluginError) { logger.error( `Failed to install plugin ${plugin}: ${pluginError.message}` ); } } } } var init = new Command().name("init").description("Initialize a new project or plugin").option("-d, --dir <dir>", "installation directory", ".").option("-y, --yes", "skip confirmation", false).option( "-t, --type <type>", "type of template to use (project or plugin)", "project" ).action(async (opts) => { try { const options = initOptionsSchema.parse(opts); const envPath = path.join(process.cwd(), ".env"); let currentPath = envPath; let depth = 0; const maxDepth = 10; let postgresUrl = null; while (depth < maxDepth && currentPath.includes(path.sep)) { if (existsSync(currentPath)) { const env = readFileSync(currentPath, "utf8"); const envVars = env.split("\n").filter((line) => line.trim() !== ""); const postgresUrlLine = envVars.find( (line) => line.startsWith("POSTGRES_URL=") ); if (postgresUrlLine) { postgresUrl = postgresUrlLine.split("=")[1].trim(); break; } } const currentDir = path.dirname(currentPath); const parentDir = path.dirname(currentDir); currentPath = path.join(parentDir, ".env"); depth++; } const { name } = await (0, import_prompts.default)({ type: "text", name: "name", message: `What would you like to name your ${options.type}?`, validate: (value) => value.length > 0 || `${options.type} name is required` }); if (!name) { process.exit(0); } const targetDir = options.dir === "." ? path.resolve(name) : path.resolve(options.dir); if (!existsSync(targetDir)) { await fs.mkdir(targetDir, { recursive: true }); } else { const files = await fs.readdir(targetDir); const isEmpty = files.length === 0 || files.every((f) => f.startsWith(".")); if (!isEmpty && !options.yes) { const { proceed } = await (0, import_prompts.default)({ type: "confirm", name: "proceed", message: "Directory is not empty. Continue anyway?", initial: false }); if (!proceed) { process.exit(0); } } } if (options.type === "plugin") { await copyTemplate("plugin", targetDir, name); logger.info("Installing dependencies..."); try { await runBunCommand(["install"], targetDir); logger.success("Dependencies installed successfully!"); await buildProject(targetDir, true); } catch (_error) { logger.warn( "Failed to install dependencies automatically. Please run 'bun install' manually." ); } logger.success("Plugin initialized successfully!"); logger.info(` Next steps: 1. ${source_default.cyan(`run \`cd ${name}\``)} to navigate to your plugin directory 2. Update the plugin code in ${source_default.cyan("src/index.ts")} 3. Run ${source_default.cyan("bun dev")} to start development 4. Run ${source_default.cyan("bun build")} to build your plugin`); return; } const availableDatabases = await getAvailableDatabases(); const { database } = await (0, import_prompts.default)({ type: "select", name: "database", message: "Select your database:", choices: availableDatabases.sort((a, b) => a.localeCompare(b)).map((db) => ({ title: db, value: db })), initial: availableDatabases.indexOf("pglite") }); if (!database) { logger.error("No database selected"); process.exit(1); } const selectedPlugins = await selectPlugins(); await copyTemplate("project", targetDir, name); let dbPath = "../../pglite"; try { const homeDir = os.homedir(); const elizaDir = path.join(homeDir, ".eliza"); const elizaDbDir = path.join(elizaDir, "db"); if (!existsSync(elizaDir)) { logger.info(`Creating .eliza directory at: ${elizaDir}`); await fs.mkdir(elizaDir, { recursive: true }); } if (!existsSync(elizaDbDir)) { logger.info(`Creating db directory at: ${elizaDbDir}`); await fs.mkdir(elizaDbDir, { recursive: true }); } dbPath = elizaDbDir; logger.debug(`Using database directory: ${dbPath}`); } catch (error) { logger.warn( "Failed to create database directory in home directory, using fallback location:", error ); } console.log(dbPath); console.log(postgresUrl); if (database === "postgres" && !postgresUrl) { const reply = await (0, import_prompts.default)({ type: "text", name: "postgresUrl", message: "Enter your postgres url" }); postgresUrl = reply.postgresUrl; } const config = rawConfigSchema.parse({ $schema: "https://elizaos.com/schema.json", database: { type: database, config: database === "postgres" ? { url: postgresUrl || null } : { dataDir: dbPath } }, plugins: { registry: "https://raw.githubusercontent.com/elizaos-plugins/registry/refs/heads/main/index.json", installed: [`@elizaos/plugin-${database}`, ...selectedPlugins] }, paths: { knowledge: "./knowledge" } }); await fs.writeFile( path.join(targetDir, "project.json"), JSON.stringify(config, null, 2) ); const srcDir = path.join(targetDir, "src"); if (!existsSync(srcDir)) { await fs.mkdir(srcDir); } await fs.writeFile( path.join(srcDir, "database.ts"), createDatabaseTemplate(database) ); await fs.writeFile( path.join(srcDir, "plugins.ts"), createPluginsTemplate(selectedPlugins) ); await setupEnvironment(targetDir, database); await fs.mkdir(path.join(targetDir, "knowledge"), { recursive: true }); await installDependencies(targetDir, database, selectedPlugins); await buildProject(targetDir); logger.success("Project initialized successfully!"); if (database !== "postgres") { logger.info(` Next steps: 1. ${source_default.cyan(`cd ${name}`)} to navigate to your project directory 2. Update ${source_default.cyan(".env")} with your database credentials 3. Run ${source_default.cyan("eliza plugins add")} to install additional plugins 4. Run ${source_default.cyan("eliza agent import")} to import an agent`); } else { logger.info(` Next steps: 1. ${source_default.cyan(`cd ${name}`)} to navigate to your project directory 2. Run ${source_default.cyan("eliza plugins add")} to install additional plugins 3. Run ${source_default.cyan("eliza agent import")} to import an agent`); } process.exit(0); } catch (error) { handleError(error); } }); export { init }; //# sourceMappingURL=chunk-O36H6QO7.js.map