@brookmind/ai-toolkit 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/bin/cli.js +8 -1
- package/package.json +1 -1
- package/src/index.js +252 -68
package/bin/cli.js
CHANGED
|
@@ -2,4 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import { run } from '../src/index.js';
|
|
4
4
|
|
|
5
|
-
run().catch(
|
|
5
|
+
run().catch((error) => {
|
|
6
|
+
if (error.name === 'ExitPromptError') {
|
|
7
|
+
console.log('\nInstallation cancelled.');
|
|
8
|
+
process.exit(0);
|
|
9
|
+
}
|
|
10
|
+
console.error(error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
});
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { select, checkbox
|
|
1
|
+
import { select, checkbox } from '@inquirer/prompts';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { readdir, cp, mkdir } from 'fs/promises';
|
|
5
|
-
import { existsSync } from 'fs';
|
|
4
|
+
import { readdir, cp, mkdir, access } from 'fs/promises';
|
|
6
5
|
import { join, dirname } from 'path';
|
|
7
6
|
import { fileURLToPath } from 'url';
|
|
8
7
|
import { homedir } from 'os';
|
|
@@ -30,16 +29,41 @@ async function getFiles(path, extension) {
|
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
|
32
|
+
async function exists(path) {
|
|
33
|
+
try {
|
|
34
|
+
await access(path);
|
|
35
|
+
return true;
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const BACK = '__BACK__';
|
|
42
|
+
const CONTINUE = '__CONTINUE__';
|
|
43
|
+
|
|
44
|
+
function createChoices(items, includeBack = false) {
|
|
45
|
+
const choices = items.map(item => ({
|
|
46
|
+
name: item,
|
|
47
|
+
value: item,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
choices.push({ name: chalk.green('─→ Continue'), value: CONTINUE });
|
|
51
|
+
|
|
52
|
+
if (includeBack) {
|
|
53
|
+
choices.push({ name: chalk.yellow('←─ Back'), value: BACK });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return choices;
|
|
57
|
+
}
|
|
58
|
+
|
|
33
59
|
export async function run() {
|
|
34
60
|
console.clear();
|
|
35
61
|
|
|
36
62
|
// Header
|
|
37
63
|
console.log('');
|
|
38
|
-
console.log(chalk.magenta('
|
|
39
|
-
console.log(chalk.magenta('║
|
|
40
|
-
console.log(chalk.magenta('
|
|
41
|
-
console.log(chalk.magenta('║ ║'));
|
|
42
|
-
console.log(chalk.magenta('╚═══════════════════════════════════════════════════╝'));
|
|
64
|
+
console.log(chalk.magenta('╔══════════════════════════════════╗'));
|
|
65
|
+
console.log(chalk.magenta('║') + chalk.white.bold(' CKW AI Toolkit Installer ') + chalk.magenta('║'));
|
|
66
|
+
console.log(chalk.magenta('╚══════════════════════════════════╝'));
|
|
43
67
|
console.log('');
|
|
44
68
|
|
|
45
69
|
// Get available items
|
|
@@ -47,70 +71,230 @@ export async function run() {
|
|
|
47
71
|
const skills = await getDirectories(join(ROOT_DIR, 'skills'));
|
|
48
72
|
const mcps = await getDirectories(join(ROOT_DIR, 'mcps'));
|
|
49
73
|
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
{ name: 'OpenCode', value: 'opencode' },
|
|
57
|
-
{ name: 'Both', value: 'both' }
|
|
58
|
-
]
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Step 2: Agents
|
|
62
|
-
console.log('');
|
|
63
|
-
console.log(chalk.cyan('Step 2/4: Agents'));
|
|
64
|
-
const selectedAgents = agents.length > 0
|
|
65
|
-
? await checkbox({
|
|
66
|
-
message: 'Select agents to install',
|
|
67
|
-
choices: agents.map(a => ({ name: a, value: a }))
|
|
68
|
-
})
|
|
69
|
-
: [];
|
|
70
|
-
|
|
71
|
-
// Step 3: Skills
|
|
72
|
-
console.log('');
|
|
73
|
-
console.log(chalk.cyan('Step 3/4: Skills'));
|
|
74
|
-
const selectedSkills = skills.length > 0
|
|
75
|
-
? await checkbox({
|
|
76
|
-
message: 'Select skills to install',
|
|
77
|
-
choices: skills.map(s => ({ name: s, value: s }))
|
|
78
|
-
})
|
|
79
|
-
: [];
|
|
80
|
-
|
|
81
|
-
// Step 4: MCPs
|
|
82
|
-
console.log('');
|
|
83
|
-
console.log(chalk.cyan('Step 4/4: MCPs'));
|
|
84
|
-
const selectedMcps = mcps.length > 0
|
|
85
|
-
? await checkbox({
|
|
86
|
-
message: 'Select MCPs to install',
|
|
87
|
-
choices: mcps.map(m => ({ name: m, value: m }))
|
|
88
|
-
})
|
|
89
|
-
: [];
|
|
90
|
-
|
|
91
|
-
// Summary
|
|
92
|
-
console.log('');
|
|
93
|
-
console.log(chalk.yellow('Summary'));
|
|
94
|
-
console.log('');
|
|
95
|
-
console.log(` Platform: ${chalk.white(platform)}`);
|
|
96
|
-
console.log(` Agents: ${chalk.white(selectedAgents.length > 0 ? selectedAgents.join(', ') : 'none')}`);
|
|
97
|
-
console.log(` Skills: ${chalk.white(selectedSkills.length > 0 ? selectedSkills.join(', ') : 'none')}`);
|
|
98
|
-
console.log(` MCPs: ${chalk.white(selectedMcps.length > 0 ? selectedMcps.join(', ') : 'none')}`);
|
|
99
|
-
console.log('');
|
|
74
|
+
// State
|
|
75
|
+
let step = 1;
|
|
76
|
+
let platform = null;
|
|
77
|
+
let selectedAgents = [];
|
|
78
|
+
let selectedSkills = [];
|
|
79
|
+
let selectedMcps = [];
|
|
100
80
|
|
|
101
|
-
const
|
|
81
|
+
const home = homedir();
|
|
102
82
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
83
|
+
// Navigation loop
|
|
84
|
+
while (step <= 5) {
|
|
85
|
+
|
|
86
|
+
if (step === 1) {
|
|
87
|
+
// Step 1: Platform
|
|
88
|
+
console.log(chalk.cyan('Step 1/5: Platform'));
|
|
89
|
+
console.log('');
|
|
90
|
+
|
|
91
|
+
platform = await select({
|
|
92
|
+
message: 'Where do you want to install?',
|
|
93
|
+
choices: [
|
|
94
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
95
|
+
{ name: 'OpenCode', value: 'opencode' },
|
|
96
|
+
{ name: 'Both', value: 'both' },
|
|
97
|
+
{ name: chalk.yellow('←─ Cancel'), value: BACK }
|
|
98
|
+
]
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (platform === BACK) {
|
|
102
|
+
console.log(chalk.yellow('Installation cancelled.'));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
step = 2;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
else if (step === 2) {
|
|
110
|
+
// Step 2: Agents
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(chalk.cyan('Step 2/5: Agents'));
|
|
113
|
+
console.log(chalk.dim('Select items with space, then choose Continue'));
|
|
114
|
+
console.log('');
|
|
115
|
+
|
|
116
|
+
if (agents.length > 0) {
|
|
117
|
+
// Check which agents already exist
|
|
118
|
+
const agentChoices = [];
|
|
119
|
+
for (const agent of agents) {
|
|
120
|
+
let alreadyInstalled = false;
|
|
121
|
+
|
|
122
|
+
if (platform === 'claude' || platform === 'both') {
|
|
123
|
+
if (await exists(join(home, '.claude', 'agents', `${agent}.md`))) {
|
|
124
|
+
alreadyInstalled = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (platform === 'opencode' || platform === 'both') {
|
|
128
|
+
if (await exists(join(home, '.config', 'opencode', 'agent', `${agent}.md`))) {
|
|
129
|
+
alreadyInstalled = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
agentChoices.push({
|
|
134
|
+
name: alreadyInstalled ? `${agent} ${chalk.yellow('(installed)')}` : agent,
|
|
135
|
+
value: agent,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
agentChoices.push({ name: chalk.green('─→ Continue'), value: CONTINUE });
|
|
140
|
+
agentChoices.push({ name: chalk.yellow('←─ Back'), value: BACK });
|
|
141
|
+
|
|
142
|
+
const result = await checkbox({
|
|
143
|
+
message: 'Select agents:',
|
|
144
|
+
choices: agentChoices,
|
|
145
|
+
theme: {
|
|
146
|
+
icon: {
|
|
147
|
+
checked: chalk.green('[✓]'),
|
|
148
|
+
unchecked: '[ ]',
|
|
149
|
+
cursor: '→'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (result.includes(BACK)) {
|
|
155
|
+
step = 1;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
selectedAgents = result.filter(r => r !== CONTINUE && r !== BACK);
|
|
160
|
+
|
|
161
|
+
if (!result.includes(CONTINUE)) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
step = 3;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
else if (step === 3) {
|
|
170
|
+
// Step 3: Skills
|
|
171
|
+
console.log('');
|
|
172
|
+
console.log(chalk.cyan('Step 3/5: Skills'));
|
|
173
|
+
console.log(chalk.dim('Select items with space, then choose Continue'));
|
|
174
|
+
console.log('');
|
|
175
|
+
|
|
176
|
+
if (skills.length > 0) {
|
|
177
|
+
// Check which skills already exist
|
|
178
|
+
const skillChoices = [];
|
|
179
|
+
for (const skill of skills) {
|
|
180
|
+
let alreadyInstalled = false;
|
|
181
|
+
|
|
182
|
+
if (platform === 'claude' || platform === 'both') {
|
|
183
|
+
if (await exists(join(home, '.claude', 'skills', skill))) {
|
|
184
|
+
alreadyInstalled = true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
skillChoices.push({
|
|
189
|
+
name: alreadyInstalled ? `${skill} ${chalk.yellow('(installed)')}` : skill,
|
|
190
|
+
value: skill,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
skillChoices.push({ name: chalk.green('─→ Continue'), value: CONTINUE });
|
|
195
|
+
skillChoices.push({ name: chalk.yellow('←─ Back'), value: BACK });
|
|
196
|
+
|
|
197
|
+
const result = await checkbox({
|
|
198
|
+
message: 'Select skills:',
|
|
199
|
+
choices: skillChoices,
|
|
200
|
+
theme: {
|
|
201
|
+
icon: {
|
|
202
|
+
checked: chalk.green('[✓]'),
|
|
203
|
+
unchecked: '[ ]',
|
|
204
|
+
cursor: '→'
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
if (result.includes(BACK)) {
|
|
210
|
+
step = 2;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
selectedSkills = result.filter(r => r !== CONTINUE && r !== BACK);
|
|
215
|
+
|
|
216
|
+
if (!result.includes(CONTINUE)) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
step = 4;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
else if (step === 4) {
|
|
225
|
+
// Step 4: MCPs
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(chalk.cyan('Step 4/5: MCPs'));
|
|
228
|
+
console.log(chalk.dim('Select items with space, then choose Continue'));
|
|
229
|
+
console.log('');
|
|
230
|
+
|
|
231
|
+
if (mcps.length > 0) {
|
|
232
|
+
const result = await checkbox({
|
|
233
|
+
message: 'Select MCPs:',
|
|
234
|
+
choices: createChoices(mcps, true),
|
|
235
|
+
theme: {
|
|
236
|
+
icon: {
|
|
237
|
+
checked: chalk.green('[✓]'),
|
|
238
|
+
unchecked: '[ ]',
|
|
239
|
+
cursor: '→'
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
if (result.includes(BACK)) {
|
|
245
|
+
step = 3;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
selectedMcps = result.filter(r => r !== CONTINUE && r !== BACK);
|
|
250
|
+
|
|
251
|
+
if (!result.includes(CONTINUE)) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
step = 5;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
else if (step === 5) {
|
|
260
|
+
// Step 5: Summary & Confirm
|
|
261
|
+
console.log('');
|
|
262
|
+
console.log(chalk.yellow('Summary'));
|
|
263
|
+
console.log('');
|
|
264
|
+
console.log(` Platform: ${chalk.white(platform)}`);
|
|
265
|
+
console.log(` Agents: ${chalk.white(selectedAgents.length > 0 ? selectedAgents.join(', ') : 'none')}`);
|
|
266
|
+
console.log(` Skills: ${chalk.white(selectedSkills.length > 0 ? selectedSkills.join(', ') : 'none')}`);
|
|
267
|
+
console.log(` MCPs: ${chalk.white(selectedMcps.length > 0 ? selectedMcps.join(', ') : 'none')}`);
|
|
268
|
+
console.log('');
|
|
269
|
+
|
|
270
|
+
const action = await select({
|
|
271
|
+
message: 'What would you like to do?',
|
|
272
|
+
choices: [
|
|
273
|
+
{ name: chalk.green('✓ Install'), value: 'install' },
|
|
274
|
+
{ name: chalk.yellow('←─ Back'), value: BACK },
|
|
275
|
+
{ name: chalk.red('✗ Cancel'), value: 'cancel' }
|
|
276
|
+
]
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
if (action === BACK) {
|
|
280
|
+
step = 4;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (action === 'cancel') {
|
|
285
|
+
console.log(chalk.yellow('Installation cancelled.'));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Proceed with installation
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
106
292
|
}
|
|
107
293
|
|
|
108
294
|
// Installation
|
|
109
295
|
console.log('');
|
|
110
296
|
const spinner = ora('Installing...').start();
|
|
111
297
|
|
|
112
|
-
const home = homedir();
|
|
113
|
-
|
|
114
298
|
async function installClaude() {
|
|
115
299
|
const claudeDir = join(home, '.claude');
|
|
116
300
|
const agentsDir = join(claudeDir, 'agents');
|
|
@@ -128,7 +312,7 @@ export async function run() {
|
|
|
128
312
|
for (const skill of selectedSkills) {
|
|
129
313
|
const src = join(ROOT_DIR, 'skills', skill);
|
|
130
314
|
const dest = join(skillsDir, skill);
|
|
131
|
-
await cp(src, dest, { recursive: true });
|
|
315
|
+
await cp(src, dest, { recursive: true, force: true });
|
|
132
316
|
}
|
|
133
317
|
}
|
|
134
318
|
|
|
@@ -164,9 +348,9 @@ export async function run() {
|
|
|
164
348
|
|
|
165
349
|
// Done
|
|
166
350
|
console.log('');
|
|
167
|
-
console.log(chalk.green('
|
|
168
|
-
console.log(chalk.green('║
|
|
169
|
-
console.log(chalk.green('
|
|
351
|
+
console.log(chalk.green('╔══════════════════════════════════╗'));
|
|
352
|
+
console.log(chalk.green('║ ✓ Installation Complete! ║'));
|
|
353
|
+
console.log(chalk.green('╚══════════════════════════════════╝'));
|
|
170
354
|
|
|
171
355
|
if (selectedMcps.length > 0) {
|
|
172
356
|
console.log('');
|