Skip to content

Commit 9c46bfd

Browse files
committed
added the create agent logic
1 parent 7ec4348 commit 9c46bfd

File tree

10 files changed

+614
-2
lines changed

10 files changed

+614
-2
lines changed

actions/createagent.js

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
const chalk = require('chalk');
2+
const axios = require('axios');
3+
const spawn = require('cross-spawn');
4+
const { Command } = require('commander');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const inquirer = require('inquirer');
8+
const yaml = require('js-yaml');
9+
const { v4: uuidv4 } = require('uuid');
10+
11+
const { checkUserAuth, getUserData } = require('./userData');
12+
13+
async function askForActions(actionsData, parsedYaml) {
14+
console.log(chalk.yellow(`\n------------------------------Action Steps-----------------------------------------\n`));
15+
console.log(chalk.green("Actions are the functionality that your Agent provides to the user. These are like functionality shortcuts that the user can invoke using \\ command.\n"));
16+
17+
const initialPrompt = [
18+
{
19+
type: 'confirm',
20+
name: 'addActions',
21+
message: 'Do you want to add actions?',
22+
default: true,
23+
}
24+
];
25+
26+
const initialRes = await inquirer.prompt(initialPrompt);
27+
let addMoreActions = initialRes.addActions;
28+
29+
while (addMoreActions) {
30+
const actionPrompt = [
31+
{
32+
type: 'input',
33+
name: 'actionName',
34+
message: 'Please Enter Action Name:',
35+
default: parsedYaml.actions[0].name
36+
},
37+
{
38+
type: 'input',
39+
name: 'description',
40+
message: 'Please Enter Action Description:',
41+
default: parsedYaml.actions[0].description
42+
},
43+
{
44+
type: 'input',
45+
name: 'detailDescription',
46+
message: 'Please Enter Detail Description (optional):',
47+
default: parsedYaml.actions[0].detailDescription,
48+
},
49+
{
50+
type: 'input',
51+
name: 'actionPrompt',
52+
message: 'Please Enter Action Prompt (optional):',
53+
default: parsedYaml.actions[0].actionPrompt,
54+
},
55+
{
56+
type: 'confirm',
57+
name: 'addMoreActions',
58+
message: 'Do you want to add more actions?',
59+
default: false,
60+
}
61+
];
62+
63+
const actionRes = await inquirer.prompt(actionPrompt);
64+
actionsData.push({
65+
name: actionRes.actionName,
66+
description: actionRes.description,
67+
detailDescription: actionRes.detailDescription,
68+
actionPrompt: actionRes.actionPrompt,
69+
});
70+
addMoreActions = actionRes.addMoreActions;
71+
}
72+
return actionsData;
73+
}
74+
75+
async function askForInstructions(sdlc, parsedYaml) {
76+
let addMoreInstructions = true;
77+
console.log(chalk.yellow(`\n------------------------------SDLC Steps-----------------------------------------\n`));
78+
console.log(chalk.green("SDLC Steps are the software development steps that your Agent will handle like code generation, deployment, testing etc. \n These are used by Universal Agent Router to route the user request to the correct Agent Invocation.\n Also add sample Instructions that the user should give to invoke that SLDC Step functionality.\n"));
79+
80+
81+
while (addMoreInstructions) {
82+
// Prompt for SDLC step name
83+
const stepPrompt = [
84+
{
85+
type: 'list',
86+
name: 'name',
87+
message: 'Please Enter SDLC Step Name:',
88+
choices: parsedYaml.metadata.sdlc_steps_managed.map(item => item.name),
89+
}
90+
];
91+
92+
const stepRes = await inquirer.prompt(stepPrompt);
93+
94+
let instructions = [];
95+
96+
// Prompt for multiple instructions
97+
let addMoreExamples = true;
98+
while (addMoreExamples) {
99+
const instructionPrompt = [
100+
{
101+
type: 'input',
102+
name: 'example_instruction',
103+
message: 'Please Enter Instruction Description:',
104+
default: 'Generate a new React component',
105+
},
106+
{
107+
type: 'confirm',
108+
name: 'addMoreExamples',
109+
message: 'Do you want to add another instruction?',
110+
default: false,
111+
}
112+
];
113+
114+
const instructionRes = await inquirer.prompt(instructionPrompt);
115+
116+
instructions.push(instructionRes.example_instruction);
117+
addMoreExamples = instructionRes.addMoreExamples;
118+
}
119+
120+
sdlc.push({
121+
name: stepRes.name,
122+
example_instructions: instructions,
123+
});
124+
125+
const addMoreStepsPrompt = [
126+
{
127+
type: 'confirm',
128+
name: 'addMoreInstructions',
129+
message: 'Do you want to add more SDLC steps?',
130+
default: false,
131+
}
132+
];
133+
134+
const addMoreStepsRes = await inquirer.prompt(addMoreStepsPrompt);
135+
addMoreInstructions = addMoreStepsRes.addMoreInstructions;
136+
}
137+
138+
return sdlc;
139+
}
140+
141+
function createProject(projectName, installPath, selectedTemplate, answers, parsedYaml ) {
142+
143+
const projectDir = path.resolve(installPath);
144+
fs.mkdirSync(projectDir, { recursive: true });
145+
146+
// Copy the selected template to the project directory
147+
const templateDir = path.resolve(__dirname,'..', 'template');
148+
const templatePath = path.join(templateDir, selectedTemplate);
149+
fs.cpSync(templatePath, projectDir, { recursive: true });
150+
151+
fs.renameSync(
152+
path.join(projectDir, 'gitignore'),
153+
path.join(projectDir, '.gitignore')
154+
);
155+
156+
const agentYamlPath = path.join(projectDir, 'codeboltagent.yaml');
157+
let agentYaml = fs.readFileSync(agentYamlPath, 'utf8');
158+
159+
let agentYamlObj = yaml.load(agentYaml);
160+
agentYamlObj.title = projectName;
161+
agentYamlObj.description = answers.agentDescription;
162+
agentYamlObj.tags = answers.tags.split(',').map(tag => tag.trim());
163+
agentYamlObj.unique_id = answers.unique_id
164+
agentYamlObj.metadata.agent_routing = {
165+
worksonblankcode: answers.worksonblankcode,
166+
worksonexistingcode: answers.worksonexistingcode,
167+
supportedlanguages: answers.supportedlanguages,
168+
supportedframeworks: answers.supportedframeworks,
169+
};
170+
171+
agentYamlObj.metadata.sdlc_steps_managed = answers.sdlc_steps_managed.map(step => ({
172+
name: step.name,
173+
example_instructions: step.example_instructions,
174+
}));
175+
176+
agentYamlObj.actions = parsedYaml.actions.map(action => ({
177+
name: action.name,
178+
description: action.description,
179+
detailDescription: action.detailDescription,
180+
actionPrompt: action.actionPrompt,
181+
}));
182+
183+
agentYaml = yaml.dump(agentYamlObj);
184+
185+
fs.writeFileSync(agentYamlPath, agentYaml, 'utf8');
186+
187+
const projectPackageJson = require(path.join(projectDir, 'package.json'));
188+
189+
// Update the project's package.json with the new project name
190+
projectPackageJson.name = projectName;
191+
192+
fs.writeFileSync(
193+
path.join(projectDir, 'package.json'),
194+
JSON.stringify(projectPackageJson, null, 2)
195+
);
196+
197+
// Run `npm install` in the project directory to install
198+
// the dependencies. We are using a third-party library
199+
// called `cross-spawn` for cross-platform support.
200+
// (Node has issues spawning child processes in Windows).
201+
spawn.sync('npm', ['install'], { stdio: 'inherit', cwd: installPath });
202+
203+
spawn.sync('git', ['init'], { stdio: 'inherit', cwd: installPath });
204+
205+
console.log('Success! Your new project is ready.');
206+
console.log(`Created ${projectName} at ${projectDir}`);
207+
}
208+
209+
function getPrompts(projectName, quickEnabled, parsedYaml){
210+
211+
const prompts = [];
212+
213+
const currentPath = process.cwd();
214+
215+
const templateDir = path.resolve(__dirname,'..', 'template');
216+
const templates = fs.readdirSync(templateDir).filter(file => fs.statSync(path.join(templateDir, file)).isDirectory());
217+
218+
219+
220+
if (!quickEnabled) {
221+
prompts.push({
222+
type: 'input',
223+
name: 'projectName',
224+
message: 'Please Enter the name of your Agent:',
225+
default: projectName,
226+
});
227+
228+
prompts.push({
229+
type: 'input',
230+
name: 'unique_id',
231+
message: 'Please enter the unique_id:',
232+
default: projectName.replace(/[^a-zA-Z0-9]/g, ''),
233+
validate: function (input) {
234+
if (/\s/.test(input)) {
235+
return 'unique_id should not contain any spaces';
236+
}
237+
return true;
238+
}
239+
});
240+
241+
prompts.push({
242+
type: 'input',
243+
name: 'installPath',
244+
message: 'Please enter the path to install the application:',
245+
default: (answers) => path.join(currentPath, answers.projectName || 'defaultProjectName'),
246+
});
247+
248+
prompts.push({
249+
type: 'list',
250+
name: 'template',
251+
message: 'Please select a template for your application:',
252+
choices: templates,
253+
});
254+
255+
prompts.push({
256+
type: 'input',
257+
name: 'agentDescription',
258+
message: 'Please enter a description for your agent:',
259+
default: 'My Codebolt Agent',
260+
});
261+
262+
prompts.push({
263+
type: 'input',
264+
name: 'tags',
265+
message: 'Please Enter agent tags by comma separated:',
266+
default: 'test',
267+
});
268+
269+
prompts.push({
270+
type: 'confirm',
271+
name: 'worksonblankcode',
272+
message: 'Works on blank code:',
273+
default: parsedYaml.metadata.agent_routing.worksonblankcode,
274+
});
275+
276+
prompts.push({
277+
type: 'confirm',
278+
name: 'worksonexistingcode',
279+
message: 'Works on existing code:',
280+
default: parsedYaml.metadata.agent_routing.worksonexistingcode,
281+
});
282+
283+
prompts.push({
284+
type: 'checkbox',
285+
name: 'supportedlanguages',
286+
message: 'Supported Languages:',
287+
choices: parsedYaml.metadata.agent_routing.supportedlanguages,
288+
validate: function (input) {
289+
if (input.length === 0) {
290+
return 'You must select at least one language';
291+
}
292+
return true;
293+
}
294+
});
295+
296+
prompts.push({
297+
type: 'checkbox',
298+
name: 'supportedframeworks',
299+
message: 'Supported Frameworks:',
300+
choices: parsedYaml.metadata.agent_routing.supportedframeworks,
301+
validate: function (input) {
302+
if (input.length === 0) {
303+
return 'You must select at least one framework';
304+
}
305+
return true;
306+
}
307+
});
308+
}
309+
310+
311+
312+
313+
return prompts;
314+
}
315+
316+
const createagent = async (options) => {
317+
console.log(options)
318+
let projectName = options.name || process.argv[3];
319+
const quickEnabled = options.quick || false;
320+
321+
const agentymlpath = path.join(__dirname, '..','template/basic', 'codeboltagent.yaml');
322+
let agentYamlData = fs.readFileSync(agentymlpath, 'utf8');
323+
const parsedYaml = yaml.load(agentYamlData);
324+
const prompts = getPrompts(projectName, quickEnabled, parsedYaml)
325+
326+
327+
328+
console.log(chalk.blue(
329+
" _____ _ _ _ _ \n"+
330+
" / __ \\ | | | | | | | \n"+
331+
" | / \\/ ___ __| | ___| |__ ___ | | |_ \n"+
332+
" | | / _ \\ / _` |/ _ \\ '_ \\ / _ \\| | __| \n"+
333+
" | \\__/\\ (_) | (_| | __/ |_) | (_) | | |_ \n"+
334+
" \\____/\\___/ \\__,_|\\___|_.__/ \\___/|_|\\__| \n"));
335+
336+
inquirer.prompt(prompts).then(async answers => {
337+
let sdlc = [];
338+
let actionsData = [];
339+
340+
let sdlcInstruction = await askForInstructions(sdlc, parsedYaml)
341+
let actions = await askForActions(actionsData, parsedYaml)
342+
343+
projectName = answers.projectName.trim();
344+
const installPath = answers.installPath.trim() === '.' ? process.cwd() : path.resolve(process.cwd(), answers.installPath.trim());
345+
const selectedTemplate = answers.template;
346+
answers.sdlc_steps_managed = sdlcInstruction
347+
answers.actions = actions
348+
createProject(projectName, installPath, selectedTemplate, answers, parsedYaml);
349+
});
350+
};
351+
352+
353+
module.exports = { createagent };

codebolt.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const inquirer = require('inquirer');
77
const {signIn,logout} = require('./actions/login')
88
// const { login } = require('./actions/login');
99
const { list } = require('./actions/list');
10+
const { createagent } = require('./actions/createagent');
1011

1112
program.version('1.0.1');
1213

@@ -15,6 +16,15 @@ program
1516
.description('Check the application version')
1617
.action(getVersion);
1718

19+
program
20+
.command('createagent')
21+
.description('Create a new Codebolt Agent')
22+
.option('-n, --name <name>', 'name of the project')
23+
.option('--quick', 'create agent quickly with default settings')
24+
.action((options) => {
25+
createagent(options);
26+
});
27+
1828
program
1929
.command('login')
2030
.description('Log in to the application')

0 commit comments

Comments
 (0)