superacli 1.1.13 → 1.1.14

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.
Files changed (75) hide show
  1. package/.agents/skills/humanenv-usage/SKILL.md +19 -0
  2. package/AGENTS.md +62 -0
  3. package/CONTRIBUTING.md +6 -2
  4. package/cli/plugin-install-guidance.js +25 -11
  5. package/cli/plugins-registry.js +25 -6
  6. package/cli/skills-catalog.js +85 -10
  7. package/coverage/clover.xml +1073 -965
  8. package/coverage/lcov-report/cli/adapter-schema.js.html +32 -32
  9. package/coverage/lcov-report/cli/adapters/builtin.js.html +1 -1
  10. package/coverage/lcov-report/cli/adapters/http.js.html +1 -1
  11. package/coverage/lcov-report/cli/adapters/index.html +1 -1
  12. package/coverage/lcov-report/cli/adapters/mcp.js.html +1 -1
  13. package/coverage/lcov-report/cli/adapters/openapi.js.html +1 -1
  14. package/coverage/lcov-report/cli/adapters/process.js.html +1 -1
  15. package/coverage/lcov-report/cli/adapters/shell.js.html +1 -1
  16. package/coverage/lcov-report/cli/ask.js.html +1 -1
  17. package/coverage/lcov-report/cli/config.js.html +109 -109
  18. package/coverage/lcov-report/cli/discover.js.html +1 -1
  19. package/coverage/lcov-report/cli/executor.js.html +1 -1
  20. package/coverage/lcov-report/cli/help-json.js.html +1 -1
  21. package/coverage/lcov-report/cli/index.html +92 -92
  22. package/coverage/lcov-report/cli/mcp-diagnostics.js.html +1 -1
  23. package/coverage/lcov-report/cli/mcp-discovery.js.html +1 -1
  24. package/coverage/lcov-report/cli/mcp-local.js.html +1 -1
  25. package/coverage/lcov-report/cli/mcp-stdio-jsonrpc.js.html +1 -1
  26. package/coverage/lcov-report/cli/namespace-passthrough.js.html +1 -1
  27. package/coverage/lcov-report/cli/plan-runtime.js.html +1 -1
  28. package/coverage/lcov-report/cli/planner.js.html +1 -1
  29. package/coverage/lcov-report/cli/plugin-install-guidance.js.html +919 -877
  30. package/coverage/lcov-report/cli/plugins-command.js.html +452 -452
  31. package/coverage/lcov-report/cli/plugins-learn.js.html +60 -60
  32. package/coverage/lcov-report/cli/plugins-manager.js.html +133 -133
  33. package/coverage/lcov-report/cli/plugins-registry.js.html +105 -48
  34. package/coverage/lcov-report/cli/plugins-store.js.html +106 -106
  35. package/coverage/lcov-report/cli/skills-catalog.js.html +366 -141
  36. package/coverage/lcov-report/cli/skills-mcp.js.html +1 -1
  37. package/coverage/lcov-report/cli/skills.js.html +1 -1
  38. package/coverage/lcov-report/index.html +19 -19
  39. package/coverage/lcov-report/server/app.js.html +1 -1
  40. package/coverage/lcov-report/server/index.html +1 -1
  41. package/coverage/lcov-report/server/routes/ask.js.html +1 -1
  42. package/coverage/lcov-report/server/routes/commands.js.html +1 -1
  43. package/coverage/lcov-report/server/routes/config.js.html +1 -1
  44. package/coverage/lcov-report/server/routes/index.html +1 -1
  45. package/coverage/lcov-report/server/routes/jobs.js.html +1 -1
  46. package/coverage/lcov-report/server/routes/mcp.js.html +1 -1
  47. package/coverage/lcov-report/server/routes/plans.js.html +1 -1
  48. package/coverage/lcov-report/server/routes/plugins.js.html +1 -1
  49. package/coverage/lcov-report/server/routes/specs.js.html +1 -1
  50. package/coverage/lcov-report/server/services/configService.js.html +1 -1
  51. package/coverage/lcov-report/server/services/index.html +1 -1
  52. package/coverage/lcov-report/server/services/pluginsService.js.html +1 -1
  53. package/coverage/lcov-report/server/storage/adapter.js.html +1 -1
  54. package/coverage/lcov-report/server/storage/file.js.html +1 -1
  55. package/coverage/lcov-report/server/storage/index.html +1 -1
  56. package/coverage/lcov-report/server/storage/mongo.js.html +1 -1
  57. package/coverage/lcov.info +1423 -1120
  58. package/package.json +1 -1
  59. package/plugins/beads/install-guidance.json +10 -0
  60. package/plugins/beads/meta.json +5 -0
  61. package/plugins/codedb/meta.json +5 -0
  62. package/plugins/codedb/plugin.json +169 -0
  63. package/plugins/codedb/skills/quickstart/SKILL.md +65 -0
  64. package/plugins/humanenv/.agents/skills/humanenv-sdk-python-usage/SKILL.md +37 -0
  65. package/plugins/humanenv/.agents/skills/humanenv-usage/SKILL.md +32 -0
  66. package/plugins/humanenv/plugin.json +65 -0
  67. package/plugins/humanenv/skills/quickstart/SKILL.md +95 -0
  68. package/plugins/mmx/install-guidance.json +10 -0
  69. package/plugins/mmx/meta.json +5 -0
  70. package/plugins/mmx/plugin.json +413 -0
  71. package/plugins/mmx/skills/quickstart/SKILL.md +234 -0
  72. package/plugins/plugins.json +21 -9
  73. package/plugins/rtk/README.md +63 -0
  74. package/plugins/rtk/plugin.json +79 -0
  75. package/plugins/rtk/skills/quickstart/SKILL.md +78 -0
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">12.62% </span>
26
+ <span class="strong">0% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>50/396</span>
28
+ <span class='fraction'>0/471</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">100% </span>
33
+ <span class="strong">0% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>0/0</span>
35
+ <span class='fraction'>0/1</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
40
  <span class="strong">0% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>0/23</span>
42
+ <span class='fraction'>0/1</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">12.62% </span>
47
+ <span class="strong">0% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>50/396</span>
49
+ <span class='fraction'>0/471</span>
50
50
  </div>
51
51
 
52
52
 
@@ -459,38 +459,190 @@
459
459
  <a name='L394'></a><a href='#L394'>394</a>
460
460
  <a name='L395'></a><a href='#L395'>395</a>
461
461
  <a name='L396'></a><a href='#L396'>396</a>
