@claude-collective/cli 0.13.4 → 0.25.1
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/CHANGELOG.md +357 -0
- package/README.md +41 -27
- package/config/skills-matrix.yaml +202 -134
- package/config/stacks.yaml +14 -20
- package/dist/chunk-3X5D7RM5.js +69 -0
- package/dist/chunk-3X5D7RM5.js.map +1 -0
- package/dist/chunk-4S4FCAA2.js +100 -0
- package/dist/chunk-4S4FCAA2.js.map +1 -0
- package/dist/chunk-4WGN6SUE.js +197 -0
- package/dist/chunk-4WGN6SUE.js.map +1 -0
- package/dist/{chunk-DHET7RCE.js → chunk-AWKZ5BDL.js} +9 -2
- package/dist/{chunk-DHET7RCE.js.map → chunk-AWKZ5BDL.js.map} +1 -1
- package/dist/{chunk-6Q3Y7KVB.js → chunk-DBRUQQUF.js} +8 -2
- package/dist/chunk-DBRUQQUF.js.map +1 -0
- package/dist/{chunk-Z7G4B5HJ.js → chunk-ETCVEV3S.js} +73 -150
- package/dist/chunk-ETCVEV3S.js.map +1 -0
- package/dist/chunk-F4RD5FYM.js +45 -0
- package/dist/chunk-F4RD5FYM.js.map +1 -0
- package/dist/{chunk-ACNBKXXJ.js → chunk-GGFOD5PK.js} +13 -44
- package/dist/chunk-GGFOD5PK.js.map +1 -0
- package/dist/chunk-H7SSBSPR.js +29 -0
- package/dist/chunk-H7SSBSPR.js.map +1 -0
- package/dist/chunk-HWD32NP7.js +19 -0
- package/dist/chunk-HWD32NP7.js.map +1 -0
- package/dist/{chunk-JIPWV2FX.js → chunk-IAYAE6MG.js} +12 -34
- package/dist/chunk-IAYAE6MG.js.map +1 -0
- package/dist/{chunk-RTE64SJA.js → chunk-IXBCRT3F.js} +2 -2
- package/dist/chunk-IXBCRT3F.js.map +1 -0
- package/dist/chunk-KWYO3M5Q.js +67 -0
- package/dist/chunk-KWYO3M5Q.js.map +1 -0
- package/dist/{chunk-E3FJH4TF.js → chunk-MCTSHLAF.js} +18 -18
- package/dist/chunk-MCTSHLAF.js.map +1 -0
- package/dist/chunk-MH66WDFV.js +251 -0
- package/dist/chunk-MH66WDFV.js.map +1 -0
- package/dist/{chunk-K3NB6DSG.js → chunk-MTPM7BX5.js} +108 -110
- package/dist/chunk-MTPM7BX5.js.map +1 -0
- package/dist/chunk-NQJ47R4N.js +1092 -0
- package/dist/chunk-NQJ47R4N.js.map +1 -0
- package/dist/chunk-NRC7XYCI.js +211 -0
- package/dist/chunk-NRC7XYCI.js.map +1 -0
- package/dist/{chunk-76DWXGQE.js → chunk-O6ZTD7ZI.js} +14 -3
- package/dist/chunk-O6ZTD7ZI.js.map +1 -0
- package/dist/chunk-OBXAY23Y.js +56 -0
- package/dist/chunk-OBXAY23Y.js.map +1 -0
- package/dist/{chunk-XY3XDVMI.js → chunk-QR2EBWL2.js} +3 -3
- package/dist/{chunk-66UDJBF6.js → chunk-REJGRCVQ.js} +2 -2
- package/dist/{chunk-D237EVNB.js → chunk-TMED5DQ2.js} +71 -48
- package/dist/chunk-TMED5DQ2.js.map +1 -0
- package/dist/chunk-U7HFKR74.js +21 -0
- package/dist/chunk-U7HFKR74.js.map +1 -0
- package/dist/chunk-UEMRJI2K.js +146 -0
- package/dist/chunk-UEMRJI2K.js.map +1 -0
- package/dist/{chunk-Z2CWURZ6.js → chunk-UNN7523L.js} +2 -2
- package/dist/chunk-V2ZIH7HV.js +29 -0
- package/dist/chunk-V2ZIH7HV.js.map +1 -0
- package/dist/{chunk-X6QONICW.js → chunk-VVYNZZUX.js} +7 -19
- package/dist/chunk-VVYNZZUX.js.map +1 -0
- package/dist/chunk-WXS4S3MA.js +220 -0
- package/dist/chunk-WXS4S3MA.js.map +1 -0
- package/dist/{chunk-CDX4W4DM.js → chunk-XENOESJZ.js} +53 -33
- package/dist/chunk-XENOESJZ.js.map +1 -0
- package/dist/chunk-YDBSSAJ6.js +4207 -0
- package/dist/chunk-YDBSSAJ6.js.map +1 -0
- package/dist/chunk-ZDREFYD2.js +696 -0
- package/dist/chunk-ZDREFYD2.js.map +1 -0
- package/dist/chunk-ZW2PELOH.js +197 -0
- package/dist/chunk-ZW2PELOH.js.map +1 -0
- package/dist/cli/defaults/agent-mappings.yaml +13 -14
- package/dist/commands/build/marketplace.js +19 -23
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +13 -240
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +13 -25
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +45 -82
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +9 -9
- package/dist/commands/config/get.js.map +1 -1
- package/dist/commands/config/index.js +8 -8
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +7 -9
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/set-project.js +12 -13
- package/dist/commands/config/set-project.js.map +1 -1
- package/dist/commands/config/show.js +7 -7
- package/dist/commands/config/unset-project.js +12 -13
- package/dist/commands/config/unset-project.js.map +1 -1
- package/dist/commands/diff.js +15 -44
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +23 -67
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +98 -81
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +27 -79
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +38 -58
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +17 -24
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +103 -779
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +8 -11
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +11 -16
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/skill.js +14 -18
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +16 -97
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +24 -43
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +22 -30
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +23 -154
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +38 -89
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/version/bump.js +12 -28
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/version/index.js +8 -24
- package/dist/commands/version/index.js.map +1 -1
- package/dist/commands/version/set.js +11 -26
- package/dist/commands/version/set.js.map +1 -1
- package/dist/commands/version/show.js +8 -24
- package/dist/commands/version/show.js.map +1 -1
- package/dist/components/common/confirm.js +2 -2
- package/dist/components/common/confirm.test.js +203 -0
- package/dist/components/common/confirm.test.js.map +1 -0
- package/dist/components/common/message.js +3 -7
- package/dist/components/common/message.js.map +1 -1
- package/dist/components/common/spinner.js +1 -1
- package/dist/components/common/spinner.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +2 -2
- package/dist/components/wizard/category-grid.test.js +138 -156
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/menu-item.js +9 -0
- package/dist/components/wizard/search-modal.js +9 -0
- package/dist/components/wizard/search-modal.test.js +216 -0
- package/dist/components/wizard/search-modal.test.js.map +1 -0
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +16 -106
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/source-grid.js +10 -0
- package/dist/components/wizard/source-grid.js.map +1 -0
- package/dist/components/wizard/source-grid.test.js +500 -0
- package/dist/components/wizard/source-grid.test.js.map +1 -0
- package/dist/components/wizard/step-approach.js +7 -5
- package/dist/components/wizard/step-approach.test.js +115 -0
- package/dist/components/wizard/step-approach.test.js.map +1 -0
- package/dist/components/wizard/step-build.js +9 -5
- package/dist/components/wizard/step-build.test.js +160 -284
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +3 -3
- package/dist/components/wizard/step-confirm.test.js +364 -0
- package/dist/components/wizard/step-confirm.test.js.map +1 -0
- package/dist/components/wizard/step-refine.js +2 -3
- package/dist/components/wizard/step-refine.test.js +24 -26
- package/dist/components/wizard/step-refine.test.js.map +1 -1
- package/dist/components/wizard/step-settings.js +14 -0
- package/dist/components/wizard/step-settings.js.map +1 -0
- package/dist/components/wizard/step-settings.test.js +240 -0
- package/dist/components/wizard/step-settings.test.js.map +1 -0
- package/dist/components/wizard/step-sources.js +17 -0
- package/dist/components/wizard/step-sources.js.map +1 -0
- package/dist/components/wizard/step-sources.test.js +290 -0
- package/dist/components/wizard/step-sources.test.js.map +1 -0
- package/dist/components/wizard/step-stack.js +7 -4
- package/dist/components/wizard/step-stack.test.js +344 -0
- package/dist/components/wizard/step-stack.test.js.map +1 -0
- package/dist/components/wizard/view-title.js +9 -0
- package/dist/components/wizard/view-title.js.map +1 -0
- package/dist/components/wizard/wizard-layout.js +17 -0
- package/dist/components/wizard/wizard-layout.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +292 -0
- package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
- package/dist/components/wizard/wizard.js +22 -15
- package/dist/config/skills-matrix.yaml +202 -134
- package/dist/config/stacks.yaml +14 -20
- package/dist/hooks/init.js +6 -8
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{magic-string.es-RGXYGAW3.js → magic-string.es-PAH2SOTR.js} +2 -2
- package/dist/source-manager-DSYZEVGZ.js +16 -0
- package/dist/source-manager-DSYZEVGZ.js.map +1 -0
- package/dist/src/agents/developer/api-developer/agent.yaml +1 -1
- package/dist/src/agents/developer/cli-developer/agent.yaml +1 -1
- package/dist/src/agents/developer/web-architecture/agent.yaml +1 -1
- package/dist/src/agents/developer/web-developer/agent.yaml +1 -1
- package/dist/src/agents/developer/web-developer/examples.md +1 -6
- package/dist/src/agents/meta/agent-summoner/agent.yaml +1 -1
- package/dist/src/agents/meta/documentor/agent.yaml +1 -1
- package/dist/src/agents/meta/documentor/workflow.md +1 -5
- package/dist/src/agents/meta/skill-summoner/agent.yaml +1 -1
- package/dist/src/agents/migration/cli-migrator/agent.yaml +1 -1
- package/dist/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
- package/dist/src/agents/pattern/pattern-scout/agent.yaml +1 -1
- package/dist/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
- package/dist/src/agents/planning/web-pm/agent.yaml +1 -1
- package/dist/src/agents/researcher/api-researcher/agent.yaml +1 -1
- package/dist/src/agents/researcher/web-researcher/agent.yaml +1 -1
- package/dist/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
- package/dist/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
- package/dist/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
- package/dist/src/agents/tester/cli-tester/agent.yaml +1 -1
- package/dist/src/agents/tester/web-tester/agent.yaml +1 -1
- package/dist/src/agents/tester/web-tester/output-format.md +1 -3
- package/dist/stores/wizard-store.js +4 -3
- package/dist/stores/wizard-store.test.js +94 -88
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +5 -3
- package/src/agents/developer/api-developer/agent.yaml +1 -1
- package/src/agents/developer/cli-developer/agent.yaml +1 -1
- package/src/agents/developer/web-architecture/agent.yaml +1 -1
- package/src/agents/developer/web-developer/agent.yaml +1 -1
- package/src/agents/developer/web-developer/examples.md +1 -6
- package/src/agents/meta/agent-summoner/agent.yaml +1 -1
- package/src/agents/meta/documentor/agent.yaml +1 -1
- package/src/agents/meta/documentor/workflow.md +1 -5
- package/src/agents/meta/skill-summoner/agent.yaml +1 -1
- package/src/agents/migration/cli-migrator/agent.yaml +1 -1
- package/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
- package/src/agents/pattern/pattern-scout/agent.yaml +1 -1
- package/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
- package/src/agents/planning/web-pm/agent.yaml +1 -1
- package/src/agents/researcher/api-researcher/agent.yaml +1 -1
- package/src/agents/researcher/web-researcher/agent.yaml +1 -1
- package/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
- package/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
- package/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
- package/src/agents/tester/cli-tester/agent.yaml +1 -1
- package/src/agents/tester/web-tester/agent.yaml +1 -1
- package/src/agents/tester/web-tester/output-format.md +1 -3
- package/dist/chunk-3U3R4NCG.js +0 -22
- package/dist/chunk-3U3R4NCG.js.map +0 -1
- package/dist/chunk-4K4ZXQRM.js +0 -317
- package/dist/chunk-4K4ZXQRM.js.map +0 -1
- package/dist/chunk-6Q3Y7KVB.js.map +0 -1
- package/dist/chunk-76DWXGQE.js.map +0 -1
- package/dist/chunk-7Q44DMSP.js +0 -582
- package/dist/chunk-7Q44DMSP.js.map +0 -1
- package/dist/chunk-ACNBKXXJ.js.map +0 -1
- package/dist/chunk-B7CCVP6Q.js +0 -639
- package/dist/chunk-B7CCVP6Q.js.map +0 -1
- package/dist/chunk-BDLUZVKU.js +0 -54
- package/dist/chunk-BDLUZVKU.js.map +0 -1
- package/dist/chunk-CDX4W4DM.js.map +0 -1
- package/dist/chunk-D237EVNB.js.map +0 -1
- package/dist/chunk-DRXPNNPB.js +0 -393
- package/dist/chunk-DRXPNNPB.js.map +0 -1
- package/dist/chunk-E3FJH4TF.js.map +0 -1
- package/dist/chunk-ED4E6Q2T.js +0 -114
- package/dist/chunk-ED4E6Q2T.js.map +0 -1
- package/dist/chunk-EHS3TWWP.js +0 -95
- package/dist/chunk-EHS3TWWP.js.map +0 -1
- package/dist/chunk-GDH553MV.js +0 -91
- package/dist/chunk-GDH553MV.js.map +0 -1
- package/dist/chunk-HLJX2FTL.js +0 -95
- package/dist/chunk-HLJX2FTL.js.map +0 -1
- package/dist/chunk-I2DSLOXZ.js +0 -75
- package/dist/chunk-I2DSLOXZ.js.map +0 -1
- package/dist/chunk-I4TPKIYX.js +0 -493
- package/dist/chunk-I4TPKIYX.js.map +0 -1
- package/dist/chunk-IAUAQJQ2.js +0 -57
- package/dist/chunk-IAUAQJQ2.js.map +0 -1
- package/dist/chunk-IBE7JIAG.js +0 -129
- package/dist/chunk-IBE7JIAG.js.map +0 -1
- package/dist/chunk-IMDW5ZUP.js +0 -132
- package/dist/chunk-IMDW5ZUP.js.map +0 -1
- package/dist/chunk-JIPWV2FX.js.map +0 -1
- package/dist/chunk-K3NB6DSG.js.map +0 -1
- package/dist/chunk-K7EVM5LY.js +0 -141
- package/dist/chunk-K7EVM5LY.js.map +0 -1
- package/dist/chunk-KAAEN2PO.js +0 -57
- package/dist/chunk-KAAEN2PO.js.map +0 -1
- package/dist/chunk-NDY25DTL.js +0 -453
- package/dist/chunk-NDY25DTL.js.map +0 -1
- package/dist/chunk-P26A2K5N.js +0 -64
- package/dist/chunk-P26A2K5N.js.map +0 -1
- package/dist/chunk-RFTSZDHV.js +0 -313
- package/dist/chunk-RFTSZDHV.js.map +0 -1
- package/dist/chunk-RTE64SJA.js.map +0 -1
- package/dist/chunk-SVYPSDWY.js +0 -84
- package/dist/chunk-SVYPSDWY.js.map +0 -1
- package/dist/chunk-TKFPKEV3.js +0 -69
- package/dist/chunk-TKFPKEV3.js.map +0 -1
- package/dist/chunk-UQTEPWU7.js +0 -108
- package/dist/chunk-UQTEPWU7.js.map +0 -1
- package/dist/chunk-V46GGCCI.js +0 -294
- package/dist/chunk-V46GGCCI.js.map +0 -1
- package/dist/chunk-X6QONICW.js.map +0 -1
- package/dist/chunk-Y2LW7R3Y.js +0 -23
- package/dist/chunk-Y2LW7R3Y.js.map +0 -1
- package/dist/chunk-Z7G4B5HJ.js.map +0 -1
- package/dist/chunk-ZENYS6KW.js +0 -90
- package/dist/chunk-ZENYS6KW.js.map +0 -1
- package/dist/chunk-ZFPSUQOU.js +0 -396
- package/dist/chunk-ZFPSUQOU.js.map +0 -1
- package/dist/commands/config/set.js +0 -61
- package/dist/commands/config/set.js.map +0 -1
- package/dist/commands/config/unset.js +0 -57
- package/dist/commands/config/unset.js.map +0 -1
- package/dist/commands/test-imports.js +0 -92
- package/dist/commands/test-imports.js.map +0 -1
- package/dist/components/wizard/step-stack-options.js +0 -11
- package/dist/components/wizard/wizard-footer.js +0 -9
- /package/dist/{chunk-XY3XDVMI.js.map → chunk-QR2EBWL2.js.map} +0 -0
- /package/dist/{chunk-66UDJBF6.js.map → chunk-REJGRCVQ.js.map} +0 -0
- /package/dist/{chunk-Z2CWURZ6.js.map → chunk-UNN7523L.js.map} +0 -0
- /package/dist/components/wizard/{step-stack-options.js.map → menu-item.js.map} +0 -0
- /package/dist/components/wizard/{wizard-footer.js.map → search-modal.js.map} +0 -0
- /package/dist/{magic-string.es-RGXYGAW3.js.map → magic-string.es-PAH2SOTR.js.map} +0 -0
package/dist/commands/update.js
CHANGED
|
@@ -1,44 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
Confirm
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-IXBCRT3F.js";
|
|
5
5
|
import {
|
|
6
6
|
recompileAgents
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-DRXPNNPB.js";
|
|
9
|
-
import "../chunk-GDH553MV.js";
|
|
10
|
-
import "../chunk-I4TPKIYX.js";
|
|
11
|
-
import {
|
|
12
|
-
getCollectivePluginDir
|
|
13
|
-
} from "../chunk-ED4E6Q2T.js";
|
|
14
|
-
import "../chunk-ZFPSUQOU.js";
|
|
15
|
-
import {
|
|
16
|
-
hashFile
|
|
17
|
-
} from "../chunk-KAAEN2PO.js";
|
|
18
|
-
import {
|
|
19
|
-
loadSkillsMatrixFromSource
|
|
20
|
-
} from "../chunk-RFTSZDHV.js";
|
|
21
|
-
import "../chunk-B7CCVP6Q.js";
|
|
22
|
-
import "../chunk-IMDW5ZUP.js";
|
|
7
|
+
} from "../chunk-NRC7XYCI.js";
|
|
23
8
|
import {
|
|
24
9
|
BaseCommand,
|
|
25
10
|
EXIT_CODES
|
|
26
|
-
} from "../chunk-
|
|
27
|
-
import
|
|
28
|
-
|
|
11
|
+
} from "../chunk-OBXAY23Y.js";
|
|
12
|
+
import {
|
|
13
|
+
compareSkills,
|
|
14
|
+
getCollectivePluginDir,
|
|
15
|
+
injectForkedFromMetadata,
|
|
16
|
+
loadSkillsMatrixFromSource
|
|
17
|
+
} from "../chunk-YDBSSAJ6.js";
|
|
29
18
|
import {
|
|
30
19
|
copy,
|
|
31
|
-
fileExists
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
writeFile
|
|
35
|
-
} from "../chunk-TKFPKEV3.js";
|
|
20
|
+
fileExists
|
|
21
|
+
} from "../chunk-ZDREFYD2.js";
|
|
22
|
+
import "../chunk-HWD32NP7.js";
|
|
36
23
|
import {
|
|
37
24
|
LOCAL_SKILLS_PATH
|
|
38
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-O6ZTD7ZI.js";
|
|
39
26
|
import {
|
|
40
27
|
init_esm_shims
|
|
41
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-AWKZ5BDL.js";
|
|
42
29
|
|
|
43
30
|
// src/cli/commands/update.tsx
|
|
44
31
|
init_esm_shims();
|
|
@@ -46,109 +33,7 @@ import { render } from "ink";
|
|
|
46
33
|
import { Flags, Args } from "@oclif/core";
|
|
47
34
|
import { printTable } from "@oclif/table";
|
|
48
35
|
import path from "path";
|
|
49
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
50
36
|
import { jsx } from "react/jsx-runtime";
|
|
51
|
-
async function readForkedFromMetadata(skillDir) {
|
|
52
|
-
const metadataPath = path.join(skillDir, "metadata.yaml");
|
|
53
|
-
if (!await fileExists(metadataPath)) {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
const content = await readFile(metadataPath);
|
|
57
|
-
const metadata = parseYaml(content);
|
|
58
|
-
return metadata.forked_from ?? null;
|
|
59
|
-
}
|
|
60
|
-
async function getLocalSkillsWithMetadata(projectDir) {
|
|
61
|
-
const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);
|
|
62
|
-
const result = /* @__PURE__ */ new Map();
|
|
63
|
-
if (!await fileExists(localSkillsPath)) {
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
const skillDirs = await listDirectories(localSkillsPath);
|
|
67
|
-
for (const dirName of skillDirs) {
|
|
68
|
-
const skillDir = path.join(localSkillsPath, dirName);
|
|
69
|
-
const forkedFrom = await readForkedFromMetadata(skillDir);
|
|
70
|
-
const skillId = forkedFrom?.skill_id ?? dirName;
|
|
71
|
-
result.set(skillId, { dirName, forkedFrom });
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
async function computeSourceHash(sourcePath, skillPath) {
|
|
76
|
-
const skillMdPath = path.join(sourcePath, "src", skillPath, "SKILL.md");
|
|
77
|
-
if (!await fileExists(skillMdPath)) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
return hashFile(skillMdPath);
|
|
81
|
-
}
|
|
82
|
-
function getCurrentDate() {
|
|
83
|
-
return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
84
|
-
}
|
|
85
|
-
async function compareSkills(projectDir, sourcePath, sourceSkills) {
|
|
86
|
-
const results = [];
|
|
87
|
-
const localSkills = await getLocalSkillsWithMetadata(projectDir);
|
|
88
|
-
for (const [skillId, { dirName, forkedFrom }] of localSkills) {
|
|
89
|
-
if (!forkedFrom) {
|
|
90
|
-
results.push({
|
|
91
|
-
id: skillId,
|
|
92
|
-
localHash: null,
|
|
93
|
-
sourceHash: null,
|
|
94
|
-
status: "local-only",
|
|
95
|
-
dirName
|
|
96
|
-
});
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const localHash = forkedFrom.content_hash;
|
|
100
|
-
const sourceSkill = sourceSkills[forkedFrom.skill_id];
|
|
101
|
-
if (!sourceSkill) {
|
|
102
|
-
results.push({
|
|
103
|
-
id: forkedFrom.skill_id,
|
|
104
|
-
localHash,
|
|
105
|
-
sourceHash: null,
|
|
106
|
-
status: "local-only",
|
|
107
|
-
dirName
|
|
108
|
-
});
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);
|
|
112
|
-
if (sourceHash === null) {
|
|
113
|
-
results.push({
|
|
114
|
-
id: forkedFrom.skill_id,
|
|
115
|
-
localHash,
|
|
116
|
-
sourceHash: null,
|
|
117
|
-
status: "local-only",
|
|
118
|
-
dirName
|
|
119
|
-
});
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
const status = localHash === sourceHash ? "current" : "outdated";
|
|
123
|
-
results.push({
|
|
124
|
-
id: forkedFrom.skill_id,
|
|
125
|
-
localHash,
|
|
126
|
-
sourceHash,
|
|
127
|
-
status,
|
|
128
|
-
dirName,
|
|
129
|
-
sourcePath: sourceSkill.path
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
results.sort((a, b) => a.id.localeCompare(b.id));
|
|
133
|
-
return results;
|
|
134
|
-
}
|
|
135
|
-
async function updateForkedFromMetadata(skillDir, skillId, contentHash) {
|
|
136
|
-
const metadataPath = path.join(skillDir, "metadata.yaml");
|
|
137
|
-
const rawContent = await readFile(metadataPath);
|
|
138
|
-
const lines = rawContent.split("\n");
|
|
139
|
-
let yamlContent = rawContent;
|
|
140
|
-
if (lines[0]?.startsWith("# yaml-language-server:")) {
|
|
141
|
-
yamlContent = lines.slice(1).join("\n");
|
|
142
|
-
}
|
|
143
|
-
const metadata = parseYaml(yamlContent);
|
|
144
|
-
metadata.forked_from = {
|
|
145
|
-
skill_id: skillId,
|
|
146
|
-
content_hash: contentHash,
|
|
147
|
-
date: getCurrentDate()
|
|
148
|
-
};
|
|
149
|
-
const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });
|
|
150
|
-
await writeFile(metadataPath, newYamlContent);
|
|
151
|
-
}
|
|
152
37
|
async function updateSkill(skill, projectDir, sourceResult) {
|
|
153
38
|
if (!skill.sourcePath || !skill.sourceHash) {
|
|
154
39
|
return { success: false, newHash: null, error: "No source path available" };
|
|
@@ -158,7 +43,7 @@ async function updateSkill(skill, projectDir, sourceResult) {
|
|
|
158
43
|
const srcPath = path.join(sourceResult.sourcePath, "src", skill.sourcePath);
|
|
159
44
|
try {
|
|
160
45
|
await copy(srcPath, destPath);
|
|
161
|
-
await
|
|
46
|
+
await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);
|
|
162
47
|
return { success: true, newHash: skill.sourceHash };
|
|
163
48
|
} catch (error) {
|
|
164
49
|
return {
|
|
@@ -176,9 +61,7 @@ function findSkillByPartialMatch(skillName, results) {
|
|
|
176
61
|
return nameWithoutAuthor === skillName.toLowerCase();
|
|
177
62
|
});
|
|
178
63
|
if (partial) return partial;
|
|
179
|
-
const byDir = results.find(
|
|
180
|
-
(r) => r.dirName.toLowerCase() === skillName.toLowerCase()
|
|
181
|
-
);
|
|
64
|
+
const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());
|
|
182
65
|
if (byDir) return byDir;
|
|
183
66
|
return null;
|
|
184
67
|
}
|
|
@@ -190,10 +73,7 @@ function findSimilarSkills(skillName, results) {
|
|
|
190
73
|
return name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(" ")[0]);
|
|
191
74
|
}).map((r) => r.id).slice(0, 3);
|
|
192
75
|
}
|
|
193
|
-
var UpdateConfirm = ({
|
|
194
|
-
onConfirm,
|
|
195
|
-
onCancel
|
|
196
|
-
}) => {
|
|
76
|
+
var UpdateConfirm = ({ onConfirm, onCancel }) => {
|
|
197
77
|
return /* @__PURE__ */ jsx(
|
|
198
78
|
Confirm,
|
|
199
79
|
{
|
|
@@ -251,18 +131,13 @@ var Update = class _Update extends BaseCommand {
|
|
|
251
131
|
`Loaded from ${sourceResult.isLocal ? "local" : "remote"}: ${sourceResult.sourcePath}`
|
|
252
132
|
);
|
|
253
133
|
const sourceSkills = {};
|
|
254
|
-
for (const [skillId, skill] of Object.entries(
|
|
255
|
-
|
|
256
|
-
)) {
|
|
134
|
+
for (const [skillId, skill] of Object.entries(sourceResult.matrix.skills)) {
|
|
135
|
+
if (!skill) continue;
|
|
257
136
|
if (!skill.local) {
|
|
258
137
|
sourceSkills[skillId] = { path: skill.path };
|
|
259
138
|
}
|
|
260
139
|
}
|
|
261
|
-
const allResults = await compareSkills(
|
|
262
|
-
projectDir,
|
|
263
|
-
sourceResult.sourcePath,
|
|
264
|
-
sourceSkills
|
|
265
|
-
);
|
|
140
|
+
const allResults = await compareSkills(projectDir, sourceResult.sourcePath, sourceSkills);
|
|
266
141
|
let outdatedSkills = allResults.filter((r) => r.status === "outdated");
|
|
267
142
|
if (args.skill) {
|
|
268
143
|
const foundSkill = findSkillByPartialMatch(args.skill, allResults);
|
|
@@ -278,9 +153,7 @@ var Update = class _Update extends BaseCommand {
|
|
|
278
153
|
}
|
|
279
154
|
this.log("");
|
|
280
155
|
}
|
|
281
|
-
this.log(
|
|
282
|
-
`Run \`cc search ${args.skill}\` to search available skills.`
|
|
283
|
-
);
|
|
156
|
+
this.log(`Run \`cc search ${args.skill}\` to search available skills.`);
|
|
284
157
|
this.log("");
|
|
285
158
|
this.error("Skill not found", { exit: EXIT_CODES.ERROR });
|
|
286
159
|
}
|
|
@@ -295,9 +168,7 @@ var Update = class _Update extends BaseCommand {
|
|
|
295
168
|
}
|
|
296
169
|
if (foundSkill.status === "local-only") {
|
|
297
170
|
this.log("");
|
|
298
|
-
this.log(
|
|
299
|
-
`Skill "${foundSkill.id}" is a local-only skill (not forked from source).`
|
|
300
|
-
);
|
|
171
|
+
this.log(`Skill "${foundSkill.id}" is a local-only skill (not forked from source).`);
|
|
301
172
|
this.log("Cannot update local-only skills.");
|
|
302
173
|
this.log("");
|
|
303
174
|
return;
|
|
@@ -404,9 +275,7 @@ var Update = class _Update extends BaseCommand {
|
|
|
404
275
|
this.log("");
|
|
405
276
|
if (failed.length === 0) {
|
|
406
277
|
const agentMsg = recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : "";
|
|
407
|
-
this.logSuccess(
|
|
408
|
-
`Update complete! ${updated.length} skill(s) updated${agentMsg}.`
|
|
409
|
-
);
|
|
278
|
+
this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);
|
|
410
279
|
} else {
|
|
411
280
|
this.warn(
|
|
412
281
|
`Update finished with errors: ${updated.length} updated, ${failed.length} failed.`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { render } from \"ink\";\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n loadSkillsMatrixFromSource,\n type SourceLoadResult,\n} from \"../lib/source-loader.js\";\nimport { hashFile } from \"../lib/versioning.js\";\nimport { recompileAgents } from \"../lib/agent-recompiler.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n fileExists,\n readFile,\n writeFile,\n listDirectories,\n copy,\n} from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { getCollectivePluginDir } from \"../lib/plugin-finder.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\n/**\n * ForkedFrom metadata stored in local skill's metadata.yaml\n */\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\n/**\n * Local skill metadata structure\n */\ninterface LocalSkillMetadata {\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\n/**\n * Result of comparing a local skill to its source\n */\ninterface SkillComparisonResult {\n id: string;\n localHash: string | null;\n sourceHash: string | null;\n status: \"current\" | \"outdated\" | \"local-only\";\n dirName: string;\n sourcePath?: string;\n}\n\n/**\n * Read forked_from metadata from a local skill's metadata.yaml\n */\nasync function readForkedFromMetadata(\n skillDir: string,\n): Promise<ForkedFromMetadata | null> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const metadata = parseYaml(content) as LocalSkillMetadata;\n\n return metadata.forked_from ?? null;\n}\n\n/**\n * Get local skills with their forked_from metadata\n */\nasync function getLocalSkillsWithMetadata(\n projectDir: string,\n): Promise<\n Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>\n> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const result = new Map<\n string,\n { dirName: string; forkedFrom: ForkedFromMetadata | null }\n >();\n\n if (!(await fileExists(localSkillsPath))) {\n return result;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const dirName of skillDirs) {\n const skillDir = path.join(localSkillsPath, dirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n // Use the skill_id from forked_from if available, otherwise use directory name\n const skillId = forkedFrom?.skill_id ?? dirName;\n\n result.set(skillId, { dirName, forkedFrom });\n }\n\n return result;\n}\n\n/**\n * Compute source hash for a skill's SKILL.md file\n */\nasync function computeSourceHash(\n sourcePath: string,\n skillPath: string,\n): Promise<string | null> {\n const skillMdPath = path.join(sourcePath, \"src\", skillPath, \"SKILL.md\");\n\n if (!(await fileExists(skillMdPath))) {\n return null;\n }\n\n return hashFile(skillMdPath);\n}\n\n/**\n * Get the current date in ISO format (YYYY-MM-DD)\n */\nfunction getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\n/**\n * Compare local skills against source and determine status\n */\nasync function compareSkills(\n projectDir: string,\n sourcePath: string,\n sourceSkills: Record<string, { path: string }>,\n): Promise<SkillComparisonResult[]> {\n const results: SkillComparisonResult[] = [];\n const localSkills = await getLocalSkillsWithMetadata(projectDir);\n\n for (const [skillId, { dirName, forkedFrom }] of localSkills) {\n if (!forkedFrom) {\n // Local-only skill (no forked_from metadata)\n results.push({\n id: skillId,\n localHash: null,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const localHash = forkedFrom.content_hash;\n const sourceSkill = sourceSkills[forkedFrom.skill_id];\n\n if (!sourceSkill) {\n // Skill was forked from a source that no longer exists\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);\n\n if (sourceHash === null) {\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const status = localHash === sourceHash ? \"current\" : \"outdated\";\n\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash,\n status,\n dirName,\n sourcePath: sourceSkill.path,\n });\n }\n\n // Sort results by skill ID\n results.sort((a, b) => a.id.localeCompare(b.id));\n\n return results;\n}\n\n/**\n * Update forked_from metadata in a skill's metadata.yaml\n */\nasync function updateForkedFromMetadata(\n skillDir: string,\n skillId: string,\n contentHash: string,\n): Promise<void> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as LocalSkillMetadata;\n\n metadata.forked_from = {\n skill_id: skillId,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataPath, newYamlContent);\n}\n\n/**\n * Update a single skill from source\n */\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n // Copy skill files from source to local\n await copy(srcPath, destPath);\n\n // Update forked_from metadata\n await updateForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Find a skill by partial name match\n */\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n // Exact match first\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n // Partial match (skill name without author)\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n // Directory name match\n const byDir = results.find(\n (r) => r.dirName.toLowerCase() === skillName.toLowerCase(),\n );\n if (byDir) return byDir;\n\n return null;\n}\n\n/**\n * Find similar skill names for suggestions\n */\nfunction findSimilarSkills(\n skillName: string,\n results: SkillComparisonResult[],\n): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) ||\n dir.includes(lowered) ||\n lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\n/**\n * Confirmation component for update operation\n */\ninterface UpdateConfirmProps {\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({\n onConfirm,\n onCancel,\n}) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n // Check if local skills directory exists\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n return;\n }\n\n this.log(\"Loading skills...\");\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n // Build source skills map for lookup\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(\n sourceResult.matrix.skills,\n )) {\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Compare local skills against source\n const allResults = await compareSkills(\n projectDir,\n sourceResult.sourcePath,\n sourceSkills,\n );\n\n // Filter to just outdated skills\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n // Handle specific skill argument\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(\n `Run \\`cc search ${args.skill}\\` to search available skills.`,\n );\n this.log(\"\");\n this.error(\"Skill not found\", { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(\n `Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`,\n );\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n // Only update this specific skill\n outdatedSkills = [foundSkill];\n }\n\n // Check if there are any outdated skills\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(\"All skills are up to date.\");\n this.log(\"\");\n return;\n }\n\n // Show what will be updated\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n // Confirm unless --yes flag\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(\"No changes made.\");\n return;\n }\n }\n\n this.log(\"\");\n\n // Update each skill\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const result = await updateSkill(skill, projectDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n // Recompile agents if needed\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(\"Recompiling agents...\");\n\n try {\n const pluginDir = getCollectivePluginDir(projectDir);\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(\"No agents to recompile\");\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(\n `Could not recompile agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Final summary\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0\n ? `, ${recompiledAgents.length} agent(s) recompiled`\n : \"\";\n this.logSuccess(\n `Update complete! ${updated.length} skill(s) updated${agentMsg}.`,\n );\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\nimport { render } from \"ink\";\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { recompileAgents } from \"../lib/agents/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n compareSkills,\n injectForkedFromMetadata,\n type SkillComparisonResult,\n} from \"../lib/skills/index.js\";\nimport { fileExists, copy } from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { getCollectivePluginDir } from \"../lib/plugins/index.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n await copy(srcPath, destPath);\n await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());\n if (byDir) return byDir;\n\n return null;\n}\n\nfunction findSimilarSkills(skillName: string, results: SkillComparisonResult[]): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\ntype UpdateConfirmProps = {\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n return;\n }\n\n this.log(\"Loading skills...\");\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(sourceResult.matrix.skills)) {\n if (!skill) continue;\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n const allResults = await compareSkills(projectDir, sourceResult.sourcePath, sourceSkills);\n\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`cc search ${args.skill}\\` to search available skills.`);\n this.log(\"\");\n this.error(\"Skill not found\", { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n outdatedSkills = [foundSkill];\n }\n\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(\"All skills are up to date.\");\n this.log(\"\");\n return;\n }\n\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(\"No changes made.\");\n return;\n }\n }\n\n this.log(\"\");\n\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const result = await updateSkill(skill, projectDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(\"Recompiling agents...\");\n\n try {\n const pluginDir = getCollectivePluginDir(projectDir);\n const recompileResult = await recompileAgents({\n pluginDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(\"No agents to recompile\");\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(\n `Could not recompile agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
BaseCommand,
|
|
4
|
+
EXIT_CODES
|
|
5
|
+
} from "../chunk-OBXAY23Y.js";
|
|
6
|
+
import {
|
|
7
|
+
extractFrontmatter,
|
|
3
8
|
printPluginValidationResult,
|
|
4
9
|
validateAllPlugins,
|
|
5
10
|
validatePlugin
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import {
|
|
8
|
-
BaseCommand,
|
|
9
|
-
EXIT_CODES
|
|
10
|
-
} from "../chunk-EHS3TWWP.js";
|
|
11
|
+
} from "../chunk-YDBSSAJ6.js";
|
|
11
12
|
import {
|
|
13
|
+
agentYamlGenerationSchema,
|
|
12
14
|
fileExists,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
metadataValidationSchema,
|
|
16
|
+
readFile,
|
|
17
|
+
skillFrontmatterValidationSchema,
|
|
18
|
+
skillsMatrixConfigSchema,
|
|
19
|
+
stackConfigValidationSchema
|
|
20
|
+
} from "../chunk-ZDREFYD2.js";
|
|
21
|
+
import "../chunk-HWD32NP7.js";
|
|
22
|
+
import "../chunk-O6ZTD7ZI.js";
|
|
18
23
|
import {
|
|
19
24
|
init_esm_shims
|
|
20
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-AWKZ5BDL.js";
|
|
21
26
|
|
|
22
27
|
// src/cli/commands/validate.ts
|
|
23
28
|
init_esm_shims();
|
|
@@ -26,121 +31,66 @@ import path2 from "path";
|
|
|
26
31
|
|
|
27
32
|
// src/cli/lib/schema-validator.ts
|
|
28
33
|
init_esm_shims();
|
|
29
|
-
import
|
|
30
|
-
import addFormats from "ajv-formats";
|
|
34
|
+
import { sumBy } from "remeda";
|
|
31
35
|
import path from "path";
|
|
32
36
|
import { parse as parseYaml } from "yaml";
|
|
33
37
|
import fg from "fast-glob";
|
|
34
|
-
function extractFrontmatter(content) {
|
|
35
|
-
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
36
|
-
const match = content.match(frontmatterRegex);
|
|
37
|
-
if (!match || !match[1]) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
return parseYaml(match[1]);
|
|
42
|
-
} catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
38
|
var VALIDATION_TARGETS = [
|
|
47
39
|
{
|
|
48
40
|
name: "Skills Matrix",
|
|
49
|
-
schema:
|
|
41
|
+
schema: skillsMatrixConfigSchema,
|
|
50
42
|
pattern: "skills-matrix.yaml",
|
|
51
43
|
baseDir: "src/config"
|
|
52
44
|
},
|
|
53
45
|
{
|
|
54
46
|
name: "Skill Metadata",
|
|
55
|
-
schema:
|
|
47
|
+
schema: metadataValidationSchema,
|
|
56
48
|
pattern: "**/metadata.yaml",
|
|
57
49
|
baseDir: "src/skills"
|
|
58
50
|
},
|
|
59
51
|
{
|
|
60
52
|
name: "Stack Skill Metadata",
|
|
61
|
-
schema:
|
|
53
|
+
schema: metadataValidationSchema,
|
|
62
54
|
pattern: "**/skills/**/metadata.yaml",
|
|
63
55
|
baseDir: "src/stacks"
|
|
64
56
|
},
|
|
65
57
|
{
|
|
66
58
|
name: "Stack Config",
|
|
67
|
-
schema:
|
|
59
|
+
schema: stackConfigValidationSchema,
|
|
68
60
|
pattern: "*/config.yaml",
|
|
69
61
|
baseDir: "src/stacks"
|
|
70
62
|
},
|
|
71
63
|
{
|
|
72
64
|
name: "Agent Definition",
|
|
73
|
-
schema:
|
|
65
|
+
schema: agentYamlGenerationSchema,
|
|
74
66
|
pattern: "**/agent.yaml",
|
|
75
67
|
baseDir: "src/agents"
|
|
76
68
|
},
|
|
77
69
|
{
|
|
78
70
|
name: "Skill Frontmatter",
|
|
79
|
-
schema:
|
|
71
|
+
schema: skillFrontmatterValidationSchema,
|
|
80
72
|
pattern: "**/SKILL.md",
|
|
81
73
|
baseDir: "src/skills",
|
|
82
74
|
extractor: extractFrontmatter
|
|
83
75
|
},
|
|
84
76
|
{
|
|
85
77
|
name: "Stack Skill Frontmatter",
|
|
86
|
-
schema:
|
|
78
|
+
schema: skillFrontmatterValidationSchema,
|
|
87
79
|
pattern: "**/skills/**/SKILL.md",
|
|
88
80
|
baseDir: "src/stacks",
|
|
89
81
|
extractor: extractFrontmatter
|
|
90
82
|
}
|
|
91
83
|
];
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return schemaCache.get(cacheKey);
|
|
98
|
-
}
|
|
99
|
-
const locations = [
|
|
100
|
-
path.join(PROJECT_ROOT, "src", "schemas", schemaName),
|
|
101
|
-
path.join(rootDir, "src", "schemas", schemaName)
|
|
102
|
-
];
|
|
103
|
-
for (const schemaPath of locations) {
|
|
104
|
-
if (await fileExists(schemaPath)) {
|
|
105
|
-
const content = await readFile(schemaPath);
|
|
106
|
-
const schema = JSON.parse(content);
|
|
107
|
-
schemaCache.set(cacheKey, schema);
|
|
108
|
-
return schema;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
throw new Error(
|
|
112
|
-
`Schema not found: ${schemaName}. Searched: ${locations.join(", ")}`
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
async function getValidator(schemaName, rootDir = process.cwd()) {
|
|
116
|
-
const cacheKey = `${rootDir}:${schemaName}`;
|
|
117
|
-
if (validatorCache.has(cacheKey)) {
|
|
118
|
-
return validatorCache.get(cacheKey);
|
|
119
|
-
}
|
|
120
|
-
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
121
|
-
addFormats(ajv);
|
|
122
|
-
const schema = await loadSchema(schemaName, rootDir);
|
|
123
|
-
const validate = ajv.compile(schema);
|
|
124
|
-
validatorCache.set(cacheKey, validate);
|
|
125
|
-
return validate;
|
|
126
|
-
}
|
|
127
|
-
function formatAjvErrors(errors) {
|
|
128
|
-
if (!errors) return [];
|
|
129
|
-
return errors.map((err) => {
|
|
130
|
-
const errorPath = err.instancePath ? err.instancePath.replace(/^\//, "").replace(/\//g, ".") : "";
|
|
131
|
-
const message = err.message || "Unknown error";
|
|
132
|
-
if (err.keyword === "additionalProperties") {
|
|
133
|
-
const prop = err.params.additionalProperty;
|
|
134
|
-
return `Unrecognized key: "${prop}"`;
|
|
135
|
-
}
|
|
136
|
-
if (err.keyword === "enum") {
|
|
137
|
-
const allowed = err.params.allowedValues;
|
|
138
|
-
return errorPath ? `${errorPath}: ${message}. Allowed: ${allowed?.join(", ")}` : `${message}. Allowed: ${allowed?.join(", ")}`;
|
|
84
|
+
function formatZodErrors(error) {
|
|
85
|
+
return error.issues.map((issue) => {
|
|
86
|
+
const path3 = issue.path.join(".");
|
|
87
|
+
if (issue.code === "unrecognized_keys") {
|
|
88
|
+
return `Unrecognized key: "${issue.keys.join('", "')}"`;
|
|
139
89
|
}
|
|
140
|
-
return
|
|
90
|
+
return path3 ? `${path3}: ${issue.message}` : issue.message;
|
|
141
91
|
});
|
|
142
92
|
}
|
|
143
|
-
async function validateFile(filePath,
|
|
93
|
+
async function validateFile(filePath, schema, extractor) {
|
|
144
94
|
try {
|
|
145
95
|
if (!await fileExists(filePath)) {
|
|
146
96
|
return { valid: false, errors: [`File not found: ${filePath}`] };
|
|
@@ -158,11 +108,11 @@ async function validateFile(filePath, validate, extractor) {
|
|
|
158
108
|
} else {
|
|
159
109
|
parsed = parseYaml(content);
|
|
160
110
|
}
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
111
|
+
const result = schema.safeParse(parsed);
|
|
112
|
+
if (result.success) {
|
|
163
113
|
return { valid: true, errors: [] };
|
|
164
114
|
}
|
|
165
|
-
return { valid: false, errors:
|
|
115
|
+
return { valid: false, errors: formatZodErrors(result.error) };
|
|
166
116
|
} catch (error) {
|
|
167
117
|
const message = error instanceof Error ? error.message : String(error);
|
|
168
118
|
return { valid: false, errors: [`Failed to parse content: ${message}`] };
|
|
@@ -182,9 +132,8 @@ async function validateTarget(target, rootDir = process.cwd()) {
|
|
|
182
132
|
if (files.length === 0) {
|
|
183
133
|
return result;
|
|
184
134
|
}
|
|
185
|
-
const validate = await getValidator(target.schema, rootDir);
|
|
186
135
|
for (const file of files) {
|
|
187
|
-
const validation = await validateFile(file,
|
|
136
|
+
const validation = await validateFile(file, target.schema, target.extractor);
|
|
188
137
|
const relativePath = path.relative(rootDir, file);
|
|
189
138
|
if (validation.valid) {
|
|
190
139
|
result.validFiles++;
|
|
@@ -206,9 +155,9 @@ async function validateAllSchemas(rootDir = process.cwd()) {
|
|
|
206
155
|
}
|
|
207
156
|
const summary = {
|
|
208
157
|
totalSchemas: results.length,
|
|
209
|
-
totalFiles: results
|
|
210
|
-
validFiles: results
|
|
211
|
-
invalidFiles: results
|
|
158
|
+
totalFiles: sumBy(results, (r) => r.totalFiles),
|
|
159
|
+
validFiles: sumBy(results, (r) => r.validFiles),
|
|
160
|
+
invalidFiles: sumBy(results, (r) => r.invalidFiles.length)
|
|
212
161
|
};
|
|
213
162
|
return {
|
|
214
163
|
valid: results.every((r) => r.valid),
|