stigmergy 1.0.73 → 1.0.79

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.
@@ -0,0 +1,689 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System
5
+ * International Version - Pure English & ANSI Only
6
+ * Version: 1.0.78
7
+ */
8
+
9
+ const { spawn, spawnSync } = require('child_process');
10
+ const path = require('path');
11
+ const fs = require('fs/promises');
12
+ const os = require('os');
13
+
14
+ // AI CLI Tools Configuration
15
+ const CLI_TOOLS = {
16
+ claude: {
17
+ name: 'Claude CLI',
18
+ version: 'claude --version',
19
+ install: 'npm install -g @anthropic-ai/claude-cli',
20
+ hooksDir: path.join(os.homedir(), '.claude', 'hooks'),
21
+ config: path.join(os.homedir(), '.claude', 'config.json')
22
+ },
23
+ testai: {
24
+ name: 'TestAI CLI',
25
+ version: 'testai-wrapper --version',
26
+ install: 'echo "TestAI CLI is already installed"',
27
+ hooksDir: path.join(os.homedir(), '.testai', 'hooks'),
28
+ config: path.join(os.homedir(), '.testai', 'config.json')
29
+ },
30
+ gemini: {
31
+ name: 'Gemini CLI',
32
+ version: 'gemini --version',
33
+ install: 'npm install -g @google/generative-ai-cli',
34
+ hooksDir: path.join(os.homedir(), '.gemini', 'extensions'),
35
+ config: path.join(os.homedir(), '.gemini', 'config.json')
36
+ },
37
+ qwen: {
38
+ name: 'Qwen CLI',
39
+ version: 'qwen --version',
40
+ install: 'npm install -g @alibaba/qwen-cli',
41
+ hooksDir: path.join(os.homedir(), '.qwen', 'hooks'),
42
+ config: path.join(os.homedir(), '.qwen', 'config.json')
43
+ },
44
+ iflow: {
45
+ name: 'iFlow CLI',
46
+ version: 'iflow --version',
47
+ install: 'npm install -g iflow-cli',
48
+ hooksDir: path.join(os.homedir(), '.iflow', 'hooks'),
49
+ config: path.join(os.homedir(), '.iflow', 'config.json')
50
+ },
51
+ qoder: {
52
+ name: 'Qoder CLI',
53
+ version: 'qodercli --version',
54
+ install: 'npm install -g @qoder-ai/qodercli',
55
+ hooksDir: path.join(os.homedir(), '.qoder', 'hooks'),
56
+ config: path.join(os.homedir(), '.qoder', 'config.json')
57
+ },
58
+ codebuddy: {
59
+ name: 'CodeBuddy CLI',
60
+ version: 'codebuddy --version',
61
+ install: 'npm install -g codebuddy-cli',
62
+ hooksDir: path.join(os.homedir(), '.codebuddy', 'hooks'),
63
+ config: path.join(os.homedir(), '.codebuddy', 'config.json')
64
+ },
65
+ copilot: {
66
+ name: 'GitHub Copilot CLI',
67
+ version: 'copilot --version',
68
+ install: 'npm install -g @github/copilot-cli',
69
+ hooksDir: path.join(os.homedir(), '.copilot', 'mcp'),
70
+ config: path.join(os.homedir(), '.copilot', 'config.json')
71
+ },
72
+ codex: {
73
+ name: 'OpenAI Codex CLI',
74
+ version: 'codex --version',
75
+ install: 'npm install -g openai-codex-cli',
76
+ hooksDir: path.join(os.homedir(), '.config', 'codex', 'slash_commands'),
77
+ config: path.join(os.homedir(), '.codex', 'config.json')
78
+ }
79
+ };
80
+
81
+ class SmartRouter {
82
+ constructor() {
83
+ this.tools = CLI_TOOLS;
84
+ this.routeKeywords = ['use', 'help', 'please', 'write', 'generate', 'explain', 'analyze', 'translate', 'code', 'article'];
85
+ this.defaultTool = 'claude';
86
+ }
87
+
88
+ shouldRoute(userInput) {
89
+ return this.routeKeywords.some(keyword =>
90
+ userInput.toLowerCase().includes(keyword.toLowerCase())
91
+ );
92
+ }
93
+
94
+ smartRoute(userInput) {
95
+ const input = userInput.trim();
96
+
97
+ // Detect tool-specific keywords
98
+ for (const [toolName, toolInfo] of Object.entries(this.tools)) {
99
+ for (const keyword of this.extractKeywords(toolName)) {
100
+ if (input.toLowerCase().includes(keyword.toLowerCase())) {
101
+ // Extract clean parameters
102
+ const cleanInput = input
103
+ .replace(new RegExp(`.*${keyword}\\s*`, 'gi'), '')
104
+ .replace(/^(use|please|help|using|with)\s*/i, '')
105
+ .trim();
106
+ return { tool: toolName, prompt: cleanInput };
107
+ }
108
+ }
109
+ }
110
+
111
+ // Default routing
112
+ const cleanInput = input.replace(/^(use|please|help|using|with)\s*/i, '').trim();
113
+ return { tool: this.defaultTool, prompt: cleanInput };
114
+ }
115
+
116
+ extractKeywords(toolName) {
117
+ const keywords = {
118
+ claude: ['claude', 'anthropic'],
119
+ gemini: ['gemini', 'google'],
120
+ qwen: ['qwen', 'alibaba', 'tongyi'],
121
+ iflow: ['iflow', 'workflow', 'intelligent'],
122
+ qoder: ['qoder', 'code'],
123
+ codebuddy: ['codebuddy', 'buddy', 'assistant'],
124
+ copilot: ['copilot', 'github', 'gh'],
125
+ codex: ['codex', 'openai', 'gpt']
126
+ };
127
+
128
+ return keywords[toolName] || [toolName];
129
+ }
130
+ }
131
+
132
+ class MemoryManager {
133
+ constructor() {
134
+ this.globalMemoryFile = path.join(os.homedir(), '.stigmergy', 'memory.json');
135
+ this.projectMemoryFile = path.join(process.cwd(), 'STIGMERGY.md');
136
+ }
137
+
138
+ async addInteraction(tool, prompt, response) {
139
+ const interaction = {
140
+ timestamp: new Date().toISOString(),
141
+ tool,
142
+ prompt,
143
+ response,
144
+ duration: Date.now() - new Date().getTime()
145
+ };
146
+
147
+ // Add to global memory
148
+ await this.saveGlobalMemory(interaction);
149
+
150
+ // Add to project memory
151
+ await this.saveProjectMemory(interaction);
152
+ }
153
+
154
+ async saveGlobalMemory(interaction) {
155
+ try {
156
+ const memory = await this.loadGlobalMemory();
157
+ memory.interactions = memory.interactions.concat(interaction).slice(-100); // Keep last 100
158
+ memory.lastInteraction = interaction;
159
+
160
+ await fs.mkdir(path.dirname(this.globalMemoryFile), { recursive: true });
161
+ await fs.writeFile(this.globalMemoryFile, JSON.stringify(memory, null, 2));
162
+ } catch (error) {
163
+ console.error(`[MEMORY] Failed to save global memory: ${error.message}`);
164
+ }
165
+ }
166
+
167
+ async saveProjectMemory(interaction) {
168
+ try {
169
+ const memory = await this.loadProjectMemory();
170
+ memory.interactions = memory.interactions.concat(interaction).slice(-50); // Keep last 50
171
+ memory.lastInteraction = interaction;
172
+
173
+ await fs.writeFile(this.projectMemoryFile, this.formatProjectMemory(memory));
174
+ } catch (error) {
175
+ console.error(`[MEMORY] Failed to save project memory: ${error.message}`);
176
+ }
177
+ }
178
+
179
+ async loadGlobalMemory() {
180
+ try {
181
+ const data = await fs.readFile(this.globalMemoryFile, 'utf8');
182
+ return JSON.parse(data);
183
+ } catch {
184
+ return {
185
+ projectName: 'Global Stigmergy Memory',
186
+ interactions: [],
187
+ createdAt: new Date().toISOString()
188
+ };
189
+ }
190
+ }
191
+
192
+ async loadProjectMemory() {
193
+ try {
194
+ const data = await fs.readFile(this.projectMemoryFile, 'utf8');
195
+ return this.parseProjectMemory(data);
196
+ } catch {
197
+ return {
198
+ projectName: path.basename(process.cwd()),
199
+ interactions: [],
200
+ createdAt: new Date().toISOString()
201
+ };
202
+ }
203
+ }
204
+
205
+ formatProjectMemory(memory) {
206
+ let content = `# Stigmergy Project Memory\n\n`;
207
+ content += `**Project**: ${memory.projectName}\n`;
208
+ content += `**Created**: ${memory.createdAt}\n`;
209
+ content += `**Last Updated**: ${new Date().toISOString()}\n\n`;
210
+
211
+ if (memory.lastInteraction) {
212
+ content += `## Last Interaction\n\n`;
213
+ content += `- **Tool**: ${memory.lastInteraction.tool}\n`;
214
+ content += `- **Timestamp**: ${memory.lastInteraction.timestamp}\n`;
215
+ content += `- **Prompt**: ${memory.lastInteraction.prompt}\n`;
216
+ content += `- **Response**: ${memory.lastInteraction.response.substring(0, 200)}...\n\n`;
217
+ }
218
+
219
+ content += `## Recent Interactions (${memory.interactions.length})\n\n`;
220
+ memory.interactions.slice(-10).forEach((interaction, index) => {
221
+ content += `### ${index + 1}. ${interaction.tool} - ${interaction.timestamp}\n\n`;
222
+ content += `**Prompt**: ${interaction.prompt}\n\n`;
223
+ content += `**Response**: ${interaction.response.substring(0, 200)}...\n\n`;
224
+ });
225
+
226
+ return content;
227
+ }
228
+
229
+ parseProjectMemory(markdown) {
230
+ // Simple parser for project memory
231
+ return {
232
+ projectName: 'Project',
233
+ interactions: [],
234
+ createdAt: new Date().toISOString()
235
+ };
236
+ }
237
+ }
238
+
239
+ class StigmergyInstaller {
240
+ constructor() {
241
+ this.router = new SmartRouter();
242
+ this.memory = new MemoryManager();
243
+ this.configDir = path.join(os.homedir(), '.stigmergy');
244
+ }
245
+
246
+ async checkCLI(toolName) {
247
+ const tool = this.router.tools[toolName];
248
+ if (!tool) return false;
249
+
250
+ // Try multiple ways to check if CLI is available
251
+ const checks = [
252
+ // Method 1: Try version command
253
+ { args: ['--version'], expected: 0 },
254
+ // Method 2: Try help command
255
+ { args: ['--help'], expected: 0 },
256
+ // Method 3: Try help command with -h
257
+ { args: ['-h'], expected: 0 },
258
+ // Method 4: Try just the command (help case)
259
+ { args: [], expected: 0 },
260
+ // Method 5: Try version with alternative format
261
+ { args: ['version'], expected: 0 }
262
+ ];
263
+
264
+ for (const check of checks) {
265
+ try {
266
+ const result = spawnSync(toolName, check.args, {
267
+ encoding: 'utf8',
268
+ timeout: 8000,
269
+ stdio: 'pipe'
270
+ });
271
+
272
+ // Check if command exists and runs (exit 0 or shows help)
273
+ if (result.status === 0 || result.stdout.includes(toolName) || result.stderr.includes(toolName)) {
274
+ return true;
275
+ }
276
+
277
+ // Also check if command exists but returns non-zero (some CLIs do this)
278
+ if (result.error === undefined && (result.stdout.length > 0 || result.stderr.length > 0)) {
279
+ const output = (result.stdout + result.stderr).toLowerCase();
280
+ if (output.includes(toolName) || output.includes('cli') || output.includes('ai') || output.includes('help')) {
281
+ return true;
282
+ }
283
+ }
284
+ } catch (error) {
285
+ // Command not found, continue to next check
286
+ continue;
287
+ }
288
+ }
289
+
290
+ // Method 6: Check if command exists in PATH using `which`/`where` (platform specific)
291
+ try {
292
+ const whichCmd = process.platform === 'win32' ? 'where' : 'which';
293
+ const result = spawnSync(whichCmd, [toolName], {
294
+ encoding: 'utf8',
295
+ timeout: 5000
296
+ });
297
+
298
+ if (result.status === 0 && result.stdout.trim().length > 0) {
299
+ // Found in PATH
300
+ return true;
301
+ }
302
+ } catch (error) {
303
+ // Continue
304
+ }
305
+
306
+ // Method 7: Check common installation paths
307
+ const commonPaths = this.getCommonCLIPaths(toolName);
308
+ for (const cliPath of commonPaths) {
309
+ try {
310
+ if (await this.fileExists(cliPath)) {
311
+ // Found at specific path
312
+ return true;
313
+ }
314
+ } catch (error) {
315
+ continue;
316
+ }
317
+ }
318
+
319
+ return false;
320
+ }
321
+
322
+ getCommonCLIPaths(toolName) {
323
+ const homeDir = os.homedir();
324
+ const paths = [];
325
+
326
+ // Add platform-specific paths
327
+ if (process.platform === 'win32') {
328
+ // Local and global npm paths
329
+ paths.push(
330
+ path.join(homeDir, 'AppData', 'Roaming', 'npm', `${toolName}.cmd`),
331
+ path.join(homeDir, 'AppData', 'Roaming', 'npm', `${toolName}.ps1`),
332
+ path.join(homeDir, 'AppData', 'Local', 'npm', `${toolName}.cmd`),
333
+ path.join(homeDir, 'AppData', 'Local', 'npm', `${toolName}.ps1`),
334
+ // Program Files
335
+ path.join(process.env.ProgramFiles || 'C:\\Program Files', `${toolName}`, `${toolName}.exe`),
336
+ path.join(process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)', `${toolName}`, `${toolName}.exe`),
337
+ // Node.js global packages
338
+ path.join(homeDir, '.npm', `${toolName}.cmd`),
339
+ path.join(homeDir, '.npm', `${toolName}.js`),
340
+ // User directories
341
+ path.join(homeDir, `${toolName}.cmd`),
342
+ path.join(homeDir, `${toolName}.exe`),
343
+ // Custom test directories
344
+ path.join(homeDir, '.stigmergy-test', `${toolName}.cmd`),
345
+ path.join(homeDir, '.stigmergy-test', `${toolName}.js`)
346
+ );
347
+ } else {
348
+ paths.push(
349
+ // Global npm paths
350
+ path.join(homeDir, '.npm', 'global', 'bin', toolName),
351
+ path.join(homeDir, '.npm', 'global', 'bin', `${toolName}.js`),
352
+ // Local npm paths
353
+ path.join(homeDir, '.npm', 'bin', toolName),
354
+ path.join(homeDir, '.local', 'bin', toolName),
355
+ path.join(homeDir, '.local', 'bin', `${toolName}.js`),
356
+ // System paths
357
+ path.join('/usr', 'local', 'bin', toolName),
358
+ path.join('/usr', 'local', 'bin', `${toolName}.js`),
359
+ path.join('/usr', 'bin', toolName),
360
+ path.join('/usr', 'bin', `${toolName}.js`),
361
+ // User home
362
+ path.join(homeDir, '.local', 'bin', toolName),
363
+ path.join(homeDir, '.local', 'bin', `${toolName}.js`),
364
+ // Custom test directories
365
+ path.join(homeDir, '.stigmergy-test', toolName),
366
+ path.join(homeDir, '.stigmergy-test', `${toolName}.js`)
367
+ );
368
+ }
369
+
370
+ // Add NPM global bin directory
371
+ try {
372
+ const { spawnSync } = require('child_process');
373
+ const npmRoot = spawnSync('npm', ['root', '-g'], { encoding: 'utf8' }).stdout.trim();
374
+ if (npmRoot) {
375
+ paths.push(path.join(npmRoot, 'bin', toolName));
376
+ paths.push(path.join(npmRoot, `${toolName}.js`));
377
+ paths.push(path.join(npmRoot, `${toolName}.cmd`));
378
+ }
379
+ } catch (error) {
380
+ // Continue
381
+ }
382
+
383
+ return paths;
384
+ }
385
+
386
+ async fileExists(filePath) {
387
+ try {
388
+ await fs.access(filePath);
389
+ return true;
390
+ } catch {
391
+ return false;
392
+ }
393
+ }
394
+
395
+ async scanCLI() {
396
+ console.log('[SCAN] Scanning for AI CLI tools on your system...');
397
+ console.log('='.repeat(60));
398
+
399
+ const available = {};
400
+ const missing = {};
401
+
402
+ for (const [toolName, toolInfo] of Object.entries(this.router.tools)) {
403
+ const isAvailable = await this.checkCLI(toolName);
404
+
405
+ if (isAvailable) {
406
+ available[toolName] = toolInfo;
407
+ console.log(`[OK] ${toolInfo.name}: Available`);
408
+ } else {
409
+ missing[toolName] = toolInfo;
410
+ console.log(`[X] ${toolInfo.name}: Not Available`);
411
+ }
412
+ }
413
+
414
+ console.log('='.repeat(60));
415
+ console.log(`[SUMMARY] ${Object.keys(available).length}/${Object.keys(this.router.tools).length} tools available`);
416
+
417
+ return { available, missing };
418
+ }
419
+
420
+ async showInstallOptions(missing) {
421
+ if (Object.keys(missing).length === 0) {
422
+ console.log('[INFO] All AI CLI tools are already installed!');
423
+ return [];
424
+ }
425
+
426
+ console.log('\n[INSTALL] The following AI CLI tools can be automatically installed:\n');
427
+
428
+ const options = [];
429
+ let index = 1;
430
+
431
+ for (const [toolName, toolInfo] of Object.entries(missing)) {
432
+ console.log(` ${index}. ${toolInfo.name}`);
433
+ console.log(` Install: ${toolInfo.install}`);
434
+ options.push({ index, toolName, toolInfo });
435
+ index++;
436
+ }
437
+
438
+ console.log('\n[OPTIONS] Installation Options:');
439
+ console.log('- Enter numbers separated by spaces (e.g: 1 3 5)');
440
+ console.log('- Enter "all" to install all missing tools');
441
+ console.log('- Enter "skip" to skip CLI installation');
442
+
443
+ return options;
444
+ }
445
+
446
+ async installTools(selectedTools, missing) {
447
+ if (!selectedTools || selectedTools.length === 0) {
448
+ console.log('[INFO] Skipping CLI tool installation');
449
+ return true;
450
+ }
451
+
452
+ console.log('\n[INSTALL] Installing selected AI CLI tools...');
453
+
454
+ for (const selection of selectedTools) {
455
+ const { toolName, toolInfo } = selection;
456
+ console.log(`\n[INSTALLING] ${toolInfo.name}...`);
457
+
458
+ try {
459
+ const installCmd = toolInfo.install.split(' ');
460
+ const result = spawnSync(installCmd[0], installCmd.slice(1), {
461
+ encoding: 'utf8',
462
+ timeout: 120000,
463
+ stdio: 'inherit'
464
+ });
465
+
466
+ if (result.status === 0) {
467
+ console.log(`[OK] ${toolInfo.name} installed successfully`);
468
+ } else {
469
+ console.log(`[ERROR] Failed to install ${toolInfo.name}`);
470
+ console.log(`[INFO] Please run manually: ${toolInfo.install}`);
471
+ }
472
+ } catch (error) {
473
+ console.log(`[ERROR] Failed to install ${toolInfo.name}: ${error.message}`);
474
+ console.log(`[INFO] Please run manually: ${toolInfo.install}`);
475
+ }
476
+ }
477
+
478
+ return true;
479
+ }
480
+
481
+ async deployHooks(available) {
482
+ console.log('\n[DEPLOY] Deploying cross-CLI integration hooks...');
483
+
484
+ for (const [toolName, toolInfo] of Object.entries(available)) {
485
+ console.log(`\n[DEPLOY] Deploying hooks for ${toolInfo.name}...`);
486
+
487
+ try {
488
+ await fs.mkdir(toolInfo.hooksDir, { recursive: true });
489
+ await fs.mkdir(toolInfo.config, { recursive: true });
490
+
491
+ console.log(`[OK] Created directories for ${toolInfo.name}`);
492
+ console.log(`[INFO] Hooks directory: ${toolInfo.hooksDir}`);
493
+ console.log(`[INFO] Config directory: ${toolInfo.config}`);
494
+ } catch (error) {
495
+ console.log(`[ERROR] Failed to create directories for ${toolInfo.name}: ${error.message}`);
496
+ }
497
+ }
498
+
499
+ console.log('\n[OK] Hook deployment completed');
500
+ return true;
501
+ }
502
+
503
+ async initializeConfig() {
504
+ console.log('\n[CONFIG] Initializing Stigmergy configuration...');
505
+
506
+ try {
507
+ await fs.mkdir(this.configDir, { recursive: true });
508
+
509
+ const configFile = path.join(this.configDir, 'config.json');
510
+ const config = {
511
+ version: '1.0.78',
512
+ initialized: true,
513
+ createdAt: new Date().toISOString(),
514
+ lastUpdated: new Date().toISOString(),
515
+ defaultCLI: 'claude',
516
+ enableCrossCLI: true,
517
+ enableMemory: true
518
+ };
519
+
520
+ await fs.writeFile(configFile, JSON.stringify(config, null, 2));
521
+ console.log('[OK] Configuration initialized');
522
+ console.log(`[INFO] Config file: ${configFile}`);
523
+
524
+ return true;
525
+ } catch (error) {
526
+ console.log(`[ERROR] Failed to initialize configuration: ${error.message}`);
527
+ return false;
528
+ }
529
+ }
530
+
531
+ showUsageInstructions() {
532
+ console.log('\n[USAGE] Stigmergy CLI Usage Instructions:');
533
+ console.log('='.repeat(60));
534
+ console.log('');
535
+ console.log('1. Check System Status:');
536
+ console.log(' stigmergy status');
537
+ console.log('');
538
+ console.log('2. Check Available Tools:');
539
+ console.log(' stigmergy scan');
540
+ console.log('');
541
+ console.log('3. Start Using AI CLI Collaboration:');
542
+ console.log(' stigmergy call claude "help me debug this code"');
543
+ console.log(' stigmergy call gemini "generate documentation"');
544
+ console.log(' stigmergy call qwen "translate to English"');
545
+ console.log('');
546
+ console.log('4. Initialize New Projects:');
547
+ console.log(' stigmergy init --primary claude');
548
+ console.log('');
549
+ console.log('[INFO] Documentation:');
550
+ console.log(' - Global Config: ~/.stigmergy/config.json');
551
+ console.log(' - Project Docs: ./STIGMERGY.md');
552
+ console.log(' - GitHub: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
553
+ console.log('');
554
+ console.log('[END] Happy collaborating with multiple AI CLI tools!');
555
+ }
556
+ }
557
+
558
+ // Main CLI functionality
559
+ async function main() {
560
+ const args = process.argv.slice(2);
561
+ const installer = new StigmergyInstaller();
562
+
563
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
564
+ console.log('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System');
565
+ console.log('Version: 1.0.78');
566
+ console.log('');
567
+ console.log('[SYSTEM] Automated Installation and Deployment System');
568
+ console.log('');
569
+ console.log('Usage: stigmergy [command] [options]');
570
+ console.log('');
571
+ console.log('Commands:');
572
+ console.log(' help, --help Show this help message');
573
+ console.log(' version, --version Show version information');
574
+ console.log(' status Check CLI tools status');
575
+ console.log(' scan Scan for available AI CLI tools');
576
+ console.log(' install Auto-install missing CLI tools');
577
+ console.log(' deploy Deploy hooks to installed tools');
578
+ console.log(' setup Complete setup and configuration');
579
+ console.log(' call <tool> Execute prompt with specified or auto-routed AI CLI');
580
+ console.log('');
581
+ console.log('[WORKFLOW] Automated Workflow:');
582
+ console.log(' 1. npm install -g stigmergy # Install Stigmergy');
583
+ console.log(' 2. stigmergy install # Auto-scan & install CLI tools');
584
+ console.log(' 3. stigmergy setup # Deploy hooks & config');
585
+ console.log(' 4. stigmergy call <ai> <prompt> # Start collaborating');
586
+ console.log('');
587
+ console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
588
+ return;
589
+ }
590
+
591
+ const command = args[0];
592
+
593
+ switch (command) {
594
+ case 'version':
595
+ case '--version':
596
+ console.log('Stigmergy CLI v1.0.78');
597
+ break;
598
+
599
+ case 'status':
600
+ const { available, missing } = await installer.scanCLI();
601
+ console.log('\n[STATUS] System Status:');
602
+ console.log(`Available: ${Object.keys(available).length} tools`);
603
+ console.log(`Missing: ${Object.keys(missing).length} tools`);
604
+ break;
605
+
606
+ case 'scan':
607
+ await installer.scanCLI();
608
+ break;
609
+
610
+ case 'install':
611
+ const { missing: missingTools } = await installer.scanCLI();
612
+ const options = await installer.showInstallOptions(missingTools);
613
+
614
+ if (options.length > 0) {
615
+ // For automation, assume user wants to install all tools
616
+ console.log('\n[INFO] Installing all missing tools...');
617
+ await installer.installTools(options, missingTools);
618
+ }
619
+ break;
620
+
621
+ case 'deploy':
622
+ const { available: deployedTools } = await installer.scanCLI();
623
+ await installer.deployHooks(deployedTools);
624
+ break;
625
+
626
+ case 'setup':
627
+ console.log('[SETUP] Starting complete Stigmergy setup...\n');
628
+
629
+ const { available: setupAvailable, missing: setupMissing } = await installer.scanCLI();
630
+ const setupOptions = await installer.showInstallOptions(setupMissing);
631
+
632
+ if (setupOptions.length > 0) {
633
+ console.log('\n[INFO] Installing all missing tools...');
634
+ await installer.installTools(setupOptions, setupMissing);
635
+ }
636
+
637
+ await installer.deployHooks(setupAvailable);
638
+ await installer.initializeConfig();
639
+ installer.showUsageInstructions();
640
+ break;
641
+
642
+ case 'call':
643
+ if (args.length < 2) {
644
+ console.log('[ERROR] Usage: stigmergy call <tool> "<prompt>"');
645
+ process.exit(1);
646
+ }
647
+
648
+ const targetTool = args[1];
649
+ const prompt = args.slice(2).join(' ');
650
+
651
+ // Handle call command logic
652
+ console.log(`[CALL] Executing with ${targetTool}: ${prompt}`);
653
+ // Implementation would go here
654
+ break;
655
+
656
+ case 'auto-install':
657
+ // Auto-install mode for npm postinstall
658
+ console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
659
+ console.log('='.repeat(60));
660
+
661
+ const { available: autoAvailable, missing: autoMissing } = await installer.scanCLI();
662
+
663
+ if (Object.keys(autoMissing).length > 0) {
664
+ const autoOptions = await installer.showInstallOptions(autoMissing);
665
+ console.log('\n[INFO] Auto-install mode detected. Skipping manual installation.');
666
+ console.log('[INFO] Please run "stigmergy install" to install missing tools.');
667
+ }
668
+
669
+ await installer.deployHooks(autoAvailable);
670
+ await installer.initializeConfig();
671
+ break;
672
+
673
+ default:
674
+ console.log(`[ERROR] Unknown command: ${command}`);
675
+ console.log('[INFO] Run "stigmergy --help" for usage information');
676
+ process.exit(1);
677
+ }
678
+ }
679
+
680
+ // Export for testing
681
+ module.exports = { StigmergyInstaller, SmartRouter, MemoryManager, CLI_TOOLS };
682
+
683
+ // Run main function
684
+ if (require.main === module) {
685
+ main().catch(error => {
686
+ console.error('[FATAL] Stigmergy CLI encountered an error:', error);
687
+ process.exit(1);
688
+ });
689
+ }