stigmergy 1.3.2-beta.0 → 1.3.2-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stigmergy",
3
- "version": "1.3.2-beta.0",
3
+ "version": "1.3.2-beta.2",
4
4
  "description": "Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -48,6 +48,8 @@
48
48
  "path-fixer": "node path-fixer.js",
49
49
  "emergency-clean": "node emergency-cleanup.js",
50
50
  "test:conflict-prevention": "node test/conflict-prevention-test.js",
51
+ "test:comprehensive": "node scripts/run-comprehensive-tests.js",
52
+ "test:quick": "node scripts/run-quick-tests.js",
51
53
  "post-deployment-config": "node scripts/post-deployment-config.js",
52
54
  "preinstall": "node scripts/preinstall-check.js",
53
55
  "postinstall": "node src/index.js auto-install",
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Comprehensive Test Runner
5
+ * Runs all tests and generates detailed coverage report
6
+ */
7
+
8
+ const { execSync } = require('child_process');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ console.log('šŸŽÆ COMPREHENSIVE TEST SUITE');
13
+ console.log('='.repeat(70));
14
+
15
+ // ANSI color codes
16
+ const colors = {
17
+ reset: '\x1b[0m',
18
+ green: '\x1b[32m',
19
+ red: '\x1b[31m',
20
+ yellow: '\x1b[33m',
21
+ blue: '\x1b[34m',
22
+ cyan: '\x1b[36m'
23
+ };
24
+
25
+ function log(message, color = 'reset') {
26
+ console.log(`${colors[color]}${message}${colors.reset}`);
27
+ }
28
+
29
+ function runCommand(command, description) {
30
+ log(`\nšŸ“¦ ${description}...`, 'cyan');
31
+
32
+ try {
33
+ const output = execSync(command, {
34
+ stdio: 'inherit',
35
+ cwd: process.cwd()
36
+ });
37
+ log(`āœ… ${description} completed`, 'green');
38
+ return true;
39
+ } catch (error) {
40
+ log(`āŒ ${description} failed`, 'red');
41
+ log(`Error: ${error.message}`, 'red');
42
+ return false;
43
+ }
44
+ }
45
+
46
+ function ensureDirectories() {
47
+ const dirs = [
48
+ 'tests/comprehensive/cli',
49
+ 'tests/comprehensive/cli/commands',
50
+ 'tests/comprehensive/core',
51
+ 'tests/comprehensive/coordination',
52
+ 'tests/comprehensive/adapters',
53
+ 'tests/comprehensive/utils',
54
+ 'coverage'
55
+ ];
56
+
57
+ dirs.forEach(dir => {
58
+ const fullPath = path.join(process.cwd(), dir);
59
+ if (!fs.existsSync(fullPath)) {
60
+ fs.mkdirSync(fullPath, { recursive: true });
61
+ }
62
+ });
63
+ }
64
+
65
+ function countTestFiles() {
66
+ const testDirs = [
67
+ 'tests/unit',
68
+ 'tests/integration',
69
+ 'tests/e2e',
70
+ 'tests/comprehensive',
71
+ 'tests/regression'
72
+ ];
73
+
74
+ let totalTests = 0;
75
+ testDirs.forEach(dir => {
76
+ const testPath = path.join(process.cwd(), dir);
77
+ if (fs.existsSync(testPath)) {
78
+ const files = fs.readdirSync(testPath)
79
+ .filter(f => f.endsWith('.test.js'));
80
+ totalTests += files.length;
81
+ }
82
+ });
83
+
84
+ return totalTests;
85
+ }
86
+
87
+ function countSourceFiles() {
88
+ const srcPath = path.join(process.cwd(), 'src');
89
+
90
+ function countDir(dir) {
91
+ let count = 0;
92
+ const items = fs.readdirSync(dir, { withFileTypes: true });
93
+
94
+ items.forEach(item => {
95
+ if (item.isDirectory()) {
96
+ count += countDir(path.join(dir, item.name));
97
+ } else if (item.name.endsWith('.js')) {
98
+ count++;
99
+ }
100
+ });
101
+
102
+ return count;
103
+ }
104
+
105
+ return countDir(srcPath);
106
+ }
107
+
108
+ function printSummary() {
109
+ log('\n' + '='.repeat(70), 'cyan');
110
+ log('šŸ“Š TEST SUITE SUMMARY', 'cyan');
111
+ log('='.repeat(70), 'cyan');
112
+
113
+ const sourceFiles = countSourceFiles();
114
+ const testFiles = countTestFiles();
115
+ const coverage = ((testFiles / sourceFiles) * 100).toFixed(1);
116
+
117
+ log(`\nšŸ“ Source Files: ${sourceFiles}`);
118
+ log(`🧪 Test Files: ${testFiles}`);
119
+ log(`šŸ“ˆ Test Coverage: ${coverage}%`);
120
+
121
+ log('\n' + '='.repeat(70), 'cyan');
122
+ }
123
+
124
+ function readCoverageReport() {
125
+ const coveragePath = path.join(process.cwd(), 'coverage', 'coverage-summary.json');
126
+
127
+ if (!fs.existsSync(coveragePath)) {
128
+ log('\nāš ļø Coverage report not found', 'yellow');
129
+ return;
130
+ }
131
+
132
+ const coverage = JSON.parse(fs.readFileSync(coveragePath, 'utf8'));
133
+
134
+ log('\n' + '='.repeat(70), 'cyan');
135
+ log('šŸ“Š DETAILED COVERAGE REPORT', 'cyan');
136
+ log('='.repeat(70), 'cyan');
137
+
138
+ const total = coverage.total;
139
+ log(`\nšŸ“ˆ Overall Coverage:`, 'cyan');
140
+ log(` Statements: ${total.statements.pct}% (${total.statements.covered}/${total.statements.total})`);
141
+ log(` Branches: ${total.branches.pct}% (${total.branches.covered}/${total.branches.total})`);
142
+ log(` Functions: ${total.functions.pct}% (${total.functions.covered}/${total.functions.total})`);
143
+ log(` Lines: ${total.lines.pct}% (${total.lines.covered}/${total.lines.total})`);
144
+
145
+ // Find files with low coverage
146
+ log('\nšŸ“‰ Files with Low Coverage (< 80%):', 'yellow');
147
+ let lowCoverageFound = false;
148
+
149
+ Object.entries(coverage).forEach(([file, data]) => {
150
+ if (file !== 'total' && data.statements.pct < 80) {
151
+ lowCoverageFound = true;
152
+ const relativePath = file.replace(process.cwd(), '');
153
+ log(` ${relativePath}: ${data.statements.pct}%`, 'red');
154
+ }
155
+ });
156
+
157
+ if (!lowCoverageFound) {
158
+ log(' āœ… All files have good coverage!', 'green');
159
+ }
160
+
161
+ log('\n' + '='.repeat(70), 'cyan');
162
+ }
163
+
164
+ async function main() {
165
+ const startTime = Date.now();
166
+
167
+ try {
168
+ // Ensure test directories exist
169
+ ensureDirectories();
170
+
171
+ // Print initial summary
172
+ log('\nšŸ” Test Environment:', 'blue');
173
+ log(` Node.js: ${process.version}`);
174
+ log(` Platform: ${process.platform}`);
175
+ log(` CWD: ${process.cwd()}`);
176
+
177
+ // Run pre-test cleanup
178
+ log('\n🧹 Cleaning test environment...', 'blue');
179
+ try {
180
+ execSync('npm run clean 2>/dev/null || true', { stdio: 'ignore' });
181
+ } catch (e) {
182
+ // Ignore cleanup errors
183
+ }
184
+
185
+ // Run tests by category
186
+ const results = {
187
+ unit: runCommand('npm run test:unit -- --silent', 'Unit Tests'),
188
+ integration: runCommand('npm run test:integration -- --silent', 'Integration Tests'),
189
+ comprehensive: runCommand('jest tests/comprehensive --coverage --silent', 'Comprehensive Tests')
190
+ };
191
+
192
+ // Generate coverage report
193
+ if (results.comprehensive) {
194
+ readCoverageReport();
195
+ }
196
+
197
+ // Calculate duration
198
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
199
+
200
+ // Print final summary
201
+ printSummary();
202
+
203
+ log(`\nā±ļø Total Duration: ${duration}s`, 'blue');
204
+
205
+ // Determine success
206
+ const allPassed = Object.values(results).every(r => r === true);
207
+
208
+ if (allPassed) {
209
+ log('\nāœ… ALL TESTS PASSED!', 'green');
210
+ log('\nšŸŽ‰ Great job! Your test suite is comprehensive.', 'green');
211
+ process.exit(0);
212
+ } else {
213
+ log('\nāŒ SOME TESTS FAILED', 'red');
214
+ log('\nšŸ’” Run with --verbose to see detailed error messages', 'yellow');
215
+ process.exit(1);
216
+ }
217
+
218
+ } catch (error) {
219
+ log(`\nšŸ’„ Fatal Error: ${error.message}`, 'red');
220
+ console.error(error);
221
+ process.exit(1);
222
+ }
223
+ }
224
+
225
+ // Run if executed directly
226
+ if (require.main === module) {
227
+ main();
228
+ }
229
+
230
+ module.exports = { runCommand, readCoverageReport, printSummary };
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Quick Test Runner
5
+ * Runs only the comprehensive tests without legacy tests
6
+ */
7
+
8
+ const { execSync } = require('child_process');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ console.log('šŸŽÆ QUICK COMPREHENSIVE TEST SUITE');
13
+ console.log('='.repeat(70));
14
+
15
+ // ANSI colors
16
+ const colors = {
17
+ reset: '\x1b[0m',
18
+ green: '\x1b[32m',
19
+ red: '\x1b[31m',
20
+ yellow: '\x1b[33m',
21
+ blue: '\x1b[34m',
22
+ cyan: '\x1b[36m'
23
+ };
24
+
25
+ function log(message, color = 'reset') {
26
+ console.log(`${colors[color]}${message}${colors.reset}`);
27
+ }
28
+
29
+ function runCommand(command, description) {
30
+ log(`\nšŸ“¦ ${description}...`, 'cyan');
31
+
32
+ try {
33
+ const output = execSync(command, {
34
+ stdio: 'inherit',
35
+ cwd: process.cwd()
36
+ });
37
+ log(`āœ… ${description} completed`, 'green');
38
+ return true;
39
+ } catch (error) {
40
+ log(`āŒ ${description} failed`, 'red');
41
+ return false;
42
+ }
43
+ }
44
+
45
+ async function main() {
46
+ const startTime = Date.now();
47
+
48
+ try {
49
+ log('\nšŸ” Running comprehensive tests only...', 'blue');
50
+
51
+ // Ensure directories exist
52
+ const dirs = ['tests/comprehensive/cli/commands', 'tests/comprehensive/core', 'tests/comprehensive/coordination'];
53
+ dirs.forEach(dir => {
54
+ const fullPath = path.join(process.cwd(), dir);
55
+ if (!fs.existsSync(fullPath)) {
56
+ fs.mkdirSync(fullPath, { recursive: true });
57
+ }
58
+ });
59
+
60
+ // Run comprehensive tests only
61
+ const result = runCommand(
62
+ 'jest tests/comprehensive --coverage',
63
+ 'Comprehensive Tests'
64
+ );
65
+
66
+ // Calculate duration
67
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
68
+
69
+ log(`\nā±ļø Duration: ${duration}s`, 'blue');
70
+
71
+ if (result) {
72
+ log('\nāœ… ALL TESTS PASSED!', 'green');
73
+ process.exit(0);
74
+ } else {
75
+ log('\nāŒ SOME TESTS FAILED', 'red');
76
+ log('\nšŸ’” Check the output above for details', 'yellow');
77
+ process.exit(1);
78
+ }
79
+
80
+ } catch (error) {
81
+ log(`\nšŸ’„ Fatal Error: ${error.message}`, 'red');
82
+ process.exit(1);
83
+ }
84
+ }
85
+
86
+ if (require.main === module) {
87
+ main();
88
+ }
89
+
90
+ module.exports = { runCommand };
@@ -150,7 +150,7 @@ async function handleInitCommand(options = {}) {
150
150
 
151
151
  // Create basic config
152
152
  const config = {
153
- version: '1.3.0-beta.0',
153
+ version: '1.3.2-beta.2',
154
154
  created: new Date().toISOString(),
155
155
  project: path.basename(projectDir)
156
156
  };
@@ -95,7 +95,7 @@ async function main() {
95
95
 
96
96
  // Program setup
97
97
  program
98
- .version('1.3.0-beta.0')
98
+ .version('1.3.2-beta.2')
99
99
  .description('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System')
100
100
  .name('stigmergy');
101
101
 
@@ -76,6 +76,11 @@ class HookDeploymentManager {
76
76
  async deployNodeJsHooks(cliName, hookDir, options) {
77
77
  console.log(`[HOOK_DEPLOYMENT] Deploying Node.js hooks for ${cliName}...`);
78
78
 
79
+ // Ensure hook directory exists
80
+ if (!fs.existsSync(hookDir)) {
81
+ fs.mkdirSync(hookDir, { recursive: true });
82
+ }
83
+
79
84
  // Deploy ResumeSession extension
80
85
  await this.deployResumeSessionExtension(cliName, hookDir);
81
86
 
@@ -92,6 +97,11 @@ class HookDeploymentManager {
92
97
  async deployResumeSessionExtension(cliName, hookDir) {
93
98
  console.log(`[HOOK_DEPLOYMENT] Deploying ResumeSession extension for ${cliName}...`);
94
99
 
100
+ // Ensure hook directory exists
101
+ if (!fs.existsSync(hookDir)) {
102
+ fs.mkdirSync(hookDir, { recursive: true });
103
+ }
104
+
95
105
  try {
96
106
  const extensionContent = this.resumeSessionGenerator.generateForCLI(cliName);
97
107
  const fileName = this.resumeSessionGenerator.getFileName(cliName);
@@ -120,6 +130,11 @@ class HookDeploymentManager {
120
130
  async deploySkillsIntegration(cliName, hookDir) {
121
131
  console.log(`[HOOK_DEPLOYMENT] Deploying skills integration for ${cliName}...`);
122
132
 
133
+ // Ensure hook directory exists
134
+ if (!fs.existsSync(hookDir)) {
135
+ fs.mkdirSync(hookDir, { recursive: true });
136
+ }
137
+
123
138
  try {
124
139
  const skillsResult = this.skillsIntegrationGenerator.generateForCLI(cliName);
125
140
  const skillsPath = path.join(hookDir, skillsResult.fileName);
@@ -158,6 +173,11 @@ class HookDeploymentManager {
158
173
  async deployCLIAdapter(cliName, hookDir) {
159
174
  console.log(`[HOOK_DEPLOYMENT] Deploying CLI adapter for ${cliName}...`);
160
175
 
176
+ // Ensure hook directory exists
177
+ if (!fs.existsSync(hookDir)) {
178
+ fs.mkdirSync(hookDir, { recursive: true });
179
+ }
180
+
161
181
  try {
162
182
  const adapterContent = this.cliAdapterGenerator.generateForCLI(cliName);
163
183
  const fileName = this.cliAdapterGenerator.getFileName(cliName);
@@ -184,6 +204,11 @@ class HookDeploymentManager {
184
204
  async createBasicConfiguration(cliName, hookDir) {
185
205
  console.log(`[HOOK_DEPLOYMENT] Creating basic configuration for ${cliName}...`);
186
206
 
207
+ // Ensure hook directory exists
208
+ if (!fs.existsSync(hookDir)) {
209
+ fs.mkdirSync(hookDir, { recursive: true });
210
+ }
211
+
187
212
  try {
188
213
  // Create main configuration file
189
214
  const config = {
@@ -332,12 +332,14 @@ class SessionFilter {
332
332
  switch (timeRange) {
333
333
  case 'today':
334
334
  return sessionDate.toDateString() === now.toDateString();
335
- case 'week':
335
+ case 'week': {
336
336
  const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
337
337
  return sessionDate >= weekAgo;
338
- case 'month':
338
+ }
339
+ case 'month': {
339
340
  const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
340
341
  return sessionDate >= monthAgo;
342
+ }
341
343
  default:
342
344
  return true;
343
345
  }
@@ -565,11 +567,11 @@ function buildQuery(input) {
565
567
 
566
568
  // CLI-specific registration logic
567
569
 
568
- ${this.generateCLIRegistrationCode(cliName, commandName)}
570
+ ${this.generateCLIRegistrationCode(cliName, commandName, projectPath)}
569
571
  `;
570
572
  }
571
573
 
572
- generateCLIRegistrationCode(cliName, commandName) {
574
+ generateCLIRegistrationCode(cliName, commandName, projectPath) {
573
575
  switch (cliName.toLowerCase()) {
574
576
  case 'claude':
575
577
  case 'codebuddy':
@@ -24,13 +24,18 @@ class EnhancedCLIInstaller {
24
24
  ...options
25
25
  };
26
26
 
27
+ // Expose commonly used options as properties for easier access
28
+ this.verbose = this.options.verbose;
29
+ this.force = options.force || false;
30
+ this.homeDir = options.homeDir || require('os').homedir();
27
31
  this.results = {
28
32
  permissionSetup: null,
29
33
  installations: {},
30
34
  failedInstallations: [],
31
35
  npmConfigured: false,
32
36
  workingDirectory: null,
33
- permissionMode: 'standard' // 'standard', 'elevated', 'failed'
37
+ permissionMode: 'standard', // 'standard', 'elevated', 'failed'
38
+ errors: []
34
39
  };
35
40
 
36
41
  this.cliTools = require('./cli_tools').CLI_TOOLS;
@@ -794,6 +799,155 @@ class EnhancedCLIInstaller {
794
799
  getResults() {
795
800
  return this.results;
796
801
  }
802
+
803
+ /**
804
+ * Detect permission availability for the current platform
805
+ */
806
+ detectPermissionAvailability() {
807
+ const platform = process.platform;
808
+
809
+ if (platform === 'win32') {
810
+ // Windows: Check if running as administrator
811
+ try {
812
+ const { execSync } = require('child_process');
813
+ const result = execSync('net session', { encoding: 'utf8' });
814
+ return result.includes('Administrator');
815
+ } catch {
816
+ return false;
817
+ }
818
+ } else {
819
+ // Unix-like systems: Check available privilege escalation tools
820
+ const privilegeEscalationTools = ['sudo', 'doas', 'run0', 'pkexec'];
821
+ for (const tool of privilegeEscalationTools) {
822
+ try {
823
+ const result = spawnSync(tool, ['--version'], {
824
+ stdio: 'pipe',
825
+ timeout: 5000
826
+ });
827
+ if (result.status !== null || result.error?.code !== 'ENOENT') {
828
+ return true;
829
+ }
830
+ } catch {
831
+ continue;
832
+ }
833
+ }
834
+ return false;
835
+ }
836
+ }
837
+
838
+ /**
839
+ * Detect available privilege escalation tools
840
+ */
841
+ detectPrivilegeTools() {
842
+ const platform = process.platform;
843
+ const availableTools = [];
844
+
845
+ if (platform === 'win32') {
846
+ // Windows: Check for admin privileges
847
+ try {
848
+ const { execSync } = require('child_process');
849
+ const result = execSync('net session', { encoding: 'utf8' });
850
+ if (result.includes('Administrator')) {
851
+ availableTools.push('admin');
852
+ }
853
+ } catch {
854
+ // Not running as admin
855
+ }
856
+ } else {
857
+ // Unix-like systems: Check privilege escalation tools
858
+ const tools = [
859
+ { name: 'sudo', checkCmd: ['-n', 'true'] },
860
+ { name: 'doas', checkCmd: ['-n', 'true'] },
861
+ { name: 'run0', checkCmd: ['-n', 'true'] },
862
+ { name: 'pkexec', checkCmd: ['--help'] }
863
+ ];
864
+
865
+ for (const tool of tools) {
866
+ try {
867
+ const result = spawnSync(tool.name, tool.checkCmd, {
868
+ stdio: 'pipe',
869
+ timeout: 5000
870
+ });
871
+ if (result.status !== null || result.error?.code !== 'ENOENT') {
872
+ availableTools.push(tool.name);
873
+ }
874
+ } catch {
875
+ continue;
876
+ }
877
+ }
878
+ }
879
+
880
+ return availableTools;
881
+ }
882
+
883
+ /**
884
+ * Upgrade a single tool
885
+ */
886
+ async upgradeTool(toolName, toolInfo) {
887
+ this.log('info', `Upgrading ${toolName}...`);
888
+
889
+ if (!toolInfo || !toolInfo.install) {
890
+ this.log('warn', `Tool ${toolName} has no install command, skipping upgrade...`);
891
+ this.results.errors.push({
892
+ tool: toolName,
893
+ error: 'No install command specified',
894
+ timestamp: new Date().toISOString()
895
+ });
896
+ return false;
897
+ }
898
+
899
+ const upgradeCommand = `npm upgrade -g ${toolName}`;
900
+
901
+ this.results.installations[toolName] = {
902
+ startTime: Date.now(),
903
+ ...this.results.installations[toolName]
904
+ };
905
+
906
+ try {
907
+ const success = await this.installTool(toolName, {
908
+ ...toolInfo,
909
+ install: upgradeCommand,
910
+ name: `${toolInfo.name} (Upgrade)`
911
+ });
912
+
913
+ return success;
914
+ } catch (error) {
915
+ this.log('error', `Failed to upgrade ${toolName}: ${error.message}`);
916
+ this.results.errors.push({
917
+ tool: toolName,
918
+ error: error.message,
919
+ timestamp: new Date().toISOString()
920
+ });
921
+ return false;
922
+ }
923
+ }
924
+
925
+ /**
926
+ * Get installation summary
927
+ */
928
+ getInstallationSummary() {
929
+ const installations = this.results.installations || {};
930
+ const errors = this.results.errors || [];
931
+
932
+ const total = Object.keys(installations).length;
933
+ const successful = Object.values(installations).filter(i => i.success !== false).length;
934
+ const failed = total - successful;
935
+
936
+ return {
937
+ total,
938
+ successful,
939
+ failed,
940
+ permissionMode: this.permissionMode,
941
+ npmConfigured: this.results.npmConfigured,
942
+ workingDirectory: this.results.workingDirectory,
943
+ errors: errors.map(e => ({
944
+ tool: e.tool,
945
+ error: e.error,
946
+ timestamp: e.timestamp
947
+ })),
948
+ details: installations
949
+ };
950
+ }
797
951
  }
798
952
 
799
953
  module.exports = EnhancedCLIInstaller;
@@ -211,6 +211,12 @@ class StigmergyInstaller extends EnhancedCLIInstaller {
211
211
  const missing = {};
212
212
 
213
213
  for (const [toolName, toolInfo] of Object.entries(this.router.tools)) {
214
+ // Skip internal functions without install command
215
+ if (!toolInfo.install) {
216
+ console.log(`[DEBUG] Tool ${toolName} has no version/install info, skipping check`);
217
+ continue;
218
+ }
219
+
214
220
  try {
215
221
  console.log(`[SCAN] Checking ${toolInfo.name}...`);
216
222
  const isAvailable = await this.checkCLI(toolName);
@@ -335,6 +341,35 @@ class StigmergyInstaller extends EnhancedCLIInstaller {
335
341
  return result;
336
342
  }
337
343
 
344
+ /**
345
+ * Generate hook for a specific CLI tool
346
+ * @param {string} toolName - Name of the CLI tool
347
+ * @param {Object} toolInfo - Tool information object
348
+ */
349
+ async generateToolHook(toolName, toolInfo) {
350
+ console.log(`[HOOK] Generating hook for ${toolName}...`);
351
+
352
+ const HookDeploymentManager = require('./coordination/nodejs/HookDeploymentManager');
353
+ const hookManager = new HookDeploymentManager();
354
+
355
+ await hookManager.initialize();
356
+
357
+ try {
358
+ const deploySuccess = await hookManager.deployHooksForCLI(toolName);
359
+
360
+ if (deploySuccess) {
361
+ console.log(`[OK] Hook generated successfully for ${toolName}`);
362
+ return true;
363
+ } else {
364
+ console.log(`[WARN] Hook generation failed for ${toolName}`);
365
+ return false;
366
+ }
367
+ } catch (error) {
368
+ console.error(`[ERROR] Hook generation error for ${toolName}:`, error.message);
369
+ throw error;
370
+ }
371
+ }
372
+
338
373
  /**
339
374
  * Deploy hooks for available CLI tools
340
375
  */