proagents 1.6.6 → 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 +191 -16
- package/lib/commands/uninstall.js +63 -6
- package/package.json +1 -1
package/lib/commands/init.js
CHANGED
|
@@ -595,6 +595,106 @@ 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
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Prompt user for .gitignore preference
|
|
671
|
+
*/
|
|
672
|
+
async function promptGitignoreChoice() {
|
|
673
|
+
const rl = createInterface({
|
|
674
|
+
input: process.stdin,
|
|
675
|
+
output: process.stdout
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
|
|
679
|
+
|
|
680
|
+
console.log(chalk.bold('\nGit Ignore Settings'));
|
|
681
|
+
console.log(chalk.gray('─'.repeat(40) + '\n'));
|
|
682
|
+
|
|
683
|
+
console.log(chalk.cyan('What to ignore in .gitignore?'));
|
|
684
|
+
console.log(chalk.white(' 1. Local data only') + chalk.green(' (recommended for teams)'));
|
|
685
|
+
console.log(chalk.gray(' Ignores: cache, learning, sessions, active-features'));
|
|
686
|
+
console.log(chalk.gray(' Shares: prompts, templates, config with team'));
|
|
687
|
+
console.log('');
|
|
688
|
+
console.log(chalk.white(' 2. Entire .proagents/ folder') + chalk.gray(' (solo developers)'));
|
|
689
|
+
console.log(chalk.gray(' Nothing shared with git'));
|
|
690
|
+
console.log('');
|
|
691
|
+
|
|
692
|
+
const choice = await question(chalk.yellow(' Choose (1 or 2, default=1): '));
|
|
693
|
+
rl.close();
|
|
694
|
+
|
|
695
|
+
return choice.trim() === '2' ? 'full' : 'local';
|
|
696
|
+
}
|
|
697
|
+
|
|
598
698
|
/**
|
|
599
699
|
* Interactive prompt for project configuration
|
|
600
700
|
*/
|
|
@@ -807,24 +907,56 @@ export async function initCommand(options = {}) {
|
|
|
807
907
|
// Check if already initialized
|
|
808
908
|
const alreadyInitialized = existsSync(proagentsDir);
|
|
809
909
|
|
|
910
|
+
// Check for incomplete setup (user killed terminal mid-setup)
|
|
911
|
+
const isIncompleteSetup = alreadyInitialized && checkIncompleteSetup(targetDir);
|
|
912
|
+
|
|
810
913
|
if (alreadyInitialized && !options.force) {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
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'));
|
|
814
945
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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
|
+
}
|
|
828
960
|
}
|
|
829
961
|
}
|
|
830
962
|
|
|
@@ -879,6 +1011,49 @@ Generated by [ProAgents](https://github.com/prakashpro3/proAgents)
|
|
|
879
1011
|
}
|
|
880
1012
|
console.log(chalk.green('✓ Created docs/ folder structure'));
|
|
881
1013
|
|
|
1014
|
+
// Add .proagents/ to .gitignore - prompt user for preference
|
|
1015
|
+
const gitignorePath = join(targetDir, '.gitignore');
|
|
1016
|
+
const existingGitignore = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf-8') : '';
|
|
1017
|
+
|
|
1018
|
+
if (!existingGitignore.includes('.proagents')) {
|
|
1019
|
+
// Prompt user for gitignore preference
|
|
1020
|
+
const gitignoreChoice = await promptGitignoreChoice();
|
|
1021
|
+
|
|
1022
|
+
let gitignoreEntries;
|
|
1023
|
+
if (gitignoreChoice === 'full') {
|
|
1024
|
+
// Ignore entire .proagents/ folder
|
|
1025
|
+
gitignoreEntries = [
|
|
1026
|
+
'# ProAgents - Entire folder ignored (not shared with team)',
|
|
1027
|
+
'.proagents/',
|
|
1028
|
+
''
|
|
1029
|
+
].join('\n');
|
|
1030
|
+
} else {
|
|
1031
|
+
// Default: Ignore only local data
|
|
1032
|
+
gitignoreEntries = [
|
|
1033
|
+
'# ProAgents - Local data only (workflow config shared with team)',
|
|
1034
|
+
'.proagents/cache/',
|
|
1035
|
+
'.proagents/.learning/',
|
|
1036
|
+
'.proagents/sessions/',
|
|
1037
|
+
'.proagents/active-features/',
|
|
1038
|
+
'.proagents/backups/',
|
|
1039
|
+
'.proagents/*.log',
|
|
1040
|
+
''
|
|
1041
|
+
].join('\n');
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (existingGitignore) {
|
|
1045
|
+
writeFileSync(gitignorePath, existingGitignore + '\n' + gitignoreEntries);
|
|
1046
|
+
} else {
|
|
1047
|
+
writeFileSync(gitignorePath, gitignoreEntries);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
if (gitignoreChoice === 'full') {
|
|
1051
|
+
console.log(chalk.green('✓ Added .proagents/ to .gitignore (entire folder)'));
|
|
1052
|
+
} else {
|
|
1053
|
+
console.log(chalk.green('✓ Added .proagents/ local data to .gitignore'));
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
882
1057
|
// Create placeholder CHANGELOG.md if not exists
|
|
883
1058
|
const changelogPath = join(targetDir, 'CHANGELOG.md');
|
|
884
1059
|
if (!existsSync(changelogPath)) {
|
|
@@ -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');
|