stigmergy 1.2.6 ā 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 +69 -20
- package/STIGMERGY.md +26 -7
- package/docs/MULTI_USER_WIKI_COLLABORATION_SYSTEM.md +523 -0
- package/docs/PROMPT_BASED_SKILLS_SYSTEM_DESIGN.md +458 -0
- package/docs/SKILL_IMPLEMENTATION_CONSTRAINTS_AND_ALIGNMENT.md +423 -0
- package/docs/TECHNICAL_FEASIBILITY_ANALYSIS.md +308 -0
- package/examples/multilingual-hook-demo.js +125 -0
- package/package.json +30 -19
- package/scripts/dependency-analyzer.js +101 -0
- package/scripts/generate-cli-docs.js +64 -0
- package/scripts/postuninstall.js +46 -0
- package/scripts/preuninstall.js +85 -0
- package/scripts/run-layered-tests.js +3 -3
- package/src/adapters/claude/install_claude_integration.js +37 -37
- package/src/adapters/codebuddy/install_codebuddy_integration.js +66 -63
- package/src/adapters/codex/install_codex_integration.js +54 -55
- package/src/adapters/copilot/install_copilot_integration.js +46 -46
- package/src/adapters/gemini/install_gemini_integration.js +68 -68
- package/src/adapters/iflow/install_iflow_integration.js +77 -77
- package/src/adapters/qoder/install_qoder_integration.js +76 -76
- package/src/adapters/qwen/install_qwen_integration.js +23 -23
- package/src/cli/router.js +713 -163
- 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/cache_cleaner.js +767 -767
- package/src/core/cli_help_analyzer.js +680 -680
- package/src/core/cli_parameter_handler.js +132 -132
- package/src/core/cli_path_detector.js +573 -0
- package/src/core/cli_tools.js +160 -89
- package/src/core/coordination/index.js +16 -16
- package/src/core/coordination/nodejs/AdapterManager.js +130 -102
- package/src/core/coordination/nodejs/CLCommunication.js +132 -132
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +272 -272
- package/src/core/coordination/nodejs/HealthChecker.js +76 -76
- package/src/core/coordination/nodejs/HookDeploymentManager.js +463 -274
- package/src/core/coordination/nodejs/StatisticsCollector.js +71 -71
- package/src/core/coordination/nodejs/index.js +90 -90
- package/src/core/coordination/nodejs/utils/Logger.js +29 -29
- package/src/core/directory_permission_manager.js +568 -0
- package/src/core/enhanced_cli_installer.js +609 -0
- package/src/core/error_handler.js +406 -406
- package/src/core/installer.js +263 -119
- package/src/core/memory_manager.js +83 -83
- package/src/core/multilingual/language-pattern-manager.js +200 -0
- package/src/core/persistent_shell_configurator.js +468 -0
- package/src/core/rest_client.js +160 -160
- 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/core/smart_router.js +261 -249
- package/src/core/upgrade_manager.js +48 -20
- package/src/index.js +30 -30
- package/src/test/cli-availability-checker.js +194 -194
- package/src/test/test-environment.js +289 -289
- package/src/utils/helpers.js +18 -35
- package/src/utils.js +921 -921
- package/src/weatherProcessor.js +228 -228
- package/test/multilingual/hook-deployment.test.js +91 -0
- package/test/multilingual/language-pattern-manager.test.js +140 -0
- package/test/multilingual/system-test.js +85 -0
- 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
|
@@ -16,6 +16,11 @@ const chalk = require('chalk');
|
|
|
16
16
|
const yaml = require('js-yaml');
|
|
17
17
|
const fs = require('fs/promises');
|
|
18
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');
|
|
19
24
|
|
|
20
25
|
// Import our custom modules
|
|
21
26
|
const SmartRouter = require('../core/smart_router');
|
|
@@ -23,7 +28,6 @@ const CLIHelpAnalyzer = require('../core/cli_help_analyzer');
|
|
|
23
28
|
const { CLI_TOOLS } = require('../core/cli_tools');
|
|
24
29
|
const { errorHandler } = require('../core/error_handler');
|
|
25
30
|
const { executeCommand, executeJSFile } = require('../utils');
|
|
26
|
-
const { UserAuthenticator } = require('../auth');
|
|
27
31
|
const MemoryManager = require('../core/memory_manager');
|
|
28
32
|
const StigmergyInstaller = require('../core/installer');
|
|
29
33
|
const UpgradeManager = require('../core/upgrade_manager');
|
|
@@ -71,17 +75,26 @@ async function main() {
|
|
|
71
75
|
console.log(' version, --version Show version information');
|
|
72
76
|
console.log(' status Check CLI tools status');
|
|
73
77
|
console.log(' scan Scan for available AI CLI tools');
|
|
74
|
-
console.log(' install Auto-install missing CLI tools');
|
|
78
|
+
console.log(' install Auto-install missing CLI tools (with permission fix)');
|
|
75
79
|
console.log(' upgrade Upgrade all CLI tools to latest versions');
|
|
76
80
|
console.log(
|
|
77
81
|
' deploy Deploy hooks and integration to installed tools',
|
|
78
82
|
);
|
|
79
83
|
console.log(' setup Complete setup and configuration');
|
|
80
84
|
console.log(
|
|
81
|
-
' init Initialize Stigmergy
|
|
85
|
+
' init Initialize Stigmergy project in current directory',
|
|
82
86
|
);
|
|
83
87
|
console.log(' clean (c) Clean temporary files and caches');
|
|
84
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)');
|
|
85
98
|
console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
|
|
86
99
|
console.log(' <tool> "<prompt>" Directly route to specific AI CLI tool');
|
|
87
100
|
console.log(' Supported tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex');
|
|
@@ -125,52 +138,106 @@ async function main() {
|
|
|
125
138
|
break;
|
|
126
139
|
|
|
127
140
|
case 'init':
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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;
|
|
131
169
|
|
|
132
170
|
case 'setup':
|
|
133
171
|
try {
|
|
134
172
|
console.log('[SETUP] Starting complete Stigmergy setup...\n');
|
|
135
173
|
|
|
136
|
-
// Step
|
|
137
|
-
|
|
174
|
+
// Step 0: Setup CLI paths detection and configuration
|
|
175
|
+
console.log('[STEP 0] Setting up CLI path detection...');
|
|
176
|
+
const pathSetup = await setupCLIPaths();
|
|
138
177
|
|
|
139
|
-
|
|
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...');
|
|
140
199
|
const { available: setupAvailable, missing: setupMissing } =
|
|
141
200
|
await installer.scanCLI();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
);
|
|
150
|
-
if (selectedTools.length > 0) {
|
|
151
|
-
console.log(
|
|
152
|
-
'\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...',
|
|
153
|
-
);
|
|
154
|
-
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}`);
|
|
155
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}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log('\n[INFO] Or use the enhanced installer:');
|
|
216
|
+
console.log(' node src/core/enhanced_installer.js');
|
|
156
217
|
} else {
|
|
157
|
-
console.log('\n[
|
|
218
|
+
console.log('\n[STEP 2] All required tools are already installed!');
|
|
158
219
|
}
|
|
159
220
|
|
|
160
|
-
// Step
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
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
|
+
}
|
|
168
228
|
|
|
169
|
-
|
|
170
|
-
|
|
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
|
+
|
|
171
236
|
} catch (error) {
|
|
172
|
-
|
|
173
|
-
|
|
237
|
+
console.error('[ERROR] Setup failed:', error.message);
|
|
238
|
+
if (process.env.DEBUG === 'true') {
|
|
239
|
+
console.error(error.stack);
|
|
240
|
+
}
|
|
174
241
|
console.log('\n[TROUBLESHOOTING] To manually complete setup:');
|
|
175
242
|
console.log('1. Run: stigmergy deploy # Deploy hooks manually');
|
|
176
243
|
console.log('2. Run: stigmergy setup # Try setup again');
|
|
@@ -221,146 +288,129 @@ async function main() {
|
|
|
221
288
|
|
|
222
289
|
case 'upgrade': {
|
|
223
290
|
try {
|
|
224
|
-
console.log('[UPGRADE] Starting CLI tools upgrade process
|
|
225
|
-
|
|
226
|
-
await upgrader.initialize();
|
|
227
|
-
|
|
291
|
+
console.log('[UPGRADE] Starting AI CLI tools upgrade process...\n');
|
|
292
|
+
|
|
228
293
|
// č§£ęå½ä»¤č”é锹
|
|
229
294
|
const upgradeArgs = args.slice(1);
|
|
230
295
|
const options = {
|
|
231
296
|
dryRun: upgradeArgs.includes('--dry-run'),
|
|
232
297
|
force: upgradeArgs.includes('--force'),
|
|
233
|
-
verbose: upgradeArgs.includes('--verbose')
|
|
234
|
-
diagnose: upgradeArgs.includes('--diagnose'),
|
|
235
|
-
suggest: upgradeArgs.includes('--suggest')
|
|
298
|
+
verbose: upgradeArgs.includes('--verbose')
|
|
236
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
|
+
});
|
|
237
308
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const deprecations = await upgrader.checkDeprecations();
|
|
309
|
+
// č·åå·²å®č£
ēå·„å
·å蔨 - 使ēØå
Øå±installerę«ę
|
|
310
|
+
const { available: installedTools } = await installer.scanCLI();
|
|
241
311
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
} else {
|
|
245
|
-
console.log('ā Issues found:');
|
|
246
|
-
deprecations.forEach((dep, index) => {
|
|
247
|
-
console.log(`\n${index + 1}. ${dep.type || 'Unknown'}`);
|
|
248
|
-
if (dep.dependency) console.log(` Dependency: ${dep.dependency}`);
|
|
249
|
-
console.log(` Issues: ${dep.issues.join(', ')}`);
|
|
250
|
-
});
|
|
251
|
-
}
|
|
312
|
+
if (Object.keys(installedTools).length === 0) {
|
|
313
|
+
console.log('[INFO] No AI CLI tools found. Please install tools first with: stigmergy install');
|
|
252
314
|
break;
|
|
253
315
|
}
|
|
254
316
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
console.log('š Recommendations:');
|
|
260
|
-
if (plan.upgrades.length > 0) {
|
|
261
|
-
console.log('\nšŗ Available Upgrades:');
|
|
262
|
-
plan.upgrades.forEach(upgrade => {
|
|
263
|
-
console.log(` ⢠${upgrade.tool}: ${upgrade.from} ā ${upgrade.to}`);
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (plan.fixes.length > 0) {
|
|
268
|
-
console.log('\nš§ Recommended Fixes:');
|
|
269
|
-
plan.fixes.forEach(fix => {
|
|
270
|
-
console.log(` ⢠${fix.type}: ${fix.description}`);
|
|
271
|
-
});
|
|
272
|
-
}
|
|
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
|
+
}
|
|
273
321
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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');
|
|
277
325
|
break;
|
|
278
326
|
}
|
|
279
327
|
|
|
280
|
-
//
|
|
281
|
-
console.log(
|
|
282
|
-
|
|
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');
|
|
283
331
|
|
|
284
|
-
|
|
285
|
-
console.log('š UPGRADE PLAN');
|
|
286
|
-
console.log('='.repeat(50));
|
|
332
|
+
console.log('\nš Upgrading AI CLI tools with automatic permission handling...\n');
|
|
287
333
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
plan.upgrades.forEach(upgrade => {
|
|
291
|
-
console.log(` ⢠${upgrade.tool.padEnd(12)} ${upgrade.from} ā ${upgrade.to}`);
|
|
292
|
-
});
|
|
293
|
-
} else {
|
|
294
|
-
console.log('\nā
All CLI tools are up to date');
|
|
295
|
-
}
|
|
334
|
+
// ę¹éåēŗ§ęęå·„å
·ļ¼äøę¬”ęéę£ęµ
|
|
335
|
+
console.log(`[INFO] Starting batch upgrade of ${Object.keys(installedTools).length} tools...`);
|
|
296
336
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
+
};
|
|
302
344
|
}
|
|
303
345
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
});
|
|
309
|
-
}
|
|
346
|
+
const upgradeResult = await enhancedInstaller.upgradeTools(
|
|
347
|
+
Object.keys(installedTools),
|
|
348
|
+
upgradeToolInfos
|
|
349
|
+
);
|
|
310
350
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
351
|
+
// ę“ēē»ę
|
|
352
|
+
const results = {
|
|
353
|
+
successful: [],
|
|
354
|
+
failed: [],
|
|
355
|
+
permissionHandled: []
|
|
356
|
+
};
|
|
316
357
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
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
|
+
});
|
|
329
369
|
}
|
|
330
370
|
}
|
|
331
|
-
|
|
332
|
-
// ę§č”åēŗ§
|
|
333
|
-
console.log('\nš Executing upgrade plan...\n');
|
|
334
|
-
const results = await upgrader.executeUpgrade(plan, options);
|
|
335
|
-
|
|
371
|
+
|
|
336
372
|
// ę¾ē¤ŗē»ę
|
|
337
373
|
console.log('\nš UPGRADE RESULTS');
|
|
338
374
|
console.log('='.repeat(50));
|
|
339
375
|
|
|
340
376
|
if (results.successful.length > 0) {
|
|
341
377
|
console.log(`\nā
Successful (${results.successful.length}):`);
|
|
342
|
-
results.successful.forEach(
|
|
343
|
-
|
|
344
|
-
|
|
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}`);
|
|
345
387
|
});
|
|
346
388
|
}
|
|
347
389
|
|
|
348
390
|
if (results.failed.length > 0) {
|
|
349
391
|
console.log(`\nā Failed (${results.failed.length}):`);
|
|
350
392
|
results.failed.forEach(result => {
|
|
351
|
-
|
|
352
|
-
console.log(` ⢠${name}: ${result.error}`);
|
|
393
|
+
console.log(` ⢠${result.tool}: ${result.error}`);
|
|
353
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
|
+
}
|
|
354
402
|
}
|
|
355
403
|
|
|
356
|
-
|
|
357
|
-
|
|
404
|
+
if (results.permissionHandled.length > 0) {
|
|
405
|
+
console.log('\nā
ęéé®é¢å·²čŖåØå¤ē');
|
|
406
|
+
console.log(`š§ čŖåØęåęéåēŗ§äŗ ${results.permissionHandled.length} äøŖå·„å
·`);
|
|
407
|
+
}
|
|
358
408
|
|
|
359
409
|
console.log('\nš Upgrade process completed!');
|
|
360
|
-
|
|
410
|
+
|
|
361
411
|
} catch (error) {
|
|
362
412
|
console.error('[ERROR] Upgrade failed:', error.message);
|
|
363
|
-
if (
|
|
413
|
+
if (process.env.DEBUG === 'true') {
|
|
364
414
|
console.error(error.stack);
|
|
365
415
|
}
|
|
366
416
|
process.exit(1);
|
|
@@ -368,30 +418,101 @@ async function main() {
|
|
|
368
418
|
break;
|
|
369
419
|
}
|
|
370
420
|
|
|
371
|
-
|
|
421
|
+
case 'install':
|
|
372
422
|
case 'inst':
|
|
373
423
|
try {
|
|
374
424
|
console.log('[INSTALL] Starting AI CLI tools installation...');
|
|
375
|
-
const { missing: missingTools } = await installer.scanCLI();
|
|
376
|
-
const options = await installer.showInstallOptions(missingTools);
|
|
377
425
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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})`);
|
|
388
458
|
}
|
|
389
459
|
} else {
|
|
390
|
-
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
|
+
}
|
|
391
508
|
}
|
|
509
|
+
|
|
510
|
+
console.log('\n[INFO] Installation process completed.');
|
|
392
511
|
} catch (error) {
|
|
393
|
-
|
|
394
|
-
|
|
512
|
+
console.error('[ERROR] Installation failed:', error.message);
|
|
513
|
+
if (process.env.DEBUG === 'true') {
|
|
514
|
+
console.error(error.stack);
|
|
515
|
+
}
|
|
395
516
|
process.exit(1);
|
|
396
517
|
}
|
|
397
518
|
break;
|
|
@@ -425,8 +546,27 @@ async function main() {
|
|
|
425
546
|
|
|
426
547
|
// Execute the routed command
|
|
427
548
|
try {
|
|
428
|
-
// Get the actual executable path for the tool
|
|
429
|
-
|
|
549
|
+
// Get the actual executable path for the tool using which/where command
|
|
550
|
+
let toolPath = route.tool;
|
|
551
|
+
try {
|
|
552
|
+
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
553
|
+
const whichResult = spawnSync(whichCmd, [route.tool], {
|
|
554
|
+
encoding: 'utf8',
|
|
555
|
+
timeout: 10000,
|
|
556
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
557
|
+
shell: true,
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
if (whichResult.status === 0 && whichResult.stdout.trim()) {
|
|
561
|
+
// Get the first match (most likely the one that would be executed)
|
|
562
|
+
toolPath = whichResult.stdout.trim().split('\n')[0].trim();
|
|
563
|
+
}
|
|
564
|
+
} catch (whichError) {
|
|
565
|
+
// If which/where fails, continue with the tool name
|
|
566
|
+
if (process.env.DEBUG === 'true') {
|
|
567
|
+
console.log(`[DEBUG] which/where command failed for ${route.tool}: ${whichError.message}`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
430
570
|
|
|
431
571
|
// SPECIAL TEST CASE: Simulate a non-existent tool for testing
|
|
432
572
|
// This is for demonstration purposes only
|
|
@@ -508,7 +648,116 @@ async function main() {
|
|
|
508
648
|
if (process.env.DEBUG === 'true') {
|
|
509
649
|
console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
|
|
510
650
|
}
|
|
511
|
-
|
|
651
|
+
|
|
652
|
+
// Special handling for Windows to construct the command properly
|
|
653
|
+
let execCommand = toolPath;
|
|
654
|
+
let execArgs = toolArgs;
|
|
655
|
+
if (process.platform === 'win32') {
|
|
656
|
+
// On Windows, we construct the full command line and pass it as a single string
|
|
657
|
+
if (toolArgs.length > 0) {
|
|
658
|
+
// For Windows, we need to properly quote the entire command line
|
|
659
|
+
const argsString = toolArgs.map(arg => {
|
|
660
|
+
// If arg contains spaces and is not already quoted, quote it
|
|
661
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
662
|
+
return `"${arg}"`;
|
|
663
|
+
}
|
|
664
|
+
return arg;
|
|
665
|
+
}).join(' ');
|
|
666
|
+
execCommand = `${toolPath} ${argsString}`;
|
|
667
|
+
execArgs = [];
|
|
668
|
+
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Special handling for Claude on Windows to bypass the wrapper script
|
|
673
|
+
if (process.platform === 'win32' && route.tool === 'claude') {
|
|
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
|
+
|
|
684
|
+
if (toolArgs.length > 0) {
|
|
685
|
+
const argsString = toolArgs.map(arg => {
|
|
686
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
687
|
+
return `"${arg}"`;
|
|
688
|
+
}
|
|
689
|
+
return arg;
|
|
690
|
+
}).join(' ');
|
|
691
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
692
|
+
execArgs = [];
|
|
693
|
+
console.log(`[DEBUG] Windows direct Claude command: ${execCommand}`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
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
|
|
732
|
+
const argsString = toolArgs.map(arg => {
|
|
733
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
734
|
+
return `"${arg}"`;
|
|
735
|
+
}
|
|
736
|
+
return arg;
|
|
737
|
+
}).join(' ');
|
|
738
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
739
|
+
execArgs = [];
|
|
740
|
+
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Apply the same Windows handling logic to ensure consistency
|
|
745
|
+
// This ensures consistency between direct routing and call command routing
|
|
746
|
+
if (process.platform === 'win32' && execArgs.length > 0) {
|
|
747
|
+
// For Windows, we need to properly quote the entire command line
|
|
748
|
+
const argsString = execArgs.map(arg => {
|
|
749
|
+
// If arg contains spaces and is not already quoted, quote it
|
|
750
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
751
|
+
return `"${arg}"`;
|
|
752
|
+
}
|
|
753
|
+
return arg;
|
|
754
|
+
}).join(' ');
|
|
755
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
756
|
+
execArgs = [];
|
|
757
|
+
console.log(`[DEBUG] Windows unified command: ${execCommand}`);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const result = await executeCommand(execCommand, execArgs, {
|
|
512
761
|
stdio: 'inherit',
|
|
513
762
|
shell: true,
|
|
514
763
|
});
|
|
@@ -587,11 +836,41 @@ async function main() {
|
|
|
587
836
|
}
|
|
588
837
|
|
|
589
838
|
case 'auto-install':
|
|
590
|
-
// Auto-install mode for npm postinstall - NON-INTERACTIVE
|
|
839
|
+
// Auto-install mode for npm postinstall - NON-INTERACTIVE with permission awareness
|
|
591
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));
|
|
592
852
|
console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
|
|
593
853
|
console.log('='.repeat(60));
|
|
594
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
|
+
|
|
595
874
|
// Force stdout flush to ensure visibility during npm install
|
|
596
875
|
if (process.stdout && process.stdout.write) {
|
|
597
876
|
process.stdout.write('');
|
|
@@ -666,7 +945,77 @@ async function main() {
|
|
|
666
945
|
console.log(` ā ${toolInfo.name} (${toolName})`);
|
|
667
946
|
console.log(` Install with: ${toolInfo.installCommand}`);
|
|
668
947
|
}
|
|
669
|
-
|
|
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
|
+
}
|
|
670
1019
|
}
|
|
671
1020
|
|
|
672
1021
|
console.log('\n[USAGE] Get started with these commands:');
|
|
@@ -773,6 +1122,75 @@ async function main() {
|
|
|
773
1122
|
}
|
|
774
1123
|
break;
|
|
775
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
|
+
|
|
776
1194
|
case 'clean':
|
|
777
1195
|
case 'c': {
|
|
778
1196
|
try {
|
|
@@ -880,7 +1298,8 @@ async function main() {
|
|
|
880
1298
|
console.log('\nš Advanced Options:');
|
|
881
1299
|
console.log(' ⢠stigmergy clean --all - Clean all caches');
|
|
882
1300
|
console.log(' ⢠stigmergy clean --dry-run - Preview cleaning');
|
|
883
|
-
console.log(' ⢠npm
|
|
1301
|
+
console.log(' ⢠npm uninstall -g stigmergy - Uninstall Stigmergy completely (runs enhanced cleanup)');
|
|
1302
|
+
console.log(' ⢠See remaining items after uninstall (individual CLI tools, docs, etc.)');
|
|
884
1303
|
}
|
|
885
1304
|
|
|
886
1305
|
} catch (error) {
|
|
@@ -890,6 +1309,71 @@ async function main() {
|
|
|
890
1309
|
break;
|
|
891
1310
|
}
|
|
892
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
|
+
|
|
893
1377
|
default:
|
|
894
1378
|
// Check if the command matches a direct CLI tool name
|
|
895
1379
|
if (CLI_TOOLS[command]) {
|
|
@@ -918,8 +1402,27 @@ async function main() {
|
|
|
918
1402
|
|
|
919
1403
|
// Execute the routed command (reusing the call command logic)
|
|
920
1404
|
try {
|
|
921
|
-
// Get the actual executable path for the tool
|
|
922
|
-
|
|
1405
|
+
// Get the actual executable path for the tool using which/where command
|
|
1406
|
+
let toolPath = toolName;
|
|
1407
|
+
try {
|
|
1408
|
+
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
1409
|
+
const whichResult = spawnSync(whichCmd, [toolName], {
|
|
1410
|
+
encoding: 'utf8',
|
|
1411
|
+
timeout: 10000,
|
|
1412
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1413
|
+
shell: true,
|
|
1414
|
+
});
|
|
1415
|
+
|
|
1416
|
+
if (whichResult.status === 0 && whichResult.stdout.trim()) {
|
|
1417
|
+
// Get the first match (most likely the one that would be executed)
|
|
1418
|
+
toolPath = whichResult.stdout.trim().split('\n')[0].trim();
|
|
1419
|
+
}
|
|
1420
|
+
} catch (whichError) {
|
|
1421
|
+
// If which/where fails, continue with the tool name
|
|
1422
|
+
if (process.env.DEBUG === 'true') {
|
|
1423
|
+
console.log(`[DEBUG] which/where command failed for ${toolName}: ${whichError.message}`);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
923
1426
|
|
|
924
1427
|
console.log(`[DEBUG] Tool path: ${toolPath}, Prompt: ${route.prompt}`);
|
|
925
1428
|
|
|
@@ -1024,12 +1527,42 @@ async function main() {
|
|
|
1024
1527
|
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
1025
1528
|
}
|
|
1026
1529
|
}
|
|
1027
|
-
|
|
1028
|
-
//
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1530
|
+
|
|
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
|
|
1551
|
+
const argsString = toolArgs.map(arg => {
|
|
1552
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1553
|
+
return `"${arg}"`;
|
|
1554
|
+
}
|
|
1555
|
+
return arg;
|
|
1556
|
+
}).join(' ');
|
|
1557
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
1558
|
+
execArgs = [];
|
|
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
|
|
1033
1566
|
const argsString = toolArgs.map(arg => {
|
|
1034
1567
|
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1035
1568
|
return `"${arg}"`;
|
|
@@ -1038,9 +1571,26 @@ async function main() {
|
|
|
1038
1571
|
}).join(' ');
|
|
1039
1572
|
execCommand = `${execCommand} ${argsString}`;
|
|
1040
1573
|
execArgs = [];
|
|
1041
|
-
console.log(`[DEBUG] Windows
|
|
1574
|
+
console.log(`[DEBUG] Windows full command: ${execCommand}`);
|
|
1042
1575
|
}
|
|
1043
1576
|
}
|
|
1577
|
+
|
|
1578
|
+
|
|
1579
|
+
// Apply the same Windows handling logic to ensure consistency
|
|
1580
|
+
// This ensures consistency between direct routing and call command routing
|
|
1581
|
+
if (process.platform === 'win32' && execArgs.length > 0) {
|
|
1582
|
+
// For Windows, we need to properly quote the entire command line
|
|
1583
|
+
const argsString = execArgs.map(arg => {
|
|
1584
|
+
// If arg contains spaces and is not already quoted, quote it
|
|
1585
|
+
if (arg.includes(' ') && !(arg.startsWith('"') && arg.endsWith('"'))) {
|
|
1586
|
+
return `"${arg}"`;
|
|
1587
|
+
}
|
|
1588
|
+
return arg;
|
|
1589
|
+
}).join(' ');
|
|
1590
|
+
execCommand = `${execCommand} ${argsString}`;
|
|
1591
|
+
execArgs = [];
|
|
1592
|
+
console.log(`[DEBUG] Windows unified command: ${execCommand}`);
|
|
1593
|
+
}
|
|
1044
1594
|
|
|
1045
1595
|
const result = await executeCommand(execCommand, execArgs, {
|
|
1046
1596
|
stdio: 'inherit',
|