proagents 1.0.10 → 1.0.11

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/proagents.js CHANGED
@@ -6,6 +6,9 @@ import { featureCommand } from '../lib/commands/feature.js';
6
6
  import { fixCommand } from '../lib/commands/fix.js';
7
7
  import { statusCommand } from '../lib/commands/status.js';
8
8
  import { helpCommand } from '../lib/commands/help.js';
9
+ import { aiAddCommand, aiListCommand, aiRemoveCommand } from '../lib/commands/ai.js';
10
+ import { uninstallCommand } from '../lib/commands/uninstall.js';
11
+ import { configListCommand, configShowCommand, configEditCommand, configSetCommand, configGetCommand, configSetupCommand, configCustomizeCommand } from '../lib/commands/config.js';
9
12
  import { readFileSync } from 'fs';
10
13
  import { fileURLToPath } from 'url';
11
14
  import { dirname, join } from 'path';
@@ -81,6 +84,73 @@ program
81
84
  console.log('GitHub: https://github.com/prakashpro3/proAgents\n');
82
85
  });
83
86
 
87
+ // AI platform commands
88
+ const ai = program
89
+ .command('ai')
90
+ .description('Manage AI platform instruction files');
91
+
92
+ ai
93
+ .command('add')
94
+ .description('Add more AI platforms')
95
+ .action(aiAddCommand);
96
+
97
+ ai
98
+ .command('list')
99
+ .description('List installed AI platforms')
100
+ .action(aiListCommand);
101
+
102
+ ai
103
+ .command('remove')
104
+ .description('Remove AI platforms from config')
105
+ .action(aiRemoveCommand);
106
+
107
+ // Config commands
108
+ const config = program
109
+ .command('config')
110
+ .description('Manage ProAgents configuration');
111
+
112
+ config
113
+ .command('list')
114
+ .description('Show all configurable options')
115
+ .action(configListCommand);
116
+
117
+ config
118
+ .command('show')
119
+ .description('Show current config values')
120
+ .action(configShowCommand);
121
+
122
+ config
123
+ .command('edit')
124
+ .description('Info on how to edit config')
125
+ .action(configEditCommand);
126
+
127
+ config
128
+ .command('set <key> <value>')
129
+ .description('Set a config value (e.g., checkpoints.after_analysis true)')
130
+ .action(configSetCommand);
131
+
132
+ config
133
+ .command('get <key>')
134
+ .description('Get a config value (e.g., checkpoints.after_analysis)')
135
+ .action(configGetCommand);
136
+
137
+ config
138
+ .command('setup')
139
+ .description('Interactive configuration wizard')
140
+ .action(configSetupCommand);
141
+
142
+ config
143
+ .command('customize')
144
+ .description('Copy templates to create custom configurations')
145
+ .action(configCustomizeCommand);
146
+
147
+ // Uninstall command
148
+ program
149
+ .command('uninstall')
150
+ .description('Remove ProAgents from current project')
151
+ .option('-f, --force', 'Skip confirmation prompt')
152
+ .action(uninstallCommand);
153
+
84
154
  // Help command (custom)
85
155
  program
86
156
  .command('commands')
