@agents-inc/cli 0.47.0 → 0.50.0
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 +39 -0
- package/README.md +113 -118
- package/config/skill-categories.yaml +344 -0
- package/config/skill-rules.yaml +740 -0
- package/config/stacks.yaml +0 -1
- package/dist/{chunk-CJFWO46A.js → chunk-26MXZUHU.js} +2 -2
- package/dist/{chunk-KQ27IDYL.js → chunk-2BWCR762.js} +2 -3
- package/dist/chunk-2BWCR762.js.map +1 -0
- package/dist/chunk-3VOL4WEG.js +31 -0
- package/dist/chunk-3VOL4WEG.js.map +1 -0
- package/dist/chunk-4QWDB2MD.js +571 -0
- package/dist/chunk-4QWDB2MD.js.map +1 -0
- package/dist/{chunk-LJ5E4GXC.js → chunk-4R52TQ3K.js} +2 -2
- package/dist/{chunk-SPSGZWTZ.js → chunk-5FCHJLM7.js} +34 -16
- package/dist/chunk-5FCHJLM7.js.map +1 -0
- package/dist/chunk-5FPIKTSA.js +40 -0
- package/dist/chunk-5FPIKTSA.js.map +1 -0
- package/dist/{chunk-HLTJK3XB.js → chunk-5L724R4C.js} +5 -6
- package/dist/{chunk-HLTJK3XB.js.map → chunk-5L724R4C.js.map} +1 -1
- package/dist/{chunk-JTTTXGHX.js → chunk-7LV4V6A4.js} +4 -4
- package/dist/{chunk-FTD5Z6QD.js → chunk-AWP5A6IM.js} +15 -7
- package/dist/chunk-AWP5A6IM.js.map +1 -0
- package/dist/chunk-C3Q43WLC.js +118 -0
- package/dist/chunk-C3Q43WLC.js.map +1 -0
- package/dist/{chunk-B4QYXVPZ.js → chunk-CMNKHDOX.js} +2 -2
- package/dist/{chunk-TBB3THSL.js → chunk-D72AFYQR.js} +8 -13
- package/dist/chunk-D72AFYQR.js.map +1 -0
- package/dist/{chunk-QR2TM4OY.js → chunk-DCE423KO.js} +46 -30
- package/dist/chunk-DCE423KO.js.map +1 -0
- package/dist/chunk-GBOW6FUW.js +74 -0
- package/dist/chunk-GBOW6FUW.js.map +1 -0
- package/dist/{chunk-GFDGYQ6M.js → chunk-HMSHB5EQ.js} +569 -269
- package/dist/chunk-HMSHB5EQ.js.map +1 -0
- package/dist/{chunk-NRCKIHND.js → chunk-HYEUETIC.js} +2 -2
- package/dist/{chunk-OEJDFGAF.js → chunk-I6IOGZSZ.js} +61 -52
- package/dist/chunk-I6IOGZSZ.js.map +1 -0
- package/dist/{chunk-3APMMQUA.js → chunk-JFF7P4LC.js} +30 -93
- package/dist/chunk-JFF7P4LC.js.map +1 -0
- package/dist/{chunk-N5OCAAXY.js → chunk-JWYRXE6C.js} +2 -2
- package/dist/{chunk-TWDVLTU6.js → chunk-KAO3LKB5.js} +3 -3
- package/dist/{chunk-XTRPYUWK.js → chunk-KQOU4POU.js} +26 -28
- package/dist/chunk-KQOU4POU.js.map +1 -0
- package/dist/{chunk-YTRFL3MR.js → chunk-M3GQ2R3E.js} +29 -28
- package/dist/chunk-M3GQ2R3E.js.map +1 -0
- package/dist/{chunk-LNA6M2IE.js → chunk-PGY5XROM.js} +2 -2
- package/dist/chunk-PGY5XROM.js.map +1 -0
- package/dist/{chunk-VAQJLHUW.js → chunk-QB5HHTAA.js} +8 -19
- package/dist/chunk-QB5HHTAA.js.map +1 -0
- package/dist/{chunk-VSZ5GDET.js → chunk-QYLCINGC.js} +2 -2
- package/dist/{chunk-IRJADQM7.js → chunk-RA2IPRO2.js} +2 -2
- package/dist/{chunk-DC333ZDC.js → chunk-RDWGYKDY.js} +4 -4
- package/dist/{chunk-FXQYEXLS.js → chunk-RFKDGJAJ.js} +26 -57
- package/dist/chunk-RFKDGJAJ.js.map +1 -0
- package/dist/{chunk-HPJP3HFD.js → chunk-SPFHPHYL.js} +7 -7
- package/dist/{chunk-EZ46ZTAQ.js → chunk-U2W5SENM.js} +3 -3
- package/dist/{chunk-MVEYK55V.js → chunk-U7X4V4HE.js} +2 -2
- package/dist/{chunk-INKJBMPJ.js → chunk-UAD3SC27.js} +4 -12
- package/dist/chunk-UAD3SC27.js.map +1 -0
- package/dist/{chunk-C4QI54PN.js → chunk-WBHPCBVN.js} +57 -34
- package/dist/chunk-WBHPCBVN.js.map +1 -0
- package/dist/chunk-WFFV254H.js +314 -0
- package/dist/chunk-WFFV254H.js.map +1 -0
- package/dist/{chunk-ZWAL2ZY7.js → chunk-WJHFV6RI.js} +3 -2
- package/dist/chunk-WJHFV6RI.js.map +1 -0
- package/dist/{chunk-2RQYJFKA.js → chunk-WLZHCM7O.js} +2 -2
- package/dist/{chunk-DVW6ASTO.js → chunk-XDSVV5GZ.js} +4 -4
- package/dist/{chunk-JZHIF3K7.js → chunk-YDYRAXSY.js} +57 -27
- package/dist/chunk-YDYRAXSY.js.map +1 -0
- package/dist/commands/build/marketplace.js +4 -4
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +11 -9
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +4 -4
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/set-project.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/config/unset-project.js +4 -4
- package/dist/commands/diff.js +4 -4
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/edit.js +58 -52
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +4 -4
- package/dist/commands/import/skill.js +7 -8
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +5 -5
- package/dist/commands/init.js +40 -435
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +4 -4
- package/dist/commands/new/agent.js +11 -10
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +24 -5
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +15 -209
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +11 -7
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +7 -8
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +6 -6
- package/dist/commands/update.js +6 -6
- package/dist/commands/validate.js +62 -250
- package/dist/commands/validate.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +3 -2
- package/dist/components/wizard/category-grid.test.js +112 -58
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/checkbox-grid.js +5 -3
- package/dist/components/wizard/checkbox-grid.test.js +5 -4
- package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
- package/dist/components/wizard/domain-selection.js +11 -9
- package/dist/components/wizard/help-modal.js +2 -2
- package/dist/components/wizard/menu-item.js +1 -1
- package/dist/components/wizard/search-modal.js +2 -2
- package/dist/components/wizard/search-modal.test.js +2 -2
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +2 -2
- package/dist/components/wizard/selection-card.js +2 -2
- package/dist/components/wizard/source-grid.js +4 -3
- package/dist/components/wizard/source-grid.test.js +4 -3
- package/dist/components/wizard/source-grid.test.js.map +1 -1
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -8
- package/dist/components/wizard/step-agents.test.js +18 -17
- package/dist/components/wizard/step-agents.test.js.map +1 -1
- package/dist/components/wizard/step-build.js +9 -8
- package/dist/components/wizard/step-build.test.js +17 -35
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +4 -4
- package/dist/components/wizard/step-confirm.test.js +8 -8
- package/dist/components/wizard/step-refine.js +2 -2
- package/dist/components/wizard/step-refine.test.js +2 -2
- package/dist/components/wizard/step-settings.js +7 -5
- package/dist/components/wizard/step-settings.test.js +10 -8
- package/dist/components/wizard/step-settings.test.js.map +1 -1
- package/dist/components/wizard/step-sources.js +11 -10
- package/dist/components/wizard/step-sources.test.js +12 -11
- package/dist/components/wizard/step-sources.test.js.map +1 -1
- package/dist/components/wizard/step-stack.js +15 -12
- package/dist/components/wizard/step-stack.test.js +16 -13
- package/dist/components/wizard/step-stack.test.js.map +1 -1
- package/dist/components/wizard/view-title.js +2 -2
- package/dist/components/wizard/wizard-layout.js +8 -8
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +2 -2
- package/dist/components/wizard/wizard.js +27 -25
- package/dist/config/skill-categories.yaml +344 -0
- package/dist/config/skill-rules.yaml +740 -0
- package/dist/config/stacks.yaml +0 -1
- package/dist/hooks/init.js +55 -3
- package/dist/hooks/init.js.map +1 -1
- package/dist/{source-manager-Q34LTUVM.js → source-manager-BVB2SG73.js} +4 -4
- package/dist/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
- package/dist/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
- package/dist/src/agents/meta/agent-summoner/examples.md +2 -2
- package/dist/src/agents/meta/agent-summoner/output-format.md +1 -1
- package/dist/src/agents/meta/agent-summoner/workflow.md +5 -7
- package/{src/agents/meta/documentor/agent.yaml → dist/src/agents/meta/documentor/metadata.yaml} +1 -0
- package/dist/stores/wizard-store.js +5 -5
- package/dist/stores/wizard-store.test.js +79 -27
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +5 -1
- package/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
- package/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
- package/src/agents/meta/agent-summoner/examples.md +2 -2
- package/src/agents/meta/agent-summoner/output-format.md +1 -1
- package/src/agents/meta/agent-summoner/workflow.md +5 -7
- package/{dist/src/agents/meta/documentor/agent.yaml → src/agents/meta/documentor/metadata.yaml} +1 -0
- package/src/schemas/agent.schema.json +1 -1
- package/src/schemas/metadata.schema.json +2 -5
- package/src/schemas/project-config.schema.json +0 -3
- package/src/schemas/project-source-config.schema.json +4 -1
- package/config/skills-matrix.yaml +0 -918
- package/dist/chunk-3APMMQUA.js.map +0 -1
- package/dist/chunk-C4QI54PN.js.map +0 -1
- package/dist/chunk-FMQ3A7W4.js +0 -29
- package/dist/chunk-FMQ3A7W4.js.map +0 -1
- package/dist/chunk-FTD5Z6QD.js.map +0 -1
- package/dist/chunk-FXQYEXLS.js.map +0 -1
- package/dist/chunk-GFDGYQ6M.js.map +0 -1
- package/dist/chunk-INKJBMPJ.js.map +0 -1
- package/dist/chunk-JZHIF3K7.js.map +0 -1
- package/dist/chunk-KQ27IDYL.js.map +0 -1
- package/dist/chunk-LNA6M2IE.js.map +0 -1
- package/dist/chunk-M4P5YJ45.js +0 -99
- package/dist/chunk-M4P5YJ45.js.map +0 -1
- package/dist/chunk-OEJDFGAF.js.map +0 -1
- package/dist/chunk-QR2TM4OY.js.map +0 -1
- package/dist/chunk-SPSGZWTZ.js.map +0 -1
- package/dist/chunk-TBB3THSL.js.map +0 -1
- package/dist/chunk-VAQJLHUW.js.map +0 -1
- package/dist/chunk-XTRPYUWK.js.map +0 -1
- package/dist/chunk-YTRFL3MR.js.map +0 -1
- package/dist/chunk-ZWAL2ZY7.js.map +0 -1
- package/dist/config/skills-matrix.yaml +0 -918
- package/dist/src/agents/migration/cli-migrator/agent.yaml +0 -12
- package/dist/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
- package/dist/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
- package/dist/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
- package/dist/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
- package/dist/src/agents/migration/cli-migrator/intro.md +0 -15
- package/dist/src/agents/migration/cli-migrator/output-format.md +0 -164
- package/dist/src/agents/migration/cli-migrator/workflow.md +0 -230
- package/src/agents/migration/cli-migrator/agent.yaml +0 -12
- package/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
- package/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
- package/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
- package/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
- package/src/agents/migration/cli-migrator/intro.md +0 -15
- package/src/agents/migration/cli-migrator/output-format.md +0 -164
- package/src/agents/migration/cli-migrator/workflow.md +0 -230
- package/src/schemas/skills-matrix.schema.json +0 -179
- /package/dist/{chunk-CJFWO46A.js.map → chunk-26MXZUHU.js.map} +0 -0
- /package/dist/{chunk-LJ5E4GXC.js.map → chunk-4R52TQ3K.js.map} +0 -0
- /package/dist/{chunk-JTTTXGHX.js.map → chunk-7LV4V6A4.js.map} +0 -0
- /package/dist/{chunk-B4QYXVPZ.js.map → chunk-CMNKHDOX.js.map} +0 -0
- /package/dist/{chunk-NRCKIHND.js.map → chunk-HYEUETIC.js.map} +0 -0
- /package/dist/{chunk-N5OCAAXY.js.map → chunk-JWYRXE6C.js.map} +0 -0
- /package/dist/{chunk-TWDVLTU6.js.map → chunk-KAO3LKB5.js.map} +0 -0
- /package/dist/{chunk-VSZ5GDET.js.map → chunk-QYLCINGC.js.map} +0 -0
- /package/dist/{chunk-IRJADQM7.js.map → chunk-RA2IPRO2.js.map} +0 -0
- /package/dist/{chunk-DC333ZDC.js.map → chunk-RDWGYKDY.js.map} +0 -0
- /package/dist/{chunk-HPJP3HFD.js.map → chunk-SPFHPHYL.js.map} +0 -0
- /package/dist/{chunk-EZ46ZTAQ.js.map → chunk-U2W5SENM.js.map} +0 -0
- /package/dist/{chunk-MVEYK55V.js.map → chunk-U7X4V4HE.js.map} +0 -0
- /package/dist/{chunk-2RQYJFKA.js.map → chunk-WLZHCM7O.js.map} +0 -0
- /package/dist/{chunk-DVW6ASTO.js.map → chunk-XDSVV5GZ.js.map} +0 -0
- /package/dist/{source-manager-Q34LTUVM.js.map → source-manager-BVB2SG73.js.map} +0 -0
- /package/dist/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
agentFrontmatterValidationSchema,
|
|
10
10
|
agentNameSchema,
|
|
11
11
|
agentYamlConfigSchema,
|
|
12
|
+
agentYamlGenerationSchema,
|
|
12
13
|
categoryPathSchema,
|
|
13
14
|
copy,
|
|
14
15
|
directoryExists,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
localSkillMetadataSchema,
|
|
27
28
|
log,
|
|
28
29
|
marketplaceSchema,
|
|
30
|
+
metadataValidationSchema,
|
|
29
31
|
pluginAuthorSchema,
|
|
30
32
|
pluginManifestSchema,
|
|
31
33
|
projectConfigLoaderSchema,
|
|
@@ -34,19 +36,21 @@ import {
|
|
|
34
36
|
readFileOptional,
|
|
35
37
|
readFileSafe,
|
|
36
38
|
remove,
|
|
39
|
+
skillCategoriesFileSchema,
|
|
37
40
|
skillDisplayNameSchema,
|
|
38
41
|
skillFrontmatterLoaderSchema,
|
|
39
42
|
skillFrontmatterValidationSchema,
|
|
40
43
|
skillIdSchema,
|
|
41
44
|
skillMetadataLoaderSchema,
|
|
42
|
-
|
|
45
|
+
skillRulesFileSchema,
|
|
46
|
+
stackConfigValidationSchema,
|
|
43
47
|
stacksConfigSchema,
|
|
44
48
|
validateNestingDepth,
|
|
45
49
|
verbose,
|
|
46
50
|
warn,
|
|
47
51
|
warnUnknownFields,
|
|
48
52
|
writeFile
|
|
49
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-WBHPCBVN.js";
|
|
50
54
|
import {
|
|
51
55
|
ARCHIVED_SKILLS_DIR_NAME,
|
|
52
56
|
CACHE_DIR,
|
|
@@ -74,13 +78,14 @@ import {
|
|
|
74
78
|
PROJECT_ROOT,
|
|
75
79
|
SCHEMA_PATHS,
|
|
76
80
|
SKILLS_DIR_PATH,
|
|
77
|
-
|
|
81
|
+
SKILL_CATEGORIES_YAML_PATH,
|
|
82
|
+
SKILL_RULES_YAML_PATH,
|
|
78
83
|
STACKS_FILE_PATH,
|
|
79
84
|
STANDARD_DIRS,
|
|
80
85
|
STANDARD_FILES,
|
|
81
86
|
YAML_FORMATTING,
|
|
82
87
|
yamlSchemaComment
|
|
83
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-AWP5A6IM.js";
|
|
84
89
|
import {
|
|
85
90
|
init_esm_shims
|
|
86
91
|
} from "./chunk-DHET7RCE.js";
|
|
@@ -90,6 +95,7 @@ init_esm_shims();
|
|
|
90
95
|
|
|
91
96
|
// src/cli/lib/configuration/config.ts
|
|
92
97
|
init_esm_shims();
|
|
98
|
+
import os from "os";
|
|
93
99
|
import path from "path";
|
|
94
100
|
import { stringify as stringifyYaml } from "yaml";
|
|
95
101
|
|
|
@@ -137,6 +143,18 @@ async function loadProjectSourceConfig(projectDir) {
|
|
|
137
143
|
verbose(`Loaded project config from ${configPath}`);
|
|
138
144
|
return data;
|
|
139
145
|
}
|
|
146
|
+
async function loadGlobalSourceConfig() {
|
|
147
|
+
const homeDir = os.homedir();
|
|
148
|
+
const globalConfigPath = path.join(homeDir, CLAUDE_SRC_DIR, PROJECT_CONFIG_FILE);
|
|
149
|
+
if (!await fileExists(globalConfigPath)) {
|
|
150
|
+
verbose(`Global config not found at ${globalConfigPath}`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const data = await safeLoadYamlFile(globalConfigPath, projectSourceConfigSchema);
|
|
154
|
+
if (!data) return null;
|
|
155
|
+
verbose(`Loaded global config from ${globalConfigPath}`);
|
|
156
|
+
return data;
|
|
157
|
+
}
|
|
140
158
|
async function saveProjectConfig(projectDir, config) {
|
|
141
159
|
const configPath = getProjectConfigPath(projectDir);
|
|
142
160
|
await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));
|
|
@@ -146,9 +164,13 @@ async function saveProjectConfig(projectDir, config) {
|
|
|
146
164
|
await writeFile(configPath, `${schemaComment}${content}`);
|
|
147
165
|
verbose(`Saved project config to ${configPath}`);
|
|
148
166
|
}
|
|
149
|
-
async function
|
|
167
|
+
async function loadEffectiveSourceConfig(projectDir) {
|
|
150
168
|
const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;
|
|
151
|
-
|
|
169
|
+
return projectConfig ?? await loadGlobalSourceConfig();
|
|
170
|
+
}
|
|
171
|
+
async function resolveSource(flagValue, projectDir) {
|
|
172
|
+
const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
|
|
173
|
+
const marketplace = effectiveConfig?.marketplace;
|
|
152
174
|
if (flagValue !== void 0) {
|
|
153
175
|
if (flagValue === "" || flagValue.trim() === "") {
|
|
154
176
|
throw new Error(
|
|
@@ -178,10 +200,10 @@ ${message}`
|
|
|
178
200
|
}
|
|
179
201
|
}
|
|
180
202
|
}
|
|
181
|
-
if (
|
|
182
|
-
verbose(`Source from project config: ${
|
|
203
|
+
if (effectiveConfig?.source) {
|
|
204
|
+
verbose(`Source from project config: ${effectiveConfig.source}`);
|
|
183
205
|
return {
|
|
184
|
-
source:
|
|
206
|
+
source: effectiveConfig.source,
|
|
185
207
|
sourceOrigin: "project",
|
|
186
208
|
marketplace
|
|
187
209
|
};
|
|
@@ -200,11 +222,11 @@ async function resolveAgentsSource(flagValue, projectDir) {
|
|
|
200
222
|
verbose(`Agents source from --agent-source flag: ${flagValue}`);
|
|
201
223
|
return { agentsSource: flagValue, agentsSourceOrigin: "flag" };
|
|
202
224
|
}
|
|
203
|
-
const
|
|
204
|
-
if (
|
|
205
|
-
verbose(`Agents source from project config: ${
|
|
225
|
+
const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
|
|
226
|
+
if (effectiveConfig?.agentsSource) {
|
|
227
|
+
verbose(`Agents source from project config: ${effectiveConfig.agentsSource}`);
|
|
206
228
|
return {
|
|
207
|
-
agentsSource:
|
|
229
|
+
agentsSource: effectiveConfig.agentsSource,
|
|
208
230
|
agentsSourceOrigin: "project"
|
|
209
231
|
};
|
|
210
232
|
}
|
|
@@ -237,11 +259,11 @@ function formatOrigin(type, origin) {
|
|
|
237
259
|
return origin;
|
|
238
260
|
}
|
|
239
261
|
async function resolveAuthor(projectDir) {
|
|
240
|
-
const
|
|
241
|
-
return
|
|
262
|
+
const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
|
|
263
|
+
return effectiveConfig?.author;
|
|
242
264
|
}
|
|
243
265
|
async function resolveAllSources(projectDir) {
|
|
244
|
-
const
|
|
266
|
+
const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
|
|
245
267
|
const resolvedConfig = await resolveSource(void 0, projectDir);
|
|
246
268
|
const primary = {
|
|
247
269
|
name: "marketplace",
|
|
@@ -250,8 +272,8 @@ async function resolveAllSources(projectDir) {
|
|
|
250
272
|
};
|
|
251
273
|
const extras = [];
|
|
252
274
|
const seenNames = /* @__PURE__ */ new Set();
|
|
253
|
-
if (
|
|
254
|
-
for (const source of
|
|
275
|
+
if (effectiveConfig?.sources) {
|
|
276
|
+
for (const source of effectiveConfig.sources) {
|
|
255
277
|
if (!seenNames.has(source.name)) {
|
|
256
278
|
seenNames.add(source.name);
|
|
257
279
|
extras.push(source);
|
|
@@ -418,7 +440,7 @@ function isLocalSource(source) {
|
|
|
418
440
|
init_esm_shims();
|
|
419
441
|
import { createHash } from "crypto";
|
|
420
442
|
import { downloadTemplate } from "giget";
|
|
421
|
-
import
|
|
443
|
+
import os3 from "os";
|
|
422
444
|
import path4 from "path";
|
|
423
445
|
|
|
424
446
|
// src/cli/lib/configuration/index.ts
|
|
@@ -533,6 +555,7 @@ import { difference } from "remeda";
|
|
|
533
555
|
|
|
534
556
|
// src/cli/lib/configuration/project-config.ts
|
|
535
557
|
init_esm_shims();
|
|
558
|
+
import os2 from "os";
|
|
536
559
|
import path3 from "path";
|
|
537
560
|
|
|
538
561
|
// src/cli/lib/stacks/stacks-loader.ts
|
|
@@ -629,7 +652,7 @@ function getStackSkillIds(stack) {
|
|
|
629
652
|
// src/cli/lib/configuration/project-config.ts
|
|
630
653
|
var CONFIG_PATH = `${CLAUDE_SRC_DIR}/config.yaml`;
|
|
631
654
|
var LEGACY_CONFIG_PATH = `${CLAUDE_DIR}/config.yaml`;
|
|
632
|
-
async function
|
|
655
|
+
async function loadProjectConfigFromDir(projectDir) {
|
|
633
656
|
const srcConfigPath = path3.join(projectDir, CONFIG_PATH);
|
|
634
657
|
const legacyConfigPath = path3.join(projectDir, LEGACY_CONFIG_PATH);
|
|
635
658
|
let configPath = srcConfigPath;
|
|
@@ -666,6 +689,15 @@ async function loadProjectConfig(projectDir) {
|
|
|
666
689
|
configPath
|
|
667
690
|
};
|
|
668
691
|
}
|
|
692
|
+
async function loadProjectConfig(projectDir) {
|
|
693
|
+
const projectResult = await loadProjectConfigFromDir(projectDir);
|
|
694
|
+
if (projectResult) return projectResult;
|
|
695
|
+
const homeDir = os2.homedir();
|
|
696
|
+
if (projectDir !== homeDir) {
|
|
697
|
+
return loadProjectConfigFromDir(homeDir);
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
669
701
|
function validateProjectConfig(config) {
|
|
670
702
|
const errors = [];
|
|
671
703
|
const warnings = [];
|
|
@@ -803,7 +835,7 @@ function getGigetCacheDir(source) {
|
|
|
803
835
|
return void 0;
|
|
804
836
|
}
|
|
805
837
|
const templateName = uriMatch.groups.repo.replace("/", "-").replace(/[^\da-z-]/gi, "-");
|
|
806
|
-
const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path4.resolve(process.env.XDG_CACHE_HOME, "giget") : path4.resolve(
|
|
838
|
+
const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path4.resolve(process.env.XDG_CACHE_HOME, "giget") : path4.resolve(os3.homedir(), ".cache", "giget");
|
|
807
839
|
return path4.join(gigetCacheRoot, providerName, templateName);
|
|
808
840
|
}
|
|
809
841
|
async function clearGigetCache(source) {
|
|
@@ -977,8 +1009,8 @@ Too many plugins: ${marketplace.plugins.length} (limit: ${MAX_MARKETPLACE_PLUGIN
|
|
|
977
1009
|
|
|
978
1010
|
// src/cli/lib/skills/local-skill-loader.ts
|
|
979
1011
|
init_esm_shims();
|
|
980
|
-
import { parse as
|
|
981
|
-
import
|
|
1012
|
+
import { parse as parseYaml9 } from "yaml";
|
|
1013
|
+
import path23 from "path";
|
|
982
1014
|
|
|
983
1015
|
// src/cli/lib/loading/index.ts
|
|
984
1016
|
init_esm_shims();
|
|
@@ -1004,7 +1036,7 @@ function parseFrontmatter(content, filePath) {
|
|
|
1004
1036
|
async function loadAllAgents(projectRoot) {
|
|
1005
1037
|
const agents = {};
|
|
1006
1038
|
const agentSourcesDir = path5.join(projectRoot, DIRS.agents);
|
|
1007
|
-
const files = await glob(
|
|
1039
|
+
const files = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, agentSourcesDir);
|
|
1008
1040
|
for (const file of files) {
|
|
1009
1041
|
const fullPath = path5.join(agentSourcesDir, file);
|
|
1010
1042
|
try {
|
|
@@ -1022,7 +1054,7 @@ async function loadAllAgents(projectRoot) {
|
|
|
1022
1054
|
};
|
|
1023
1055
|
verbose(`Loaded agent: ${config.id} from ${file}`);
|
|
1024
1056
|
} catch (error) {
|
|
1025
|
-
warn(`Skipping invalid
|
|
1057
|
+
warn(`Skipping invalid metadata.yaml at '${fullPath}': ${getErrorMessage(error)}`);
|
|
1026
1058
|
}
|
|
1027
1059
|
}
|
|
1028
1060
|
return agents;
|
|
@@ -1034,7 +1066,7 @@ async function loadProjectAgents(projectRoot) {
|
|
|
1034
1066
|
verbose(`No project agents directory at ${projectAgentsDir}`);
|
|
1035
1067
|
return agents;
|
|
1036
1068
|
}
|
|
1037
|
-
const files = await glob(
|
|
1069
|
+
const files = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, projectAgentsDir);
|
|
1038
1070
|
for (const file of files) {
|
|
1039
1071
|
const fullPath = path5.join(projectAgentsDir, file);
|
|
1040
1072
|
try {
|
|
@@ -1054,7 +1086,7 @@ async function loadProjectAgents(projectRoot) {
|
|
|
1054
1086
|
};
|
|
1055
1087
|
verbose(`Loaded project agent: ${config.id} from ${file}`);
|
|
1056
1088
|
} catch (error) {
|
|
1057
|
-
warn(`Skipping invalid
|
|
1089
|
+
warn(`Skipping invalid metadata.yaml at '${fullPath}': ${getErrorMessage(error)}`);
|
|
1058
1090
|
}
|
|
1059
1091
|
}
|
|
1060
1092
|
return agents;
|
|
@@ -1159,13 +1191,14 @@ async function loadPluginSkills(pluginDir) {
|
|
|
1159
1191
|
|
|
1160
1192
|
// src/cli/lib/loading/source-loader.ts
|
|
1161
1193
|
init_esm_shims();
|
|
1162
|
-
import
|
|
1194
|
+
import os6 from "os";
|
|
1195
|
+
import path22 from "path";
|
|
1163
1196
|
import { unique as unique4 } from "remeda";
|
|
1164
1197
|
|
|
1165
1198
|
// src/cli/lib/metadata-keys.ts
|
|
1166
1199
|
init_esm_shims();
|
|
1167
1200
|
var METADATA_KEYS = {
|
|
1168
|
-
|
|
1201
|
+
DISPLAY_NAME: "displayName",
|
|
1169
1202
|
CLI_DESCRIPTION: "cliDescription",
|
|
1170
1203
|
CATEGORY: "category",
|
|
1171
1204
|
FORKED_FROM: "forkedFrom",
|
|
@@ -1291,6 +1324,10 @@ async function writeContentHash(pluginDir, contentHash, getManifestPath) {
|
|
|
1291
1324
|
|
|
1292
1325
|
// src/cli/lib/skills/skill-metadata.ts
|
|
1293
1326
|
async function readForkedFromMetadata(skillDir) {
|
|
1327
|
+
const metadata = await readLocalSkillMetadata(skillDir);
|
|
1328
|
+
return metadata?.forkedFrom ?? null;
|
|
1329
|
+
}
|
|
1330
|
+
async function readLocalSkillMetadata(skillDir) {
|
|
1294
1331
|
const metadataPath = path7.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
1295
1332
|
if (!await fileExists(metadataPath)) {
|
|
1296
1333
|
return null;
|
|
@@ -1301,7 +1338,7 @@ async function readForkedFromMetadata(skillDir) {
|
|
|
1301
1338
|
warn(`Invalid metadata.yaml at ${metadataPath}: ${formatZodErrors(result.error.issues)}`);
|
|
1302
1339
|
return null;
|
|
1303
1340
|
}
|
|
1304
|
-
return result.data
|
|
1341
|
+
return result.data;
|
|
1305
1342
|
}
|
|
1306
1343
|
async function getLocalSkillsWithMetadata(projectDir) {
|
|
1307
1344
|
const localSkillsPath = path7.join(projectDir, LOCAL_SKILLS_PATH);
|
|
@@ -1474,8 +1511,8 @@ async function copySkillsToLocalFlattened(selectedSkillIds, localSkillsDir, matr
|
|
|
1474
1511
|
|
|
1475
1512
|
// src/cli/lib/skills/skill-plugin-compiler.ts
|
|
1476
1513
|
init_esm_shims();
|
|
1477
|
-
import
|
|
1478
|
-
import { parse as
|
|
1514
|
+
import path18 from "path";
|
|
1515
|
+
import { parse as parseYaml7 } from "yaml";
|
|
1479
1516
|
|
|
1480
1517
|
// src/cli/lib/plugins/index.ts
|
|
1481
1518
|
init_esm_shims();
|
|
@@ -1582,19 +1619,21 @@ init_esm_shims();
|
|
|
1582
1619
|
|
|
1583
1620
|
// src/cli/lib/installation/installation.ts
|
|
1584
1621
|
init_esm_shims();
|
|
1622
|
+
import os4 from "os";
|
|
1585
1623
|
import path11 from "path";
|
|
1586
|
-
async function
|
|
1624
|
+
async function detectProjectInstallation(projectDir) {
|
|
1587
1625
|
const srcConfigPath = path11.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML);
|
|
1588
1626
|
const legacyConfigPath = path11.join(projectDir, CLAUDE_DIR, STANDARD_FILES.CONFIG_YAML);
|
|
1589
1627
|
const localConfigPath = await fileExists(srcConfigPath) ? srcConfigPath : await fileExists(legacyConfigPath) ? legacyConfigPath : null;
|
|
1590
1628
|
if (!localConfigPath) {
|
|
1591
1629
|
return null;
|
|
1592
1630
|
}
|
|
1593
|
-
const loaded = await
|
|
1631
|
+
const loaded = await loadProjectConfigFromDir(projectDir);
|
|
1594
1632
|
const mode = loaded?.config?.installMode ?? "local";
|
|
1595
1633
|
if (mode === "local") {
|
|
1596
1634
|
return {
|
|
1597
1635
|
mode: "local",
|
|
1636
|
+
scope: "project",
|
|
1598
1637
|
configPath: localConfigPath,
|
|
1599
1638
|
agentsDir: path11.join(projectDir, CLAUDE_DIR, "agents"),
|
|
1600
1639
|
skillsDir: path11.join(projectDir, CLAUDE_DIR, "skills"),
|
|
@@ -1603,12 +1642,45 @@ async function detectInstallation(projectDir = process.cwd()) {
|
|
|
1603
1642
|
}
|
|
1604
1643
|
return {
|
|
1605
1644
|
mode: "plugin",
|
|
1645
|
+
scope: "project",
|
|
1606
1646
|
configPath: localConfigPath,
|
|
1607
1647
|
agentsDir: path11.join(projectDir, CLAUDE_DIR, "agents"),
|
|
1608
1648
|
skillsDir: path11.join(projectDir, CLAUDE_DIR, PLUGINS_SUBDIR),
|
|
1609
1649
|
projectDir
|
|
1610
1650
|
};
|
|
1611
1651
|
}
|
|
1652
|
+
async function detectGlobalInstallation() {
|
|
1653
|
+
const homeDir = os4.homedir();
|
|
1654
|
+
const srcConfigPath = path11.join(homeDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML);
|
|
1655
|
+
if (!await fileExists(srcConfigPath)) {
|
|
1656
|
+
return null;
|
|
1657
|
+
}
|
|
1658
|
+
const loaded = await loadProjectConfigFromDir(homeDir);
|
|
1659
|
+
const mode = loaded?.config?.installMode ?? "local";
|
|
1660
|
+
if (mode === "local") {
|
|
1661
|
+
return {
|
|
1662
|
+
mode: "local",
|
|
1663
|
+
scope: "global",
|
|
1664
|
+
configPath: srcConfigPath,
|
|
1665
|
+
agentsDir: path11.join(homeDir, CLAUDE_DIR, "agents"),
|
|
1666
|
+
skillsDir: path11.join(homeDir, CLAUDE_DIR, "skills"),
|
|
1667
|
+
projectDir: homeDir
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
return {
|
|
1671
|
+
mode: "plugin",
|
|
1672
|
+
scope: "global",
|
|
1673
|
+
configPath: srcConfigPath,
|
|
1674
|
+
agentsDir: path11.join(homeDir, CLAUDE_DIR, "agents"),
|
|
1675
|
+
skillsDir: path11.join(homeDir, CLAUDE_DIR, PLUGINS_SUBDIR),
|
|
1676
|
+
projectDir: homeDir
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
async function detectInstallation(projectDir = process.cwd()) {
|
|
1680
|
+
const projectInstallation = await detectProjectInstallation(projectDir);
|
|
1681
|
+
if (projectInstallation) return projectInstallation;
|
|
1682
|
+
return detectGlobalInstallation();
|
|
1683
|
+
}
|
|
1612
1684
|
|
|
1613
1685
|
// src/cli/lib/installation/local-installer.ts
|
|
1614
1686
|
init_esm_shims();
|
|
@@ -1684,7 +1756,7 @@ async function resolveAgents(agents, skills, compileConfig, _projectRoot, stack)
|
|
|
1684
1756
|
const availableAgents = typedKeys(agents);
|
|
1685
1757
|
const agentList = availableAgents.length > 0 ? `Available agents: ${availableAgents.slice(0, 5).join(", ")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : ""}` : "No agents found in scanned directories";
|
|
1686
1758
|
throw new Error(
|
|
1687
|
-
`Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/
|
|
1759
|
+
`Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/metadata.yaml exists.`
|
|
1688
1760
|
);
|
|
1689
1761
|
}
|
|
1690
1762
|
const agentConfig = compileConfig.agents[agentName];
|
|
@@ -2181,9 +2253,6 @@ async function buildLocalConfig(wizardResult, sourceResult) {
|
|
|
2181
2253
|
}
|
|
2182
2254
|
function setConfigMetadata(config, wizardResult, sourceResult, sourceFlag) {
|
|
2183
2255
|
config.installMode = wizardResult.installMode;
|
|
2184
|
-
if (wizardResult.expertMode) {
|
|
2185
|
-
config.expertMode = true;
|
|
2186
|
-
}
|
|
2187
2256
|
if (wizardResult.selectedDomains && wizardResult.selectedDomains.length > 0) {
|
|
2188
2257
|
config.domains = wizardResult.selectedDomains;
|
|
2189
2258
|
}
|
|
@@ -2225,7 +2294,8 @@ var PATH_OVERRIDES_COMMENT = [
|
|
|
2225
2294
|
`# skillsDir: ${SKILLS_DIR_PATH}`,
|
|
2226
2295
|
`# agentsDir: ${DIRS.agents}`,
|
|
2227
2296
|
`# stacksFile: ${STACKS_FILE_PATH}`,
|
|
2228
|
-
`#
|
|
2297
|
+
`# categoriesFile: ${SKILL_CATEGORIES_YAML_PATH}`,
|
|
2298
|
+
`# rulesFile: ${SKILL_RULES_YAML_PATH}`,
|
|
2229
2299
|
""
|
|
2230
2300
|
].join("\n");
|
|
2231
2301
|
async function writeConfigFile(config, configPath) {
|
|
@@ -2359,7 +2429,7 @@ init_esm_shims();
|
|
|
2359
2429
|
// src/cli/lib/plugins/plugin-settings.ts
|
|
2360
2430
|
init_esm_shims();
|
|
2361
2431
|
import path15 from "path";
|
|
2362
|
-
import
|
|
2432
|
+
import os5 from "os";
|
|
2363
2433
|
import { z } from "zod";
|
|
2364
2434
|
var pluginSettingsSchema = z.object({
|
|
2365
2435
|
enabledPlugins: z.record(z.string(), z.unknown()).optional()
|
|
@@ -2410,7 +2480,7 @@ async function resolvePluginInstallPaths(pluginKeys, projectDir) {
|
|
|
2410
2480
|
if (pluginKeys.length === 0) {
|
|
2411
2481
|
return [];
|
|
2412
2482
|
}
|
|
2413
|
-
const registryPath = path15.join(
|
|
2483
|
+
const registryPath = path15.join(os5.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR, INSTALLED_PLUGINS_FILE);
|
|
2414
2484
|
if (!await fileExists(registryPath)) {
|
|
2415
2485
|
verbose(`Plugin registry not found at '${registryPath}'`);
|
|
2416
2486
|
return [];
|
|
@@ -2585,9 +2655,221 @@ function formatInstallationDisplay(info) {
|
|
|
2585
2655
|
// src/cli/lib/plugins/plugin-validator.ts
|
|
2586
2656
|
init_esm_shims();
|
|
2587
2657
|
import { z as z2 } from "zod";
|
|
2658
|
+
import path17 from "path";
|
|
2659
|
+
import fg2 from "fast-glob";
|
|
2660
|
+
import { countBy } from "remeda";
|
|
2661
|
+
|
|
2662
|
+
// src/cli/lib/schema-validator.ts
|
|
2663
|
+
init_esm_shims();
|
|
2664
|
+
import { sumBy } from "remeda";
|
|
2588
2665
|
import path16 from "path";
|
|
2666
|
+
import { parse as parseYaml6 } from "yaml";
|
|
2589
2667
|
import fg from "fast-glob";
|
|
2590
|
-
|
|
2668
|
+
var VALIDATION_TARGETS = [
|
|
2669
|
+
{
|
|
2670
|
+
name: "Skill Categories",
|
|
2671
|
+
schema: skillCategoriesFileSchema,
|
|
2672
|
+
pattern: STANDARD_FILES.SKILL_CATEGORIES_YAML,
|
|
2673
|
+
baseDir: "config"
|
|
2674
|
+
},
|
|
2675
|
+
{
|
|
2676
|
+
name: "Skill Rules",
|
|
2677
|
+
schema: skillRulesFileSchema,
|
|
2678
|
+
pattern: STANDARD_FILES.SKILL_RULES_YAML,
|
|
2679
|
+
baseDir: "config"
|
|
2680
|
+
},
|
|
2681
|
+
{
|
|
2682
|
+
name: "Skill Metadata",
|
|
2683
|
+
schema: metadataValidationSchema,
|
|
2684
|
+
pattern: `**/${STANDARD_FILES.METADATA_YAML}`,
|
|
2685
|
+
baseDir: "src/skills"
|
|
2686
|
+
},
|
|
2687
|
+
{
|
|
2688
|
+
name: "Stack Skill Metadata",
|
|
2689
|
+
schema: metadataValidationSchema,
|
|
2690
|
+
pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,
|
|
2691
|
+
baseDir: "src/stacks"
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
name: "Stack Config",
|
|
2695
|
+
schema: stackConfigValidationSchema,
|
|
2696
|
+
pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,
|
|
2697
|
+
baseDir: "src/stacks"
|
|
2698
|
+
},
|
|
2699
|
+
{
|
|
2700
|
+
name: "Agent Definition",
|
|
2701
|
+
schema: agentYamlGenerationSchema,
|
|
2702
|
+
pattern: `**/${STANDARD_FILES.AGENT_METADATA_YAML}`,
|
|
2703
|
+
baseDir: "src/agents"
|
|
2704
|
+
},
|
|
2705
|
+
{
|
|
2706
|
+
name: "Skill Frontmatter",
|
|
2707
|
+
schema: skillFrontmatterValidationSchema,
|
|
2708
|
+
pattern: `**/${STANDARD_FILES.SKILL_MD}`,
|
|
2709
|
+
baseDir: "src/skills",
|
|
2710
|
+
extractor: extractFrontmatter
|
|
2711
|
+
},
|
|
2712
|
+
{
|
|
2713
|
+
name: "Stack Skill Frontmatter",
|
|
2714
|
+
schema: skillFrontmatterValidationSchema,
|
|
2715
|
+
pattern: `**/skills/**/${STANDARD_FILES.SKILL_MD}`,
|
|
2716
|
+
baseDir: "src/stacks",
|
|
2717
|
+
extractor: extractFrontmatter
|
|
2718
|
+
},
|
|
2719
|
+
{
|
|
2720
|
+
name: "Stacks Config",
|
|
2721
|
+
schema: stacksConfigSchema,
|
|
2722
|
+
pattern: "stacks.yaml",
|
|
2723
|
+
baseDir: "config"
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
name: "Project Source Config",
|
|
2727
|
+
schema: projectSourceConfigSchema,
|
|
2728
|
+
pattern: STANDARD_FILES.CONFIG_YAML,
|
|
2729
|
+
baseDir: CLAUDE_SRC_DIR
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
name: "Project Skill Metadata",
|
|
2733
|
+
schema: metadataValidationSchema,
|
|
2734
|
+
pattern: `*/${STANDARD_FILES.METADATA_YAML}`,
|
|
2735
|
+
baseDir: `${CLAUDE_DIR}/skills`
|
|
2736
|
+
},
|
|
2737
|
+
{
|
|
2738
|
+
name: "Project Skill Frontmatter",
|
|
2739
|
+
schema: skillFrontmatterValidationSchema,
|
|
2740
|
+
pattern: `*/${STANDARD_FILES.SKILL_MD}`,
|
|
2741
|
+
baseDir: `${CLAUDE_DIR}/skills`,
|
|
2742
|
+
extractor: extractFrontmatter
|
|
2743
|
+
},
|
|
2744
|
+
{
|
|
2745
|
+
name: "Project Agent Frontmatter",
|
|
2746
|
+
schema: agentFrontmatterValidationSchema,
|
|
2747
|
+
pattern: "*.md",
|
|
2748
|
+
baseDir: `${CLAUDE_DIR}/agents`,
|
|
2749
|
+
extractor: extractFrontmatter
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
name: "Plugin Manifest",
|
|
2753
|
+
schema: pluginManifestSchema,
|
|
2754
|
+
pattern: `*/${STANDARD_FILES.PLUGIN_JSON}`,
|
|
2755
|
+
baseDir: `${CLAUDE_DIR}/plugins`,
|
|
2756
|
+
extractor: (content) => JSON.parse(content)
|
|
2757
|
+
}
|
|
2758
|
+
];
|
|
2759
|
+
function formatZodErrors2(error) {
|
|
2760
|
+
return error.issues.map((issue) => {
|
|
2761
|
+
const path24 = issue.path.join(".");
|
|
2762
|
+
if (issue.code === "unrecognized_keys") {
|
|
2763
|
+
return `Unrecognized key: "${issue.keys.join('", "')}"`;
|
|
2764
|
+
}
|
|
2765
|
+
return path24 ? `${path24}: ${issue.message}` : issue.message;
|
|
2766
|
+
});
|
|
2767
|
+
}
|
|
2768
|
+
async function validateFile(filePath, schema, extractor) {
|
|
2769
|
+
try {
|
|
2770
|
+
if (!await fileExists(filePath)) {
|
|
2771
|
+
return { valid: false, errors: [`File not found: ${filePath}`] };
|
|
2772
|
+
}
|
|
2773
|
+
const content = await readFile(filePath);
|
|
2774
|
+
let parsed;
|
|
2775
|
+
if (extractor) {
|
|
2776
|
+
parsed = extractor(content);
|
|
2777
|
+
if (parsed === null) {
|
|
2778
|
+
return {
|
|
2779
|
+
valid: false,
|
|
2780
|
+
errors: ["Failed to extract content (no valid frontmatter found)"]
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
} else {
|
|
2784
|
+
parsed = parseYaml6(content);
|
|
2785
|
+
}
|
|
2786
|
+
const result = schema.safeParse(parsed);
|
|
2787
|
+
if (result.success) {
|
|
2788
|
+
return { valid: true, errors: [] };
|
|
2789
|
+
}
|
|
2790
|
+
return { valid: false, errors: formatZodErrors2(result.error) };
|
|
2791
|
+
} catch (error) {
|
|
2792
|
+
const message = getErrorMessage(error);
|
|
2793
|
+
return { valid: false, errors: [`Failed to parse content: ${message}`] };
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
async function validateTarget(target, rootDir = process.cwd()) {
|
|
2797
|
+
const baseDir = path16.join(rootDir, target.baseDir);
|
|
2798
|
+
const pattern = path16.join(baseDir, target.pattern);
|
|
2799
|
+
const files = await fg(pattern, { absolute: true });
|
|
2800
|
+
const result = {
|
|
2801
|
+
schemaName: target.name,
|
|
2802
|
+
valid: true,
|
|
2803
|
+
totalFiles: files.length,
|
|
2804
|
+
validFiles: 0,
|
|
2805
|
+
invalidFiles: []
|
|
2806
|
+
};
|
|
2807
|
+
if (files.length === 0) {
|
|
2808
|
+
return result;
|
|
2809
|
+
}
|
|
2810
|
+
for (const file of files) {
|
|
2811
|
+
const validation = await validateFile(file, target.schema, target.extractor);
|
|
2812
|
+
const relativePath = path16.relative(rootDir, file);
|
|
2813
|
+
if (validation.valid) {
|
|
2814
|
+
result.validFiles++;
|
|
2815
|
+
} else {
|
|
2816
|
+
result.valid = false;
|
|
2817
|
+
result.invalidFiles.push({
|
|
2818
|
+
file: relativePath,
|
|
2819
|
+
errors: validation.errors
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
return result;
|
|
2824
|
+
}
|
|
2825
|
+
async function validateAllSchemas(rootDir = process.cwd()) {
|
|
2826
|
+
const results = [];
|
|
2827
|
+
for (const target of VALIDATION_TARGETS) {
|
|
2828
|
+
const result = await validateTarget(target, rootDir);
|
|
2829
|
+
results.push(result);
|
|
2830
|
+
}
|
|
2831
|
+
const summary = {
|
|
2832
|
+
totalSchemas: results.length,
|
|
2833
|
+
totalFiles: sumBy(results, (r) => r.totalFiles),
|
|
2834
|
+
validFiles: sumBy(results, (r) => r.validFiles),
|
|
2835
|
+
invalidFiles: sumBy(results, (r) => r.invalidFiles.length)
|
|
2836
|
+
};
|
|
2837
|
+
return {
|
|
2838
|
+
valid: results.every((r) => r.valid),
|
|
2839
|
+
results,
|
|
2840
|
+
summary
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
function printValidationResults(result) {
|
|
2844
|
+
log("\n Schema Validation Summary:");
|
|
2845
|
+
log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2846
|
+
log(` Total schemas checked: ${result.summary.totalSchemas}`);
|
|
2847
|
+
log(` Total files: ${result.summary.totalFiles}`);
|
|
2848
|
+
log(` Valid: ${result.summary.validFiles}`);
|
|
2849
|
+
log(` Invalid: ${result.summary.invalidFiles}`);
|
|
2850
|
+
for (const schemaResult of result.results) {
|
|
2851
|
+
if (schemaResult.totalFiles === 0) continue;
|
|
2852
|
+
const status = schemaResult.valid ? "\u2713" : "\u2717";
|
|
2853
|
+
log(
|
|
2854
|
+
`
|
|
2855
|
+
${status} ${schemaResult.schemaName}: ${schemaResult.validFiles}/${schemaResult.totalFiles} valid`
|
|
2856
|
+
);
|
|
2857
|
+
if (schemaResult.invalidFiles.length > 0) {
|
|
2858
|
+
for (const file of schemaResult.invalidFiles) {
|
|
2859
|
+
log(`
|
|
2860
|
+
${file.file}:`);
|
|
2861
|
+
file.errors.forEach((e) => log(` - ${e}`));
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
if (result.valid) {
|
|
2866
|
+
log("\n \u2713 All schemas validated successfully\n");
|
|
2867
|
+
} else {
|
|
2868
|
+
log("\n \u2717 Validation failed\n");
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
// src/cli/lib/plugins/plugin-validator.ts
|
|
2591
2873
|
var PLUGIN_DIR = PLUGIN_MANIFEST_DIR;
|
|
2592
2874
|
var PLUGIN_MANIFEST = STANDARD_FILES.PLUGIN_JSON;
|
|
2593
2875
|
var KEBAB_CASE_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
@@ -2603,15 +2885,6 @@ var pluginManifestValidationSchema = z2.object({
|
|
|
2603
2885
|
skills: z2.union([z2.string(), z2.array(z2.string())]).optional(),
|
|
2604
2886
|
hooks: z2.union([z2.string(), hooksRecordSchema]).optional()
|
|
2605
2887
|
}).strict();
|
|
2606
|
-
function formatZodErrors2(error) {
|
|
2607
|
-
return error.issues.map((issue) => {
|
|
2608
|
-
const path23 = issue.path.join(".");
|
|
2609
|
-
if (issue.code === "unrecognized_keys") {
|
|
2610
|
-
return `Unrecognized key: "${issue.keys.join('", "')}"`;
|
|
2611
|
-
}
|
|
2612
|
-
return path23 ? `${path23}: ${issue.message}` : issue.message;
|
|
2613
|
-
});
|
|
2614
|
-
}
|
|
2615
2888
|
function isKebabCase(str) {
|
|
2616
2889
|
return KEBAB_CASE_REGEX.test(str);
|
|
2617
2890
|
}
|
|
@@ -2628,15 +2901,15 @@ async function validatePluginStructure(pluginPath) {
|
|
|
2628
2901
|
warnings: []
|
|
2629
2902
|
};
|
|
2630
2903
|
}
|
|
2631
|
-
const pluginDir =
|
|
2904
|
+
const pluginDir = path17.join(pluginPath, PLUGIN_DIR);
|
|
2632
2905
|
if (!await directoryExists(pluginDir)) {
|
|
2633
2906
|
errors.push(`Missing ${PLUGIN_DIR}/ directory`);
|
|
2634
2907
|
}
|
|
2635
|
-
const manifestPath =
|
|
2908
|
+
const manifestPath = path17.join(pluginDir, PLUGIN_MANIFEST);
|
|
2636
2909
|
if (!await fileExists(manifestPath)) {
|
|
2637
2910
|
errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);
|
|
2638
2911
|
}
|
|
2639
|
-
const readmePath =
|
|
2912
|
+
const readmePath = path17.join(pluginPath, "README.md");
|
|
2640
2913
|
if (!await fileExists(readmePath)) {
|
|
2641
2914
|
warnings.push("Missing README.md (recommended for documentation)");
|
|
2642
2915
|
}
|
|
@@ -2686,15 +2959,15 @@ async function validatePluginManifest(manifestPath) {
|
|
|
2686
2959
|
if (!manifest.description) {
|
|
2687
2960
|
warnings.push("Missing description field (recommended for discoverability)");
|
|
2688
2961
|
}
|
|
2689
|
-
const pluginDir =
|
|
2962
|
+
const pluginDir = path17.dirname(path17.dirname(manifestPath));
|
|
2690
2963
|
if (manifest.skills && typeof manifest.skills === "string") {
|
|
2691
|
-
const skillsPath =
|
|
2964
|
+
const skillsPath = path17.join(pluginDir, manifest.skills);
|
|
2692
2965
|
if (!await directoryExists(skillsPath)) {
|
|
2693
2966
|
errors.push(`Skills path does not exist: ${manifest.skills}`);
|
|
2694
2967
|
}
|
|
2695
2968
|
}
|
|
2696
2969
|
if (manifest.agents && typeof manifest.agents === "string") {
|
|
2697
|
-
const agentsPath =
|
|
2970
|
+
const agentsPath = path17.join(pluginDir, manifest.agents);
|
|
2698
2971
|
if (!await directoryExists(agentsPath)) {
|
|
2699
2972
|
errors.push(`Agents path does not exist: ${manifest.agents}`);
|
|
2700
2973
|
}
|
|
@@ -2783,9 +3056,9 @@ function prefixResult(result, prefix) {
|
|
|
2783
3056
|
};
|
|
2784
3057
|
}
|
|
2785
3058
|
async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
|
|
2786
|
-
const skillsDir =
|
|
3059
|
+
const skillsDir = path17.join(pluginPath, skillsRelPath);
|
|
2787
3060
|
if (!await directoryExists(skillsDir)) return EMPTY_RESULT;
|
|
2788
|
-
const files = await
|
|
3061
|
+
const files = await fg2("**/SKILL.md", { cwd: skillsDir, absolute: true });
|
|
2789
3062
|
if (files.length === 0) {
|
|
2790
3063
|
return {
|
|
2791
3064
|
valid: true,
|
|
@@ -2795,15 +3068,15 @@ async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
|
|
|
2795
3068
|
}
|
|
2796
3069
|
const results = await Promise.all(
|
|
2797
3070
|
files.map(
|
|
2798
|
-
async (f) => prefixResult(await validateSkillFrontmatter(f),
|
|
3071
|
+
async (f) => prefixResult(await validateSkillFrontmatter(f), path17.relative(pluginPath, f))
|
|
2799
3072
|
)
|
|
2800
3073
|
);
|
|
2801
3074
|
return mergeResults(results);
|
|
2802
3075
|
}
|
|
2803
3076
|
async function validatePluginAgentFiles(pluginPath, agentsRelPath) {
|
|
2804
|
-
const agentsDir =
|
|
3077
|
+
const agentsDir = path17.join(pluginPath, agentsRelPath);
|
|
2805
3078
|
if (!await directoryExists(agentsDir)) return EMPTY_RESULT;
|
|
2806
|
-
const files = await
|
|
3079
|
+
const files = await fg2("*.md", { cwd: agentsDir, absolute: true });
|
|
2807
3080
|
if (files.length === 0) {
|
|
2808
3081
|
return {
|
|
2809
3082
|
valid: true,
|
|
@@ -2813,7 +3086,7 @@ async function validatePluginAgentFiles(pluginPath, agentsRelPath) {
|
|
|
2813
3086
|
}
|
|
2814
3087
|
const results = await Promise.all(
|
|
2815
3088
|
files.map(
|
|
2816
|
-
async (f) => prefixResult(await validateAgentFrontmatter(f),
|
|
3089
|
+
async (f) => prefixResult(await validateAgentFrontmatter(f), path17.relative(pluginPath, f))
|
|
2817
3090
|
)
|
|
2818
3091
|
);
|
|
2819
3092
|
return mergeResults(results);
|
|
@@ -2829,7 +3102,7 @@ async function loadManifestForValidation(manifestPath) {
|
|
|
2829
3102
|
async function validatePlugin(pluginPath) {
|
|
2830
3103
|
const structureResult = await validatePluginStructure(pluginPath);
|
|
2831
3104
|
if (!structureResult.valid) return structureResult;
|
|
2832
|
-
const manifestPath =
|
|
3105
|
+
const manifestPath = path17.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);
|
|
2833
3106
|
const manifestResult = await validatePluginManifest(manifestPath);
|
|
2834
3107
|
const manifest = await loadManifestForValidation(manifestPath);
|
|
2835
3108
|
const skillsResult = manifest?.skills && typeof manifest.skills === "string" ? await validatePluginSkillFiles(pluginPath, manifest.skills) : EMPTY_RESULT;
|
|
@@ -2857,7 +3130,7 @@ async function validateAllPlugins(pluginsDir) {
|
|
|
2857
3130
|
const allDirs = await listDirectories(pluginsDir);
|
|
2858
3131
|
const pluginDirs = [];
|
|
2859
3132
|
for (const dirName of allDirs) {
|
|
2860
|
-
const potentialPluginDir =
|
|
3133
|
+
const potentialPluginDir = path17.join(pluginsDir, dirName, PLUGIN_DIR);
|
|
2861
3134
|
if (await directoryExists(potentialPluginDir)) {
|
|
2862
3135
|
pluginDirs.push(dirName);
|
|
2863
3136
|
}
|
|
@@ -2881,7 +3154,7 @@ async function validateAllPlugins(pluginsDir) {
|
|
|
2881
3154
|
};
|
|
2882
3155
|
}
|
|
2883
3156
|
for (const pluginName of pluginDirs) {
|
|
2884
|
-
const pluginPath =
|
|
3157
|
+
const pluginPath = path17.join(pluginsDir, pluginName);
|
|
2885
3158
|
const result = await validatePlugin(pluginPath);
|
|
2886
3159
|
results.push({ name: pluginName, result });
|
|
2887
3160
|
}
|
|
@@ -2919,7 +3192,7 @@ function sanitizeSkillName(name) {
|
|
|
2919
3192
|
return name.replace(/\+/g, "-");
|
|
2920
3193
|
}
|
|
2921
3194
|
async function readSkillMetadata(skillPath) {
|
|
2922
|
-
const metadataPath =
|
|
3195
|
+
const metadataPath = path18.join(skillPath, STANDARD_FILES.METADATA_YAML);
|
|
2923
3196
|
if (!await fileExists(metadataPath)) {
|
|
2924
3197
|
return null;
|
|
2925
3198
|
}
|
|
@@ -2927,7 +3200,7 @@ async function readSkillMetadata(skillPath) {
|
|
|
2927
3200
|
const content = await readFile(metadataPath);
|
|
2928
3201
|
const lines = content.split("\n");
|
|
2929
3202
|
const yamlContent = lines[0]?.startsWith("# yaml-language-server:") ? lines.slice(1).join("\n") : content;
|
|
2930
|
-
const result = skillMetadataLoaderSchema.safeParse(
|
|
3203
|
+
const result = skillMetadataLoaderSchema.safeParse(parseYaml7(yamlContent));
|
|
2931
3204
|
if (!result.success) {
|
|
2932
3205
|
warn(`Invalid metadata.yaml at '${skillPath}': ${formatZodErrors(result.error.issues)}`);
|
|
2933
3206
|
return null;
|
|
@@ -2976,8 +3249,8 @@ function generateReadme(skillName, frontmatter, metadata) {
|
|
|
2976
3249
|
}
|
|
2977
3250
|
async function compileSkillPlugin(options) {
|
|
2978
3251
|
const { skillPath, outputDir, skillName: overrideName } = options;
|
|
2979
|
-
const dirBasename =
|
|
2980
|
-
const skillMdPath =
|
|
3252
|
+
const dirBasename = path18.basename(skillPath);
|
|
3253
|
+
const skillMdPath = path18.join(skillPath, STANDARD_FILES.SKILL_MD);
|
|
2981
3254
|
if (!await fileExists(skillMdPath)) {
|
|
2982
3255
|
throw new Error(
|
|
2983
3256
|
`Skill '${dirBasename}' is missing required ${STANDARD_FILES.SKILL_MD} file. Expected at: ${skillMdPath}`
|
|
@@ -2993,8 +3266,8 @@ async function compileSkillPlugin(options) {
|
|
|
2993
3266
|
const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);
|
|
2994
3267
|
verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);
|
|
2995
3268
|
const metadata = await readSkillMetadata(skillPath);
|
|
2996
|
-
const pluginDir =
|
|
2997
|
-
const skillsDir =
|
|
3269
|
+
const pluginDir = path18.join(outputDir, skillName);
|
|
3270
|
+
const skillsDir = path18.join(pluginDir, "skills", skillName);
|
|
2998
3271
|
await ensureDir(pluginDir);
|
|
2999
3272
|
await ensureDir(skillsDir);
|
|
3000
3273
|
const newHash = await computeSkillFolderHash(skillPath);
|
|
@@ -3013,26 +3286,26 @@ async function compileSkillPlugin(options) {
|
|
|
3013
3286
|
await writePluginManifest(pluginDir, manifest);
|
|
3014
3287
|
await writeContentHash(pluginDir, contentHash, getPluginManifestPath);
|
|
3015
3288
|
verbose(` Wrote plugin.json for ${skillName} (v${version})`);
|
|
3016
|
-
await writeFile(
|
|
3289
|
+
await writeFile(path18.join(skillsDir, STANDARD_FILES.SKILL_MD), skillMdContent);
|
|
3017
3290
|
verbose(` Copied ${STANDARD_FILES.SKILL_MD}`);
|
|
3018
3291
|
for (const fileName of SKILL_CONTENT_FILES) {
|
|
3019
3292
|
if (fileName === STANDARD_FILES.SKILL_MD) continue;
|
|
3020
|
-
const sourcePath =
|
|
3293
|
+
const sourcePath = path18.join(skillPath, fileName);
|
|
3021
3294
|
if (await fileExists(sourcePath)) {
|
|
3022
3295
|
const content = await readFile(sourcePath);
|
|
3023
|
-
await writeFile(
|
|
3296
|
+
await writeFile(path18.join(skillsDir, fileName), content);
|
|
3024
3297
|
verbose(` Copied ${fileName}`);
|
|
3025
3298
|
}
|
|
3026
3299
|
}
|
|
3027
3300
|
for (const dirName of SKILL_CONTENT_DIRS) {
|
|
3028
|
-
const sourceDir =
|
|
3301
|
+
const sourceDir = path18.join(skillPath, dirName);
|
|
3029
3302
|
if (await fileExists(sourceDir)) {
|
|
3030
|
-
await copy(sourceDir,
|
|
3303
|
+
await copy(sourceDir, path18.join(skillsDir, dirName));
|
|
3031
3304
|
verbose(` Copied ${dirName}/`);
|
|
3032
3305
|
}
|
|
3033
3306
|
}
|
|
3034
3307
|
const readme = generateReadme(skillName, frontmatter, metadata);
|
|
3035
|
-
await writeFile(
|
|
3308
|
+
await writeFile(path18.join(pluginDir, "README.md"), readme);
|
|
3036
3309
|
verbose(" Generated README.md");
|
|
3037
3310
|
return {
|
|
3038
3311
|
pluginPath: pluginDir,
|
|
@@ -3044,7 +3317,7 @@ async function compileAllSkillPlugins(skillsDir, outputDir) {
|
|
|
3044
3317
|
const results = [];
|
|
3045
3318
|
const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
|
|
3046
3319
|
for (const skillMdFile of skillMdFiles) {
|
|
3047
|
-
const skillPath =
|
|
3320
|
+
const skillPath = path18.join(skillsDir, path18.dirname(skillMdFile));
|
|
3048
3321
|
try {
|
|
3049
3322
|
const result = await compileSkillPlugin({
|
|
3050
3323
|
skillPath,
|
|
@@ -3054,7 +3327,7 @@ async function compileAllSkillPlugins(skillsDir, outputDir) {
|
|
|
3054
3327
|
log(` [OK] ${result.skillName}`);
|
|
3055
3328
|
} catch (error) {
|
|
3056
3329
|
const errorMessage = getErrorMessage(error);
|
|
3057
|
-
const dirBasename =
|
|
3330
|
+
const dirBasename = path18.basename(skillPath);
|
|
3058
3331
|
warn(`Failed to compile skill from '${dirBasename}': ${errorMessage}`);
|
|
3059
3332
|
}
|
|
3060
3333
|
}
|
|
@@ -3070,7 +3343,7 @@ Compiled ${results.length} skill plugins:`);
|
|
|
3070
3343
|
|
|
3071
3344
|
// src/cli/lib/skills/source-switcher.ts
|
|
3072
3345
|
init_esm_shims();
|
|
3073
|
-
import
|
|
3346
|
+
import path19 from "path";
|
|
3074
3347
|
function validateSkillId(skillId) {
|
|
3075
3348
|
if (!isValidSkillId(skillId)) {
|
|
3076
3349
|
return false;
|
|
@@ -3078,19 +3351,19 @@ function validateSkillId(skillId) {
|
|
|
3078
3351
|
return !(skillId.includes("\0") || skillId.includes("..") || skillId.includes("/") || skillId.includes("\\"));
|
|
3079
3352
|
}
|
|
3080
3353
|
function validatePathBoundary(resolvedPath, expectedParent) {
|
|
3081
|
-
const normalizedPath =
|
|
3082
|
-
const normalizedParent =
|
|
3083
|
-
return normalizedPath.startsWith(normalizedParent +
|
|
3354
|
+
const normalizedPath = path19.resolve(resolvedPath);
|
|
3355
|
+
const normalizedParent = path19.resolve(expectedParent);
|
|
3356
|
+
return normalizedPath.startsWith(normalizedParent + path19.sep);
|
|
3084
3357
|
}
|
|
3085
3358
|
async function archiveLocalSkill(projectDir, skillId) {
|
|
3086
3359
|
if (!validateSkillId(skillId)) {
|
|
3087
3360
|
warn(`Invalid skill ID for archiving: '${skillId}'`);
|
|
3088
3361
|
return;
|
|
3089
3362
|
}
|
|
3090
|
-
const skillsDir =
|
|
3091
|
-
const skillPath =
|
|
3092
|
-
const archivedDir =
|
|
3093
|
-
const archivedSkillPath =
|
|
3363
|
+
const skillsDir = path19.resolve(path19.join(projectDir, LOCAL_SKILLS_PATH));
|
|
3364
|
+
const skillPath = path19.resolve(path19.join(skillsDir, skillId));
|
|
3365
|
+
const archivedDir = path19.resolve(path19.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
|
|
3366
|
+
const archivedSkillPath = path19.resolve(path19.join(archivedDir, skillId));
|
|
3094
3367
|
if (!validatePathBoundary(skillPath, skillsDir) || !validatePathBoundary(archivedSkillPath, archivedDir)) {
|
|
3095
3368
|
warn(`Skill ID '${skillId}' resolves outside the skills directory.`);
|
|
3096
3369
|
return;
|
|
@@ -3110,10 +3383,10 @@ async function restoreArchivedSkill(projectDir, skillId) {
|
|
|
3110
3383
|
warn(`Invalid skill ID for restoring: '${skillId}'`);
|
|
3111
3384
|
return false;
|
|
3112
3385
|
}
|
|
3113
|
-
const skillsDir =
|
|
3114
|
-
const skillPath =
|
|
3115
|
-
const archivedDir =
|
|
3116
|
-
const archivedSkillPath =
|
|
3386
|
+
const skillsDir = path19.resolve(path19.join(projectDir, LOCAL_SKILLS_PATH));
|
|
3387
|
+
const skillPath = path19.resolve(path19.join(skillsDir, skillId));
|
|
3388
|
+
const archivedDir = path19.resolve(path19.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
|
|
3389
|
+
const archivedSkillPath = path19.resolve(path19.join(archivedDir, skillId));
|
|
3117
3390
|
if (!validatePathBoundary(skillPath, skillsDir) || !validatePathBoundary(archivedSkillPath, archivedDir)) {
|
|
3118
3391
|
warn(`Skill ID '${skillId}' resolves outside the skills directory.`);
|
|
3119
3392
|
return false;
|
|
@@ -3133,39 +3406,61 @@ init_esm_shims();
|
|
|
3133
3406
|
|
|
3134
3407
|
// src/cli/lib/matrix/matrix-loader.ts
|
|
3135
3408
|
init_esm_shims();
|
|
3136
|
-
import { parse as
|
|
3137
|
-
import
|
|
3409
|
+
import { parse as parseYaml8 } from "yaml";
|
|
3410
|
+
import path20 from "path";
|
|
3138
3411
|
import { z as z3 } from "zod";
|
|
3139
3412
|
var rawMetadataSchema = z3.object({
|
|
3140
3413
|
category: categoryPathSchema,
|
|
3141
|
-
categoryExclusive: z3.boolean().optional(),
|
|
3142
3414
|
author: z3.string(),
|
|
3143
|
-
|
|
3415
|
+
displayName: z3.string().optional(),
|
|
3144
3416
|
cliDescription: z3.string().optional(),
|
|
3145
3417
|
usageGuidance: z3.string().optional(),
|
|
3146
3418
|
tags: z3.array(z3.string()).optional(),
|
|
3147
|
-
// Lenient: accepts display names and skill IDs from YAML, resolved to canonical IDs during matrix merge
|
|
3148
|
-
compatibleWith: z3.array(z3.string()).optional(),
|
|
3149
|
-
conflictsWith: z3.array(z3.string()).optional(),
|
|
3150
|
-
requires: z3.array(z3.string()).optional(),
|
|
3151
|
-
requiresSetup: z3.array(z3.string()).optional(),
|
|
3152
|
-
providesSetupFor: z3.array(z3.string()).optional(),
|
|
3153
3419
|
domain: extensibleDomainSchema.optional(),
|
|
3154
3420
|
custom: z3.boolean().optional()
|
|
3155
3421
|
});
|
|
3156
|
-
|
|
3422
|
+
var KNOWN_DOMAINS = new Set(DOMAIN_VALUES);
|
|
3423
|
+
var AUTO_SYNTH_ORDER = 999;
|
|
3424
|
+
function synthesizeCategory(categoryPath, skillDomain) {
|
|
3425
|
+
const prefix = categoryPath.split("-")[0];
|
|
3426
|
+
const domain = skillDomain ?? (KNOWN_DOMAINS.has(prefix) ? prefix : void 0);
|
|
3427
|
+
const displayName = categoryPath.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3428
|
+
return {
|
|
3429
|
+
id: categoryPath,
|
|
3430
|
+
displayName,
|
|
3431
|
+
description: `Auto-generated category for ${categoryPath}`,
|
|
3432
|
+
domain,
|
|
3433
|
+
exclusive: true,
|
|
3434
|
+
required: false,
|
|
3435
|
+
order: AUTO_SYNTH_ORDER,
|
|
3436
|
+
custom: true
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3439
|
+
async function loadSkillCategories(configPath) {
|
|
3440
|
+
const content = await readFile(configPath);
|
|
3441
|
+
const raw = parseYaml8(content);
|
|
3442
|
+
const result = skillCategoriesFileSchema.safeParse(raw);
|
|
3443
|
+
if (!result.success) {
|
|
3444
|
+
throw new Error(
|
|
3445
|
+
`Invalid skill categories at '${configPath}': ${formatZodErrors(result.error.issues)}`
|
|
3446
|
+
);
|
|
3447
|
+
}
|
|
3448
|
+
verbose(`Loaded skill categories: ${configPath}`);
|
|
3449
|
+
return result.data.categories;
|
|
3450
|
+
}
|
|
3451
|
+
async function loadSkillRules(configPath) {
|
|
3157
3452
|
const content = await readFile(configPath);
|
|
3158
|
-
const raw =
|
|
3159
|
-
const result =
|
|
3453
|
+
const raw = parseYaml8(content);
|
|
3454
|
+
const result = skillRulesFileSchema.safeParse(raw);
|
|
3160
3455
|
if (!result.success) {
|
|
3161
3456
|
throw new Error(
|
|
3162
|
-
`Invalid
|
|
3457
|
+
`Invalid skill rules at '${configPath}': ${formatZodErrors(result.error.issues)}`
|
|
3163
3458
|
);
|
|
3164
3459
|
}
|
|
3165
3460
|
const data = result.data;
|
|
3166
|
-
const
|
|
3461
|
+
const config = {
|
|
3167
3462
|
version: data.version,
|
|
3168
|
-
|
|
3463
|
+
aliases: data.aliases ?? {},
|
|
3169
3464
|
relationships: data.relationships ?? {
|
|
3170
3465
|
conflicts: [],
|
|
3171
3466
|
discourages: [],
|
|
@@ -3173,24 +3468,24 @@ async function loadSkillsMatrix(configPath) {
|
|
|
3173
3468
|
requires: [],
|
|
3174
3469
|
alternatives: []
|
|
3175
3470
|
},
|
|
3176
|
-
|
|
3471
|
+
perSkill: data["per-skill"] ?? {}
|
|
3177
3472
|
};
|
|
3178
|
-
verbose(`Loaded
|
|
3179
|
-
return
|
|
3473
|
+
verbose(`Loaded skill rules: ${configPath}`);
|
|
3474
|
+
return config;
|
|
3180
3475
|
}
|
|
3181
3476
|
async function extractAllSkills(skillsDir) {
|
|
3182
3477
|
const skills = [];
|
|
3183
3478
|
const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);
|
|
3184
3479
|
for (const metadataFile of metadataFiles) {
|
|
3185
|
-
const skillDir =
|
|
3186
|
-
const skillMdPath =
|
|
3187
|
-
const metadataPath =
|
|
3480
|
+
const skillDir = path20.dirname(metadataFile);
|
|
3481
|
+
const skillMdPath = path20.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
|
|
3482
|
+
const metadataPath = path20.join(skillsDir, metadataFile);
|
|
3188
3483
|
if (!await fileExists(skillMdPath)) {
|
|
3189
3484
|
verbose(`Skipping ${metadataFile}: No ${STANDARD_FILES.SKILL_MD} found`);
|
|
3190
3485
|
continue;
|
|
3191
3486
|
}
|
|
3192
3487
|
const metadataContent = await readFile(metadataPath);
|
|
3193
|
-
const rawMetadata =
|
|
3488
|
+
const rawMetadata = parseYaml8(metadataContent);
|
|
3194
3489
|
const metadataResult = rawMetadataSchema.safeParse(rawMetadata);
|
|
3195
3490
|
if (!metadataResult.success) {
|
|
3196
3491
|
warn(
|
|
@@ -3205,9 +3500,9 @@ async function extractAllSkills(skillsDir) {
|
|
|
3205
3500
|
verbose(`Skipping ${metadataFile}: Invalid SKILL.md frontmatter`);
|
|
3206
3501
|
continue;
|
|
3207
3502
|
}
|
|
3208
|
-
if (!metadata.
|
|
3503
|
+
if (!metadata.displayName) {
|
|
3209
3504
|
throw new Error(
|
|
3210
|
-
`Skill at ${metadataFile} is missing required '${METADATA_KEYS.
|
|
3505
|
+
`Skill at ${metadataFile} is missing required '${METADATA_KEYS.DISPLAY_NAME}' field in metadata.yaml`
|
|
3211
3506
|
);
|
|
3212
3507
|
}
|
|
3213
3508
|
const skillId = frontmatter.name;
|
|
@@ -3217,14 +3512,8 @@ async function extractAllSkills(skillsDir) {
|
|
|
3217
3512
|
description: metadata.cliDescription || frontmatter.description,
|
|
3218
3513
|
usageGuidance: metadata.usageGuidance,
|
|
3219
3514
|
category: metadata.category,
|
|
3220
|
-
categoryExclusive: metadata.categoryExclusive ?? true,
|
|
3221
3515
|
author: metadata.author,
|
|
3222
3516
|
tags: metadata.tags ?? [],
|
|
3223
|
-
compatibleWith: metadata.compatibleWith ?? [],
|
|
3224
|
-
conflictsWith: metadata.conflictsWith ?? [],
|
|
3225
|
-
requires: metadata.requires ?? [],
|
|
3226
|
-
requiresSetup: metadata.requiresSetup ?? [],
|
|
3227
|
-
providesSetupFor: metadata.providesSetupFor ?? [],
|
|
3228
3517
|
path: `skills/${skillDir}/`,
|
|
3229
3518
|
...metadata.domain ? { domain: metadata.domain } : {},
|
|
3230
3519
|
...metadata.custom === true ? { custom: true } : {}
|
|
@@ -3271,25 +3560,36 @@ function resolveToCanonicalId(nameOrId, displayNameToId, directoryPathToId = {},
|
|
|
3271
3560
|
}
|
|
3272
3561
|
return nameOrId;
|
|
3273
3562
|
}
|
|
3274
|
-
async function mergeMatrixWithSkills(
|
|
3275
|
-
const displayNameToId =
|
|
3563
|
+
async function mergeMatrixWithSkills(categories, relationships, aliases, skills, perSkillRules) {
|
|
3564
|
+
const displayNameToId = aliases;
|
|
3276
3565
|
const displayNames = buildReverseDisplayNames(displayNameToId);
|
|
3277
3566
|
const directoryPathToId = buildDirectoryPathToIdMap(skills);
|
|
3278
3567
|
const resolvedSkills = {};
|
|
3279
3568
|
for (const skill of skills) {
|
|
3280
3569
|
const resolved = buildResolvedSkill(
|
|
3281
3570
|
skill,
|
|
3282
|
-
|
|
3571
|
+
categories,
|
|
3572
|
+
relationships,
|
|
3283
3573
|
displayNameToId,
|
|
3284
3574
|
displayNames,
|
|
3285
|
-
directoryPathToId
|
|
3575
|
+
directoryPathToId,
|
|
3576
|
+
perSkillRules
|
|
3286
3577
|
);
|
|
3287
3578
|
resolvedSkills[skill.id] = resolved;
|
|
3288
3579
|
}
|
|
3580
|
+
const synthesizedCategories = { ...categories };
|
|
3581
|
+
for (const skill of skills) {
|
|
3582
|
+
const subcategory = skill.category;
|
|
3583
|
+
if (!synthesizedCategories[subcategory]) {
|
|
3584
|
+
const synthesized = synthesizeCategory(skill.category, skill.domain);
|
|
3585
|
+
synthesizedCategories[subcategory] = synthesized;
|
|
3586
|
+
verbose(`Auto-synthesized category '${skill.category}' for skill '${skill.id}'`);
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3289
3589
|
const suggestedStacks = resolveSuggestedStacks();
|
|
3290
3590
|
const merged = {
|
|
3291
|
-
version:
|
|
3292
|
-
categories:
|
|
3591
|
+
version: "1.0.0",
|
|
3592
|
+
categories: synthesizedCategories,
|
|
3293
3593
|
skills: resolvedSkills,
|
|
3294
3594
|
suggestedStacks,
|
|
3295
3595
|
displayNameToId,
|
|
@@ -3382,41 +3682,48 @@ function resolveDiscourages(skillId, discourageRules, resolve) {
|
|
|
3382
3682
|
}
|
|
3383
3683
|
return discourages;
|
|
3384
3684
|
}
|
|
3385
|
-
function buildResolvedSkill(skill,
|
|
3685
|
+
function buildResolvedSkill(skill, _categories, relationships, displayNameToId, displayNames, directoryPathToId, perSkillRules) {
|
|
3386
3686
|
const resolve = (id, context) => resolveToCanonicalId(
|
|
3387
3687
|
id,
|
|
3388
3688
|
displayNameToId,
|
|
3389
3689
|
directoryPathToId,
|
|
3390
3690
|
context ? `${skill.id} ${context}` : void 0
|
|
3391
3691
|
);
|
|
3392
|
-
const
|
|
3692
|
+
const skillAlias = displayNames[skill.id];
|
|
3693
|
+
const perSkill = skillAlias ? perSkillRules?.[skillAlias] : void 0;
|
|
3393
3694
|
return {
|
|
3394
3695
|
id: skill.id,
|
|
3395
3696
|
displayName: displayNames[skill.id],
|
|
3396
3697
|
description: skill.description,
|
|
3397
3698
|
usageGuidance: skill.usageGuidance,
|
|
3398
3699
|
category: skill.category,
|
|
3399
|
-
categoryExclusive: skill.categoryExclusive,
|
|
3400
3700
|
tags: skill.tags,
|
|
3401
3701
|
author: skill.author,
|
|
3402
3702
|
conflictsWith: resolveConflicts(
|
|
3403
3703
|
skill.id,
|
|
3404
|
-
|
|
3704
|
+
perSkill?.conflictsWith ?? [],
|
|
3405
3705
|
relationships.conflicts,
|
|
3406
3706
|
resolve
|
|
3407
3707
|
),
|
|
3408
3708
|
recommends: resolveRecommends(
|
|
3409
3709
|
skill.id,
|
|
3410
|
-
|
|
3710
|
+
perSkill?.compatibleWith ?? [],
|
|
3411
3711
|
relationships.recommends,
|
|
3412
3712
|
resolve
|
|
3413
3713
|
),
|
|
3414
|
-
requires: resolveRequirements(
|
|
3714
|
+
requires: resolveRequirements(
|
|
3715
|
+
skill.id,
|
|
3716
|
+
perSkill?.requires ?? [],
|
|
3717
|
+
relationships.requires,
|
|
3718
|
+
resolve
|
|
3719
|
+
),
|
|
3415
3720
|
alternatives: resolveAlternatives(skill.id, relationships.alternatives, resolve),
|
|
3416
3721
|
discourages: resolveDiscourages(skill.id, relationships.discourages, resolve),
|
|
3417
|
-
compatibleWith:
|
|
3418
|
-
requiresSetup:
|
|
3419
|
-
providesSetupFor:
|
|
3722
|
+
compatibleWith: (perSkill?.compatibleWith ?? []).map((id) => resolve(id, "compatibleWith")),
|
|
3723
|
+
requiresSetup: (perSkill?.requiresSetup ?? []).map((id) => resolve(id, "requiresSetup")),
|
|
3724
|
+
providesSetupFor: (perSkill?.providesSetupFor ?? []).map(
|
|
3725
|
+
(id) => resolve(id, "providesSetupFor")
|
|
3726
|
+
),
|
|
3420
3727
|
path: skill.path
|
|
3421
3728
|
};
|
|
3422
3729
|
}
|
|
@@ -3438,26 +3745,31 @@ function initializeSelectionContext(currentSelections, matrix) {
|
|
|
3438
3745
|
const selectedSet = new Set(resolvedSelections);
|
|
3439
3746
|
return { resolvedSelections, selectedSet };
|
|
3440
3747
|
}
|
|
3441
|
-
function
|
|
3442
|
-
if (options?.expertMode) {
|
|
3443
|
-
return false;
|
|
3444
|
-
}
|
|
3748
|
+
function isDiscouraged(skillId, currentSelections, matrix) {
|
|
3445
3749
|
const fullId = resolveAlias(skillId, matrix);
|
|
3446
3750
|
const skill = matrix.skills[fullId];
|
|
3447
3751
|
if (!skill) {
|
|
3448
3752
|
return false;
|
|
3449
3753
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3754
|
+
const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);
|
|
3755
|
+
for (const selectedId of resolvedSelections) {
|
|
3756
|
+
const selectedSkill = matrix.skills[selectedId];
|
|
3757
|
+
if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {
|
|
3758
|
+
return true;
|
|
3759
|
+
}
|
|
3760
|
+
if (skill.discourages.some((d) => d.skillId === selectedId)) {
|
|
3761
|
+
return true;
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
for (const selectedId of resolvedSelections) {
|
|
3765
|
+
if (skill.conflictsWith.some((c) => c.skillId === selectedId)) {
|
|
3453
3766
|
return true;
|
|
3454
3767
|
}
|
|
3455
|
-
const selectedSkill = matrix.skills[
|
|
3768
|
+
const selectedSkill = matrix.skills[selectedId];
|
|
3456
3769
|
if (selectedSkill?.conflictsWith.some((c) => c.skillId === fullId)) {
|
|
3457
3770
|
return true;
|
|
3458
3771
|
}
|
|
3459
3772
|
}
|
|
3460
|
-
const { selectedSet } = initializeSelectionContext(currentSelections, matrix);
|
|
3461
3773
|
for (const requirement of skill.requires) {
|
|
3462
3774
|
if (requirement.needsAny) {
|
|
3463
3775
|
const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));
|
|
@@ -3473,13 +3785,26 @@ function isDisabled(skillId, currentSelections, matrix, options) {
|
|
|
3473
3785
|
}
|
|
3474
3786
|
return false;
|
|
3475
3787
|
}
|
|
3476
|
-
function
|
|
3788
|
+
function getDiscourageReason(skillId, currentSelections, matrix) {
|
|
3477
3789
|
const fullId = resolveAlias(skillId, matrix);
|
|
3478
3790
|
const skill = matrix.skills[fullId];
|
|
3479
3791
|
if (!skill) {
|
|
3480
3792
|
return void 0;
|
|
3481
3793
|
}
|
|
3482
3794
|
const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);
|
|
3795
|
+
for (const selectedId of resolvedSelections) {
|
|
3796
|
+
const selectedSkill = matrix.skills[selectedId];
|
|
3797
|
+
if (selectedSkill) {
|
|
3798
|
+
const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);
|
|
3799
|
+
if (discourage) {
|
|
3800
|
+
return discourage.reason;
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);
|
|
3804
|
+
if (reverseDiscourage) {
|
|
3805
|
+
return reverseDiscourage.reason;
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3483
3808
|
for (const selectedId of resolvedSelections) {
|
|
3484
3809
|
const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);
|
|
3485
3810
|
if (conflict) {
|
|
@@ -3511,46 +3836,6 @@ function getDisableReason(skillId, currentSelections, matrix) {
|
|
|
3511
3836
|
}
|
|
3512
3837
|
return void 0;
|
|
3513
3838
|
}
|
|
3514
|
-
function isDiscouraged(skillId, currentSelections, matrix) {
|
|
3515
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
3516
|
-
const skill = matrix.skills[fullId];
|
|
3517
|
-
if (!skill) {
|
|
3518
|
-
return false;
|
|
3519
|
-
}
|
|
3520
|
-
const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);
|
|
3521
|
-
for (const selectedId of resolvedSelections) {
|
|
3522
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
3523
|
-
if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {
|
|
3524
|
-
return true;
|
|
3525
|
-
}
|
|
3526
|
-
if (skill.discourages.some((d) => d.skillId === selectedId)) {
|
|
3527
|
-
return true;
|
|
3528
|
-
}
|
|
3529
|
-
}
|
|
3530
|
-
return false;
|
|
3531
|
-
}
|
|
3532
|
-
function getDiscourageReason(skillId, currentSelections, matrix) {
|
|
3533
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
3534
|
-
const skill = matrix.skills[fullId];
|
|
3535
|
-
if (!skill) {
|
|
3536
|
-
return void 0;
|
|
3537
|
-
}
|
|
3538
|
-
const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);
|
|
3539
|
-
for (const selectedId of resolvedSelections) {
|
|
3540
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
3541
|
-
if (selectedSkill) {
|
|
3542
|
-
const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);
|
|
3543
|
-
if (discourage) {
|
|
3544
|
-
return discourage.reason;
|
|
3545
|
-
}
|
|
3546
|
-
}
|
|
3547
|
-
const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);
|
|
3548
|
-
if (reverseDiscourage) {
|
|
3549
|
-
return reverseDiscourage.reason;
|
|
3550
|
-
}
|
|
3551
|
-
}
|
|
3552
|
-
return void 0;
|
|
3553
|
-
}
|
|
3554
3839
|
function isRecommended(skillId, currentSelections, matrix) {
|
|
3555
3840
|
const fullId = resolveAlias(skillId, matrix);
|
|
3556
3841
|
const skill = matrix.skills[fullId];
|
|
@@ -3713,7 +3998,7 @@ function validateSelection(selections, matrix) {
|
|
|
3713
3998
|
warnings
|
|
3714
3999
|
};
|
|
3715
4000
|
}
|
|
3716
|
-
function getAvailableSkills(categoryId, currentSelections, matrix
|
|
4001
|
+
function getAvailableSkills(categoryId, currentSelections, matrix) {
|
|
3717
4002
|
const skillOptions = [];
|
|
3718
4003
|
const { selectedSet } = initializeSelectionContext(currentSelections, matrix);
|
|
3719
4004
|
for (const skill of Object.values(matrix.skills)) {
|
|
@@ -3721,15 +4006,12 @@ function getAvailableSkills(categoryId, currentSelections, matrix, options) {
|
|
|
3721
4006
|
if (skill.category !== categoryId) {
|
|
3722
4007
|
continue;
|
|
3723
4008
|
}
|
|
3724
|
-
const
|
|
3725
|
-
const
|
|
3726
|
-
const recommended = !disabled && !discouraged && isRecommended(skill.id, currentSelections, matrix);
|
|
4009
|
+
const discouraged = isDiscouraged(skill.id, currentSelections, matrix);
|
|
4010
|
+
const recommended = !discouraged && isRecommended(skill.id, currentSelections, matrix);
|
|
3727
4011
|
skillOptions.push({
|
|
3728
4012
|
id: skill.id,
|
|
3729
4013
|
displayName: skill.displayName,
|
|
3730
4014
|
description: skill.description,
|
|
3731
|
-
disabled,
|
|
3732
|
-
disabledReason: disabled ? getDisableReason(skill.id, currentSelections, matrix) : void 0,
|
|
3733
4015
|
discouraged,
|
|
3734
4016
|
discouragedReason: discouraged ? getDiscourageReason(skill.id, currentSelections, matrix) : void 0,
|
|
3735
4017
|
recommended,
|
|
@@ -3768,12 +4050,15 @@ function checkSubcategoryDomains(matrix, issues) {
|
|
|
3768
4050
|
function checkSkillCategories(matrix, issues) {
|
|
3769
4051
|
for (const [skillId, skill] of typedEntries(matrix.skills)) {
|
|
3770
4052
|
if (!skill) continue;
|
|
3771
|
-
|
|
4053
|
+
const category = matrix.categories[skill.category];
|
|
4054
|
+
if (!category) {
|
|
3772
4055
|
issues.push({
|
|
3773
4056
|
severity: "warning",
|
|
3774
4057
|
finding: "skill-unknown-category",
|
|
3775
4058
|
details: `Skill '${skillId}' references category '${skill.category}' which does not exist in the matrix`
|
|
3776
4059
|
});
|
|
4060
|
+
} else if (category.custom) {
|
|
4061
|
+
verbose(`Skill '${skillId}' uses auto-synthesized category '${skill.category}'`);
|
|
3777
4062
|
}
|
|
3778
4063
|
}
|
|
3779
4064
|
}
|
|
@@ -3821,7 +4106,7 @@ function checkSkillRelationRefs(matrix, issues) {
|
|
|
3821
4106
|
|
|
3822
4107
|
// src/cli/lib/loading/multi-source-loader.ts
|
|
3823
4108
|
init_esm_shims();
|
|
3824
|
-
import
|
|
4109
|
+
import path21 from "path";
|
|
3825
4110
|
async function loadSkillsFromAllSources(primaryMatrix, sourceConfig, projectDir, forceRefresh = false, marketplace) {
|
|
3826
4111
|
const resolvedMarketplace = marketplace ?? sourceConfig.marketplace;
|
|
3827
4112
|
const isDefaultPublicSource = sourceConfig.source === DEFAULT_SOURCE;
|
|
@@ -3910,7 +4195,7 @@ async function tagPublicSourceSkills(matrix, forceRefresh) {
|
|
|
3910
4195
|
}
|
|
3911
4196
|
try {
|
|
3912
4197
|
const fetchResult = await fetchFromSource(DEFAULT_SOURCE, { forceRefresh });
|
|
3913
|
-
const skillsDir =
|
|
4198
|
+
const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
|
|
3914
4199
|
const publicSkills = await extractAllSkills(skillsDir);
|
|
3915
4200
|
let matchCount = 0;
|
|
3916
4201
|
for (const publicSkill of publicSkills) {
|
|
@@ -3948,7 +4233,7 @@ async function tagExtraSources(matrix, projectDir, forceRefresh) {
|
|
|
3948
4233
|
verbose(`Loading extra source: ${extraSource.name} (${extraSource.url})`);
|
|
3949
4234
|
try {
|
|
3950
4235
|
const fetchResult = await fetchFromSource(extraSource.url, { forceRefresh });
|
|
3951
|
-
const skillsDir =
|
|
4236
|
+
const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
|
|
3952
4237
|
const skills = await extractAllSkills(skillsDir);
|
|
3953
4238
|
let matchCount = 0;
|
|
3954
4239
|
for (const extractedSkill of skills) {
|
|
@@ -3991,7 +4276,7 @@ async function searchExtraSources(alias, configuredSources) {
|
|
|
3991
4276
|
for (const source of configuredSources) {
|
|
3992
4277
|
try {
|
|
3993
4278
|
const fetchResult = await fetchFromSource(source.url, { forceRefresh: false });
|
|
3994
|
-
const skillsDir =
|
|
4279
|
+
const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
|
|
3995
4280
|
const skills = await extractAllSkills(skillsDir);
|
|
3996
4281
|
for (const skill of skills) {
|
|
3997
4282
|
const segments = skill.directoryPath.split("/");
|
|
@@ -4029,7 +4314,11 @@ async function loadSkillsMatrixFromSource(options = {}) {
|
|
|
4029
4314
|
result = await loadFromRemote(source, sourceConfig, forceRefresh);
|
|
4030
4315
|
}
|
|
4031
4316
|
const resolvedProjectDir = projectDir || process.cwd();
|
|
4032
|
-
|
|
4317
|
+
let localSkillsResult = await discoverLocalSkills(resolvedProjectDir);
|
|
4318
|
+
const homeDir = os6.homedir();
|
|
4319
|
+
if ((!localSkillsResult || localSkillsResult.skills.length === 0) && resolvedProjectDir !== homeDir) {
|
|
4320
|
+
localSkillsResult = await discoverLocalSkills(homeDir);
|
|
4321
|
+
}
|
|
4033
4322
|
if (localSkillsResult && localSkillsResult.skills.length > 0) {
|
|
4034
4323
|
verbose(
|
|
4035
4324
|
`Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`
|
|
@@ -4049,7 +4338,7 @@ async function loadSkillsMatrixFromSource(options = {}) {
|
|
|
4049
4338
|
async function loadFromLocal(source, sourceConfig) {
|
|
4050
4339
|
let skillsPath;
|
|
4051
4340
|
if (isLocalSource(source)) {
|
|
4052
|
-
skillsPath =
|
|
4341
|
+
skillsPath = path22.isAbsolute(source) ? source : path22.resolve(process.cwd(), source);
|
|
4053
4342
|
} else {
|
|
4054
4343
|
skillsPath = PROJECT_ROOT;
|
|
4055
4344
|
}
|
|
@@ -4088,47 +4377,62 @@ async function loadFromRemote(source, sourceConfig, forceRefresh) {
|
|
|
4088
4377
|
}
|
|
4089
4378
|
async function loadAndMergeFromBasePath(basePath) {
|
|
4090
4379
|
const sourceProjectConfig = await loadProjectSourceConfig(basePath);
|
|
4091
|
-
const matrixRelPath = sourceProjectConfig?.matrixFile ?? SKILLS_MATRIX_PATH;
|
|
4092
4380
|
const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;
|
|
4093
4381
|
const stacksRelFile = sourceProjectConfig?.stacksFile;
|
|
4094
|
-
const
|
|
4095
|
-
const
|
|
4096
|
-
|
|
4382
|
+
const cliCategoriesPath = path22.join(PROJECT_ROOT, SKILL_CATEGORIES_YAML_PATH);
|
|
4383
|
+
const cliRulesPath = path22.join(PROJECT_ROOT, SKILL_RULES_YAML_PATH);
|
|
4384
|
+
const cliCategories = await loadSkillCategories(cliCategoriesPath);
|
|
4385
|
+
const cliRules = await loadSkillRules(cliRulesPath);
|
|
4386
|
+
let categories = cliCategories;
|
|
4387
|
+
let relationships = cliRules.relationships;
|
|
4388
|
+
let aliases = cliRules.aliases;
|
|
4389
|
+
let perSkillRules = cliRules.perSkill;
|
|
4097
4390
|
await discoverAndExtendFromSource(basePath);
|
|
4098
|
-
const
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4391
|
+
const sourceCategoriesPath = path22.join(basePath, SKILL_CATEGORIES_YAML_PATH);
|
|
4392
|
+
const sourceRulesPath = path22.join(basePath, SKILL_RULES_YAML_PATH);
|
|
4393
|
+
const hasSourceCategories = await fileExists(sourceCategoriesPath);
|
|
4394
|
+
const hasSourceRules = await fileExists(sourceRulesPath);
|
|
4395
|
+
if (hasSourceCategories || hasSourceRules) {
|
|
4396
|
+
if (hasSourceCategories) {
|
|
4397
|
+
const sourceCategories = await loadSkillCategories(sourceCategoriesPath);
|
|
4398
|
+
categories = { ...cliCategories, ...sourceCategories };
|
|
4399
|
+
verbose(
|
|
4400
|
+
`Loaded source categories: ${sourceCategoriesPath} (${typedKeys(sourceCategories).length} categories)`
|
|
4401
|
+
);
|
|
4402
|
+
}
|
|
4403
|
+
if (hasSourceRules) {
|
|
4404
|
+
const sourceRules = await loadSkillRules(sourceRulesPath);
|
|
4405
|
+
relationships = {
|
|
4406
|
+
conflicts: [...cliRules.relationships.conflicts, ...sourceRules.relationships.conflicts],
|
|
4407
|
+
discourages: [
|
|
4408
|
+
...cliRules.relationships.discourages,
|
|
4409
|
+
...sourceRules.relationships.discourages
|
|
4410
|
+
],
|
|
4411
|
+
recommends: [...cliRules.relationships.recommends, ...sourceRules.relationships.recommends],
|
|
4412
|
+
requires: [...cliRules.relationships.requires, ...sourceRules.relationships.requires],
|
|
4413
|
+
alternatives: [
|
|
4414
|
+
...cliRules.relationships.alternatives,
|
|
4415
|
+
...sourceRules.relationships.alternatives
|
|
4416
|
+
]
|
|
4417
|
+
};
|
|
4418
|
+
aliases = { ...cliRules.aliases, ...sourceRules.aliases };
|
|
4419
|
+
perSkillRules = { ...cliRules.perSkill, ...sourceRules.perSkill };
|
|
4420
|
+
verbose(`Loaded source rules: ${sourceRulesPath}`);
|
|
4421
|
+
}
|
|
4422
|
+
verbose(`Matrix merged: CLI (${typedKeys(cliCategories).length} categories) + source`);
|
|
4125
4423
|
} else {
|
|
4126
|
-
verbose(`Matrix from CLI only (source has no
|
|
4424
|
+
verbose(`Matrix from CLI only (source has no categories/rules files)`);
|
|
4127
4425
|
}
|
|
4128
|
-
const skillsDir =
|
|
4426
|
+
const skillsDir = path22.join(basePath, skillsDirRelPath);
|
|
4129
4427
|
verbose(`Skills from source: ${skillsDir}`);
|
|
4130
4428
|
const skills = await extractAllSkills(skillsDir);
|
|
4131
|
-
const mergedMatrix = await mergeMatrixWithSkills(
|
|
4429
|
+
const mergedMatrix = await mergeMatrixWithSkills(
|
|
4430
|
+
categories,
|
|
4431
|
+
relationships,
|
|
4432
|
+
aliases,
|
|
4433
|
+
skills,
|
|
4434
|
+
perSkillRules
|
|
4435
|
+
);
|
|
4132
4436
|
const sourceStacks = await loadStacks(basePath, stacksRelFile);
|
|
4133
4437
|
const stacks = sourceStacks.length > 0 ? sourceStacks : await loadStacks(PROJECT_ROOT);
|
|
4134
4438
|
if (stacks.length > 0) {
|
|
@@ -4206,9 +4510,9 @@ function getMarketplaceLabel(sourceResult) {
|
|
|
4206
4510
|
}
|
|
4207
4511
|
return marketplace;
|
|
4208
4512
|
}
|
|
4209
|
-
async function discoverCustomAgentValues(agentsDir, file,
|
|
4210
|
-
const content = await readFile(
|
|
4211
|
-
const raw =
|
|
4513
|
+
async function discoverCustomAgentValues(agentsDir, file, parseYaml10, builtinDomains) {
|
|
4514
|
+
const content = await readFile(path22.join(agentsDir, file));
|
|
4515
|
+
const raw = parseYaml10(content);
|
|
4212
4516
|
if (raw?.custom !== true) return {};
|
|
4213
4517
|
const result = {};
|
|
4214
4518
|
if (typeof raw?.id === "string" && !agentNameSchema.safeParse(raw.id).success) {
|
|
@@ -4219,16 +4523,16 @@ async function discoverCustomAgentValues(agentsDir, file, parseYaml9, builtinDom
|
|
|
4219
4523
|
}
|
|
4220
4524
|
return result;
|
|
4221
4525
|
}
|
|
4222
|
-
async function discoverCustomSkillValues(skillsDir, file,
|
|
4223
|
-
const content = await readFile(
|
|
4526
|
+
async function discoverCustomSkillValues(skillsDir, file, parseYaml10, builtinSubcategories, builtinDomains) {
|
|
4527
|
+
const content = await readFile(path22.join(skillsDir, file));
|
|
4224
4528
|
const frontmatter = parseFrontmatter(content);
|
|
4225
4529
|
if (!frontmatter) return {};
|
|
4226
4530
|
const skillId = frontmatter.name;
|
|
4227
|
-
const skillDir =
|
|
4228
|
-
const metadataPath =
|
|
4531
|
+
const skillDir = path22.dirname(path22.join(skillsDir, file));
|
|
4532
|
+
const metadataPath = path22.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
4229
4533
|
if (!await fileExists(metadataPath)) return {};
|
|
4230
4534
|
const metadataContent = await readFile(metadataPath);
|
|
4231
|
-
const metadataRaw =
|
|
4535
|
+
const metadataRaw = parseYaml10(metadataContent);
|
|
4232
4536
|
if (metadataRaw?.custom !== true) return {};
|
|
4233
4537
|
const result = {};
|
|
4234
4538
|
result.skillId = skillId;
|
|
@@ -4243,26 +4547,26 @@ async function discoverCustomSkillValues(skillsDir, file, parseYaml9, builtinSub
|
|
|
4243
4547
|
return result;
|
|
4244
4548
|
}
|
|
4245
4549
|
async function discoverAndExtendFromSource(basePath) {
|
|
4246
|
-
const { parse:
|
|
4550
|
+
const { parse: parseYaml10 } = await import("yaml");
|
|
4247
4551
|
const builtinSubcategories = new Set(SUBCATEGORY_VALUES);
|
|
4248
4552
|
const builtinDomains = new Set(DOMAIN_VALUES);
|
|
4249
4553
|
const customCategories = [];
|
|
4250
4554
|
const customDomains = [];
|
|
4251
4555
|
const customAgentNames = [];
|
|
4252
4556
|
const customSkillIds = [];
|
|
4253
|
-
const agentsDir =
|
|
4557
|
+
const agentsDir = path22.join(basePath, DIRS.agents);
|
|
4254
4558
|
if (await directoryExists(agentsDir)) {
|
|
4255
|
-
const agentFiles = await glob(`**/${STANDARD_FILES.
|
|
4559
|
+
const agentFiles = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, agentsDir);
|
|
4256
4560
|
for (const file of agentFiles) {
|
|
4257
4561
|
try {
|
|
4258
|
-
const result = await discoverCustomAgentValues(agentsDir, file,
|
|
4562
|
+
const result = await discoverCustomAgentValues(agentsDir, file, parseYaml10, builtinDomains);
|
|
4259
4563
|
if (result.agentName) customAgentNames.push(result.agentName);
|
|
4260
4564
|
if (result.domain) customDomains.push(result.domain);
|
|
4261
4565
|
} catch {
|
|
4262
4566
|
}
|
|
4263
4567
|
}
|
|
4264
4568
|
}
|
|
4265
|
-
const skillsDir =
|
|
4569
|
+
const skillsDir = path22.join(basePath, DIRS.skills);
|
|
4266
4570
|
if (await directoryExists(skillsDir)) {
|
|
4267
4571
|
const skillFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
|
|
4268
4572
|
for (const file of skillFiles) {
|
|
@@ -4270,7 +4574,7 @@ async function discoverAndExtendFromSource(basePath) {
|
|
|
4270
4574
|
const result = await discoverCustomSkillValues(
|
|
4271
4575
|
skillsDir,
|
|
4272
4576
|
file,
|
|
4273
|
-
|
|
4577
|
+
parseYaml10,
|
|
4274
4578
|
builtinSubcategories,
|
|
4275
4579
|
builtinDomains
|
|
4276
4580
|
);
|
|
@@ -4305,7 +4609,6 @@ function mergeLocalSkillsIntoMatrix(matrix, localResult) {
|
|
|
4305
4609
|
description: metadata.description,
|
|
4306
4610
|
usageGuidance: metadata.usageGuidance,
|
|
4307
4611
|
category,
|
|
4308
|
-
categoryExclusive: metadata.categoryExclusive,
|
|
4309
4612
|
tags: metadata.tags ?? [],
|
|
4310
4613
|
author: LOCAL_DEFAULTS.AUTHOR,
|
|
4311
4614
|
conflictsWith: existingSkill?.conflictsWith ?? [],
|
|
@@ -4328,7 +4631,7 @@ function mergeLocalSkillsIntoMatrix(matrix, localResult) {
|
|
|
4328
4631
|
|
|
4329
4632
|
// src/cli/lib/skills/local-skill-loader.ts
|
|
4330
4633
|
async function discoverLocalSkills(projectDir) {
|
|
4331
|
-
const localSkillsPath =
|
|
4634
|
+
const localSkillsPath = path23.join(projectDir, LOCAL_SKILLS_PATH);
|
|
4332
4635
|
if (!await directoryExists(localSkillsPath)) {
|
|
4333
4636
|
verbose(`Local skills directory not found: ${localSkillsPath}`);
|
|
4334
4637
|
return null;
|
|
@@ -4348,9 +4651,9 @@ async function discoverLocalSkills(projectDir) {
|
|
|
4348
4651
|
};
|
|
4349
4652
|
}
|
|
4350
4653
|
async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
4351
|
-
const skillDir =
|
|
4352
|
-
const metadataPath =
|
|
4353
|
-
const skillMdPath =
|
|
4654
|
+
const skillDir = path23.join(localSkillsPath, skillDirName);
|
|
4655
|
+
const metadataPath = path23.join(skillDir, STANDARD_FILES.METADATA_YAML);
|
|
4656
|
+
const skillMdPath = path23.join(skillDir, STANDARD_FILES.SKILL_MD);
|
|
4354
4657
|
if (!await fileExists(metadataPath)) {
|
|
4355
4658
|
verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);
|
|
4356
4659
|
return null;
|
|
@@ -4360,24 +4663,23 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
|
4360
4663
|
return null;
|
|
4361
4664
|
}
|
|
4362
4665
|
const metadataContent = await readFile(metadataPath);
|
|
4363
|
-
const parsed = localRawMetadataSchema.safeParse(
|
|
4666
|
+
const parsed = localRawMetadataSchema.safeParse(parseYaml9(metadataContent));
|
|
4364
4667
|
if (!parsed.success) {
|
|
4365
|
-
|
|
4668
|
+
verbose(
|
|
4366
4669
|
`Skipping local skill '${skillDirName}': invalid metadata.yaml \u2014 ${formatZodErrors(parsed.error.issues)}`
|
|
4367
4670
|
);
|
|
4368
4671
|
return null;
|
|
4369
4672
|
}
|
|
4370
4673
|
const metadata = parsed.data;
|
|
4371
|
-
if (!metadata.
|
|
4372
|
-
|
|
4373
|
-
`
|
|
4674
|
+
if (!metadata.displayName) {
|
|
4675
|
+
throw new Error(
|
|
4676
|
+
`Local skill '${skillDirName}' is missing required '${METADATA_KEYS.DISPLAY_NAME}' field in metadata.yaml`
|
|
4374
4677
|
);
|
|
4375
|
-
return null;
|
|
4376
4678
|
}
|
|
4377
4679
|
const skillMdContent = await readFile(skillMdPath);
|
|
4378
4680
|
const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);
|
|
4379
4681
|
if (!frontmatter) {
|
|
4380
|
-
|
|
4682
|
+
verbose(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);
|
|
4381
4683
|
return null;
|
|
4382
4684
|
}
|
|
4383
4685
|
const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;
|
|
@@ -4394,14 +4696,8 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
|
|
|
4394
4696
|
description: metadata.cliDescription || frontmatter.description,
|
|
4395
4697
|
usageGuidance: metadata.usageGuidance,
|
|
4396
4698
|
category,
|
|
4397
|
-
categoryExclusive: metadata.categoryExclusive ?? false,
|
|
4398
4699
|
author: LOCAL_DEFAULTS.AUTHOR,
|
|
4399
4700
|
tags: metadata.tags ?? [],
|
|
4400
|
-
compatibleWith: metadata.compatibleWith ?? [],
|
|
4401
|
-
conflictsWith: metadata.conflictsWith ?? [],
|
|
4402
|
-
requires: metadata.requires ?? [],
|
|
4403
|
-
requiresSetup: metadata.requiresSetup ?? [],
|
|
4404
|
-
providesSetupFor: metadata.providesSetupFor ?? [],
|
|
4405
4701
|
path: relativePath,
|
|
4406
4702
|
local: true,
|
|
4407
4703
|
localPath: relativePath
|
|
@@ -4518,7 +4814,8 @@ export {
|
|
|
4518
4814
|
printCompilationSummary,
|
|
4519
4815
|
archiveLocalSkill,
|
|
4520
4816
|
restoreArchivedSkill,
|
|
4521
|
-
|
|
4817
|
+
loadSkillCategories,
|
|
4818
|
+
loadSkillRules,
|
|
4522
4819
|
extractAllSkills,
|
|
4523
4820
|
mergeMatrixWithSkills,
|
|
4524
4821
|
resolveAlias,
|
|
@@ -4542,13 +4839,16 @@ export {
|
|
|
4542
4839
|
addSource,
|
|
4543
4840
|
removeSource,
|
|
4544
4841
|
getSourceSummary,
|
|
4842
|
+
detectProjectInstallation,
|
|
4545
4843
|
detectInstallation,
|
|
4546
4844
|
installPluginConfig,
|
|
4547
4845
|
installLocal,
|
|
4548
4846
|
getInstallationInfo,
|
|
4549
4847
|
formatInstallationDisplay,
|
|
4848
|
+
validateAllSchemas,
|
|
4849
|
+
printValidationResults,
|
|
4550
4850
|
validatePlugin,
|
|
4551
4851
|
validateAllPlugins,
|
|
4552
4852
|
printPluginValidationResult
|
|
4553
4853
|
};
|
|
4554
|
-
//# sourceMappingURL=chunk-
|
|
4854
|
+
//# sourceMappingURL=chunk-HMSHB5EQ.js.map
|