462
- <a name='L397'></a><a href='#L397'>397</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
463
- <span class="cline-any cline-yes">1x</span>
464
- <span class="cline-any cline-yes">1x</span>
465
- <span class="cline-any cline-yes">1x</span>
466
- <span class="cline-any cline-yes">1x</span>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
538
+ <span class="cline-any cline-no">&nbsp;</span>
539
+ <span class="cline-any cline-no">&nbsp;</span>
540
+ <span class="cline-any cline-no">&nbsp;</span>
541
+ <span class="cline-any cline-no">&nbsp;</span>
542
+ <span class="cline-any cline-no">&nbsp;</span>
543
+ <span class="cline-any cline-no">&nbsp;</span>
544
+ <span class="cline-any cline-no">&nbsp;</span>
545
+ <span class="cline-any cline-no">&nbsp;</span>
546
+ <span class="cline-any cline-no">&nbsp;</span>
547
+ <span class="cline-any cline-no">&nbsp;</span>
548
+ <span class="cline-any cline-no">&nbsp;</span>
549
+ <span class="cline-any cline-no">&nbsp;</span>
550
+ <span class="cline-any cline-no">&nbsp;</span>
551
+ <span class="cline-any cline-no">&nbsp;</span>
552
+ <span class="cline-any cline-no">&nbsp;</span>
553
+ <span class="cline-any cline-no">&nbsp;</span>
554
+ <span class="cline-any cline-no">&nbsp;</span>
555
+ <span class="cline-any cline-no">&nbsp;</span>
556
+ <span class="cline-any cline-no">&nbsp;</span>
557
+ <span class="cline-any cline-no">&nbsp;</span>
558
+ <span class="cline-any cline-no">&nbsp;</span>
559
+ <span class="cline-any cline-no">&nbsp;</span>
560
+ <span class="cline-any cline-no">&nbsp;</span>
561
+ <span class="cline-any cline-no">&nbsp;</span>
562
+ <span class="cline-any cline-no">&nbsp;</span>
563
+ <span class="cline-any cline-no">&nbsp;</span>
564
+ <span class="cline-any cline-no">&nbsp;</span>
565
+ <span class="cline-any cline-no">&nbsp;</span>
566
+ <span class="cline-any cline-no">&nbsp;</span>
567
+ <span class="cline-any cline-no">&nbsp;</span>
568
+ <span class="cline-any cline-no">&nbsp;</span>
569
+ <span class="cline-any cline-no">&nbsp;</span>
570
+ <span class="cline-any cline-no">&nbsp;</span>
571
+ <span class="cline-any cline-no">&nbsp;</span>
572
+ <span class="cline-any cline-no">&nbsp;</span>
573
+ <span class="cline-any cline-no">&nbsp;</span>
574
+ <span class="cline-any cline-no">&nbsp;</span>
575
+ <span class="cline-any cline-no">&nbsp;</span>
576
+ <span class="cline-any cline-no">&nbsp;</span>
577
+ <span class="cline-any cline-no">&nbsp;</span>
578
+ <span class="cline-any cline-no">&nbsp;</span>
579
+ <span class="cline-any cline-no">&nbsp;</span>
580
+ <span class="cline-any cline-no">&nbsp;</span>
581
+ <span class="cline-any cline-no">&nbsp;</span>
582
+ <span class="cline-any cline-no">&nbsp;</span>
583
+ <span class="cline-any cline-no">&nbsp;</span>
584
+ <span class="cline-any cline-no">&nbsp;</span>
585
+ <span class="cline-any cline-no">&nbsp;</span>
586
+ <span class="cline-any cline-no">&nbsp;</span>
587
+ <span class="cline-any cline-no">&nbsp;</span>
588
+ <span class="cline-any cline-no">&nbsp;</span>
589
+ <span class="cline-any cline-no">&nbsp;</span>
590
+ <span class="cline-any cline-no">&nbsp;</span>
591
+ <span class="cline-any cline-no">&nbsp;</span>
592
+ <span class="cline-any cline-no">&nbsp;</span>
593
+ <span class="cline-any cline-no">&nbsp;</span>
594
+ <span class="cline-any cline-no">&nbsp;</span>
595
+ <span class="cline-any cline-no">&nbsp;</span>
596
+ <span class="cline-any cline-no">&nbsp;</span>
597
+ <span class="cline-any cline-no">&nbsp;</span>
598
+ <span class="cline-any cline-no">&nbsp;</span>
599
+ <span class="cline-any cline-no">&nbsp;</span>
600
+ <span class="cline-any cline-no">&nbsp;</span>
601
+ <span class="cline-any cline-no">&nbsp;</span>
602
+ <span class="cline-any cline-no">&nbsp;</span>
603
+ <span class="cline-any cline-no">&nbsp;</span>
604
+ <span class="cline-any cline-no">&nbsp;</span>
605
+ <span class="cline-any cline-no">&nbsp;</span>
606
+ <span class="cline-any cline-no">&nbsp;</span>
607
+ <span class="cline-any cline-no">&nbsp;</span>
608
+ <span class="cline-any cline-no">&nbsp;</span>
609
+ <span class="cline-any cline-no">&nbsp;</span>
610
+ <span class="cline-any cline-no">&nbsp;</span>
611
+ <span class="cline-any cline-no">&nbsp;</span>
612
+ <span class="cline-any cline-no">&nbsp;</span>
613
+ <span class="cline-any cline-no">&nbsp;</span>
614
+ <span class="cline-any cline-no">&nbsp;</span>
615
+ <span class="cline-any cline-no">&nbsp;</span>
616
+ <span class="cline-any cline-no">&nbsp;</span>
617
+ <span class="cline-any cline-no">&nbsp;</span>
618
+ <span class="cline-any cline-no">&nbsp;</span>
619
+ <span class="cline-any cline-no">&nbsp;</span>
620
+ <span class="cline-any cline-no">&nbsp;</span>
621
+ <span class="cline-any cline-no">&nbsp;</span>
622
+ <span class="cline-any cline-no">&nbsp;</span>
623
+ <span class="cline-any cline-no">&nbsp;</span>
467
624
  <span class="cline-any cline-no">&nbsp;</span>
468
625
  <span class="cline-any cline-no">&nbsp;</span>
469
626
  <span class="cline-any cline-no">&nbsp;</span>
470
- <span class="cline-any cline-yes">1x</span>
471
627
  <span class="cline-any cline-no">&nbsp;</span>
472
628
  <span class="cline-any cline-no">&nbsp;</span>
473
629
  <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-yes">1x</span>
475
630
  <span class="cline-any cline-no">&nbsp;</span>
476
631
  <span class="cline-any cline-no">&nbsp;</span>
477
632
  <span class="cline-any cline-no">&nbsp;</span>
478
633
  <span class="cline-any cline-no">&nbsp;</span>
479
634
  <span class="cline-any cline-no">&nbsp;</span>
480
- <span class="cline-any cline-yes">1x</span>
481
635
  <span class="cline-any cline-no">&nbsp;</span>
482
636
  <span class="cline-any cline-no">&nbsp;</span>
483
637
  <span class="cline-any cline-no">&nbsp;</span>
484
638
  <span class="cline-any cline-no">&nbsp;</span>
485
639
  <span class="cline-any cline-no">&nbsp;</span>
486
- <span class="cline-any cline-yes">1x</span>
487
640
  <span class="cline-any cline-no">&nbsp;</span>
488
641
  <span class="cline-any cline-no">&nbsp;</span>
489
642
  <span class="cline-any cline-no">&nbsp;</span>
490
643
  <span class="cline-any cline-no">&nbsp;</span>
491
644
  <span class="cline-any cline-no">&nbsp;</span>
492
645
  <span class="cline-any cline-no">&nbsp;</span>
