@orchestra-research/ai-research-skills 1.0.0
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/README.md +97 -0
- package/bin/cli.js +8 -0
- package/package.json +46 -0
- package/src/agents.js +81 -0
- package/src/ascii.js +126 -0
- package/src/index.js +282 -0
- package/src/installer.js +391 -0
- package/src/prompts.js +436 -0
package/src/prompts.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Skill categories with their skill counts and example skills
|
|
6
|
+
*/
|
|
7
|
+
export const CATEGORIES = [
|
|
8
|
+
{ id: '01-model-architecture', name: 'Model Architecture', skills: 6, examples: 'LitGPT, Mamba, TorchTitan, Megatron' },
|
|
9
|
+
{ id: '02-tokenization', name: 'Tokenization', skills: 2, examples: 'HuggingFace Tokenizers, SentencePiece' },
|
|
10
|
+
{ id: '03-fine-tuning', name: 'Fine-Tuning', skills: 5, examples: 'Axolotl, Unsloth, Torchtune, PEFT' },
|
|
11
|
+
{ id: '04-mechanistic-interpretability', name: 'Mechanistic Interp.', skills: 4, examples: 'TransformerLens, SAELens, NNsight' },
|
|
12
|
+
{ id: '05-data-processing', name: 'Data Processing', skills: 2, examples: 'NeMo Curator, Ray Data' },
|
|
13
|
+
{ id: '06-post-training', name: 'Post-Training', skills: 8, examples: 'GRPO, verl, slime, miles, torchforge' },
|
|
14
|
+
{ id: '07-safety-alignment', name: 'Safety & Alignment', skills: 3, examples: 'Constitutional AI, LlamaGuard' },
|
|
15
|
+
{ id: '08-distributed-training', name: 'Distributed Training', skills: 6, examples: 'DeepSpeed, FSDP, Megatron, Accelerate' },
|
|
16
|
+
{ id: '09-infrastructure', name: 'Infrastructure', skills: 3, examples: 'Modal, SkyPilot, Lambda Labs' },
|
|
17
|
+
{ id: '10-optimization', name: 'Optimization', skills: 6, examples: 'Flash Attention, GPTQ, AWQ, bitsandbytes' },
|
|
18
|
+
{ id: '11-evaluation', name: 'Evaluation', skills: 3, examples: 'lm-eval-harness, Inspect AI' },
|
|
19
|
+
{ id: '12-inference-serving', name: 'Inference Serving', skills: 4, examples: 'vLLM, TensorRT-LLM, SGLang, llama.cpp' },
|
|
20
|
+
{ id: '13-mlops', name: 'MLOps', skills: 3, examples: 'Weights & Biases, MLflow, TensorBoard' },
|
|
21
|
+
{ id: '14-agents', name: 'Agents', skills: 4, examples: 'LangChain, LlamaIndex, Smolagents' },
|
|
22
|
+
{ id: '15-rag', name: 'RAG', skills: 5, examples: 'Chroma, FAISS, Pinecone, Milvus' },
|
|
23
|
+
{ id: '16-prompt-engineering', name: 'Prompt Engineering', skills: 4, examples: 'DSPy, Instructor, Outlines, Guidance' },
|
|
24
|
+
{ id: '17-observability', name: 'Observability', skills: 2, examples: 'LangSmith, Phoenix' },
|
|
25
|
+
{ id: '18-multimodal', name: 'Multimodal', skills: 7, examples: 'CLIP, Whisper, LLaVA, Qwen2-VL' },
|
|
26
|
+
{ id: '19-emerging-techniques', name: 'Emerging Techniques', skills: 6, examples: 'MoE, Model Merging, Speculative Decoding' },
|
|
27
|
+
{ id: '20-ml-paper-writing', name: 'ML Paper Writing', skills: 1, examples: 'NeurIPS/ICML paper writing' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Individual skills for selection
|
|
32
|
+
*/
|
|
33
|
+
export const INDIVIDUAL_SKILLS = [
|
|
34
|
+
// Post-Training
|
|
35
|
+
{ id: '06-post-training/grpo-rl-training', name: 'GRPO Training', category: 'Post-Training' },
|
|
36
|
+
{ id: '06-post-training/verl', name: 'verl', category: 'Post-Training' },
|
|
37
|
+
{ id: '06-post-training/slime', name: 'slime', category: 'Post-Training' },
|
|
38
|
+
{ id: '06-post-training/miles', name: 'miles', category: 'Post-Training' },
|
|
39
|
+
{ id: '06-post-training/torchforge', name: 'torchforge', category: 'Post-Training' },
|
|
40
|
+
{ id: '06-post-training/trl-fine-tuning', name: 'TRL', category: 'Post-Training' },
|
|
41
|
+
{ id: '06-post-training/openrlhf', name: 'OpenRLHF', category: 'Post-Training' },
|
|
42
|
+
{ id: '06-post-training/simpo', name: 'SimPO', category: 'Post-Training' },
|
|
43
|
+
// Fine-Tuning
|
|
44
|
+
{ id: '03-fine-tuning/axolotl', name: 'Axolotl', category: 'Fine-Tuning' },
|
|
45
|
+
{ id: '03-fine-tuning/unsloth', name: 'Unsloth', category: 'Fine-Tuning' },
|
|
46
|
+
{ id: '03-fine-tuning/torchtune', name: 'Torchtune', category: 'Fine-Tuning' },
|
|
47
|
+
// Inference
|
|
48
|
+
{ id: '12-inference-serving/vllm', name: 'vLLM', category: 'Inference' },
|
|
49
|
+
{ id: '12-inference-serving/sglang', name: 'SGLang', category: 'Inference' },
|
|
50
|
+
{ id: '12-inference-serving/tensorrt-llm', name: 'TensorRT-LLM', category: 'Inference' },
|
|
51
|
+
// Training
|
|
52
|
+
{ id: '08-distributed-training/deepspeed', name: 'DeepSpeed', category: 'Training' },
|
|
53
|
+
{ id: '08-distributed-training/fsdp', name: 'FSDP', category: 'Training' },
|
|
54
|
+
{ id: '01-model-architecture/torchtitan', name: 'TorchTitan', category: 'Architecture' },
|
|
55
|
+
// Optimization
|
|
56
|
+
{ id: '10-optimization/flash-attention', name: 'Flash Attention', category: 'Optimization' },
|
|
57
|
+
{ id: '10-optimization/gptq', name: 'GPTQ', category: 'Optimization' },
|
|
58
|
+
// Tools
|
|
59
|
+
{ id: '13-mlops/wandb', name: 'Weights & Biases', category: 'MLOps' },
|
|
60
|
+
{ id: '11-evaluation/lm-eval-harness', name: 'lm-eval-harness', category: 'Evaluation' },
|
|
61
|
+
{ id: '16-prompt-engineering/dspy', name: 'DSPy', category: 'Prompting' },
|
|
62
|
+
{ id: '15-rag/chroma', name: 'Chroma', category: 'RAG' },
|
|
63
|
+
// Paper Writing
|
|
64
|
+
{ id: '20-ml-paper-writing', name: 'ML Paper Writing', category: 'Writing' },
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Quick start bundle - essential skills including paper writing
|
|
69
|
+
*/
|
|
70
|
+
export const QUICK_START_SKILLS = [
|
|
71
|
+
'06-post-training/grpo-rl-training',
|
|
72
|
+
'06-post-training/verl',
|
|
73
|
+
'06-post-training/trl-fine-tuning',
|
|
74
|
+
'03-fine-tuning/axolotl',
|
|
75
|
+
'03-fine-tuning/unsloth',
|
|
76
|
+
'12-inference-serving/vllm',
|
|
77
|
+
'12-inference-serving/sglang',
|
|
78
|
+
'08-distributed-training/deepspeed',
|
|
79
|
+
'10-optimization/flash-attention',
|
|
80
|
+
'13-mlops/wandb',
|
|
81
|
+
'11-evaluation/lm-eval-harness',
|
|
82
|
+
'16-prompt-engineering/dspy',
|
|
83
|
+
'15-rag/chroma',
|
|
84
|
+
'20-ml-paper-writing',
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get total skill count
|
|
89
|
+
*/
|
|
90
|
+
export function getTotalSkillCount() {
|
|
91
|
+
return CATEGORIES.reduce((sum, cat) => sum + cat.skills, 0);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Ask main menu action after agent detection
|
|
96
|
+
*/
|
|
97
|
+
export async function askMainMenuAction() {
|
|
98
|
+
console.log();
|
|
99
|
+
const { action } = await inquirer.prompt([
|
|
100
|
+
{
|
|
101
|
+
type: 'list',
|
|
102
|
+
name: 'action',
|
|
103
|
+
message: ' ',
|
|
104
|
+
choices: [
|
|
105
|
+
{ name: 'Install new skills', value: 'install' },
|
|
106
|
+
{ name: 'View installed skills', value: 'view' },
|
|
107
|
+
{ name: 'Update all skills', value: 'update' },
|
|
108
|
+
new inquirer.Separator(' '),
|
|
109
|
+
{ name: chalk.dim('Exit'), value: 'exit' },
|
|
110
|
+
],
|
|
111
|
+
prefix: ' ',
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
114
|
+
return action;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Ask what to install
|
|
119
|
+
*/
|
|
120
|
+
export async function askInstallChoice() {
|
|
121
|
+
const totalSkills = getTotalSkillCount();
|
|
122
|
+
|
|
123
|
+
console.log();
|
|
124
|
+
console.log(chalk.dim(' What would you like to install?'));
|
|
125
|
+
console.log();
|
|
126
|
+
|
|
127
|
+
const { choice } = await inquirer.prompt([
|
|
128
|
+
{
|
|
129
|
+
type: 'list',
|
|
130
|
+
name: 'choice',
|
|
131
|
+
message: ' ',
|
|
132
|
+
choices: [
|
|
133
|
+
{
|
|
134
|
+
name: `Everything ${chalk.dim(totalSkills + ' skills')}`,
|
|
135
|
+
value: 'everything',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: `Quick start ${chalk.dim(QUICK_START_SKILLS.length + ' essential skills')}`,
|
|
139
|
+
value: 'quickstart',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: `Select categories ${chalk.dim('Choose by category')}`,
|
|
143
|
+
value: 'categories',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: `Select individual skills ${chalk.dim('Pick specific skills')}`,
|
|
147
|
+
value: 'individual',
|
|
148
|
+
},
|
|
149
|
+
new inquirer.Separator(' '),
|
|
150
|
+
{
|
|
151
|
+
name: chalk.dim('← Back'),
|
|
152
|
+
value: 'back',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
prefix: ' ',
|
|
156
|
+
},
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
return choice;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Ask which categories to install
|
|
164
|
+
*/
|
|
165
|
+
export async function askCategories() {
|
|
166
|
+
console.log();
|
|
167
|
+
console.log(chalk.dim(' Select categories:'));
|
|
168
|
+
console.log(chalk.dim(' (Space to select, Enter to confirm)'));
|
|
169
|
+
console.log();
|
|
170
|
+
|
|
171
|
+
const { categories } = await inquirer.prompt([
|
|
172
|
+
{
|
|
173
|
+
type: 'checkbox',
|
|
174
|
+
name: 'categories',
|
|
175
|
+
message: ' ',
|
|
176
|
+
choices: CATEGORIES.map(cat => ({
|
|
177
|
+
name: `${cat.name.padEnd(22)} ${chalk.dim((cat.skills + '').padStart(2) + ' skills')}`,
|
|
178
|
+
value: cat.id,
|
|
179
|
+
short: cat.name,
|
|
180
|
+
})),
|
|
181
|
+
prefix: ' ',
|
|
182
|
+
pageSize: 12,
|
|
183
|
+
},
|
|
184
|
+
]);
|
|
185
|
+
|
|
186
|
+
if (categories.length === 0) {
|
|
187
|
+
console.log();
|
|
188
|
+
const { action } = await inquirer.prompt([
|
|
189
|
+
{
|
|
190
|
+
type: 'list',
|
|
191
|
+
name: 'action',
|
|
192
|
+
message: chalk.yellow('No categories selected'),
|
|
193
|
+
choices: [
|
|
194
|
+
{ name: 'Try again', value: 'retry' },
|
|
195
|
+
{ name: chalk.dim('← Back'), value: 'back' },
|
|
196
|
+
],
|
|
197
|
+
prefix: ' ',
|
|
198
|
+
},
|
|
199
|
+
]);
|
|
200
|
+
return { categories: [], action };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { categories, action: 'confirm' };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Ask which individual skills to install
|
|
208
|
+
*/
|
|
209
|
+
export async function askIndividualSkills() {
|
|
210
|
+
console.log();
|
|
211
|
+
console.log(chalk.dim(' Select skills:'));
|
|
212
|
+
console.log(chalk.dim(' (Space to select, Enter to confirm)'));
|
|
213
|
+
console.log();
|
|
214
|
+
|
|
215
|
+
const { skills } = await inquirer.prompt([
|
|
216
|
+
{
|
|
217
|
+
type: 'checkbox',
|
|
218
|
+
name: 'skills',
|
|
219
|
+
message: ' ',
|
|
220
|
+
choices: INDIVIDUAL_SKILLS.map(skill => ({
|
|
221
|
+
name: `${skill.name.padEnd(20)} ${chalk.dim(skill.category)}`,
|
|
222
|
+
value: skill.id,
|
|
223
|
+
short: skill.name,
|
|
224
|
+
})),
|
|
225
|
+
prefix: ' ',
|
|
226
|
+
pageSize: 15,
|
|
227
|
+
},
|
|
228
|
+
]);
|
|
229
|
+
|
|
230
|
+
if (skills.length === 0) {
|
|
231
|
+
console.log();
|
|
232
|
+
const { action } = await inquirer.prompt([
|
|
233
|
+
{
|
|
234
|
+
type: 'list',
|
|
235
|
+
name: 'action',
|
|
236
|
+
message: chalk.yellow('No skills selected'),
|
|
237
|
+
choices: [
|
|
238
|
+
{ name: 'Try again', value: 'retry' },
|
|
239
|
+
{ name: chalk.dim('← Back'), value: 'back' },
|
|
240
|
+
],
|
|
241
|
+
prefix: ' ',
|
|
242
|
+
},
|
|
243
|
+
]);
|
|
244
|
+
return { skills: [], action };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return { skills, action: 'confirm' };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Ask for confirmation with description
|
|
252
|
+
*/
|
|
253
|
+
export async function askConfirmation(skillCount, agents, selectedCategories, selectedSkills, installType) {
|
|
254
|
+
console.log();
|
|
255
|
+
console.log(chalk.white(' Installation Summary'));
|
|
256
|
+
console.log(chalk.dim(' ─────────────────────────────────────────────────────'));
|
|
257
|
+
console.log();
|
|
258
|
+
|
|
259
|
+
// What's being installed
|
|
260
|
+
console.log(` ${chalk.white('Skills:')} ${skillCount} skills`);
|
|
261
|
+
console.log(` ${chalk.white('Agents:')} ${agents.map(a => a.name).join(', ')}`);
|
|
262
|
+
console.log();
|
|
263
|
+
|
|
264
|
+
// Description based on install type
|
|
265
|
+
if (installType === 'everything') {
|
|
266
|
+
console.log(chalk.dim(' All 20 categories including:'));
|
|
267
|
+
console.log(chalk.dim(' Post-Training, Fine-Tuning, Inference, Distributed Training,'));
|
|
268
|
+
console.log(chalk.dim(' Optimization, Evaluation, MLOps, RAG, Agents, Paper Writing...'));
|
|
269
|
+
} else if (installType === 'quickstart') {
|
|
270
|
+
console.log(chalk.dim(' Essential skills for AI research:'));
|
|
271
|
+
console.log(chalk.dim(' • GRPO, verl, TRL for post-training'));
|
|
272
|
+
console.log(chalk.dim(' • Axolotl, Unsloth for fine-tuning'));
|
|
273
|
+
console.log(chalk.dim(' • vLLM, SGLang for inference'));
|
|
274
|
+
console.log(chalk.dim(' • DeepSpeed, Flash Attention for training'));
|
|
275
|
+
console.log(chalk.dim(' • W&B, lm-eval, DSPy, Chroma'));
|
|
276
|
+
console.log(chalk.dim(' • ML Paper Writing for NeurIPS/ICML'));
|
|
277
|
+
} else if (selectedCategories && selectedCategories.length > 0) {
|
|
278
|
+
const catNames = CATEGORIES
|
|
279
|
+
.filter(c => selectedCategories.includes(c.id))
|
|
280
|
+
.map(c => c.name);
|
|
281
|
+
console.log(chalk.dim(' Selected categories:'));
|
|
282
|
+
catNames.forEach(name => console.log(chalk.dim(` • ${name}`)));
|
|
283
|
+
} else if (selectedSkills && selectedSkills.length > 0) {
|
|
284
|
+
console.log(chalk.dim(' Selected skills:'));
|
|
285
|
+
const skillNames = INDIVIDUAL_SKILLS
|
|
286
|
+
.filter(s => selectedSkills.includes(s.id))
|
|
287
|
+
.map(s => s.name)
|
|
288
|
+
.slice(0, 8);
|
|
289
|
+
skillNames.forEach(name => console.log(chalk.dim(` • ${name}`)));
|
|
290
|
+
if (selectedSkills.length > 8) {
|
|
291
|
+
console.log(chalk.dim(` • ...and ${selectedSkills.length - 8} more`));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
console.log();
|
|
296
|
+
console.log(chalk.dim(' ─────────────────────────────────────────────────────'));
|
|
297
|
+
console.log();
|
|
298
|
+
|
|
299
|
+
const { action } = await inquirer.prompt([
|
|
300
|
+
{
|
|
301
|
+
type: 'list',
|
|
302
|
+
name: 'action',
|
|
303
|
+
message: ' ',
|
|
304
|
+
choices: [
|
|
305
|
+
{ name: chalk.green('Install'), value: 'confirm' },
|
|
306
|
+
{ name: chalk.dim('← Back'), value: 'back' },
|
|
307
|
+
{ name: chalk.dim('Exit'), value: 'exit' },
|
|
308
|
+
],
|
|
309
|
+
prefix: ' ',
|
|
310
|
+
},
|
|
311
|
+
]);
|
|
312
|
+
|
|
313
|
+
return action;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Ask which agents to install to
|
|
318
|
+
*/
|
|
319
|
+
export async function askSelectAgents(agents) {
|
|
320
|
+
console.log();
|
|
321
|
+
console.log(chalk.dim(' Install to which agents?'));
|
|
322
|
+
console.log();
|
|
323
|
+
|
|
324
|
+
const { selection } = await inquirer.prompt([
|
|
325
|
+
{
|
|
326
|
+
type: 'list',
|
|
327
|
+
name: 'selection',
|
|
328
|
+
message: ' ',
|
|
329
|
+
choices: [
|
|
330
|
+
{ name: `All detected agents (${agents.length})`, value: 'all' },
|
|
331
|
+
{ name: 'Select specific agents', value: 'select' },
|
|
332
|
+
new inquirer.Separator(' '),
|
|
333
|
+
{ name: chalk.dim('← Back'), value: 'back' },
|
|
334
|
+
],
|
|
335
|
+
prefix: ' ',
|
|
336
|
+
},
|
|
337
|
+
]);
|
|
338
|
+
|
|
339
|
+
if (selection === 'back') {
|
|
340
|
+
return { agents: [], action: 'back' };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (selection === 'all') {
|
|
344
|
+
return { agents, action: 'confirm' };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Select specific agents
|
|
348
|
+
console.log();
|
|
349
|
+
const { selectedAgents } = await inquirer.prompt([
|
|
350
|
+
{
|
|
351
|
+
type: 'checkbox',
|
|
352
|
+
name: 'selectedAgents',
|
|
353
|
+
message: ' ',
|
|
354
|
+
choices: agents.map(agent => ({
|
|
355
|
+
name: `${agent.name.padEnd(14)} ${chalk.dim(agent.path)}`,
|
|
356
|
+
value: agent,
|
|
357
|
+
checked: true,
|
|
358
|
+
})),
|
|
359
|
+
prefix: ' ',
|
|
360
|
+
},
|
|
361
|
+
]);
|
|
362
|
+
|
|
363
|
+
if (selectedAgents.length === 0) {
|
|
364
|
+
console.log();
|
|
365
|
+
const { action } = await inquirer.prompt([
|
|
366
|
+
{
|
|
367
|
+
type: 'list',
|
|
368
|
+
name: 'action',
|
|
369
|
+
message: chalk.yellow('No agents selected'),
|
|
370
|
+
choices: [
|
|
371
|
+
{ name: 'Try again', value: 'retry' },
|
|
372
|
+
{ name: chalk.dim('← Back'), value: 'back' },
|
|
373
|
+
],
|
|
374
|
+
prefix: ' ',
|
|
375
|
+
},
|
|
376
|
+
]);
|
|
377
|
+
return { agents: [], action };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return { agents: selectedAgents, action: 'confirm' };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Ask what to do after viewing/updating
|
|
385
|
+
*/
|
|
386
|
+
export async function askAfterAction() {
|
|
387
|
+
console.log();
|
|
388
|
+
const { action } = await inquirer.prompt([
|
|
389
|
+
{
|
|
390
|
+
type: 'list',
|
|
391
|
+
name: 'action',
|
|
392
|
+
message: ' ',
|
|
393
|
+
choices: [
|
|
394
|
+
{ name: '← Back to main menu', value: 'back' },
|
|
395
|
+
{ name: chalk.dim('Exit'), value: 'exit' },
|
|
396
|
+
],
|
|
397
|
+
prefix: ' ',
|
|
398
|
+
},
|
|
399
|
+
]);
|
|
400
|
+
return action;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Parse command line arguments
|
|
405
|
+
*/
|
|
406
|
+
export function parseArgs(args) {
|
|
407
|
+
const options = {
|
|
408
|
+
command: null,
|
|
409
|
+
all: false,
|
|
410
|
+
category: null,
|
|
411
|
+
skill: null,
|
|
412
|
+
agent: null,
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
for (let i = 0; i < args.length; i++) {
|
|
416
|
+
const arg = args[i];
|
|
417
|
+
|
|
418
|
+
if (arg === 'install') {
|
|
419
|
+
options.command = 'install';
|
|
420
|
+
} else if (arg === 'list') {
|
|
421
|
+
options.command = 'list';
|
|
422
|
+
} else if (arg === 'update') {
|
|
423
|
+
options.command = 'update';
|
|
424
|
+
} else if (arg === '--all' || arg === '-a') {
|
|
425
|
+
options.all = true;
|
|
426
|
+
} else if (arg === '--agent' && args[i + 1]) {
|
|
427
|
+
options.agent = args[++i];
|
|
428
|
+
} else if (arg === '--category' && args[i + 1]) {
|
|
429
|
+
options.category = args[++i];
|
|
430
|
+
} else if (!arg.startsWith('-') && !options.command) {
|
|
431
|
+
options.skill = arg;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return options;
|
|
436
|
+
}
|