stigmergy 1.2.13 → 1.3.2-beta.1

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.
Files changed (50) hide show
  1. package/README.md +39 -3
  2. package/STIGMERGY.md +3 -0
  3. package/config/enhanced-cli-config.json +438 -0
  4. package/docs/CLI_TOOLS_AGENT_SKILL_ANALYSIS.md +463 -0
  5. package/docs/ENHANCED_CLI_AGENT_SKILL_CONFIG.md +285 -0
  6. package/docs/INSTALLER_ARCHITECTURE.md +257 -0
  7. package/docs/SUDO_PROBLEM_AND_SOLUTION.md +529 -0
  8. package/package.json +16 -5
  9. package/scripts/analyze-router.js +168 -0
  10. package/scripts/run-comprehensive-tests.js +230 -0
  11. package/scripts/run-quick-tests.js +90 -0
  12. package/scripts/test-runner.js +344 -0
  13. package/src/cli/commands/autoinstall.js +158 -0
  14. package/src/cli/commands/errors.js +190 -0
  15. package/src/cli/commands/install.js +142 -0
  16. package/src/cli/commands/permissions.js +108 -0
  17. package/src/cli/commands/project.js +449 -0
  18. package/src/cli/commands/resume.js +136 -0
  19. package/src/cli/commands/scan.js +97 -0
  20. package/src/cli/commands/skills.js +158 -0
  21. package/src/cli/commands/status.js +106 -0
  22. package/src/cli/commands/system.js +301 -0
  23. package/src/cli/router-beta.js +477 -0
  24. package/src/cli/utils/environment.js +75 -0
  25. package/src/cli/utils/formatters.js +47 -0
  26. package/src/cli/utils/skills_cache.js +92 -0
  27. package/src/core/cache_cleaner.js +1 -0
  28. package/src/core/cli_adapters.js +345 -0
  29. package/src/core/cli_help_analyzer.js +473 -1
  30. package/src/core/cli_path_detector.js +2 -1
  31. package/src/core/cli_tools.js +107 -0
  32. package/src/core/coordination/nodejs/HookDeploymentManager.js +204 -416
  33. package/src/core/coordination/nodejs/HookDeploymentManager.refactored.js +323 -0
  34. package/src/core/coordination/nodejs/generators/CLIAdapterGenerator.js +363 -0
  35. package/src/core/coordination/nodejs/generators/ResumeSessionGenerator.js +703 -0
  36. package/src/core/coordination/nodejs/generators/SkillsIntegrationGenerator.js +1210 -0
  37. package/src/core/coordination/nodejs/generators/index.js +12 -0
  38. package/src/core/enhanced_cli_installer.js +375 -31
  39. package/src/core/enhanced_cli_parameter_handler.js +395 -0
  40. package/src/core/execution_mode_detector.js +222 -0
  41. package/src/core/installer.js +83 -67
  42. package/src/core/local_skill_scanner.js +732 -0
  43. package/src/core/multilingual/language-pattern-manager.js +1 -1
  44. package/src/core/skills/StigmergySkillManager.js +26 -8
  45. package/src/core/smart_router.js +279 -2
  46. package/src/index.js +10 -4
  47. package/test/cli-integration.test.js +304 -0
  48. package/test/enhanced-cli-agent-skill-test.js +485 -0
  49. package/test/specific-cli-agent-skill-analysis.js +385 -0
  50. package/src/cli/router.js +0 -1783
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Enhanced Test Runner for HookDeploymentManager Test Suite
5
+ * Provides comprehensive testing with reporting and analysis
6
+ */
7
+
8
+ const { execSync } = require('child_process');
9
+ const fs = require('fs-extra');
10
+ const path = require('path');
11
+ const chalk = require('chalk');
12
+
13
+ class TestRunner {
14
+ constructor() {
15
+ this.testResults = {
16
+ unit: { passed: 0, failed: 0, total: 0, duration: 0 },
17
+ integration: { passed: 0, failed: 0, total: 0, duration: 0 },
18
+ regression: { passed: 0, failed: 0, total: 0, duration: 0 },
19
+ performance: { passed: 0, failed: 0, total: 0, duration: 0 }
20
+ };
21
+ this.startTime = Date.now();
22
+ }
23
+
24
+ log(message, type = 'info') {
25
+ const colors = {
26
+ info: chalk.blue,
27
+ success: chalk.green,
28
+ warning: chalk.yellow,
29
+ error: chalk.red
30
+ };
31
+
32
+ console.log(colors[type](`[${new Date().toLocaleTimeString()}] ${message}`));
33
+ }
34
+
35
+ async runCommand(command, description) {
36
+ this.log(`Running: ${description}...`);
37
+ const startTime = Date.now();
38
+
39
+ try {
40
+ const output = execSync(command, {
41
+ encoding: 'utf8',
42
+ stdio: 'pipe'
43
+ });
44
+
45
+ const duration = Date.now() - startTime;
46
+ this.log(`${description} completed successfully (${duration}ms)`, 'success');
47
+
48
+ return {
49
+ success: true,
50
+ output,
51
+ duration
52
+ };
53
+ } catch (error) {
54
+ const duration = Date.now() - startTime;
55
+ this.log(`${description} failed after ${duration}ms`, 'error');
56
+
57
+ return {
58
+ success: false,
59
+ error: error.message,
60
+ output: error.stdout,
61
+ duration
62
+ };
63
+ }
64
+ }
65
+
66
+ parseJestOutput(output) {
67
+ const lines = output.split('\n');
68
+ const results = {
69
+ passed: 0,
70
+ failed: 0,
71
+ total: 0,
72
+ suites: 0
73
+ };
74
+
75
+ lines.forEach(line => {
76
+ const match = line.match(/Tests:\s+(\d+)\s+passed,\s+(\d+)\s+failed/);
77
+ if (match) {
78
+ results.passed = parseInt(match[1]);
79
+ results.failed = parseInt(match[2]);
80
+ results.total = results.passed + results.failed;
81
+ }
82
+
83
+ const suiteMatch = line.match(/Test Suites:\s+(\d+)\s+passed,\s+(\d+)\s+failed/);
84
+ if (suiteMatch) {
85
+ results.suites = parseInt(suiteMatch[1]) + parseInt(suiteMatch[2]);
86
+ }
87
+ });
88
+
89
+ return results;
90
+ }
91
+
92
+ async runUnitTests() {
93
+ this.log('\n🧪 Running Unit Tests', 'info');
94
+
95
+ const result = await this.runCommand(
96
+ 'npm run test:unit -- --verbose --json',
97
+ 'Unit Tests'
98
+ );
99
+
100
+ if (result.success) {
101
+ const jestOutput = result.output;
102
+ try {
103
+ const jsonMatch = jestOutput.match(/\{[\s\S]*\}/);
104
+ if (jsonMatch) {
105
+ const jestResults = JSON.parse(jsonMatch[0]);
106
+ this.testResults.unit.passed = jestResults.numPassedTests || 0;
107
+ this.testResults.unit.failed = jestResults.numFailedTests || 0;
108
+ this.testResults.unit.total = jestResults.numTotalTests || 0;
109
+ this.testResults.unit.duration = jestResults.testResults?.reduce(
110
+ (total, test) => total + (test.duration || 0), 0
111
+ ) || 0;
112
+ } else {
113
+ const parsed = this.parseJestOutput(result.output);
114
+ Object.assign(this.testResults.unit, parsed);
115
+ }
116
+ } catch (parseError) {
117
+ this.log('Failed to parse Jest output, using fallback parsing', 'warning');
118
+ const parsed = this.parseJestOutput(result.output);
119
+ Object.assign(this.testResults.unit, parsed);
120
+ }
121
+ } else {
122
+ this.testResults.unit.failed = 1;
123
+ }
124
+
125
+ return result.success;
126
+ }
127
+
128
+ async runIntegrationTests() {
129
+ this.log('\nšŸ”— Running Integration Tests', 'info');
130
+
131
+ const result = await this.runCommand(
132
+ 'npm run test:integration -- --verbose',
133
+ 'Integration Tests'
134
+ );
135
+
136
+ if (result.success) {
137
+ const parsed = this.parseJestOutput(result.output);
138
+ Object.assign(this.testResults.integration, parsed);
139
+ this.testResults.integration.duration = result.duration;
140
+ } else {
141
+ this.testResults.integration.failed = 1;
142
+ }
143
+
144
+ return result.success;
145
+ }
146
+
147
+ async runRegressionTests() {
148
+ this.log('\nšŸ”„ Running Regression Tests', 'info');
149
+
150
+ const result = await this.runCommand(
151
+ 'npm run test:regression -- --verbose',
152
+ 'Regression Tests'
153
+ );
154
+
155
+ if (result.success) {
156
+ const parsed = this.parseJestOutput(result.output);
157
+ Object.assign(this.testResults.regression, parsed);
158
+ this.testResults.regression.duration = result.duration;
159
+ } else {
160
+ this.testResults.regression.failed = 1;
161
+ }
162
+
163
+ return result.success;
164
+ }
165
+
166
+ async runPerformanceTests() {
167
+ this.log('\n⚔ Running Performance Tests', 'info');
168
+
169
+ const result = await this.runCommand(
170
+ 'npm run test:performance -- --verbose',
171
+ 'Performance Tests'
172
+ );
173
+
174
+ if (result.success) {
175
+ const parsed = this.parseJestOutput(result.output);
176
+ Object.assign(this.testResults.performance, parsed);
177
+ this.testResults.performance.duration = result.duration;
178
+ } else {
179
+ this.testResults.performance.failed = 1;
180
+ }
181
+
182
+ return result.success;
183
+ }
184
+
185
+ generateReport() {
186
+ const totalDuration = Date.now() - this.startTime;
187
+ const allTests = Object.values(this.testResults);
188
+ const totalPassed = allTests.reduce((sum, cat) => sum + cat.passed, 0);
189
+ const totalFailed = allTests.reduce((sum, cat) => sum + cat.failed, 0);
190
+ const totalTests = totalPassed + totalFailed;
191
+
192
+ console.log('\n' + '='.repeat(80));
193
+ console.log(chalk.bold.blue('šŸ“Š TEST SUITE REPORT'));
194
+ console.log('='.repeat(80));
195
+
196
+ // Summary
197
+ console.log(chalk.bold('\nšŸ“‹ SUMMARY:'));
198
+ console.log(`Total Duration: ${(totalDuration / 1000).toFixed(2)}s`);
199
+ console.log(`Total Tests: ${totalTests}`);
200
+ console.log(`Passed: ${chalk.green(totalPassed)}`);
201
+ console.log(`Failed: ${chalk.red(totalFailed)}`);
202
+ console.log(`Success Rate: ${((totalPassed / totalTests) * 100).toFixed(1)}%`);
203
+
204
+ // Category breakdown
205
+ console.log(chalk.bold('\nšŸ“‚ TEST CATEGORIES:'));
206
+
207
+ const categories = [
208
+ { name: 'Unit Tests', key: 'unit', icon: '🧪' },
209
+ { name: 'Integration Tests', key: 'integration', icon: 'šŸ”—' },
210
+ { name: 'Regression Tests', key: 'regression', icon: 'šŸ”„' },
211
+ { name: 'Performance Tests', key: 'performance', icon: '⚔' }
212
+ ];
213
+
214
+ categories.forEach(category => {
215
+ const results = this.testResults[category.key];
216
+ const success = results.failed === 0;
217
+ const status = success ? 'āœ…' : 'āŒ';
218
+ const color = success ? chalk.green : chalk.red;
219
+
220
+ console.log(`\n${category.icon} ${category.name}: ${status}`);
221
+ console.log(` Tests: ${results.total}`);
222
+ console.log(` Passed: ${color(results.passed)}`);
223
+ console.log(` Failed: ${results.failed > 0 ? chalk.red(results.failed) : results.failed}`);
224
+ console.log(` Duration: ${(results.duration / 1000).toFixed(2)}s`);
225
+ });
226
+
227
+ // Coverage information if available
228
+ const coveragePath = path.join(process.cwd(), 'coverage', 'coverage-summary.json');
229
+ if (fs.existsSync(coveragePath)) {
230
+ try {
231
+ const coverage = fs.readJsonSync(coveragePath);
232
+ console.log(chalk.bold('\nšŸ“ˆ COVERAGE SUMMARY:'));
233
+ console.log(`Lines: ${coverage.total.lines.pct}%`);
234
+ console.log(`Functions: ${coverage.total.functions.pct}%`);
235
+ console.log(`Branches: ${coverage.total.branches.pct}%`);
236
+ console.log(`Statements: ${coverage.total.statements.pct}%`);
237
+ } catch (error) {
238
+ this.log('Could not read coverage information', 'warning');
239
+ }
240
+ }
241
+
242
+ console.log('\n' + '='.repeat(80));
243
+
244
+ // Exit with appropriate code
245
+ const exitCode = totalFailed > 0 ? 1 : 0;
246
+
247
+ if (exitCode === 0) {
248
+ console.log(chalk.green.bold('\nšŸŽ‰ ALL TESTS PASSED!'));
249
+ } else {
250
+ console.log(chalk.red.bold(`\nāŒ ${totalFailed} TEST(S) FAILED!`));
251
+ }
252
+
253
+ return exitCode;
254
+ }
255
+
256
+ async runTestSuite() {
257
+ console.log(chalk.bold.blue('šŸš€ Starting HookDeploymentManager Test Suite'));
258
+ console.log(`Node.js version: ${process.version}`);
259
+ console.log(`Platform: ${process.platform}`);
260
+ console.log(`Working directory: ${process.cwd()}`);
261
+
262
+ try {
263
+ // Clean previous results
264
+ await fs.remove('coverage');
265
+ await fs.remove('test-results');
266
+
267
+ const unitSuccess = await this.runUnitTests();
268
+ const integrationSuccess = await this.runIntegrationTests();
269
+ const regressionSuccess = await this.runRegressionTests();
270
+
271
+ // Run performance tests only if others pass (to save time)
272
+ let performanceSuccess = true;
273
+ if (unitSuccess && integrationSuccess && regressionSuccess) {
274
+ performanceSuccess = await this.runPerformanceTests();
275
+ } else {
276
+ this.log('Skipping performance tests due to failures in other categories', 'warning');
277
+ }
278
+
279
+ // Generate report and exit
280
+ const exitCode = this.generateReport();
281
+ process.exit(exitCode);
282
+
283
+ } catch (error) {
284
+ this.log(`Test runner error: ${error.message}`, 'error');
285
+ console.error(error.stack);
286
+ process.exit(1);
287
+ }
288
+ }
289
+ }
290
+
291
+ // CLI interface
292
+ if (require.main === module) {
293
+ const runner = new TestRunner();
294
+
295
+ // Parse command line arguments
296
+ const args = process.argv.slice(2);
297
+
298
+ if (args.includes('--help') || args.includes('-h')) {
299
+ console.log(`
300
+ HookDeploymentManager Test Runner
301
+
302
+ Usage: node scripts/test-runner.js [options]
303
+
304
+ Options:
305
+ --help, -h Show this help message
306
+ --unit-only Run only unit tests
307
+ --integration-only Run only integration tests
308
+ --regression-only Run only regression tests
309
+ --performance-only Run only performance tests
310
+ --no-performance Skip performance tests
311
+ --verbose Enable verbose output
312
+
313
+ Examples:
314
+ node scripts/test-runner.js # Run all tests
315
+ node scripts/test-runner.js --unit-only # Run only unit tests
316
+ node scripts/test-runner.js --no-performance # Skip performance tests
317
+ `);
318
+ process.exit(0);
319
+ }
320
+
321
+ // Handle specific test category requests
322
+ if (args.includes('--unit-only')) {
323
+ runner.runUnitTests().then(success => {
324
+ process.exit(success ? 0 : 1);
325
+ });
326
+ } else if (args.includes('--integration-only')) {
327
+ runner.runIntegrationTests().then(success => {
328
+ process.exit(success ? 0 : 1);
329
+ });
330
+ } else if (args.includes('--regression-only')) {
331
+ runner.runRegressionTests().then(success => {
332
+ process.exit(success ? 0 : 1);
333
+ });
334
+ } else if (args.includes('--performance-only')) {
335
+ runner.runPerformanceTests().then(success => {
336
+ process.exit(success ? 0 : 1);
337
+ });
338
+ } else {
339
+ // Run all tests
340
+ runner.runTestSuite();
341
+ }
342
+ }
343
+
344
+ module.exports = TestRunner;
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Auto-install Command
3
+ * Modular implementation for automated CLI tool installation (npm postinstall)
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const { handleInstallCommand } = require('./install');
8
+
9
+ /**
10
+ * Handle auto-install command - Automated installation for npm postinstall
11
+ * @param {Object} options - Command options
12
+ */
13
+ async function handleAutoInstallCommand(options = {}) {
14
+ try {
15
+ // Detect npm environment for better output visibility
16
+ const isNpmPostinstall = process.env.npm_lifecycle_event === 'postinstall';
17
+
18
+ // Use stderr for critical messages in npm environment (more likely to be shown)
19
+ const criticalLog = isNpmPostinstall ? console.error : console.log;
20
+
21
+ criticalLog(chalk.cyan('šŸš€ STIGMERGY CLI AUTO-INSTALL STARTING'));
22
+ criticalLog('='.repeat(60));
23
+ criticalLog('Installing cross-CLI integration and scanning for AI tools...');
24
+ criticalLog('='.repeat(60));
25
+
26
+ console.log(chalk.blue('[AUTO-INSTALL] Stigmergy CLI automated setup'));
27
+ console.log('='.repeat(60));
28
+
29
+ // Check if we're in npm postinstall environment
30
+ if (isNpmPostinstall) {
31
+ console.log(chalk.yellow('šŸ“¦ Detected npm postinstall environment'));
32
+ console.log(chalk.gray('Setting up CLI integrations automatically...'));
33
+ }
34
+
35
+ // Auto-install options - non-interactive mode
36
+ const autoInstallOptions = {
37
+ cli: 'all', // Install all available CLI tools
38
+ verbose: options.verbose || process.env.DEBUG === 'true',
39
+ force: options.force || false,
40
+ nonInteractive: true, // Critical for automated installation
41
+ autoDetect: true, // Auto-detect available tools
42
+ skipPermissionCheck: process.env.STIGMERGY_SKIP_PERMISSION_CHECK === 'true'
43
+ };
44
+
45
+ console.log(chalk.blue('šŸ” Scanning for available CLI tools...'));
46
+
47
+ // Run the installation
48
+ console.log(chalk.blue('šŸ› ļø Starting automated CLI tool installation...'));
49
+
50
+ const installResult = await handleInstallCommand(autoInstallOptions);
51
+
52
+ if (installResult.success) {
53
+ console.log(chalk.green('\nāœ… Auto-install completed successfully!'));
54
+
55
+ if (isNpmPostinstall) {
56
+ criticalLog(chalk.green('āœ… STIGMERGY CLI SETUP COMPLETE'));
57
+ criticalLog(chalk.gray('You can now use: stigmergy <tool> <command>'));
58
+ }
59
+
60
+ // Show summary of what was installed
61
+ if (installResult.installed && installResult.installed.length > 0) {
62
+ console.log(chalk.blue('\nšŸ“‹ Installation Summary:'));
63
+ installResult.installed.forEach(tool => {
64
+ console.log(` ${chalk.green('āœ…')} ${tool}`);
65
+ });
66
+ }
67
+
68
+ if (installResult.failed && installResult.failed.length > 0) {
69
+ console.log(chalk.blue('\nāŒ Failed Tools:'));
70
+ installResult.failed.forEach(tool => {
71
+ console.log(` ${chalk.red('āŒ')} ${tool} (installation failed)`);
72
+ });
73
+ }
74
+
75
+ if (installResult.existing && installResult.existing.length > 0) {
76
+ console.log(chalk.blue('\nšŸ”§ Already Available:'));
77
+ installResult.existing.forEach(tool => {
78
+ console.log(` ${chalk.yellow('āš ļø')} ${tool} (already installed)`);
79
+ });
80
+ }
81
+
82
+ } else {
83
+ console.log(chalk.red('\nāŒ Auto-install encountered issues'));
84
+
85
+ if (isNpmPostinstall) {
86
+ criticalLog(chalk.red('āŒ STIGMERGY CLI SETUP INCOMPLETE'));
87
+ criticalLog(chalk.yellow('Run: stigmergy install to complete setup manually'));
88
+ }
89
+
90
+ if (installResult.error) {
91
+ console.log(chalk.red(`Error: ${installResult.error}`));
92
+ }
93
+ }
94
+
95
+ // Setup verification
96
+ console.log(chalk.blue('\nšŸ” Verifying installation...'));
97
+
98
+ // Quick verification of core functionality
99
+ const verificationChecks = [
100
+ { name: 'Core modules accessible', check: () => require('../utils/formatters') && require('../utils/environment') },
101
+ { name: 'Error handler available', check: () => require('../../core/error_handler') },
102
+ { name: 'Smart router available', check: () => require('../../core/smart_router') }
103
+ ];
104
+
105
+ let verificationPassed = 0;
106
+ for (const check of verificationChecks) {
107
+ try {
108
+ check.check();
109
+ console.log(` ${chalk.green('āœ…')} ${check.name}`);
110
+ verificationPassed++;
111
+ } catch (error) {
112
+ console.log(` ${chalk.red('āŒ')} ${check.name}`);
113
+ }
114
+ }
115
+
116
+ if (verificationPassed === verificationChecks.length) {
117
+ console.log(chalk.green('\nāœ… All verification checks passed!'));
118
+
119
+ if (isNpmPostinstall) {
120
+ criticalLog(chalk.green('šŸŽ‰ STIGMERGY CLI IS READY TO USE!'));
121
+ }
122
+ } else {
123
+ console.log(chalk.yellow('\nāš ļø Some verification checks failed'));
124
+ console.log(chalk.yellow('Run: stigmergy diagnostic for full system check'));
125
+ }
126
+
127
+ // Final summary for npm environment
128
+ if (isNpmPostinstall) {
129
+ criticalLog('='.repeat(60));
130
+ criticalLog(chalk.cyan('šŸŽÆ STIGMERGY CLI AUTO-INSTALL FINISHED'));
131
+ criticalLog('='.repeat(60));
132
+ }
133
+
134
+ return {
135
+ success: installResult.success,
136
+ verificationPassed,
137
+ installed: installResult.installed || [],
138
+ existing: installResult.existing || []
139
+ };
140
+
141
+ } catch (error) {
142
+ const isNpmPostinstall = process.env.npm_lifecycle_event === 'postinstall';
143
+ const criticalLog = isNpmPostinstall ? console.error : console.log;
144
+
145
+ console.error(chalk.red('[ERROR] Auto-install failed:'), error.message);
146
+
147
+ if (isNpmPostinstall) {
148
+ criticalLog(chalk.red('šŸ’„ AUTO-INSTALL FAILED'));
149
+ criticalLog(chalk.yellow('Run: stigmergy install --verbose for detailed installation'));
150
+ }
151
+
152
+ return { success: false, error: error.message };
153
+ }
154
+ }
155
+
156
+ module.exports = {
157
+ handleAutoInstallCommand
158
+ };
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Error Reporting Commands
3
+ * Modular implementation for error reporting and system troubleshooting
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const { errorHandler } = require('../../core/error_handler');
8
+ const fs = require('fs').promises;
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ /**
13
+ * Handle errors command - Generate comprehensive error report
14
+ * @param {Object} options - Command options
15
+ */
16
+ async function handleErrorsCommand(options = {}) {
17
+ try {
18
+ console.log(chalk.cyan('[ERRORS] Generating Stigmergy CLI error report...\n'));
19
+
20
+ const report = {
21
+ timestamp: new Date().toISOString(),
22
+ system: {},
23
+ environment: {},
24
+ errors: [],
25
+ diagnostics: {}
26
+ };
27
+
28
+ // System information
29
+ console.log(chalk.blue('šŸ–„ļø System Information:'));
30
+ report.system = {
31
+ platform: os.platform(),
32
+ arch: os.arch(),
33
+ nodeVersion: process.version,
34
+ memory: Math.round(os.totalmem() / 1024 / 1024) + ' MB',
35
+ freeMemory: Math.round(os.freemem() / 1024 / 1024) + ' MB'
36
+ };
37
+
38
+ Object.entries(report.system).forEach(([key, value]) => {
39
+ console.log(` ${key}: ${chalk.green(value)}`);
40
+ });
41
+
42
+ // Environment information
43
+ console.log(chalk.blue('\nšŸŒ Environment Information:'));
44
+ report.environment = {
45
+ pwd: process.cwd(),
46
+ home: os.homedir(),
47
+ shell: process.env.SHELL || process.env.COMSPEC || 'unknown',
48
+ path: process.env.PATH ? process.env.PATH.split(path.delimiter).slice(0, 3).join(path.delimiter) + '...' : 'unknown',
49
+ nodeEnv: process.env.NODE_ENV || 'undefined',
50
+ debugMode: process.env.DEBUG === 'true'
51
+ };
52
+
53
+ Object.entries(report.environment).forEach(([key, value]) => {
54
+ console.log(` ${key}: ${chalk.green(value)}`);
55
+ });
56
+
57
+ // Error handler report (if available)
58
+ console.log(chalk.blue('\nšŸ“‹ Error Handler Report:'));
59
+ try {
60
+ if (errorHandler && typeof errorHandler.printErrorReport === 'function') {
61
+ await errorHandler.printErrorReport();
62
+ console.log(chalk.green(' āœ… Error handler report generated'));
63
+ } else {
64
+ console.log(chalk.yellow(' āš ļø Error handler not available'));
65
+ }
66
+ } catch (error) {
67
+ console.log(chalk.red(` āŒ Error handler failed: ${error.message}`));
68
+ report.errors.push({
69
+ type: 'error_handler',
70
+ message: error.message,
71
+ timestamp: new Date().toISOString()
72
+ });
73
+ }
74
+
75
+ // Check for common issues
76
+ console.log(chalk.blue('\nšŸ” Common Issues Check:'));
77
+
78
+ const checks = [
79
+ {
80
+ name: 'Current directory writable',
81
+ check: async () => {
82
+ try {
83
+ await fs.access(process.cwd(), fs.constants.W_OK);
84
+ return true;
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+ },
90
+ {
91
+ name: 'Home directory accessible',
92
+ check: async () => {
93
+ try {
94
+ await fs.access(os.homedir(), fs.constants.R_OK);
95
+ return true;
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
100
+ },
101
+ {
102
+ name: 'Node modules accessible',
103
+ check: async () => {
104
+ try {
105
+ await fs.access(path.join(process.cwd(), 'node_modules'), fs.constants.R_OK);
106
+ return true;
107
+ } catch {
108
+ return false;
109
+ }
110
+ }
111
+ },
112
+ {
113
+ name: 'Package.json exists',
114
+ check: async () => {
115
+ try {
116
+ await fs.access(path.join(process.cwd(), 'package.json'), fs.constants.R_OK);
117
+ return true;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+ }
123
+ ];
124
+
125
+ for (const check of checks) {
126
+ try {
127
+ const passed = await check.check();
128
+ const icon = passed ? chalk.green('āœ…') : chalk.red('āŒ');
129
+ console.log(` ${icon} ${check.name}`);
130
+
131
+ if (!passed) {
132
+ report.errors.push({
133
+ type: 'common_issue',
134
+ message: `${check.name} failed`,
135
+ timestamp: new Date().toISOString()
136
+ });
137
+ }
138
+ } catch (error) {
139
+ console.log(` ${chalk.yellow('āš ļø')} ${check.name} - Check failed`);
140
+ }
141
+ }
142
+
143
+ // Log files check
144
+ console.log(chalk.blue('\nšŸ“„ Log Files:'));
145
+ const logLocations = [
146
+ path.join(os.homedir(), '.stigmergy', 'logs'),
147
+ path.join(process.cwd(), 'logs'),
148
+ path.join(os.tmpdir(), 'stigmergy-logs')
149
+ ];
150
+
151
+ for (const logLocation of logLocations) {
152
+ try {
153
+ const stats = await fs.stat(logLocation);
154
+ console.log(` ${chalk.green('āœ…')} ${logLocation} (${stats.size} bytes)`);
155
+ } catch {
156
+ console.log(` ${chalk.gray('⚪')} ${logLocation} (not found)`);
157
+ }
158
+ }
159
+
160
+ // Summary
161
+ console.log(chalk.blue('\nšŸ“Š Error Report Summary:'));
162
+ const errorCount = report.errors.length;
163
+ const warningCount = report.environment.debugMode ? 1 : 0;
164
+
165
+ console.log(` Errors: ${chalk.red(errorCount)}`);
166
+ console.log(` Warnings: ${chalk.yellow(warningCount)}`);
167
+
168
+ if (errorCount === 0) {
169
+ console.log(chalk.green('\nāœ… No critical errors detected!'));
170
+ } else {
171
+ console.log(chalk.red(`\nāŒ ${errorCount} issue(s) found - see details above`));
172
+ }
173
+
174
+ // Save report to file if requested
175
+ if (options.save) {
176
+ const reportPath = path.join(process.cwd(), `stigmergy-error-report-${Date.now()}.json`);
177
+ await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
178
+ console.log(chalk.blue(`\nšŸ’¾ Report saved to: ${reportPath}`));
179
+ }
180
+
181
+ return { success: true, report };
182
+ } catch (error) {
183
+ console.error(chalk.red('[ERROR] Failed to generate error report:'), error.message);
184
+ return { success: false, error: error.message };
185
+ }
186
+ }
187
+
188
+ module.exports = {
189
+ handleErrorsCommand
190
+ };