@ibm-adw/skill-toolkit
Version:
Developing your own skills with IBM Automation Digital Worker Skill Toolkit
182 lines (143 loc) • 7.3 kB
JavaScript
/*
Licensed Materials - Property of IBM
5737-I23
Copyright IBM Corp. 2019. All Rights Reserved.
U.S. Government Users Restricted Rights:
Use, duplication or disclosure restricted by GSA ADP Schedule
Contract with IBM Corp.
*/
const { generateAllFiles } = require('./generate-files');
const exec = require('child_process').exec;
const fs = require('fs');
const chalk = require('chalk');
const convertArrayIntoStringForDisplay = (array) => {
let displayStr = '';
array.forEach((val, i) => {
const start = (!i ? '[ ' : ' ');
const end = (i === array.length - 1 ? ' ]' : ',');
displayStr += start;
displayStr += chalk.green(val);
displayStr += end;
});
return displayStr;
};
const createSkill = async (skillProjectRepo, pathSkillProject) => {
console.log('\nCreating a new skill project in', chalk.cyan(pathSkillProject));
if (!fs.existsSync(pathSkillProject)) {
fs.mkdirSync(pathSkillProject);
}
console.log('This utility will walk you through creating a skill package for IBM Automation Digital Worker.');
console.log('Let\'s start by configuring your new skill.\n');
console.log('Press ^C at any time to quit.\n');
let onGoing = true;
const availableCategories = [
'act',
'understand',
'decide'
];
const availableLevels = [
'tech_preview',
'released'
];
const skillData = {
packageName: '@scope/my-skill-package-name',
name: 'My Skill Name',
description: 'This is my skill description.',
author: 'me',
category: availableCategories[0],
level: availableLevels[0]
};
async function sh(cmd) {
return new Promise(function (resolve, reject) {
exec(cmd, (err, stdout, stderr) => {
if (err) {
reject(err);
} else {
resolve({ stdout, stderr });
}
});
});
}
const askQuestion = (readline, question, element, availableValues) => {
return new Promise(resolve => {
readline.question(question, async (answer) => {
if (answer && availableValues && !availableValues.includes(answer)) {
console.log(chalk.red('error:'), answer, 'is not a valid value for', element);
console.log('Please choose one from:\n', convertArrayIntoStringForDisplay(availableValues));
await askQuestion(readline, question, element, availableValues);
} else if (element && answer) {
skillData[element] = answer;
}
resolve(answer);
});
});
};
const askAllQuestions = async (readline) => {
await askQuestion(readline, `skill package name [${skillData.packageName}]: `, 'packageName');
await askQuestion(readline, `skill name [${skillData.name}]: `, 'name');
await askQuestion(readline, `skill description [${skillData.description}]: `, 'description');
await askQuestion(readline, `skill author [${skillData.author}]: `, 'author');
console.log('\nThe category of your skill can be one of:');
console.log(convertArrayIntoStringForDisplay(availableCategories));
await askQuestion(readline, `skill category [${skillData.category}]: `, 'category', availableCategories);
console.log('\nThe level of your skill can be one of:');
console.log(convertArrayIntoStringForDisplay(availableLevels));
await askQuestion(readline, `skill level [${skillData.level}]: `, 'level', availableLevels);
console.log('\n',skillData,'\n');
const agree = await askQuestion(readline, 'Is this OK? [yes]: ') || 'yes';
if (agree === 'yes' || agree === 'y') {
const sample = await askQuestion(readline, '\nDo you want to generate a sample skill? [yes]: ') || 'yes';
readline.close();
// continue
console.log('\nSetting up the project...\nThis can take a while.\n');
generateAllFiles(pathSkillProject, skillProjectRepo, skillData, (sample === 'yes' || sample === 'y'));
const { stdout, stderr } = await sh('cd "' + pathSkillProject + '" && npm i');
for (const line of stdout.split('\n')) {
if (line !== '') {
console.log(chalk.blue('info'), line);
}
}
for (const line of stderr.split('\n')) {
if (line !== '') {
console.log(chalk.red('error'), line);
}
}
console.log('\nAll set !');
console.log('');
console.log('You can now start implementing your skill at', chalk.yellow(pathSkillProject));
console.log('There, you can run several commands:\n');
console.log(chalk.cyan(' npm run lint'));
console.log(chalk.white(' Check that your code is correctly formatted.\n'));
console.log(chalk.cyan(' npm run test'));
console.log(chalk.white(' Start the test script.\n'));
console.log(chalk.cyan(' npm pack'));
console.log(chalk.white(' Generate a tar.gz when your skill is ready.\n'));
console.log('');
console.log('You can use the IBM Automation Digital Worker skill test kit.');
console.log('It provides a user interface that will guide you in implementing and testing your skill.');
console.log('In two different terminal windows, run:\n');
console.log(chalk.cyan(' npx adw-launch-server ' + skillProjectRepo), chalk.blue('[SERVER_PORT]'));
console.log(chalk.white(' Launches the server side of the IBM Automation Digital Worker test kit to serve your skill located in folder'), chalk.green(skillProjectRepo), chalk.white('.'));
console.log(chalk.blue(' (optional)'), chalk.white('[SERVER_PORT] is the port where the skill endpoint is available. If not specified, the default is 8888.\n'));
console.log(chalk.cyan(' npx adw-launch-client'), chalk.blue('[CLIENT_PORT] [SERVER_PORT]'));
console.log(chalk.white(' Launches the user interface of the IBM Automation Digital Worker test kit.'));
console.log(chalk.blue(' (optional)'), chalk.white('[CLIENT_PORT] is the port where the test kit client application is running. If not specified, the default is 3000.'));
console.log(chalk.blue(' (optional)'), chalk.white('[SERVER_PORT] is the port where the skill endpoint is available and must correspond to the one you provided when you launched the server. If not specified, the default is 8888. \n'));
return false;
}
else {
console.log('Aborted.');
console.log('Let\'s start and configure your skill again.');
return true;
}
};
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
while (onGoing) {
onGoing = await askAllQuestions(readline);
}
};
module.exports = { createSkill };