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.
- package/README.md +39 -3
- package/STIGMERGY.md +3 -0
- package/config/enhanced-cli-config.json +438 -0
- package/docs/CLI_TOOLS_AGENT_SKILL_ANALYSIS.md +463 -0
- package/docs/ENHANCED_CLI_AGENT_SKILL_CONFIG.md +285 -0
- package/docs/INSTALLER_ARCHITECTURE.md +257 -0
- package/docs/SUDO_PROBLEM_AND_SOLUTION.md +529 -0
- package/package.json +16 -5
- package/scripts/analyze-router.js +168 -0
- package/scripts/run-comprehensive-tests.js +230 -0
- package/scripts/run-quick-tests.js +90 -0
- package/scripts/test-runner.js +344 -0
- package/src/cli/commands/autoinstall.js +158 -0
- package/src/cli/commands/errors.js +190 -0
- package/src/cli/commands/install.js +142 -0
- package/src/cli/commands/permissions.js +108 -0
- package/src/cli/commands/project.js +449 -0
- package/src/cli/commands/resume.js +136 -0
- package/src/cli/commands/scan.js +97 -0
- package/src/cli/commands/skills.js +158 -0
- package/src/cli/commands/status.js +106 -0
- package/src/cli/commands/system.js +301 -0
- package/src/cli/router-beta.js +477 -0
- package/src/cli/utils/environment.js +75 -0
- package/src/cli/utils/formatters.js +47 -0
- package/src/cli/utils/skills_cache.js +92 -0
- package/src/core/cache_cleaner.js +1 -0
- package/src/core/cli_adapters.js +345 -0
- package/src/core/cli_help_analyzer.js +473 -1
- package/src/core/cli_path_detector.js +2 -1
- package/src/core/cli_tools.js +107 -0
- package/src/core/coordination/nodejs/HookDeploymentManager.js +204 -416
- package/src/core/coordination/nodejs/HookDeploymentManager.refactored.js +323 -0
- package/src/core/coordination/nodejs/generators/CLIAdapterGenerator.js +363 -0
- package/src/core/coordination/nodejs/generators/ResumeSessionGenerator.js +703 -0
- package/src/core/coordination/nodejs/generators/SkillsIntegrationGenerator.js +1210 -0
- package/src/core/coordination/nodejs/generators/index.js +12 -0
- package/src/core/enhanced_cli_installer.js +375 -31
- package/src/core/enhanced_cli_parameter_handler.js +395 -0
- package/src/core/execution_mode_detector.js +222 -0
- package/src/core/installer.js +83 -67
- package/src/core/local_skill_scanner.js +732 -0
- package/src/core/multilingual/language-pattern-manager.js +1 -1
- package/src/core/skills/StigmergySkillManager.js +26 -8
- package/src/core/smart_router.js +279 -2
- package/src/index.js +10 -4
- package/test/cli-integration.test.js +304 -0
- package/test/enhanced-cli-agent-skill-test.js +485 -0
- package/test/specific-cli-agent-skill-analysis.js +385 -0
- package/src/cli/router.js +0 -1783
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Command Module
|
|
3
|
+
* Handles CLI tool installation commands
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const StigmergyInstaller = require('../../core/installer');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const { ensureSkillsCache } = require('../utils/skills_cache');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Handle install command
|
|
12
|
+
* @param {Object} options - Command options
|
|
13
|
+
* @param {string} options.cli - Specific CLI to install
|
|
14
|
+
* @param {boolean} options.verbose - Verbose output
|
|
15
|
+
* @param {boolean} options.force - Force installation
|
|
16
|
+
*/
|
|
17
|
+
async function handleInstallCommand(options = {}) {
|
|
18
|
+
const installer = new StigmergyInstaller();
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Initialize or update skills/agents cache
|
|
22
|
+
await ensureSkillsCache({ verbose: options.verbose || process.env.DEBUG === 'true' });
|
|
23
|
+
|
|
24
|
+
console.log(chalk.blue('š Starting CLI tools installation...'));
|
|
25
|
+
|
|
26
|
+
// Handle auto-install mode (non-interactive)
|
|
27
|
+
if (options.nonInteractive) {
|
|
28
|
+
console.log(chalk.blue('[AUTO-INSTALL] Running in non-interactive mode'));
|
|
29
|
+
|
|
30
|
+
// Scan for available and missing tools
|
|
31
|
+
const { missing: missingTools, available: availableTools } = await installer.scanCLI();
|
|
32
|
+
|
|
33
|
+
if (Object.keys(missingTools).length === 0) {
|
|
34
|
+
console.log(chalk.green('ā
All AI CLI tools are already installed!'));
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
installed: [],
|
|
38
|
+
existing: Object.keys(availableTools)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Install all missing tools in auto mode
|
|
43
|
+
const selectedTools = Object.keys(missingTools);
|
|
44
|
+
console.log(chalk.blue(`[AUTO-INSTALL] Installing ${selectedTools.length} tools: ${selectedTools.join(', ')}`));
|
|
45
|
+
|
|
46
|
+
const installResult = await installer.installTools(selectedTools, missingTools);
|
|
47
|
+
|
|
48
|
+
if (installResult.success) {
|
|
49
|
+
console.log(chalk.green('ā
Auto-install completed successfully!'));
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
installed: installResult.installed || [],
|
|
53
|
+
failed: installResult.failed || [],
|
|
54
|
+
existing: Object.keys(availableTools)
|
|
55
|
+
};
|
|
56
|
+
} else {
|
|
57
|
+
console.log(chalk.yellow('ā ļø Some tools may not have installed successfully'));
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
installed: installResult.installed || [],
|
|
61
|
+
failed: installResult.failed || [],
|
|
62
|
+
existing: Object.keys(availableTools),
|
|
63
|
+
error: 'Some installations failed'
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Interactive install mode
|
|
69
|
+
const { missing: missingTools, available: availableTools } = await installer.scanCLI();
|
|
70
|
+
|
|
71
|
+
if (Object.keys(missingTools).length === 0) {
|
|
72
|
+
console.log(chalk.green('ā
All AI CLI tools are already installed!'));
|
|
73
|
+
|
|
74
|
+
if (Object.keys(availableTools).length > 0) {
|
|
75
|
+
console.log(chalk.cyan('\nš¦ Available tools:'));
|
|
76
|
+
Object.keys(availableTools).forEach(tool => {
|
|
77
|
+
console.log(` ā
${tool}`);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
installed: [],
|
|
84
|
+
existing: Object.keys(availableTools)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(chalk.yellow(`\nā ļø Found ${Object.keys(missingTools).length} missing tools:`));
|
|
89
|
+
Object.entries(missingTools).forEach(([toolName, toolInfo]) => {
|
|
90
|
+
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// For now, install all missing tools
|
|
94
|
+
const selectedTools = Object.keys(missingTools);
|
|
95
|
+
const installResult = await installer.installTools(selectedTools, missingTools);
|
|
96
|
+
|
|
97
|
+
if (installResult.success) {
|
|
98
|
+
console.log(chalk.green('ā
Installation completed successfully!'));
|
|
99
|
+
|
|
100
|
+
if (installResult.installed && installResult.installed.length > 0) {
|
|
101
|
+
console.log(chalk.cyan('\nš¦ Installed tools:'));
|
|
102
|
+
installResult.installed.forEach(tool => {
|
|
103
|
+
console.log(` ā
${tool}`);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (installResult.failed && installResult.failed.length > 0) {
|
|
108
|
+
console.log(chalk.red('\nā Failed tools:'));
|
|
109
|
+
installResult.failed.forEach(tool => {
|
|
110
|
+
console.log(` ā ${tool}`);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
installed: installResult.installed || [],
|
|
117
|
+
failed: installResult.failed || [],
|
|
118
|
+
existing: Object.keys(availableTools)
|
|
119
|
+
};
|
|
120
|
+
} else {
|
|
121
|
+
console.log(chalk.red('ā Installation failed!'));
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
installed: installResult.installed || [],
|
|
125
|
+
failed: installResult.failed || [],
|
|
126
|
+
existing: Object.keys(availableTools),
|
|
127
|
+
error: 'Installation failed'
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.log(chalk.red(`ā Installation error: ${error.message}`));
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
error: error.message,
|
|
135
|
+
installed: []
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
handleInstallCommand
|
|
142
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Management Commands
|
|
3
|
+
* Modular implementation for fix-perms and perm-check commands
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const DirectoryPermissionManager = require('../../core/directory_permission_manager');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Handle permission check command
|
|
11
|
+
* @param {Object} options - Command options
|
|
12
|
+
*/
|
|
13
|
+
async function handlePermCheckCommand(options = {}) {
|
|
14
|
+
try {
|
|
15
|
+
console.log(chalk.cyan('[PERM-CHECK] Checking current directory permissions...\n'));
|
|
16
|
+
|
|
17
|
+
const permissionManager = new DirectoryPermissionManager({
|
|
18
|
+
verbose: options.verbose || process.env.DEBUG === 'true'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
22
|
+
|
|
23
|
+
console.log(`š Current directory: ${process.cwd()}`);
|
|
24
|
+
console.log(`š§ Write permission: ${hasWritePermission ? chalk.green('ā
Yes') : chalk.red('ā No')}`);
|
|
25
|
+
|
|
26
|
+
if (!hasWritePermission) {
|
|
27
|
+
console.log('\nš” Suggestions:');
|
|
28
|
+
console.log('1. Run: stigmergy fix-perms # Fix permissions automatically');
|
|
29
|
+
console.log('2. Change to user directory: cd ~');
|
|
30
|
+
console.log('3. Create project directory: mkdir ~/stigmergy && cd ~/stigmergy');
|
|
31
|
+
|
|
32
|
+
console.log('\nš System Info:');
|
|
33
|
+
const sysInfo = permissionManager.getSystemInfo();
|
|
34
|
+
console.log(` Platform: ${sysInfo.platform}`);
|
|
35
|
+
console.log(` Shell: ${sysInfo.shell}`);
|
|
36
|
+
console.log(` Home: ${sysInfo.homeDir}`);
|
|
37
|
+
} else {
|
|
38
|
+
console.log(chalk.green('\nā
Directory permissions are OK!'));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return { success: true, hasWritePermission };
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(chalk.red('[ERROR] Permission check failed:'), error.message);
|
|
44
|
+
return { success: false, error: error.message };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Handle fix permissions command
|
|
50
|
+
* @param {Object} options - Command options
|
|
51
|
+
*/
|
|
52
|
+
async function handleFixPermsCommand(options = {}) {
|
|
53
|
+
try {
|
|
54
|
+
console.log(chalk.cyan('[FIX-PERMS] Setting up working directory with proper permissions...\n'));
|
|
55
|
+
|
|
56
|
+
// Using DirectoryPermissionManager for permission handling
|
|
57
|
+
// This provides the core permission management functionality
|
|
58
|
+
const permissionManager = new DirectoryPermissionManager({
|
|
59
|
+
verbose: options.verbose || process.env.DEBUG === 'true',
|
|
60
|
+
createStigmergyDir: true
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
64
|
+
|
|
65
|
+
if (hasWritePermission) {
|
|
66
|
+
console.log(chalk.green('ā
Current directory already has proper permissions!'));
|
|
67
|
+
return { success: true, alreadyFixed: true };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(chalk.yellow('š§ Attempting to fix permissions...'));
|
|
71
|
+
|
|
72
|
+
// Try to create a .stigmergy directory in user home as fallback
|
|
73
|
+
const fs = require('fs').promises;
|
|
74
|
+
const path = require('path');
|
|
75
|
+
const os = require('os');
|
|
76
|
+
|
|
77
|
+
const stigmergyDir = path.join(os.homedir(), '.stigmergy');
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await fs.mkdir(stigmergyDir, { recursive: true });
|
|
81
|
+
console.log(chalk.green(`ā
Created Stigmergy directory: ${stigmergyDir}`));
|
|
82
|
+
console.log(chalk.yellow('š” Consider changing to this directory for your projects'));
|
|
83
|
+
|
|
84
|
+
return { success: true, createdDirectory: stigmergyDir };
|
|
85
|
+
} catch (mkdirError) {
|
|
86
|
+
console.log(chalk.red('ā Could not create directory or fix permissions'));
|
|
87
|
+
console.log(chalk.red(`Error: ${mkdirError.message}`));
|
|
88
|
+
|
|
89
|
+
console.log('\nš§ Manual fix required:');
|
|
90
|
+
console.log('1. Run in a directory where you have write permissions');
|
|
91
|
+
console.log('2. Try: cd ~ && mkdir stigmergy-workspace && cd stigmergy-workspace');
|
|
92
|
+
|
|
93
|
+
return { success: false, error: mkdirError.message };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(chalk.red('[ERROR] Permission setup failed:'), error.message);
|
|
98
|
+
if (options.verbose) {
|
|
99
|
+
console.error(error.stack);
|
|
100
|
+
}
|
|
101
|
+
return { success: false, error: error.message };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
handlePermCheckCommand,
|
|
107
|
+
handleFixPermsCommand
|
|
108
|
+
};
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Commands
|
|
3
|
+
* Modular implementation for init, setup, deploy, upgrade, call commands
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const { handleStatusCommand } = require('./status');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const { getCLIPath, setupCLIPaths } = require('../../core/cli_tools');
|
|
11
|
+
const SmartRouter = require('../../core/smart_router');
|
|
12
|
+
const EnhancedCLIInstaller = require('../../core/enhanced_cli_installer');
|
|
13
|
+
const StigmergyInstaller = require('../../core/installer');
|
|
14
|
+
const { executeCommand } = require('../../utils');
|
|
15
|
+
const LocalSkillScanner = require('../../core/local_skill_scanner');
|
|
16
|
+
const CLIHelpAnalyzer = require('../../core/cli_help_analyzer');
|
|
17
|
+
const { CLI_TOOLS } = require('../../core/cli_tools');
|
|
18
|
+
const { ensureSkillsCache } = require('../utils/skills_cache');
|
|
19
|
+
|
|
20
|
+
// Import execution mode detection and CLI adapters
|
|
21
|
+
const ExecutionModeDetector = require('../../core/execution_mode_detector');
|
|
22
|
+
const { CLIAdapterManager } = require('../../core/cli_adapters');
|
|
23
|
+
|
|
24
|
+
// Create instances
|
|
25
|
+
const modeDetector = new ExecutionModeDetector();
|
|
26
|
+
const cliAdapterManager = new CLIAdapterManager();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Handle upgrade command
|
|
30
|
+
* @param {Object} options - Command options
|
|
31
|
+
*/
|
|
32
|
+
async function handleUpgradeCommand(options = {}) {
|
|
33
|
+
try {
|
|
34
|
+
console.log(chalk.cyan('[UPGRADE] Starting AI CLI tools upgrade process...\n'));
|
|
35
|
+
|
|
36
|
+
// Initialize or update skills/agents cache
|
|
37
|
+
await ensureSkillsCache({ verbose: process.env.DEBUG === 'true' });
|
|
38
|
+
|
|
39
|
+
const upgradeOptions = {
|
|
40
|
+
dryRun: options.dryRun || false,
|
|
41
|
+
force: options.force || false,
|
|
42
|
+
verbose: options.verbose || process.env.DEBUG === 'true'
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Use enhanced CLI installer for upgrade
|
|
46
|
+
const enhancedInstaller = new EnhancedCLIInstaller({
|
|
47
|
+
verbose: upgradeOptions.verbose,
|
|
48
|
+
autoRetry: true,
|
|
49
|
+
maxRetries: 2
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Get installed tools
|
|
53
|
+
const installer = new StigmergyInstaller({ verbose: upgradeOptions.verbose });
|
|
54
|
+
const { available: installedTools } = await installer.scanCLI();
|
|
55
|
+
|
|
56
|
+
if (Object.keys(installedTools).length === 0) {
|
|
57
|
+
console.log(chalk.yellow('[INFO] No CLI tools found to upgrade'));
|
|
58
|
+
console.log(chalk.blue('š” Run: stigmergy install to install CLI tools first'));
|
|
59
|
+
return { success: true, upgraded: 0 };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(chalk.blue(`[INFO] Found ${Object.keys(installedTools).length} CLI tools to upgrade`));
|
|
63
|
+
|
|
64
|
+
if (upgradeOptions.dryRun) {
|
|
65
|
+
console.log(chalk.yellow('[DRY RUN] Would upgrade the following tools:'));
|
|
66
|
+
Object.keys(installedTools).forEach(tool => {
|
|
67
|
+
console.log(` ⢠${tool}`);
|
|
68
|
+
});
|
|
69
|
+
return { success: true, upgraded: Object.keys(installedTools).length };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Perform upgrade
|
|
73
|
+
console.log(chalk.blue('[INFO] Starting upgrade process...'));
|
|
74
|
+
const toolsToUpgrade = Object.keys(installedTools);
|
|
75
|
+
|
|
76
|
+
const upgradeResult = await enhancedInstaller.upgradeTools(toolsToUpgrade, installedTools);
|
|
77
|
+
|
|
78
|
+
if (upgradeResult) {
|
|
79
|
+
console.log(chalk.green(`\nā
Successfully upgraded ${toolsToUpgrade.length} CLI tools!`));
|
|
80
|
+
return { success: true, upgraded: toolsToUpgrade.length };
|
|
81
|
+
} else {
|
|
82
|
+
console.log(chalk.red('\nā Upgrade process encountered issues'));
|
|
83
|
+
return { success: false, upgraded: 0 };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error(chalk.red('[ERROR] Upgrade failed:'), error.message);
|
|
88
|
+
if (options.verbose) {
|
|
89
|
+
console.error(error.stack);
|
|
90
|
+
}
|
|
91
|
+
return { success: false, error: error.message };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Handle deploy command
|
|
97
|
+
* @param {Object} options - Command options
|
|
98
|
+
*/
|
|
99
|
+
async function handleDeployCommand(options = {}) {
|
|
100
|
+
try {
|
|
101
|
+
console.log(chalk.cyan('[DEPLOY] Starting hook deployment...\n'));
|
|
102
|
+
|
|
103
|
+
const installer = new StigmergyInstaller({ verbose: options.verbose });
|
|
104
|
+
const { available: deployedTools } = await installer.scanCLI();
|
|
105
|
+
|
|
106
|
+
if (Object.keys(deployedTools).length === 0) {
|
|
107
|
+
console.log(chalk.yellow('[INFO] No CLI tools found for deployment'));
|
|
108
|
+
console.log(chalk.blue('š” Run: stigmergy install to install CLI tools first'));
|
|
109
|
+
return { success: true, deployed: 0 };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log(chalk.blue(`[INFO] Deploying hooks for ${Object.keys(deployedTools).length} tools...`));
|
|
113
|
+
|
|
114
|
+
await installer.deployHooks(deployedTools);
|
|
115
|
+
|
|
116
|
+
console.log(chalk.green('\nā
Hook deployment completed successfully!'));
|
|
117
|
+
return { success: true, deployed: Object.keys(deployedTools).length };
|
|
118
|
+
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error(chalk.red('[ERROR] Deployment failed:'), error.message);
|
|
121
|
+
return { success: false, error: error.message };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Handle init command
|
|
127
|
+
* @param {Object} options - Command options
|
|
128
|
+
*/
|
|
129
|
+
async function handleInitCommand(options = {}) {
|
|
130
|
+
try {
|
|
131
|
+
console.log(chalk.cyan('[INIT] Initializing Stigmergy project in current directory...\n'));
|
|
132
|
+
|
|
133
|
+
// Initialize or update skills/agents cache
|
|
134
|
+
await ensureSkillsCache({ verbose: true });
|
|
135
|
+
|
|
136
|
+
// Quick path detection for better tool availability
|
|
137
|
+
console.log(chalk.blue('[INIT] Detecting CLI tool paths...'));
|
|
138
|
+
const pathSetup = await setupCLIPaths();
|
|
139
|
+
|
|
140
|
+
console.log(`[INIT] CLI tool detection: ${pathSetup.report.summary.found}/${pathSetup.report.summary.total} tools found`);
|
|
141
|
+
|
|
142
|
+
// Quick setup for basic project structure
|
|
143
|
+
const projectDir = process.cwd();
|
|
144
|
+
const stigmergyDir = path.join(projectDir, '.stigmergy');
|
|
145
|
+
|
|
146
|
+
const fs = require('fs').promises;
|
|
147
|
+
|
|
148
|
+
// Create .stigmergy directory
|
|
149
|
+
await fs.mkdir(stigmergyDir, { recursive: true });
|
|
150
|
+
|
|
151
|
+
// Create basic config
|
|
152
|
+
const config = {
|
|
153
|
+
version: '1.3.0-beta.0',
|
|
154
|
+
created: new Date().toISOString(),
|
|
155
|
+
project: path.basename(projectDir)
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
await fs.writeFile(
|
|
159
|
+
path.join(stigmergyDir, 'config.json'),
|
|
160
|
+
JSON.stringify(config, null, 2)
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
console.log(chalk.green(`ā
Stigmergy project initialized in: ${projectDir}`));
|
|
164
|
+
console.log(chalk.blue(`š Configuration created: ${stigmergyDir}/config.json`));
|
|
165
|
+
console.log(chalk.gray('\nš” Next steps:'));
|
|
166
|
+
console.log(chalk.gray(' ⢠stigmergy install # Install CLI tools'));
|
|
167
|
+
console.log(chalk.gray(' ⢠stigmergy deploy # Deploy integration hooks'));
|
|
168
|
+
console.log(chalk.gray(' ⢠stigmergy status # Check tool status'));
|
|
169
|
+
|
|
170
|
+
if (pathSetup.report.summary.missing > 0) {
|
|
171
|
+
console.log(chalk.gray('\nš” For full CLI integration, run:'));
|
|
172
|
+
console.log(chalk.gray(' ⢠stigmergy setup # Complete setup with PATH configuration'));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { success: true, projectDir };
|
|
176
|
+
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error(chalk.red('[ERROR] Initialization failed:'), error.message);
|
|
179
|
+
return { success: false, error: error.message };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Handle setup command
|
|
185
|
+
* @param {Object} options - Command options
|
|
186
|
+
*/
|
|
187
|
+
async function handleSetupCommand(options = {}) {
|
|
188
|
+
try {
|
|
189
|
+
console.log(chalk.cyan('[SETUP] Starting complete Stigmergy setup...\n'));
|
|
190
|
+
|
|
191
|
+
// Initialize or update skills/agents cache (explicit call, will also be called in init)
|
|
192
|
+
await ensureSkillsCache({ verbose: true });
|
|
193
|
+
|
|
194
|
+
// Step 0: Setup CLI paths detection and configuration
|
|
195
|
+
console.log(chalk.blue('[STEP 0] Setting up CLI path detection...'));
|
|
196
|
+
const pathSetup = await setupCLIPaths();
|
|
197
|
+
|
|
198
|
+
console.log(`[PATH] Path detection complete:`);
|
|
199
|
+
console.log(` - Found: ${pathSetup.report.summary.found} CLI tools`);
|
|
200
|
+
console.log(` - Missing: ${pathSetup.report.summary.missing} CLI tools`);
|
|
201
|
+
|
|
202
|
+
if (pathSetup.pathStatus.updated) {
|
|
203
|
+
console.log(chalk.green('\n[PATH] ā All npm global directories are now available in PATH'));
|
|
204
|
+
console.log(chalk.gray('[PATH] CLI tools will be globally accessible after terminal restart'));
|
|
205
|
+
} else {
|
|
206
|
+
console.log(chalk.yellow('\n[PATH] ā ļø PATH update failed:'));
|
|
207
|
+
console.log(chalk.gray(` Error: ${pathSetup.pathStatus.message}`));
|
|
208
|
+
console.log(chalk.gray('\n[PATH] Manual update required:'));
|
|
209
|
+
console.log(chalk.gray(' Run the generated scripts to update PATH:'));
|
|
210
|
+
if (pathSetup.pathStatus.scriptPath) {
|
|
211
|
+
console.log(chalk.gray(` - Script directory: ${pathSetup.pathStatus.scriptPath}`));
|
|
212
|
+
}
|
|
213
|
+
console.log(chalk.gray(' - Windows: Run PowerShell as Administrator and execute the scripts'));
|
|
214
|
+
console.log(chalk.gray(' - Unix/Linux: Source the shell script (source update-path.sh)'));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Initialize project (will call ensureSkillsCache again, that's ok)
|
|
218
|
+
await handleInitCommand({ verbose: options.verbose });
|
|
219
|
+
|
|
220
|
+
// Install CLI tools
|
|
221
|
+
const installer = new StigmergyInstaller({ verbose: options.verbose });
|
|
222
|
+
const { available: setupAvailable, missing: setupMissing } = await installer.scanCLI();
|
|
223
|
+
|
|
224
|
+
if (Object.keys(setupMissing).length > 0) {
|
|
225
|
+
console.log(chalk.yellow('\n[STEP 1] Missing tools found:'));
|
|
226
|
+
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
227
|
+
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.log(chalk.blue('\n[INFO] To install missing tools, run:'));
|
|
231
|
+
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
232
|
+
console.log(` ${toolInfo.install}`);
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
console.log(chalk.green('\n[STEP 1] All required tools are already installed!'));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Deploy hooks to available CLI tools
|
|
239
|
+
if (Object.keys(setupAvailable).length > 0) {
|
|
240
|
+
console.log(chalk.blue('\n[STEP 2] Deploying hooks to available tools...'));
|
|
241
|
+
await installer.deployHooks(setupAvailable);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(chalk.yellow('\n[STEP 2] No tools available for hook deployment'));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Verify setup
|
|
247
|
+
console.log(chalk.blue('\n[STEP 3] Verifying installation...'));
|
|
248
|
+
await handleStatusCommand({ verbose: false });
|
|
249
|
+
|
|
250
|
+
console.log(chalk.green('\nš Setup completed successfully!'));
|
|
251
|
+
console.log(chalk.blue('\n[USAGE] Get started with these commands:'));
|
|
252
|
+
console.log(chalk.gray(' stigmergy d - System diagnostic (recommended first)'));
|
|
253
|
+
console.log(chalk.gray(' stigmergy inst - Install missing AI CLI tools'));
|
|
254
|
+
console.log(chalk.gray(' stigmergy deploy - Deploy hooks to installed tools'));
|
|
255
|
+
console.log(chalk.gray(' stigmergy call - Execute prompts with auto-routing'));
|
|
256
|
+
|
|
257
|
+
return { success: true };
|
|
258
|
+
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.error(chalk.red('[ERROR] Setup failed:'), error.message);
|
|
261
|
+
return { success: false, error: error.message };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Get working directory for a specific CLI tool
|
|
267
|
+
*/
|
|
268
|
+
function getWorkingDirectoryForTool(toolName) {
|
|
269
|
+
const toolConfig = CLI_TOOLS[toolName];
|
|
270
|
+
if (toolConfig && toolConfig.workingDirectory) {
|
|
271
|
+
return toolConfig.workingDirectory;
|
|
272
|
+
}
|
|
273
|
+
return process.cwd();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Get environment for a specific CLI tool
|
|
278
|
+
*/
|
|
279
|
+
function getEnvironmentForTool(toolName) {
|
|
280
|
+
const env = { ...process.env };
|
|
281
|
+
|
|
282
|
+
// Tool-specific environment handling
|
|
283
|
+
if (toolName === 'qwen') {
|
|
284
|
+
// Qwen CLI requires NODE_PATH to be unset
|
|
285
|
+
delete env.NODE_PATH;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return env;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Add OAuth authentication arguments to command args
|
|
293
|
+
*/
|
|
294
|
+
function addOAuthAuthArgs(toolName, args = []) {
|
|
295
|
+
const toolConfig = CLI_TOOLS[toolName];
|
|
296
|
+
|
|
297
|
+
if (toolConfig && toolConfig.oauth) {
|
|
298
|
+
const oauth = toolConfig.oauth;
|
|
299
|
+
if (oauth.authRequired) {
|
|
300
|
+
// Qwen-specific OAuth handling
|
|
301
|
+
if (toolName === 'qwen' && process.env.QWEN_ACCESS_TOKEN) {
|
|
302
|
+
return [...args, '--access-token', process.env.QWEN_ACCESS_TOKEN];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return args;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Execute a smart routed command with full parameter handling and mode detection
|
|
312
|
+
* @param {Object} route - Route object with tool and prompt
|
|
313
|
+
* @param {Object} options - Execution options
|
|
314
|
+
*/
|
|
315
|
+
async function executeSmartRoutedCommand(route, options = {}) {
|
|
316
|
+
const { verbose = false, maxRetries = 3, interactive, print } = options;
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
// Detect execution mode
|
|
320
|
+
const mode = modeDetector.detect({
|
|
321
|
+
interactive,
|
|
322
|
+
print,
|
|
323
|
+
verbose
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
const modeDescription = modeDetector.getModeDescription(mode);
|
|
327
|
+
if (verbose) {
|
|
328
|
+
console.log(chalk.gray(`[MODE] ${modeDescription}`));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Get adapted arguments for the tool and mode
|
|
332
|
+
let toolArgs = cliAdapterManager.getArguments(route.tool, mode, route.prompt);
|
|
333
|
+
|
|
334
|
+
// Add OAuth authentication if needed
|
|
335
|
+
toolArgs = addOAuthAuthArgs(route.tool, toolArgs);
|
|
336
|
+
|
|
337
|
+
// Use enhanced parameter handling for one-time mode only
|
|
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
|
|
349
|
+
}
|
|
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
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
if (verbose) {
|
|
362
|
+
console.log(chalk.gray(`[DEBUG] Adapted args: ${toolArgs.join(' ')}`));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Get tool path
|
|
367
|
+
const toolPath = await getCLIPath(route.tool);
|
|
368
|
+
if (!toolPath) {
|
|
369
|
+
throw new Error(`Tool ${route.tool} not found`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Prepare execution environment
|
|
373
|
+
const cwd = getWorkingDirectoryForTool(route.tool);
|
|
374
|
+
const env = getEnvironmentForTool(route.tool);
|
|
375
|
+
|
|
376
|
+
if (verbose) {
|
|
377
|
+
console.log(chalk.gray(`[DEBUG] Executing: ${toolPath} ${toolArgs.join(' ')}`));
|
|
378
|
+
console.log(chalk.gray(`[DEBUG] Working directory: ${cwd}`));
|
|
379
|
+
console.log(chalk.gray(`[DEBUG] Mode: ${mode}`));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Execute the command
|
|
383
|
+
// For interactive mode, we need stdio: 'inherit' to allow user interaction
|
|
384
|
+
const result = await executeCommand(toolPath, toolArgs, {
|
|
385
|
+
stdio: mode === 'interactive' ? 'inherit' : 'pipe',
|
|
386
|
+
shell: true,
|
|
387
|
+
cwd,
|
|
388
|
+
env,
|
|
389
|
+
timeout: 300000 // 5 minutes
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
return { success: true, tool: route.tool, result, mode };
|
|
393
|
+
|
|
394
|
+
} catch (error) {
|
|
395
|
+
if (verbose) {
|
|
396
|
+
console.error(chalk.red('[ERROR] Execution failed:'), error.message);
|
|
397
|
+
}
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Handle call command - Smart tool routing
|
|
404
|
+
* @param {string} prompt - Prompt to process
|
|
405
|
+
* @param {Object} options - Command options
|
|
406
|
+
*/
|
|
407
|
+
async function handleCallCommand(prompt, options = {}) {
|
|
408
|
+
try {
|
|
409
|
+
if (!prompt) {
|
|
410
|
+
console.log(chalk.red('[ERROR] Usage: stigmergy call "<prompt>"'));
|
|
411
|
+
console.log(chalk.blue('\nš” Examples:'));
|
|
412
|
+
console.log(chalk.gray(' ⢠stigmergy call "Write a Python function to sort a list"'));
|
|
413
|
+
console.log(chalk.gray(' ⢠stigmergy call "Create a React component with TypeScript"'));
|
|
414
|
+
console.log(chalk.gray(' ⢠stigmergy call "Help me debug this JavaScript code"'));
|
|
415
|
+
console.log(chalk.gray('\n ⢠stigmergy call -i "Start interactive session"'));
|
|
416
|
+
console.log(chalk.gray(' ⢠stigmergy call --print "Quick answer"'));
|
|
417
|
+
return { success: false, error: 'Prompt required' };
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Use smart router to determine which tool to use
|
|
421
|
+
const router = new SmartRouter();
|
|
422
|
+
await router.initialize();
|
|
423
|
+
const route = await router.smartRoute(prompt);
|
|
424
|
+
|
|
425
|
+
console.log(chalk.blue(`[CALL] Routing to ${route.tool}: ${route.prompt}`));
|
|
426
|
+
|
|
427
|
+
// Use enhanced execution with parameter handling and mode detection
|
|
428
|
+
await executeSmartRoutedCommand(route, {
|
|
429
|
+
verbose: options.verbose || process.env.DEBUG === 'true',
|
|
430
|
+
maxRetries: options.maxRetries || 3,
|
|
431
|
+
interactive: options.interactive,
|
|
432
|
+
print: options.print
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
return { success: true, tool: route.tool };
|
|
436
|
+
|
|
437
|
+
} catch (error) {
|
|
438
|
+
console.error(chalk.red('[ERROR] Call command failed:'), error.message);
|
|
439
|
+
return { success: false, error: error.message };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
module.exports = {
|
|
444
|
+
handleUpgradeCommand,
|
|
445
|
+
handleDeployCommand,
|
|
446
|
+
handleInitCommand,
|
|
447
|
+
handleSetupCommand,
|
|
448
|
+
handleCallCommand
|
|
449
|
+
};
|