@@ -0,0 +1,385 @@
1
+ import { existsSync, cpSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { createInterface } from 'readline';
5
+ import chalk from 'chalk';
6
+ import yaml from 'js-yaml';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ // AI Platform definitions grouped by type
12
+ export const AI_PLATFORMS = {
13
+ ide: {
14
+ label: 'IDE-based AI Assistants',
15
+ platforms: [
16
+ { id: 'claude', name: 'Claude Code', file: 'CLAUDE.md', desc: 'Anthropic Claude in terminal/IDE' },
17
+ { id: 'cursor', name: 'Cursor', file: '.cursorrules', desc: 'Cursor AI IDE' },
18
+ { id: 'windsurf', name: 'Windsurf', file: '.windsurfrules', desc: 'Codeium Windsurf IDE' },
19
+ { id: 'copilot', name: 'GitHub Copilot', file: '.github/copilot-instructions.md', desc: 'GitHub Copilot' },
20
+ { id: 'kiro', name: 'AWS Kiro', file: 'KIRO.md', desc: 'AWS Kiro IDE' },
21
+ { id: 'antigravity', name: 'Antigravity', file: 'ANTIGRAVITY.md', desc: 'Antigravity IDE (Gemini/Claude)' },
22
+ ]
23
+ },
24
+ web: {
25
+ label: 'Web-based AI Platforms',
26
+ platforms: [
27
+ { id: 'chatgpt', name: 'ChatGPT / Codex', file: 'CHATGPT.md', desc: 'OpenAI ChatGPT' },
28
+ { id: 'gemini', name: 'Gemini', file: 'GEMINI.md', desc: 'Google Gemini' },
29
+ { id: 'replit', name: 'Replit AI', file: 'REPLIT.md', desc: 'Replit Ghostwriter' },
30
+ { id: 'bolt', name: 'Bolt.new', file: 'BOLT.md', desc: 'StackBlitz Bolt' },
31
+ { id: 'lovable', name: 'Lovable', file: 'LOVABLE.md', desc: 'Lovable (GPT Engineer)' },
32
+ { id: 'groq', name: 'Groq', file: 'GROQ.md', desc: 'Groq fast inference' },
33
+ ]
34
+ }
35
+ };
36
+
37
+ // Get all platforms as flat array
38
+ export function getAllPlatforms() {
39
+ return [
40
+ ...AI_PLATFORMS.ide.platforms,
41
+ ...AI_PLATFORMS.web.platforms,
42
+ ];
43
+ }
44
+
45
+ // Get platform by ID
46
+ export function getPlatformById(id) {
47
+ return getAllPlatforms().find(p => p.id === id);
48
+ }
49
+
50
+ /**
51
+ * Interactive platform selection using readline
52
+ */
53
+ export async function selectPlatforms() {
54
+ const rl = createInterface({
55
+ input: process.stdin,
56
+ output: process.stdout
57
+ });
58
+
59
+ const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
60
+
61
+ console.log('\n' + chalk.bold('Which AI platform(s) do you use?'));
62
+ console.log(chalk.gray('(Enter numbers separated by commas, or "all" for all platforms)\n'));
63
+
64
+ let index = 1;
65
+ const indexMap = {};
66
+
67
+ // IDE-based platforms
68
+ console.log(chalk.cyan.bold(` ${AI_PLATFORMS.ide.label}:`));
69
+ for (const platform of AI_PLATFORMS.ide.platforms) {
70
+ console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`));
71
+ indexMap[index] = platform.id;
72
+ index++;
73
+ }
74
+
75
+ console.log('');
76
+
77
+ // Web-based platforms
78
+ console.log(chalk.cyan.bold(` ${AI_PLATFORMS.web.label}:`));
79
+ for (const platform of AI_PLATFORMS.web.platforms) {
80
+ console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`));
81
+ indexMap[index] = platform.id;
82
+ index++;
83
+ }
84
+
85
+ console.log('');
86
+
87
+ const answer = await question(chalk.yellow('Your selection (e.g., 1,2,3 or "all"): '));
88
+ rl.close();
89
+
90
+ if (answer.toLowerCase() === 'all') {
91
+ return getAllPlatforms().map(p => p.id);
92
+ }
93
+
94
+ const selected = [];
95
+ const numbers = answer.split(',').map(s => parseInt(s.trim())).filter(n => !isNaN(n));
96
+
97
+ for (const num of numbers) {
98
+ if (indexMap[num]) {
99
+ selected.push(indexMap[num]);
100
+ }
101
+ }
102
+
103
+ return selected.length > 0 ? selected : ['claude']; // Default to Claude if nothing selected
104
+ }
105
+
106
+ /**
107
+ * Copy AI instruction files for selected platforms
108
+ */
109
+ export function copyPlatformFiles(selectedIds, sourceDir, targetDir) {
110
+ const results = { created: [], skipped: [], failed: [] };
111
+
112
+ for (const id of selectedIds) {
113
+ const platform = getPlatformById(id);
114
+ if (!platform) continue;
115
+
116
+ const sourcePath = join(sourceDir, platform.file);
117
+ let targetPath;
118
+
119
+ // Handle .github/copilot-instructions.md specially
120
+ if (platform.file.startsWith('.github/')) {
121
+ const githubDir = join(targetDir, '.github');
122
+ targetPath = join(targetDir, platform.file);
123
+
124
+ if (!existsSync(githubDir)) {
125
+ mkdirSync(githubDir, { recursive: true });
126
+ }
127
+ } else {
128
+ targetPath = join(targetDir, platform.file);
129
+ }
130
+
131
+ try {
132
+ if (existsSync(sourcePath)) {
133
+ if (!existsSync(targetPath)) {
134
+ cpSync(sourcePath, targetPath);
135
+ results.created.push(platform.name);
136
+ } else {
137
+ results.skipped.push(platform.name);
138
+ }
139
+ }
140
+ } catch (error) {
141
+ results.failed.push(platform.name);
142
+ }
143
+ }
144
+
145
+ return results;
146
+ }
147
+
148
+ /**
149
+ * Save selected platforms to config
150
+ */
151
+ export function savePlatformConfig(selectedIds, configPath) {
152
+ let config = {};
153
+
154
+ if (existsSync(configPath)) {
155
+ try {
156
+ const content = readFileSync(configPath, 'utf-8');
157
+ config = yaml.load(content) || {};
158
+ } catch {
159
+ config = {};
160
+ }
161
+ }
162
+
163
+ config.ai_platforms = selectedIds;
164
+
165
+ const yamlContent = yaml.dump(config, { indent: 2, lineWidth: 120 });
166
+ writeFileSync(configPath, yamlContent);
167
+ }
168
+
169
+ /**
170
+ * Load selected platforms from config
171
+ */
172
+ export function loadPlatformConfig(configPath) {
173
+ if (!existsSync(configPath)) return [];
174
+
175
+ try {
176
+ const content = readFileSync(configPath, 'utf-8');
177
+ const config = yaml.load(content) || {};
178
+ return config.ai_platforms || [];
179
+ } catch {
180
+ return [];
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Show available platforms that can be added
186
+ */
187
+ export function showAvailablePlatforms(currentIds) {
188
+ console.log('\n' + chalk.bold('Available AI Platforms:\n'));
189
+
190
+ let index = 1;
191
+ const available = [];
192
+
193
+ // IDE-based platforms
194
+ console.log(chalk.cyan.bold(` ${AI_PLATFORMS.ide.label}:`));
195
+ for (const platform of AI_PLATFORMS.ide.platforms) {
196
+ const status = currentIds.includes(platform.id)
197
+ ? chalk.green(' ✓ (installed)')
198
+ : chalk.gray(' (not installed)');
199
+ console.log(chalk.white(` ${index}. ${platform.name}`) + status);
200
+ if (!currentIds.includes(platform.id)) {
201
+ available.push({ index, platform });
202
+ }
203
+ index++;
204
+ }
205
+
206
+ console.log('');
207
+
208
+ // Web-based platforms
209
+ console.log(chalk.cyan.bold(` ${AI_PLATFORMS.web.label}:`));
210
+ for (const platform of AI_PLATFORMS.web.platforms) {
211
+ const status = currentIds.includes(platform.id)
212
+ ? chalk.green(' ✓ (installed)')
213
+ : chalk.gray(' (not installed)');
214
+ console.log(chalk.white(` ${index}. ${platform.name}`) + status);
215
+ if (!currentIds.includes(platform.id)) {
216
+ available.push({ index, platform });
217
+ }
218
+ index++;
219
+ }
220
+
221
+ return available;
222
+ }
223
+
224
+ /**
225
+ * Command: proagents ai add
226
+ */
227
+ export async function aiAddCommand() {
228
+ const targetDir = process.cwd();
229
+ const proagentsDir = join(targetDir, 'proagents');
230
+ const sourceDir = join(__dirname, '..', '..', 'proagents');
231
+ const configPath = join(proagentsDir, 'proagents.config.yaml');
232
+
233
+ // Check if proagents is initialized
234
+ if (!existsSync(proagentsDir)) {
235
+ console.log(chalk.red('\n✗ ProAgents not initialized. Run "proagents init" first.\n'));
236
+ return;
237
+ }
238
+
239
+ // Load current platforms
240
+ const currentIds = loadPlatformConfig(configPath);
241
+
242
+ console.log(chalk.bold.blue('\nProAgents - Add AI Platform'));
243
+ console.log(chalk.blue('===========================\n'));
244
+
245
+ // Show available platforms
246
+ const available = showAvailablePlatforms(currentIds);
247
+
248
+ if (available.length === 0) {
249
+ console.log(chalk.green('\n✓ All AI platforms are already installed!\n'));
250
+ return;
251
+ }
252
+
253
+ const rl = createInterface({
254
+ input: process.stdin,
255
+ output: process.stdout
256
+ });
257
+
258
+ const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
259
+
260
+ console.log('');
261
+ const answer = await question(chalk.yellow('Enter platform number(s) to add (e.g., 1,2,3): '));
262
+ rl.close();
263
+
264
+ const numbers = answer.split(',').map(s => parseInt(s.trim())).filter(n => !isNaN(n));
265
+ const toAdd = [];
266
+
267
+ for (const num of numbers) {
268
+ const found = available.find(a => a.index === num);
269
+ if (found) {
270
+ toAdd.push(found.platform.id);
271
+ }
272
+ }
273
+
274
+ if (toAdd.length === 0) {
275
+ console.log(chalk.yellow('\nNo platforms selected.\n'));
276
+ return;
277
+ }
278
+
279
+ // Copy files for new platforms
280
+ const results = copyPlatformFiles(toAdd, sourceDir, targetDir);
281
+
282
+ // Update config
283
+ const newIds = [...currentIds, ...toAdd];
284
+ savePlatformConfig(newIds, configPath);
285
+
286
+ // Show results
287
+ if (results.created.length > 0) {
288
+ console.log(chalk.green(`\n✓ Added: ${results.created.join(', ')}`));
289
+ }
290
+ if (results.skipped.length > 0) {
291
+ console.log(chalk.yellow(`⚠️ Already exist: ${results.skipped.join(', ')}`));
292
+ }
293
+
294
+ console.log(chalk.gray('\nAI instruction files copied to project root.'));
295
+ console.log(chalk.gray('Config updated in proagents/proagents.config.yaml\n'));
296
+ }
297
+
298
+ /**
299
+ * Command: proagents ai list
300
+ */
301
+ export function aiListCommand() {
302
+ const targetDir = process.cwd();
303
+ const proagentsDir = join(targetDir, 'proagents');
304
+ const configPath = join(proagentsDir, 'proagents.config.yaml');
305
+
306
+ const currentIds = loadPlatformConfig(configPath);
307
+
308
+ console.log(chalk.bold.blue('\nProAgents - AI Platforms'));
309
+ console.log(chalk.blue('========================\n'));
310
+
311
+ showAvailablePlatforms(currentIds);
312
+ console.log('');
313
+ }
314
+
315
+ /**
316
+ * Command: proagents ai remove
317
+ */
318
+ export async function aiRemoveCommand() {
319
+ const targetDir = process.cwd();
320
+ const proagentsDir = join(targetDir, 'proagents');
321
+ const configPath = join(proagentsDir, 'proagents.config.yaml');
322
+
323
+ if (!existsSync(proagentsDir)) {
324
+ console.log(chalk.red('\n✗ ProAgents not initialized.\n'));
325
+ return;
326
+ }
327
+
328
+ const currentIds = loadPlatformConfig(configPath);
329
+
330
+ if (currentIds.length === 0) {
331
+ console.log(chalk.yellow('\nNo AI platforms configured.\n'));
332
+ return;
333
+ }
334
+
335
+ console.log(chalk.bold.blue('\nProAgents - Remove AI Platform'));
336
+ console.log(chalk.blue('==============================\n'));
337
+
338
+ console.log(chalk.cyan('Currently installed platforms:\n'));
339
+
340
+ let index = 1;
341
+ const indexMap = {};
342
+
343
+ for (const id of currentIds) {
344
+ const platform = getPlatformById(id);
345
+ if (platform) {
346
+ console.log(chalk.white(` ${index}. ${platform.name}`));
347
+ indexMap[index] = id;
348
+ index++;
349
+ }
350
+ }
351
+
352
+ const rl = createInterface({
353
+ input: process.stdin,
354
+ output: process.stdout
355
+ });
356
+
357
+ const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
358
+
359
+ console.log('');
360
+ const answer = await question(chalk.yellow('Enter platform number(s) to remove (e.g., 1,2): '));
361
+ rl.close();
362
+
363
+ const numbers = answer.split(',').map(s => parseInt(s.trim())).filter(n => !isNaN(n));
364
+ const toRemove = [];
365
+
366
+ for (const num of numbers) {
367
+ if (indexMap[num]) {
368
+ toRemove.push(indexMap[num]);
369
+ }
370
+ }
371
+
372
+ if (toRemove.length === 0) {
373
+ console.log(chalk.yellow('\nNo platforms selected.\n'));
374
+ return;
375
+ }
376
+
377
+ // Remove from config (don't delete files - user might have customized them)
378
+ const newIds = currentIds.filter(id => !toRemove.includes(id));
379
+ savePlatformConfig(newIds, configPath);
380
+
381
+ const removedNames = toRemove.map(id => getPlatformById(id)?.name).filter(Boolean);
382
+ console.log(chalk.green(`\n✓ Removed from config: ${removedNames.join(', ')}`));
383
+ console.log(chalk.gray('Note: AI instruction files in project root were not deleted.'));
384
+ console.log(chalk.gray('You can manually delete them if needed.\n'));
385
+ }