nexscope 1.0.0 → 1.0.1
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.
- package/package.json +5 -2
- package/src/commands/install.js +45 -56
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexscope",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "NexScope CLI tool",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"nexscope": "bin/nexscope.js"
|
|
7
|
+
"nexscope": "./bin/nexscope.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "node bin/nexscope.js --help"
|
|
@@ -16,5 +16,8 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">=14.0.0"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"listr2": "^5.0.8"
|
|
19
22
|
}
|
|
20
23
|
}
|
package/src/commands/install.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
4
|
const https = require('https');
|
|
5
|
+
const { Listr } = require('listr2');
|
|
5
6
|
|
|
6
7
|
const SKILLS_REPO = 'nexscope-ai/eCommerce-Skills';
|
|
7
8
|
const REPO_API = 'https://api.github.com/repos/nexscope-ai/eCommerce-Skills/contents';
|
|
@@ -47,37 +48,40 @@ async function fetchSkillList() {
|
|
|
47
48
|
return JSON.parse(data).filter((i) => i.type === 'dir').map((i) => i.name);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
// Parse directory-related flags to pass through to npx skills
|
|
51
51
|
function parseDirFlags(args) {
|
|
52
52
|
const flags = [];
|
|
53
|
-
|
|
54
|
-
if (args.includes('--global') || args.includes('-g')) {
|
|
55
|
-
flags.push('-g');
|
|
56
|
-
}
|
|
57
|
-
|
|
53
|
+
if (args.includes('--global') || args.includes('-g')) flags.push('-g');
|
|
58
54
|
const agentIndex = args.findIndex((a) => a === '--agent' || a === '-a');
|
|
59
55
|
if (agentIndex !== -1 && args[agentIndex + 1]) {
|
|
60
56
|
flags.push('--agent', args[agentIndex + 1]);
|
|
61
57
|
}
|
|
62
|
-
|
|
63
58
|
return flags;
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
function
|
|
67
|
-
return new Promise((resolve) => {
|
|
68
|
-
const
|
|
69
|
-
const proc = spawn('npx', skillsArgs, { shell: true });
|
|
70
|
-
|
|
61
|
+
function spawnAsync(cmd, args) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const proc = spawn(cmd, args, { shell: true });
|
|
71
64
|
let output = '';
|
|
72
65
|
proc.stdout.on('data', (d) => (output += d.toString()));
|
|
73
66
|
proc.stderr.on('data', (d) => (output += d.toString()));
|
|
74
|
-
|
|
75
67
|
proc.on('close', (code) => {
|
|
76
|
-
|
|
68
|
+
if (code === 0) resolve(output);
|
|
69
|
+
else reject(new Error(output.trim()));
|
|
77
70
|
});
|
|
78
71
|
});
|
|
79
72
|
}
|
|
80
73
|
|
|
74
|
+
async function getInstalledSkills(dirFlags) {
|
|
75
|
+
try {
|
|
76
|
+
const output = await spawnAsync('npx', ['skills', 'ls', '--json', ...dirFlags]);
|
|
77
|
+
const data = JSON.parse(output);
|
|
78
|
+
// Each entry may be a string or object with a name field
|
|
79
|
+
return data.map((s) => (typeof s === 'string' ? s : s.name || s.skill || '')).filter(Boolean);
|
|
80
|
+
} catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
81
85
|
function runSkillsSync(skillsArgs) {
|
|
82
86
|
return new Promise((resolve) => {
|
|
83
87
|
const proc = spawn('npx', ['skills', ...skillsArgs], { shell: true, stdio: 'inherit' });
|
|
@@ -106,60 +110,45 @@ async function run(args) {
|
|
|
106
110
|
console.error("Run 'nexscope install --help' for usage.");
|
|
107
111
|
process.exit(1);
|
|
108
112
|
}
|
|
109
|
-
|
|
113
|
+
|
|
114
|
+
const installed = await getInstalledSkills(dirFlags);
|
|
115
|
+
if (installed.includes(skillName)) {
|
|
116
|
+
console.log(`Skill "${skillName}" is already installed. Skipping.`);
|
|
117
|
+
printThankYou();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
const code = await runSkillsSync(['add', SKILLS_REPO, '--skill', skillName, '-y', ...dirFlags]);
|
|
111
122
|
printThankYou();
|
|
112
123
|
process.exit(code || 0);
|
|
113
124
|
} else {
|
|
114
|
-
// All skills: fetch list then install concurrently
|
|
115
125
|
process.stdout.write('Fetching skill list... ');
|
|
116
|
-
const skills = await
|
|
126
|
+
const [skills, installed] = await Promise.all([
|
|
127
|
+
fetchSkillList(),
|
|
128
|
+
getInstalledSkills(dirFlags),
|
|
129
|
+
]);
|
|
117
130
|
console.log(`${skills.length} skills found.\n`);
|
|
118
131
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const icon =
|
|
130
|
-
status[s] === 'pending' ? '⏳' :
|
|
131
|
-
status[s] === 'running' ? '⚙ ' :
|
|
132
|
-
status[s] === 'done' ? '✓ ' : '✗ ';
|
|
133
|
-
console.log(` ${icon} ${s}`);
|
|
132
|
+
const tasks = new Listr(
|
|
133
|
+
skills.map((skillName) => ({
|
|
134
|
+
title: skillName,
|
|
135
|
+
skip: () => installed.includes(skillName) ? 'Already installed' : false,
|
|
136
|
+
task: () => spawnAsync('npx', ['skills', 'add', SKILLS_REPO, '--skill', skillName, '-y', ...dirFlags]),
|
|
137
|
+
})),
|
|
138
|
+
{
|
|
139
|
+
concurrent: true,
|
|
140
|
+
exitOnError: false,
|
|
141
|
+
rendererOptions: { collapseErrors: false },
|
|
134
142
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
printStatus();
|
|
138
|
-
|
|
139
|
-
const promises = skills.map((skillName) => {
|
|
140
|
-
status[skillName] = 'running';
|
|
141
|
-
printStatus();
|
|
142
|
-
return installOne(skillName, dirFlags).then((result) => {
|
|
143
|
-
status[skillName] = result.success ? 'done' : 'failed';
|
|
144
|
-
printStatus();
|
|
145
|
-
return result;
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const results = await Promise.all(promises);
|
|
150
|
-
|
|
151
|
-
const succeeded = results.filter((r) => r.success);
|
|
152
|
-
const failed = results.filter((r) => !r.success);
|
|
153
|
-
|
|
154
|
-
console.log(`\n${succeeded.length}/${skills.length} skills installed successfully.`);
|
|
143
|
+
);
|
|
155
144
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
145
|
+
try {
|
|
146
|
+
await tasks.run();
|
|
147
|
+
} catch {
|
|
148
|
+
// listr2 throws if any task fails; results are already displayed
|
|
159
149
|
}
|
|
160
150
|
|
|
161
151
|
printThankYou();
|
|
162
|
-
process.exit(failed.length > 0 ? 1 : 0);
|
|
163
152
|
}
|
|
164
153
|
}
|
|
165
154
|
|