proagents 1.6.8 → 1.6.9

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.
@@ -1,4 +1,4 @@
1
- import { existsSync, cpSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
1
+ import { existsSync, cpSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'fs';
2
2
  import { join, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { createInterface } from 'readline';
@@ -49,8 +49,9 @@ export function getPlatformById(id) {
49
49
 
50
50
  /**
51
51
  * Interactive platform selection using readline
52
+ * @param {string[]} previouslySelected - Previously selected platforms (from interrupted setup)
52
53
  */
53
- export async function selectPlatforms() {
54
+ export async function selectPlatforms(previouslySelected = []) {
54
55
  const rl = createInterface({
55
56
  input: process.stdin,
56
57
  output: process.stdout
@@ -63,12 +64,16 @@ export async function selectPlatforms() {
63
64
 
64
65
  let index = 1;
65
66
  const indexMap = {};
67
+ const preSelectedIndices = [];
66
68
 
67
69
  // IDE-based platforms
68
70
  console.log(chalk.cyan.bold(` ${AI_PLATFORMS.ide.label}:`));
69
71
  for (const platform of AI_PLATFORMS.ide.platforms) {
70
- console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`));
72
+ const wasSelected = previouslySelected && previouslySelected.includes(platform.id);
73
+ const marker = wasSelected ? chalk.green(' ✓ (previously selected)') : '';
74
+ console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`) + marker);
71
75
  indexMap[index] = platform.id;
76
+ if (wasSelected) preSelectedIndices.push(index);
72
77
  index++;
73
78
  }
74
79
 
@@ -77,16 +82,29 @@ export async function selectPlatforms() {
77
82
  // Web-based platforms
78
83
  console.log(chalk.cyan.bold(` ${AI_PLATFORMS.web.label}:`));
79
84
  for (const platform of AI_PLATFORMS.web.platforms) {
80
- console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`));
85
+ const wasSelected = previouslySelected && previouslySelected.includes(platform.id);
86
+ const marker = wasSelected ? chalk.green(' ✓ (previously selected)') : '';
87
+ console.log(chalk.white(` ${index}. ${platform.name}`) + chalk.gray(` - ${platform.desc}`) + marker);
81
88
  indexMap[index] = platform.id;
89
+ if (wasSelected) preSelectedIndices.push(index);
82
90
  index++;
83
91
  }
84
92
 
85
93
  console.log('');
86
94
 
87
- const answer = await question(chalk.yellow('Your selection (e.g., 1,2,3 or "all"): '));
95
+ // Show default based on previous selection
96
+ const defaultHint = preSelectedIndices.length > 0
97
+ ? `Enter for previous: ${preSelectedIndices.join(',')}`
98
+ : 'e.g., 1,2,3 or "all"';
99
+
100
+ const answer = await question(chalk.yellow(`Your selection (${defaultHint}): `));
88
101
  rl.close();
89
102
 
103
+ // If user just pressed enter and we have previous selections, use them
104
+ if (answer.trim() === '' && preSelectedIndices.length > 0) {
105
+ return previouslySelected;
106
+ }
107
+
90
108
  if (answer.toLowerCase() === 'all') {
91
109
  return getAllPlatforms().map(p => p.id);
92
110
  }
@@ -131,6 +149,46 @@ function extractProagentsSection(content) {
131
149
  return null;
132
150
  }
133
151
 
152
+ /**
153
+ * Remove only ProAgents section from a file, keep user's original content
154
+ * Returns: 'deleted' (file removed), 'cleaned' (section removed), 'skipped' (no ProAgents section)
155
+ */
156
+ function removeProagentsSectionFromFile(filePath) {
157
+ try {
158
+ const content = readFileSync(filePath, 'utf-8');
159
+
160
+ const startIndex = content.indexOf(PROAGENTS_START);
161
+ const endIndex = content.indexOf(PROAGENTS_END);
162
+
163
+ if (startIndex !== -1 && endIndex !== -1) {
164
+ // Has ProAgents section - remove it, keep the rest
165
+ const before = content.substring(0, startIndex).trim();
166
+ const after = content.substring(endIndex + PROAGENTS_END.length).trim();
167
+ const remaining = (before + '\n\n' + after).trim();
168
+
169
+ if (remaining.length === 0) {
170
+ // File only had ProAgents content - delete it
171
+ rmSync(filePath, { force: true });
172
+ return 'deleted';
173
+ } else {
174
+ // File has other content - keep it, remove only ProAgents section
175
+ writeFileSync(filePath, remaining + '\n');
176
+ return 'cleaned';
177
+ }
178
+ } else {
179
+ // No ProAgents markers - file was created by ProAgents (not merged)
180
+ // Check if it's a ProAgents-generated file by looking for ProAgents reference
181
+ if (content.includes('proagents') || content.includes('ProAgents') || content.includes('.proagents/')) {
182
+ rmSync(filePath, { force: true });
183
+ return 'deleted';
184
+ }
185
+ return 'skipped';
186
+ }
187
+ } catch (error) {
188
+ return 'skipped';
189
+ }
190
+ }
191
+
134
192
  /**
135
193
  * Merge ProAgents instructions with existing file content
136
194
  * - If file doesn't exist: create with ProAgents content
@@ -247,6 +305,51 @@ export function loadPlatformConfig(configPath) {
247
305
  }
248
306
  }
249
307
 
308
+ /**
309
+ * Check if a file contains ProAgents content
310
+ */
311
+ function hasProagentsContent(filePath) {
312
+ try {
313
+ const content = readFileSync(filePath, 'utf-8');
314
+ // Check for ProAgents markers or references
315
+ return content.includes(PROAGENTS_START) ||
316
+ content.includes('.proagents/') ||
317
+ content.includes('ProAgents Commands');
318
+ } catch {
319
+ return false;
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Detect installed platforms by checking for actual files with ProAgents content
325
+ * Only counts as installed if the file has ProAgents-related content
326
+ */
327
+ export function detectInstalledPlatforms(targetDir) {
328
+ const installed = [];
329
+
330
+ for (const platform of getAllPlatforms()) {
331
+ const filePath = join(targetDir, platform.file);
332
+ if (existsSync(filePath) && hasProagentsContent(filePath)) {
333
+ installed.push(platform.id);
334
+ }
335
+ }
336
+
337
+ return installed;
338
+ }
339
+
340
+ /**
341
+ * Get installed platforms - combines config and file detection
342
+ * Returns platforms that are either in config OR have files present
343
+ */
344
+ export function getInstalledPlatforms(targetDir, configPath) {
345
+ const fromConfig = loadPlatformConfig(configPath);
346
+ const fromFiles = detectInstalledPlatforms(targetDir);
347
+
348
+ // Merge both sources, remove duplicates
349
+ const combined = [...new Set([...fromConfig, ...fromFiles])];
350
+ return combined;
351
+ }
352
+
250
353
  /**
251
354
  * Show available platforms that can be added
252
355
  */
@@ -294,7 +397,7 @@ export async function aiAddCommand() {
294
397
  const targetDir = process.cwd();
295
398
  const proagentsDir = join(targetDir, '.proagents');
296
399
  const sourceDir = join(__dirname, '..', '..', '.proagents');
297
- const configPath = join(proagentsDir, 'proagents.config.yaml');
400
+ const configPath = join(targetDir, 'proagents.config.yaml');
298
401
 
299
402
  // Check if proagents is initialized
300
403
  if (!existsSync(proagentsDir)) {
@@ -302,8 +405,8 @@ export async function aiAddCommand() {
302
405
  return;
303
406
  }
304
407
 
305
- // Load current platforms
306
- const currentIds = loadPlatformConfig(configPath);
408
+ // Detect from both config AND actual files
409
+ const currentIds = getInstalledPlatforms(targetDir, configPath);
307
410
 
308
411
  console.log(chalk.bold.blue('\nProAgents - Add AI Platform'));
309
412
  console.log(chalk.blue('===========================\n'));
@@ -361,7 +464,7 @@ export async function aiAddCommand() {
361
464
  }
362
465
 
363
466
  console.log(chalk.gray('\nAI instruction files added to project root.'));
364
- console.log(chalk.gray('Config updated in .proagents/proagents.config.yaml\n'));
467
+ console.log(chalk.gray('Config updated in proagents.config.yaml\n'));
365
468
  }
366
469
 
367
470
  /**
@@ -370,9 +473,10 @@ export async function aiAddCommand() {
370
473
  export function aiListCommand() {
371
474
  const targetDir = process.cwd();
372
475
  const proagentsDir = join(targetDir, '.proagents');
373
- const configPath = join(proagentsDir, 'proagents.config.yaml');
476
+ const configPath = join(targetDir, 'proagents.config.yaml');
374
477
 
375
- const currentIds = loadPlatformConfig(configPath);
478
+ // Detect from both config AND actual files
479
+ const currentIds = getInstalledPlatforms(targetDir, configPath);
376
480
 
377
481
  console.log(chalk.bold.blue('\nProAgents - AI Platforms'));
378
482
  console.log(chalk.blue('========================\n'));
@@ -387,17 +491,18 @@ export function aiListCommand() {
387
491
  export async function aiRemoveCommand() {
388
492
  const targetDir = process.cwd();
389
493
  const proagentsDir = join(targetDir, '.proagents');
390
- const configPath = join(proagentsDir, 'proagents.config.yaml');
494
+ const configPath = join(targetDir, 'proagents.config.yaml');
391
495
 
392
496
  if (!existsSync(proagentsDir)) {
393
497
  console.log(chalk.red('\n✗ ProAgents not initialized.\n'));
394
498
  return;
395
499
  }
396
500
 
397
- const currentIds = loadPlatformConfig(configPath);
501
+ // Detect from both config AND actual files
502
+ const currentIds = getInstalledPlatforms(targetDir, configPath);
398
503
 
399
504
  if (currentIds.length === 0) {
400
- console.log(chalk.yellow('\nNo AI platforms configured.\n'));
505
+ console.log(chalk.yellow('\nNo AI platforms installed.\n'));
401
506
  return;
402
507
  }
403
508
 
@@ -443,12 +548,36 @@ export async function aiRemoveCommand() {
443
548
  return;
444
549
  }
445
550
 
446
- // Remove from config (don't delete files - user might have customized them)
551
+ // Remove from config
447
552
  const newIds = currentIds.filter(id => !toRemove.includes(id));
448
553
  savePlatformConfig(newIds, configPath);
449
554
 
450
- const removedNames = toRemove.map(id => getPlatformById(id)?.name).filter(Boolean);
451
- console.log(chalk.green(`\n✓ Removed from config: ${removedNames.join(', ')}`));
452
- console.log(chalk.gray('Note: AI instruction files in project root were not deleted.'));
453
- console.log(chalk.gray('You can manually delete them if needed.\n'));
555
+ // Remove ProAgents sections from AI files (smart removal - keeps user content)
556
+ const results = { deleted: [], cleaned: [], skipped: [] };
557
+
558
+ for (const id of toRemove) {
559
+ const platform = getPlatformById(id);
560
+ if (!platform) continue;
561
+
562
+ const filePath = join(targetDir, platform.file);
563
+ if (existsSync(filePath)) {
564
+ const result = removeProagentsSectionFromFile(filePath);
565
+ if (result === 'deleted') {
566
+ results.deleted.push(platform.name);
567
+ } else if (result === 'cleaned') {
568
+ results.cleaned.push(platform.name);
569
+ }
570
+ }
571
+ }
572
+
573
+ // Show results
574
+ console.log('');
575
+ if (results.deleted.length > 0) {
576
+ console.log(chalk.green(`✓ Removed: ${results.deleted.join(', ')}`));
577
+ }
578
+ if (results.cleaned.length > 0) {
579
+ console.log(chalk.green(`✓ Cleaned ProAgents section from: ${results.cleaned.join(', ')} (kept your custom config)`));
580
+ }
581
+
582
+ console.log(chalk.gray('\nConfig updated in proagents.config.yaml\n'));
454
583
  }
@@ -28,12 +28,12 @@ export function configListCommand() {
28
28
  // 1. Main Config
29
29
  console.log(chalk.cyan.bold('1. Main Configuration'));
30
30
  console.log(chalk.gray(' ─────────────────────────────────────────'));
31
- const configPath = join(proagentsDir, 'proagents.config.yaml');
31
+ const configPath = join(targetDir, 'proagents.config.yaml');
32
32
  if (existsSync(configPath)) {
33
- console.log(chalk.green(' ✓ ') + chalk.white('.proagents/proagents.config.yaml'));
33
+ console.log(chalk.green(' ✓ ') + chalk.white('proagents.config.yaml'));
34
34
  console.log(chalk.gray(' Checkpoints, git settings, parallel features, etc.\n'));
35
35
  } else {
36
- console.log(chalk.yellow(' ○ ') + chalk.white('.proagents/proagents.config.yaml') + chalk.gray(' (not created)\n'));
36
+ console.log(chalk.yellow(' ○ ') + chalk.white('proagents.config.yaml') + chalk.gray(' (not created)\n'));
37
37
  }
38
38
 
39
39
  // 2. AI Platforms
@@ -184,7 +184,7 @@ export function configListCommand() {
184
184
  */
185
185
  export function configShowCommand() {
186
186
  const targetDir = process.cwd();
187
- const configPath = join(targetDir, '.proagents', 'proagents.config.yaml');
187
+ const configPath = join(targetDir, 'proagents.config.yaml');
188
188
 
189
189
  console.log('\n' + chalk.bold.blue('ProAgents Current Configuration'));
190
190
  console.log(chalk.blue('================================\n'));
@@ -198,7 +198,7 @@ export function configShowCommand() {
198
198
  const content = readFileSync(configPath, 'utf-8');
199
199
  const config = yaml.load(content);
200
200
 
201
- console.log(chalk.cyan('File: ') + chalk.white('.proagents/proagents.config.yaml\n'));
201
+ console.log(chalk.cyan('File: ') + chalk.white('proagents.config.yaml\n'));
202
202
  console.log(chalk.gray('─────────────────────────────────────────────\n'));
203
203
  console.log(content);
204
204
  } catch (error) {
@@ -212,7 +212,7 @@ export function configShowCommand() {
212
212
  */
213
213
  export function configEditCommand() {
214
214
  const targetDir = process.cwd();
215
- const configPath = join(targetDir, '.proagents', 'proagents.config.yaml');
215
+ const configPath = join(targetDir, 'proagents.config.yaml');
216
216
 
217
217
  if (!existsSync(configPath)) {
218
218
  console.log(chalk.yellow('\nConfig file not found. Run "proagents init" first.\n'));
@@ -220,7 +220,7 @@ export function configEditCommand() {
220
220
  }
221
221
 
222
222
  console.log(chalk.cyan('\nTo edit configuration:\n'));
223
- console.log(chalk.white(' Open: ') + chalk.green('.proagents/proagents.config.yaml'));
223
+ console.log(chalk.white(' Open: ') + chalk.green('proagents.config.yaml'));
224
224
  console.log(chalk.white(' Docs: ') + chalk.green('.proagents/config/README.md\n'));
225
225
  }
226
226
 
@@ -261,7 +261,7 @@ function parseValue(value) {
261
261
  */
262
262
  export function configSetCommand(key, value) {
263
263
  const targetDir = process.cwd();
264
- const configPath = join(targetDir, '.proagents', 'proagents.config.yaml');
264
+ const configPath = join(targetDir, 'proagents.config.yaml');
265
265
 
266
266
  console.log('');
267
267
 
@@ -297,7 +297,7 @@ export function configSetCommand(key, value) {
297
297
  */
298
298
  export function configGetCommand(key) {
299
299
  const targetDir = process.cwd();
300
- const configPath = join(targetDir, '.proagents', 'proagents.config.yaml');
300
+ const configPath = join(targetDir, 'proagents.config.yaml');
301
301
 
302
302
  console.log('');
303
303
 
@@ -324,13 +324,25 @@ export function configGetCommand(key) {
324
324
  }
325
325
  }
326
326
 
327
+ /**
328
+ * Save config setup progress (for resume after interrupt)
329
+ */
330
+ function saveSetupProgress(configPath, config, step) {
331
+ config._config_setup = {
332
+ last_step: step,
333
+ timestamp: new Date().toISOString()
334
+ };
335
+ const yamlContent = yaml.dump(config, { indent: 2, lineWidth: 120 });
336
+ writeFileSync(configPath, yamlContent);
337
+ }
338
+
327
339
  /**
328
340
  * Command: proagents config setup
329
341
  * Interactive wizard for main configuration
330
342
  */
331
343
  export async function configSetupCommand() {
332
344
  const targetDir = process.cwd();
333
- const configPath = join(targetDir, '.proagents', 'proagents.config.yaml');
345
+ const configPath = join(targetDir, 'proagents.config.yaml');
334
346
 
335
347
  console.log('\n' + chalk.bold.blue('ProAgents Configuration Wizard'));
336
348
  console.log(chalk.blue('===============================\n'));
@@ -366,15 +378,22 @@ export async function configSetupCommand() {
366
378
  config = yaml.load(readFileSync(configPath, 'utf-8')) || {};
367
379
  }
368
380
 
381
+ // Check for interrupted setup
382
+ if (config._config_setup) {
383
+ console.log(chalk.cyan('📋 Resuming with your previous choices...\n'));
384
+ }
385
+
369
386
  console.log(chalk.cyan('Project Settings\n'));
370
387
 
371
388
  // Project settings
372
389
  config.project = config.project || {};
373
390
  config.project.name = await question('Project name', config.project.name || 'My Project');
391
+ saveSetupProgress(configPath, config, 'project_name');
374
392
 
375
393
  const projectTypes = ['web-frontend', 'fullstack', 'mobile', 'backend'];
376
394
  console.log(chalk.gray(' Types: ' + projectTypes.join(', ')));
377
395
  config.project.type = await question('Project type', config.project.type || 'fullstack');
396
+ saveSetupProgress(configPath, config, 'project_type');
378
397
 
379
398
  console.log('\n' + chalk.cyan('Checkpoints (pause for approval)\n'));
380
399
 
@@ -386,12 +405,14 @@ export async function configSetupCommand() {
386
405
  config.checkpoints.after_implementation = await yesNo('Pause after implementation?', config.checkpoints.after_implementation ?? false);
387
406
  config.checkpoints.after_testing = await yesNo('Pause after testing?', config.checkpoints.after_testing ?? false);
388
407
  config.checkpoints.before_deployment = await yesNo('Pause before deployment?', config.checkpoints.before_deployment ?? true);
408
+ saveSetupProgress(configPath, config, 'checkpoints');
389
409
 
390
410
  console.log('\n' + chalk.cyan('Git Settings\n'));
391
411
 
392
412
  // Git settings
393
413
  config.git = config.git || {};
394
414
  config.git.enabled = await yesNo('Enable git integration?', config.git.enabled ?? true);
415
+ saveSetupProgress(configPath, config, 'git_enabled');
395
416
 
396
417
  if (config.git.enabled) {
397
418
  config.git.branch_prefix = await question('Branch prefix', config.git.branch_prefix || 'feature/');
@@ -400,6 +421,7 @@ export async function configSetupCommand() {
400
421
  console.log(chalk.gray(' Conventions: ' + conventions.join(', ')));
401
422
  config.git.commit_convention = await question('Commit convention', config.git.commit_convention || 'conventional');
402
423
  config.git.require_pr = await yesNo('Require pull requests?', config.git.require_pr ?? true);
424
+ saveSetupProgress(configPath, config, 'git');
403
425
  }
404
426
 
405
427
  console.log('\n' + chalk.cyan('Parallel Features\n'));
@@ -407,20 +429,25 @@ export async function configSetupCommand() {
407
429
  // Parallel features
408
430
  config.parallel_features = config.parallel_features || {};
409
431
  config.parallel_features.enabled = await yesNo('Enable parallel features?', config.parallel_features.enabled ?? true);
432
+ saveSetupProgress(configPath, config, 'parallel_enabled');
410
433
 
411
434
  if (config.parallel_features.enabled) {
412
435
  const maxStr = await question('Max concurrent features', String(config.parallel_features.max_concurrent || 3));
413
436
  config.parallel_features.max_concurrent = parseInt(maxStr) || 3;
437
+ saveSetupProgress(configPath, config, 'parallel');
414
438
  }
415
439
 
416
440
  rl.close();
417
441
 
418
- // Save config
442
+ // Remove setup progress marker (setup complete)
443
+ delete config._config_setup;
444
+
445
+ // Save final config
419
446
  const header = `# ProAgents Configuration\n# Generated by setup wizard\n# Last updated: ${new Date().toISOString().split('T')[0]}\n\n`;
420
447
  const yamlContent = yaml.dump(config, { indent: 2, lineWidth: 120 });
421
448
  writeFileSync(configPath, header + yamlContent);
422
449
 
423
- console.log(chalk.green('\n✓ Configuration saved to proagents/proagents.config.yaml\n'));
450
+ console.log(chalk.green('\n✓ Configuration saved to proagents.config.yaml\n'));
424
451
 
425
452
  } catch (error) {
426
453
  rl.close();
@@ -697,8 +697,10 @@ async function promptGitignoreChoice() {
697
697
 
698
698
  /**
699
699
  * Interactive prompt for project configuration
700
+ * @param {string} targetDir - The target directory
701
+ * @param {object} existingConfig - Existing partial config from interrupted setup
700
702
  */
701
- async function promptProjectConfig(targetDir) {
703
+ async function promptProjectConfig(targetDir, existingConfig = {}) {
702
704
  const rl = createInterface({
703
705
  input: process.stdin,
704
706
  output: process.stdout
@@ -706,12 +708,19 @@ async function promptProjectConfig(targetDir) {
706
708
 
707
709
  const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
708
710
 
711
+ // Get saved values from interrupted setup
712
+ const savedProject = existingConfig.project || {};
713
+ const savedName = savedProject.name;
714
+ const savedType = savedProject.type;
715
+
709
716
  // Detect project name
710
- const detectedName = detectProjectName(targetDir);
717
+ const detectedName = savedName || detectProjectName(targetDir);
711
718
 
712
719
  // Detect project types
713
720
  const detectedTypes = detectProjectType(targetDir);
714
- const topDetectedType = detectedTypes.length > 0 ? detectedTypes[0] : null;
721
+ const topDetectedType = savedType
722
+ ? PROJECT_TYPES.find(t => t.id === savedType)
723
+ : (detectedTypes.length > 0 ? detectedTypes[0] : null);
715
724
 
716
725
  // Detect tech stack
717
726
  const detectedTechStack = detectTechStack(targetDir);
@@ -719,9 +728,16 @@ async function promptProjectConfig(targetDir) {
719
728
  console.log(chalk.bold('\nProject Configuration'));
720
729
  console.log(chalk.gray('─'.repeat(40) + '\n'));
721
730
 
731
+ // Show resume notice if we have saved values
732
+ if (savedName || savedType) {
733
+ console.log(chalk.cyan('📋 Resuming with your previous choices...\n'));
734
+ }
735
+
722
736
  // Project Name
723
737
  console.log(chalk.cyan('Project Name'));
724
- if (detectedName) {
738
+ if (savedName) {
739
+ console.log(chalk.green(` Previously saved: ${savedName}`));
740
+ } else if (detectedName) {
725
741
  console.log(chalk.gray(` Detected: ${detectedName}`));
726
742
  }
727
743
  const nameInput = await question(chalk.yellow(` Enter name (press Enter for "${detectedName}"): `));
@@ -836,6 +852,44 @@ function applyTemplate(templateId, targetDir) {
836
852
  };
837
853
  }
838
854
 
855
+ /**
856
+ * Load existing partial config (for resume after interrupted setup)
857
+ */
858
+ function loadPartialConfig(configPath) {
859
+ if (!existsSync(configPath)) return {};
860
+
861
+ try {
862
+ const content = readFileSync(configPath, 'utf-8');
863
+ return yaml.load(content) || {};
864
+ } catch {
865
+ return {};
866
+ }
867
+ }
868
+
869
+ /**
870
+ * Save partial config progress (called after each setup step)
871
+ */
872
+ function savePartialConfig(configPath, updates) {
873
+ let config = loadPartialConfig(configPath);
874
+
875
+ // Deep merge updates into config
876
+ for (const [key, value] of Object.entries(updates)) {
877
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
878
+ config[key] = { ...(config[key] || {}), ...value };
879
+ } else {
880
+ config[key] = value;
881
+ }
882
+ }
883
+
884
+ // Add setup progress marker
885
+ config._setup = config._setup || {};
886
+ config._setup.last_step = updates._step || config._setup.last_step;
887
+ config._setup.timestamp = new Date().toISOString();
888
+
889
+ const yamlContent = yaml.dump(config, { indent: 2, lineWidth: 120 });
890
+ writeFileSync(configPath, yamlContent);
891
+ }
892
+
839
893
  /**
840
894
  * Save project config to proagents.config.yaml
841
895
  */
@@ -900,6 +954,10 @@ export async function initCommand(options = {}) {
900
954
  const targetDir = process.cwd();
901
955
  const proagentsDir = join(targetDir, '.proagents');
902
956
  const sourceDir = join(__dirname, '..', '..', '.proagents');
957
+ const configPath = join(targetDir, 'proagents.config.yaml');
958
+
959
+ // Load any existing partial config (from interrupted setup)
960
+ const existingConfig = loadPartialConfig(configPath);
903
961
 
904
962
  console.log('\n' + chalk.bold.blue('ProAgents Initialization'));
905
963
  console.log(chalk.blue('========================\n'));
@@ -1052,6 +1110,12 @@ Generated by [ProAgents](https://github.com/prakashpro3/proAgents)
1052
1110
  } else {
1053
1111
  console.log(chalk.green('✓ Added .proagents/ local data to .gitignore'));
1054
1112
  }
1113
+
1114
+ // Save progress after gitignore choice
1115
+ savePartialConfig(configPath, {
1116
+ gitignore_mode: gitignoreChoice,
1117
+ _step: 'gitignore'
1118
+ });
1055
1119
  }
1056
1120
 
1057
1121
  // Create placeholder CHANGELOG.md if not exists
@@ -1119,10 +1183,19 @@ No releases yet. Use \`pa:release\` to generate release notes.
1119
1183
  }
1120
1184
  console.log(chalk.green(`\n✓ Using template: ${PROJECT_TEMPLATES[options.template].name}`));
1121
1185
  } else {
1122
- // Interactive prompts
1123
- projectConfig = await promptProjectConfig(targetDir);
1186
+ // Interactive prompts - pass existing config for pre-filling
1187
+ projectConfig = await promptProjectConfig(targetDir, existingConfig);
1124
1188
  }
1125
1189
 
1190
+ // Save progress after project config
1191
+ savePartialConfig(configPath, {
1192
+ project: {
1193
+ name: projectConfig.name,
1194
+ type: projectConfig.type
1195
+ },
1196
+ _step: 'project_config'
1197
+ });
1198
+
1126
1199
  // Add ProAgents section to README.md (AI tools auto-read this)
1127
1200
  const readmePath = join(targetDir, 'README.md');
1128
1201
  const proagentsSection = `
@@ -1161,9 +1234,16 @@ For detailed commands, see \`./.proagents/PROAGENTS.md\`
1161
1234
  selectedPlatforms = projectConfig.platforms;
1162
1235
  console.log(chalk.gray(` Using template platforms: ${selectedPlatforms.join(', ')}`));
1163
1236
  } else {
1164
- selectedPlatforms = await selectPlatforms();
1237
+ // Pass existing config for pre-selection
1238
+ selectedPlatforms = await selectPlatforms(existingConfig.ai_platforms);
1165
1239
  }
1166
1240
 
1241
+ // Save progress after platform selection
1242
+ savePartialConfig(configPath, {
1243
+ ai_platforms: selectedPlatforms,
1244
+ _step: 'platforms'
1245
+ });
1246
+
1167
1247
  // Copy AI instruction files for selected platforms (merges with existing files)
1168
1248
  const aiResults = copyPlatformFiles(selectedPlatforms, sourceDir, targetDir);
1169
1249
 
@@ -1177,11 +1257,16 @@ For detailed commands, see \`./.proagents/PROAGENTS.md\`
1177
1257
  console.log(chalk.green(`✓ Merged with existing: ${aiResults.merged.join(', ')}`));
1178
1258
  }
1179
1259
 
1180
- // Save project and platform config to ROOT config (not proagents/ folder)
1181
- const configPath = join(targetDir, 'proagents.config.yaml');
1260
+ // Save final project and platform config (removes _setup marker)
1182
1261
  saveProjectConfig(projectConfig, configPath);
1183
1262
  savePlatformConfig(selectedPlatforms, configPath);
1184
1263
 
1264
+ // Clean up setup progress marker
1265
+ const finalConfig = loadPartialConfig(configPath);
1266
+ delete finalConfig._setup;
1267
+ const yamlContent = yaml.dump(finalConfig, { indent: 2, lineWidth: 120 });
1268
+ writeFileSync(configPath, yamlContent);
1269
+
1185
1270
  // Success message
1186
1271
  console.log(chalk.green('\n✓ ProAgents initialized successfully!\n'));
1187
1272
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proagents",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "description": "AI-agnostic development workflow framework that automates the full software development lifecycle",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",