create-eliza
Version:
Initialize an Eliza project
373 lines (361 loc) • 12 kB
JavaScript
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import {
copyTemplate,
execa,
getAvailableDatabases,
installPlugin,
listPluginsByType,
rawConfigSchema,
runBunCommand
} from "./chunk-HKP2R5KY.js";
import {
handleError
} from "./chunk-3GOUAKN6.js";
import {
require_prompts
} from "./chunk-OGSHIQ3J.js";
import {
source_default
} from "./chunk-BY3DNMXE.js";
import {
logger,
z
} from "./chunk-RYUT2GQB.js";
import {
Command
} from "./chunk-CKY7YPIS.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!");
} 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);
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-RT3TTGZ2.js.map