493
- <span class="cline-any cline-yes">1x</span>
494
646
  <span class="cline-any cline-no">&nbsp;</span>
495
647
  <span class="cline-any cline-no">&nbsp;</span>
496
648
  <span class="cline-any cline-no">&nbsp;</span>
@@ -502,7 +654,6 @@
502
654
  <span class="cline-any cline-no">&nbsp;</span>
503
655
  <span class="cline-any cline-no">&nbsp;</span>
504
656
  <span class="cline-any cline-no">&nbsp;</span>
505
- <span class="cline-any cline-yes">1x</span>
506
657
  <span class="cline-any cline-no">&nbsp;</span>
507
658
  <span class="cline-any cline-no">&nbsp;</span>
508
659
  <span class="cline-any cline-no">&nbsp;</span>
@@ -511,22 +662,18 @@
511
662
  <span class="cline-any cline-no">&nbsp;</span>
512
663
  <span class="cline-any cline-no">&nbsp;</span>
513
664
  <span class="cline-any cline-no">&nbsp;</span>
514
- <span class="cline-any cline-yes">1x</span>
515
665
  <span class="cline-any cline-no">&nbsp;</span>
516
666
  <span class="cline-any cline-no">&nbsp;</span>
517
667
  <span class="cline-any cline-no">&nbsp;</span>
518
668
  <span class="cline-any cline-no">&nbsp;</span>
519
669
  <span class="cline-any cline-no">&nbsp;</span>
520
- <span class="cline-any cline-yes">1x</span>
521
670
  <span class="cline-any cline-no">&nbsp;</span>
522
671
  <span class="cline-any cline-no">&nbsp;</span>
523
672
  <span class="cline-any cline-no">&nbsp;</span>
524
673
  <span class="cline-any cline-no">&nbsp;</span>
525
- <span class="cline-any cline-yes">1x</span>
526
674
  <span class="cline-any cline-no">&nbsp;</span>
527
675
  <span class="cline-any cline-no">&nbsp;</span>
528
676
  <span class="cline-any cline-no">&nbsp;</span>
529
- <span class="cline-any cline-yes">1x</span>
530
677
  <span class="cline-any cline-no">&nbsp;</span>
531
678
  <span class="cline-any cline-no">&nbsp;</span>
532
679
  <span class="cline-any cline-no">&nbsp;</span>
@@ -535,7 +682,6 @@
535
682
  <span class="cline-any cline-no">&nbsp;</span>
536
683
  <span class="cline-any cline-no">&nbsp;</span>
537
684
  <span class="cline-any cline-no">&nbsp;</span>
538
- <span class="cline-any cline-yes">1x</span>
539
685
  <span class="cline-any cline-no">&nbsp;</span>
540
686
  <span class="cline-any cline-no">&nbsp;</span>
541
687
  <span class="cline-any cline-no">&nbsp;</span>
@@ -543,11 +689,9 @@
543
689
  <span class="cline-any cline-no">&nbsp;</span>
544
690
  <span class="cline-any cline-no">&nbsp;</span>
545
691
  <span class="cline-any cline-no">&nbsp;</span>
546
- <span class="cline-any cline-yes">1x</span>
547
692
  <span class="cline-any cline-no">&nbsp;</span>
548
693
  <span class="cline-any cline-no">&nbsp;</span>
549
694
  <span class="cline-any cline-no">&nbsp;</span>
550
- <span class="cline-any cline-yes">1x</span>
551
695
  <span class="cline-any cline-no">&nbsp;</span>
552
696
  <span class="cline-any cline-no">&nbsp;</span>
553
697
  <span class="cline-any cline-no">&nbsp;</span>
@@ -555,7 +699,6 @@
555
699
  <span class="cline-any cline-no">&nbsp;</span>
556
700
  <span class="cline-any cline-no">&nbsp;</span>
557
701
  <span class="cline-any cline-no">&nbsp;</span>
558
- <span class="cline-any cline-yes">1x</span>
559
702
  <span class="cline-any cline-no">&nbsp;</span>
560
703
  <span class="cline-any cline-no">&nbsp;</span>
561
704
  <span class="cline-any cline-no">&nbsp;</span>
@@ -570,7 +713,6 @@
570
713
  <span class="cline-any cline-no">&nbsp;</span>
571
714
  <span class="cline-any cline-no">&nbsp;</span>
572
715
  <span class="cline-any cline-no">&nbsp;</span>
573
- <span class="cline-any cline-yes">1x</span>
574
716
  <span class="cline-any cline-no">&nbsp;</span>
575
717
  <span class="cline-any cline-no">&nbsp;</span>
576
718
  <span class="cline-any cline-no">&nbsp;</span>
@@ -587,13 +729,11 @@
587
729
  <span class="cline-any cline-no">&nbsp;</span>
588
730
  <span class="cline-any cline-no">&nbsp;</span>
589
731
  <span class="cline-any cline-no">&nbsp;</span>
590
- <span class="cline-any cline-yes">1x</span>
591
732
  <span class="cline-any cline-no">&nbsp;</span>
592
733
  <span class="cline-any cline-no">&nbsp;</span>
593
734
  <span class="cline-any cline-no">&nbsp;</span>
594
735
  <span class="cline-any cline-no">&nbsp;</span>
595
736
  <span class="cline-any cline-no">&nbsp;</span>
596
- <span class="cline-any cline-yes">1x</span>
597
737
  <span class="cline-any cline-no">&nbsp;</span>
598
738
  <span class="cline-any cline-no">&nbsp;</span>
599
739
  <span class="cline-any cline-no">&nbsp;</span>
@@ -680,14 +820,12 @@
680
820
  <span class="cline-any cline-no">&nbsp;</span>
681
821
  <span class="cline-any cline-no">&nbsp;</span>
682
822
  <span class="cline-any cline-no">&nbsp;</span>
683
- <span class="cline-any cline-yes">1x</span>
684
823
  <span class="cline-any cline-no">&nbsp;</span>
685
824
  <span class="cline-any cline-no">&nbsp;</span>
686
825
  <span class="cline-any cline-no">&nbsp;</span>
687
826
  <span class="cline-any cline-no">&nbsp;</span>
688
827
  <span class="cline-any cline-no">&nbsp;</span>
689
828
  <span class="cline-any cline-no">&nbsp;</span>
690
- <span class="cline-any cline-yes">1x</span>
691
829
  <span class="cline-any cline-no">&nbsp;</span>
692
830
  <span class="cline-any cline-no">&nbsp;</span>
693
831
  <span class="cline-any cline-no">&nbsp;</span>
@@ -698,7 +836,6 @@
698
836
  <span class="cline-any cline-no">&nbsp;</span>
699
837
  <span class="cline-any cline-no">&nbsp;</span>
700
838
  <span class="cline-any cline-no">&nbsp;</span>
701
- <span class="cline-any cline-yes">1x</span>
702
839
  <span class="cline-any cline-no">&nbsp;</span>
703
840
  <span class="cline-any cline-no">&nbsp;</span>
704
841
  <span class="cline-any cline-no">&nbsp;</span>
@@ -715,12 +852,6 @@
715
852
  <span class="cline-any cline-no">&nbsp;</span>
