stigmergy 1.2.0 → 1.2.6
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/LICENSE +18 -18
- package/README.md +28 -223
- package/STIGMERGY.md +61 -61
- package/docs/PROJECT_CONSTITUTION.md +433 -433
- package/docs/PROJECT_STRUCTURE_CURRENT.md +80 -80
- package/examples/calculator-example.js +72 -72
- package/examples/cline_usage_examples.md +364 -364
- package/examples/encryption-example.js +67 -67
- package/examples/json-parser-example.js +120 -120
- package/examples/json-validation-example.js +64 -64
- package/examples/rest-client-example.js +52 -52
- package/examples/rest_client_example.js +54 -54
- package/package.json +36 -15
- package/scripts/build.js +74 -74
- package/scripts/post-deployment-config.js +296 -296
- package/scripts/preinstall-check.js +173 -173
- package/scripts/publish.js +58 -268
- package/scripts/run-layered-tests.js +247 -0
- package/scripts/safe-install.js +139 -139
- package/scripts/simple-publish.js +57 -59
- package/src/adapters/claude/install_claude_integration.js +292 -0
- package/src/adapters/codebuddy/install_codebuddy_integration.js +349 -0
- package/src/adapters/codex/install_codex_integration.js +395 -0
- package/src/adapters/copilot/install_copilot_integration.js +716 -0
- package/src/adapters/gemini/install_gemini_integration.js +304 -0
- package/src/adapters/iflow/install_iflow_integration.js +304 -0
- package/src/adapters/qoder/install_qoder_integration.js +1090 -0
- package/src/adapters/qwen/install_qwen_integration.js +285 -0
- package/src/auth.js +173 -173
- package/src/auth_command.js +208 -208
- package/src/calculator.js +313 -313
- package/src/cli/router.js +417 -38
- package/src/core/cache_cleaner.js +767 -744
- package/src/core/cli_help_analyzer.js +680 -674
- package/src/core/cli_parameter_handler.js +132 -127
- package/src/core/cli_tools.js +89 -89
- package/src/core/coordination/index.js +16 -16
- package/src/core/coordination/nodejs/AdapterManager.js +102 -89
- package/src/core/coordination/nodejs/CLCommunication.js +132 -124
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +272 -236
- package/src/core/coordination/nodejs/HealthChecker.js +76 -77
- package/src/core/coordination/nodejs/HookDeploymentManager.js +263 -190
- package/src/core/coordination/nodejs/StatisticsCollector.js +71 -71
- package/src/core/coordination/nodejs/index.js +90 -72
- package/src/core/coordination/nodejs/utils/Logger.js +29 -29
- package/src/core/enhanced_installer.js +479 -456
- package/src/core/enhanced_uninstaller.js +638 -618
- package/src/core/error_handler.js +406 -406
- package/src/core/installer.js +815 -294
- package/src/core/memory_manager.js +83 -83
- package/src/core/rest_client.js +160 -160
- package/src/core/smart_router.js +249 -146
- package/src/core/upgrade_manager.js +76 -59
- package/src/data_encryption.js +143 -143
- package/src/data_structures.js +440 -440
- package/src/deploy.js +55 -55
- package/src/index.js +30 -30
- package/src/test/cli-availability-checker.js +194 -0
- package/src/test/test-environment.js +289 -0
- package/src/utils/helpers.js +35 -35
- package/src/utils.js +921 -915
- package/src/weatherProcessor.js +228 -228
- package/test/cache-cleaner-implemented.test.js +0 -328
- package/test/cache-cleaner.test.js +0 -390
- package/test/calculator.test.js +0 -215
- package/test/collision-test.js +0 -26
- package/test/comprehensive-enhanced-features.test.js +0 -252
- package/test/comprehensive-execution-test.js +0 -428
- package/test/conflict-prevention-test.js +0 -95
- package/test/cross-cli-detection-test.js +0 -33
- package/test/csv-processing-test.js +0 -36
- package/test/deploy-hooks-test.js +0 -250
- package/test/e2e/claude-cli-test.js +0 -128
- package/test/e2e/collaboration-test.js +0 -75
- package/test/e2e/comprehensive-test.js +0 -431
- package/test/e2e/error-handling-test.js +0 -90
- package/test/e2e/individual-tool-test.js +0 -143
- package/test/e2e/other-cli-test.js +0 -130
- package/test/e2e/qoder-cli-test.js +0 -128
- package/test/e2e/run-e2e-tests.js +0 -73
- package/test/e2e/test-data.js +0 -88
- package/test/e2e/test-utils.js +0 -222
- package/test/encryption-simple-test.js +0 -110
- package/test/encryption.test.js +0 -129
- package/test/enhanced-main-alignment.test.js +0 -298
- package/test/enhanced-uninstaller-implemented.test.js +0 -271
- package/test/enhanced-uninstaller.test.js +0 -284
- package/test/error-handling-test.js +0 -341
- package/test/fibonacci.test.js +0 -178
- package/test/final-deploy-test.js +0 -221
- package/test/final-install-test.js +0 -226
- package/test/hash-table-demo.js +0 -33
- package/test/hash-table-test.js +0 -26
- package/test/hash_table_test.js +0 -114
- package/test/hook-system-integration-test.js +0 -307
- package/test/iflow-integration-test.js +0 -292
- package/test/improved-install-test.js +0 -362
- package/test/install-command-test.js +0 -370
- package/test/json-parser-test.js +0 -161
- package/test/json-validation-test.js +0 -164
- package/test/natural-language-skills-test.js +0 -320
- package/test/nl-integration-test.js +0 -179
- package/test/parameter-parsing-test.js +0 -143
- package/test/plugin-deployment-test.js +0 -316
- package/test/postinstall-test.js +0 -269
- package/test/python-plugins-test.js +0 -259
- package/test/real-test.js +0 -435
- package/test/remaining-adapters-test.js +0 -256
- package/test/rest-client-test.js +0 -56
- package/test/rest_client.test.js +0 -85
- package/test/safe-installation-cleaner.test.js +0 -343
- package/test/simple-iflow-hook-test.js +0 -137
- package/test/stigmergy-upgrade-test.js +0 -243
- package/test/system-compatibility-test.js +0 -467
- package/test/tdd-deploy-fix-test.js +0 -324
- package/test/tdd-fixes-test.js +0 -211
- package/test/third-party-skills-test.js +0 -321
- package/test/tool-selection-integration-test.js +0 -158
- package/test/unit/calculator-full.test.js +0 -191
- package/test/unit/calculator-simple.test.js +0 -96
- package/test/unit/calculator.test.js +0 -97
- package/test/unit/cli-scanner.test.js +0 -291
- package/test/unit/cli_parameter_handler.test.js +0 -116
- package/test/unit/cross-cli-executor.test.js +0 -399
- package/test/weather-processor.test.js +0 -104
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Layered Test Runner
|
|
5
|
+
* Executes tests in layers with appropriate filtering based on CLI availability
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawn } = require('child_process');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const CLIAvailabilityChecker = require('../src/test/cli-availability-checker');
|
|
11
|
+
|
|
12
|
+
class LayeredTestRunner {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.baseDir = path.resolve(__dirname, '..');
|
|
15
|
+
this.coverageDir = path.join(this.baseDir, 'coverage');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Run all test layers
|
|
20
|
+
*/
|
|
21
|
+
async runAll(options = {}) {
|
|
22
|
+
console.log('🧪 Stigmergy CLI Layered Test Runner');
|
|
23
|
+
console.log('=====================================\n');
|
|
24
|
+
|
|
25
|
+
const { skipE2E = false, onlyAvailable = false } = options;
|
|
26
|
+
|
|
27
|
+
// Check CLI availability
|
|
28
|
+
console.log('1. Checking CLI tool availability...');
|
|
29
|
+
const availabilityChecker = new CLIAvailabilityChecker();
|
|
30
|
+
await availabilityChecker.printAvailabilityReport();
|
|
31
|
+
|
|
32
|
+
// Layer 1: Unit Tests
|
|
33
|
+
console.log('\n2. Running Unit Tests...');
|
|
34
|
+
const unitResult = await this.runUnitTests();
|
|
35
|
+
|
|
36
|
+
// Layer 2: Integration Tests
|
|
37
|
+
console.log('\n3. Running Integration Tests...');
|
|
38
|
+
const integrationResult = await this.runIntegrationTests();
|
|
39
|
+
|
|
40
|
+
// Layer 3: E2E Tests (optional)
|
|
41
|
+
let e2eResult = null;
|
|
42
|
+
if (!skipE2E) {
|
|
43
|
+
console.log('\n4. Running E2E Tests...');
|
|
44
|
+
e2eResult = await this.runE2ETests(onlyAvailable);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Generate report
|
|
48
|
+
this.printSummary({
|
|
49
|
+
unit: unitResult,
|
|
50
|
+
integration: integrationResult,
|
|
51
|
+
e2e: e2eResult
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Exit with appropriate code
|
|
55
|
+
const allPassed = this.allTestsPassed(unitResult, integrationResult, e2eResult);
|
|
56
|
+
process.exit(allPassed ? 0 : 1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Run unit tests
|
|
61
|
+
*/
|
|
62
|
+
async runUnitTests() {
|
|
63
|
+
return this.runJest('tests/unit', {
|
|
64
|
+
coverage: true,
|
|
65
|
+
coverageDirectory: 'coverage/unit',
|
|
66
|
+
testPathIgnorePatterns: ['<rootDir>/tests/e2e/', '<rootDir>/tests/integration/']
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Run integration tests
|
|
72
|
+
*/
|
|
73
|
+
async runIntegrationTests() {
|
|
74
|
+
return this.runJest('tests/integration', {
|
|
75
|
+
coverage: true,
|
|
76
|
+
coverageDirectory: 'coverage/integration',
|
|
77
|
+
testPathIgnorePatterns: ['<rootDir>/tests/unit/', '<rootDir>/tests/e2e/']
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Run E2E tests
|
|
83
|
+
*/
|
|
84
|
+
async runE2ETests(onlyAvailable = false) {
|
|
85
|
+
const env = onlyAvailable ? { ONLY_AVAILABLE_CLIS: 'true' } : {};
|
|
86
|
+
|
|
87
|
+
return this.runJest('tests/e2e', {
|
|
88
|
+
coverage: false, // Usually not needed for E2E
|
|
89
|
+
testTimeout: 60000, // Longer timeout for E2E
|
|
90
|
+
maxWorkers: 1, // Run E2E tests serially to avoid conflicts
|
|
91
|
+
env
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Run Jest with specific options
|
|
97
|
+
*/
|
|
98
|
+
async runJest(testPath, options = {}) {
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
const args = [
|
|
101
|
+
testPath,
|
|
102
|
+
'--verbose',
|
|
103
|
+
'--no-cache',
|
|
104
|
+
`--testTimeout=${options.testTimeout || 30000}`,
|
|
105
|
+
`--maxWorkers=${options.maxWorkers || 4}`
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
if (options.coverage) {
|
|
109
|
+
args.push('--coverage');
|
|
110
|
+
args.push(`--coverageDirectory=${options.coverageDirectory}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (options.testPathIgnorePatterns) {
|
|
114
|
+
options.testPathIgnorePatterns.forEach(pattern => {
|
|
115
|
+
args.push('--testPathIgnorePatterns=' + pattern);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const jestPath = process.platform === 'win32'
|
|
120
|
+
? path.join(this.baseDir, 'node_modules', '.bin', 'jest.cmd')
|
|
121
|
+
: path.join(this.baseDir, 'node_modules', '.bin', 'jest');
|
|
122
|
+
|
|
123
|
+
const child = spawn(jestPath, args, {
|
|
124
|
+
cwd: this.baseDir,
|
|
125
|
+
stdio: 'pipe',
|
|
126
|
+
env: { ...process.env, ...options.env }
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
let stdout = '';
|
|
130
|
+
let stderr = '';
|
|
131
|
+
|
|
132
|
+
child.stdout.on('data', (data) => {
|
|
133
|
+
stdout += data.toString();
|
|
134
|
+
process.stdout.write(data);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
child.stderr.on('data', (data) => {
|
|
138
|
+
stderr += data.toString();
|
|
139
|
+
process.stderr.write(data);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
child.on('close', (code) => {
|
|
143
|
+
resolve({
|
|
144
|
+
success: code === 0,
|
|
145
|
+
exitCode: code,
|
|
146
|
+
stdout,
|
|
147
|
+
stderr
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Check if all tests passed
|
|
155
|
+
*/
|
|
156
|
+
allTestsPassed(unit, integration, e2e) {
|
|
157
|
+
const results = [unit, integration];
|
|
158
|
+
if (e2e) results.push(e2e);
|
|
159
|
+
|
|
160
|
+
return results.every(result => result && result.success);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Print test summary
|
|
165
|
+
*/
|
|
166
|
+
printSummary(results) {
|
|
167
|
+
console.log('\n=====================================');
|
|
168
|
+
console.log('Test Layer Summary:');
|
|
169
|
+
console.log('=====================================');
|
|
170
|
+
|
|
171
|
+
const layers = [
|
|
172
|
+
{ name: 'Unit Tests', result: results.unit },
|
|
173
|
+
{ name: 'Integration Tests', result: results.integration },
|
|
174
|
+
{ name: 'E2E Tests', result: results.e2e, optional: true }
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
let allPassed = true;
|
|
178
|
+
|
|
179
|
+
layers.forEach(layer => {
|
|
180
|
+
if (!layer.result) {
|
|
181
|
+
console.log(`${layer.name}: SKIPPED`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const status = layer.result.success ? '�? : '�?;
|
|
186
|
+
console.log(`${layer.name}: ${status} (exit code: ${layer.result.exitCode})`);
|
|
187
|
+
|
|
188
|
+
if (!layer.result.success) {
|
|
189
|
+
allPassed = false;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
console.log('=====================================');
|
|
194
|
+
console.log(`Overall: ${allPassed ? '�?ALL TESTS PASSED' : '�?SOME TESTS FAILED'}`);
|
|
195
|
+
console.log('=====================================\n');
|
|
196
|
+
|
|
197
|
+
if (allPassed) {
|
|
198
|
+
console.log('🎉 Ready for deployment!');
|
|
199
|
+
} else {
|
|
200
|
+
console.log('�?Please fix failing tests before deployment.');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// CLI interface
|
|
206
|
+
async function main() {
|
|
207
|
+
const args = process.argv.slice(2);
|
|
208
|
+
const options = {};
|
|
209
|
+
|
|
210
|
+
if (args.includes('--skip-e2e')) {
|
|
211
|
+
options.skipE2E = true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (args.includes('--only-available')) {
|
|
215
|
+
options.onlyAvailable = true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
219
|
+
console.log(`
|
|
220
|
+
Usage: node scripts/run-layered-tests.js [options]
|
|
221
|
+
|
|
222
|
+
Options:
|
|
223
|
+
--skip-e2e Skip end-to-end tests
|
|
224
|
+
--only-available Only test with available CLI tools
|
|
225
|
+
--help, -h Show this help message
|
|
226
|
+
|
|
227
|
+
Examples:
|
|
228
|
+
node scripts/run-layered-tests.js
|
|
229
|
+
node scripts/run-layered-tests.js --skip-e2e
|
|
230
|
+
node scripts/run-layered-tests.js --only-available
|
|
231
|
+
`);
|
|
232
|
+
process.exit(0);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const runner = new LayeredTestRunner();
|
|
236
|
+
await runner.runAll(options);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Run if called directly
|
|
240
|
+
if (require.main === module) {
|
|
241
|
+
main().catch(error => {
|
|
242
|
+
console.error('Test runner failed:', error);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
module.exports = LayeredTestRunner;
|
package/scripts/safe-install.js
CHANGED
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stigmergy Safe Installation Script
|
|
5
|
-
* This script ensures safe installation without conflicting with other CLI tools
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const fs = require('fs').promises;
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const { spawn } = require('child_process');
|
|
11
|
-
|
|
12
|
-
class SafeInstaller {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.npmBinDir = path.join(process.env.APPDATA || process.env.HOME, 'npm');
|
|
15
|
-
this.backupDir = path.join(process.env.TEMP || '/tmp', 'stigmergy-backup-' + Date.now());
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Backup existing files that might conflict
|
|
19
|
-
async backupPotentialConflicts() {
|
|
20
|
-
console.log('[BACKUP] Creating backup of potential conflicting files...');
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
await fs.mkdir(this.backupDir, { recursive: true });
|
|
24
|
-
} catch (error) {
|
|
25
|
-
console.log('[INFO] Could not create backup directory, continuing without backup...');
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const potentialConflicts = [
|
|
30
|
-
'node',
|
|
31
|
-
'node.exe',
|
|
32
|
-
'node.cmd'
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
for (const fileName of potentialConflicts) {
|
|
36
|
-
const filePath = path.join(this.npmBinDir, fileName);
|
|
37
|
-
const backupPath = path.join(this.backupDir, fileName);
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
await fs.access(filePath);
|
|
41
|
-
console.log(`[BACKUP] Backing up ${fileName}...`);
|
|
42
|
-
await fs.copyFile(filePath, backupPath);
|
|
43
|
-
} catch (error) {
|
|
44
|
-
// File doesn't exist, that's fine
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
console.log(`[OK] Backup created at: ${this.backupDir}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Restore backed up files if installation fails
|
|
52
|
-
async restoreBackupIfNeeded(success) {
|
|
53
|
-
if (success) {
|
|
54
|
-
console.log('[CLEANUP] Installation successful, cleaning up backup...');
|
|
55
|
-
try {
|
|
56
|
-
const rimraf = require('rimraf');
|
|
57
|
-
rimraf.sync(this.backupDir);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
// If rimraf is not available, just leave the backup
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
console.log('[RESTORE] Installation failed, restoring backed up files...');
|
|
63
|
-
// We would restore files here if needed
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Monitor installation for conflicts
|
|
68
|
-
async monitorInstallation() {
|
|
69
|
-
console.log('[MONITOR] Monitoring installation for conflicts...');
|
|
70
|
-
|
|
71
|
-
// Check for the specific issue we're trying to prevent
|
|
72
|
-
const nodePackageDir = path.join(this.npmBinDir, 'node_modules', 'node');
|
|
73
|
-
try {
|
|
74
|
-
await fs.access(nodePackageDir);
|
|
75
|
-
console.warn('[WARNING] Detected "node" package installation during installation!');
|
|
76
|
-
console.warn('[WARNING] This may cause conflicts with other CLI tools.');
|
|
77
|
-
console.warn('[WARNING] If you experience issues, run: npm run fix-node-conflict');
|
|
78
|
-
} catch (error) {
|
|
79
|
-
// Package doesn't exist, that's good
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Safe installation process
|
|
84
|
-
async install() {
|
|
85
|
-
let success = false;
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
// Step 1: Backup potential conflicts
|
|
89
|
-
await this.backupPotentialConflicts();
|
|
90
|
-
|
|
91
|
-
// Step 2: Run the actual installation
|
|
92
|
-
console.log('[INSTALL] Starting safe installation...');
|
|
93
|
-
|
|
94
|
-
// This would be where we run the actual installation logic
|
|
95
|
-
// For now, we'll just simulate it
|
|
96
|
-
|
|
97
|
-
success = true;
|
|
98
|
-
console.log('[SUCCESS] Safe installation completed.');
|
|
99
|
-
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error('[ERROR] Installation failed:', error.message);
|
|
102
|
-
} finally {
|
|
103
|
-
// Step 3: Restore backups if needed
|
|
104
|
-
await this.restoreBackupIfNeeded(success);
|
|
105
|
-
|
|
106
|
-
// Step 4: Monitor for conflicts
|
|
107
|
-
await this.monitorInstallation();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return success;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Run safe installation
|
|
115
|
-
async function runSafeInstallation() {
|
|
116
|
-
console.log('Stigmergy Safe Installation');
|
|
117
|
-
console.log('='.repeat(30));
|
|
118
|
-
|
|
119
|
-
const installer = new SafeInstaller();
|
|
120
|
-
const success = await installer.install();
|
|
121
|
-
|
|
122
|
-
if (success) {
|
|
123
|
-
console.log('\n[COMPLETE] Stigmergy installed safely!');
|
|
124
|
-
console.log('[NEXT] Run "stigmergy --help" to get started.');
|
|
125
|
-
} else {
|
|
126
|
-
console.log('\n[FAILED] Installation failed. Please check the errors above.');
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Only run if this script is called directly
|
|
132
|
-
if (require.main === module) {
|
|
133
|
-
runSafeInstallation().catch(error => {
|
|
134
|
-
console.error('[FATAL]', error.message);
|
|
135
|
-
process.exit(1);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = { SafeInstaller };
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stigmergy Safe Installation Script
|
|
5
|
+
* This script ensures safe installation without conflicting with other CLI tools
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs').promises;
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { spawn } = require('child_process');
|
|
11
|
+
|
|
12
|
+
class SafeInstaller {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.npmBinDir = path.join(process.env.APPDATA || process.env.HOME, 'npm');
|
|
15
|
+
this.backupDir = path.join(process.env.TEMP || '/tmp', 'stigmergy-backup-' + Date.now());
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Backup existing files that might conflict
|
|
19
|
+
async backupPotentialConflicts() {
|
|
20
|
+
console.log('[BACKUP] Creating backup of potential conflicting files...');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await fs.mkdir(this.backupDir, { recursive: true });
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.log('[INFO] Could not create backup directory, continuing without backup...');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const potentialConflicts = [
|
|
30
|
+
'node',
|
|
31
|
+
'node.exe',
|
|
32
|
+
'node.cmd'
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
for (const fileName of potentialConflicts) {
|
|
36
|
+
const filePath = path.join(this.npmBinDir, fileName);
|
|
37
|
+
const backupPath = path.join(this.backupDir, fileName);
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await fs.access(filePath);
|
|
41
|
+
console.log(`[BACKUP] Backing up ${fileName}...`);
|
|
42
|
+
await fs.copyFile(filePath, backupPath);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// File doesn't exist, that's fine
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`[OK] Backup created at: ${this.backupDir}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Restore backed up files if installation fails
|
|
52
|
+
async restoreBackupIfNeeded(success) {
|
|
53
|
+
if (success) {
|
|
54
|
+
console.log('[CLEANUP] Installation successful, cleaning up backup...');
|
|
55
|
+
try {
|
|
56
|
+
const rimraf = require('rimraf');
|
|
57
|
+
rimraf.sync(this.backupDir);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
// If rimraf is not available, just leave the backup
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
console.log('[RESTORE] Installation failed, restoring backed up files...');
|
|
63
|
+
// We would restore files here if needed
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Monitor installation for conflicts
|
|
68
|
+
async monitorInstallation() {
|
|
69
|
+
console.log('[MONITOR] Monitoring installation for conflicts...');
|
|
70
|
+
|
|
71
|
+
// Check for the specific issue we're trying to prevent
|
|
72
|
+
const nodePackageDir = path.join(this.npmBinDir, 'node_modules', 'node');
|
|
73
|
+
try {
|
|
74
|
+
await fs.access(nodePackageDir);
|
|
75
|
+
console.warn('[WARNING] Detected "node" package installation during installation!');
|
|
76
|
+
console.warn('[WARNING] This may cause conflicts with other CLI tools.');
|
|
77
|
+
console.warn('[WARNING] If you experience issues, run: npm run fix-node-conflict');
|
|
78
|
+
} catch (error) {
|
|
79
|
+
// Package doesn't exist, that's good
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Safe installation process
|
|
84
|
+
async install() {
|
|
85
|
+
let success = false;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
// Step 1: Backup potential conflicts
|
|
89
|
+
await this.backupPotentialConflicts();
|
|
90
|
+
|
|
91
|
+
// Step 2: Run the actual installation
|
|
92
|
+
console.log('[INSTALL] Starting safe installation...');
|
|
93
|
+
|
|
94
|
+
// This would be where we run the actual installation logic
|
|
95
|
+
// For now, we'll just simulate it
|
|
96
|
+
|
|
97
|
+
success = true;
|
|
98
|
+
console.log('[SUCCESS] Safe installation completed.');
|
|
99
|
+
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('[ERROR] Installation failed:', error.message);
|
|
102
|
+
} finally {
|
|
103
|
+
// Step 3: Restore backups if needed
|
|
104
|
+
await this.restoreBackupIfNeeded(success);
|
|
105
|
+
|
|
106
|
+
// Step 4: Monitor for conflicts
|
|
107
|
+
await this.monitorInstallation();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return success;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Run safe installation
|
|
115
|
+
async function runSafeInstallation() {
|
|
116
|
+
console.log('Stigmergy Safe Installation');
|
|
117
|
+
console.log('='.repeat(30));
|
|
118
|
+
|
|
119
|
+
const installer = new SafeInstaller();
|
|
120
|
+
const success = await installer.install();
|
|
121
|
+
|
|
122
|
+
if (success) {
|
|
123
|
+
console.log('\n[COMPLETE] Stigmergy installed safely!');
|
|
124
|
+
console.log('[NEXT] Run "stigmergy --help" to get started.');
|
|
125
|
+
} else {
|
|
126
|
+
console.log('\n[FAILED] Installation failed. Please check the errors above.');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Only run if this script is called directly
|
|
132
|
+
if (require.main === module) {
|
|
133
|
+
runSafeInstallation().catch(error => {
|
|
134
|
+
console.error('[FATAL]', error.message);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = { SafeInstaller };
|
|
@@ -1,59 +1,57 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stigmergy CLI
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const {
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
console.log(`📦
|
|
24
|
-
console.log(`📦
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
console.log(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
console.log('
|
|
43
|
-
console.log('
|
|
44
|
-
console.log('
|
|
45
|
-
|
|
46
|
-
console.log('
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
main();
|
|
59
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stigmergy CLI 简化发布脚�? */
|
|
5
|
+
|
|
6
|
+
const { execSync } = 'child_process';
|
|
7
|
+
const { readFile } from 'fs/promises';
|
|
8
|
+
const { join, dirname } from 'path';
|
|
9
|
+
const { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
|
|
14
|
+
console.log('🚀 Stigmergy CLI 发布工具');
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
try {
|
|
18
|
+
// 读取package.json
|
|
19
|
+
const packagePath = join(__dirname, 'package.json');
|
|
20
|
+
const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
|
|
21
|
+
|
|
22
|
+
console.log(`📦 包名: ${pkg.name}`);
|
|
23
|
+
console.log(`📦 版本: ${pkg.version}`);
|
|
24
|
+
console.log(`📦 描述: ${pkg.description}`);
|
|
25
|
+
|
|
26
|
+
// 检查必要文�? const requiredFiles = ['src/index.js', 'package.json', 'README.md', 'LICENSE'];
|
|
27
|
+
console.log('📍 检查必要文�?..');
|
|
28
|
+
|
|
29
|
+
for (const file of requiredFiles) {
|
|
30
|
+
try {
|
|
31
|
+
execSync(`test -f ${file}`, { cwd: __dirname });
|
|
32
|
+
console.log(`�?${file} 存在`);
|
|
33
|
+
} catch {
|
|
34
|
+
console.log(`�?${file} 不存在`);
|
|
35
|
+
throw new Error(`缺少必要文件: ${file}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 模拟npm发布
|
|
40
|
+
console.log('📤 模拟npm发布...');
|
|
41
|
+
console.log('⚠️ 注意: 这是模拟发布,实际发布需�?');
|
|
42
|
+
console.log(' 1. npm login');
|
|
43
|
+
console.log(' 2. node scripts/simple-publish.js');
|
|
44
|
+
console.log(' 3. npm publish');
|
|
45
|
+
|
|
46
|
+
console.log('�?模拟发布完成�?);
|
|
47
|
+
console.log('📦 包准备就绪,可以实际发布');
|
|
48
|
+
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('�?发布过程失败:', error.message);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
56
|
+
main();
|
|
57
|
+
}
|