stigmergy 1.2.12 → 1.3.2-beta.0
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 +14 -5
- package/scripts/analyze-router.js +168 -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 +185 -422
- 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 +701 -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 +220 -30
- package/src/core/enhanced_cli_parameter_handler.js +395 -0
- package/src/core/execution_mode_detector.js +222 -0
- package/src/core/installer.js +51 -70
- 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 -1737
package/src/cli/router.js
DELETED
|
@@ -1,1737 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System
|
|
5
|
-
* Unified Entry Point
|
|
6
|
-
* International Version - Pure English & ANSI Only
|
|
7
|
-
* Version: 1.0.94
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// Import all components
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const os = require('os');
|
|
13
|
-
const { Command } = require('commander');
|
|
14
|
-
const inquirer = require('inquirer');
|
|
15
|
-
const chalk = require('chalk');
|
|
16
|
-
const yaml = require('js-yaml');
|
|
17
|
-
const fs = require('fs/promises');
|
|
18
|
-
const fsSync = require('fs');
|
|
19
|
-
const { spawnSync } = require('child_process');
|
|
20
|
-
|
|
21
|
-
// Import permission management components
|
|
22
|
-
const DirectoryPermissionManager = require('../core/directory_permission_manager');
|
|
23
|
-
const { setupCLIPaths, getCLIPath } = require('../core/cli_tools');
|
|
24
|
-
|
|
25
|
-
// Import our custom modules
|
|
26
|
-
const SmartRouter = require('../core/smart_router');
|
|
27
|
-
const CLIHelpAnalyzer = require('../core/cli_help_analyzer');
|
|
28
|
-
const { CLI_TOOLS } = require('../core/cli_tools');
|
|
29
|
-
const { errorHandler } = require('../core/error_handler');
|
|
30
|
-
const { executeCommand, executeJSFile } = require('../utils');
|
|
31
|
-
const MemoryManager = require('../core/memory_manager');
|
|
32
|
-
const StigmergyInstaller = require('../core/installer');
|
|
33
|
-
const UpgradeManager = require('../core/upgrade_manager');
|
|
34
|
-
const { maxOfTwo, isAuthenticated } = require('../utils/helpers');
|
|
35
|
-
|
|
36
|
-
// Set up global error handlers using our error handler module
|
|
37
|
-
const { setupGlobalErrorHandlers } = require('../core/error_handler');
|
|
38
|
-
setupGlobalErrorHandlers();
|
|
39
|
-
|
|
40
|
-
// Helper function to format bytes
|
|
41
|
-
function formatBytes(bytes) {
|
|
42
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
43
|
-
if (bytes === 0) return '0 Bytes';
|
|
44
|
-
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
45
|
-
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Helper function to get appropriate working directory for CLI tools
|
|
49
|
-
function getWorkingDirectoryForTool(toolName) {
|
|
50
|
-
switch (toolName) {
|
|
51
|
-
case 'qwen':
|
|
52
|
-
// For Qwen CLI, use user home directory to avoid module resolution issues
|
|
53
|
-
return os.homedir();
|
|
54
|
-
case 'claude':
|
|
55
|
-
// For Claude CLI, use user home directory
|
|
56
|
-
return os.homedir();
|
|
57
|
-
case 'gemini':
|
|
58
|
-
// For Gemini CLI, use user home directory
|
|
59
|
-
return os.homedir();
|
|
60
|
-
case 'iflow':
|
|
61
|
-
// For iFlow CLI, use user home directory
|
|
62
|
-
return os.homedir();
|
|
63
|
-
case 'qodercli':
|
|
64
|
-
// For Qoder CLI, use user home directory
|
|
65
|
-
return os.homedir();
|
|
66
|
-
default:
|
|
67
|
-
// For other tools, use current directory
|
|
68
|
-
return process.cwd();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function main() {
|
|
73
|
-
const args = process.argv.slice(2);
|
|
74
|
-
|
|
75
|
-
// Debug mode
|
|
76
|
-
if (process.env.DEBUG === 'true') {
|
|
77
|
-
console.log('[DEBUG] Main function called with args:', process.argv);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Create instances
|
|
81
|
-
const memory = new MemoryManager();
|
|
82
|
-
const installer = new StigmergyInstaller();
|
|
83
|
-
const router = new SmartRouter();
|
|
84
|
-
|
|
85
|
-
// Handle help command early
|
|
86
|
-
if (
|
|
87
|
-
args.length === 0 ||
|
|
88
|
-
args.includes('-h') ||
|
|
89
|
-
args.includes('--help') ||
|
|
90
|
-
args.includes('help')
|
|
91
|
-
) {
|
|
92
|
-
console.log('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System');
|
|
93
|
-
console.log('=====================================================================');
|
|
94
|
-
console.log('');
|
|
95
|
-
console.log('Usage: stigmergy <command> [options]');
|
|
96
|
-
console.log('');
|
|
97
|
-
console.log('Commands:');
|
|
98
|
-
console.log(' help, --help Show this help message');
|
|
99
|
-
console.log(' version, --version Show version information');
|
|
100
|
-
console.log(' status Check CLI tools status');
|
|
101
|
-
console.log(' scan Scan for available AI CLI tools');
|
|
102
|
-
console.log(' install Auto-install missing CLI tools (with permission fix)');
|
|
103
|
-
console.log(' upgrade Upgrade all CLI tools to latest versions');
|
|
104
|
-
console.log(
|
|
105
|
-
' deploy Deploy hooks and integration to installed tools',
|
|
106
|
-
);
|
|
107
|
-
console.log(' setup Complete setup and configuration');
|
|
108
|
-
console.log(
|
|
109
|
-
' init Initialize Stigmergy project in current directory',
|
|
110
|
-
);
|
|
111
|
-
console.log(' clean (c) Clean temporary files and caches');
|
|
112
|
-
console.log(' diagnostic (d) Show system diagnostic information');
|
|
113
|
-
console.log(' fix-perms Fix directory permissions for installation');
|
|
114
|
-
console.log(' perm-check Check current directory permissions');
|
|
115
|
-
console.log(' skill <action> Manage skills across CLIs (install/read/list/sync/remove)');
|
|
116
|
-
console.log(' skill-i <src> Install skills (shortcut for: skill install)');
|
|
117
|
-
console.log(' skill-l List skills (shortcut for: skill list)');
|
|
118
|
-
console.log(' skill-r <name> Read skill (shortcut for: skill read)');
|
|
119
|
-
console.log(' skill-v <name> View/validate skill (auto-detect read or validate)');
|
|
120
|
-
console.log(' skill-d <name> Delete/remove skill (shortcut for: skill remove)');
|
|
121
|
-
console.log(' skill Sync skills to all CLI configs (shortcut for: skill sync)');
|
|
122
|
-
console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
|
|
123
|
-
console.log(' <tool> "<prompt>" Directly route to specific AI CLI tool');
|
|
124
|
-
console.log(' Supported tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex');
|
|
125
|
-
console.log('');
|
|
126
|
-
|
|
127
|
-
console.log('[QUICK START] Getting Started:');
|
|
128
|
-
console.log(' 1. npm install -g stigmergy # Install Stigmergy (auto-cleans cache)');
|
|
129
|
-
console.log(' 2. stigmergy d # System diagnostic');
|
|
130
|
-
console.log(' 3. stigmergy inst # Install missing AI CLI tools');
|
|
131
|
-
console.log(' 4. stigmergy deploy # Deploy hooks for CLI integration');
|
|
132
|
-
|
|
133
|
-
console.log('');
|
|
134
|
-
console.log(
|
|
135
|
-
'For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents',
|
|
136
|
-
);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const command = args[0];
|
|
141
|
-
|
|
142
|
-
switch (command) {
|
|
143
|
-
case 'version':
|
|
144
|
-
case '--version': {
|
|
145
|
-
// Use the version from package.json instead of hardcoding
|
|
146
|
-
const packageJson = require('../../package.json');
|
|
147
|
-
console.log(`Stigmergy CLI v${packageJson.version}`);
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
case 'errors':
|
|
152
|
-
try {
|
|
153
|
-
console.log('[ERRORS] Generating Stigmergy CLI error report...\n');
|
|
154
|
-
await errorHandler.printErrorReport();
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error(
|
|
157
|
-
'[ERROR] Failed to generate error report:',
|
|
158
|
-
error.message,
|
|
159
|
-
);
|
|
160
|
-
process.exit(1);
|
|
161
|
-
}
|
|
162
|
-
break;
|
|
163
|
-
|
|
164
|
-
case 'init':
|
|
165
|
-
try {
|
|
166
|
-
console.log('[INIT] Initializing Stigmergy project in current directory...\n');
|
|
167
|
-
|
|
168
|
-
// Quick path detection for better tool availability
|
|
169
|
-
console.log('[INIT] Detecting CLI tool paths...');
|
|
170
|
-
const pathSetup = await setupCLIPaths();
|
|
171
|
-
|
|
172
|
-
console.log(`[INIT] CLI tool detection: ${pathSetup.report.summary.found}/${pathSetup.report.summary.total} tools found`);
|
|
173
|
-
|
|
174
|
-
// Initialize project files in current directory
|
|
175
|
-
await installer.createProjectFiles();
|
|
176
|
-
|
|
177
|
-
console.log('[INIT] Project initialization completed successfully!');
|
|
178
|
-
console.log('\n[INFO] Created:');
|
|
179
|
-
console.log(' - PROJECT_SPEC.json (project specification)');
|
|
180
|
-
console.log(' - PROJECT_CONSTITUTION.md (collaboration guidelines)');
|
|
181
|
-
console.log(' - CLI path detection cache in ~/.stigmergy/cli-paths/');
|
|
182
|
-
|
|
183
|
-
if (pathSetup.report.summary.missing > 0) {
|
|
184
|
-
console.log('\n[INFO] For full CLI integration, run:');
|
|
185
|
-
console.log(' stigmergy setup # Complete setup with PATH configuration');
|
|
186
|
-
}
|
|
187
|
-
} catch (error) {
|
|
188
|
-
await errorHandler.logError(error, 'ERROR', 'main.init');
|
|
189
|
-
console.log(`[ERROR] Project initialization failed: ${error.message}`);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
break;
|
|
193
|
-
|
|
194
|
-
case 'setup':
|
|
195
|
-
try {
|
|
196
|
-
console.log('[SETUP] Starting complete Stigmergy setup...\n');
|
|
197
|
-
|
|
198
|
-
// Step 0: Setup CLI paths detection and configuration
|
|
199
|
-
console.log('[STEP 0] Setting up CLI path detection...');
|
|
200
|
-
const pathSetup = await setupCLIPaths();
|
|
201
|
-
|
|
202
|
-
console.log(`[PATH] Path detection complete:`);
|
|
203
|
-
console.log(` - Found: ${pathSetup.report.summary.found} CLI tools`);
|
|
204
|
-
console.log(` - Missing: ${pathSetup.report.summary.missing} CLI tools`);
|
|
205
|
-
|
|
206
|
-
if (pathSetup.pathStatus.updated) {
|
|
207
|
-
console.log('\n[PATH] ✓ All npm global directories are now available in PATH');
|
|
208
|
-
console.log('[PATH] CLI tools will be globally accessible after terminal restart');
|
|
209
|
-
} else {
|
|
210
|
-
console.log('\n[PATH] ⚠️ PATH update failed:');
|
|
211
|
-
console.log(` Error: ${pathSetup.pathStatus.message}`);
|
|
212
|
-
console.log('\n[PATH] Manual update required:');
|
|
213
|
-
console.log(' Run the generated scripts to update PATH:');
|
|
214
|
-
if (pathSetup.pathStatus.scriptPath) {
|
|
215
|
-
console.log(` - Script directory: ${pathSetup.pathStatus.scriptPath}`);
|
|
216
|
-
}
|
|
217
|
-
console.log(' - Windows: Run PowerShell as Administrator and execute the scripts');
|
|
218
|
-
console.log(' - Unix/Linux: Source the shell script (source update-path.sh)');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Step 1: Scan for CLI tools
|
|
222
|
-
console.log('\n[STEP 1] Scanning for AI CLI tools...');
|
|
223
|
-
const { available: setupAvailable, missing: setupMissing } =
|
|
224
|
-
await installer.scanCLI();
|
|
225
|
-
|
|
226
|
-
// Step 2: Install missing CLI tools
|
|
227
|
-
if (Object.keys(setupMissing).length > 0) {
|
|
228
|
-
console.log('\n[STEP 2] Installing missing tools...');
|
|
229
|
-
console.log('[INFO] Missing tools found:');
|
|
230
|
-
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
231
|
-
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
console.log('\n[INFO] To install missing tools, run:');
|
|
235
|
-
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
236
|
-
console.log(` ${toolInfo.install}`);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
console.log('\n[INFO] Or use the enhanced installer:');
|
|
240
|
-
console.log(' node src/core/enhanced_installer.js');
|
|
241
|
-
} else {
|
|
242
|
-
console.log('\n[STEP 2] All required tools are already installed!');
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Step 3: Deploy hooks to available CLI tools
|
|
246
|
-
if (Object.keys(setupAvailable).length > 0) {
|
|
247
|
-
console.log('\n[STEP 3] Deploying hooks to available tools...');
|
|
248
|
-
await installer.deployHooks(setupAvailable);
|
|
249
|
-
} else {
|
|
250
|
-
console.log('\n[STEP 3] No tools available for hook deployment');
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
console.log('\n🎉 Setup completed successfully!');
|
|
254
|
-
console.log('\n[USAGE] Get started with these commands:');
|
|
255
|
-
console.log(' stigmergy d - System diagnostic (recommended first)');
|
|
256
|
-
console.log(' stigmergy inst - Install missing AI CLI tools');
|
|
257
|
-
console.log(' stigmergy deploy - Deploy hooks to installed tools');
|
|
258
|
-
console.log(' stigmergy call - Execute prompts with auto-routing');
|
|
259
|
-
|
|
260
|
-
} catch (error) {
|
|
261
|
-
console.error('[ERROR] Setup failed:', error.message);
|
|
262
|
-
if (process.env.DEBUG === 'true') {
|
|
263
|
-
console.error(error.stack);
|
|
264
|
-
}
|
|
265
|
-
console.log('\n[TROUBLESHOOTING] To manually complete setup:');
|
|
266
|
-
console.log('1. Run: stigmergy deploy # Deploy hooks manually');
|
|
267
|
-
console.log('2. Run: stigmergy setup # Try setup again');
|
|
268
|
-
process.exit(1);
|
|
269
|
-
}
|
|
270
|
-
break;
|
|
271
|
-
|
|
272
|
-
case 'status':
|
|
273
|
-
try {
|
|
274
|
-
const { available, missing } = await installer.scanCLI();
|
|
275
|
-
console.log('\n[STATUS] AI CLI Tools Status Report');
|
|
276
|
-
console.log('=====================================');
|
|
277
|
-
|
|
278
|
-
if (Object.keys(available).length > 0) {
|
|
279
|
-
console.log('\n✅ Available Tools:');
|
|
280
|
-
for (const [toolName, toolInfo] of Object.entries(available)) {
|
|
281
|
-
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (Object.keys(missing).length > 0) {
|
|
286
|
-
console.log('\n❌ Missing Tools:');
|
|
287
|
-
for (const [toolName, toolInfo] of Object.entries(missing)) {
|
|
288
|
-
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
289
|
-
console.log(` Install command: ${toolInfo.install}`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
console.log(
|
|
294
|
-
`\n[SUMMARY] ${Object.keys(available).length} available, ${Object.keys(missing).length} missing`,
|
|
295
|
-
);
|
|
296
|
-
} catch (error) {
|
|
297
|
-
await errorHandler.logError(error, 'ERROR', 'main.status');
|
|
298
|
-
console.log(`[ERROR] Failed to get status: ${error.message}`);
|
|
299
|
-
process.exit(1);
|
|
300
|
-
}
|
|
301
|
-
break;
|
|
302
|
-
|
|
303
|
-
case 'scan':
|
|
304
|
-
try {
|
|
305
|
-
await installer.scanCLI();
|
|
306
|
-
} catch (error) {
|
|
307
|
-
await errorHandler.logError(error, 'ERROR', 'main.scan');
|
|
308
|
-
console.log(`[ERROR] Failed to scan CLI tools: ${error.message}`);
|
|
309
|
-
process.exit(1);
|
|
310
|
-
}
|
|
311
|
-
break;
|
|
312
|
-
|
|
313
|
-
case 'upgrade': {
|
|
314
|
-
try {
|
|
315
|
-
console.log('[UPGRADE] Starting AI CLI tools upgrade process...\n');
|
|
316
|
-
|
|
317
|
-
// 解析命令行选项
|
|
318
|
-
const upgradeArgs = args.slice(1);
|
|
319
|
-
const options = {
|
|
320
|
-
dryRun: upgradeArgs.includes('--dry-run'),
|
|
321
|
-
force: upgradeArgs.includes('--force'),
|
|
322
|
-
verbose: upgradeArgs.includes('--verbose')
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// 使用EnhancedCLIInstaller进行升级
|
|
326
|
-
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
327
|
-
const enhancedInstaller = new EnhancedCLIInstaller({
|
|
328
|
-
verbose: process.env.DEBUG === 'true' || options.verbose,
|
|
329
|
-
autoRetry: true,
|
|
330
|
-
maxRetries: 2
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
// 获取已安装的工具列表 - 使用全局installer扫描
|
|
334
|
-
const { available: installedTools } = await installer.scanCLI();
|
|
335
|
-
|
|
336
|
-
if (Object.keys(installedTools).length === 0) {
|
|
337
|
-
console.log('[INFO] No AI CLI tools found. Please install tools first with: stigmergy install');
|
|
338
|
-
break;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
console.log(`[INFO] Found ${Object.keys(installedTools).length} installed AI CLI tools:`);
|
|
342
|
-
for (const [toolName, toolInfo] of Object.entries(installedTools)) {
|
|
343
|
-
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (options.dryRun) {
|
|
347
|
-
console.log('\n🔍 DRY RUN MODE - No changes will be made');
|
|
348
|
-
console.log(' Use --force to execute the upgrade');
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// 默认直接执行升级,无需用户确认
|
|
353
|
-
console.log(`\n[UPGRADE] Upgrading ${Object.keys(installedTools).length} AI CLI tools...`);
|
|
354
|
-
console.log('[INFO] Use --dry-run to preview upgrades without executing');
|
|
355
|
-
|
|
356
|
-
console.log('\n🚀 Upgrading AI CLI tools with automatic permission handling...\n');
|
|
357
|
-
|
|
358
|
-
// 批量升级所有工具,一次权限检测
|
|
359
|
-
console.log(`[INFO] Starting batch upgrade of ${Object.keys(installedTools).length} tools...`);
|
|
360
|
-
|
|
361
|
-
const upgradeToolInfos = {};
|
|
362
|
-
for (const [toolName, toolInfo] of Object.entries(installedTools)) {
|
|
363
|
-
upgradeToolInfos[toolName] = {
|
|
364
|
-
...toolInfo,
|
|
365
|
-
install: `npm upgrade -g ${toolName}`,
|
|
366
|
-
name: `${toolInfo.name} (Upgrade)`
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const upgradeResult = await enhancedInstaller.upgradeTools(
|
|
371
|
-
Object.keys(installedTools),
|
|
372
|
-
upgradeToolInfos
|
|
373
|
-
);
|
|
374
|
-
|
|
375
|
-
// 整理结果
|
|
376
|
-
const results = {
|
|
377
|
-
successful: [],
|
|
378
|
-
failed: [],
|
|
379
|
-
permissionHandled: []
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
for (const [toolName, installation] of Object.entries(upgradeResult.results.installations || {})) {
|
|
383
|
-
if (installation.success) {
|
|
384
|
-
results.successful.push(toolName);
|
|
385
|
-
if (installation.permissionHandled) {
|
|
386
|
-
results.permissionHandled.push(toolName);
|
|
387
|
-
}
|
|
388
|
-
} else {
|
|
389
|
-
results.failed.push({
|
|
390
|
-
tool: toolName,
|
|
391
|
-
error: installation.error || 'Installation failed'
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// 显示结果
|
|
397
|
-
console.log('\n📊 UPGRADE RESULTS');
|
|
398
|
-
console.log('='.repeat(50));
|
|
399
|
-
|
|
400
|
-
if (results.successful.length > 0) {
|
|
401
|
-
console.log(`\n✅ Successful (${results.successful.length}):`);
|
|
402
|
-
results.successful.forEach(tool => {
|
|
403
|
-
console.log(` • ${tool}`);
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (results.permissionHandled.length > 0) {
|
|
408
|
-
console.log(`\n🔧 Auto-handled permissions (${results.permissionHandled.length}):`);
|
|
409
|
-
results.permissionHandled.forEach(tool => {
|
|
410
|
-
console.log(` • ${tool}`);
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
if (results.failed.length > 0) {
|
|
415
|
-
console.log(`\n❌ Failed (${results.failed.length}):`);
|
|
416
|
-
results.failed.forEach(result => {
|
|
417
|
-
console.log(` • ${result.tool}: ${result.error}`);
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// Provide guidance for permission issues
|
|
421
|
-
if (results.failed.length > 0) {
|
|
422
|
-
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
423
|
-
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy upgrade');
|
|
424
|
-
console.log(' macOS/Linux: sudo stigmergy upgrade');
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (results.permissionHandled.length > 0) {
|
|
429
|
-
console.log('\n✅ 权限问题已自动处理');
|
|
430
|
-
console.log(`🔧 自动提升权限升级了 ${results.permissionHandled.length} 个工具`);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
console.log('\n🎉 Upgrade process completed!');
|
|
434
|
-
|
|
435
|
-
} catch (error) {
|
|
436
|
-
console.error('[ERROR] Upgrade failed:', error.message);
|
|
437
|
-
if (process.env.DEBUG === 'true') {
|
|
438
|
-
console.error(error.stack);
|
|
439
|
-
}
|
|
440
|
-
process.exit(1);
|
|
441
|
-
}
|
|
442
|
-
break;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
case 'install':
|
|
446
|
-
case 'inst':
|
|
447
|
-
try {
|
|
448
|
-
console.log('[INSTALL] Starting AI CLI tools installation...');
|
|
449
|
-
|
|
450
|
-
// Check directory permissions first
|
|
451
|
-
const permissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
452
|
-
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
453
|
-
|
|
454
|
-
if (!hasWritePermission) {
|
|
455
|
-
console.log('\n⚠️ Current directory lacks write permission');
|
|
456
|
-
console.log('🔧 Using permission-aware installation...');
|
|
457
|
-
|
|
458
|
-
// Use permission-aware installer
|
|
459
|
-
const permAwareInstaller = new PermissionAwareInstaller({
|
|
460
|
-
verbose: process.env.DEBUG === 'true',
|
|
461
|
-
skipPermissionCheck: false
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
const result = await permAwareInstaller.install();
|
|
465
|
-
if (result.success) {
|
|
466
|
-
console.log('\n✅ Permission-aware installation completed successfully!');
|
|
467
|
-
} else {
|
|
468
|
-
console.log('\n❌ Permission-aware installation failed');
|
|
469
|
-
process.exit(1);
|
|
470
|
-
}
|
|
471
|
-
break;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// Normal installation if directory has write permission
|
|
475
|
-
const { missing: missingTools, available: availableTools } = await installer.scanCLI();
|
|
476
|
-
|
|
477
|
-
if (Object.keys(missingTools).length === 0) {
|
|
478
|
-
console.log('[INFO] All AI CLI tools are already installed!');
|
|
479
|
-
console.log('\nAvailable tools:');
|
|
480
|
-
for (const [toolName, toolInfo] of Object.entries(availableTools)) {
|
|
481
|
-
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
482
|
-
}
|
|
483
|
-
} else {
|
|
484
|
-
console.log(`\n[INFO] Found ${Object.keys(missingTools).length} missing AI CLI tools:`);
|
|
485
|
-
for (const [toolName, toolInfo] of Object.entries(missingTools)) {
|
|
486
|
-
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// 默认自动安装所有缺失的工具
|
|
490
|
-
console.log(`\n[AUTO-INSTALL] Installing ${Object.keys(missingTools).length} missing AI CLI tools...`);
|
|
491
|
-
|
|
492
|
-
const selectedTools = Object.keys(missingTools);
|
|
493
|
-
|
|
494
|
-
// Use EnhancedCLIInstaller with batch permission handling
|
|
495
|
-
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
496
|
-
const installer = new EnhancedCLIInstaller({
|
|
497
|
-
verbose: process.env.DEBUG === 'true',
|
|
498
|
-
autoRetry: true,
|
|
499
|
-
maxRetries: 2
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
console.log(`[INFO] Installing ${selectedTools.length} CLI tools with optimized permission handling...`);
|
|
503
|
-
const installResult = await installer.installTools(selectedTools, missingTools);
|
|
504
|
-
|
|
505
|
-
if (installResult) {
|
|
506
|
-
console.log(`\n[SUCCESS] Installed ${selectedTools.length} AI CLI tools!`);
|
|
507
|
-
|
|
508
|
-
// Check if any permissions were handled automatically
|
|
509
|
-
const installations = installer.results.installations || {};
|
|
510
|
-
const permissionHandledTools = Object.entries(installations)
|
|
511
|
-
.filter(([name, result]) => result.success && result.permissionHandled)
|
|
512
|
-
.map(([name]) => name);
|
|
513
|
-
|
|
514
|
-
if (permissionHandledTools.length > 0) {
|
|
515
|
-
console.log('✅ 权限问题已自动处理');
|
|
516
|
-
console.log(`🔧 自动提升权限安装了 ${permissionHandledTools.length} 个工具: ${permissionHandledTools.join(', ')}`);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Show permission mode used
|
|
520
|
-
console.log(`🔧 权限模式: ${installResult.permissionMode}`);
|
|
521
|
-
} else {
|
|
522
|
-
console.log('\n[WARN] Some tools may not have installed successfully. Check the logs above for details.');
|
|
523
|
-
|
|
524
|
-
// Provide manual guidance for permission issues
|
|
525
|
-
const failedInstallations = installer.results.failedInstallations || [];
|
|
526
|
-
if (failedInstallations.length > 0) {
|
|
527
|
-
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
528
|
-
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
529
|
-
console.log(' macOS/Linux: sudo stigmergy install');
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
console.log('\n[INFO] Installation process completed.');
|
|
535
|
-
} catch (error) {
|
|
536
|
-
console.error('[ERROR] Installation failed:', error.message);
|
|
537
|
-
if (process.env.DEBUG === 'true') {
|
|
538
|
-
console.error(error.stack);
|
|
539
|
-
}
|
|
540
|
-
process.exit(1);
|
|
541
|
-
}
|
|
542
|
-
break;
|
|
543
|
-
|
|
544
|
-
case 'deploy':
|
|
545
|
-
try {
|
|
546
|
-
const { available: deployedTools } = await installer.scanCLI();
|
|
547
|
-
await installer.deployHooks(deployedTools);
|
|
548
|
-
} catch (error) {
|
|
549
|
-
await errorHandler.logError(error, 'ERROR', 'main.deploy');
|
|
550
|
-
console.log(`[ERROR] Deployment failed: ${error.message}`);
|
|
551
|
-
process.exit(1);
|
|
552
|
-
}
|
|
553
|
-
break;
|
|
554
|
-
|
|
555
|
-
case 'call': {
|
|
556
|
-
if (args.length < 2) {
|
|
557
|
-
console.log('[ERROR] Usage: stigmergy call "<prompt>"');
|
|
558
|
-
process.exit(1);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Get the prompt (everything after the command)
|
|
562
|
-
const prompt = args.slice(1).join(' ');
|
|
563
|
-
|
|
564
|
-
// Use smart router to determine which tool to use
|
|
565
|
-
const router = new SmartRouter();
|
|
566
|
-
await router.initialize(); // Initialize the router first
|
|
567
|
-
const route = await router.smartRoute(prompt);
|
|
568
|
-
|
|
569
|
-
console.log(`[CALL] Routing to ${route.tool}: ${route.prompt}`);
|
|
570
|
-
|
|
571
|
-
// Execute the routed command
|
|
572
|
-
try {
|
|
573
|
-
// Get the actual executable path for the tool using which/where command
|
|
574
|
-
let toolPath = route.tool;
|
|
575
|
-
try {
|
|
576
|
-
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
577
|
-
const whichResult = spawnSync(whichCmd, [route.tool], {
|
|
578
|
-
encoding: 'utf8',
|
|
579
|
-
timeout: 10000,
|
|
580
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
581
|
-
shell: true,
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
if (whichResult.status === 0 && whichResult.stdout.trim()) {
|
|
585
|
-
// Get the first match (most likely the one that would be executed)
|
|
586
|
-
toolPath = whichResult.stdout.trim().split('\n')[0].trim();
|
|
587
|
-
}
|
|
588
|
-
} catch (whichError) {
|
|
589
|
-
// If which/where fails, continue with the tool name
|
|
590
|
-
if (process.env.DEBUG === 'true') {
|
|
591
|
-
console.log(`[DEBUG] which/where command failed for ${route.tool}: ${whichError.message}`);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// SPECIAL TEST CASE: Simulate a non-existent tool for testing
|
|
596
|
-
// This is for demonstration purposes only
|
|
597
|
-
/*
|
|
598
|
-
if (route.tool === "nonexistenttool") {
|
|
599
|
-
toolPath = "this_tool_definitely_does_not_exist_12345";
|
|
600
|
-
}
|
|
601
|
-
*/
|
|
602
|
-
|
|
603
|
-
console.log(
|
|
604
|
-
`[DEBUG] Tool path: ${toolPath}, Prompt: ${route.prompt}`,
|
|
605
|
-
);
|
|
606
|
-
|
|
607
|
-
// For different tools, we need to pass the prompt differently
|
|
608
|
-
// Use unified parameter handler for better parameter handling
|
|
609
|
-
let toolArgs = [];
|
|
610
|
-
|
|
611
|
-
try {
|
|
612
|
-
// Get CLI pattern for this tool
|
|
613
|
-
const cliPattern = await router.analyzer.getCLIPattern(route.tool);
|
|
614
|
-
|
|
615
|
-
// Log the CLI pattern to debug command format issues
|
|
616
|
-
if (process.env.DEBUG === 'true' && cliPattern) {
|
|
617
|
-
console.log(`[DEBUG] CLI Pattern for ${route.tool}:`, JSON.stringify(cliPattern, null, 2));
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// Use the unified CLI parameter handler
|
|
621
|
-
const CLIParameterHandler = require('../core/cli_parameter_handler');
|
|
622
|
-
toolArgs = CLIParameterHandler.generateArguments(
|
|
623
|
-
route.tool,
|
|
624
|
-
route.prompt,
|
|
625
|
-
cliPattern,
|
|
626
|
-
);
|
|
627
|
-
} catch (patternError) {
|
|
628
|
-
// Fallback to original logic if pattern analysis fails
|
|
629
|
-
if (route.tool === 'claude') {
|
|
630
|
-
// Claude CLI expects the prompt with -p flag for non-interactive mode
|
|
631
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
632
|
-
} else if (route.tool === 'qodercli' || route.tool === 'iflow') {
|
|
633
|
-
// Qoder CLI and iFlow expect the prompt with -p flag
|
|
634
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
635
|
-
} else if (route.tool === 'codex') {
|
|
636
|
-
// Codex CLI needs 'exec' subcommand for non-interactive mode
|
|
637
|
-
toolArgs = ['exec', '-p', `"${route.prompt}"`];
|
|
638
|
-
} else {
|
|
639
|
-
// For other tools, pass the prompt with -p flag
|
|
640
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// Use the reliable cross-platform execution function
|
|
645
|
-
try {
|
|
646
|
-
// Validate that the tool exists before attempting to execute
|
|
647
|
-
if (!toolPath || typeof toolPath !== 'string') {
|
|
648
|
-
throw new Error(`Invalid tool path: ${toolPath}`);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Special handling for JS files to ensure proper execution
|
|
652
|
-
if (toolPath.endsWith('.js') || toolPath.endsWith('.cjs')) {
|
|
653
|
-
// Use safe JS file execution
|
|
654
|
-
if (process.env.DEBUG === 'true') {
|
|
655
|
-
console.log(
|
|
656
|
-
`[EXEC] Safely executing JS file: ${toolPath} ${toolArgs.join(' ')}`,
|
|
657
|
-
);
|
|
658
|
-
}
|
|
659
|
-
const result = await executeJSFile(toolPath, toolArgs, {
|
|
660
|
-
stdio: 'inherit',
|
|
661
|
-
shell: true,
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
if (!result.success) {
|
|
665
|
-
console.log(
|
|
666
|
-
`[WARN] ${route.tool} exited with code ${result.code}`,
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
process.exit(result.code || 0);
|
|
670
|
-
} else {
|
|
671
|
-
// Regular command execution
|
|
672
|
-
if (process.env.DEBUG === 'true') {
|
|
673
|
-
console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// Special handling for Windows to construct the command properly
|
|
677
|
-
let execCommand = toolPath;
|
|
678
|
-
let execArgs = toolArgs;
|
|
679
|
-
if (process.platform === 'win32') {
|
|
680
|
-
// On Windows, we construct the full command line and pass it as a single string
|
|
681
|
-
if (toolArgs.length > 0) {
|
|
682
|
-
// For Windows, we need to properly quote the entire command line
|
|
683
|
-
const argsString = toolArgs.map(arg => {
|
|
684
|
-
// If arg contains spaces and is not already quoted, quote it
|
|
685
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
686
|
-
return `"${arg}"`;
|
|
687
|
-
}
|
|
688
|
-
return arg;
|
|
689
|
-
}).join(' ');
|
|
690
|
-
execCommand = `${toolPath} ${argsString}`;
|
|
691
|
-
execArgs = [];
|
|
692
|
-
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
// Special handling for Claude on Windows to bypass the wrapper script
|
|
697
|
-
if (process.platform === 'win32' && route.tool === 'claude') {
|
|
698
|
-
// Use detected path to avoid the wrapper script that interferes with parameter passing
|
|
699
|
-
const detectedPath = await getCLIPath('claude');
|
|
700
|
-
if (detectedPath) {
|
|
701
|
-
execCommand = detectedPath;
|
|
702
|
-
console.log(`[DEBUG] Using detected Claude path: ${execCommand}`);
|
|
703
|
-
} else {
|
|
704
|
-
execCommand = 'C:\\npm_global\\claude';
|
|
705
|
-
console.log(`[DEBUG] Using default Claude path: ${execCommand}`);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
if (toolArgs.length > 0) {
|
|
709
|
-
const argsString = toolArgs.map(arg => {
|
|
710
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
711
|
-
return `"${arg}"`;
|
|
712
|
-
}
|
|
713
|
-
return arg;
|
|
714
|
-
}).join(' ');
|
|
715
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
716
|
-
execArgs = [];
|
|
717
|
-
console.log(`[DEBUG] Windows direct Claude command: ${execCommand}`);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
// Use detected paths for all CLI tools on all platforms
|
|
722
|
-
const supportedTools = ['claude', 'copilot', 'qodercli', 'gemini', 'qwen', 'iflow', 'codebuddy', 'codex'];
|
|
723
|
-
|
|
724
|
-
if (supportedTools.includes(route.tool)) {
|
|
725
|
-
// Use detected path for all CLI tools regardless of platform
|
|
726
|
-
const detectedPath = await getCLIPath(route.tool);
|
|
727
|
-
if (detectedPath) {
|
|
728
|
-
execCommand = detectedPath;
|
|
729
|
-
console.log(`[DEBUG] Using detected ${route.tool} path: ${execCommand}`);
|
|
730
|
-
} else {
|
|
731
|
-
// Fallback to system PATH for tools not detected
|
|
732
|
-
console.log(`[DEBUG] Using system PATH for ${route.tool}: ${route.tool}`);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
// Platform-specific command construction
|
|
737
|
-
if (process.platform === 'win32') {
|
|
738
|
-
// Special handling for Windows CLI tools
|
|
739
|
-
if (route.tool === 'claude' && toolArgs.length > 0) {
|
|
740
|
-
// Special parameter handling for Claude to avoid wrapper script issues
|
|
741
|
-
const argsString = toolArgs.map(arg => {
|
|
742
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
743
|
-
return `"${arg}"`;
|
|
744
|
-
}
|
|
745
|
-
return arg;
|
|
746
|
-
}).join(' ');
|
|
747
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
748
|
-
execArgs = [];
|
|
749
|
-
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
750
|
-
} else if (route.tool === 'copilot') {
|
|
751
|
-
// Copilot doesn't use -p parameter format
|
|
752
|
-
execArgs = [];
|
|
753
|
-
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
754
|
-
} else if (toolArgs.length > 0) {
|
|
755
|
-
// For other Windows tools, construct full command line
|
|
756
|
-
const argsString = toolArgs.map(arg => {
|
|
757
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
758
|
-
return `"${arg}"`;
|
|
759
|
-
}
|
|
760
|
-
return arg;
|
|
761
|
-
}).join(' ');
|
|
762
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
763
|
-
execArgs = [];
|
|
764
|
-
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
// Apply the same Windows handling logic to ensure consistency
|
|
769
|
-
// This ensures consistency between direct routing and call command routing
|
|
770
|
-
if (process.platform === 'win32' && execArgs.length > 0) {
|
|
771
|
-
// For Windows, we need to properly quote the entire command line
|
|
772
|
-
const argsString = execArgs.map(arg => {
|
|
773
|
-
// If arg contains spaces and is not already quoted, quote it
|
|
774
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
775
|
-
return `"${arg}"`;
|
|
776
|
-
}
|
|
777
|
-
return arg;
|
|
778
|
-
}).join(' ');
|
|
779
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
780
|
-
execArgs = [];
|
|
781
|
-
console.log(`[DEBUG] Windows unified command: ${execCommand}`);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// Set environment for tools that need specific working directories
|
|
785
|
-
const env = { ...process.env };
|
|
786
|
-
if (route.tool === 'qwen') {
|
|
787
|
-
// For Qwen CLI, clear NODE_PATH to avoid import conflicts
|
|
788
|
-
delete env.NODE_PATH;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
const result = await executeCommand(execCommand, execArgs, {
|
|
792
|
-
stdio: 'inherit',
|
|
793
|
-
shell: true,
|
|
794
|
-
cwd: getWorkingDirectoryForTool(route.tool),
|
|
795
|
-
env,
|
|
796
|
-
});
|
|
797
|
-
|
|
798
|
-
if (!result.success) {
|
|
799
|
-
console.log(
|
|
800
|
-
`[WARN] ${route.tool} exited with code ${result.code}`,
|
|
801
|
-
);
|
|
802
|
-
}
|
|
803
|
-
process.exit(result.code || 0);
|
|
804
|
-
}
|
|
805
|
-
} catch (executionError) {
|
|
806
|
-
// Check for specific errors that might not be actual failures
|
|
807
|
-
const errorMessage = executionError.error?.message || executionError.message || executionError;
|
|
808
|
-
|
|
809
|
-
// For some tools like Claude, they may output to stdout and return non-zero codes
|
|
810
|
-
// without actually failing - handle these cases more gracefully
|
|
811
|
-
if (errorMessage.includes('not recognized as an internal or external command') ||
|
|
812
|
-
errorMessage.includes('command not found') ||
|
|
813
|
-
errorMessage.includes('ENOENT')) {
|
|
814
|
-
// This is a genuine error - tool is not installed
|
|
815
|
-
const cliError = await errorHandler.handleCLIError(
|
|
816
|
-
route.tool,
|
|
817
|
-
executionError.error || executionError,
|
|
818
|
-
toolArgs.join(' '),
|
|
819
|
-
);
|
|
820
|
-
|
|
821
|
-
// Provide clear ANSI English error message
|
|
822
|
-
console.log('==================================================');
|
|
823
|
-
console.log('ERROR: Failed to execute AI CLI tool');
|
|
824
|
-
console.log('==================================================');
|
|
825
|
-
console.log(`Tool: ${route.tool}`);
|
|
826
|
-
console.log(`Error: ${cliError.message}`);
|
|
827
|
-
if (executionError.stderr) {
|
|
828
|
-
console.log(`Stderr: ${executionError.stderr}`);
|
|
829
|
-
}
|
|
830
|
-
console.log('');
|
|
831
|
-
console.log('Possible solutions:');
|
|
832
|
-
console.log('1. Check if the AI CLI tool is properly installed');
|
|
833
|
-
console.log('2. Verify the tool is in your system PATH');
|
|
834
|
-
console.log('3. Try reinstalling the tool with: stigmergy install');
|
|
835
|
-
console.log('4. Run stigmergy status to check tool availability');
|
|
836
|
-
console.log('');
|
|
837
|
-
console.log('For manual execution, you can run:');
|
|
838
|
-
console.log(`${toolPath} ${toolArgs.join(' ')}`);
|
|
839
|
-
console.log('==================================================');
|
|
840
|
-
process.exit(1);
|
|
841
|
-
} else {
|
|
842
|
-
// For other execution errors, try to execute the command directly
|
|
843
|
-
// which handles cases where the tool executed successfully but returned an error object
|
|
844
|
-
console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
|
|
845
|
-
// Set environment for tools that need specific working directories
|
|
846
|
-
const env = { ...process.env };
|
|
847
|
-
if (route.tool === 'qwen') {
|
|
848
|
-
delete env.NODE_PATH;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
const result = await executeCommand(toolPath, toolArgs, {
|
|
852
|
-
stdio: 'inherit',
|
|
853
|
-
shell: true,
|
|
854
|
-
cwd: getWorkingDirectoryForTool(route.tool),
|
|
855
|
-
env,
|
|
856
|
-
});
|
|
857
|
-
|
|
858
|
-
if (!result.success) {
|
|
859
|
-
console.log(`[WARN] ${route.tool} exited with code ${result.code}`);
|
|
860
|
-
}
|
|
861
|
-
process.exit(result.code || 0);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
} catch (error) {
|
|
865
|
-
const cliError = await errorHandler.handleCLIError(
|
|
866
|
-
route.tool,
|
|
867
|
-
error,
|
|
868
|
-
prompt,
|
|
869
|
-
);
|
|
870
|
-
console.log(
|
|
871
|
-
`[ERROR] Failed to execute ${route.tool}:`,
|
|
872
|
-
cliError.message,
|
|
873
|
-
);
|
|
874
|
-
process.exit(1);
|
|
875
|
-
}
|
|
876
|
-
break;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
case 'auto-install':
|
|
880
|
-
// Auto-install mode for npm postinstall - NON-INTERACTIVE with permission awareness
|
|
881
|
-
// Force immediate output visibility during npm install
|
|
882
|
-
|
|
883
|
-
// Detect npm environment for better output visibility
|
|
884
|
-
const isNpmPostinstall = process.env.npm_lifecycle_event === 'postinstall';
|
|
885
|
-
|
|
886
|
-
// Use stderr for critical messages in npm environment (more likely to be shown)
|
|
887
|
-
const criticalLog = isNpmPostinstall ? console.error : console.log;
|
|
888
|
-
|
|
889
|
-
criticalLog('🚀 STIGMERGY CLI AUTO-INSTALL STARTING');
|
|
890
|
-
criticalLog('='.repeat(60));
|
|
891
|
-
criticalLog('Installing cross-CLI integration and scanning for AI tools...');
|
|
892
|
-
criticalLog('='.repeat(60));
|
|
893
|
-
console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
|
|
894
|
-
console.log('='.repeat(60));
|
|
895
|
-
|
|
896
|
-
// Check directory permissions
|
|
897
|
-
const autoPermissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
898
|
-
const autoHasWritePermission = await autoPermissionManager.checkWritePermission();
|
|
899
|
-
|
|
900
|
-
if (!autoHasWritePermission && !process.env.STIGMERGY_SKIP_PERMISSION_CHECK) {
|
|
901
|
-
criticalLog('⚠️ Directory permission detected, setting up permission-aware installation...');
|
|
902
|
-
|
|
903
|
-
try {
|
|
904
|
-
const permResult = await autoPermissionManager.setupWorkingDirectory();
|
|
905
|
-
if (permResult.success) {
|
|
906
|
-
criticalLog('✅ Working directory configured with proper permissions');
|
|
907
|
-
} else {
|
|
908
|
-
criticalLog('⚠️ Could not configure working directory, continuing with limited functionality');
|
|
909
|
-
}
|
|
910
|
-
} catch (error) {
|
|
911
|
-
criticalLog(`⚠️ Permission setup failed: ${error.message}`);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
// Force stdout flush to ensure visibility during npm install
|
|
916
|
-
if (process.stdout && process.stdout.write) {
|
|
917
|
-
process.stdout.write('');
|
|
918
|
-
if (process.stdout.flush) {
|
|
919
|
-
process.stdout.flush();
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
// Add a small delay to ensure output is visible
|
|
924
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
925
|
-
|
|
926
|
-
try {
|
|
927
|
-
// Step 1: Download required assets
|
|
928
|
-
try {
|
|
929
|
-
console.log('[STEP] Downloading required assets...');
|
|
930
|
-
// Force flush to ensure visibility
|
|
931
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
932
|
-
|
|
933
|
-
await installer.downloadRequiredAssets();
|
|
934
|
-
console.log('[OK] Assets downloaded successfully');
|
|
935
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
936
|
-
} catch (error) {
|
|
937
|
-
console.log(`[WARN] Failed to download assets: ${error.message}`);
|
|
938
|
-
console.log('[INFO] Continuing with installation...');
|
|
939
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
// Step 2: Scan for CLI tools
|
|
943
|
-
let autoAvailable = {},
|
|
944
|
-
autoMissing = {};
|
|
945
|
-
try {
|
|
946
|
-
console.log('[STEP] Scanning for CLI tools...');
|
|
947
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
948
|
-
|
|
949
|
-
const scanResult = await installer.scanCLI();
|
|
950
|
-
autoAvailable = scanResult.available;
|
|
951
|
-
autoMissing = scanResult.missing;
|
|
952
|
-
console.log('[OK] CLI tools scanned successfully');
|
|
953
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
954
|
-
} catch (error) {
|
|
955
|
-
console.log(`[WARN] Failed to scan CLI tools: ${error.message}`);
|
|
956
|
-
console.log('[INFO] Continuing with installation...');
|
|
957
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
// Step 4: Show usage instructions using existing scan results
|
|
961
|
-
try {
|
|
962
|
-
console.log('\n' + '='.repeat(60));
|
|
963
|
-
console.log('[SUCCESS] Stigmergy CLI installation completed!');
|
|
964
|
-
console.log('='.repeat(60));
|
|
965
|
-
|
|
966
|
-
console.log(`\n[SCAN RESULT] Found ${Object.keys(autoAvailable).length} available AI CLI tools:`);
|
|
967
|
-
|
|
968
|
-
if (Object.keys(autoAvailable).length > 0) {
|
|
969
|
-
for (const [toolName, toolInfo] of Object.entries(autoAvailable)) {
|
|
970
|
-
const status = toolInfo.installed ? '✓ Installed' : '✗ Not Installed';
|
|
971
|
-
console.log(` ✓ ${toolInfo.name} (${toolName}) - ${status}`);
|
|
972
|
-
if (toolInfo.path) {
|
|
973
|
-
console.log(` Path: ${toolInfo.path}`);
|
|
974
|
-
}
|
|
975
|
-
if (toolInfo.version) {
|
|
976
|
-
console.log(` Version: ${toolInfo.version}`);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
} else {
|
|
980
|
-
console.log(' [INFO] No AI CLI tools found on your system');
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
if (Object.keys(autoMissing).length > 0) {
|
|
984
|
-
console.log(`\n[MISSING] ${Object.keys(autoMissing).length} tools not found:`);
|
|
985
|
-
for (const [toolName, toolInfo] of Object.entries(autoMissing)) {
|
|
986
|
-
console.log(` ✗ ${toolInfo.name} (${toolName})`);
|
|
987
|
-
console.log(` Install with: ${toolInfo.installCommand}`);
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
// Check if auto-install is enabled for npm postinstall
|
|
991
|
-
const autoInstallEnabled = process.env.STIGMERGY_AUTO_INSTALL !== 'false';
|
|
992
|
-
|
|
993
|
-
if (autoInstallEnabled && !process.env.CI) {
|
|
994
|
-
console.log('\n[AUTO-INSTALL] Installing missing CLI tools automatically...');
|
|
995
|
-
console.log('[INFO] Set STIGMERGY_AUTO_INSTALL=false to disable this behavior');
|
|
996
|
-
|
|
997
|
-
try {
|
|
998
|
-
const selectedTools = Object.keys(autoMissing);
|
|
999
|
-
|
|
1000
|
-
// Use EnhancedCLIInstaller with batch permission handling
|
|
1001
|
-
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
1002
|
-
const installer = new EnhancedCLIInstaller({
|
|
1003
|
-
verbose: process.env.DEBUG === 'true',
|
|
1004
|
-
autoRetry: true,
|
|
1005
|
-
maxRetries: 2
|
|
1006
|
-
});
|
|
1007
|
-
|
|
1008
|
-
console.log(`[INFO] Installing ${selectedTools.length} CLI tools with optimized permission handling...`);
|
|
1009
|
-
const installResult = await installer.installTools(selectedTools, autoMissing);
|
|
1010
|
-
|
|
1011
|
-
if (installResult) {
|
|
1012
|
-
console.log(`[SUCCESS] Auto-installed ${selectedTools.length} CLI tools!`);
|
|
1013
|
-
|
|
1014
|
-
// Check if permissions were handled automatically
|
|
1015
|
-
const installations = installer.results.installations || {};
|
|
1016
|
-
const permissionHandledTools = Object.entries(installations)
|
|
1017
|
-
.filter(([name, result]) => result.success && result.permissionHandled)
|
|
1018
|
-
.map(([name]) => name);
|
|
1019
|
-
|
|
1020
|
-
if (permissionHandledTools.length > 0) {
|
|
1021
|
-
console.log('✅ 权限问题已自动处理');
|
|
1022
|
-
console.log(`🔧 自动提升权限安装了 ${permissionHandledTools.length} 个工具: ${permissionHandledTools.join(', ')}`);
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
// Show permission mode used
|
|
1026
|
-
console.log(`🔧 权限模式: ${installResult.permissionMode}`);
|
|
1027
|
-
} else {
|
|
1028
|
-
console.log('[WARN] Some tools may not have installed successfully');
|
|
1029
|
-
|
|
1030
|
-
// Provide manual guidance for permission issues
|
|
1031
|
-
const failedInstallations = installer.results.failedInstallations || [];
|
|
1032
|
-
if (failedInstallations.length > 0) {
|
|
1033
|
-
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
1034
|
-
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
1035
|
-
console.log(' macOS/Linux: sudo stigmergy install');
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
} catch (installError) {
|
|
1039
|
-
console.log(`[ERROR] Auto-install failed: ${installError.message}`);
|
|
1040
|
-
console.log('[INFO] You can manually install tools with: stigmergy install --auto');
|
|
1041
|
-
|
|
1042
|
-
// Check if it's a permission error
|
|
1043
|
-
const permissionIndicators = ['EACCES', 'EPERM', 'permission denied', 'access denied'];
|
|
1044
|
-
const isPermissionError = permissionIndicators.some(indicator =>
|
|
1045
|
-
installError.message.toLowerCase().includes(indicator.toLowerCase())
|
|
1046
|
-
);
|
|
1047
|
-
|
|
1048
|
-
if (isPermissionError) {
|
|
1049
|
-
console.log('\n💡 这看起来像是权限问题,请尝试:');
|
|
1050
|
-
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
1051
|
-
console.log(' macOS/Linux: sudo stigmergy install');
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
} else {
|
|
1055
|
-
console.log('\n[INFO] You can install missing tools with: stigmergy install --auto');
|
|
1056
|
-
if (process.env.CI) {
|
|
1057
|
-
console.log('[CI] Auto-install disabled in CI environment');
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
console.log('\n[USAGE] Get started with these commands:');
|
|
1063
|
-
console.log(' stigmergy d - System diagnostic (recommended first)');
|
|
1064
|
-
console.log(' stigmergy inst - Install missing CLI tools');
|
|
1065
|
-
console.log(' stigmergy deploy - Deploy hooks for CLI integration');
|
|
1066
|
-
console.log(' stigmergy c - Clean caches if needed');
|
|
1067
|
-
console.log('\n[INFO] Stigmergy CLI enables collaboration between multiple AI CLI tools!');
|
|
1068
|
-
console.log('[INFO] Try "stigmergy" to see all available commands and abbreviations.');
|
|
1069
|
-
|
|
1070
|
-
} catch (error) {
|
|
1071
|
-
console.log(`[WARN] Failed to show usage instructions: ${error.message}`);
|
|
1072
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
// Step 4: Deploy hooks to available CLI tools (with Linux-specific error handling)
|
|
1076
|
-
try {
|
|
1077
|
-
console.log('[STEP] Deploying hooks to available CLI tools...');
|
|
1078
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1079
|
-
|
|
1080
|
-
await installer.deployHooks(autoAvailable);
|
|
1081
|
-
console.log('[OK] Hooks deployed successfully');
|
|
1082
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1083
|
-
} catch (error) {
|
|
1084
|
-
// Linux-specific error handling
|
|
1085
|
-
const errorMessage = error.message || error.toString();
|
|
1086
|
-
console.log(`[ERROR] Failed to deploy hooks: ${errorMessage}`);
|
|
1087
|
-
|
|
1088
|
-
if (process.platform === 'linux') {
|
|
1089
|
-
if (errorMessage.includes('EACCES') || errorMessage.includes('permission')) {
|
|
1090
|
-
console.log('[LINUX-INFO] Permission denied. This may be normal if hooks are being placed in system directories.');
|
|
1091
|
-
console.log('[LINUX-INFO] You can try running with sudo or check directory permissions.');
|
|
1092
|
-
} else if (errorMessage.includes('ENOENT') || errorMessage.includes('no such file')) {
|
|
1093
|
-
console.log('[LINUX-INFO] Some directories do not exist. This is normal for tools that are not installed.');
|
|
1094
|
-
} else if (errorMessage.includes('EPERM')) {
|
|
1095
|
-
console.log('[LINUX-INFO] Operation not permitted. This may be due to filesystem permissions.');
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
console.log('[INFO] You can manually deploy hooks later by running: stigmergy deploy');
|
|
1100
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
// Step 5: Deploy project documentation
|
|
1104
|
-
try {
|
|
1105
|
-
console.log('[STEP] Deploying project documentation...');
|
|
1106
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1107
|
-
|
|
1108
|
-
await installer.deployProjectDocumentation();
|
|
1109
|
-
console.log('[OK] Documentation deployed successfully');
|
|
1110
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1111
|
-
} catch (error) {
|
|
1112
|
-
console.log(
|
|
1113
|
-
`[WARN] Failed to deploy documentation: ${error.message}`,
|
|
1114
|
-
);
|
|
1115
|
-
console.log('[INFO] Continuing with installation...');
|
|
1116
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
// Step 6: Initialize configuration
|
|
1120
|
-
try {
|
|
1121
|
-
console.log('[STEP] Initializing configuration...');
|
|
1122
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1123
|
-
|
|
1124
|
-
await installer.initializeConfig();
|
|
1125
|
-
console.log('[OK] Configuration initialized successfully');
|
|
1126
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1127
|
-
} catch (error) {
|
|
1128
|
-
console.log(
|
|
1129
|
-
`[ERROR] Failed to initialize configuration: ${error.message}`,
|
|
1130
|
-
);
|
|
1131
|
-
console.log(
|
|
1132
|
-
'[INFO] You can manually initialize configuration later by running: stigmergy setup',
|
|
1133
|
-
);
|
|
1134
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
// Step 7: Show final message to guide users
|
|
1138
|
-
console.log('\n[SUCCESS] Stigmergy CLI installed successfully!');
|
|
1139
|
-
console.log(
|
|
1140
|
-
'[USAGE] Run "stigmergy setup" to complete full configuration and install missing AI CLI tools.',
|
|
1141
|
-
);
|
|
1142
|
-
console.log(
|
|
1143
|
-
'[USAGE] Run "stigmergy install" to install only missing AI CLI tools.',
|
|
1144
|
-
);
|
|
1145
|
-
console.log(
|
|
1146
|
-
'[USAGE] Run "stigmergy --help" to see all available commands.',
|
|
1147
|
-
);
|
|
1148
|
-
|
|
1149
|
-
// Force final flush to ensure all output is visible
|
|
1150
|
-
if (process.stdout.flush) process.stdout.flush();
|
|
1151
|
-
if (process.stderr.flush) process.stderr.flush();
|
|
1152
|
-
} catch (fatalError) {
|
|
1153
|
-
await errorHandler.logError(fatalError, 'ERROR', 'main.auto-install');
|
|
1154
|
-
console.error(
|
|
1155
|
-
'[FATAL] Auto-install process failed:',
|
|
1156
|
-
fatalError.message,
|
|
1157
|
-
);
|
|
1158
|
-
console.log('\n[TROUBLESHOOTING] To manually complete installation:');
|
|
1159
|
-
console.log('1. Run: stigmergy setup # Complete setup');
|
|
1160
|
-
console.log('2. Run: stigmergy install # Install missing tools');
|
|
1161
|
-
console.log('3. Run: stigmergy deploy # Deploy hooks manually');
|
|
1162
|
-
process.exit(1);
|
|
1163
|
-
}
|
|
1164
|
-
break;
|
|
1165
|
-
|
|
1166
|
-
// Skill命令简化别名
|
|
1167
|
-
case 'skill-i': // install
|
|
1168
|
-
case 'skill-l': // list
|
|
1169
|
-
case 'skill-v': // validate/read
|
|
1170
|
-
case 'skill-r': // read
|
|
1171
|
-
case 'skill-d': // remove/delete
|
|
1172
|
-
case 'skill-m': // remove (移除)
|
|
1173
|
-
case 'skill': {
|
|
1174
|
-
try {
|
|
1175
|
-
// Skill命令通过桥接器调用ES模块
|
|
1176
|
-
const { handleSkillCommand } = require('../commands/skill-handler');
|
|
1177
|
-
|
|
1178
|
-
// 处理简化命令
|
|
1179
|
-
let skillAction;
|
|
1180
|
-
let skillArgs;
|
|
1181
|
-
|
|
1182
|
-
switch (command) {
|
|
1183
|
-
case 'skill-i':
|
|
1184
|
-
skillAction = 'install';
|
|
1185
|
-
skillArgs = args.slice(1);
|
|
1186
|
-
break;
|
|
1187
|
-
case 'skill-l':
|
|
1188
|
-
skillAction = 'list';
|
|
1189
|
-
skillArgs = args.slice(1);
|
|
1190
|
-
break;
|
|
1191
|
-
case 'skill-v':
|
|
1192
|
-
// skill-v可以是validate或read,根据参数判断
|
|
1193
|
-
skillAction = args[1] && (args[1].endsWith('.md') || args[1].includes('/') || args[1].includes('\\'))
|
|
1194
|
-
? 'validate'
|
|
1195
|
-
: 'read';
|
|
1196
|
-
skillArgs = args.slice(1);
|
|
1197
|
-
break;
|
|
1198
|
-
case 'skill-r':
|
|
1199
|
-
skillAction = 'read';
|
|
1200
|
-
skillArgs = args.slice(1);
|
|
1201
|
-
break;
|
|
1202
|
-
case 'skill-d':
|
|
1203
|
-
case 'skill-m':
|
|
1204
|
-
skillAction = 'remove';
|
|
1205
|
-
skillArgs = args.slice(1);
|
|
1206
|
-
break;
|
|
1207
|
-
default:
|
|
1208
|
-
// 标准skill命令
|
|
1209
|
-
skillAction = args[1];
|
|
1210
|
-
skillArgs = args.slice(2);
|
|
1211
|
-
|
|
1212
|
-
// 如果没有子命令,默认执行sync
|
|
1213
|
-
if (!skillAction) {
|
|
1214
|
-
skillAction = 'sync';
|
|
1215
|
-
skillArgs = [];
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
const skillOptions = {
|
|
1220
|
-
force: args.includes('--force'),
|
|
1221
|
-
verbose: args.includes('--verbose'),
|
|
1222
|
-
autoSync: !args.includes('--no-auto-sync')
|
|
1223
|
-
};
|
|
1224
|
-
|
|
1225
|
-
const exitCode = await handleSkillCommand(skillAction, skillArgs, skillOptions);
|
|
1226
|
-
process.exit(exitCode || 0);
|
|
1227
|
-
} catch (error) {
|
|
1228
|
-
await errorHandler.logError(error, 'ERROR', 'main.skill');
|
|
1229
|
-
console.error(`[ERROR] Skill command failed: ${error.message}`);
|
|
1230
|
-
process.exit(1);
|
|
1231
|
-
}
|
|
1232
|
-
break;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
case 'clean':
|
|
1236
|
-
case 'c': {
|
|
1237
|
-
try {
|
|
1238
|
-
console.log('[CLEAN] Starting intelligent cache cleaning...\n');
|
|
1239
|
-
|
|
1240
|
-
// Import our enhanced cache cleaner
|
|
1241
|
-
const CacheCleaner = require('../core/cache_cleaner');
|
|
1242
|
-
const cleaner = new CacheCleaner({
|
|
1243
|
-
dryRun: false,
|
|
1244
|
-
force: true,
|
|
1245
|
-
verbose: true,
|
|
1246
|
-
preserveRecent: 60 * 60 * 1000 // Preserve files from last hour
|
|
1247
|
-
});
|
|
1248
|
-
|
|
1249
|
-
// Show options if arguments provided
|
|
1250
|
-
if (args.includes('--dry-run')) {
|
|
1251
|
-
console.log('[DRY RUN] Preview mode - no files will be deleted\n');
|
|
1252
|
-
await cleaner.cleanAllCaches({
|
|
1253
|
-
cleanStigmergy: args.includes('--stigmergy') || args.includes('--all'),
|
|
1254
|
-
cleanNPX: args.includes('--npx') || args.includes('--all'),
|
|
1255
|
-
cleanNPM: args.includes('--npm') || args.includes('--all'),
|
|
1256
|
-
cleanCLI: args.includes('--cli') || args.includes('--all'),
|
|
1257
|
-
cleanTemp: true // Always clean temp files
|
|
1258
|
-
});
|
|
1259
|
-
break;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
// Default clean: safe options
|
|
1263
|
-
console.log('[OPTIONS] Running safe cache cleaning...');
|
|
1264
|
-
console.log('[INFO] This will remove temporary files and NPX cache only\n');
|
|
1265
|
-
|
|
1266
|
-
const results = await cleaner.cleanAllCaches({
|
|
1267
|
-
cleanStigmergy: false, // Don't clean main config
|
|
1268
|
-
cleanNPX: true, // Clean NPX cache (safe)
|
|
1269
|
-
cleanNPM: false, // Don't clean NPM cache during normal run
|
|
1270
|
-
cleanCLI: false, // Don't clean CLI configs during normal run
|
|
1271
|
-
cleanTemp: true // Clean temporary files (always safe)
|
|
1272
|
-
});
|
|
1273
|
-
|
|
1274
|
-
console.log('\n[SUMMARY] Cache cleaning completed:');
|
|
1275
|
-
console.log(` 📄 Files removed: ${results.filesRemoved}`);
|
|
1276
|
-
console.log(` 📁 Directories removed: ${results.directoriesRemoved}`);
|
|
1277
|
-
console.log(` 💾 Space freed: ${formatBytes(results.bytesFreed)}`);
|
|
1278
|
-
|
|
1279
|
-
if (results.errors.length > 0) {
|
|
1280
|
-
console.log(`\n⚠️ Warnings: ${results.errors.length} files couldn't be removed`);
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
} catch (error) {
|
|
1284
|
-
console.error('[ERROR] Cache cleaning failed:', error.message);
|
|
1285
|
-
process.exit(1);
|
|
1286
|
-
}
|
|
1287
|
-
break;
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
case 'diagnostic':
|
|
1291
|
-
case 'diag':
|
|
1292
|
-
case 'd': {
|
|
1293
|
-
try {
|
|
1294
|
-
console.log('[DIAGNOSTIC] Stigmergy CLI System Diagnostic...\n');
|
|
1295
|
-
|
|
1296
|
-
// System information
|
|
1297
|
-
const packageJson = require('../../package.json');
|
|
1298
|
-
console.log(`📦 Stigmergy CLI v${packageJson.version}`);
|
|
1299
|
-
console.log(`🔧 Node.js: ${process.version}`);
|
|
1300
|
-
console.log(`💻 Platform: ${process.platform} (${process.arch})\n`);
|
|
1301
|
-
|
|
1302
|
-
// Check cache cleaner availability
|
|
1303
|
-
try {
|
|
1304
|
-
const CacheCleaner = require('../core/cache_cleaner');
|
|
1305
|
-
const cleaner = new CacheCleaner({ dryRun: true });
|
|
1306
|
-
|
|
1307
|
-
const plan = await cleaner.createInstallationPlan();
|
|
1308
|
-
console.log('🧹 Cache Analysis:');
|
|
1309
|
-
console.log(` 📊 Estimated space to clean: ${formatBytes(plan.estimatedSize)}`);
|
|
1310
|
-
console.log(` 🗂️ Temporary files detected: ${plan.files.length}`);
|
|
1311
|
-
} catch (error) {
|
|
1312
|
-
console.log('⚠️ Cache cleaner not available');
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
// CLI tools status
|
|
1316
|
-
try {
|
|
1317
|
-
const { available, missing } = await installer.scanCLI();
|
|
1318
|
-
console.log('\n🔧 CLI Tools Status:');
|
|
1319
|
-
console.log(` ✅ Available: ${Object.keys(available).length}`);
|
|
1320
|
-
console.log(` ❌ Missing: ${Object.keys(missing).length}`);
|
|
1321
|
-
|
|
1322
|
-
if (Object.keys(missing).length > 0) {
|
|
1323
|
-
console.log('\nMissing Tools:');
|
|
1324
|
-
for (const [toolName, toolInfo] of Object.entries(missing)) {
|
|
1325
|
-
console.log(` - ${toolInfo.name}`);
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
} catch (error) {
|
|
1329
|
-
console.log('⚠️ CLI scan failed');
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
// Installation suggestions
|
|
1333
|
-
console.log('\n💡 Recommendations:');
|
|
1334
|
-
console.log(' • Run "stigmergy install" to install missing CLI tools');
|
|
1335
|
-
console.log(' • Run "stigmergy clean" to free up disk space');
|
|
1336
|
-
console.log(' • Run "stigmergy setup" for complete configuration');
|
|
1337
|
-
|
|
1338
|
-
if (args.includes('--verbose')) {
|
|
1339
|
-
console.log('\n📋 Advanced Options:');
|
|
1340
|
-
console.log(' • stigmergy clean --all - Clean all caches');
|
|
1341
|
-
console.log(' • stigmergy clean --dry-run - Preview cleaning');
|
|
1342
|
-
console.log(' • npm uninstall -g stigmergy - Uninstall Stigmergy completely (runs enhanced cleanup)');
|
|
1343
|
-
console.log(' • See remaining items after uninstall (individual CLI tools, docs, etc.)');
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
} catch (error) {
|
|
1347
|
-
console.error('[ERROR] Diagnostic failed:', error.message);
|
|
1348
|
-
process.exit(1);
|
|
1349
|
-
}
|
|
1350
|
-
break;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
case 'fix-perms': {
|
|
1354
|
-
try {
|
|
1355
|
-
console.log('[FIX-PERMS] Setting up working directory with proper permissions...\n');
|
|
1356
|
-
|
|
1357
|
-
const permAwareInstaller = new PermissionAwareInstaller({
|
|
1358
|
-
verbose: process.env.DEBUG === 'true',
|
|
1359
|
-
skipPermissionCheck: false,
|
|
1360
|
-
autoConfigureShell: true
|
|
1361
|
-
});
|
|
1362
|
-
|
|
1363
|
-
const result = await permAwareInstaller.install();
|
|
1364
|
-
|
|
1365
|
-
if (result.success) {
|
|
1366
|
-
console.log('\n✅ Permission setup completed successfully!');
|
|
1367
|
-
permAwareInstaller.permissionManager.displayResults(result.permissionSetup);
|
|
1368
|
-
} else {
|
|
1369
|
-
console.log('\n❌ Permission setup failed');
|
|
1370
|
-
console.log(`Error: ${result.error || 'Unknown error'}`);
|
|
1371
|
-
process.exit(1);
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
} catch (error) {
|
|
1375
|
-
console.error('[ERROR] Permission setup failed:', error.message);
|
|
1376
|
-
if (process.env.DEBUG === 'true') {
|
|
1377
|
-
console.error(error.stack);
|
|
1378
|
-
}
|
|
1379
|
-
process.exit(1);
|
|
1380
|
-
}
|
|
1381
|
-
break;
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
case 'perm-check': {
|
|
1385
|
-
try {
|
|
1386
|
-
console.log('[PERM-CHECK] Checking current directory permissions...\n');
|
|
1387
|
-
|
|
1388
|
-
const permissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
1389
|
-
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
1390
|
-
|
|
1391
|
-
console.log(`📍 Current directory: ${process.cwd()}`);
|
|
1392
|
-
console.log(`🔧 Write permission: ${hasWritePermission ? '✅ Yes' : '❌ No'}`);
|
|
1393
|
-
|
|
1394
|
-
if (!hasWritePermission) {
|
|
1395
|
-
console.log('\n💡 Suggestions:');
|
|
1396
|
-
console.log('1. Run: stigmergy fix-perms # Fix permissions automatically');
|
|
1397
|
-
console.log('2. Change to user directory: cd ~');
|
|
1398
|
-
console.log('3. Create project directory: mkdir ~/stigmergy && cd ~/stigmergy');
|
|
1399
|
-
console.log('\n🔍 System Info:');
|
|
1400
|
-
const sysInfo = permissionManager.getSystemInfo();
|
|
1401
|
-
console.log(` Platform: ${sysInfo.platform}`);
|
|
1402
|
-
console.log(` Shell: ${sysInfo.shell}`);
|
|
1403
|
-
console.log(` Home: ${sysInfo.homeDir}`);
|
|
1404
|
-
} else {
|
|
1405
|
-
console.log('\n✅ Current directory is ready for installation');
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
} catch (error) {
|
|
1409
|
-
console.error('[ERROR] Permission check failed:', error.message);
|
|
1410
|
-
if (process.env.DEBUG === 'true') {
|
|
1411
|
-
console.error(error.stack);
|
|
1412
|
-
}
|
|
1413
|
-
process.exit(1);
|
|
1414
|
-
}
|
|
1415
|
-
break;
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
default:
|
|
1419
|
-
// Check if the command matches a direct CLI tool name
|
|
1420
|
-
if (CLI_TOOLS[command]) {
|
|
1421
|
-
const toolName = command;
|
|
1422
|
-
const toolInfo = CLI_TOOLS[toolName];
|
|
1423
|
-
|
|
1424
|
-
// Get the prompt (everything after the tool name)
|
|
1425
|
-
const prompt = args.slice(1).join(' ');
|
|
1426
|
-
|
|
1427
|
-
if (!prompt) {
|
|
1428
|
-
console.log(`[ERROR] Usage: stigmergy ${toolName} "<prompt>"`);
|
|
1429
|
-
process.exit(1);
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
console.log(`[DIRECT] Routing to ${toolInfo.name}: ${prompt}`);
|
|
1433
|
-
|
|
1434
|
-
// Use smart router to handle the execution
|
|
1435
|
-
const router = new SmartRouter();
|
|
1436
|
-
await router.initialize();
|
|
1437
|
-
|
|
1438
|
-
// Create a route object similar to what smartRoute would return
|
|
1439
|
-
const route = {
|
|
1440
|
-
tool: toolName,
|
|
1441
|
-
prompt: prompt
|
|
1442
|
-
};
|
|
1443
|
-
|
|
1444
|
-
// Execute the routed command (reusing the call command logic)
|
|
1445
|
-
try {
|
|
1446
|
-
// Get the actual executable path for the tool using which/where command
|
|
1447
|
-
let toolPath = toolName;
|
|
1448
|
-
try {
|
|
1449
|
-
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
1450
|
-
const whichResult = spawnSync(whichCmd, [toolName], {
|
|
1451
|
-
encoding: 'utf8',
|
|
1452
|
-
timeout: 10000,
|
|
1453
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1454
|
-
shell: true,
|
|
1455
|
-
});
|
|
1456
|
-
|
|
1457
|
-
if (whichResult.status === 0 && whichResult.stdout.trim()) {
|
|
1458
|
-
// Get the first match (most likely the one that would be executed)
|
|
1459
|
-
toolPath = whichResult.stdout.trim().split('\n')[0].trim();
|
|
1460
|
-
}
|
|
1461
|
-
} catch (whichError) {
|
|
1462
|
-
// If which/where fails, continue with the tool name
|
|
1463
|
-
if (process.env.DEBUG === 'true') {
|
|
1464
|
-
console.log(`[DEBUG] which/where command failed for ${toolName}: ${whichError.message}`);
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
console.log(`[DEBUG] Tool path: ${toolPath}, Prompt: ${route.prompt}`);
|
|
1469
|
-
|
|
1470
|
-
// For different tools, we need to pass the prompt differently
|
|
1471
|
-
// Use unified parameter handler for better parameter handling
|
|
1472
|
-
let toolArgs = [];
|
|
1473
|
-
|
|
1474
|
-
try {
|
|
1475
|
-
// Get CLI pattern for this tool
|
|
1476
|
-
console.log(`[DEBUG] Attempting to get CLI pattern for: ${route.tool}`);
|
|
1477
|
-
const cliPattern = await router.analyzer.getCLIPattern(route.tool);
|
|
1478
|
-
console.log(`[DEBUG] Got CLI pattern: ${JSON.stringify(cliPattern)}`);
|
|
1479
|
-
|
|
1480
|
-
// Log the CLI pattern to debug command format issues
|
|
1481
|
-
if (process.env.DEBUG === 'true' && cliPattern) {
|
|
1482
|
-
console.log(
|
|
1483
|
-
`[DEBUG] CLI Pattern for ${route.tool}:`,
|
|
1484
|
-
JSON.stringify(cliPattern, null, 2),
|
|
1485
|
-
);
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
// Use the unified CLI parameter handler
|
|
1489
|
-
const CLIParameterHandler = require('../core/cli_parameter_handler');
|
|
1490
|
-
toolArgs = CLIParameterHandler.generateArguments(
|
|
1491
|
-
route.tool,
|
|
1492
|
-
route.prompt,
|
|
1493
|
-
cliPattern,
|
|
1494
|
-
);
|
|
1495
|
-
|
|
1496
|
-
// Add debug logging for the final arguments
|
|
1497
|
-
console.log(`[DEBUG] Final toolArgs: ${JSON.stringify(toolArgs)}`);
|
|
1498
|
-
} catch (patternError) {
|
|
1499
|
-
// Fallback to original logic if pattern analysis fails
|
|
1500
|
-
console.log(`[DEBUG] Pattern analysis failed, using fallback logic: ${patternError.message}`);
|
|
1501
|
-
if (route.tool === 'claude') {
|
|
1502
|
-
// Claude CLI expects the prompt with -p flag for non-interactive mode
|
|
1503
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
1504
|
-
} else if (route.tool === 'qodercli' || route.tool === 'iflow') {
|
|
1505
|
-
// Qoder CLI and iFlow expect the prompt with -p flag
|
|
1506
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
1507
|
-
} else if (route.tool === 'codex') {
|
|
1508
|
-
// Codex CLI needs 'exec' subcommand for non-interactive mode
|
|
1509
|
-
toolArgs = ['exec', '-p', `"${route.prompt}"`];
|
|
1510
|
-
} else {
|
|
1511
|
-
// For other tools, pass the prompt with -p flag
|
|
1512
|
-
toolArgs = ['-p', `"${route.prompt}"`];
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
// Add debug logging for the fallback arguments
|
|
1516
|
-
console.log(`[DEBUG] Fallback toolArgs: ${JSON.stringify(toolArgs)}`);
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
// Use the reliable cross-platform execution function
|
|
1520
|
-
try {
|
|
1521
|
-
// Validate that the tool exists before attempting to execute
|
|
1522
|
-
if (!toolPath || typeof toolPath !== 'string') {
|
|
1523
|
-
throw new Error(`Invalid tool path: ${toolPath}`);
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
|
-
// Special handling for JS files to ensure proper execution
|
|
1527
|
-
if (toolPath.endsWith('.js') || toolPath.endsWith('.cjs')) {
|
|
1528
|
-
// Use safe JS file execution
|
|
1529
|
-
if (process.env.DEBUG === 'true') {
|
|
1530
|
-
console.log(
|
|
1531
|
-
`[EXEC] Safely executing JS file: ${toolPath} ${toolArgs.join(' ')}`,
|
|
1532
|
-
);
|
|
1533
|
-
}
|
|
1534
|
-
const result = await executeJSFile(toolPath, toolArgs, {
|
|
1535
|
-
stdio: 'inherit',
|
|
1536
|
-
shell: true,
|
|
1537
|
-
});
|
|
1538
|
-
|
|
1539
|
-
if (!result.success) {
|
|
1540
|
-
console.log(
|
|
1541
|
-
`[WARN] ${route.tool} exited with code ${result.code}`,
|
|
1542
|
-
);
|
|
1543
|
-
}
|
|
1544
|
-
process.exit(result.code || 0);
|
|
1545
|
-
} else {
|
|
1546
|
-
// Regular command execution
|
|
1547
|
-
if (process.env.DEBUG === 'true') {
|
|
1548
|
-
console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
|
|
1549
|
-
}
|
|
1550
|
-
console.log(`[DEBUG] About to execute: ${toolPath} with args: ${JSON.stringify(toolArgs)}`);
|
|
1551
|
-
|
|
1552
|
-
// Special handling for Windows to construct the command properly
|
|
1553
|
-
let execCommand = toolPath;
|
|
1554
|
-
let execArgs = toolArgs;
|
|
1555
|
-
if (process.platform === 'win32') {
|
|
1556
|
-
// On Windows, we construct the full command line and pass it as a single string
|
|
1557
|
-
if (toolArgs.length > 0) {
|
|
1558
|
-
// For Windows, we need to properly quote the entire command line
|
|
1559
|
-
const argsString = toolArgs.map(arg => {
|
|
1560
|
-
// If arg contains spaces and is not already quoted, quote it
|
|
1561
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1562
|
-
return `"${arg}"`;
|
|
1563
|
-
}
|
|
1564
|
-
return arg;
|
|
1565
|
-
}).join(' ');
|
|
1566
|
-
execCommand = `${toolPath} ${argsString}`;
|
|
1567
|
-
execArgs = [];
|
|
1568
|
-
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
// Use detected paths for all CLI tools on all platforms
|
|
1573
|
-
const supportedTools = ['claude', 'copilot', 'qodercli', 'gemini', 'qwen', 'iflow', 'codebuddy', 'codex'];
|
|
1574
|
-
|
|
1575
|
-
if (supportedTools.includes(route.tool)) {
|
|
1576
|
-
// Use detected path for all CLI tools regardless of platform
|
|
1577
|
-
const detectedPath = await getCLIPath(route.tool);
|
|
1578
|
-
if (detectedPath) {
|
|
1579
|
-
execCommand = detectedPath;
|
|
1580
|
-
console.log(`[DEBUG] Using detected ${route.tool} path: ${execCommand}`);
|
|
1581
|
-
} else {
|
|
1582
|
-
// Fallback to system PATH for tools not detected
|
|
1583
|
-
console.log(`[DEBUG] Using system PATH for ${route.tool}: ${route.tool}`);
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1587
|
-
// Platform-specific command construction
|
|
1588
|
-
if (process.platform === 'win32') {
|
|
1589
|
-
// Special handling for Windows CLI tools
|
|
1590
|
-
if (route.tool === 'claude' && toolArgs.length > 0) {
|
|
1591
|
-
// Special parameter handling for Claude to avoid wrapper script issues
|
|
1592
|
-
const argsString = toolArgs.map(arg => {
|
|
1593
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1594
|
-
return `"${arg}"`;
|
|
1595
|
-
}
|
|
1596
|
-
return arg;
|
|
1597
|
-
}).join(' ');
|
|
1598
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
1599
|
-
execArgs = [];
|
|
1600
|
-
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
1601
|
-
} else if (route.tool === 'copilot') {
|
|
1602
|
-
// Copilot doesn't use -p parameter format
|
|
1603
|
-
execArgs = [];
|
|
1604
|
-
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
1605
|
-
} else if (toolArgs.length > 0) {
|
|
1606
|
-
// For other Windows tools, construct full command line
|
|
1607
|
-
const argsString = toolArgs.map(arg => {
|
|
1608
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1609
|
-
return `"${arg}"`;
|
|
1610
|
-
}
|
|
1611
|
-
return arg;
|
|
1612
|
-
}).join(' ');
|
|
1613
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
1614
|
-
execArgs = [];
|
|
1615
|
-
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
// Apply the same Windows handling logic to ensure consistency
|
|
1621
|
-
// This ensures consistency between direct routing and call command routing
|
|
1622
|
-
if (process.platform === 'win32' && execArgs.length > 0) {
|
|
1623
|
-
// For Windows, we need to properly quote the entire command line
|
|
1624
|
-
const argsString = execArgs.map(arg => {
|
|
1625
|
-
// If arg contains spaces and is not already quoted, quote it
|
|
1626
|
-
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1627
|
-
return `"${arg}"`;
|
|
1628
|
-
}
|
|
1629
|
-
return arg;
|
|
1630
|
-
}).join(' ');
|
|
1631
|
-
execCommand = `${execCommand} ${argsString}`;
|
|
1632
|
-
execArgs = [];
|
|
1633
|
-
console.log(`[DEBUG] Windows unified command: ${execCommand}`);
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
const result = await executeCommand(execCommand, execArgs, {
|
|
1637
|
-
stdio: 'inherit',
|
|
1638
|
-
shell: true,
|
|
1639
|
-
});
|
|
1640
|
-
|
|
1641
|
-
if (!result.success) {
|
|
1642
|
-
console.log(
|
|
1643
|
-
`[WARN] ${route.tool} exited with code ${result.code}`,
|
|
1644
|
-
);
|
|
1645
|
-
}
|
|
1646
|
-
process.exit(result.code || 0);
|
|
1647
|
-
}
|
|
1648
|
-
} catch (executionError) {
|
|
1649
|
-
// Check for specific errors that might not be actual failures
|
|
1650
|
-
const errorMessage =
|
|
1651
|
-
executionError.error?.message ||
|
|
1652
|
-
executionError.message ||
|
|
1653
|
-
executionError;
|
|
1654
|
-
|
|
1655
|
-
// For some tools like Claude, they may output to stdout and return non-zero codes
|
|
1656
|
-
// without actually failing - handle these cases more gracefully
|
|
1657
|
-
if (
|
|
1658
|
-
errorMessage.includes(
|
|
1659
|
-
'not recognized as an internal or external command',
|
|
1660
|
-
) ||
|
|
1661
|
-
errorMessage.includes('command not found') ||
|
|
1662
|
-
errorMessage.includes('ENOENT')
|
|
1663
|
-
) {
|
|
1664
|
-
// This is a genuine error - tool is not installed
|
|
1665
|
-
const cliError = await errorHandler.handleCLIError(
|
|
1666
|
-
route.tool,
|
|
1667
|
-
executionError.error || executionError,
|
|
1668
|
-
toolArgs.join(' '),
|
|
1669
|
-
);
|
|
1670
|
-
|
|
1671
|
-
// Provide clear ANSI English error message
|
|
1672
|
-
console.log('==================================================');
|
|
1673
|
-
console.log('ERROR: Failed to execute AI CLI tool');
|
|
1674
|
-
console.log('==================================================');
|
|
1675
|
-
console.log(`Tool: ${route.tool}`);
|
|
1676
|
-
console.log(`Error: ${cliError.message}`);
|
|
1677
|
-
if (executionError.stderr) {
|
|
1678
|
-
console.log(`Stderr: ${executionError.stderr}`);
|
|
1679
|
-
}
|
|
1680
|
-
console.log('');
|
|
1681
|
-
console.log('Possible solutions:');
|
|
1682
|
-
console.log('1. Check if the AI CLI tool is properly installed');
|
|
1683
|
-
console.log('2. Verify the tool is in your system PATH');
|
|
1684
|
-
console.log('3. Try reinstalling the tool with: stigmergy install');
|
|
1685
|
-
console.log('4. Run stigmergy status to check tool availability');
|
|
1686
|
-
console.log('');
|
|
1687
|
-
console.log('For manual execution, you can run:');
|
|
1688
|
-
console.log(`${toolPath} ${toolArgs.join(' ')}`);
|
|
1689
|
-
console.log('==================================================');
|
|
1690
|
-
process.exit(1);
|
|
1691
|
-
} else {
|
|
1692
|
-
// For other execution errors, try to execute the command directly
|
|
1693
|
-
// which handles cases where the tool executed successfully but returned an error object
|
|
1694
|
-
console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
|
|
1695
|
-
|
|
1696
|
-
// Set environment for tools that need specific working directories
|
|
1697
|
-
const env = { ...process.env };
|
|
1698
|
-
if (route.tool === 'qwen') {
|
|
1699
|
-
delete env.NODE_PATH;
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
const result = await executeCommand(toolPath, toolArgs, {
|
|
1703
|
-
stdio: 'inherit',
|
|
1704
|
-
shell: true,
|
|
1705
|
-
cwd: getWorkingDirectoryForTool(route.tool),
|
|
1706
|
-
env,
|
|
1707
|
-
});
|
|
1708
|
-
|
|
1709
|
-
if (!result.success) {
|
|
1710
|
-
console.log(
|
|
1711
|
-
`[WARN] ${route.tool} exited with code ${result.code}`,
|
|
1712
|
-
);
|
|
1713
|
-
}
|
|
1714
|
-
process.exit(result.code || 0);
|
|
1715
|
-
}
|
|
1716
|
-
}
|
|
1717
|
-
} catch (error) {
|
|
1718
|
-
const cliError = await errorHandler.handleCLIError(
|
|
1719
|
-
route.tool,
|
|
1720
|
-
error,
|
|
1721
|
-
prompt,
|
|
1722
|
-
);
|
|
1723
|
-
console.log(
|
|
1724
|
-
`[ERROR] Failed to execute ${route.tool}:`,
|
|
1725
|
-
cliError.message,
|
|
1726
|
-
);
|
|
1727
|
-
process.exit(1);
|
|
1728
|
-
}
|
|
1729
|
-
} else {
|
|
1730
|
-
console.log(`[ERROR] Unknown command: ${command}`);
|
|
1731
|
-
console.log('[INFO] Run "stigmergy --help" for usage information');
|
|
1732
|
-
process.exit(1);
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
module.exports = main;
|