716
853
  <span class="cline-any cline-no">&nbsp;</span>
717
854
  <span class="cline-any cline-no">&nbsp;</span>
718
- <span class="cline-any cline-yes">1x</span>
719
- <span class="cline-any cline-yes">1x</span>
720
- <span class="cline-any cline-yes">1x</span>
721
- <span class="cline-any cline-yes">1x</span>
722
- <span class="cline-any cline-yes">1x</span>
723
- <span class="cline-any cline-yes">1x</span>
724
855
  <span class="cline-any cline-no">&nbsp;</span>
725
856
  <span class="cline-any cline-no">&nbsp;</span>
726
857
  <span class="cline-any cline-no">&nbsp;</span>
@@ -791,10 +922,6 @@
791
922
  <span class="cline-any cline-no">&nbsp;</span>
792
923
  <span class="cline-any cline-no">&nbsp;</span>
793
924
  <span class="cline-any cline-no">&nbsp;</span>
794
- <span class="cline-any cline-yes">1x</span>
795
- <span class="cline-any cline-yes">1x</span>
796
- <span class="cline-any cline-yes">1x</span>
797
- <span class="cline-any cline-yes">1x</span>
798
925
  <span class="cline-any cline-no">&nbsp;</span>
799
926
  <span class="cline-any cline-no">&nbsp;</span>
800
927
  <span class="cline-any cline-no">&nbsp;</span>
@@ -840,54 +967,77 @@
840
967
  <span class="cline-any cline-no">&nbsp;</span>
841
968
  <span class="cline-any cline-no">&nbsp;</span>
842
969
  <span class="cline-any cline-no">&nbsp;</span>
