stigmergy 1.2.10 → 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/router.js +50 -0
- package/src/core/cli_path_detector.js +148 -11
package/package.json
CHANGED
package/src/cli/router.js
CHANGED
|
@@ -45,6 +45,30 @@ function formatBytes(bytes) {
|
|
|
45
45
|
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
|
46
46
|
}
|
|
47
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
|
+
|
|
48
72
|
async function main() {
|
|
49
73
|
const args = process.argv.slice(2);
|
|
50
74
|
|
|
@@ -757,9 +781,18 @@ async function main() {
|
|
|
757
781
|
console.log(`[DEBUG] Windows unified command: ${execCommand}`);
|
|
758
782
|
}
|
|
759
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
|
+
|
|
760
791
|
const result = await executeCommand(execCommand, execArgs, {
|
|
761
792
|
stdio: 'inherit',
|
|
762
793
|
shell: true,
|
|
794
|
+
cwd: getWorkingDirectoryForTool(route.tool),
|
|
795
|
+
env,
|
|
763
796
|
});
|
|
764
797
|
|
|
765
798
|
if (!result.success) {
|
|
@@ -809,9 +842,17 @@ async function main() {
|
|
|
809
842
|
// For other execution errors, try to execute the command directly
|
|
810
843
|
// which handles cases where the tool executed successfully but returned an error object
|
|
811
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
|
+
|
|
812
851
|
const result = await executeCommand(toolPath, toolArgs, {
|
|
813
852
|
stdio: 'inherit',
|
|
814
853
|
shell: true,
|
|
854
|
+
cwd: getWorkingDirectoryForTool(route.tool),
|
|
855
|
+
env,
|
|
815
856
|
});
|
|
816
857
|
|
|
817
858
|
if (!result.success) {
|
|
@@ -1651,9 +1692,18 @@ async function main() {
|
|
|
1651
1692
|
// For other execution errors, try to execute the command directly
|
|
1652
1693
|
// which handles cases where the tool executed successfully but returned an error object
|
|
1653
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
|
+
|
|
1654
1702
|
const result = await executeCommand(toolPath, toolArgs, {
|
|
1655
1703
|
stdio: 'inherit',
|
|
1656
1704
|
shell: true,
|
|
1705
|
+
cwd: getWorkingDirectoryForTool(route.tool),
|
|
1706
|
+
env,
|
|
1657
1707
|
});
|
|
1658
1708
|
|
|
1659
1709
|
if (!result.success) {
|
|
@@ -48,17 +48,52 @@ class CLIPathDetector {
|
|
|
48
48
|
path.join(process.env.ProgramFiles || 'C:/Program Files', 'npm')
|
|
49
49
|
);
|
|
50
50
|
} else {
|
|
51
|
-
// Unix-like paths
|
|
51
|
+
// Unix-like paths - comprehensive coverage
|
|
52
52
|
paths.push(
|
|
53
|
-
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
path.join(os.homedir(), '
|
|
53
|
+
// User-specific npm global paths
|
|
54
|
+
path.join(os.homedir(), '.npm-global', 'bin'), // User local with custom prefix
|
|
55
|
+
path.join(os.homedir(), '.npm', 'bin'), // User npm
|
|
56
|
+
path.join(os.homedir(), 'node_modules', '.bin'), // Local node_modules bin
|
|
57
|
+
|
|
58
|
+
// System-wide paths
|
|
59
|
+
'/usr/local/bin', // Common system location
|
|
60
|
+
'/usr/bin', // System binaries
|
|
61
|
+
'/opt/node/bin', // Node.js installed to /opt
|
|
62
|
+
'/opt/nodejs/bin', // Alternative system installation
|
|
63
|
+
|
|
64
|
+
// Root-specific paths (when running as root)
|
|
65
|
+
'/root/.npm-global/bin', // Root user custom prefix
|
|
66
|
+
'/root/.npm/bin', // Root user npm
|
|
67
|
+
'/root/node_modules/.bin', // Root local node_modules
|
|
68
|
+
'/root/.nvm/versions/node/*/bin', // NVM installations for root
|
|
69
|
+
|
|
70
|
+
// NVM (Node Version Manager) paths for regular users
|
|
71
|
+
path.join(os.homedir(), '.nvm', 'versions', 'node', '*', 'bin'), // NVM user installations
|
|
72
|
+
path.join(os.homedir(), '.nvm', 'current', 'bin'), // NVM current version
|
|
73
|
+
|
|
74
|
+
// NodeSource installation paths
|
|
75
|
+
'/usr/bin/nodejs', // NodeSource package installations
|
|
76
|
+
'/usr/local/share/npm/bin', // npm share location
|
|
77
|
+
|
|
78
|
+
// Homebrew (macOS) paths
|
|
79
|
+
path.join(os.homedir(), '.brew', 'node', 'bin'), // Custom Homebrew
|
|
80
|
+
'/opt/homebrew/bin', // Apple Silicon Homebrew
|
|
81
|
+
'/usr/local/bin', // Intel Homebrew
|
|
82
|
+
|
|
83
|
+
// pkg-config and other package managers
|
|
84
|
+
path.join(os.homedir(), '.local', 'bin'), // User local binaries
|
|
85
|
+
'/snap/bin', // Snap packages (Ubuntu)
|
|
86
|
+
'/var/lib/snapd/snap/bin' // Snap system
|
|
57
87
|
);
|
|
58
88
|
}
|
|
59
89
|
|
|
90
|
+
// Filter paths, handling wildcards for NVM
|
|
60
91
|
return paths.filter(p => {
|
|
61
92
|
try {
|
|
93
|
+
// Handle wildcard paths (NVM versions)
|
|
94
|
+
if (p.includes('*')) {
|
|
95
|
+
return this.expandWildcardPath(p);
|
|
96
|
+
}
|
|
62
97
|
return fs.existsSync(p);
|
|
63
98
|
} catch {
|
|
64
99
|
return false;
|
|
@@ -66,6 +101,36 @@ class CLIPathDetector {
|
|
|
66
101
|
});
|
|
67
102
|
}
|
|
68
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Expand wildcard paths (e.g., NVM version paths)
|
|
106
|
+
*/
|
|
107
|
+
expandWildcardPath(wildcardPath) {
|
|
108
|
+
try {
|
|
109
|
+
const { spawnSync } = require('child_process');
|
|
110
|
+
|
|
111
|
+
// Use shell to expand wildcards
|
|
112
|
+
const result = spawnSync('bash', ['-c', `ls -d ${wildcardPath} 2>/dev/null`], {
|
|
113
|
+
encoding: 'utf8',
|
|
114
|
+
shell: true
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (result.status === 0 && result.stdout.trim()) {
|
|
118
|
+
// Check if any of the expanded paths exist
|
|
119
|
+
const expandedPaths = result.stdout.trim().split('\n');
|
|
120
|
+
return expandedPaths.some(p => {
|
|
121
|
+
try {
|
|
122
|
+
return fs.existsSync(p.trim());
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
} catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
69
134
|
/**
|
|
70
135
|
* Get current PATH environment variable
|
|
71
136
|
*/
|
|
@@ -146,8 +211,15 @@ class CLIPathDetector {
|
|
|
146
211
|
const commandNames = this.cliNameMap[toolName] || [toolName];
|
|
147
212
|
|
|
148
213
|
for (const command of commandNames) {
|
|
214
|
+
// Method 0: Use npm to get actual global installation path
|
|
215
|
+
let pathFound = await this.findCommandViaNPM(command);
|
|
216
|
+
if (pathFound) {
|
|
217
|
+
console.log(`[DETECTOR] Found ${toolName} via npm: ${pathFound}`);
|
|
218
|
+
return pathFound;
|
|
219
|
+
}
|
|
220
|
+
|
|
149
221
|
// Method 1: Check system PATH (most common)
|
|
150
|
-
|
|
222
|
+
pathFound = this.findCommandInPath(command);
|
|
151
223
|
if (pathFound) {
|
|
152
224
|
console.log(`[DETECTOR] Found ${toolName} in PATH: ${pathFound}`);
|
|
153
225
|
return pathFound;
|
|
@@ -169,11 +241,23 @@ class CLIPathDetector {
|
|
|
169
241
|
return pathFound;
|
|
170
242
|
}
|
|
171
243
|
} else {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
244
|
+
// Check multiple Unix-like locations
|
|
245
|
+
const unixPaths = [
|
|
246
|
+
path.join(os.homedir(), '.npm-global', 'bin'),
|
|
247
|
+
path.join(os.homedir(), '.npm', 'bin'),
|
|
248
|
+
'/usr/local/bin',
|
|
249
|
+
'/usr/bin',
|
|
250
|
+
path.join(os.homedir(), '.local', 'bin'),
|
|
251
|
+
'/root/.npm-global/bin',
|
|
252
|
+
'/root/.npm/bin'
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
for (const dir of unixPaths) {
|
|
256
|
+
pathFound = this.checkCommandInDir(command, dir);
|
|
257
|
+
if (pathFound) {
|
|
258
|
+
console.log(`[DETECTOR] Found ${toolName} in ${dir}: ${pathFound}`);
|
|
259
|
+
return pathFound;
|
|
260
|
+
}
|
|
177
261
|
}
|
|
178
262
|
}
|
|
179
263
|
}
|
|
@@ -182,6 +266,59 @@ class CLIPathDetector {
|
|
|
182
266
|
return null;
|
|
183
267
|
}
|
|
184
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Find command using npm's actual global installation path
|
|
271
|
+
*/
|
|
272
|
+
async findCommandViaNPM(command) {
|
|
273
|
+
try {
|
|
274
|
+
const { spawnSync } = require('child_process');
|
|
275
|
+
|
|
276
|
+
// Get npm global prefix
|
|
277
|
+
const npmPrefixResult = spawnSync('npm', ['config', 'get', 'prefix'], {
|
|
278
|
+
encoding: 'utf8',
|
|
279
|
+
shell: true
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (npmPrefixResult.status === 0 && npmPrefixResult.stdout.trim()) {
|
|
283
|
+
const npmPrefix = npmPrefixResult.stdout.trim();
|
|
284
|
+
let binDir;
|
|
285
|
+
|
|
286
|
+
if (this.platform === 'win32') {
|
|
287
|
+
binDir = npmPrefix; // Windows: prefix already points to the directory with executables
|
|
288
|
+
} else {
|
|
289
|
+
binDir = path.join(npmPrefix, 'bin'); // Unix: bin subdirectory
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const commandPath = this.checkCommandInDir(command, binDir);
|
|
293
|
+
if (commandPath) {
|
|
294
|
+
return commandPath;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Try alternative npm config methods
|
|
299
|
+
const npmListResult = spawnSync('npm', ['list', '-g', '--depth=0'], {
|
|
300
|
+
encoding: 'utf8',
|
|
301
|
+
shell: true
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (npmListResult.status === 0) {
|
|
305
|
+
// Extract global prefix from npm list output if needed
|
|
306
|
+
const lines = npmListResult.stdout.split('\n');
|
|
307
|
+
for (const line of lines) {
|
|
308
|
+
if (line.includes(`${command}@`)) {
|
|
309
|
+
// Package is installed globally, try to find it in common locations
|
|
310
|
+
return null; // Fall back to other methods
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return null;
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.log(`[DETECTOR] npm query failed: ${error.message}`);
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
185
322
|
/**
|
|
186
323
|
* Detect all CLI tool paths
|
|
187
324
|
*/
|