proagents 1.6.7 → 1.6.8

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.
@@ -595,6 +595,77 @@ function detectProjectType(targetDir) {
595
595
  return detectedTypes;
596
596
  }
597
597
 
598
+ /**
599
+ * Check if setup was interrupted (incomplete)
600
+ * Returns true if .proagents exists but setup wasn't completed
601
+ */
602
+ function checkIncompleteSetup(targetDir) {
603
+ const configPath = join(targetDir, 'proagents.config.yaml');
604
+ const readmePath = join(targetDir, 'README.md');
605
+ const gitignorePath = join(targetDir, '.gitignore');
606
+
607
+ // Check 1: No config file in root = incomplete
608
+ if (!existsSync(configPath)) {
609
+ return true;
610
+ }
611
+
612
+ // Check 2: No AI instruction files at all = incomplete
613
+ const aiFiles = ['CLAUDE.md', '.cursorrules', '.windsurfrules', 'CHATGPT.md', 'GEMINI.md'];
614
+ const hasAnyAiFile = aiFiles.some(f => existsSync(join(targetDir, f)));
615
+ if (!hasAnyAiFile) {
616
+ return true;
617
+ }
618
+
619
+ // Check 3: README exists but no ProAgents section = incomplete
620
+ if (existsSync(readmePath)) {
621
+ const readmeContent = readFileSync(readmePath, 'utf-8');
622
+ if (!readmeContent.includes('PROAGENTS:START')) {
623
+ return true;
624
+ }
625
+ }
626
+
627
+ // Check 4: .gitignore exists but no proagents entry = incomplete
628
+ if (existsSync(gitignorePath)) {
629
+ const gitignoreContent = readFileSync(gitignorePath, 'utf-8');
630
+ if (!gitignoreContent.includes('.proagents')) {
631
+ return true;
632
+ }
633
+ }
634
+
635
+ return false;
636
+ }
637
+
638
+ /**
639
+ * Prompt user for what to do with incomplete setup
640
+ */
641
+ async function promptIncompleteSetupChoice() {
642
+ const rl = createInterface({
643
+ input: process.stdin,
644
+ output: process.stdout
645
+ });
646
+
647
+ const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
648
+
649
+ console.log(chalk.cyan('What would you like to do?'));
650
+ console.log(chalk.white(' 1. Continue setup') + chalk.green(' (recommended)'));
651
+ console.log(chalk.gray(' Complete the remaining setup steps'));
652
+ console.log('');
653
+ console.log(chalk.white(' 2. Restart fresh'));
654
+ console.log(chalk.gray(' Remove everything and start over'));
655
+ console.log('');
656
+ console.log(chalk.white(' 3. Update only'));
657
+ console.log(chalk.gray(' Just update framework files, skip setup'));
658
+ console.log('');
659
+
660
+ const choice = await question(chalk.yellow(' Choose (1, 2, or 3, default=1): '));
661
+ rl.close();
662
+
663
+ const trimmed = choice.trim();
664
+ if (trimmed === '2') return 'restart';
665
+ if (trimmed === '3') return 'update';
666
+ return 'continue';
667
+ }
668
+
598
669
  /**
599
670
  * Prompt user for .gitignore preference
600
671
  */