843
- <span class="cline-any cline-yes">1x</span>
844
- <span class="cline-any cline-yes">1x</span>
845
- <span class="cline-any cline-yes">1x</span>
846
- <span class="cline-any cline-yes">1x</span>
847
- <span class="cline-any cline-yes">1x</span>
848
- <span class="cline-any cline-yes">1x</span>
849
- <span class="cline-any cline-yes">1x</span>
850
- <span class="cline-any cline-yes">1x</span>
851
- <span class="cline-any cline-yes">1x</span>
852
- <span class="cline-any cline-yes">1x</span>
853
- <span class="cline-any cline-yes">1x</span>
854
- <span class="cline-any cline-yes">1x</span>
855
- <span class="cline-any cline-yes">1x</span>
856
- <span class="cline-any cline-yes">1x</span>
857
- <span class="cline-any cline-yes">1x</span>
858
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const fs = require("fs")
859
- const os = require("os")
860
- const path = require("path")
861
- const { spawnSync } = require("child_process")
862
- &nbsp;
863
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function dcliDir() {</span></span>
970
+ <span class="cline-any cline-no">&nbsp;</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-no">&nbsp;</span>
975
+ <span class="cline-any cline-no">&nbsp;</span>
976
+ <span class="cline-any cline-no">&nbsp;</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-no">&nbsp;</span>
980
+ <span class="cline-any cline-no">&nbsp;</span>
981
+ <span class="cline-any cline-no">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-no">&nbsp;</span>
986
+ <span class="cline-any cline-no">&nbsp;</span>
987
+ <span class="cline-any cline-no">&nbsp;</span>
988
+ <span class="cline-any cline-no">&nbsp;</span>
989
+ <span class="cline-any cline-no">&nbsp;</span>
990
+ <span class="cline-any cline-no">&nbsp;</span>
991
+ <span class="cline-any cline-no">&nbsp;</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-no">&nbsp;</span>
994
+ <span class="cline-any cline-no">&nbsp;</span>
995
+ <span class="cline-any cline-no">&nbsp;</span>
996
+ <span class="cline-any cline-no">&nbsp;</span>
997
+ <span class="cline-any cline-no">&nbsp;</span>
998
+ <span class="cline-any cline-no">&nbsp;</span>
999
+ <span class="cline-any cline-no">&nbsp;</span>
1000
+ <span class="cline-any cline-no">&nbsp;</span>
1001
+ <span class="cline-any cline-no">&nbsp;</span>
1002
+ <span class="cline-any cline-no">&nbsp;</span>
1003
+ <span class="cline-any cline-no">&nbsp;</span>
1004
+ <span class="cline-any cline-no">&nbsp;</span>
1005
+ <span class="cline-any cline-no">&nbsp;</span>
1006
+ <span class="cline-any cline-no">&nbsp;</span>
1007
+ <span class="cline-any cline-no">&nbsp;</span>
1008
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js"><span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" ><span class="branch-0 cbranch-no" title="branch not covered" >const fs = require("fs")</span></span></span>
1009
+ <span class="cstat-no" title="statement not covered" >const os = require("os")</span>
1010
+ <span class="cstat-no" title="statement not covered" >const path = require("path")</span>
1011
+ <span class="cstat-no" title="statement not covered" >const { spawnSync } = require("child_process")</span>
1012
+ <span class="cstat-no" title="statement not covered" ></span>
1013
+ <span class="cstat-no" title="statement not covered" >function dcliDir() {</span>
864
1014
  <span class="cstat-no" title="statement not covered" > return process.env.SUPERCLI_HOME || path.join(os.homedir(), ".dcli")</span>
865
1015
  <span class="cstat-no" title="statement not covered" >}</span>
866
- &nbsp;
867
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function supercliDir() {</span></span>
1016
+ <span class="cstat-no" title="statement not covered" ></span>
1017
+ <span class="cstat-no" title="statement not covered" >function supercliDir() {</span>
868
1018
  <span class="cstat-no" title="statement not covered" > return process.env.SUPERCLI_HOME || path.join(os.homedir(), ".supercli")</span>
869
1019
  <span class="cstat-no" title="statement not covered" >}</span>
870
- &nbsp;
871
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function providersFile() {</span></span>
1020
+ <span class="cstat-no" title="statement not covered" ></span>
1021
+ <span class="cstat-no" title="statement not covered" >function providersFile() {</span>
872
1022
  <span class="cstat-no" title="statement not covered" > const supercliPath = path.join(supercliDir(), "skills-providers.json")</span>
873
1023
  <span class="cstat-no" title="statement not covered" > const dcliPath = path.join(dcliDir(), "skills-providers.json")</span>
874
1024
  <span class="cstat-no" title="statement not covered" > return fs.existsSync(supercliPath) ? supercliPath : dcliPath</span>
875
1025
  <span class="cstat-no" title="statement not covered" >}</span>
876
- &nbsp;
877
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function indexFile() {</span></span>
1026
+ <span class="cstat-no" title="statement not covered" ></span>
1027
+ <span class="cstat-no" title="statement not covered" >function indexFile() {</span>
878
1028
  <span class="cstat-no" title="statement not covered" > const supercliPath = path.join(supercliDir(), "skills-index.json")</span>
879
1029
  <span class="cstat-no" title="statement not covered" > const dcliPath = path.join(dcliDir(), "skills-index.json")</span>
880
1030
  <span class="cstat-no" title="statement not covered" > return fs.existsSync(supercliPath) ? supercliPath : dcliPath</span>
881
1031
  <span class="cstat-no" title="statement not covered" >}</span>
882
- &nbsp;
883
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function ensureDir() {</span></span>
1032
+ <span class="cstat-no" title="statement not covered" ></span>
1033
+ <span class="cstat-no" title="statement not covered" >function ensureDir() {</span>
884
1034
  <span class="cstat-no" title="statement not covered" > const dir = dcliDir()</span>
885
1035
  <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })</span>
886
1036
  <span class="cstat-no" title="statement not covered" > const supercliDirPath = supercliDir()</span>
887
1037
  <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(supercliDirPath)) fs.mkdirSync(supercliDirPath, { recursive: true })</span>
888
1038
  <span class="cstat-no" title="statement not covered" >}</span>
889
- &nbsp;
890
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function defaultProviders() {</span></span>
1039
+ <span class="cstat-no" title="statement not covered" ></span>
1040
+ <span class="cstat-no" title="statement not covered" >function defaultProviders() {</span>
891
1041
  <span class="cstat-no" title="statement not covered" > const home = os.homedir()</span>
892
1042
  <span class="cstat-no" title="statement not covered" > const cwd = process.cwd()</span>
893
1043
  <span class="cstat-no" title="statement not covered" > return [</span>
@@ -898,8 +1048,57 @@ const { spawnSync } = require("child_process")
898
1048
  <span class="cstat-no" title="statement not covered" > { name: "repo", type: "repo_fs", roots: [path.join(cwd, ".agents", "skills"), path.join(cwd, "docs", "skills")], enabled: true }</span>
899
1049
  <span class="cstat-no" title="statement not covered" > ]</span>
900
1050
  <span class="cstat-no" title="statement not covered" >}</span>
901
- &nbsp;
902
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function readJson(file, fallback) {</span></span>
1051
+ <span class="cstat-no" title="statement not covered" ></span>
1052
+ <span class="cstat-no" title="statement not covered" >function discoverInstalledPluginProviders() {</span>
1053
+ <span class="cstat-no" title="statement not covered" > const pluginsLockPath = path.join(supercliDir(), "plugins", "plugins.lock.json")</span>
1054
+ <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(pluginsLockPath)) return []</span>
1055
+ <span class="cstat-no" title="statement not covered" > </span>
1056
+ <span class="cstat-no" title="statement not covered" > try {</span>
1057
+ <span class="cstat-no" title="statement not covered" > const lock = JSON.parse(fs.readFileSync(pluginsLockPath, "utf-8"))</span>
1058
+ <span class="cstat-no" title="statement not covered" > if (!lock || !lock.installed) return []</span>
1059
+ <span class="cstat-no" title="statement not covered" > </span>
1060
+ <span class="cstat-no" title="statement not covered" > const providers = []</span>
1061
+ <span class="cstat-no" title="statement not covered" > const addedNames = new Set()</span>
1062
+ <span class="cstat-no" title="statement not covered" > </span>
1063
+ <span class="cstat-no" title="statement not covered" > for (const [name, plugin] of Object.entries(lock.installed)) {</span>
1064
+ <span class="cstat-no" title="statement not covered" > if (addedNames.has(name)) continue</span>
1065
+ <span class="cstat-no" title="statement not covered" > </span>
1066
+ <span class="cstat-no" title="statement not covered" > const resolvedFrom = plugin.resolved_from || {}</span>
1067
+ <span class="cstat-no" title="statement not covered" > let pluginDir = null</span>
1068
+ <span class="cstat-no" title="statement not covered" > </span>
1069
+ <span class="cstat-no" title="statement not covered" > if (resolvedFrom.type === "bundled") {</span>
1070
+ <span class="cstat-no" title="statement not covered" > const bundledDir = path.join(__dirname, "..", "plugins")</span>
1071
+ <span class="cstat-no" title="statement not covered" > pluginDir = path.join(bundledDir, name)</span>
1072
+ <span class="cstat-no" title="statement not covered" > } else if (resolvedFrom.manifest_path) {</span>
1073
+ <span class="cstat-no" title="statement not covered" > pluginDir = path.dirname(resolvedFrom.manifest_path)</span>
1074
+ <span class="cstat-no" title="statement not covered" > }</span>
1075
+ <span class="cstat-no" title="statement not covered" > </span>
1076
+ <span class="cstat-no" title="statement not covered" > if (pluginDir &amp;&amp; fs.existsSync(pluginDir)) {</span>
1077
+ <span class="cstat-no" title="statement not covered" > const skillsDirs = [</span>
1078
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, "skills"),</span>
1079
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, ".agents", "skills")</span>
1080
+ <span class="cstat-no" title="statement not covered" > ]</span>
1081
+ <span class="cstat-no" title="statement not covered" > const hasSkills = skillsDirs.some(dir =&gt; fs.existsSync(dir))</span>
1082
+ <span class="cstat-no" title="statement not covered" > </span>
1083
+ <span class="cstat-no" title="statement not covered" > if (hasSkills) {</span>
1084
+ <span class="cstat-no" title="statement not covered" > providers.push({</span>
1085
+ <span class="cstat-no" title="statement not covered" > name: name,</span>
1086
+ <span class="cstat-no" title="statement not covered" > type: "plugin_fs",</span>
1087
+ <span class="cstat-no" title="statement not covered" > enabled: true,</span>
1088
+ <span class="cstat-no" title="statement not covered" > plugin_dir: pluginDir</span>
1089
+ <span class="cstat-no" title="statement not covered" > })</span>
1090
+ <span class="cstat-no" title="statement not covered" > addedNames.add(name)</span>
1091
+ <span class="cstat-no" title="statement not covered" > }</span>
1092
+ <span class="cstat-no" title="statement not covered" > }</span>
1093
+ <span class="cstat-no" title="statement not covered" > }</span>
1094
+ <span class="cstat-no" title="statement not covered" > </span>
1095
+ <span class="cstat-no" title="statement not covered" > return providers</span>
1096
+ <span class="cstat-no" title="statement not covered" > } catch {</span>
1097
+ <span class="cstat-no" title="statement not covered" > return []</span>
1098
+ <span class="cstat-no" title="statement not covered" > }</span>
1099
+ <span class="cstat-no" title="statement not covered" >}</span>
1100
+ <span class="cstat-no" title="statement not covered" ></span>
1101
+ <span class="cstat-no" title="statement not covered" >function readJson(file, fallback) {</span>
903
1102
  <span class="cstat-no" title="statement not covered" > try {</span>
904
1103
  <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(file)) return fallback</span>
905
1104
  <span class="cstat-no" title="statement not covered" > return JSON.parse(fs.readFileSync(file, "utf-8"))</span>
@@ -907,23 +1106,38 @@ const { spawnSync } = require("child_process")
907
1106
  <span class="cstat-no" title="statement not covered" > return fallback</span>
908
1107
  <span class="cstat-no" title="statement not covered" > }</span>
909
1108
  <span class="cstat-no" title="statement not covered" >}</span>
