@nestbox-ai/cli 1.0.38 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.github/workflows/test.yml +54 -0
  2. package/dist/commands/agent/apiUtils.d.ts +20 -0
  3. package/dist/commands/agent/apiUtils.js +75 -2
  4. package/dist/commands/agent/apiUtils.js.map +1 -1
  5. package/dist/commands/agent/create.d.ts +2 -29
  6. package/dist/commands/agent/create.js +123 -61
  7. package/dist/commands/agent/create.js.map +1 -1
  8. package/dist/commands/agent/deploy.js +183 -137
  9. package/dist/commands/agent/deploy.js.map +1 -1
  10. package/dist/commands/agent/index.d.ts +1 -2
  11. package/dist/commands/agent/index.js +3 -6
  12. package/dist/commands/agent/index.js.map +1 -1
  13. package/dist/commands/agent/yaml-schema.d.ts +72 -0
  14. package/dist/commands/agent/yaml-schema.js +61 -0
  15. package/dist/commands/agent/yaml-schema.js.map +1 -0
  16. package/dist/commands/agent.js +2 -2
  17. package/dist/commands/agent.js.map +1 -1
  18. package/dist/commands/generate/project.js +32 -28
  19. package/dist/commands/generate/project.js.map +1 -1
  20. package/dist/utils/agent.js +18 -20
  21. package/dist/utils/agent.js.map +1 -1
  22. package/package.json +3 -2
  23. package/src/commands/agent/apiUtils.ts +103 -14
  24. package/src/commands/agent/create.ts +266 -100
  25. package/src/commands/agent/deploy.ts +515 -264
  26. package/src/commands/agent/index.ts +1 -4
  27. package/src/commands/agent/yaml-schema.ts +57 -0
  28. package/src/commands/agent.ts +10 -10
  29. package/src/commands/generate/project.ts +179 -147
  30. package/src/utils/agent.ts +141 -125
  31. package/test/agent.test.ts +153 -124
  32. package/dist/commands/agent/createFromYaml.d.ts +0 -2
  33. package/dist/commands/agent/createFromYaml.js +0 -172
  34. package/dist/commands/agent/createFromYaml.js.map +0 -1
  35. package/src/commands/agent/createFromYaml.ts +0 -192
@@ -1,11 +1,8 @@
1
- // Main agent command exports
2
- export { createAgent, type CreateAgentOptions } from "./create";
3
-
4
1
  // Individual command exports for direct usage if needed
5
2
  export { registerListCommand } from "./list";
6
3
  export { registerRemoveCommand } from "./remove";
7
4
  export { registerDeployCommand } from "./deploy";
8
- export { registerCreateFromYamlCommand } from "./createFromYaml";
5
+ export { registerCreateCommand } from "./create";
9
6
 
10
7
  // API utilities
11
8
  export { createApis, type ApiInstances } from "./apiUtils";
@@ -0,0 +1,57 @@
1
+ export const yamlSchema = {
2
+ type: "object",
3
+ properties: {
4
+ agents: {
5
+ type: "array",
6
+ items: {
7
+ type: "object",
8
+ properties: {
9
+ name: { type: "string", minLength: 1 },
10
+ description: { type: "string", minLength: 1 },
11
+ entry: { type: "string", minLength: 1 },
12
+ type: {
13
+ type: "string",
14
+ enum: ["REGULAR", "CHATBOT", "WORKFLOW"],
15
+ },
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ type: { type: "string", const: "object" },
20
+ properties: {
21
+ type: "object",
22
+ additionalProperties: {
23
+ type: "object",
24
+ properties: {
25
+ type: { type: "string", minLength: 1 },
26
+ description: { type: "string" },
27
+ default: {
28
+ type: [
29
+ "string",
30
+ "number",
31
+ "boolean",
32
+ "null",
33
+ ],
34
+ },
35
+ },
36
+ required: ["type"],
37
+ additionalProperties: true,
38
+ },
39
+ },
40
+ required: {
41
+ type: "array",
42
+ items: { type: "string", minLength: 1 },
43
+ uniqueItems: true,
44
+ },
45
+ },
46
+ required: ["type", "properties"],
47
+ additionalProperties: true,
48
+ },
49
+ },
50
+ required: ["name", "description", "entry", "inputSchema"],
51
+ additionalProperties: true,
52
+ },
53
+ },
54
+ },
55
+ required: ["agents"],
56
+ additionalProperties: true,
57
+ } as const;
@@ -2,20 +2,20 @@ import { Command } from "commander";
2
2
  import { registerListCommand } from "./agent/list";
