agents-inc 0.154.0 → 0.156.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 +55 -0
- package/dist/chunk-2H7UWE2G.js +246 -0
- package/dist/chunk-2H7UWE2G.js.map +1 -0
- package/dist/{chunk-LA3JPESW.js → chunk-4A4L3YIW.js} +5 -5
- package/dist/chunk-4G2YHZIM.js +132 -0
- package/dist/chunk-4G2YHZIM.js.map +1 -0
- package/dist/{chunk-BZ4CZBOM.js → chunk-5F2YR5XV.js} +3 -3
- package/dist/{chunk-CHNA5RVS.js → chunk-5OKLCVM4.js} +3 -3
- package/dist/{chunk-ZU6DAR4S.js → chunk-5QZAK6J7.js} +7 -7
- package/dist/{chunk-ZU6DAR4S.js.map → chunk-5QZAK6J7.js.map} +1 -1
- package/dist/{chunk-NFH6SA62.js → chunk-6RLV45HN.js} +10 -10
- package/dist/{chunk-NFH6SA62.js.map → chunk-6RLV45HN.js.map} +1 -1
- package/dist/{chunk-GUDGCFSF.js → chunk-CLFHC2DK.js} +15 -106
- package/dist/chunk-CLFHC2DK.js.map +1 -0
- package/dist/chunk-D2CAV7MG.js +61 -0
- package/dist/chunk-D2CAV7MG.js.map +1 -0
- package/dist/{chunk-UW44KSYL.js → chunk-F2AMBBIA.js} +6 -6
- package/dist/{chunk-UW44KSYL.js.map → chunk-F2AMBBIA.js.map} +1 -1
- package/dist/{chunk-QQTYMW7N.js → chunk-F5T6TV4Z.js} +206 -73
- package/dist/chunk-F5T6TV4Z.js.map +1 -0
- package/dist/{chunk-K3O3YQYG.js → chunk-G47TDUK3.js} +2 -2
- package/dist/{chunk-AURY6RT6.js → chunk-GS2NZ3GD.js} +8 -8
- package/dist/chunk-GS2NZ3GD.js.map +1 -0
- package/dist/{chunk-5MFJ24VM.js → chunk-H6UTKTLK.js} +104 -250
- package/dist/chunk-H6UTKTLK.js.map +1 -0
- package/dist/{chunk-MJFIO5SX.js → chunk-HG4JPXJT.js} +11 -11
- package/dist/chunk-HG4JPXJT.js.map +1 -0
- package/dist/{chunk-IXEDSKMH.js → chunk-HTYH7CKN.js} +3 -3
- package/dist/{chunk-JC7DBPRD.js → chunk-HXKOIWLU.js} +2 -2
- package/dist/chunk-HXKOIWLU.js.map +1 -0
- package/dist/{chunk-NSJ2S7R5.js → chunk-ILUVL7WM.js} +2 -2
- package/dist/{chunk-R54KIGN2.js → chunk-IO5YBKHV.js} +13 -2
- package/dist/chunk-IO5YBKHV.js.map +1 -0
- package/dist/chunk-IXRZAHZF.js +53 -0
- package/dist/chunk-IXRZAHZF.js.map +1 -0
- package/dist/chunk-JCPANDNR.js +35 -0
- package/dist/chunk-JCPANDNR.js.map +1 -0
- package/dist/{chunk-NKCY2ULI.js → chunk-LJCNUP6M.js} +2 -2
- package/dist/{chunk-PRJD5MMQ.js → chunk-MHRC3KRX.js} +5 -5
- package/dist/chunk-MHRC3KRX.js.map +1 -0
- package/dist/chunk-MO5FGLVS.js +142 -0
- package/dist/chunk-MO5FGLVS.js.map +1 -0
- package/dist/{chunk-Q5FLW4JG.js → chunk-OKH64JZE.js} +2 -2
- package/dist/{chunk-WRRP47PY.js → chunk-PCC4LBKB.js} +2 -2
- package/dist/chunk-PMUABBPG.js +258 -0
- package/dist/chunk-PMUABBPG.js.map +1 -0
- package/dist/{chunk-2IMYK4WN.js → chunk-PNMM5HNX.js} +5 -5
- package/dist/{chunk-AKQ5QISO.js → chunk-QWVXOCXO.js} +6 -6
- package/dist/{chunk-IPJOMAWC.js → chunk-RWOYPOMR.js} +12 -2
- package/dist/{chunk-IPJOMAWC.js.map → chunk-RWOYPOMR.js.map} +1 -1
- package/dist/{chunk-ONWEOS77.js → chunk-SY4X2LND.js} +4 -4
- package/dist/{chunk-XGMOXMS4.js → chunk-TBOVYLQJ.js} +2 -2
- package/dist/{chunk-R7JV22QK.js → chunk-TNGMF4UX.js} +20 -20
- package/dist/{chunk-R7JV22QK.js.map → chunk-TNGMF4UX.js.map} +1 -1
- package/dist/{chunk-7VZV4O6B.js → chunk-UMH2YZKG.js} +14 -5
- package/dist/chunk-UMH2YZKG.js.map +1 -0
- package/dist/{chunk-6CNRMCFM.js → chunk-VPASBA7P.js} +2 -2
- package/dist/{chunk-CBF4ZYV3.js → chunk-WCAUUBHO.js} +1376 -741
- package/dist/chunk-WCAUUBHO.js.map +1 -0
- package/dist/{chunk-V3ENMW7G.js → chunk-WFRTHH3A.js} +3 -3
- package/dist/{chunk-DRKSYJZ2.js → chunk-WTJ3AY33.js} +1 -1
- package/dist/{chunk-DRKSYJZ2.js.map → chunk-WTJ3AY33.js.map} +1 -1
- package/dist/{chunk-XMEIVWAS.js → chunk-WUQ3MTPF.js} +11 -5
- package/dist/{chunk-XMEIVWAS.js.map → chunk-WUQ3MTPF.js.map} +1 -1
- package/dist/{chunk-4VCWL2IG.js → chunk-XAXJWXI4.js} +92 -59
- package/dist/chunk-XAXJWXI4.js.map +1 -0
- package/dist/{chunk-B66SC72V.js → chunk-Y5Y7XHVU.js} +4 -4
- package/dist/{chunk-FMYHWKGG.js → chunk-YO2LTXB4.js} +66 -16
- package/dist/chunk-YO2LTXB4.js.map +1 -0
- package/dist/{chunk-TUQF577Z.js → chunk-ZUAZHDKP.js} +40 -41
- package/dist/chunk-ZUAZHDKP.js.map +1 -0
- package/dist/commands/build/marketplace.js +98 -121
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +8 -8
- package/dist/commands/compile.js +19 -24
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +220 -79
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +549 -75
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +26 -21
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +41 -39
- package/dist/commands/list.js +11 -11
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +243 -0
- package/dist/commands/new/marketplace.js.map +1 -0
- package/dist/commands/search.js +16 -14
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +67 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/uninstall.js +61 -74
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +1 -1
- package/dist/components/common/removal-plan-confirm.js +10 -0
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +5 -5
- package/dist/components/wizard/checkbox-grid.js +5 -5
- package/dist/components/wizard/domain-selection.js +11 -11
- package/dist/components/wizard/run-wizard-session.js +29 -28
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +6 -6
- package/dist/components/wizard/source-grid.js +6 -6
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -11
- package/dist/components/wizard/step-build.js +9 -9
- package/dist/components/wizard/step-confirm.js +10 -10
- package/dist/components/wizard/step-sources.js +10 -10
- package/dist/components/wizard/step-stack.js +9 -9
- package/dist/components/wizard/summary-panel.js +9 -9
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +14 -14
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +27 -27
- package/dist/copy-local-skills-NSUTBVLJ.js +14 -0
- package/dist/hooks/init.js +42 -62
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-X4E57I2U.js +15 -0
- package/dist/{loader-JIZDTR4G.js → loader-G6BFG2VA.js} +3 -3
- package/dist/recompile-project-agents-JE4MM72I.js +20 -0
- package/dist/{source-loader-OE6EJFPU.js → source-loader-3DL3NYUX.js} +7 -5
- package/dist/source-loader-3DL3NYUX.js.map +1 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/dist/src/agents/developer/ai-developer/identity.md +1 -1
- package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
- package/dist/src/agents/developer/api-developer/identity.md +1 -1
- package/dist/src/agents/developer/cli-developer/identity.md +1 -1
- package/dist/src/agents/developer/web-developer/identity.md +1 -1
- package/dist/src/agents/meta/codex-keeper/identity.md +1 -1
- package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
- package/dist/src/agents/meta/skill-summoner/identity.md +1 -1
- package/dist/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/api-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/web-researcher/identity.md +1 -1
- package/dist/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/dist/src/agents/tester/ai-tester/identity.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/dist/src/agents/tester/api-tester/identity.md +2 -2
- package/dist/src/agents/tester/cli-tester/identity.md +1 -1
- package/dist/src/agents/tester/web-tester/identity.md +3 -3
- package/dist/stores/wizard-store.js +7 -5
- package/package.json +10 -7
- package/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/src/agents/developer/ai-developer/identity.md +1 -1
- package/src/agents/developer/ai-developer/playbook.md +1 -1
- package/src/agents/developer/api-developer/identity.md +1 -1
- package/src/agents/developer/cli-developer/identity.md +1 -1
- package/src/agents/developer/web-developer/identity.md +1 -1
- package/src/agents/meta/codex-keeper/identity.md +1 -1
- package/src/agents/meta/convention-keeper/identity.md +1 -1
- package/src/agents/meta/skill-summoner/identity.md +1 -1
- package/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/src/agents/researcher/api-researcher/identity.md +1 -1
- package/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/src/agents/researcher/web-researcher/identity.md +1 -1
- package/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/src/agents/tester/ai-tester/identity.md +1 -1
- package/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/src/agents/tester/api-tester/identity.md +2 -2
- package/src/agents/tester/cli-tester/identity.md +1 -1
- package/src/agents/tester/web-tester/identity.md +3 -3
- package/src/schemas/custom-metadata.schema.json +3 -0
- package/src/schemas/metadata.schema.json +3 -0
- package/src/schemas/project-config.schema.json +4 -8
- package/src/schemas/project-source-config.schema.json +2 -2
- package/dist/chunk-4VCWL2IG.js.map +0 -1
- package/dist/chunk-5MFJ24VM.js.map +0 -1
- package/dist/chunk-7VZV4O6B.js.map +0 -1
- package/dist/chunk-AURY6RT6.js.map +0 -1
- package/dist/chunk-CBF4ZYV3.js.map +0 -1
- package/dist/chunk-FMYHWKGG.js.map +0 -1
- package/dist/chunk-GUDGCFSF.js.map +0 -1
- package/dist/chunk-JC7DBPRD.js.map +0 -1
- package/dist/chunk-MJFIO5SX.js.map +0 -1
- package/dist/chunk-OJJLYHM3.js +0 -34
- package/dist/chunk-OJJLYHM3.js.map +0 -1
- package/dist/chunk-PRJD5MMQ.js.map +0 -1
- package/dist/chunk-QQTYMW7N.js.map +0 -1
- package/dist/chunk-QUDQTO3O.js +0 -41
- package/dist/chunk-QUDQTO3O.js.map +0 -1
- package/dist/chunk-R54KIGN2.js.map +0 -1
- package/dist/chunk-TUQF577Z.js.map +0 -1
- package/dist/copy-local-skills-WVHJFRPK.js +0 -14
- package/dist/load-agent-defs-5OT54J5M.js +0 -15
- package/dist/recompile-project-agents-VREEPBDV.js +0 -20
- /package/dist/{chunk-LA3JPESW.js.map → chunk-4A4L3YIW.js.map} +0 -0
- /package/dist/{chunk-BZ4CZBOM.js.map → chunk-5F2YR5XV.js.map} +0 -0
- /package/dist/{chunk-CHNA5RVS.js.map → chunk-5OKLCVM4.js.map} +0 -0
- /package/dist/{chunk-K3O3YQYG.js.map → chunk-G47TDUK3.js.map} +0 -0
- /package/dist/{chunk-IXEDSKMH.js.map → chunk-HTYH7CKN.js.map} +0 -0
- /package/dist/{chunk-NSJ2S7R5.js.map → chunk-ILUVL7WM.js.map} +0 -0
- /package/dist/{chunk-NKCY2ULI.js.map → chunk-LJCNUP6M.js.map} +0 -0
- /package/dist/{chunk-Q5FLW4JG.js.map → chunk-OKH64JZE.js.map} +0 -0
- /package/dist/{chunk-WRRP47PY.js.map → chunk-PCC4LBKB.js.map} +0 -0
- /package/dist/{chunk-2IMYK4WN.js.map → chunk-PNMM5HNX.js.map} +0 -0
- /package/dist/{chunk-AKQ5QISO.js.map → chunk-QWVXOCXO.js.map} +0 -0
- /package/dist/{chunk-ONWEOS77.js.map → chunk-SY4X2LND.js.map} +0 -0
- /package/dist/{chunk-XGMOXMS4.js.map → chunk-TBOVYLQJ.js.map} +0 -0
- /package/dist/{chunk-6CNRMCFM.js.map → chunk-VPASBA7P.js.map} +0 -0
- /package/dist/{chunk-V3ENMW7G.js.map → chunk-WFRTHH3A.js.map} +0 -0
- /package/dist/{chunk-B66SC72V.js.map → chunk-Y5Y7XHVU.js.map} +0 -0
- /package/dist/{copy-local-skills-WVHJFRPK.js.map → components/common/removal-plan-confirm.js.map} +0 -0
- /package/dist/{load-agent-defs-5OT54J5M.js.map → copy-local-skills-NSUTBVLJ.js.map} +0 -0
- /package/dist/{loader-JIZDTR4G.js.map → load-agent-defs-X4E57I2U.js.map} +0 -0
- /package/dist/{recompile-project-agents-VREEPBDV.js.map → loader-G6BFG2VA.js.map} +0 -0
- /package/dist/{source-loader-OE6EJFPU.js.map → recompile-project-agents-JE4MM72I.js.map} +0 -0
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
generateAgentPluginManifest,
|
|
11
11
|
getPluginAgentsDir,
|
|
12
12
|
getPluginManifestPath,
|
|
13
|
-
|
|
13
|
+
hasProvenanceMarker,
|
|
14
14
|
loadProjectConfig,
|
|
15
15
|
loadProjectSourceConfig,
|
|
16
16
|
resolveAgents,
|
|
17
17
|
writeCompiledAgentsByScope,
|
|
18
18
|
writeContentHash,
|
|
19
19
|
writePluginManifest
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-WCAUUBHO.js";
|
|
21
21
|
import {
|
|
22
22
|
agentFrontmatterValidationSchema,
|
|
23
23
|
copy,
|
|
@@ -27,31 +27,45 @@ import {
|
|
|
27
27
|
formatZodIssues,
|
|
28
28
|
getErrorMessage,
|
|
29
29
|
glob,
|
|
30
|
+
isAgentName,
|
|
30
31
|
loadAllAgents,
|
|
31
32
|
loadProjectAgents,
|
|
32
33
|
log,
|
|
33
34
|
readFile,
|
|
35
|
+
readFileOptional,
|
|
34
36
|
remove,
|
|
35
37
|
verbose,
|
|
36
38
|
warn
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-XAXJWXI4.js";
|
|
38
40
|
import {
|
|
39
41
|
typedEntries,
|
|
40
42
|
typedFromEntries,
|
|
41
43
|
typedKeys
|
|
42
44
|
} from "./chunk-VASLW636.js";
|
|
43
45
|
import {
|
|
44
|
-
CLAUDE_DIR,
|
|
45
46
|
DIRS,
|
|
46
|
-
PROJECT_ROOT
|
|
47
|
-
|
|
48
|
-
} from "./chunk-R54KIGN2.js";
|
|
47
|
+
PROJECT_ROOT
|
|
48
|
+
} from "./chunk-IO5YBKHV.js";
|
|
49
49
|
|
|
50
50
|
// src/cli/lib/agents/list-compiled-agents.ts
|
|
51
51
|
import path from "path";
|
|
52
|
+
import { partition } from "remeda";
|
|
52
53
|
async function listAgentMdFiles(agentsDir) {
|
|
53
54
|
return glob("*.md", agentsDir);
|
|
54
55
|
}
|
|
56
|
+
async function splitAgentsByProvenance(agentsDir) {
|
|
57
|
+
const files = await listAgentMdFiles(agentsDir);
|
|
58
|
+
const classified = await Promise.all(files.map((file) => readAgentProvenance(agentsDir, file)));
|
|
59
|
+
const [marked, unmarked] = partition(classified, (agent) => agent.compiledHere);
|
|
60
|
+
return { marked: marked.map(agentName), unmarked: unmarked.map(agentName) };
|
|
61
|
+
}
|
|
62
|
+
async function readAgentProvenance(agentsDir, file) {
|
|
63
|
+
const content = await readFileOptional(path.join(agentsDir, file));
|
|
64
|
+
return { name: path.basename(file, ".md"), compiledHere: hasProvenanceMarker(content) };
|
|
65
|
+
}
|
|
66
|
+
function agentName(agent) {
|
|
67
|
+
return agent.name;
|
|
68
|
+
}
|
|
55
69
|
async function listCompiledAgentNames(agentsDir) {
|
|
56
70
|
const files = await listAgentMdFiles(agentsDir);
|
|
57
71
|
return files.map((f) => path.basename(f, ".md"));
|
|
@@ -69,33 +83,22 @@ async function pruneStaleCompiledAgents(agentsDir, keep) {
|
|
|
69
83
|
|
|
70
84
|
// src/cli/lib/agents/agent-fetcher.ts
|
|
71
85
|
import path2 from "path";
|
|
72
|
-
async function getAgentDefinitions(remoteSource
|
|
86
|
+
async function getAgentDefinitions(remoteSource) {
|
|
73
87
|
if (remoteSource) {
|
|
74
|
-
return fetchAgentDefinitionsFromRemote(remoteSource
|
|
88
|
+
return fetchAgentDefinitionsFromRemote(remoteSource);
|
|
75
89
|
}
|
|
76
|
-
return getLocalAgentDefinitions(
|
|
90
|
+
return getLocalAgentDefinitions();
|
|
77
91
|
}
|
|
78
|
-
async function getLocalAgentDefinitions(
|
|
92
|
+
async function getLocalAgentDefinitions() {
|
|
79
93
|
const agentsDir = path2.join(PROJECT_ROOT, DIRS.agents);
|
|
80
94
|
if (!await directoryExists(agentsDir)) {
|
|
81
95
|
throw new Error(
|
|
82
96
|
`Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`
|
|
83
97
|
);
|
|
84
98
|
}
|
|
85
|
-
const localTemplatesDir = options.projectDir ? path2.join(options.projectDir, CLAUDE_DIR, STANDARD_DIRS.TEMPLATES) : void 0;
|
|
86
|
-
const useLocalTemplates = localTemplatesDir !== void 0 && await directoryExists(localTemplatesDir);
|
|
87
|
-
if (useLocalTemplates) {
|
|
88
|
-
verbose(`Using local templates from: ${localTemplatesDir}`);
|
|
89
|
-
}
|
|
90
|
-
const templatesDir = useLocalTemplates ? localTemplatesDir : path2.join(PROJECT_ROOT, DIRS.templates);
|
|
91
|
-
if (!await directoryExists(templatesDir)) {
|
|
92
|
-
verbose(`Templates directory not found: ${templatesDir}`);
|
|
93
|
-
}
|
|
94
99
|
verbose(`Agent partials loaded from CLI: ${agentsDir}`);
|
|
95
|
-
verbose(`Templates directory: ${templatesDir}`);
|
|
96
100
|
return {
|
|
97
101
|
agentsDir,
|
|
98
|
-
templatesDir,
|
|
99
102
|
sourcePath: PROJECT_ROOT
|
|
100
103
|
};
|
|
101
104
|
}
|
|
@@ -108,23 +111,18 @@ async function fetchAgentDefinitionsFromRemote(source, options = {}) {
|
|
|
108
111
|
}
|
|
109
112
|
const agentsDirRelPath = options.agentsDir ?? sourceProjectConfig?.agentsDir ?? DIRS.agents;
|
|
110
113
|
const agentsDir = path2.join(result.path, agentsDirRelPath);
|
|
111
|
-
const templatesDir = path2.join(agentsDir, path2.basename(DIRS.templates));
|
|
112
114
|
if (!await directoryExists(agentsDir)) {
|
|
113
115
|
throw new Error(`Agent partials not found at '${agentsDir}'`);
|
|
114
116
|
}
|
|
115
|
-
if (!await directoryExists(templatesDir)) {
|
|
116
|
-
verbose(`Templates directory not found: ${templatesDir}`);
|
|
117
|
-
}
|
|
118
117
|
verbose(`Agent partials fetched from: ${result.path}`);
|
|
119
118
|
return {
|
|
120
119
|
agentsDir,
|
|
121
|
-
templatesDir,
|
|
122
120
|
sourcePath: result.path
|
|
123
121
|
};
|
|
124
122
|
}
|
|
125
123
|
|
|
126
124
|
// src/cli/lib/agents/agent-recompiler.ts
|
|
127
|
-
import { partition } from "remeda";
|
|
125
|
+
import { partition as partition2 } from "remeda";
|
|
128
126
|
import path3 from "path";
|
|
129
127
|
async function getExistingAgentNames(pluginDir) {
|
|
130
128
|
return listCompiledAgentNames(getPluginAgentsDir(pluginDir));
|
|
@@ -147,7 +145,7 @@ async function resolveAgentNames(params) {
|
|
|
147
145
|
return getExistingAgentNames(pluginDir);
|
|
148
146
|
}
|
|
149
147
|
function buildRecompileResult(outcomes, priorWarnings) {
|
|
150
|
-
const [succeeded, failedOutcomes] =
|
|
148
|
+
const [succeeded, failedOutcomes] = partition2(
|
|
151
149
|
outcomes,
|
|
152
150
|
(outcome) => outcome.ok
|
|
153
151
|
);
|
|
@@ -174,8 +172,8 @@ function filterExcludedEntries(config) {
|
|
|
174
172
|
const activeAgents = config.agents.filter((a) => !a.excluded);
|
|
175
173
|
const filteredStack = config.stack === void 0 ? {} : {
|
|
176
174
|
stack: Object.fromEntries(
|
|
177
|
-
typedEntries(config.stack).map(([
|
|
178
|
-
|
|
175
|
+
typedEntries(config.stack).map(([agentName2, agentStack]) => [
|
|
176
|
+
agentName2,
|
|
179
177
|
Object.fromEntries(
|
|
180
178
|
typedEntries(agentStack).map(([category, assignments]) => [
|
|
181
179
|
category,
|
|
@@ -212,7 +210,7 @@ async function recompileAgents(options) {
|
|
|
212
210
|
verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);
|
|
213
211
|
const pluginSkills = providedSkills ?? await discoverAllPluginSkills(projectDir ?? pluginDir);
|
|
214
212
|
const allConfigAgents = filteredConfig ? buildCompileAgents(filteredConfig, allAgents) : {};
|
|
215
|
-
const [knownAgents, missingAgents] =
|
|
213
|
+
const [knownAgents, missingAgents] = partition2(
|
|
216
214
|
agentNames,
|
|
217
215
|
(name) => Boolean(allConfigAgents[name] || allAgents[name])
|
|
218
216
|
);
|
|
@@ -265,9 +263,9 @@ async function compileAgentPlugin(options) {
|
|
|
265
263
|
`Agent '${fileName}' has invalid or missing YAML frontmatter. Required fields: 'name' and 'description'. File: ${agentPath}`
|
|
266
264
|
);
|
|
267
265
|
}
|
|
268
|
-
const
|
|
269
|
-
verbose(`Compiling agent plugin: ${
|
|
270
|
-
const pluginDir = path4.join(outputDir, `agent-${
|
|
266
|
+
const agentName2 = frontmatter.name;
|
|
267
|
+
verbose(`Compiling agent plugin: ${agentName2} from ${agentPath}`);
|
|
268
|
+
const pluginDir = path4.join(outputDir, `agent-${agentName2}`);
|
|
271
269
|
const agentsDir = path4.join(pluginDir, "agents");
|
|
272
270
|
await ensureDir(pluginDir);
|
|
273
271
|
await ensureDir(agentsDir);
|
|
@@ -278,19 +276,19 @@ async function compileAgentPlugin(options) {
|
|
|
278
276
|
getPluginManifestPath
|
|
279
277
|
);
|
|
280
278
|
const manifest = generateAgentPluginManifest({
|
|
281
|
-
agentName,
|
|
279
|
+
agentName: agentName2,
|
|
282
280
|
description: frontmatter.description,
|
|
283
281
|
version
|
|
284
282
|
});
|
|
285
283
|
await writePluginManifest(pluginDir, manifest);
|
|
286
284
|
await writeContentHash(pluginDir, contentHash, getPluginManifestPath);
|
|
287
|
-
verbose(` Wrote plugin.json for ${
|
|
288
|
-
await copy(agentPath, path4.join(agentsDir, `${
|
|
289
|
-
verbose(` Copied agent ${fileName} -> agents/${
|
|
285
|
+
verbose(` Wrote plugin.json for ${agentName2} (v${version})`);
|
|
286
|
+
await copy(agentPath, path4.join(agentsDir, `${agentName2}.md`));
|
|
287
|
+
verbose(` Copied agent ${fileName} -> agents/${agentName2}.md`);
|
|
290
288
|
return {
|
|
291
289
|
pluginPath: pluginDir,
|
|
292
290
|
manifest,
|
|
293
|
-
agentName
|
|
291
|
+
agentName: agentName2
|
|
294
292
|
};
|
|
295
293
|
}
|
|
296
294
|
async function compileAllAgentPlugins(agentsDir, outputDir) {
|
|
@@ -322,6 +320,7 @@ Compiled ${results.length} agent plugins:`);
|
|
|
322
320
|
|
|
323
321
|
export {
|
|
324
322
|
listAgentMdFiles,
|
|
323
|
+
splitAgentsByProvenance,
|
|
325
324
|
pruneStaleCompiledAgents,
|
|
326
325
|
getAgentDefinitions,
|
|
327
326
|
filterExcludedEntries,
|
|
@@ -329,4 +328,4 @@ export {
|
|
|
329
328
|
compileAllAgentPlugins,
|
|
330
329
|
printAgentCompilationSummary
|
|
331
330
|
};
|
|
332
|
-
//# sourceMappingURL=chunk-
|
|
331
|
+
//# sourceMappingURL=chunk-ZUAZHDKP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/lib/agents/list-compiled-agents.ts","../src/cli/lib/agents/agent-fetcher.ts","../src/cli/lib/agents/agent-recompiler.ts","../src/cli/lib/agents/agent-plugin-compiler.ts"],"sourcesContent":["import path from \"path\";\nimport { partition } from \"remeda\";\nimport { glob, readFileOptional, remove } from \"../../utils/fs\";\nimport { isAgentName } from \"../../utils/type-guards\";\nimport { hasProvenanceMarker } from \"./agent-provenance\";\nimport type { AgentName } from \"../../types\";\n\n/** Compiled-agent basenames in a directory, split by whether this CLI compiled them. */\nexport type AgentProvenanceSplit = {\n /** Files carrying the provenance marker — provably written by this CLI. */\n marked: string[];\n /** Everything else in the directory, the user's own agents among them. */\n unmarked: string[];\n};\n\n/** Lists compiled-agent markdown filenames (e.g. \"web-developer.md\") in a directory. */\nexport async function listAgentMdFiles(agentsDir: string): Promise<string[]> {\n return glob(\"*.md\", agentsDir);\n}\n\n/**\n * Splits the agent files in a directory by the provenance marker each compiled agent carries.\n *\n * This is the only thing that identifies this CLI's own output once the configuration naming\n * it is gone, so the split errs one way by construction: a file that cannot be read yields no\n * marker and lands in `unmarked`, because \"cannot prove it is ours\" and \"is not ours\" call for\n * the same answer — leave it alone.\n */\nexport async function splitAgentsByProvenance(agentsDir: string): Promise<AgentProvenanceSplit> {\n const files = await listAgentMdFiles(agentsDir);\n const classified = await Promise.all(files.map((file) => readAgentProvenance(agentsDir, file)));\n const [marked, unmarked] = partition(classified, (agent) => agent.compiledHere);\n\n return { marked: marked.map(agentName), unmarked: unmarked.map(agentName) };\n}\n\ntype ClassifiedAgent = { name: string; compiledHere: boolean };\n\nasync function readAgentProvenance(agentsDir: string, file: string): Promise<ClassifiedAgent> {\n const content = await readFileOptional(path.join(agentsDir, file));\n return { name: path.basename(file, \".md\"), compiledHere: hasProvenanceMarker(content) };\n}\n\nfunction agentName(agent: ClassifiedAgent): string {\n return agent.name;\n}\n\n/** Lists compiled-agent names (filenames without the `.md` extension) in a directory. */\nexport async function listCompiledAgentNames(agentsDir: string): Promise<AgentName[]> {\n const files = await listAgentMdFiles(agentsDir);\n // Boundary cast: compiled .md filenames are agent names by convention; custom\n // agents from marketplace stacks may not be members of the AgentName union.\n return files.map((f) => path.basename(f, \".md\") as AgentName);\n}\n\n/**\n * Removes stale CLI-compiled agent files from `agentsDir`: deletes any `.md`\n * whose basename is a built-in CLI agent name (`isAgentName`) that is NOT in\n * `keep`. The built-in-name check protects hand-authored agents (whose basename\n * is not a built-in name) — it is never the removal criterion. Only call this\n * when `keep` is the COMPLETE set of agents that should live in `agentsDir`.\n */\nexport async function pruneStaleCompiledAgents(\n agentsDir: string,\n keep: ReadonlySet<AgentName>,\n): Promise<void> {\n // A non-built-in basename is a hand-authored agent — always preserved.\n const isStaleCompiledAgent = (file: string): boolean => {\n const name = path.basename(file, \".md\");\n return isAgentName(name) && !keep.has(name);\n };\n\n const files = await listAgentMdFiles(agentsDir);\n await Promise.all(\n files.filter(isStaleCompiledAgent).map((file) => remove(path.join(agentsDir, file))),\n );\n}\n","import path from \"path\";\nimport { directoryExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { PROJECT_ROOT, DIRS } from \"../../consts\";\nimport { fetchFromSource, type FetchOptions } from \"../loading\";\nimport { loadProjectSourceConfig } from \"../configuration\";\nimport type { AgentSourcePaths } from \"../../types\";\n\nexport async function getAgentDefinitions(remoteSource?: string): Promise<AgentSourcePaths> {\n if (remoteSource) {\n return fetchAgentDefinitionsFromRemote(remoteSource);\n }\n return getLocalAgentDefinitions();\n}\n\nexport async function getLocalAgentDefinitions(): Promise<AgentSourcePaths> {\n const agentsDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(\n `Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`,\n );\n }\n\n verbose(`Agent partials loaded from CLI: ${agentsDir}`);\n\n return {\n agentsDir,\n sourcePath: PROJECT_ROOT,\n };\n}\n\nexport async function fetchAgentDefinitionsFromRemote(\n source: string,\n options: FetchOptions & { agentsDir?: string } = {},\n): Promise<AgentSourcePaths> {\n verbose(`Fetching agent partials from remote: ${source}`);\n\n const result = await fetchFromSource(source, { subdir: \"\" });\n\n const sourceProjectConfig = options.agentsDir\n ? undefined\n : await loadProjectSourceConfig(result.path);\n if (sourceProjectConfig?.agentsDir) {\n verbose(`Using agentsDir from source config: ${sourceProjectConfig.agentsDir}`);\n }\n const agentsDirRelPath = options.agentsDir ?? sourceProjectConfig?.agentsDir ?? DIRS.agents;\n\n const agentsDir = path.join(result.path, agentsDirRelPath);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(`Agent partials not found at '${agentsDir}'`);\n }\n\n verbose(`Agent partials fetched from: ${result.path}`);\n\n return {\n agentsDir,\n sourcePath: result.path,\n };\n}\n","import { partition } from \"remeda\";\nimport { writeCompiledAgentsByScope, type AgentWriteOutcome } from \"./write-compiled-agents\";\nimport { listCompiledAgentNames } from \"./list-compiled-agents\";\nimport path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport type {\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n ProjectConfig,\n SkillDefinitionMap,\n SkillScope,\n} from \"../../types\";\n\nimport { buildCompileAgents } from \"../installation/local-installer\";\nimport { ensureDir } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedFromEntries, typedKeys } from \"../../utils/typed-object\";\nimport { createLiquidEngine } from \"../compiler\";\nimport { loadProjectConfig, effectivelyExcludedSkillIds } from \"../configuration\";\nimport { loadAllAgents, loadProjectAgents } from \"../loading\";\nimport { getPluginAgentsDir } from \"../plugins\";\nimport { discoverAllPluginSkills } from \"../plugins/plugin-discovery\";\nimport { resolveAgents } from \"../resolver\";\n\nexport type RecompileAgentsOptions = {\n pluginDir: string;\n sourcePath: string;\n agents?: AgentName[];\n skills?: SkillDefinitionMap;\n projectDir?: string;\n outputDir?: string;\n /** When provided, routes agents by scope: global agents to ~/.claude/agents/, project agents to outputDir */\n agentScopeMap?: Map<AgentName, SkillScope>;\n};\n\nexport type RecompileAgentsResult = {\n compiled: AgentName[];\n /**\n * The subset of `compiled` whose file this pass actually wrote. `compiled` is\n * every agent that came through the pass with a correct file at the end of it;\n * `rewritten` is the ones whose content moved, so `compiled minus rewritten` is\n * the count a summary reports as unchanged.\n */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nasync function getExistingAgentNames(pluginDir: string): Promise<AgentName[]> {\n return listCompiledAgentNames(getPluginAgentsDir(pluginDir));\n}\n\ntype ResolveAgentNamesParams = {\n specifiedAgents?: AgentName[];\n projectConfig: ProjectConfig | null;\n allAgents: Partial<Record<AgentName, AgentDefinition>>;\n outputDir?: string;\n pluginDir: string;\n};\n\nasync function resolveAgentNames(params: ResolveAgentNamesParams): Promise<AgentName[]> {\n const { specifiedAgents, projectConfig, allAgents, outputDir, pluginDir } = params;\n\n if (specifiedAgents) {\n return specifiedAgents;\n }\n\n // A present config is authoritative over its agent roster — even when empty.\n // `agents: []` means \"no agents\", so it must NOT fall through to the\n // all-agents branch below; that branch exists only for the config-LESS case.\n if (projectConfig) {\n const agentNames = projectConfig.agents.map((a) => a.name);\n verbose(`Using agents from config: ${agentNames.join(\", \")}`);\n return agentNames;\n }\n\n if (outputDir) {\n const names = typedKeys<AgentName>(allAgents);\n verbose(`Using all available agents from source: ${names.join(\", \")}`);\n return names;\n }\n\n return getExistingAgentNames(pluginDir);\n}\n\n/** Splits write outcomes into the recompile result; logs each success at verbose level. */\nfunction buildRecompileResult(\n outcomes: AgentWriteOutcome[],\n priorWarnings: string[],\n): RecompileAgentsResult {\n const [succeeded, failedOutcomes] = partition(\n outcomes,\n (outcome): outcome is Extract<AgentWriteOutcome, { ok: true }> => outcome.ok,\n );\n succeeded.forEach((outcome) =>\n verbose(\n ` ${outcome.rewritten ? \"Rewrote\" : \"Unchanged\"}: ${outcome.name} (${outcome.scope} -> ${outcome.targetDir})`,\n ),\n );\n return {\n compiled: succeeded.map((outcome) => outcome.name),\n rewritten: succeeded.filter((outcome) => outcome.rewritten).map((outcome) => outcome.name),\n failed: failedOutcomes.map((outcome) => outcome.name),\n warnings: [\n ...priorWarnings,\n ...failedOutcomes.map(\n (outcome) => `Failed to compile ${outcome.name}: ${getErrorMessage(outcome.error)}`,\n ),\n ],\n };\n}\n\nexport function filterExcludedEntries(config: ProjectConfig): ProjectConfig {\n const excludedIds = effectivelyExcludedSkillIds(config.skills);\n const activeSkills = config.skills.filter((s) => !s.excluded);\n const activeAgents = config.agents.filter((a) => !a.excluded);\n\n // Also remove excluded skill refs from stack assignments. A config with no stack keeps\n // none — the key stays absent rather than becoming an explicit `undefined`.\n const filteredStack =\n config.stack === undefined\n ? {}\n : {\n stack: Object.fromEntries(\n typedEntries(config.stack).map(([agentName, agentStack]) => [\n agentName,\n Object.fromEntries(\n typedEntries(agentStack).map(([category, assignments]) => [\n category,\n assignments.filter((a) => !excludedIds.has(a.id)),\n ]),\n ),\n ]),\n ),\n };\n\n return { ...config, skills: activeSkills, agents: activeAgents, ...filteredStack };\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const { pluginDir, sourcePath, skills: providedSkills, projectDir, outputDir } = options;\n\n const configDir = projectDir ?? pluginDir;\n const loadedConfig = await loadProjectConfig(configDir);\n const projectConfig = loadedConfig?.config ?? null;\n\n // Filter excluded entries once at the entry point — callees receive clean data\n const filteredConfig = projectConfig ? filterExcludedEntries(projectConfig) : null;\n\n const builtinAgents = await loadAllAgents(sourcePath);\n const projectAgents = projectDir ? await loadProjectAgents(projectDir) : {};\n\n // Priority: project agents > built-in agents\n const allAgents: Partial<Record<AgentName, AgentDefinition>> = {\n ...builtinAgents,\n ...projectAgents,\n };\n\n const agentNames = await resolveAgentNames({\n ...(options.agents !== undefined && { specifiedAgents: options.agents }),\n projectConfig: filteredConfig,\n allAgents,\n ...(outputDir !== undefined && { outputDir }),\n pluginDir,\n });\n\n if (agentNames.length === 0) {\n return { compiled: [], rewritten: [], failed: [], warnings: [\"No agents found to recompile\"] };\n }\n\n verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);\n\n // When skills are not provided, discover from all plugin directories.\n const pluginSkills: SkillDefinitionMap =\n providedSkills ?? (await discoverAllPluginSkills(projectDir ?? pluginDir));\n\n const allConfigAgents = filteredConfig ? buildCompileAgents(filteredConfig, allAgents) : {};\n\n // Restrict to only the agents we're compiling (agentNames).\n // buildCompileAgents returns entries for ALL agents in the config, but when\n // scopeFilter is active, we only want the agents matching that scope.\n // Without this filter, a project pass would compile global agents without\n // their stack (since the project config omits global agent stack entries)\n // and overwrite correctly compiled global agent files.\n const [knownAgents, missingAgents] = partition(agentNames, (name) =>\n Boolean(allConfigAgents[name] || allAgents[name]),\n );\n const missingWarnings = missingAgents.map(\n (name) => `Agent \"${name}\" not found in source definitions`,\n );\n const configAgents = typedFromEntries<AgentName, CompileAgentConfig>(\n knownAgents.map((name) => [name, allConfigAgents[name] ?? {}]),\n );\n\n const compileConfig: CompileConfig = {\n name: filteredConfig?.name || path.basename(pluginDir),\n description: filteredConfig?.description || \"Recompiled plugin\",\n agents: configAgents,\n };\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n const outcomes = await writeCompiledAgentsByScope({\n resolvedAgents,\n sourcePath,\n engine,\n projectAgentsDir: agentsDir,\n ...(options.agentScopeMap !== undefined && { agentScopeMap: options.agentScopeMap }),\n });\n return buildRecompileResult(outcomes, missingWarnings);\n}\n","import path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, ensureDir, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateAgentPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { listAgentMdFiles } from \"./list-compiled-agents\";\nimport { computeStringHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport type { AgentFrontmatter, PluginManifest } from \"../../types\";\nimport { agentFrontmatterValidationSchema, formatZodIssues } from \"../schemas\";\n\nexport type AgentPluginOptions = {\n agentPath: string;\n outputDir: string;\n};\n\nexport type CompiledAgentPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n agentName: string;\n};\n\nfunction parseAgentFrontmatter(\n content: string,\n filePath: string,\n): Pick<AgentFrontmatter, \"name\" | \"description\"> | null {\n const raw = extractFrontmatter(content);\n if (!raw) {\n return null;\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(raw);\n if (!result.success) {\n warn(`Invalid agent frontmatter in ${filePath}: ${formatZodIssues(result.error.issues)}`);\n return null;\n }\n\n return { name: result.data.name, description: result.data.description };\n}\n\nexport async function compileAgentPlugin(\n options: AgentPluginOptions,\n): Promise<CompiledAgentPlugin> {\n const { agentPath, outputDir } = options;\n const fileName = path.basename(agentPath);\n\n const content = await readFile(agentPath);\n const frontmatter = parseAgentFrontmatter(content, agentPath);\n\n if (!frontmatter) {\n throw new Error(\n `Agent '${fileName}' has invalid or missing YAML frontmatter. ` +\n `Required fields: 'name' and 'description'. File: ${agentPath}`,\n );\n }\n\n const agentName = frontmatter.name;\n\n verbose(`Compiling agent plugin: ${agentName} from ${agentPath}`);\n\n const pluginDir = path.join(outputDir, `agent-${agentName}`);\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await ensureDir(pluginDir);\n await ensureDir(agentsDir);\n\n const newHash = computeStringHash(content);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateAgentPluginManifest({\n agentName,\n description: frontmatter.description,\n version,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${agentName} (v${version})`);\n\n await copy(agentPath, path.join(agentsDir, `${agentName}.md`));\n verbose(` Copied agent ${fileName} -> agents/${agentName}.md`);\n\n return {\n pluginPath: pluginDir,\n manifest,\n agentName,\n };\n}\n\nexport async function compileAllAgentPlugins(\n agentsDir: string,\n outputDir: string,\n): Promise<CompiledAgentPlugin[]> {\n const results: CompiledAgentPlugin[] = [];\n\n const agentMdFiles = await listAgentMdFiles(agentsDir);\n\n for (const agentFile of agentMdFiles) {\n const agentPath = path.join(agentsDir, agentFile);\n\n try {\n const result = await compileAgentPlugin({\n agentPath,\n outputDir,\n });\n results.push(result);\n log(` [OK] agent-${result.agentName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile agent from '${agentFile}': ${errorMessage}`);\n }\n }\n\n return results;\n}\n\nexport function printAgentCompilationSummary(results: CompiledAgentPlugin[]): void {\n log(`\\nCompiled ${results.length} agent plugins:`);\n for (const result of results) {\n log(` - agent-${result.agentName} (v${result.manifest.version})`);\n }\n}\n"],"mappings":"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","names":["path","path","partition","path","partition","agentName","path","path","path","agentName"]}
|
|
@@ -1,122 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
generateMarketplace,
|
|
4
|
+
getMarketplaceStats,
|
|
5
|
+
validateMarketplaceName,
|
|
6
|
+
validateSkillIdNamespace,
|
|
7
|
+
writeMarketplace
|
|
8
|
+
} from "../../chunk-4G2YHZIM.js";
|
|
2
9
|
import {
|
|
3
10
|
BaseCommand,
|
|
4
11
|
EXIT_CODES
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
7
|
-
import "../../chunk-
|
|
12
|
+
} from "../../chunk-YO2LTXB4.js";
|
|
13
|
+
import "../../chunk-UMH2YZKG.js";
|
|
14
|
+
import "../../chunk-G47TDUK3.js";
|
|
8
15
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
loadMarketplaceMatrix,
|
|
17
|
+
marketplaceHasNoVersion,
|
|
18
|
+
marketplaceNameNotPublishable,
|
|
19
|
+
marketplaceOwnerHasNoName,
|
|
20
|
+
validateKebabCaseName
|
|
21
|
+
} from "../../chunk-WCAUUBHO.js";
|
|
11
22
|
import {
|
|
12
|
-
ensureDir,
|
|
13
23
|
getErrorMessage,
|
|
14
|
-
glob,
|
|
15
24
|
readFile,
|
|
16
25
|
setVerbose,
|
|
17
|
-
verbose,
|
|
18
26
|
warn,
|
|
19
27
|
writeFile
|
|
20
|
-
} from "../../chunk-
|
|
21
|
-
import "../../chunk-
|
|
28
|
+
} from "../../chunk-XAXJWXI4.js";
|
|
29
|
+
import "../../chunk-RWOYPOMR.js";
|
|
22
30
|
import "../../chunk-VASLW636.js";
|
|
23
31
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
CATALOG_JSON,
|
|
33
|
+
CLI_INVOKE_COMMAND,
|
|
34
|
+
GENERATED_AT_BUILD,
|
|
26
35
|
MARKETPLACE_JSON,
|
|
27
36
|
PLUGINS_DIST_PATH,
|
|
28
37
|
PLUGIN_MANIFEST_DIR,
|
|
29
|
-
|
|
30
|
-
} from "../../chunk-
|
|
38
|
+
STANDARD_FILES
|
|
39
|
+
} from "../../chunk-IO5YBKHV.js";
|
|
31
40
|
import "../../chunk-VZRO7RYT.js";
|
|
32
41
|
|
|
33
42
|
// src/cli/commands/build/marketplace.ts
|
|
34
43
|
import { Flags } from "@oclif/core";
|
|
35
|
-
import path2 from "path";
|
|
36
|
-
import { sortBy as sortBy2 } from "remeda";
|
|
37
|
-
import { z } from "zod";
|
|
38
|
-
|
|
39
|
-
// src/cli/lib/marketplace-generator.ts
|
|
40
44
|
import path from "path";
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
var MARKETPLACE_SCHEMA_URL = "https://anthropic.com/claude-code/marketplace.schema.json";
|
|
44
|
-
function convertManifestToMarketplacePlugin(manifest, pluginRoot, pluginDirName) {
|
|
45
|
-
return {
|
|
46
|
-
name: manifest.name,
|
|
47
|
-
source: `./${pluginRoot}/${pluginDirName}`,
|
|
48
|
-
...manifest.description !== void 0 && { description: manifest.description },
|
|
49
|
-
...manifest.version !== void 0 && { version: manifest.version },
|
|
50
|
-
...manifest.author !== void 0 && { author: manifest.author },
|
|
51
|
-
...manifest.category !== void 0 && { category: manifest.category },
|
|
52
|
-
...manifest.keywords !== void 0 && { keywords: manifest.keywords }
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
async function generateMarketplace(pluginsDir, options) {
|
|
56
|
-
verbose(`Scanning plugins directory: ${pluginsDir}`);
|
|
57
|
-
const manifestFiles = await glob(`**/${PLUGIN_MANIFEST_PATH}`, pluginsDir);
|
|
58
|
-
verbose(`Found ${manifestFiles.length} plugin manifests`);
|
|
59
|
-
const plugins = [];
|
|
60
|
-
for (const manifestFile of manifestFiles) {
|
|
61
|
-
const separator = manifestFile.indexOf("/");
|
|
62
|
-
const pluginDirName = separator === -1 ? manifestFile : manifestFile.slice(0, separator);
|
|
63
|
-
const pluginDir = path.join(pluginsDir, pluginDirName);
|
|
64
|
-
const manifest = await readPluginManifest(pluginDir);
|
|
65
|
-
if (!manifest) {
|
|
66
|
-
warn(`Could not read plugin manifest: '${manifestFile}'`);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const plugin = convertManifestToMarketplacePlugin(
|
|
70
|
-
manifest,
|
|
71
|
-
options.pluginRoot.replace(/^\.\//, ""),
|
|
72
|
-
pluginDirName
|
|
73
|
-
);
|
|
74
|
-
plugins.push(plugin);
|
|
75
|
-
verbose(` [OK] ${plugin.name}`);
|
|
76
|
-
}
|
|
77
|
-
const sortedPlugins = sortBy(plugins, (p) => p.name);
|
|
78
|
-
return {
|
|
79
|
-
$schema: MARKETPLACE_SCHEMA_URL,
|
|
80
|
-
name: options.name,
|
|
81
|
-
version: options.version ?? DEFAULT_VERSION,
|
|
82
|
-
owner: {
|
|
83
|
-
name: options.ownerName,
|
|
84
|
-
...options.ownerEmail ? { email: options.ownerEmail } : {}
|
|
85
|
-
},
|
|
86
|
-
metadata: {
|
|
87
|
-
pluginRoot: options.pluginRoot
|
|
88
|
-
},
|
|
89
|
-
plugins: sortedPlugins,
|
|
90
|
-
...options.description ? { description: options.description } : {}
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
async function writeMarketplace(outputPath, marketplace) {
|
|
94
|
-
await ensureDir(path.dirname(outputPath));
|
|
95
|
-
const content = `${JSON.stringify(marketplace, null, 2)}
|
|
96
|
-
`;
|
|
97
|
-
await writeFile(outputPath, content);
|
|
98
|
-
}
|
|
99
|
-
function getMarketplaceStats(marketplace) {
|
|
100
|
-
return {
|
|
101
|
-
total: marketplace.plugins.length,
|
|
102
|
-
byCategory: countBy(marketplace.plugins, (p) => p.category ?? "uncategorized")
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/cli/lib/validate-kebab-name.ts
|
|
107
|
-
function validateKebabCaseName(name, noun) {
|
|
108
|
-
if (!name || name.trim() === "") {
|
|
109
|
-
return `${noun} name is required`;
|
|
110
|
-
}
|
|
111
|
-
if (!KEBAB_CASE_PATTERN.test(name)) {
|
|
112
|
-
return `${noun} name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)`;
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// src/cli/commands/build/marketplace.ts
|
|
45
|
+
import { sortBy } from "remeda";
|
|
46
|
+
import { z } from "zod";
|
|
118
47
|
var DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;
|
|
119
48
|
var AUTHOR_STRING_PATTERN = /^(.*?)\s*<([^>]+)>\s*(?:\(([^)]+)\))?\s*$/;
|
|
49
|
+
var MARKETPLACE_NOUN = "Marketplace";
|
|
120
50
|
var packageAuthorObjectSchema = z.object({
|
|
121
51
|
name: z.string(),
|
|
122
52
|
email: z.string().exactOptional(),
|
|
@@ -173,8 +103,8 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
173
103
|
const { flags } = await this.parse(_BuildMarketplace);
|
|
174
104
|
setVerbose(flags.verbose);
|
|
175
105
|
const projectRoot = process.cwd();
|
|
176
|
-
const pluginsDir =
|
|
177
|
-
const outputPath =
|
|
106
|
+
const pluginsDir = path.resolve(projectRoot, flags["plugins-dir"]);
|
|
107
|
+
const outputPath = path.resolve(projectRoot, flags.output);
|
|
178
108
|
const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);
|
|
179
109
|
this.printHeader(pluginsDir, outputPath);
|
|
180
110
|
try {
|
|
@@ -184,6 +114,7 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
184
114
|
flags["plugins-dir"],
|
|
185
115
|
identity
|
|
186
116
|
);
|
|
117
|
+
await this.writeCatalog(projectRoot, outputPath);
|
|
187
118
|
this.printStats(marketplace);
|
|
188
119
|
this.printSample(marketplace);
|
|
189
120
|
this.log("");
|
|
@@ -197,7 +128,7 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
197
128
|
}
|
|
198
129
|
}
|
|
199
130
|
async loadMarketplaceIdentity(projectRoot, nameOverride) {
|
|
200
|
-
const packageJsonPath =
|
|
131
|
+
const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);
|
|
201
132
|
let rawContent;
|
|
202
133
|
try {
|
|
203
134
|
rawContent = await readFile(packageJsonPath);
|
|
@@ -224,16 +155,17 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
224
155
|
);
|
|
225
156
|
}
|
|
226
157
|
const { name, version, description, author } = parseResult.data;
|
|
158
|
+
if (version.trim() === "") {
|
|
159
|
+
this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });
|
|
160
|
+
}
|
|
227
161
|
const owner = parseAuthor(author);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
resolvedName = nameOverride;
|
|
162
|
+
if (owner.name.trim() === "") {
|
|
163
|
+
this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });
|
|
164
|
+
}
|
|
165
|
+
const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);
|
|
166
|
+
const reservedError = validateMarketplaceName(resolvedName, name);
|
|
167
|
+
if (reservedError) {
|
|
168
|
+
this.error(reservedError, { exit: EXIT_CODES.ERROR });
|
|
237
169
|
}
|
|
238
170
|
return {
|
|
239
171
|
name: resolvedName,
|
|
@@ -243,6 +175,32 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
243
175
|
...owner.email !== void 0 && { ownerEmail: owner.email }
|
|
244
176
|
};
|
|
245
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* The name this marketplace publishes under, refused before anything is written when
|
|
180
|
+
* it is not one `claude plugin marketplace add` will accept.
|
|
181
|
+
*
|
|
182
|
+
* Both halves are judged by the same rule and refused with different sentences: a
|
|
183
|
+
* `--name` the author typed is an argument they can retype, while a name derived from
|
|
184
|
+
* package.json is a fact about their package — an npm scoped name is legitimate there
|
|
185
|
+
* and illegitimate here — so its way out is the flag rather than a package rename.
|
|
186
|
+
*/
|
|
187
|
+
resolvePublishableName(packageName, nameOverride, packageJsonPath) {
|
|
188
|
+
if (nameOverride !== void 0) {
|
|
189
|
+
const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);
|
|
190
|
+
if (invalidOverride) {
|
|
191
|
+
this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {
|
|
192
|
+
exit: EXIT_CODES.INVALID_ARGS
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return nameOverride;
|
|
196
|
+
}
|
|
197
|
+
if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {
|
|
198
|
+
this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {
|
|
199
|
+
exit: EXIT_CODES.ERROR
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return packageName;
|
|
203
|
+
}
|
|
246
204
|
printHeader(pluginsDir, outputPath) {
|
|
247
205
|
this.log("");
|
|
248
206
|
this.log("Generating marketplace.json");
|
|
@@ -262,15 +220,41 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
262
220
|
});
|
|
263
221
|
const stats = getMarketplaceStats(marketplace);
|
|
264
222
|
this.log(`Found ${stats.total} plugins`);
|
|
223
|
+
if (marketplace.plugins.length === 0) {
|
|
224
|
+
this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });
|
|
225
|
+
}
|
|
226
|
+
const namespaceError = validateSkillIdNamespace(marketplace);
|
|
227
|
+
if (namespaceError) {
|
|
228
|
+
this.error(namespaceError, { exit: EXIT_CODES.ERROR });
|
|
229
|
+
}
|
|
265
230
|
this.log("Writing marketplace.json...");
|
|
266
231
|
await writeMarketplace(outputPath, marketplace);
|
|
267
232
|
this.log(`Wrote ${outputPath}`);
|
|
268
233
|
return marketplace;
|
|
269
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Writes the marketplace's catalogue beside its manifest.
|
|
237
|
+
*
|
|
238
|
+
* Unconditional, and there is no flag to make it otherwise: a consumer
|
|
239
|
+
* fetching a marketplace cannot tell an author who omitted a flag from a
|
|
240
|
+
* marketplace that is broken, so an absent catalogue has to mean the second.
|
|
241
|
+
*
|
|
242
|
+
* `generatedAt` is stamped rather than carried: see {@link GENERATED_AT_BUILD}
|
|
243
|
+
* for why a published artefact records a build and not a moment.
|
|
244
|
+
*/
|
|
245
|
+
async writeCatalog(projectRoot, outputPath) {
|
|
246
|
+
const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);
|
|
247
|
+
this.log(`Writing ${CATALOG_JSON}...`);
|
|
248
|
+
const matrix = await loadMarketplaceMatrix(projectRoot);
|
|
249
|
+
const catalog = { ...matrix, generatedAt: GENERATED_AT_BUILD };
|
|
250
|
+
await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}
|
|
251
|
+
`);
|
|
252
|
+
this.log(`Wrote ${catalogPath}`);
|
|
253
|
+
}
|
|
270
254
|
printStats(marketplace) {
|
|
271
255
|
this.log("");
|
|
272
256
|
this.log("Category breakdown:");
|
|
273
|
-
const sortedCategories =
|
|
257
|
+
const sortedCategories = sortBy(
|
|
274
258
|
Object.entries(getMarketplaceStats(marketplace).byCategory),
|
|
275
259
|
([, count]) => -count
|
|
276
260
|
);
|
|
@@ -295,24 +279,17 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
|
295
279
|
}
|
|
296
280
|
}
|
|
297
281
|
};
|
|
282
|
+
function noPluginsToPublish(pluginsDir, pluginsDirFlag) {
|
|
283
|
+
return `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point --plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`;
|
|
284
|
+
}
|
|
298
285
|
function parseAuthor(author) {
|
|
299
|
-
if (!author) {
|
|
300
|
-
warn("package.json is missing 'author' field \u2014 marketplace owner.email will be empty");
|
|
301
|
-
return { name: "" };
|
|
302
|
-
}
|
|
286
|
+
if (!author) return { name: "" };
|
|
303
287
|
if (typeof author === "object") {
|
|
304
288
|
return { name: author.name, ...author.email !== void 0 && { email: author.email } };
|
|
305
289
|
}
|
|
306
290
|
const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];
|
|
307
291
|
if (matchedName !== void 0 && matchedEmail !== void 0) {
|
|
308
|
-
|
|
309
|
-
const email = matchedEmail.trim();
|
|
310
|
-
if (name === "") {
|
|
311
|
-
warn(
|
|
312
|
-
`package.json 'author' field "${author}" has no parseable name \u2014 marketplace owner.name will be empty`
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
return { name, email };
|
|
292
|
+
return { name: matchedName.trim(), email: matchedEmail.trim() };
|
|
316
293
|
}
|
|
317
294
|
warn(
|
|
318
295
|
`package.json 'author' field "${author}" has no parseable email \u2014 marketplace owner.email will be empty`
|