@nestbox-ai/cli
Version:
The cli tools that helps developers to build agents
159 lines (139 loc) • 5.89 kB
text/typescript
import { Command } from "commander";
import chalk from "chalk";
import ora from "ora";
import fs from "fs";
import {
createNestboxConfig,
} from "../../utils/agent";
import { generateWithPlop, listAvailableTemplates } from "../../utils/plopGenerator";
import { isValidFunctionName } from "../../utils/validation";
import inquirer from "inquirer";
import path from "path";
export function registerProjectCommand(generateCommand: Command): void {
generateCommand
.command("project <folder>")
.description("Generate a new project from templates")
.option("--lang <language>", "Project language (ts|js)")
.option("--template <type>", "Template type (agent|chatbot)")
.option("--name <agentName>", "Agent/Chatbot name (must be a valid function name)")
.option("--project <projectId>", "Project ID")
.action(async (folder, options) => {
try {
const spinner = ora("Initializing project generation...").start();
// Ensure target folder doesn't exist
if (fs.existsSync(folder)) {
spinner.fail(`Folder ${folder} already exists`);
return;
}
let selectedLang = options.lang;
let selectedTemplate = options.template;
let agentName = options.name;
// Interactive selection if not provided
if (!selectedLang || !selectedTemplate) {
spinner.stop();
const answers = await inquirer.prompt([
{
type: 'list',
name: 'lang',
message: 'Select project language:',
choices: [
{ name: 'TypeScript', value: 'ts' },
{ name: 'JavaScript', value: 'js' }
],
when: () => !selectedLang
},
{
type: 'list',
name: 'template',
message: 'Select template type:',
choices: [
{ name: 'Agent', value: 'agent' },
{ name: 'Chatbot', value: 'chatbot' }
],
when: () => !selectedTemplate
},
{
type: 'input',
name: 'agentName',
message: 'Enter agent/chatbot name (must be a valid function name):',
when: () => !agentName,
default: (answers: any) => {
const type = selectedTemplate || answers.template;
return type === 'agent' ? 'myAgent' : 'myChatbot';
},
validate: (input: string) => {
if (!input.trim()) {
return 'Agent name cannot be empty';
}
if (!isValidFunctionName(input.trim())) {
return 'Must be a valid function name (e.g., myAgent, chatBot123, my_agent)';
}
return true;
}
}
]);
selectedLang = selectedLang || answers.lang;
selectedTemplate = selectedTemplate || answers.template;
agentName = agentName || answers.agentName;
spinner.start("Generating project...");
}
// Validate agent name if provided via CLI option
if (agentName && !isValidFunctionName(agentName)) {
spinner.fail(`Invalid agent name: "${agentName}". Must be a valid function name (e.g., myAgent, chatBot123, my_agent)`);
return;
}
// Set default agent name if not provided
if (!agentName) {
agentName = selectedTemplate === 'agent' ? 'myAgent' : 'myChatbot';
}
// Find matching template in local templates folder
const templateMapping: Record<string, string> = {
'agent': 'base',
'chatbot': 'chatbot'
};
const mappedTemplateType = templateMapping[selectedTemplate] || selectedTemplate;
// Check if template directory exists
const templatePath = path.resolve(__dirname, `../../../../templates/${mappedTemplateType}-${selectedLang}`);
if (!fs.existsSync(templatePath)) {
spinner.fail(`Template not found: ${templatePath}`);
// Show available templates
const availableTemplates = listAvailableTemplates();
if (availableTemplates.length > 0) {
console.log(chalk.yellow('Available templates:'));
availableTemplates.forEach(template => {
console.log(chalk.yellow(` - ${template}`));
});
} else {
console.log(chalk.red('No templates found. Please add your templates to the templates directory.'));
}
return;
}
spinner.text = `Generating ${mappedTemplateType} project in ${folder}...`;
try {
// Generate project using plop
await generateWithPlop(selectedTemplate, selectedLang, folder, path.basename(folder), agentName);
// Create nestbox.config.json for TypeScript projects
createNestboxConfig(folder, selectedLang === 'ts');
spinner.succeed(`Successfully generated ${mappedTemplateType} project in ${folder}`);
console.log(chalk.green("\nNext steps:"));
console.log(chalk.yellow(` cd ${folder}`));
console.log(chalk.yellow(" npm install"));
if (selectedLang === 'ts') {
console.log(chalk.yellow(" npm run build"));
}
console.log(chalk.yellow(" nestbox agent deploy --agent <agent-name> --instance <instance-name>"));
} catch (error) {
// Clean up on error
if (fs.existsSync(folder)) {
fs.rmSync(folder, { recursive: true, force: true });
}
throw error;
}
} catch (error: any) {
console.error(
chalk.red("Error:"),
error.message || "Failed to generate project"
);
}
});
}