@@ -836,24 +907,56 @@ export async function initCommand(options = {}) {
836
907
  // Check if already initialized
837
908
  const alreadyInitialized = existsSync(proagentsDir);
838
909
 
910
+ // Check for incomplete setup (user killed terminal mid-setup)
911
+ const isIncompleteSetup = alreadyInitialized && checkIncompleteSetup(targetDir);
912
+
839
913
  if (alreadyInitialized && !options.force) {
840
- // Smart update mode - preserve user files, update framework
841
- console.log(chalk.cyan('ℹ️ ProAgents detected. Running smart update...'));
842
- console.log(chalk.gray(' (Preserving your customizations)\n'));
914
+ if (isIncompleteSetup) {
915
+ // Incomplete setup detected - ask user what to do
916
+ console.log(chalk.yellow('⚠️ Incomplete setup detected!'));
917
+ console.log(chalk.gray(' Previous setup was interrupted before completion.\n'));
918
+
919
+ const choice = await promptIncompleteSetupChoice();
920
+
921
+ if (choice === 'continue') {
922
+ console.log(chalk.cyan('\nContinuing setup...\n'));
923
+ // Fall through to fresh install (but keep .proagents folder)
924
+ } else if (choice === 'restart') {
925
+ console.log(chalk.cyan('\nRestarting fresh setup...\n'));
926
+ rmSync(proagentsDir, { recursive: true, force: true });
927
+ // Fall through to fresh install
928
+ } else {
929
+ // Update only
930
+ console.log(chalk.cyan('\nRunning smart update...\n'));
931
+ try {
932
+ await smartUpdate(sourceDir, proagentsDir);
933
+ console.log(chalk.green('\n✓ ProAgents updated successfully!\n'));
934
+ return;
935
+ } catch (error) {
936
+ console.error(chalk.red('\n✗ Error updating ProAgents:'));
937
+ console.error(chalk.red(error.message));
938
+ process.exit(1);
939
+ }
940
+ }
941
+ } else {
942
+ // Complete setup exists - run smart update
943
+ console.log(chalk.cyan('ℹ️ ProAgents detected. Running smart update...'));
944
+ console.log(chalk.gray(' (Preserving your customizations)\n'));
843
945
 
844
- try {
845
- await smartUpdate(sourceDir, proagentsDir);
846
- console.log(chalk.green('\n✓ ProAgents updated successfully!\n'));
847
- console.log(chalk.gray('Preserved:'));
848
- console.log(chalk.gray(' • active-features/ (your work in progress)'));
849
- console.log(chalk.gray(' • proagents.config.yaml (your values + new options merged)'));
850
- console.log(chalk.gray(' • .learning/ (learned patterns)'));
851
- console.log(chalk.gray(' • cache/ (analysis cache)\n'));
852
- return;
853
- } catch (error) {
854
- console.error(chalk.red('\n✗ Error updating ProAgents:'));
855
- console.error(chalk.red(error.message));
856
- process.exit(1);
946
+ try {
947
+ await smartUpdate(sourceDir, proagentsDir);
948
+ console.log(chalk.green('\n✓ ProAgents updated successfully!\n'));
949
+ console.log(chalk.gray('Preserved:'));
950
+ console.log(chalk.gray(' • active-features/ (your work in progress)'));
951
+ console.log(chalk.gray(' • proagents.config.yaml (your values + new options merged)'));
952
+ console.log(chalk.gray(' • .learning/ (learned patterns)'));
953
+ console.log(chalk.gray(' • cache/ (analysis cache)\n'));
954
+ return;
955
+ } catch (error) {
956
+ console.error(chalk.red('\n✗ Error updating ProAgents:'));
957
+ console.error(chalk.red(error.message));
958
+ process.exit(1);
959
+ }
857
960
  }
858
961
  }
859
962
 
@@ -19,6 +19,50 @@ const AI_FILES = [
19
19
  'AI_INSTRUCTIONS.md',
20
20
  ];
21
21
 
22
+ // ProAgents markers used in merged files
23
+ const PROAGENTS_START = '<!-- PROAGENTS:START -->';
24
+ const PROAGENTS_END = '<!-- PROAGENTS:END -->';
25
+
26
+ /**
27
+ * Remove only ProAgents section from a file, keep user's original content
28
+ * Returns: 'deleted' (file removed), 'cleaned' (section removed), 'skipped' (no ProAgents section)
29
+ */
30
+ function removeProagentsSectionFromFile(filePath) {
31
+ try {
32
+ const content = readFileSync(filePath, 'utf-8');
33
+
34
+ const startIndex = content.indexOf(PROAGENTS_START);
35
+ const endIndex = content.indexOf(PROAGENTS_END);
36
+
37
+ if (startIndex !== -1 && endIndex !== -1) {
38
+ // Has ProAgents section - remove it, keep the rest
39
+ const before = content.substring(0, startIndex).trim();
40
+ const after = content.substring(endIndex + PROAGENTS_END.length).trim();
41
+ const remaining = (before + '\n\n' + after).trim();
42
+
43
+ if (remaining.length === 0) {
44
+ // File only had ProAgents content - delete it
45
+ rmSync(filePath, { force: true });
46
+ return 'deleted';
47
+ } else {
48
+ // File has other content - keep it, remove only ProAgents section
49
+ writeFileSync(filePath, remaining + '\n');
50
+ return 'cleaned';
51
+ }
52
+ } else {
53
+ // No ProAgents markers - file was created by ProAgents (not merged)
54
+ // Check if it's a ProAgents-generated file by looking for ProAgents reference
55
+ if (content.includes('proagents') || content.includes('ProAgents') || content.includes('.proagents/')) {
56
+ rmSync(filePath, { force: true });
57
+ return 'deleted';
58
+ }
59
+ return 'skipped';
60
+ }
61
+ } catch (error) {
62
+ return 'skipped';
63
+ }
64
+ }
65
+
22
66
  /**
23
67
  * Command: proagents uninstall
24
68
  */
@@ -46,7 +90,7 @@ export async function uninstallCommand(options = {}) {
46
90
 
47
91
  console.log(chalk.yellow('This will remove:'));
48
92
  console.log(chalk.gray(' • ./.proagents/ folder'));
49
- console.log(chalk.gray(' • AI instruction files (CLAUDE.md, .cursorrules, etc.)'));
93
+ console.log(chalk.gray(' • ProAgents sections from AI files (keeps your original config)'));
50
94
  console.log(chalk.gray(' • ProAgents section from README.md\n'));
51
95
 
52
96
  const answer = await question(chalk.yellow('Are you sure? (yes/no): '));
@@ -66,26 +110,39 @@ export async function uninstallCommand(options = {}) {
66
110
  console.log(chalk.green('✓ Removed ./.proagents/ folder'));
67
111
  }
68
112
 
69
- // 2. Remove AI instruction files from project root
113
+ // 2. Remove AI instruction files from project root (smart removal)
70
114
  let aiFilesRemoved = 0;
115
+ let aiFilesCleaned = 0;
116
+
71
117
  for (const file of AI_FILES) {
72
118
  const filePath = join(targetDir, file);
73
119
  if (existsSync(filePath)) {
74
- rmSync(filePath, { force: true });
75
- aiFilesRemoved++;
120
+ const result = removeProagentsSectionFromFile(filePath);
121
+ if (result === 'deleted') {
122
+ aiFilesRemoved++;
123
+ } else if (result === 'cleaned') {
124
+ aiFilesCleaned++;
125
+ }
76
126
  }
77
127
  }
78
128
 
79
129
  // Remove .github/copilot-instructions.md
80
130
  const copilotPath = join(targetDir, '.github', 'copilot-instructions.md');
81
131
  if (existsSync(copilotPath)) {
82
- rmSync(copilotPath, { force: true });
83
- aiFilesRemoved++;
132
+ const result = removeProagentsSectionFromFile(copilotPath);
133
+ if (result === 'deleted') {
134
+ aiFilesRemoved++;
135
+ } else if (result === 'cleaned') {
136
+ aiFilesCleaned++;
137
+ }
84
138
  }
85
139
 
86
140
  if (aiFilesRemoved > 0) {
87
141
  console.log(chalk.green(`✓ Removed ${aiFilesRemoved} AI instruction file(s)`));
88
142
  }
143
+ if (aiFilesCleaned > 0) {
144
+ console.log(chalk.green(`✓ Cleaned ProAgents section from ${aiFilesCleaned} AI file(s) (kept original config)`));
145
+ }
89
146
 
90
147
  // 3. Remove ProAgents section from README.md
91
148
  const readmePath = join(targetDir, 'README.md');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proagents",
3
- "version": "1.6.7",
3
+ "version": "1.6.8",
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",