stigmergy 1.2.8 → 1.2.10
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 +40 -6
- package/STIGMERGY.md +10 -0
- package/package.json +19 -5
- package/scripts/preuninstall.js +10 -0
- package/src/adapters/claude/install_claude_integration.js +21 -21
- package/src/adapters/codebuddy/install_codebuddy_integration.js +54 -51
- package/src/adapters/codex/install_codex_integration.js +27 -28
- package/src/adapters/gemini/install_gemini_integration.js +60 -60
- package/src/adapters/iflow/install_iflow_integration.js +72 -72
- package/src/adapters/qoder/install_qoder_integration.js +64 -64
- package/src/adapters/qwen/install_qwen_integration.js +7 -7
- package/src/cli/router.js +581 -175
- package/src/commands/skill-bridge.js +39 -0
- package/src/commands/skill-handler.js +150 -0
- package/src/commands/skill.js +127 -0
- package/src/core/cli_path_detector.js +573 -0
- package/src/core/cli_tools.js +72 -1
- package/src/core/coordination/nodejs/AdapterManager.js +29 -1
- package/src/core/directory_permission_manager.js +568 -0
- package/src/core/enhanced_cli_installer.js +609 -0
- package/src/core/installer.js +232 -88
- package/src/core/multilingual/language-pattern-manager.js +78 -50
- package/src/core/persistent_shell_configurator.js +468 -0
- package/src/core/skills/StigmergySkillManager.js +357 -0
- package/src/core/skills/__tests__/SkillInstaller.test.js +275 -0
- package/src/core/skills/__tests__/SkillParser.test.js +202 -0
- package/src/core/skills/__tests__/SkillReader.test.js +189 -0
- package/src/core/skills/cli-command-test.js +201 -0
- package/src/core/skills/comprehensive-e2e-test.js +473 -0
- package/src/core/skills/e2e-test.js +267 -0
- package/src/core/skills/embedded-openskills/SkillInstaller.js +438 -0
- package/src/core/skills/embedded-openskills/SkillParser.js +123 -0
- package/src/core/skills/embedded-openskills/SkillReader.js +143 -0
- package/src/core/skills/integration-test.js +248 -0
- package/src/core/skills/package.json +6 -0
- package/src/core/skills/regression-test.js +285 -0
- package/src/core/skills/run-all-tests.js +129 -0
- package/src/core/skills/sync-test.js +210 -0
- package/src/core/skills/test-runner.js +242 -0
- package/src/utils/helpers.js +3 -20
- package/src/auth.js +0 -173
- package/src/auth_command.js +0 -208
- package/src/calculator.js +0 -313
- package/src/core/enhanced_installer.js +0 -479
- package/src/core/enhanced_uninstaller.js +0 -638
- package/src/data_encryption.js +0 -143
- package/src/data_structures.js +0 -440
- package/src/deploy.js +0 -55
package/src/cli/router.js
CHANGED
|
@@ -18,13 +18,16 @@ const fs = require('fs/promises');
|
|
|
18
18
|
const fsSync = require('fs');
|
|
19
19
|
const { spawnSync } = require('child_process');
|
|
20
20
|
|
|
21
|
+
// Import permission management components
|
|
22
|
+
const DirectoryPermissionManager = require('../core/directory_permission_manager');
|
|
23
|
+
const { setupCLIPaths, getCLIPath } = require('../core/cli_tools');
|
|
24
|
+
|
|
21
25
|
// Import our custom modules
|
|
22
26
|
const SmartRouter = require('../core/smart_router');
|
|
23
27
|
const CLIHelpAnalyzer = require('../core/cli_help_analyzer');
|
|
24
28
|
const { CLI_TOOLS } = require('../core/cli_tools');
|
|
25
29
|
const { errorHandler } = require('../core/error_handler');
|
|
26
30
|
const { executeCommand, executeJSFile } = require('../utils');
|
|
27
|
-
const { UserAuthenticator } = require('../auth');
|
|
28
31
|
const MemoryManager = require('../core/memory_manager');
|
|
29
32
|
const StigmergyInstaller = require('../core/installer');
|
|
30
33
|
const UpgradeManager = require('../core/upgrade_manager');
|
|
@@ -72,17 +75,26 @@ async function main() {
|
|
|
72
75
|
console.log(' version, --version Show version information');
|
|
73
76
|
console.log(' status Check CLI tools status');
|
|
74
77
|
console.log(' scan Scan for available AI CLI tools');
|
|
75
|
-
console.log(' install Auto-install missing CLI tools');
|
|
78
|
+
console.log(' install Auto-install missing CLI tools (with permission fix)');
|
|
76
79
|
console.log(' upgrade Upgrade all CLI tools to latest versions');
|
|
77
80
|
console.log(
|
|
78
81
|
' deploy Deploy hooks and integration to installed tools',
|
|
79
82
|
);
|
|
80
83
|
console.log(' setup Complete setup and configuration');
|
|
81
84
|
console.log(
|
|
82
|
-
' init Initialize Stigmergy
|
|
85
|
+
' init Initialize Stigmergy project in current directory',
|
|
83
86
|
);
|
|
84
87
|
console.log(' clean (c) Clean temporary files and caches');
|
|
85
88
|
console.log(' diagnostic (d) Show system diagnostic information');
|
|
89
|
+
console.log(' fix-perms Fix directory permissions for installation');
|
|
90
|
+
console.log(' perm-check Check current directory permissions');
|
|
91
|
+
console.log(' skill <action> Manage skills across CLIs (install/read/list/sync/remove)');
|
|
92
|
+
console.log(' skill-i <src> Install skills (shortcut for: skill install)');
|
|
93
|
+
console.log(' skill-l List skills (shortcut for: skill list)');
|
|
94
|
+
console.log(' skill-r <name> Read skill (shortcut for: skill read)');
|
|
95
|
+
console.log(' skill-v <name> View/validate skill (auto-detect read or validate)');
|
|
96
|
+
console.log(' skill-d <name> Delete/remove skill (shortcut for: skill remove)');
|
|
97
|
+
console.log(' skill Sync skills to all CLI configs (shortcut for: skill sync)');
|
|
86
98
|
console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
|
|
87
99
|
console.log(' <tool> "<prompt>" Directly route to specific AI CLI tool');
|
|
88
100
|
console.log(' Supported tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex');
|
|
@@ -126,52 +138,106 @@ async function main() {
|
|
|
126
138
|
break;
|
|
127
139
|
|
|
128
140
|
case 'init':
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
141
|
+
try {
|
|
142
|
+
console.log('[INIT] Initializing Stigmergy project in current directory...\n');
|
|
143
|
+
|
|
144
|
+
// Quick path detection for better tool availability
|
|
145
|
+
console.log('[INIT] Detecting CLI tool paths...');
|
|
146
|
+
const pathSetup = await setupCLIPaths();
|
|
147
|
+
|
|
148
|
+
console.log(`[INIT] CLI tool detection: ${pathSetup.report.summary.found}/${pathSetup.report.summary.total} tools found`);
|
|
149
|
+
|
|
150
|
+
// Initialize project files in current directory
|
|
151
|
+
await installer.createProjectFiles();
|
|
152
|
+
|
|
153
|
+
console.log('[INIT] Project initialization completed successfully!');
|
|
154
|
+
console.log('\n[INFO] Created:');
|
|
155
|
+
console.log(' - PROJECT_SPEC.json (project specification)');
|
|
156
|
+
console.log(' - PROJECT_CONSTITUTION.md (collaboration guidelines)');
|
|
157
|
+
console.log(' - CLI path detection cache in ~/.stigmergy/cli-paths/');
|
|
158
|
+
|
|
159
|
+
if (pathSetup.report.summary.missing > 0) {
|
|
160
|
+
console.log('\n[INFO] For full CLI integration, run:');
|
|
161
|
+
console.log(' stigmergy setup # Complete setup with PATH configuration');
|
|
162
|
+
}
|
|
163
|
+
} catch (error) {
|
|
164
|
+
await errorHandler.logError(error, 'ERROR', 'main.init');
|
|
165
|
+
console.log(`[ERROR] Project initialization failed: ${error.message}`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
132
169
|
|
|
133
170
|
case 'setup':
|
|
134
171
|
try {
|
|
135
172
|
console.log('[SETUP] Starting complete Stigmergy setup...\n');
|
|
136
173
|
|
|
137
|
-
// Step
|
|
138
|
-
|
|
174
|
+
// Step 0: Setup CLI paths detection and configuration
|
|
175
|
+
console.log('[STEP 0] Setting up CLI path detection...');
|
|
176
|
+
const pathSetup = await setupCLIPaths();
|
|
139
177
|
|
|
140
|
-
|
|
178
|
+
console.log(`[PATH] Path detection complete:`);
|
|
179
|
+
console.log(` - Found: ${pathSetup.report.summary.found} CLI tools`);
|
|
180
|
+
console.log(` - Missing: ${pathSetup.report.summary.missing} CLI tools`);
|
|
181
|
+
|
|
182
|
+
if (pathSetup.pathStatus.updated) {
|
|
183
|
+
console.log('\n[PATH] ✓ All npm global directories are now available in PATH');
|
|
184
|
+
console.log('[PATH] CLI tools will be globally accessible after terminal restart');
|
|
185
|
+
} else {
|
|
186
|
+
console.log('\n[PATH] ⚠️ PATH update failed:');
|
|
187
|
+
console.log(` Error: ${pathSetup.pathStatus.message}`);
|
|
188
|
+
console.log('\n[PATH] Manual update required:');
|
|
189
|
+
console.log(' Run the generated scripts to update PATH:');
|
|
190
|
+
if (pathSetup.pathStatus.scriptPath) {
|
|
191
|
+
console.log(` - Script directory: ${pathSetup.pathStatus.scriptPath}`);
|
|
192
|
+
}
|
|
193
|
+
console.log(' - Windows: Run PowerShell as Administrator and execute the scripts');
|
|
194
|
+
console.log(' - Unix/Linux: Source the shell script (source update-path.sh)');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Step 1: Scan for CLI tools
|
|
198
|
+
console.log('\n[STEP 1] Scanning for AI CLI tools...');
|
|
141
199
|
const { available: setupAvailable, missing: setupMissing } =
|
|
142
200
|
await installer.scanCLI();
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
);
|
|
155
|
-
await installer.installTools(selectedTools, setupMissing);
|
|
201
|
+
|
|
202
|
+
// Step 2: Install missing CLI tools
|
|
203
|
+
if (Object.keys(setupMissing).length > 0) {
|
|
204
|
+
console.log('\n[STEP 2] Installing missing tools...');
|
|
205
|
+
console.log('[INFO] Missing tools found:');
|
|
206
|
+
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
207
|
+
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log('\n[INFO] To install missing tools, run:');
|
|
211
|
+
for (const [toolName, toolInfo] of Object.entries(setupMissing)) {
|
|
212
|
+
console.log(` ${toolInfo.install}`);
|
|
156
213
|
}
|
|
214
|
+
|
|
215
|
+
console.log('\n[INFO] Or use the enhanced installer:');
|
|
216
|
+
console.log(' node src/core/enhanced_installer.js');
|
|
157
217
|
} else {
|
|
158
|
-
console.log('\n[
|
|
218
|
+
console.log('\n[STEP 2] All required tools are already installed!');
|
|
159
219
|
}
|
|
160
220
|
|
|
161
|
-
// Step
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
await installer.initializeConfig();
|
|
221
|
+
// Step 3: Deploy hooks to available CLI tools
|
|
222
|
+
if (Object.keys(setupAvailable).length > 0) {
|
|
223
|
+
console.log('\n[STEP 3] Deploying hooks to available tools...');
|
|
224
|
+
await installer.deployHooks(setupAvailable);
|
|
225
|
+
} else {
|
|
226
|
+
console.log('\n[STEP 3] No tools available for hook deployment');
|
|
227
|
+
}
|
|
169
228
|
|
|
170
|
-
|
|
171
|
-
|
|
229
|
+
console.log('\n🎉 Setup completed successfully!');
|
|
230
|
+
console.log('\n[USAGE] Get started with these commands:');
|
|
231
|
+
console.log(' stigmergy d - System diagnostic (recommended first)');
|
|
232
|
+
console.log(' stigmergy inst - Install missing AI CLI tools');
|
|
233
|
+
console.log(' stigmergy deploy - Deploy hooks to installed tools');
|
|
234
|
+
console.log(' stigmergy call - Execute prompts with auto-routing');
|
|
235
|
+
|
|
172
236
|
} catch (error) {
|
|
173
|
-
|
|
174
|
-
|
|
237
|
+
console.error('[ERROR] Setup failed:', error.message);
|
|
238
|
+
if (process.env.DEBUG === 'true') {
|
|
239
|
+
console.error(error.stack);
|
|
240
|
+
}
|
|
175
241
|
console.log('\n[TROUBLESHOOTING] To manually complete setup:');
|
|
176
242
|
console.log('1. Run: stigmergy deploy # Deploy hooks manually');
|
|
177
243
|
console.log('2. Run: stigmergy setup # Try setup again');
|
|
@@ -222,146 +288,129 @@ async function main() {
|
|
|
222
288
|
|
|
223
289
|
case 'upgrade': {
|
|
224
290
|
try {
|
|
225
|
-
console.log('[UPGRADE] Starting CLI tools upgrade process
|
|
226
|
-
|
|
227
|
-
await upgrader.initialize();
|
|
228
|
-
|
|
291
|
+
console.log('[UPGRADE] Starting AI CLI tools upgrade process...\n');
|
|
292
|
+
|
|
229
293
|
// 解析命令行选项
|
|
230
294
|
const upgradeArgs = args.slice(1);
|
|
231
295
|
const options = {
|
|
232
296
|
dryRun: upgradeArgs.includes('--dry-run'),
|
|
233
297
|
force: upgradeArgs.includes('--force'),
|
|
234
|
-
verbose: upgradeArgs.includes('--verbose')
|
|
235
|
-
diagnose: upgradeArgs.includes('--diagnose'),
|
|
236
|
-
suggest: upgradeArgs.includes('--suggest')
|
|
298
|
+
verbose: upgradeArgs.includes('--verbose')
|
|
237
299
|
};
|
|
300
|
+
|
|
301
|
+
// 使用EnhancedCLIInstaller进行升级
|
|
302
|
+
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
303
|
+
const enhancedInstaller = new EnhancedCLIInstaller({
|
|
304
|
+
verbose: process.env.DEBUG === 'true' || options.verbose,
|
|
305
|
+
autoRetry: true,
|
|
306
|
+
maxRetries: 2
|
|
307
|
+
});
|
|
238
308
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const deprecations = await upgrader.checkDeprecations();
|
|
309
|
+
// 获取已安装的工具列表 - 使用全局installer扫描
|
|
310
|
+
const { available: installedTools } = await installer.scanCLI();
|
|
242
311
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} else {
|
|
246
|
-
console.log('❌ Issues found:');
|
|
247
|
-
deprecations.forEach((dep, index) => {
|
|
248
|
-
console.log(`\n${index + 1}. ${dep.type || 'Unknown'}`);
|
|
249
|
-
if (dep.dependency) console.log(` Dependency: ${dep.dependency}`);
|
|
250
|
-
console.log(` Issues: ${dep.issues.join(', ')}`);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
312
|
+
if (Object.keys(installedTools).length === 0) {
|
|
313
|
+
console.log('[INFO] No AI CLI tools found. Please install tools first with: stigmergy install');
|
|
253
314
|
break;
|
|
254
315
|
}
|
|
255
316
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
console.log('📋 Recommendations:');
|
|
261
|
-
if (plan.upgrades.length > 0) {
|
|
262
|
-
console.log('\n🔺 Available Upgrades:');
|
|
263
|
-
plan.upgrades.forEach(upgrade => {
|
|
264
|
-
console.log(` • ${upgrade.tool}: ${upgrade.from} → ${upgrade.to}`);
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (plan.fixes.length > 0) {
|
|
269
|
-
console.log('\n🔧 Recommended Fixes:');
|
|
270
|
-
plan.fixes.forEach(fix => {
|
|
271
|
-
console.log(` • ${fix.type}: ${fix.description}`);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
317
|
+
console.log(`[INFO] Found ${Object.keys(installedTools).length} installed AI CLI tools:`);
|
|
318
|
+
for (const [toolName, toolInfo] of Object.entries(installedTools)) {
|
|
319
|
+
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
320
|
+
}
|
|
274
321
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
322
|
+
if (options.dryRun) {
|
|
323
|
+
console.log('\n🔍 DRY RUN MODE - No changes will be made');
|
|
324
|
+
console.log(' Use --force to execute the upgrade');
|
|
278
325
|
break;
|
|
279
326
|
}
|
|
280
327
|
|
|
281
|
-
//
|
|
282
|
-
console.log(
|
|
283
|
-
|
|
328
|
+
// 默认直接执行升级,无需用户确认
|
|
329
|
+
console.log(`\n[UPGRADE] Upgrading ${Object.keys(installedTools).length} AI CLI tools...`);
|
|
330
|
+
console.log('[INFO] Use --dry-run to preview upgrades without executing');
|
|
284
331
|
|
|
285
|
-
|
|
286
|
-
console.log('📊 UPGRADE PLAN');
|
|
287
|
-
console.log('='.repeat(50));
|
|
332
|
+
console.log('\n🚀 Upgrading AI CLI tools with automatic permission handling...\n');
|
|
288
333
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
plan.upgrades.forEach(upgrade => {
|
|
292
|
-
console.log(` • ${upgrade.tool.padEnd(12)} ${upgrade.from} → ${upgrade.to}`);
|
|
293
|
-
});
|
|
294
|
-
} else {
|
|
295
|
-
console.log('\n✅ All CLI tools are up to date');
|
|
296
|
-
}
|
|
334
|
+
// 批量升级所有工具,一次权限检测
|
|
335
|
+
console.log(`[INFO] Starting batch upgrade of ${Object.keys(installedTools).length} tools...`);
|
|
297
336
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
337
|
+
const upgradeToolInfos = {};
|
|
338
|
+
for (const [toolName, toolInfo] of Object.entries(installedTools)) {
|
|
339
|
+
upgradeToolInfos[toolName] = {
|
|
340
|
+
...toolInfo,
|
|
341
|
+
install: `npm upgrade -g ${toolName}`,
|
|
342
|
+
name: `${toolInfo.name} (Upgrade)`
|
|
343
|
+
};
|
|
303
344
|
}
|
|
304
345
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
});
|
|
310
|
-
}
|
|
346
|
+
const upgradeResult = await enhancedInstaller.upgradeTools(
|
|
347
|
+
Object.keys(installedTools),
|
|
348
|
+
upgradeToolInfos
|
|
349
|
+
);
|
|
311
350
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
351
|
+
// 整理结果
|
|
352
|
+
const results = {
|
|
353
|
+
successful: [],
|
|
354
|
+
failed: [],
|
|
355
|
+
permissionHandled: []
|
|
356
|
+
};
|
|
317
357
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
break;
|
|
358
|
+
for (const [toolName, installation] of Object.entries(upgradeResult.results.installations || {})) {
|
|
359
|
+
if (installation.success) {
|
|
360
|
+
results.successful.push(toolName);
|
|
361
|
+
if (installation.permissionHandled) {
|
|
362
|
+
results.permissionHandled.push(toolName);
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
results.failed.push({
|
|
366
|
+
tool: toolName,
|
|
367
|
+
error: installation.error || 'Installation failed'
|
|
368
|
+
});
|
|
330
369
|
}
|
|
331
370
|
}
|
|
332
|
-
|
|
333
|
-
// 执行升级
|
|
334
|
-
console.log('\n🚀 Executing upgrade plan...\n');
|
|
335
|
-
const results = await upgrader.executeUpgrade(plan, options);
|
|
336
|
-
|
|
371
|
+
|
|
337
372
|
// 显示结果
|
|
338
373
|
console.log('\n📊 UPGRADE RESULTS');
|
|
339
374
|
console.log('='.repeat(50));
|
|
340
375
|
|
|
341
376
|
if (results.successful.length > 0) {
|
|
342
377
|
console.log(`\n✅ Successful (${results.successful.length}):`);
|
|
343
|
-
results.successful.forEach(
|
|
344
|
-
|
|
345
|
-
|
|
378
|
+
results.successful.forEach(tool => {
|
|
379
|
+
console.log(` • ${tool}`);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (results.permissionHandled.length > 0) {
|
|
384
|
+
console.log(`\n🔧 Auto-handled permissions (${results.permissionHandled.length}):`);
|
|
385
|
+
results.permissionHandled.forEach(tool => {
|
|
386
|
+
console.log(` • ${tool}`);
|
|
346
387
|
});
|
|
347
388
|
}
|
|
348
389
|
|
|
349
390
|
if (results.failed.length > 0) {
|
|
350
391
|
console.log(`\n❌ Failed (${results.failed.length}):`);
|
|
351
392
|
results.failed.forEach(result => {
|
|
352
|
-
|
|
353
|
-
console.log(` • ${name}: ${result.error}`);
|
|
393
|
+
console.log(` • ${result.tool}: ${result.error}`);
|
|
354
394
|
});
|
|
395
|
+
|
|
396
|
+
// Provide guidance for permission issues
|
|
397
|
+
if (results.failed.length > 0) {
|
|
398
|
+
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
399
|
+
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy upgrade');
|
|
400
|
+
console.log(' macOS/Linux: sudo stigmergy upgrade');
|
|
401
|
+
}
|
|
355
402
|
}
|
|
356
403
|
|
|
357
|
-
|
|
358
|
-
|
|
404
|
+
if (results.permissionHandled.length > 0) {
|
|
405
|
+
console.log('\n✅ 权限问题已自动处理');
|
|
406
|
+
console.log(`🔧 自动提升权限升级了 ${results.permissionHandled.length} 个工具`);
|
|
407
|
+
}
|
|
359
408
|
|
|
360
409
|
console.log('\n🎉 Upgrade process completed!');
|
|
361
|
-
|
|
410
|
+
|
|
362
411
|
} catch (error) {
|
|
363
412
|
console.error('[ERROR] Upgrade failed:', error.message);
|
|
364
|
-
if (
|
|
413
|
+
if (process.env.DEBUG === 'true') {
|
|
365
414
|
console.error(error.stack);
|
|
366
415
|
}
|
|
367
416
|
process.exit(1);
|
|
@@ -369,30 +418,101 @@ async function main() {
|
|
|
369
418
|
break;
|
|
370
419
|
}
|
|
371
420
|
|
|
372
|
-
|
|
421
|
+
case 'install':
|
|
373
422
|
case 'inst':
|
|
374
423
|
try {
|
|
375
424
|
console.log('[INSTALL] Starting AI CLI tools installation...');
|
|
376
|
-
const { missing: missingTools } = await installer.scanCLI();
|
|
377
|
-
const options = await installer.showInstallOptions(missingTools);
|
|
378
425
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
426
|
+
// Check directory permissions first
|
|
427
|
+
const permissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
428
|
+
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
429
|
+
|
|
430
|
+
if (!hasWritePermission) {
|
|
431
|
+
console.log('\n⚠️ Current directory lacks write permission');
|
|
432
|
+
console.log('🔧 Using permission-aware installation...');
|
|
433
|
+
|
|
434
|
+
// Use permission-aware installer
|
|
435
|
+
const permAwareInstaller = new PermissionAwareInstaller({
|
|
436
|
+
verbose: process.env.DEBUG === 'true',
|
|
437
|
+
skipPermissionCheck: false
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const result = await permAwareInstaller.install();
|
|
441
|
+
if (result.success) {
|
|
442
|
+
console.log('\n✅ Permission-aware installation completed successfully!');
|
|
443
|
+
} else {
|
|
444
|
+
console.log('\n❌ Permission-aware installation failed');
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Normal installation if directory has write permission
|
|
451
|
+
const { missing: missingTools, available: availableTools } = await installer.scanCLI();
|
|
452
|
+
|
|
453
|
+
if (Object.keys(missingTools).length === 0) {
|
|
454
|
+
console.log('[INFO] All AI CLI tools are already installed!');
|
|
455
|
+
console.log('\nAvailable tools:');
|
|
456
|
+
for (const [toolName, toolInfo] of Object.entries(availableTools)) {
|
|
457
|
+
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
389
458
|
}
|
|
390
459
|
} else {
|
|
391
|
-
console.log(
|
|
460
|
+
console.log(`\n[INFO] Found ${Object.keys(missingTools).length} missing AI CLI tools:`);
|
|
461
|
+
for (const [toolName, toolInfo] of Object.entries(missingTools)) {
|
|
462
|
+
console.log(` - ${toolInfo.name}: ${toolInfo.install}`);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// 默认自动安装所有缺失的工具
|
|
466
|
+
console.log(`\n[AUTO-INSTALL] Installing ${Object.keys(missingTools).length} missing AI CLI tools...`);
|
|
467
|
+
|
|
468
|
+
const selectedTools = Object.keys(missingTools);
|
|
469
|
+
|
|
470
|
+
// Use EnhancedCLIInstaller with batch permission handling
|
|
471
|
+
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
472
|
+
const installer = new EnhancedCLIInstaller({
|
|
473
|
+
verbose: process.env.DEBUG === 'true',
|
|
474
|
+
autoRetry: true,
|
|
475
|
+
maxRetries: 2
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
console.log(`[INFO] Installing ${selectedTools.length} CLI tools with optimized permission handling...`);
|
|
479
|
+
const installResult = await installer.installTools(selectedTools, missingTools);
|
|
480
|
+
|
|
481
|
+
if (installResult) {
|
|
482
|
+
console.log(`\n[SUCCESS] Installed ${selectedTools.length} AI CLI tools!`);
|
|
483
|
+
|
|
484
|
+
// Check if any permissions were handled automatically
|
|
485
|
+
const installations = installer.results.installations || {};
|
|
486
|
+
const permissionHandledTools = Object.entries(installations)
|
|
487
|
+
.filter(([name, result]) => result.success && result.permissionHandled)
|
|
488
|
+
.map(([name]) => name);
|
|
489
|
+
|
|
490
|
+
if (permissionHandledTools.length > 0) {
|
|
491
|
+
console.log('✅ 权限问题已自动处理');
|
|
492
|
+
console.log(`🔧 自动提升权限安装了 ${permissionHandledTools.length} 个工具: ${permissionHandledTools.join(', ')}`);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Show permission mode used
|
|
496
|
+
console.log(`🔧 权限模式: ${installResult.permissionMode}`);
|
|
497
|
+
} else {
|
|
498
|
+
console.log('\n[WARN] Some tools may not have installed successfully. Check the logs above for details.');
|
|
499
|
+
|
|
500
|
+
// Provide manual guidance for permission issues
|
|
501
|
+
const failedInstallations = installer.results.failedInstallations || [];
|
|
502
|
+
if (failedInstallations.length > 0) {
|
|
503
|
+
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
504
|
+
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
505
|
+
console.log(' macOS/Linux: sudo stigmergy install');
|
|
506
|
+
}
|
|
507
|
+
}
|
|
392
508
|
}
|
|
509
|
+
|
|
510
|
+
console.log('\n[INFO] Installation process completed.');
|
|
393
511
|
} catch (error) {
|
|
394
|
-
|
|
395
|
-
|
|
512
|
+
console.error('[ERROR] Installation failed:', error.message);
|
|
513
|
+
if (process.env.DEBUG === 'true') {
|
|
514
|
+
console.error(error.stack);
|
|
515
|
+
}
|
|
396
516
|
process.exit(1);
|
|
397
517
|
}
|
|
398
518
|
break;
|
|
@@ -432,7 +552,7 @@ async function main() {
|
|
|
432
552
|
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
433
553
|
const whichResult = spawnSync(whichCmd, [route.tool], {
|
|
434
554
|
encoding: 'utf8',
|
|
435
|
-
timeout:
|
|
555
|
+
timeout: 10000,
|
|
436
556
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
437
557
|
shell: true,
|
|
438
558
|
});
|
|
@@ -551,8 +671,16 @@ async function main() {
|
|
|
551
671
|
|
|
552
672
|
// Special handling for Claude on Windows to bypass the wrapper script
|
|
553
673
|
if (process.platform === 'win32' && route.tool === 'claude') {
|
|
554
|
-
// Use
|
|
555
|
-
|
|
674
|
+
// Use detected path to avoid the wrapper script that interferes with parameter passing
|
|
675
|
+
const detectedPath = await getCLIPath('claude');
|
|
676
|
+
if (detectedPath) {
|
|
677
|
+
execCommand = detectedPath;
|
|
678
|
+
console.log(`[DEBUG] Using detected Claude path: ${execCommand}`);
|
|
679
|
+
} else {
|
|
680
|
+
execCommand = 'C:\\npm_global\\claude';
|
|
681
|
+
console.log(`[DEBUG] Using default Claude path: ${execCommand}`);
|
|
682
|
+
}
|
|
683
|
+
|
|
556
684
|
if (toolArgs.length > 0) {
|
|
557
685
|
const argsString = toolArgs.map(arg => {
|
|
558
686
|
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
@@ -566,11 +694,41 @@ async function main() {
|
|
|
566
694
|
}
|
|
567
695
|
}
|
|
568
696
|
|
|
569
|
-
//
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
697
|
+
// Use detected paths for all CLI tools on all platforms
|
|
698
|
+
const supportedTools = ['claude', 'copilot', 'qodercli', 'gemini', 'qwen', 'iflow', 'codebuddy', 'codex'];
|
|
699
|
+
|
|
700
|
+
if (supportedTools.includes(route.tool)) {
|
|
701
|
+
// Use detected path for all CLI tools regardless of platform
|
|
702
|
+
const detectedPath = await getCLIPath(route.tool);
|
|
703
|
+
if (detectedPath) {
|
|
704
|
+
execCommand = detectedPath;
|
|
705
|
+
console.log(`[DEBUG] Using detected ${route.tool} path: ${execCommand}`);
|
|
706
|
+
} else {
|
|
707
|
+
// Fallback to system PATH for tools not detected
|
|
708
|
+
console.log(`[DEBUG] Using system PATH for ${route.tool}: ${route.tool}`);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Platform-specific command construction
|
|
713
|
+
if (process.platform === 'win32') {
|
|
714
|
+
// Special handling for Windows CLI tools
|
|
715
|
+
if (route.tool === 'claude' && toolArgs.length > 0) {
|
|
716
|
+
// Special parameter handling for Claude to avoid wrapper script issues
|
|
717
|
+
const argsString = toolArgs.map(arg => {
|
|
718
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
719
|
+
return `"${arg}"`;
|
|
720
|
+
}
|
|
721
|
+
return arg;
|
|
722
|
+
}).join(' ');
|
|
723
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
724
|
+
execArgs = [];
|
|
725
|
+
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
726
|
+
} else if (route.tool === 'copilot') {
|
|
727
|
+
// Copilot doesn't use -p parameter format
|
|
728
|
+
execArgs = [];
|
|
729
|
+
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
730
|
+
} else if (toolArgs.length > 0) {
|
|
731
|
+
// For other Windows tools, construct full command line
|
|
574
732
|
const argsString = toolArgs.map(arg => {
|
|
575
733
|
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
576
734
|
return `"${arg}"`;
|
|
@@ -579,7 +737,7 @@ async function main() {
|
|
|
579
737
|
}).join(' ');
|
|
580
738
|
execCommand = `${execCommand} ${argsString}`;
|
|
581
739
|
execArgs = [];
|
|
582
|
-
console.log(`[DEBUG] Windows
|
|
740
|
+
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
583
741
|
}
|
|
584
742
|
}
|
|
585
743
|
|
|
@@ -678,11 +836,41 @@ async function main() {
|
|
|
678
836
|
}
|
|
679
837
|
|
|
680
838
|
case 'auto-install':
|
|
681
|
-
// Auto-install mode for npm postinstall - NON-INTERACTIVE
|
|
839
|
+
// Auto-install mode for npm postinstall - NON-INTERACTIVE with permission awareness
|
|
682
840
|
// Force immediate output visibility during npm install
|
|
841
|
+
|
|
842
|
+
// Detect npm environment for better output visibility
|
|
843
|
+
const isNpmPostinstall = process.env.npm_lifecycle_event === 'postinstall';
|
|
844
|
+
|
|
845
|
+
// Use stderr for critical messages in npm environment (more likely to be shown)
|
|
846
|
+
const criticalLog = isNpmPostinstall ? console.error : console.log;
|
|
847
|
+
|
|
848
|
+
criticalLog('🚀 STIGMERGY CLI AUTO-INSTALL STARTING');
|
|
849
|
+
criticalLog('='.repeat(60));
|
|
850
|
+
criticalLog('Installing cross-CLI integration and scanning for AI tools...');
|
|
851
|
+
criticalLog('='.repeat(60));
|
|
683
852
|
console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
|
|
684
853
|
console.log('='.repeat(60));
|
|
685
854
|
|
|
855
|
+
// Check directory permissions
|
|
856
|
+
const autoPermissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
857
|
+
const autoHasWritePermission = await autoPermissionManager.checkWritePermission();
|
|
858
|
+
|
|
859
|
+
if (!autoHasWritePermission && !process.env.STIGMERGY_SKIP_PERMISSION_CHECK) {
|
|
860
|
+
criticalLog('⚠️ Directory permission detected, setting up permission-aware installation...');
|
|
861
|
+
|
|
862
|
+
try {
|
|
863
|
+
const permResult = await autoPermissionManager.setupWorkingDirectory();
|
|
864
|
+
if (permResult.success) {
|
|
865
|
+
criticalLog('✅ Working directory configured with proper permissions');
|
|
866
|
+
} else {
|
|
867
|
+
criticalLog('⚠️ Could not configure working directory, continuing with limited functionality');
|
|
868
|
+
}
|
|
869
|
+
} catch (error) {
|
|
870
|
+
criticalLog(`⚠️ Permission setup failed: ${error.message}`);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
686
874
|
// Force stdout flush to ensure visibility during npm install
|
|
687
875
|
if (process.stdout && process.stdout.write) {
|
|
688
876
|
process.stdout.write('');
|
|
@@ -757,7 +945,77 @@ async function main() {
|
|
|
757
945
|
console.log(` ✗ ${toolInfo.name} (${toolName})`);
|
|
758
946
|
console.log(` Install with: ${toolInfo.installCommand}`);
|
|
759
947
|
}
|
|
760
|
-
|
|
948
|
+
|
|
949
|
+
// Check if auto-install is enabled for npm postinstall
|
|
950
|
+
const autoInstallEnabled = process.env.STIGMERGY_AUTO_INSTALL !== 'false';
|
|
951
|
+
|
|
952
|
+
if (autoInstallEnabled && !process.env.CI) {
|
|
953
|
+
console.log('\n[AUTO-INSTALL] Installing missing CLI tools automatically...');
|
|
954
|
+
console.log('[INFO] Set STIGMERGY_AUTO_INSTALL=false to disable this behavior');
|
|
955
|
+
|
|
956
|
+
try {
|
|
957
|
+
const selectedTools = Object.keys(autoMissing);
|
|
958
|
+
|
|
959
|
+
// Use EnhancedCLIInstaller with batch permission handling
|
|
960
|
+
const EnhancedCLIInstaller = require(path.resolve(__dirname, '../core/enhanced_cli_installer'));
|
|
961
|
+
const installer = new EnhancedCLIInstaller({
|
|
962
|
+
verbose: process.env.DEBUG === 'true',
|
|
963
|
+
autoRetry: true,
|
|
964
|
+
maxRetries: 2
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
console.log(`[INFO] Installing ${selectedTools.length} CLI tools with optimized permission handling...`);
|
|
968
|
+
const installResult = await installer.installTools(selectedTools, autoMissing);
|
|
969
|
+
|
|
970
|
+
if (installResult) {
|
|
971
|
+
console.log(`[SUCCESS] Auto-installed ${selectedTools.length} CLI tools!`);
|
|
972
|
+
|
|
973
|
+
// Check if permissions were handled automatically
|
|
974
|
+
const installations = installer.results.installations || {};
|
|
975
|
+
const permissionHandledTools = Object.entries(installations)
|
|
976
|
+
.filter(([name, result]) => result.success && result.permissionHandled)
|
|
977
|
+
.map(([name]) => name);
|
|
978
|
+
|
|
979
|
+
if (permissionHandledTools.length > 0) {
|
|
980
|
+
console.log('✅ 权限问题已自动处理');
|
|
981
|
+
console.log(`🔧 自动提升权限安装了 ${permissionHandledTools.length} 个工具: ${permissionHandledTools.join(', ')}`);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// Show permission mode used
|
|
985
|
+
console.log(`🔧 权限模式: ${installResult.permissionMode}`);
|
|
986
|
+
} else {
|
|
987
|
+
console.log('[WARN] Some tools may not have installed successfully');
|
|
988
|
+
|
|
989
|
+
// Provide manual guidance for permission issues
|
|
990
|
+
const failedInstallations = installer.results.failedInstallations || [];
|
|
991
|
+
if (failedInstallations.length > 0) {
|
|
992
|
+
console.log('\n💡 如果遇到权限问题,请尝试:');
|
|
993
|
+
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
994
|
+
console.log(' macOS/Linux: sudo stigmergy install');
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
} catch (installError) {
|
|
998
|
+
console.log(`[ERROR] Auto-install failed: ${installError.message}`);
|
|
999
|
+
console.log('[INFO] You can manually install tools with: stigmergy install --auto');
|
|
1000
|
+
|
|
1001
|
+
// Check if it's a permission error
|
|
1002
|
+
const permissionIndicators = ['EACCES', 'EPERM', 'permission denied', 'access denied'];
|
|
1003
|
+
const isPermissionError = permissionIndicators.some(indicator =>
|
|
1004
|
+
installError.message.toLowerCase().includes(indicator.toLowerCase())
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
if (isPermissionError) {
|
|
1008
|
+
console.log('\n💡 这看起来像是权限问题,请尝试:');
|
|
1009
|
+
console.log(' Windows: 以管理员身份运行PowerShell,然后执行 stigmergy install');
|
|
1010
|
+
console.log(' macOS/Linux: sudo stigmergy install');
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
} else {
|
|
1014
|
+
console.log('\n[INFO] You can install missing tools with: stigmergy install --auto');
|
|
1015
|
+
if (process.env.CI) {
|
|
1016
|
+
console.log('[CI] Auto-install disabled in CI environment');
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
761
1019
|
}
|
|
762
1020
|
|
|
763
1021
|
console.log('\n[USAGE] Get started with these commands:');
|
|
@@ -864,6 +1122,75 @@ async function main() {
|
|
|
864
1122
|
}
|
|
865
1123
|
break;
|
|
866
1124
|
|
|
1125
|
+
// Skill命令简化别名
|
|
1126
|
+
case 'skill-i': // install
|
|
1127
|
+
case 'skill-l': // list
|
|
1128
|
+
case 'skill-v': // validate/read
|
|
1129
|
+
case 'skill-r': // read
|
|
1130
|
+
case 'skill-d': // remove/delete
|
|
1131
|
+
case 'skill-m': // remove (移除)
|
|
1132
|
+
case 'skill': {
|
|
1133
|
+
try {
|
|
1134
|
+
// Skill命令通过桥接器调用ES模块
|
|
1135
|
+
const { handleSkillCommand } = require('../commands/skill-handler');
|
|
1136
|
+
|
|
1137
|
+
// 处理简化命令
|
|
1138
|
+
let skillAction;
|
|
1139
|
+
let skillArgs;
|
|
1140
|
+
|
|
1141
|
+
switch (command) {
|
|
1142
|
+
case 'skill-i':
|
|
1143
|
+
skillAction = 'install';
|
|
1144
|
+
skillArgs = args.slice(1);
|
|
1145
|
+
break;
|
|
1146
|
+
case 'skill-l':
|
|
1147
|
+
skillAction = 'list';
|
|
1148
|
+
skillArgs = args.slice(1);
|
|
1149
|
+
break;
|
|
1150
|
+
case 'skill-v':
|
|
1151
|
+
// skill-v可以是validate或read,根据参数判断
|
|
1152
|
+
skillAction = args[1] && (args[1].endsWith('.md') || args[1].includes('/') || args[1].includes('\\'))
|
|
1153
|
+
? 'validate'
|
|
1154
|
+
: 'read';
|
|
1155
|
+
skillArgs = args.slice(1);
|
|
1156
|
+
break;
|
|
1157
|
+
case 'skill-r':
|
|
1158
|
+
skillAction = 'read';
|
|
1159
|
+
skillArgs = args.slice(1);
|
|
1160
|
+
break;
|
|
1161
|
+
case 'skill-d':
|
|
1162
|
+
case 'skill-m':
|
|
1163
|
+
skillAction = 'remove';
|
|
1164
|
+
skillArgs = args.slice(1);
|
|
1165
|
+
break;
|
|
1166
|
+
default:
|
|
1167
|
+
// 标准skill命令
|
|
1168
|
+
skillAction = args[1];
|
|
1169
|
+
skillArgs = args.slice(2);
|
|
1170
|
+
|
|
1171
|
+
// 如果没有子命令,默认执行sync
|
|
1172
|
+
if (!skillAction) {
|
|
1173
|
+
skillAction = 'sync';
|
|
1174
|
+
skillArgs = [];
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const skillOptions = {
|
|
1179
|
+
force: args.includes('--force'),
|
|
1180
|
+
verbose: args.includes('--verbose'),
|
|
1181
|
+
autoSync: !args.includes('--no-auto-sync')
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
const exitCode = await handleSkillCommand(skillAction, skillArgs, skillOptions);
|
|
1185
|
+
process.exit(exitCode || 0);
|
|
1186
|
+
} catch (error) {
|
|
1187
|
+
await errorHandler.logError(error, 'ERROR', 'main.skill');
|
|
1188
|
+
console.error(`[ERROR] Skill command failed: ${error.message}`);
|
|
1189
|
+
process.exit(1);
|
|
1190
|
+
}
|
|
1191
|
+
break;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
867
1194
|
case 'clean':
|
|
868
1195
|
case 'c': {
|
|
869
1196
|
try {
|
|
@@ -982,6 +1309,71 @@ async function main() {
|
|
|
982
1309
|
break;
|
|
983
1310
|
}
|
|
984
1311
|
|
|
1312
|
+
case 'fix-perms': {
|
|
1313
|
+
try {
|
|
1314
|
+
console.log('[FIX-PERMS] Setting up working directory with proper permissions...\n');
|
|
1315
|
+
|
|
1316
|
+
const permAwareInstaller = new PermissionAwareInstaller({
|
|
1317
|
+
verbose: process.env.DEBUG === 'true',
|
|
1318
|
+
skipPermissionCheck: false,
|
|
1319
|
+
autoConfigureShell: true
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
const result = await permAwareInstaller.install();
|
|
1323
|
+
|
|
1324
|
+
if (result.success) {
|
|
1325
|
+
console.log('\n✅ Permission setup completed successfully!');
|
|
1326
|
+
permAwareInstaller.permissionManager.displayResults(result.permissionSetup);
|
|
1327
|
+
} else {
|
|
1328
|
+
console.log('\n❌ Permission setup failed');
|
|
1329
|
+
console.log(`Error: ${result.error || 'Unknown error'}`);
|
|
1330
|
+
process.exit(1);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
} catch (error) {
|
|
1334
|
+
console.error('[ERROR] Permission setup failed:', error.message);
|
|
1335
|
+
if (process.env.DEBUG === 'true') {
|
|
1336
|
+
console.error(error.stack);
|
|
1337
|
+
}
|
|
1338
|
+
process.exit(1);
|
|
1339
|
+
}
|
|
1340
|
+
break;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
case 'perm-check': {
|
|
1344
|
+
try {
|
|
1345
|
+
console.log('[PERM-CHECK] Checking current directory permissions...\n');
|
|
1346
|
+
|
|
1347
|
+
const permissionManager = new DirectoryPermissionManager({ verbose: process.env.DEBUG === 'true' });
|
|
1348
|
+
const hasWritePermission = await permissionManager.checkWritePermission();
|
|
1349
|
+
|
|
1350
|
+
console.log(`📍 Current directory: ${process.cwd()}`);
|
|
1351
|
+
console.log(`🔧 Write permission: ${hasWritePermission ? '✅ Yes' : '❌ No'}`);
|
|
1352
|
+
|
|
1353
|
+
if (!hasWritePermission) {
|
|
1354
|
+
console.log('\n💡 Suggestions:');
|
|
1355
|
+
console.log('1. Run: stigmergy fix-perms # Fix permissions automatically');
|
|
1356
|
+
console.log('2. Change to user directory: cd ~');
|
|
1357
|
+
console.log('3. Create project directory: mkdir ~/stigmergy && cd ~/stigmergy');
|
|
1358
|
+
console.log('\n🔍 System Info:');
|
|
1359
|
+
const sysInfo = permissionManager.getSystemInfo();
|
|
1360
|
+
console.log(` Platform: ${sysInfo.platform}`);
|
|
1361
|
+
console.log(` Shell: ${sysInfo.shell}`);
|
|
1362
|
+
console.log(` Home: ${sysInfo.homeDir}`);
|
|
1363
|
+
} else {
|
|
1364
|
+
console.log('\n✅ Current directory is ready for installation');
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
} catch (error) {
|
|
1368
|
+
console.error('[ERROR] Permission check failed:', error.message);
|
|
1369
|
+
if (process.env.DEBUG === 'true') {
|
|
1370
|
+
console.error(error.stack);
|
|
1371
|
+
}
|
|
1372
|
+
process.exit(1);
|
|
1373
|
+
}
|
|
1374
|
+
break;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
985
1377
|
default:
|
|
986
1378
|
// Check if the command matches a direct CLI tool name
|
|
987
1379
|
if (CLI_TOOLS[command]) {
|
|
@@ -1016,7 +1408,7 @@ async function main() {
|
|
|
1016
1408
|
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
1017
1409
|
const whichResult = spawnSync(whichCmd, [toolName], {
|
|
1018
1410
|
encoding: 'utf8',
|
|
1019
|
-
timeout:
|
|
1411
|
+
timeout: 10000,
|
|
1020
1412
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1021
1413
|
shell: true,
|
|
1022
1414
|
});
|
|
@@ -1136,11 +1528,26 @@ async function main() {
|
|
|
1136
1528
|
}
|
|
1137
1529
|
}
|
|
1138
1530
|
|
|
1139
|
-
//
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1531
|
+
// Use detected paths for all CLI tools on all platforms
|
|
1532
|
+
const supportedTools = ['claude', 'copilot', 'qodercli', 'gemini', 'qwen', 'iflow', 'codebuddy', 'codex'];
|
|
1533
|
+
|
|
1534
|
+
if (supportedTools.includes(route.tool)) {
|
|
1535
|
+
// Use detected path for all CLI tools regardless of platform
|
|
1536
|
+
const detectedPath = await getCLIPath(route.tool);
|
|
1537
|
+
if (detectedPath) {
|
|
1538
|
+
execCommand = detectedPath;
|
|
1539
|
+
console.log(`[DEBUG] Using detected ${route.tool} path: ${execCommand}`);
|
|
1540
|
+
} else {
|
|
1541
|
+
// Fallback to system PATH for tools not detected
|
|
1542
|
+
console.log(`[DEBUG] Using system PATH for ${route.tool}: ${route.tool}`);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
// Platform-specific command construction
|
|
1547
|
+
if (process.platform === 'win32') {
|
|
1548
|
+
// Special handling for Windows CLI tools
|
|
1549
|
+
if (route.tool === 'claude' && toolArgs.length > 0) {
|
|
1550
|
+
// Special parameter handling for Claude to avoid wrapper script issues
|
|
1144
1551
|
const argsString = toolArgs.map(arg => {
|
|
1145
1552
|
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1146
1553
|
return `"${arg}"`;
|
|
@@ -1149,15 +1556,13 @@ async function main() {
|
|
|
1149
1556
|
}).join(' ');
|
|
1150
1557
|
execCommand = `${execCommand} ${argsString}`;
|
|
1151
1558
|
execArgs = [];
|
|
1152
|
-
console.log(`[DEBUG] Windows direct
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
execCommand = 'C:\\npm_global\\copilot';
|
|
1160
|
-
if (toolArgs.length > 0) {
|
|
1559
|
+
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
1560
|
+
} else if (route.tool === 'copilot') {
|
|
1561
|
+
// Copilot doesn't use -p parameter format
|
|
1562
|
+
execArgs = [];
|
|
1563
|
+
console.log(`[DEBUG] Windows ${route.tool} direct command: ${execCommand}`);
|
|
1564
|
+
} else if (toolArgs.length > 0) {
|
|
1565
|
+
// For other Windows tools, construct full command line
|
|
1161
1566
|
const argsString = toolArgs.map(arg => {
|
|
1162
1567
|
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1163
1568
|
return `"${arg}"`;
|
|
@@ -1166,10 +1571,11 @@ async function main() {
|
|
|
1166
1571
|
}).join(' ');
|
|
1167
1572
|
execCommand = `${execCommand} ${argsString}`;
|
|
1168
1573
|
execArgs = [];
|
|
1169
|
-
console.log(`[DEBUG] Windows
|
|
1574
|
+
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
1170
1575
|
}
|
|
1171
1576
|
}
|
|
1172
1577
|
|
|
1578
|
+
|
|
1173
1579
|
// Apply the same Windows handling logic to ensure consistency
|
|
1174
1580
|
// This ensures consistency between direct routing and call command routing
|
|
1175
1581
|
if (process.platform === 'win32' && execArgs.length > 0) {
|