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.
- package/lib/commands/init.js +119 -16
- package/lib/commands/uninstall.js +63 -6
- package/package.json +1 -1
package/lib/commands/init.js
CHANGED
|
@@ -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
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
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
|
|
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
|
-
|
|
75
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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');
|