3
3
  import { registerRemoveCommand } from "./agent/remove";
4
4
  import { registerDeployCommand } from "./agent/deploy";
5
- import { registerCreateFromYamlCommand } from "./agent/createFromYaml";
5
+ import { registerCreateCommand } from "./agent/create";
6
6
 
7
7
  /**
8
8
  * Register all agent-related commands
9
9
  */
10
10
  export function registerAgentCommands(program: Command): void {
11
- // Create the main agent command
12
- const agentCommand = program
13
- .command("agent")
14
- .description("Manage Nestbox agents");
11
+ // Create the main agent command
12
+ const agentCommand = program
13
+ .command("agent")
14
+ .description("Manage Nestbox agents");
15
15
 
16
- // Register all subcommands
17
- registerListCommand(agentCommand);
18
- registerRemoveCommand(agentCommand);
19
- registerDeployCommand(agentCommand);
20
- registerCreateFromYamlCommand(agentCommand);
16
+ // Register all subcommands
17
+ registerListCommand(agentCommand);
18
+ registerRemoveCommand(agentCommand);
19
+ registerDeployCommand(agentCommand);
20
+ registerCreateCommand(agentCommand);
21
21
  }
@@ -2,157 +2,189 @@ import { Command } from "commander";
2
2
  import chalk from "chalk";
3
3
  import ora from "ora";
4
4
  import fs from "fs";
5
+ import { createNestboxConfig } from "../../utils/agent";
5
6
  import {
6
- createNestboxConfig,
7
- } from "../../utils/agent";
8
- import { generateWithPlop, listAvailableTemplates } from "../../utils/plopGenerator";
7
+ generateWithPlop,
8
+ listAvailableTemplates,
9
+ } from "../../utils/plopGenerator";
9
10
  import { isValidFunctionName } from "../../utils/validation";
10
11
  import inquirer from "inquirer";
11
12
  import path from "path";
12
13
 