910
- &nbsp;
911
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function writeJson(file, value) {</span></span>
1109
+ <span class="cstat-no" title="statement not covered" ></span>
1110
+ <span class="cstat-no" title="statement not covered" >function writeJson(file, value) {</span>
912
1111
  <span class="cstat-no" title="statement not covered" > ensureDir()</span>
913
1112
  <span class="cstat-no" title="statement not covered" > fs.writeFileSync(file, JSON.stringify(value, null, 2))</span>
914
1113
  <span class="cstat-no" title="statement not covered" > return value</span>
915
1114
  <span class="cstat-no" title="statement not covered" >}</span>
916
- &nbsp;
917
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function listProviders() {</span></span>
918
- <span class="cstat-no" title="statement not covered" > const providers = readJson(providersFile(), defaultProviders())</span>
919
- <span class="cstat-no" title="statement not covered" > return Array.isArray(providers) ? providers : defaultProviders()</span>
1115
+ <span class="cstat-no" title="statement not covered" ></span>
1116
+ <span class="cstat-no" title="statement not covered" >function listProviders() {</span>
1117
+ <span class="cstat-no" title="statement not covered" > const manualProviders = readJson(providersFile(), defaultProviders())</span>
1118
+ <span class="cstat-no" title="statement not covered" > const manual = Array.isArray(manualProviders) ? manualProviders : defaultProviders()</span>
1119
+ <span class="cstat-no" title="statement not covered" > const discoveredPlugins = discoverInstalledPluginProviders()</span>
1120
+ <span class="cstat-no" title="statement not covered" > </span>
1121
+ <span class="cstat-no" title="statement not covered" > const merged = new Map()</span>
1122
+ <span class="cstat-no" title="statement not covered" > </span>
1123
+ <span class="cstat-no" title="statement not covered" > for (const p of manual) {</span>
1124
+ <span class="cstat-no" title="statement not covered" > merged.set(p.name, p)</span>
1125
+ <span class="cstat-no" title="statement not covered" > }</span>
1126
+ <span class="cstat-no" title="statement not covered" > </span>
1127
+ <span class="cstat-no" title="statement not covered" > for (const p of discoveredPlugins) {</span>
1128
+ <span class="cstat-no" title="statement not covered" > if (!merged.has(p.name)) {</span>
1129
+ <span class="cstat-no" title="statement not covered" > merged.set(p.name, p)</span>
1130
+ <span class="cstat-no" title="statement not covered" > }</span>
1131
+ <span class="cstat-no" title="statement not covered" > }</span>
1132
+ <span class="cstat-no" title="statement not covered" > </span>
1133
+ <span class="cstat-no" title="statement not covered" > return Array.from(merged.values())</span>
920
1134
  <span class="cstat-no" title="statement not covered" >}</span>
921
- &nbsp;
922
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function setProviders(providers) {</span></span>
1135
+ <span class="cstat-no" title="statement not covered" ></span>
1136
+ <span class="cstat-no" title="statement not covered" >function setProviders(providers) {</span>
923
1137
  <span class="cstat-no" title="statement not covered" > return writeJson(providersFile(), providers)</span>
924
1138
  <span class="cstat-no" title="statement not covered" >}</span>
925
- &nbsp;
926
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function addProvider(entry) {</span></span>
1139
+ <span class="cstat-no" title="statement not covered" ></span>
1140
+ <span class="cstat-no" title="statement not covered" >function addProvider(entry) {</span>
927
1141
  <span class="cstat-no" title="statement not covered" > const providers = listProviders()</span>
928
1142
  <span class="cstat-no" title="statement not covered" > const idx = providers.findIndex(p =&gt; p.name === entry.name)</span>
929
1143
  <span class="cstat-no" title="statement not covered" > if (idx &gt;= 0) providers[idx] = entry</span>
@@ -931,28 +1145,28 @@ const { spawnSync } = require("child_process")
931
1145
  <span class="cstat-no" title="statement not covered" > setProviders(providers)</span>
932
1146
  <span class="cstat-no" title="statement not covered" > return entry</span>
933
1147
  <span class="cstat-no" title="statement not covered" >}</span>
934
- &nbsp;
935
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function removeProvider(name) {</span></span>
1148
+ <span class="cstat-no" title="statement not covered" ></span>
1149
+ <span class="cstat-no" title="statement not covered" >function removeProvider(name) {</span>
936
1150
  <span class="cstat-no" title="statement not covered" > const providers = listProviders()</span>
937
1151
  <span class="cstat-no" title="statement not covered" > const next = providers.filter(p =&gt; p.name !== name)</span>
938
1152
  <span class="cstat-no" title="statement not covered" > const removed = next.length !== providers.length</span>
939
1153
  <span class="cstat-no" title="statement not covered" > setProviders(next)</span>
940
1154
  <span class="cstat-no" title="statement not covered" > return removed</span>
941
1155
  <span class="cstat-no" title="statement not covered" >}</span>
942
- &nbsp;
943
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function getProvider(name) {</span></span>
1156
+ <span class="cstat-no" title="statement not covered" ></span>
1157
+ <span class="cstat-no" title="statement not covered" >function getProvider(name) {</span>
944
1158
  <span class="cstat-no" title="statement not covered" > return listProviders().find(p =&gt; p.name === name) || null</span>
945
1159
  <span class="cstat-no" title="statement not covered" >}</span>
946
- &nbsp;
947
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function readIndex() {</span></span>
1160
+ <span class="cstat-no" title="statement not covered" ></span>
1161
+ <span class="cstat-no" title="statement not covered" >function readIndex() {</span>
948
1162
  <span class="cstat-no" title="statement not covered" > const empty = { version: 1, updated_at: null, skills: [] }</span>
949
1163
  <span class="cstat-no" title="statement not covered" > const idx = readJson(indexFile(), empty)</span>
950
1164
  <span class="cstat-no" title="statement not covered" > if (!idx || typeof idx !== "object") return empty</span>
951
1165
  <span class="cstat-no" title="statement not covered" > if (!Array.isArray(idx.skills)) idx.skills = []</span>
952
1166
  <span class="cstat-no" title="statement not covered" > return idx</span>
953
1167
  <span class="cstat-no" title="statement not covered" >}</span>
954
- &nbsp;
955
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function walkDir(dir) {</span></span>
1168
+ <span class="cstat-no" title="statement not covered" ></span>
1169
+ <span class="cstat-no" title="statement not covered" >function walkDir(dir) {</span>
956
1170
  <span class="cstat-no" title="statement not covered" > const files = []</span>
957
1171
  <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(dir)) return files</span>
958
1172
  <span class="cstat-no" title="statement not covered" > const entries = fs.readdirSync(dir, { withFileTypes: true })</span>
@@ -966,8 +1180,8 @@ const { spawnSync } = require("child_process")
966
1180
  <span class="cstat-no" title="statement not covered" > }</span>
967
1181
  <span class="cstat-no" title="statement not covered" > return files</span>
968
1182
  <span class="cstat-no" title="statement not covered" >}</span>
969
- &nbsp;
970
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function parseFrontmatter(markdown) {</span></span>
1183
+ <span class="cstat-no" title="statement not covered" ></span>
1184
+ <span class="cstat-no" title="statement not covered" >function parseFrontmatter(markdown) {</span>
971
1185
  <span class="cstat-no" title="statement not covered" > if (!markdown.startsWith("---\n")) return { frontmatter: {}, body: markdown }</span>
972
1186
  <span class="cstat-no" title="statement not covered" > const end = markdown.indexOf("\n---\n", 4)</span>
973
1187
  <span class="cstat-no" title="statement not covered" > if (end &lt; 0) return { frontmatter: {}, body: markdown }</span>
@@ -983,14 +1197,14 @@ const { spawnSync } = require("child_process")
983
1197
  <span class="cstat-no" title="statement not covered" > }</span>
984
1198
  <span class="cstat-no" title="statement not covered" > return { frontmatter, body }</span>
985
1199
  <span class="cstat-no" title="statement not covered" >}</span>
986
- &nbsp;
987
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function baseSkillId(filePath, frontmatter, root) {</span></span>
1200
+ <span class="cstat-no" title="statement not covered" ></span>
1201
+ <span class="cstat-no" title="statement not covered" >function baseSkillId(filePath, frontmatter, root) {</span>
988
1202
  <span class="cstat-no" title="statement not covered" > if (frontmatter.skill_name) return frontmatter.skill_name</span>
989
1203
  <span class="cstat-no" title="statement not covered" > const rel = path.relative(root, filePath)</span>
990
1204
  <span class="cstat-no" title="statement not covered" > return rel.replace(/\\/g, "/").replace(/\/SKILL\.md$/, "").replace(/\//g, ".")</span>
991
1205
  <span class="cstat-no" title="statement not covered" >}</span>
992
- &nbsp;
993
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function syncCatalog() {</span></span>
1206
+ <span class="cstat-no" title="statement not covered" ></span>
1207
+ <span class="cstat-no" title="statement not covered" >function syncCatalog() {</span>
994
1208
  <span class="cstat-no" title="statement not covered" > const providers = listProviders()</span>
995
1209
  <span class="cstat-no" title="statement not covered" > const skills = []</span>
996
1210
  <span class="cstat-no" title="statement not covered" ></span>
@@ -1017,8 +1231,12 @@ const { spawnSync } = require("child_process")
1017
1231
  <span class="cstat-no" title="statement not covered" > if (provider.type === "plugin_fs") {</span>
1018
1232
  <span class="cstat-no" title="statement not covered" > const pluginDir = provider.plugin_dir</span>
1019
1233
  <span class="cstat-no" title="statement not covered" > if (!pluginDir || !fs.existsSync(pluginDir)) continue</span>
1020
- <span class="cstat-no" title="statement not covered" > const skillsDir = path.join(pluginDir, "skills")</span>
1021
- <span class="cstat-no" title="statement not covered" > if (fs.existsSync(skillsDir)) {</span>
1234
+ <span class="cstat-no" title="statement not covered" > const skillDirs = [</span>
1235
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, "skills"),</span>
1236
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, ".agents", "skills")</span>
1237
+ <span class="cstat-no" title="statement not covered" > ]</span>
1238
+ <span class="cstat-no" title="statement not covered" > for (const skillsDir of skillDirs) {</span>
1239
+ <span class="cstat-no" title="statement not covered" > if (!fs.existsSync(skillsDir)) continue</span>
1022
1240
  <span class="cstat-no" title="statement not covered" > const files = walkDir(skillsDir)</span>
1023
1241
  <span class="cstat-no" title="statement not covered" > for (const filePath of files) {</span>
1024
1242
  <span class="cstat-no" title="statement not covered" > const markdown = fs.readFileSync(filePath, "utf-8")</span>
@@ -1076,15 +1294,15 @@ const { spawnSync } = require("child_process")
1076
1294
  <span class="cstat-no" title="statement not covered" > writeJson(indexFile(), next)</span>
1077
1295
  <span class="cstat-no" title="statement not covered" > return next</span>
1078
1296
  <span class="cstat-no" title="statement not covered" >}</span>
1079
- &nbsp;
1080
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function listCatalogSkills(options = {}) {</span></span>
1297
+ <span class="cstat-no" title="statement not covered" ></span>
1298
+ <span class="cstat-no" title="statement not covered" >function listCatalogSkills(options = {}) {</span>
1081
1299
  <span class="cstat-no" title="statement not covered" > const idx = readIndex()</span>
1082
1300
  <span class="cstat-no" title="statement not covered" > let items = idx.skills || []</span>
1083
1301
  <span class="cstat-no" title="statement not covered" > if (options.provider) items = items.filter(s =&gt; s.provider === options.provider)</span>
1084
1302
  <span class="cstat-no" title="statement not covered" > return items.map(s =&gt; ({ id: s.id, name: s.name, description: s.description, provider: s.provider }))</span>
1085
1303
  <span class="cstat-no" title="statement not covered" >}</span>
1086
- &nbsp;
1087
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function searchCatalog(query, options = {}) {</span></span>
1304
+ <span class="cstat-no" title="statement not covered" ></span>
1305
+ <span class="cstat-no" title="statement not covered" >function searchCatalog(query, options = {}) {</span>
1088
1306
  <span class="cstat-no" title="statement not covered" > const q = String(query || "").trim().toLowerCase()</span>
1089
1307
  <span class="cstat-no" title="statement not covered" > if (!q) return []</span>
1090
1308
  <span class="cstat-no" title="statement not covered" > const items = listCatalogSkills(options)</span>
@@ -1094,8 +1312,8 @@ const { spawnSync } = require("child_process")
1094
1312
  <span class="cstat-no" title="statement not covered" > String(s.description || "").toLowerCase().includes(q)</span>
1095
1313
  <span class="cstat-no" title="statement not covered" > )</span>
1096
1314
  <span class="cstat-no" title="statement not covered" >}</span>
1097
- &nbsp;
1098
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function getCatalogSkill(providerId) {</span></span>
1315
+ <span class="cstat-no" title="statement not covered" ></span>
1316
+ <span class="cstat-no" title="statement not covered" >function getCatalogSkill(providerId) {</span>
1099
1317
  <span class="cstat-no" title="statement not covered" > const idx = readIndex()</span>
1100
1318
  <span class="cstat-no" title="statement not covered" > const hit = (idx.skills || []).find(s =&gt; s.id === providerId)</span>
1101
1319
  <span class="cstat-no" title="statement not covered" > if (!hit) return null</span>
@@ -1111,13 +1329,13 @@ const { spawnSync } = require("child_process")
1111
1329
  <span class="cstat-no" title="statement not covered" > if (!markdown) return null</span>
1112
1330
  <span class="cstat-no" title="statement not covered" > return { ...hit, markdown }</span>
1113
1331
  <span class="cstat-no" title="statement not covered" >}</span>
1114
- &nbsp;
1115
- &nbsp;
1116
- &nbsp;
1117
- /**
1118
- * Get catalog information with provider breakdown
1119
- */
1120
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function getCatalogInfo() {</span></span>
1332
+ <span class="cstat-no" title="statement not covered" ></span>
1333
+ <span class="cstat-no" title="statement not covered" ></span>
1334
+ <span class="cstat-no" title="statement not covered" ></span>
1335
+ <span class="cstat-no" title="statement not covered" >/**</span>
1336
+ <span class="cstat-no" title="statement not covered" > * Get catalog information with provider breakdown</span>
1337
+ <span class="cstat-no" title="statement not covered" > */</span>
1338
+ <span class="cstat-no" title="statement not covered" >function getCatalogInfo() {</span>
1121
1339
  <span class="cstat-no" title="statement not covered" > const idx = readIndex()</span>
1122
1340
  <span class="cstat-no" title="statement not covered" > const providers = listProviders()</span>
1123
1341
  <span class="cstat-no" title="statement not covered" > </span>
@@ -1136,15 +1354,22 @@ const { spawnSync } = require("child_process")
1136
1354
  <span class="cstat-no" title="statement not covered" > status = 'missing'</span>
1137
1355
  <span class="cstat-no" title="statement not covered" > details.error = 'Plugin directory not found'</span>
1138
1356
  <span class="cstat-no" title="statement not covered" > } else {</span>
1139
- <span class="cstat-no" title="statement not covered" > const skillsDir = path.join(pluginDir, 'skills')</span>
1140
- <span class="cstat-no" title="statement not covered" > if (fs.existsSync(skillsDir)) {</span>
1141
- <span class="cstat-no" title="statement not covered" > const files = walkDir(skillsDir)</span>
1142
- <span class="cstat-no" title="statement not covered" > skillsCount = files.length</span>
1357
+ <span class="cstat-no" title="statement not covered" > const skillsDirs = [</span>
1358
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, 'skills'),</span>
1359
+ <span class="cstat-no" title="statement not covered" > path.join(pluginDir, '.agents', 'skills')</span>
1360
+ <span class="cstat-no" title="statement not covered" > ]</span>
1361
+ <span class="cstat-no" title="statement not covered" > for (const skillsDir of skillsDirs) {</span>
1362
+ <span class="cstat-no" title="statement not covered" > if (fs.existsSync(skillsDir)) {</span>
1363
+ <span class="cstat-no" title="statement not covered" > const files = walkDir(skillsDir)</span>
1364
+ <span class="cstat-no" title="statement not covered" > skillsCount += files.length</span>
1365
+ <span class="cstat-no" title="statement not covered" > }</span>
1366
+ <span class="cstat-no" title="statement not covered" > }</span>
1367
+ <span class="cstat-no" title="statement not covered" > if (skillsCount &gt; 0) {</span>
1143
1368
  <span class="cstat-no" title="statement not covered" > details.plugin_dir = pluginDir</span>
1144
- <span class="cstat-no" title="statement not covered" > details.skills_dir = skillsDir</span>
1369
+ <span class="cstat-no" title="statement not covered" > details.skills_dirs = skillsDirs</span>
1145
1370
  <span class="cstat-no" title="statement not covered" > } else {</span>
1146
1371
  <span class="cstat-no" title="statement not covered" > status = 'no_skills_dir'</span>
1147
- <span class="cstat-no" title="statement not covered" > details.skills_dir = skillsDir</span>
1372
+ <span class="cstat-no" title="statement not covered" > details.skills_dirs = skillsDirs</span>
1148
1373
  <span class="cstat-no" title="statement not covered" > }</span>
1149
1374
  <span class="cstat-no" title="statement not covered" > }</span>
1150
1375
  <span class="cstat-no" title="statement not covered" > } else if (provider.type === 'local_fs' || provider.type === 'repo_fs') {</span>
@@ -1187,11 +1412,11 @@ const { spawnSync } = require("child_process")
1187
1412
  <span class="cstat-no" title="statement not covered" > }))</span>
1188
1413
  <span class="cstat-no" title="statement not covered" > }</span>
1189
1414
  <span class="cstat-no" title="statement not covered" >}</span>
1190
- &nbsp;
1191
- /**
1192
- * Describe all provider types with examples
1193
- */
1194
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function describeProviderTypes() {</span></span>
1415
+ <span class="cstat-no" title="statement not covered" ></span>
1416
+ <span class="cstat-no" title="statement not covered" >/**</span>
1417
+ <span class="cstat-no" title="statement not covered" > * Describe all provider types with examples</span>
1418
+ <span class="cstat-no" title="statement not covered" > */</span>
1419
+ <span class="cstat-no" title="statement not covered" >function describeProviderTypes() {</span>
1195
1420
  <span class="cstat-no" title="statement not covered" > return {</span>
1196
1421
  <span class="cstat-no" title="statement not covered" > provider_types: [</span>
1197
1422
  <span class="cstat-no" title="statement not covered" > {</span>
@@ -1236,21 +1461,21 @@ const { spawnSync } = require("child_process")
1236
1461
  <span class="cstat-no" title="statement not covered" > ]</span>
1237
1462
  <span class="cstat-no" title="statement not covered" > }</span>
1238
1463
  <span class="cstat-no" title="statement not covered" >}</span>
1239
- &nbsp;
1240
- &nbsp;
1241
- module.exports = {
1242
- listProviders,
1243
- addProvider,
1244
- removeProvider,
1245
- getProvider,
1246
- readIndex,
1247
- syncCatalog,
1248
- listCatalogSkills,
1249
- searchCatalog,
1250
- getCatalogSkill,
1251
- getCatalogInfo,
1252
- describeProviderTypes
1253
- }
1464
+ <span class="cstat-no" title="statement not covered" ></span>
1465
+ <span class="cstat-no" title="statement not covered" ></span>
1466
+ <span class="cstat-no" title="statement not covered" >module.exports = {</span>
1467
+ <span class="cstat-no" title="statement not covered" > listProviders,</span>
1468
+ <span class="cstat-no" title="statement not covered" > addProvider,</span>
1469
+ <span class="cstat-no" title="statement not covered" > removeProvider,</span>
1470
+ <span class="cstat-no" title="statement not covered" > getProvider,</span>
1471
+ <span class="cstat-no" title="statement not covered" > readIndex,</span>
1472
+ <span class="cstat-no" title="statement not covered" > syncCatalog,</span>
1473
+ <span class="cstat-no" title="statement not covered" > listCatalogSkills,</span>
1474
+ <span class="cstat-no" title="statement not covered" > searchCatalog,</span>
1475
+ <span class="cstat-no" title="statement not covered" > getCatalogSkill,</span>
1476
+ <span class="cstat-no" title="statement not covered" > getCatalogInfo,</span>
1477
+ <span class="cstat-no" title="statement not covered" > describeProviderTypes</span>
1478
+ <span class="cstat-no" title="statement not covered" >}</span>
1254
1479
  &nbsp;</pre></td></tr></table></pre>
1255
1480
 
1256
1481
  <div class='push'></div><!-- for sticky footer -->
@@ -1258,7 +1483,7 @@ module.exports = {
1258
1483
  <div class='footer quiet pad2 space-top1 center small'>
1259
1484
  Code coverage generated by
1260
1485
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1261
- at 2026-03-18T21:19:48.416Z
1486
+ at 2026-04-10T17:55:25.401Z
1262
1487
  </div>
1263
1488
  <script src="../prettify.js"></script>
1264
1489
  <script>