stigmergy 1.3.10 → 1.3.13

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.10",
3
+ "version": "1.3.13",
4
4
  "description": "Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -336,26 +336,41 @@ async function executeSmartRoutedCommand(route, options = {}) {
336
336
 
337
337
  // Use enhanced parameter handling for one-time mode only
338
338
  if (mode === 'one-time') {
339
- const EnhancedCLIParameterHandler = require('../../core/enhanced_cli_parameter_handler');
340
- const paramHandler = new EnhancedCLIParameterHandler();
341
-
342
- // Generate optimized arguments with agent/skill support
343
- const paramResult = await paramHandler.generateArgumentsWithRetry(
344
- route.tool,
345
- route.prompt,
346
- {
347
- maxRetries,
348
- enableAgentSkillOptimization: true
339
+ try {
340
+ const EnhancedCLIParameterHandler = require('../../core/enhanced_cli_parameter_handler');
341
+ const paramHandler = new EnhancedCLIParameterHandler();
342
+
343
+ // Generate optimized arguments with agent/skill support
344
+ // Add timeout protection for parameter generation
345
+ const timeoutPromise = new Promise((_, reject) => {
346
+ setTimeout(() => reject(new Error('Parameter generation timeout')), 30000); // 30 second timeout for parameter generation
347
+ });
348
+
349
+ const paramPromise = paramHandler.generateArgumentsWithRetry(
350
+ route.tool,
351
+ route.prompt,
352
+ {
353
+ maxRetries,
354
+ enableAgentSkillOptimization: true
355
+ }
356
+ );
357
+
358
+ const paramResult = await Promise.race([paramPromise, timeoutPromise]);
359
+
360
+ toolArgs = paramResult.arguments;
361
+
362
+ // Re-add OAuth authentication (paramResult might overwrite)
363
+ toolArgs = addOAuthAuthArgs(route.tool, toolArgs);
364
+
365
+ if (verbose) {
366
+ console.log(chalk.gray(`[DEBUG] Generated args: ${toolArgs.join(' ')}`));
367
+ }
368
+ } catch (paramError) {
369
+ console.log(chalk.yellow(`[WARN] Parameter generation failed: ${paramError.message}, using basic arguments`));
370
+ // Fallback to basic arguments if enhanced parameter generation fails
371
+ if (verbose) {
372
+ console.log(chalk.gray(`[DEBUG] Falling back to basic args: ${toolArgs.join(' ')}`));
349
373
  }
350
- );
351
-
352
- toolArgs = paramResult.arguments;
353
-
354
- // Re-add OAuth authentication (paramResult might overwrite)
355
- toolArgs = addOAuthAuthArgs(route.tool, toolArgs);
356
-
357
- if (verbose) {
358
- console.log(chalk.gray(`[DEBUG] Generated args: ${toolArgs.join(' ')}`));
359
374
  }
360
375
  } else {
361
376
  if (verbose) {
@@ -379,15 +394,23 @@ async function executeSmartRoutedCommand(route, options = {}) {
379
394
  console.log(chalk.gray(`[DEBUG] Mode: ${mode}`));
380
395
  }
381
396
 
397
+ console.log(chalk.gray(`[EXEC] ${route.tool}: ${route.prompt}`)); // Add this to match direct command format
398
+
382
399
  // Execute the command
383
400
  // For interactive mode, we need stdio: 'inherit' to allow user interaction
401
+ // For one-time mode, we should use 'inherit' to ensure CLI tools can properly execute
402
+ const stdioOption = mode === 'interactive' ? 'inherit' : 'inherit'; // Use 'inherit' for both modes to ensure proper CLI execution
403
+
404
+ console.log(chalk.gray(`[DEBUG] About to execute command with args: ${toolArgs.join(' ')}`)); // Debug log
405
+ console.log(chalk.gray(`[DEBUG] Using stdio option: ${stdioOption}`)); // Debug log
384
406
  const result = await executeCommand(toolPath, toolArgs, {
385
- stdio: mode === 'interactive' ? 'inherit' : 'pipe',
407
+ stdio: stdioOption,
386
408
  shell: true,
387
409
  cwd,
388
410
  env,
389
411
  timeout: 300000 // 5 minutes
390
412
  });
413
+ console.log(chalk.gray(`[DEBUG] Command execution completed`)); // Debug log
391
414
 
392
415
  return { success: true, tool: route.tool, result, mode };
393
416
 
package/src/utils.js CHANGED
@@ -631,10 +631,12 @@ async function executeCommand(command, args = [], options = {}) {
631
631
  const opts = {
632
632
  stdio: 'inherit',
633
633
  shell: true,
634
- timeout: 300000, // 5 minute timeout
635
634
  ...options,
636
635
  };
637
636
 
637
+ // Extract timeout from options to handle separately
638
+ const timeoutValue = options.timeout || 300000; // Default to 5 minutes if not specified
639
+
638
640
  return new Promise((resolve, reject) => {
639
641
  // Don't log the command if it contains sensitive information
640
642
  if (process.env.DEBUG === 'true') {
@@ -704,6 +706,9 @@ async function executeCommand(command, args = [], options = {}) {
704
706
  // Flag to ensure timeout is cleared only once
705
707
  let timeoutCleared = false;
706
708
 
709
+ // Flag to prevent duplicate promise resolution
710
+ let promiseResolved = false;
711
+
707
712
  // Function to clear timeout safely
708
713
  const clearTimeoutSafely = () => {
709
714
  if (timeoutId && !timeoutCleared) {
@@ -712,25 +717,51 @@ async function executeCommand(command, args = [], options = {}) {
712
717
  }
713
718
  };
714
719
 
715
- child.on('exit', (code) => {
720
+ // Function to resolve safely (prevent duplicate resolution)
721
+ const safeResolve = (result) => {
722
+ if (!promiseResolved) {
723
+ promiseResolved = true;
724
+ resolve(result);
725
+ }
726
+ };
727
+
728
+ // Function to reject safely (prevent duplicate rejection)
729
+ const safeReject = (error) => {
730
+ if (!promiseResolved) {
731
+ promiseResolved = true;
732
+ reject(error);
733
+ }
734
+ };
735
+
736
+ child.on('exit', (code, signal) => {
716
737
  // Clear timeout when process exits
717
738
  clearTimeoutSafely();
718
739
 
719
740
  // Resolve with collected stdout/stderr
720
- resolve({
741
+ safeResolve({
721
742
  code,
743
+ signal,
722
744
  stdout,
723
745
  stderr,
724
746
  success: code === 0,
725
747
  });
726
748
  });
727
749
 
728
- child.on('close', (code) => {
750
+ child.on('close', (code, signal) => {
729
751
  // Clear timeout when all stdio streams are closed
730
752
  clearTimeoutSafely();
731
753
 
732
754
  // Only resolve if not already resolved via 'exit' event
733
755
  // This prevents duplicate resolution
756
+ if (!promiseResolved) {
757
+ safeResolve({
758
+ code,
759
+ signal,
760
+ stdout,
761
+ stderr,
762
+ success: code === 0,
763
+ });
764
+ }
734
765
  });
735
766
 
736
767
  child.on('error', (error) => {
@@ -756,16 +787,16 @@ async function executeCommand(command, args = [], options = {}) {
756
787
  });
757
788
 
758
789
  // Handle timeout
759
- if (opts.timeout) {
790
+ if (timeoutValue) {
760
791
  timeoutId = setTimeout(() => {
761
792
  child.kill();
762
793
  reject({
763
794
  error: new Error('Command timeout'),
764
- message: `Command timed out after ${opts.timeout}ms`,
795
+ message: `Command timed out after ${timeoutValue}ms`,
765
796
  stdout,
766
797
  stderr,
767
798
  });
768
- }, opts.timeout);
799
+ }, timeoutValue);
769
800
  }
770
801
  } catch (error) {
771
802
  reject({
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test for basic functionality
5
+ */
6
+
7
+ // Mock the CLI tools to ensure they're available for testing
8
+ jest.doMock('../src/core/cli_tools', () => ({
9
+ CLI_TOOLS: {
10
+ claude: { name: 'Claude CLI', command: 'claude', version: 'claude --version' },
11
+ qwen: { name: 'Qwen CLI', command: 'qwen', version: 'qwen --version' },
12
+ gemini: { name: 'Gemini CLI', command: 'gemini', version: 'gemini --version' },
13
+ iflow: { name: 'iFlow CLI', command: 'iflow', version: 'iflow --version' },
14
+ codebuddy: { name: 'CodeBuddy CLI', command: 'codebuddy', version: 'codebuddy --version' },
15
+ codex: { name: 'Codex CLI', command: 'codex', version: 'codex --version' },
16
+ qodercli: { name: 'QoderCLI', command: 'qodercli', version: 'qodercli --version' },
17
+ copilot: { name: 'Copilot CLI', command: 'copilot', version: 'copilot --version' },
18
+ kode: { name: 'Kode CLI', command: 'kode', version: 'kode --version' }
19
+ },
20
+ validateCLITool: jest.fn().mockReturnValue(true)
21
+ }));
22
+
23
+ // Mock CLIHelpAnalyzer to avoid actual CLI analysis during testing
24
+ jest.doMock('../src/core/cli_help_analyzer', () => {
25
+ return jest.fn().mockImplementation(() => {
26
+ return {
27
+ setCLITools: jest.fn(),
28
+ initialize: jest.fn().mockResolvedValue(undefined),
29
+ analyzeCLI: jest.fn().mockResolvedValue({
30
+ success: true,
31
+ cliName: 'test-cli',
32
+ patterns: {
33
+ commands: [{ name: 'analyze' }, { name: 'generate' }, { name: 'explain' }],
34
+ subcommands: []
35
+ }
36
+ }),
37
+ loadPersistentConfig: jest.fn().mockResolvedValue({
38
+ failedAttempts: {},
39
+ cliPatterns: {}
40
+ }),
41
+ getCachedAnalysis: jest.fn().mockResolvedValue(null),
42
+ isCacheExpired: jest.fn().mockReturnValue(false),
43
+ generateOptimizedCall: jest.fn().mockReturnValue({
44
+ optimizedPrompt: 'test prompt'
45
+ }),
46
+ getAgentSkillCompatibilityScore: jest.fn().mockReturnValue({ score: 0.5, reasons: ['test'] }),
47
+ getEnhancedCLIPattern: jest.fn().mockResolvedValue({})
48
+ };
49
+ });
50
+ });
51
+
52
+ const SmartRouter = require('../src/core/smart_router');
53
+
54
+ async function runSimpleTest() {
55
+ console.log('Running simple test...');
56
+
57
+ try {
58
+ const router = new SmartRouter();
59
+ await router.initialize();
60
+
61
+ console.log('✓ Router initialized successfully');
62
+
63
+ // Test a simple routing case
64
+ const result = await router.smartRoute('use claude to analyze code');
65
+ console.log(`✓ Simple routing test passed: ${result.tool}`);
66
+
67
+ // Test shouldRoute functionality
68
+ const shouldRoute = router.shouldRoute('help with code');
69
+ console.log(`✓ shouldRoute test passed: ${shouldRoute}`);
70
+
71
+ console.log('All simple tests passed!');
72
+ return true;
73
+ } catch (error) {
74
+ console.error('Simple test failed:', error);
75
+ return false;
76
+ }
77
+ }
78
+
79
+ // Run the test
80
+ runSimpleTest().then(success => {
81
+ process.exit(success ? 0 : 1);
82
+ });
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Very simple test without complex mocking
5
+ */
6
+
7
+ // Simple test to check basic functionality
8
+ async function runVerySimpleTest() {
9
+ console.log('Running very simple test...');
10
+
11
+ try {
12
+ // Test basic Node.js functionality
13
+ console.log('✓ Node.js environment is working');
14
+
15
+ // Test basic string operations
16
+ const testString = 'hello world';
17
+ if (testString.toUpperCase() === 'HELLO WORLD') {
18
+ console.log('✓ String operations working');
19
+ } else {
20
+ console.log('✗ String operations failed');
21
+ return false;
22
+ }
23
+
24
+ // Test basic math
25
+ if (2 + 2 === 4) {
26
+ console.log('✓ Math operations working');
27
+ } else {
28
+ console.log('✗ Math operations failed');
29
+ return false;
30
+ }
31
+
32
+ // Test basic array operations
33
+ const arr = [1, 2, 3];
34
+ arr.push(4);
35
+ if (arr.length === 4 && arr[3] === 4) {
36
+ console.log('✓ Array operations working');
37
+ } else {
38
+ console.log('✗ Array operations failed');
39
+ return false;
40
+ }
41
+
42
+ console.log('All very simple tests passed!');
43
+ return true;
44
+ } catch (error) {
45
+ console.error('Very simple test failed:', error);
46
+ return false;
47
+ }
48
+ }
49
+
50
+ // Run the test
51
+ runVerySimpleTest().then(success => {
52
+ console.log(`Test completed with success: ${success}`);
53
+ process.exit(success ? 0 : 1);
54
+ });