13
14
  export function registerProjectCommand(generateCommand: Command): void {
14
- generateCommand
15
- .command("project <folder>")
16
- .description("Generate a new project from templates")
17
- .option("--lang <language>", "Project language (ts|js)")
18
- .option("--template <type>", "Template type (agent|chatbot)")
19
- .option("--name <agentName>", "Agent/Chatbot name (must be a valid function name)")
20
- .option("--project <projectId>", "Project ID")
21
- .action(async (folder, options) => {
22
- try {
23
- const spinner = ora("Initializing project generation...").start();
24
-
25
- // Ensure target folder doesn't exist
26
- if (fs.existsSync(folder)) {
27
- spinner.fail(`Folder ${folder} already exists`);
28
- return;
29
- }
30
-
31
- let selectedLang = options.lang;
32
- let selectedTemplate = options.template;
33
- let agentName = options.name;
34
-
35
- // Interactive selection if not provided
36
- if (!selectedLang || !selectedTemplate) {
37
- spinner.stop();
38
-
39
- const answers = await inquirer.prompt([
40
- {
41
- type: 'list',
42
- name: 'lang',
43
- message: 'Select project language:',
44
- choices: [
45
- { name: 'TypeScript', value: 'ts' },
46
- { name: 'JavaScript', value: 'js' }
47
- ],
48
- when: () => !selectedLang
49
- },
50
- {
51
- type: 'list',
52
- name: 'template',
53
- message: 'Select template type:',
54
- choices: [
55
- { name: 'Agent', value: 'agent' },
56
- { name: 'Chatbot', value: 'chatbot' }
57
- ],
58
- when: () => !selectedTemplate
59
- },
60
- {
61
- type: 'input',
62
- name: 'agentName',
63
- message: 'Enter agent/chatbot name (must be a valid function name):',
64
- when: () => !agentName,
65
- default: (answers: any) => {
66
- const type = selectedTemplate || answers.template;
67
- return type === 'agent' ? 'myAgent' : 'myChatbot';
68
- },
69
- validate: (input: string) => {
70
- if (!input.trim()) {
71
- return 'Agent name cannot be empty';
72
- }
73
- if (!isValidFunctionName(input.trim())) {
74
- return 'Must be a valid function name (e.g., myAgent, chatBot123, my_agent)';
75
- }
76
- return true;
77
- }
78
- }
79
- ]);
80
-
81
- selectedLang = selectedLang || answers.lang;
82
- selectedTemplate = selectedTemplate || answers.template;
83
- agentName = agentName || answers.agentName;
84
-
85
- spinner.start("Generating project...");
86
- }
87
-
88
- // Validate agent name if provided via CLI option
89
- if (agentName && !isValidFunctionName(agentName)) {
90
- spinner.fail(`Invalid agent name: "${agentName}". Must be a valid function name (e.g., myAgent, chatBot123, my_agent)`);
91
- return;
92
- }
93
-
94
- // Set default agent name if not provided
95
- if (!agentName) {
96
- agentName = selectedTemplate === 'agent' ? 'myAgent' : 'myChatbot';
97
- }
98
-
99
- // Find matching template in local templates folder
100
- const templateMapping: Record<string, string> = {
101
- 'agent': 'base',
102
- 'chatbot': 'chatbot'
103
- };
104
- const mappedTemplateType = templateMapping[selectedTemplate] || selectedTemplate;
105
-
106
- // Check if template directory exists
107
- const templatePath = path.resolve(__dirname, `../../../../templates/${mappedTemplateType}-${selectedLang}`);
108
-
109
- if (!fs.existsSync(templatePath)) {
110
- spinner.fail(`Template not found: ${templatePath}`);
111
- // Show available templates
112
- const availableTemplates = listAvailableTemplates();
113
- if (availableTemplates.length > 0) {
114
- console.log(chalk.yellow('Available templates:'));
115
- availableTemplates.forEach(template => {
116
- console.log(chalk.yellow(` - ${template}`));
117
- });
118
- } else {
119
- console.log(chalk.red('No templates found. Please add your templates to the templates directory.'));
120
- }
121
- return;
122
- }
123
-
124
- spinner.text = `Generating ${mappedTemplateType} project in ${folder}...`;
125
-
126
- try {
127
- // Generate project using plop
128
- await generateWithPlop(selectedTemplate, selectedLang, folder, path.basename(folder), agentName);
129
-
130
- // Create nestbox.config.json for TypeScript projects
131
- createNestboxConfig(folder, selectedLang === 'ts');
132
-
133
- spinner.succeed(`Successfully generated ${mappedTemplateType} project in ${folder}`);
134
-
135
- console.log(chalk.green("\nNext steps:"));
136
- console.log(chalk.yellow(` cd ${folder}`));
137
- console.log(chalk.yellow(" npm install"));
138
- if (selectedLang === 'ts') {
139
- console.log(chalk.yellow(" npm run build"));
140
- }
141
- console.log(chalk.yellow(" nestbox agent deploy --agent <agent-name> --instance <instance-name>"));
142
-
143
- } catch (error) {
144
- // Clean up on error
145
- if (fs.existsSync(folder)) {
146
- fs.rmSync(folder, { recursive: true, force: true });
147
- }
148
- throw error;
149
- }
150
-
151
- } catch (error: any) {
152
- console.error(
153
- chalk.red("Error:"),
154
- error.message || "Failed to generate project"
155
- );
156
- }
157
- });
15
+ generateCommand
16
+ .command("project <folder>")
17
+ .description("Generate a new project from templates")
18
+ .option("--lang <language>", "Project language (ts|js)")
19
+ .option("--template <type>", "Template type (agent|chatbot)")
20
+ .option(
21
+ "--name <agentName>",
22
+ "Agent/Chatbot name (must be a valid function name)"
23
+ )
24
+ .option("--project <projectId>", "Project ID")
25
+ .action(async (folder, options) => {
26
+ try {
27
+ const spinner = ora(
28
+ "Initializing project generation..."
29
+ ).start();
30
+
31
+ // Ensure target folder doesn't exist
32
+ if (fs.existsSync(folder)) {
33
+ spinner.fail(`Folder ${folder} already exists`);
34
+ return;
35
+ }
36
+
37
+ let selectedLang = options.lang;
38
+ let selectedTemplate = options.template;
39
+ let agentName = options.name;
40
+
41
+ // Interactive selection if not provided
42
+ if (!selectedLang || !selectedTemplate) {
43
+ spinner.stop();
44
+
45
+ const answers = await inquirer.prompt([
46
+ {
47
+ type: "list",
48
+ name: "lang",
49
+ message: "Select project language:",
50
+ choices: [
51
+ { name: "TypeScript", value: "ts" },
52
+ { name: "JavaScript", value: "js" },
53
+ ],
54
+ when: () => !selectedLang,
55
+ },
56
+ {
57
+ type: "list",
58
+ name: "template",
59
+ message: "Select template type:",
60
+ choices: [
61
+ { name: "Agent", value: "agent" },
62
+ { name: "Chatbot", value: "chatbot" },
63
+ ],
64
+ when: () => !selectedTemplate,
65
+ },
66
+ {
67
+ type: "input",
68
+ name: "agentName",
69
+ message:
70
+ "Enter agent/chatbot name (must be a valid function name):",
71
+ when: () => !agentName,
72
+ default: (answers: any) => {
73
+ const type =
74
+ selectedTemplate || answers.template;
75
+ return type === "agent"
76
+ ? "myAgent"
77
+ : "myChatbot";
78
+ },
79
+ validate: (input: string) => {
80
+ if (!input.trim()) {
81
+ return "Agent name cannot be empty";
82
+ }
83
+ if (!isValidFunctionName(input.trim())) {
84
+ return "Must be a valid function name (e.g., myAgent, chatBot123, my_agent)";
85
+ }
86
+ return true;
87
+ },
88
+ },
89
+ ]);
90
+
91
+ selectedLang = selectedLang || answers.lang;
92
+ selectedTemplate = selectedTemplate || answers.template;
93
+ agentName = agentName || answers.agentName;
94
+
95
+ spinner.start("Generating project...");
96
+ }
97
+
98
+ // Validate agent name if provided via CLI option
99
+ if (agentName && !isValidFunctionName(agentName)) {
100
+ spinner.fail(
101
+ `Invalid agent name: "${agentName}". Must be a valid function name (e.g., myAgent, chatBot123, my_agent)`
102
+ );
103
+ return;
104
+ }
105
+
106
+ // Set default agent name if not provided
107
+ if (!agentName) {
108
+ agentName =
109
+ selectedTemplate === "agent" ? "myAgent" : "myChatbot";
110
+ }
111
+
112
+ // Find matching template in local templates folder
113
+ const templateMapping: Record<string, string> = {
114
+ agent: "base",
115
+ chatbot: "chatbot",
116
+ };
117
+ const mappedTemplateType =
118
+ templateMapping[selectedTemplate] || selectedTemplate;
119
+
120
+ // Check if template directory exists
121
+ console.log(__dirname);
122
+ const templatePath = path.resolve(
123
+ __dirname,
124
+ `../../../templates/${mappedTemplateType}-${selectedLang}`
125
+ );
126
+
127
+ if (!fs.existsSync(templatePath)) {
128
+ spinner.fail(`Template not found: ${templatePath}`);
129
+ // Show available templates
130
+ const availableTemplates = listAvailableTemplates();
131
+ if (availableTemplates.length > 0) {
132
+ console.log(chalk.yellow("Available templates:"));
133
+ availableTemplates.forEach(template => {
134
+ console.log(chalk.yellow(` - ${template}`));
135
+ });
136
+ } else {
137
+ console.log(
138
+ chalk.red(
139
+ "No templates found. Please add your templates to the templates directory."
140
+ )
141
+ );
142
+ }
143
+ return;
144
+ }
145
+
146
+ spinner.text = `Generating ${mappedTemplateType} project in ${folder}...`;
147
+
148
+ try {
149
+ // Generate project using plop
150
+ await generateWithPlop(
151
+ selectedTemplate,
152
+ selectedLang,
153
+ folder,
154
+ path.basename(folder),
155
+ agentName
156
+ );
157
+
158
+ // Create nestbox.config.json for TypeScript projects
159
+ createNestboxConfig(folder, selectedLang === "ts");
160
+
161
+ spinner.succeed(
162
+ `Successfully generated ${mappedTemplateType} project in ${folder}`
163
+ );
164
+
165
+ console.log(chalk.green("\nNext steps:"));
166
+ console.log(chalk.yellow(` cd ${folder}`));
167
+ console.log(chalk.yellow(" npm install"));
168
+ if (selectedLang === "ts") {
169
+ console.log(chalk.yellow(" npm run build"));
170
+ }
171
+ console.log(
172
+ chalk.yellow(
173
+ " nestbox agent deploy --agent <agent-name> --instance <instance-name>"
174
+ )
175
+ );
176
+ } catch (error) {
177
+ // Clean up on error
178
+ if (fs.existsSync(folder)) {
179
+ fs.rmSync(folder, { recursive: true, force: true });
180
+ }
181
+ throw error;
182
+ }
183
+ } catch (error: any) {
184
+ console.error(
185
+ chalk.red("Error:"),
186
+ error.message || "Failed to generate project"
187
+ );
188
+ }
189
+ });
158
190
  }