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