agents-inc 0.175.0 → 0.176.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 +67 -0
- package/dist/{chunk-EGC7PNDI.js → chunk-3F5LT433.js} +138 -41
- package/dist/chunk-3F5LT433.js.map +1 -0
- package/dist/chunk-5CFHP6Z5.js +109 -0
- package/dist/chunk-5CFHP6Z5.js.map +1 -0
- package/dist/{chunk-MFCZARV2.js → chunk-B7AVWSK2.js} +18 -8
- package/dist/chunk-B7AVWSK2.js.map +1 -0
- package/dist/{chunk-6HJVH27C.js → chunk-C2BSCEDN.js} +2 -2
- package/dist/{chunk-SNXEYAFP.js → chunk-CKBWEWHZ.js} +60 -30
- package/dist/chunk-CKBWEWHZ.js.map +1 -0
- package/dist/{chunk-SI2LLEIR.js → chunk-EC3JXT23.js} +4 -4
- package/dist/{chunk-YM3VEDAP.js → chunk-ENET4IF6.js} +440 -192
- package/dist/chunk-ENET4IF6.js.map +1 -0
- package/dist/{chunk-ICHWAFAC.js → chunk-FACDJH6O.js} +11 -104
- package/dist/chunk-FACDJH6O.js.map +1 -0
- package/dist/{chunk-P5XEK7HC.js → chunk-H6WUOW5F.js} +2 -2
- package/dist/{chunk-DQB3E2SX.js → chunk-JNRACLNS.js} +3 -3
- package/dist/{chunk-37QFHJUW.js → chunk-JTMSFBCA.js} +106 -28
- package/dist/chunk-JTMSFBCA.js.map +1 -0
- package/dist/{chunk-GNMRXXRY.js → chunk-MQZNDK5F.js} +3 -3
- package/dist/chunk-MQZNDK5F.js.map +1 -0
- package/dist/{chunk-SRII2GMF.js → chunk-SN64WNWE.js} +2 -2
- package/dist/{chunk-EHEBN4NB.js → chunk-U672FZVC.js} +2 -2
- package/dist/{chunk-TG3SPPZY.js → chunk-UE4Z3YMB.js} +1 -1
- package/dist/chunk-UE4Z3YMB.js.map +1 -0
- package/dist/{chunk-Q4NWATGH.js → chunk-XMQIWPIR.js} +58 -10
- package/dist/chunk-XMQIWPIR.js.map +1 -0
- package/dist/{chunk-YLFKFVQP.js → chunk-ZBI6GFJD.js} +2 -2
- package/dist/commands/build/marketplace.js +4 -3
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +6 -5
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/compile.js +15 -11
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +38 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +46 -25
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +12 -8
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +15 -14
- package/dist/commands/list.js +8 -6
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +4 -3
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/search.js +13 -8
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +14 -16
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +18 -14
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +97 -17
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/skill-agent-summary.js +3 -2
- package/dist/components/common/summary-panel.js +4 -3
- package/dist/hooks/init.js +15 -14
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-5BSECHE6.js +14 -0
- package/dist/{recompile-project-agents-2QTFMYDC.js → recompile-project-agents-U3UGHPWG.js} +7 -7
- package/dist/{source-loader-I6SWWDUF.js → source-loader-E2Y5MMN5.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-37QFHJUW.js.map +0 -1
- package/dist/chunk-EGC7PNDI.js.map +0 -1
- package/dist/chunk-GNMRXXRY.js.map +0 -1
- package/dist/chunk-ICHWAFAC.js.map +0 -1
- package/dist/chunk-MFCZARV2.js.map +0 -1
- package/dist/chunk-Q4NWATGH.js.map +0 -1
- package/dist/chunk-SNXEYAFP.js.map +0 -1
- package/dist/chunk-TG3SPPZY.js.map +0 -1
- package/dist/chunk-YM3VEDAP.js.map +0 -1
- package/dist/load-agent-defs-BJ4KBKBA.js +0 -14
- /package/dist/{chunk-6HJVH27C.js.map → chunk-C2BSCEDN.js.map} +0 -0
- /package/dist/{chunk-SI2LLEIR.js.map → chunk-EC3JXT23.js.map} +0 -0
- /package/dist/{chunk-P5XEK7HC.js.map → chunk-H6WUOW5F.js.map} +0 -0
- /package/dist/{chunk-DQB3E2SX.js.map → chunk-JNRACLNS.js.map} +0 -0
- /package/dist/{chunk-SRII2GMF.js.map → chunk-SN64WNWE.js.map} +0 -0
- /package/dist/{chunk-EHEBN4NB.js.map → chunk-U672FZVC.js.map} +0 -0
- /package/dist/{chunk-YLFKFVQP.js.map → chunk-ZBI6GFJD.js.map} +0 -0
- /package/dist/{load-agent-defs-BJ4KBKBA.js.map → load-agent-defs-5BSECHE6.js.map} +0 -0
- /package/dist/{recompile-project-agents-2QTFMYDC.js.map → recompile-project-agents-U3UGHPWG.js.map} +0 -0
- /package/dist/{source-loader-I6SWWDUF.js.map → source-loader-E2Y5MMN5.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
pruneStaleCompiledAgents,
|
|
4
4
|
recompileAgents
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MQZNDK5F.js";
|
|
6
6
|
import {
|
|
7
7
|
agentCodec,
|
|
8
8
|
buildAgentScopeMap,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
hostAt,
|
|
15
15
|
inheritedGlobalProvider,
|
|
16
16
|
isHomeDirectory,
|
|
17
|
+
listDirectories,
|
|
17
18
|
loadProjectConfigFromDir,
|
|
18
19
|
loadSkillsFromDir,
|
|
19
20
|
loadSkillsMatrixFromSource,
|
|
@@ -26,27 +27,35 @@ import {
|
|
|
26
27
|
skillsDir,
|
|
27
28
|
skillsPathPrefix,
|
|
28
29
|
verbose
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ENET4IF6.js";
|
|
30
31
|
import {
|
|
31
32
|
initializeMatrix,
|
|
32
33
|
matrix,
|
|
33
34
|
typedEntries,
|
|
34
35
|
typedKeys
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-UE4Z3YMB.js";
|
|
36
37
|
import {
|
|
38
|
+
EJECT_SOURCE,
|
|
37
39
|
globalInstallRoot
|
|
38
40
|
} from "./chunk-U46LYYRA.js";
|
|
39
41
|
|
|
40
42
|
// src/cli/lib/operations/skills/discover-skills.ts
|
|
43
|
+
import path from "path";
|
|
41
44
|
var NO_LOCAL_SKILLS = { skills: {}, unusableMetadata: [] };
|
|
42
45
|
async function discoverLocalProjectSkills(projectDir, scope) {
|
|
43
46
|
const provider = providerAtScope(projectDir, scope);
|
|
47
|
+
const pathPrefix = skillsPathPrefix(provider, scope, projectDir);
|
|
44
48
|
const scan = () => loadSkillsFromDir(skillsDir(provider, scope, projectDir), {
|
|
45
|
-
pathPrefix
|
|
46
|
-
requireMetadata: true
|
|
49
|
+
pathPrefix,
|
|
50
|
+
requireMetadata: true,
|
|
51
|
+
folderLabel: folderLabelAt(pathPrefix, scope)
|
|
47
52
|
});
|
|
48
53
|
return scope === "global" ? sayingEachWarningOnce(scan) : scan();
|
|
49
54
|
}
|
|
55
|
+
function folderLabelAt(pathPrefix, scope) {
|
|
56
|
+
const underHome = scope === "global" && !path.isAbsolute(pathPrefix);
|
|
57
|
+
return underHome ? `~/${pathPrefix}/` : `${pathPrefix}/`;
|
|
58
|
+
}
|
|
50
59
|
function skillsRootAt(projectDir, scope) {
|
|
51
60
|
return skillsDir(providerAtScope(projectDir, scope), scope, projectDir);
|
|
52
61
|
}
|
|
@@ -122,6 +131,7 @@ function skillCount(skills) {
|
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
// src/cli/lib/operations/skills/copy-local-skills.ts
|
|
134
|
+
import path2 from "path";
|
|
125
135
|
async function copyScopedLocalSkills(scopeSkills, skillsDir2, sourceResult) {
|
|
126
136
|
if (scopeSkills.length === 0) return [];
|
|
127
137
|
await ensureDir(skillsDir2);
|
|
@@ -152,6 +162,22 @@ async function copyLocalSkills(skills, projectDir, sourceResult) {
|
|
|
152
162
|
totalCopied: projectCopied.length + globalCopied.length
|
|
153
163
|
};
|
|
154
164
|
}
|
|
165
|
+
async function skillFoldersAt(projectDir) {
|
|
166
|
+
const skillsDirs = [
|
|
167
|
+
resolveInstallPaths(projectDir, "project").skillsDir,
|
|
168
|
+
resolveInstallPaths(projectDir, "global").skillsDir
|
|
169
|
+
];
|
|
170
|
+
const folders = await Promise.all(skillsDirs.map(foldersIn));
|
|
171
|
+
return new Set(folders.flat());
|
|
172
|
+
}
|
|
173
|
+
async function foldersIn(dir) {
|
|
174
|
+
return (await listDirectories(dir)).map((name) => path2.join(dir, name));
|
|
175
|
+
}
|
|
176
|
+
async function removeSkillFoldersCreatedSince(before, projectDir) {
|
|
177
|
+
const created = [...await skillFoldersAt(projectDir)].filter((folder) => !before.has(folder));
|
|
178
|
+
await Promise.all(created.map(remove));
|
|
179
|
+
return new Set(created);
|
|
180
|
+
}
|
|
155
181
|
|
|
156
182
|
// src/cli/lib/operations/skills/uninstall-plugin-skills.ts
|
|
157
183
|
var SCOPE_OF_AN_UNRECORDED_SKILL = "project";
|
|
@@ -162,9 +188,13 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
|
|
|
162
188
|
for (const skillId of skillIds) {
|
|
163
189
|
const oldSkill = oldSkills.find((s) => s.id === skillId);
|
|
164
190
|
const pluginScope = oldSkill?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;
|
|
165
|
-
const pluginRef = buildMarketplacePluginRef(skillId, marketplace);
|
|
166
191
|
try {
|
|
167
|
-
const outcome = await
|
|
192
|
+
const outcome = await removeUnderFirstNameHeld(
|
|
193
|
+
host,
|
|
194
|
+
pluginRefsOf(skillId, oldSkill?.origin, marketplace),
|
|
195
|
+
pluginScope,
|
|
196
|
+
projectDir
|
|
197
|
+
);
|
|
168
198
|
if (outcome === "removed") uninstalled.push(skillId);
|
|
169
199
|
} catch (error) {
|
|
170
200
|
failed.push({ id: skillId, error: getErrorMessage(error) });
|
|
@@ -172,6 +202,20 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
|
|
|
172
202
|
}
|
|
173
203
|
return { uninstalled, failed };
|
|
174
204
|
}
|
|
205
|
+
function pluginRefsOf(skillId, origin, marketplace) {
|
|
206
|
+
const marketplaceRef = buildMarketplacePluginRef(skillId, marketplace);
|
|
207
|
+
if (origin === void 0 || origin === marketplace || origin === EJECT_SOURCE) {
|
|
208
|
+
return [marketplaceRef];
|
|
209
|
+
}
|
|
210
|
+
return [buildMarketplacePluginRef(skillId, origin), marketplaceRef];
|
|
211
|
+
}
|
|
212
|
+
async function removeUnderFirstNameHeld(host, pluginRefs, scope, projectDir) {
|
|
213
|
+
for (const pluginRef of pluginRefs) {
|
|
214
|
+
const outcome = await host.uninstallPlugin(pluginRef, scope, projectDir);
|
|
215
|
+
if (outcome === "removed") return outcome;
|
|
216
|
+
}
|
|
217
|
+
return "absent";
|
|
218
|
+
}
|
|
175
219
|
|
|
176
220
|
// src/cli/lib/loading/catalogue-seat.ts
|
|
177
221
|
async function withCatalogueSeatedFor(projectDir, body) {
|
|
@@ -190,7 +234,7 @@ async function withCatalogueSeatedFor(projectDir, body) {
|
|
|
190
234
|
}
|
|
191
235
|
|
|
192
236
|
// src/cli/lib/operations/project/remove-compiled-agents.ts
|
|
193
|
-
import
|
|
237
|
+
import path3 from "path";
|
|
194
238
|
async function removeCompiledAgents(options) {
|
|
195
239
|
const outcomes = await Promise.all(
|
|
196
240
|
options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name))
|
|
@@ -209,7 +253,7 @@ async function pruneCompiledAgents(options) {
|
|
|
209
253
|
}
|
|
210
254
|
async function removeCompiledAgentFile(agentsDir, name) {
|
|
211
255
|
try {
|
|
212
|
-
await remove(
|
|
256
|
+
await remove(path3.join(agentsDir, `${name}${agentCodec("claude").extension}`));
|
|
213
257
|
return { name, ok: true };
|
|
214
258
|
} catch (error) {
|
|
215
259
|
return { name, ok: false, error: getErrorMessage(error) };
|
|
@@ -273,9 +317,13 @@ async function pruneStaleAgentsForPass(options, provider, recompileResult) {
|
|
|
273
317
|
export {
|
|
274
318
|
discoverInstalledSkills,
|
|
275
319
|
copyLocalSkills,
|
|
320
|
+
skillFoldersAt,
|
|
321
|
+
removeSkillFoldersCreatedSince,
|
|
276
322
|
uninstallPluginSkills,
|
|
323
|
+
pluginRefsOf,
|
|
324
|
+
removeUnderFirstNameHeld,
|
|
277
325
|
withCatalogueSeatedFor,
|
|
278
326
|
removeCompiledAgents,
|
|
279
327
|
compileAgents
|
|
280
328
|
};
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
329
|
+
//# sourceMappingURL=chunk-XMQIWPIR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/lib/operations/skills/discover-skills.ts","../src/cli/lib/operations/skills/copy-local-skills.ts","../src/cli/lib/operations/skills/uninstall-plugin-skills.ts","../src/cli/lib/loading/catalogue-seat.ts","../src/cli/lib/operations/project/remove-compiled-agents.ts","../src/cli/lib/operations/project/compile-agents.ts"],"sourcesContent":["import path from \"path\";\n\nimport { discoverAllPluginSkills } from \"../../plugins/index.js\";\nimport { isHomeDirectory } from \"../../installation/is-home-directory.js\";\nimport { loadSkillsFromDir, type LoadedSkills } from \"../../loading/index.js\";\nimport { sayingEachWarningOnce, verbose } from \"../../../utils/logger.js\";\nimport { globalInstallRoot } from \"../../../consts.js\";\nimport {\n inheritedGlobalProvider,\n providerAtScope,\n skillsDir,\n skillsPathPrefix,\n} from \"../../installation/install-layout.js\";\nimport { typedEntries, typedKeys } from \"../../../utils/typed-object.js\";\nimport type { UnusableSkillMetadata } from \"../../loading/index.js\";\nimport type {\n SkillDefinition,\n SkillDefinitionMap,\n SkillId,\n SkillScope,\n} from \"../../../types/index.js\";\n\nexport type DiscoveredSkills = {\n allSkills: SkillDefinitionMap;\n totalSkillCount: number;\n pluginSkillCount: number;\n globalPluginSkillCount: number;\n globalLocalSkillCount: number;\n /** Skills whose metadata.yaml describes no skill; `compile` refuses over any entry. */\n unusableMetadata: UnusableSkillMetadata[];\n};\n\nconst NO_LOCAL_SKILLS: LoadedSkills = { skills: {}, unusableMetadata: [] };\n\n/**\n * Discovers copied-in (not plugin) skills at one scope. A global scan's warnings are said once per\n * run, since the fan-out asks for that one directory once per registered project.\n */\nasync function discoverLocalProjectSkills(\n projectDir: string,\n scope: SkillScope,\n): Promise<LoadedSkills> {\n const provider = providerAtScope(projectDir, scope);\n const pathPrefix = skillsPathPrefix(provider, scope, projectDir);\n const scan = () =>\n loadSkillsFromDir(skillsDir(provider, scope, projectDir), {\n pathPrefix,\n requireMetadata: true,\n folderLabel: folderLabelAt(pathPrefix, scope),\n });\n\n return scope === \"global\" ? sayingEachWarningOnce(scan) : scan();\n}\n\n/** From `~/`: saying it once per run matches on text, so it must never equal a project's line. */\nfunction folderLabelAt(pathPrefix: string, scope: SkillScope): string {\n const underHome = scope === \"global\" && !path.isAbsolute(pathPrefix);\n return underHome ? `~/${pathPrefix}/` : `${pathPrefix}/`;\n}\n\nfunction skillsRootAt(projectDir: string, scope: SkillScope): string {\n return skillsDir(providerAtScope(projectDir, scope), scope, projectDir);\n}\n\n/** Later sources win. */\nfunction mergeSkills(...skillSources: SkillDefinitionMap[]): SkillDefinitionMap {\n const merged: SkillDefinitionMap = {};\n\n for (const source of skillSources) {\n for (const [id, skill] of typedEntries<SkillId, SkillDefinition | undefined>(source)) {\n if (skill) {\n merged[id] = skill;\n }\n }\n }\n\n return merged;\n}\n\n/** Merges global plugins, global copied-in, project plugins, project copied-in; project wins. */\nexport async function discoverInstalledSkills(projectDir: string): Promise<DiscoveredSkills> {\n const isGlobalProject = isHomeDirectory(projectDir);\n\n const globalPlugins = isGlobalProject ? {} : await discoverGlobalPluginSkills(projectDir);\n const globalLocal = isGlobalProject\n ? NO_LOCAL_SKILLS\n : await discoverGlobalLocalSkills(projectDir);\n const projectPlugins = await discoverProjectPluginSkills(projectDir);\n // At the home root both scopes are one installation, so ask the global scope only.\n const localScope: SkillScope = isGlobalProject ? \"global\" : \"project\";\n const projectLocal = await discoverLocalSkillsAt(projectDir, localScope);\n\n return assembleDiscoveredSkills({ globalPlugins, globalLocal, projectPlugins, projectLocal });\n}\n\nasync function discoverGlobalPluginSkills(projectDir: string): Promise<SkillDefinitionMap> {\n const skills = await discoverAllPluginSkills(\n globalInstallRoot(),\n inheritedGlobalProvider(projectDir),\n );\n const count = skillCount(skills);\n if (count > 0) verbose(` Found ${count} skills from global plugins`);\n return skills;\n}\n\nasync function discoverGlobalLocalSkills(projectDir: string): Promise<LoadedSkills> {\n const loaded = await discoverLocalProjectSkills(projectDir, \"global\");\n const count = skillCount(loaded.skills);\n if (count > 0) {\n verbose(` Found ${count} global local skills from ${skillsRootAt(projectDir, \"global\")}`);\n }\n return loaded;\n}\n\nasync function discoverProjectPluginSkills(projectDir: string): Promise<SkillDefinitionMap> {\n const skills = await discoverAllPluginSkills(projectDir);\n verbose(` Found ${skillCount(skills)} skills from installed plugins`);\n return skills;\n}\n\nasync function discoverLocalSkillsAt(projectDir: string, scope: SkillScope): Promise<LoadedSkills> {\n const loaded = await discoverLocalProjectSkills(projectDir, scope);\n verbose(\n ` Found ${skillCount(loaded.skills)} local skills from ${skillsRootAt(projectDir, scope)}`,\n );\n return loaded;\n}\n\ntype SkillsByOrigin = {\n globalPlugins: SkillDefinitionMap;\n globalLocal: LoadedSkills;\n projectPlugins: SkillDefinitionMap;\n projectLocal: LoadedSkills;\n};\n\nfunction assembleDiscoveredSkills(found: SkillsByOrigin): DiscoveredSkills {\n const { globalPlugins, globalLocal, projectPlugins, projectLocal } = found;\n const allSkills = mergeSkills(\n globalPlugins,\n globalLocal.skills,\n projectPlugins,\n projectLocal.skills,\n );\n // A plugin installed at both scopes is listed by both, but is one skill.\n const distinctPluginSkills = mergeSkills(globalPlugins, projectPlugins);\n\n return {\n allSkills,\n totalSkillCount: skillCount(allSkills),\n pluginSkillCount: skillCount(distinctPluginSkills),\n globalPluginSkillCount: skillCount(globalPlugins),\n globalLocalSkillCount: skillCount(globalLocal.skills),\n unusableMetadata: [...globalLocal.unusableMetadata, ...projectLocal.unusableMetadata],\n };\n}\n\nfunction skillCount(skills: SkillDefinitionMap): number {\n return typedKeys<SkillId>(skills).length;\n}\n","import path from \"path\";\nimport { resolveInstallPaths } from \"../../installation/index.js\";\nimport { copySkillsToLocalFlattened, type CopiedSkill } from \"../../skills/index.js\";\nimport { ensureDir, listDirectories, remove } from \"../../../utils/fs.js\";\nimport type { SkillConfig } from \"../../../types/config.js\";\nimport type { SourceLoadResult } from \"../../loading/source-loader.js\";\n\nexport type SkillCopyResult = {\n projectCopied: CopiedSkill[];\n globalCopied: CopiedSkill[];\n totalCopied: number;\n};\n\nasync function copyScopedLocalSkills(\n scopeSkills: SkillConfig[],\n skillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n if (scopeSkills.length === 0) return [];\n\n await ensureDir(skillsDir);\n\n return copySkillsToLocalFlattened(\n scopeSkills.map((s) => s.id),\n skillsDir,\n sourceResult,\n );\n}\n\nexport async function copyLocalSkills(\n skills: SkillConfig[],\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<SkillCopyResult> {\n const projectLocalSkills = skills.filter((s) => s.scope !== \"global\");\n const globalLocalSkills = skills.filter((s) => s.scope === \"global\");\n\n const projectPaths = resolveInstallPaths(projectDir, \"project\");\n const globalPaths = resolveInstallPaths(projectDir, \"global\");\n\n const projectCopied = await copyScopedLocalSkills(\n projectLocalSkills,\n projectPaths.skillsDir,\n sourceResult,\n );\n const globalCopied = await copyScopedLocalSkills(\n globalLocalSkills,\n globalPaths.skillsDir,\n sourceResult,\n );\n\n return {\n projectCopied,\n globalCopied,\n totalCopied: projectCopied.length + globalCopied.length,\n };\n}\n\n/** Every skill folder at both scopes, as a full path. */\nexport async function skillFoldersAt(projectDir: string): Promise<ReadonlySet<string>> {\n const skillsDirs = [\n resolveInstallPaths(projectDir, \"project\").skillsDir,\n resolveInstallPaths(projectDir, \"global\").skillsDir,\n ];\n const folders = await Promise.all(skillsDirs.map(foldersIn));\n return new Set(folders.flat());\n}\n\nasync function foldersIn(dir: string): Promise<string[]> {\n return (await listDirectories(dir)).map((name) => path.join(dir, name));\n}\n\n/** A folder already in `before` stays, whatever was written into it since. */\nexport async function removeSkillFoldersCreatedSince(\n before: ReadonlySet<string>,\n projectDir: string,\n): Promise<ReadonlySet<string>> {\n const created = [...(await skillFoldersAt(projectDir))].filter((folder) => !before.has(folder));\n await Promise.all(created.map(remove));\n return new Set(created);\n}\n","import { hostAt } from \"../../hosts/host-for.js\";\nimport type { PluginHost, PluginRemovalOutcome } from \"../../hosts/plugin-host.js\";\nimport { buildMarketplacePluginRef } from \"../../plugins/index.js\";\nimport { EJECT_SOURCE } from \"../../../consts.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport type { SkillId } from \"../../../types/index.js\";\nimport type { SkillConfig, SkillScope } from \"../../../types/config.js\";\n\n/** The safe default: a project removal cannot take a plugin from every project under one HOME. */\nconst SCOPE_OF_AN_UNRECORDED_SKILL: SkillScope = \"project\";\n\nexport type PluginUninstallResult = {\n /** Only plugins the host reported `removed`; an already-absent plugin is not listed. */\n uninstalled: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\nexport async function uninstallPluginSkills(\n skillIds: SkillId[],\n oldSkills: SkillConfig[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginUninstallResult> {\n const host = hostAt(projectDir);\n const uninstalled: SkillId[] = [];\n const failed: PluginUninstallResult[\"failed\"] = [];\n\n for (const skillId of skillIds) {\n const oldSkill = oldSkills.find((s) => s.id === skillId);\n const pluginScope = oldSkill?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;\n try {\n const outcome = await removeUnderFirstNameHeld(\n host,\n pluginRefsOf(skillId, oldSkill?.origin, marketplace),\n pluginScope,\n projectDir,\n );\n if (outcome === \"removed\") uninstalled.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { uninstalled, failed };\n}\n\n/**\n * The name its install recorded, then the installation's marketplace's, as `uninstall` asks: a\n * project can leave a plugin from its own marketplace at global scope.\n */\nexport function pluginRefsOf(\n skillId: SkillId,\n origin: string | undefined,\n marketplace: string,\n): string[] {\n const marketplaceRef = buildMarketplacePluginRef(skillId, marketplace);\n if (origin === undefined || origin === marketplace || origin === EJECT_SOURCE) {\n return [marketplaceRef];\n }\n return [buildMarketplacePluginRef(skillId, origin), marketplaceRef];\n}\n\n/** `absent` passes the ask to the next name; a throw is a real failure and ends it. */\nexport async function removeUnderFirstNameHeld(\n host: PluginHost,\n pluginRefs: string[],\n scope: SkillScope,\n projectDir: string,\n): Promise<PluginRemovalOutcome> {\n for (const pluginRef of pluginRefs) {\n const outcome = await host.uninstallPlugin(pluginRef, scope, projectDir);\n if (outcome === \"removed\") return outcome;\n }\n return \"absent\";\n}\n","import type { MergedSkillsMatrix } from \"../../types\";\nimport { initializeMatrix, matrix } from \"../matrix/matrix-provider.js\";\nimport { loadSkillsMatrixFromSource } from \"./source-loader.js\";\n\n/**\n * Runs `body` against `projectDir`'s own skills catalogue, then restores the caller's. The load\n * stays outside the `try`: a failed load seats nothing, so there is nothing to restore.\n */\nexport async function withCatalogueSeatedFor<T>(\n projectDir: string,\n body: (catalogue: MergedSkillsMatrix) => Promise<T>,\n): Promise<T> {\n const callersCatalogue = matrix;\n const { matrix: seated } = await loadSkillsMatrixFromSource({\n projectDir,\n purpose: \"upkeep\",\n skipExtraSources: true,\n matrixOnly: true,\n });\n try {\n return await body(seated);\n } finally {\n initializeMatrix(callersCatalogue);\n }\n}\n","import path from \"path\";\nimport { pruneStaleCompiledAgents } from \"../../agents/list-compiled-agents.js\";\nimport { type AgentCodec, agentCodec } from \"../../installation/install-layout.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport { remove, removeDirIfEmpty } from \"../../../utils/fs.js\";\nimport type { AgentName } from \"../../../types/index.js\";\n\nexport type RemoveCompiledAgentsOptions = {\n agentsDir: string;\n agents: readonly AgentName[];\n};\n\nexport type PruneCompiledAgentsOptions = {\n agentsDir: string;\n /** The COMPLETE set of agents that belong in `agentsDir`; every other compiled agent is stale. */\n keep: ReadonlySet<AgentName>;\n codec?: AgentCodec;\n};\n\nexport type RemoveCompiledAgentsResult = {\n /** An absent file counts as removed. */\n removed: AgentName[];\n failed: Array<{ name: AgentName; error: string }>;\n};\n\ntype RemovalOutcome = { name: AgentName; ok: true } | { name: AgentName; ok: false; error: string };\n\n/**\n * Also removes `agentsDir` when nothing at all is left in it; the `.claude/` above is uninstall's.\n */\nexport async function removeCompiledAgents(\n options: RemoveCompiledAgentsOptions,\n): Promise<RemoveCompiledAgentsResult> {\n const outcomes = await Promise.all(\n options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name)),\n );\n await removeDirIfEmpty(options.agentsDir);\n\n return {\n removed: outcomes.flatMap((outcome) => (outcome.ok ? [outcome.name] : [])),\n failed: outcomes.flatMap((outcome) =>\n outcome.ok ? [] : [{ name: outcome.name, error: outcome.error }],\n ),\n };\n}\n\n/** Hand-authored agents survive; the directory goes only when nothing at all remains. */\nexport async function pruneCompiledAgents(options: PruneCompiledAgentsOptions): Promise<void> {\n await pruneStaleCompiledAgents(options.agentsDir, options.keep, options.codec);\n await removeDirIfEmpty(options.agentsDir);\n}\n\nasync function removeCompiledAgentFile(\n agentsDir: string,\n name: AgentName,\n): Promise<RemovalOutcome> {\n try {\n await remove(path.join(agentsDir, `${name}${agentCodec(\"claude\").extension}`));\n return { name, ok: true };\n } catch (error) {\n return { name, ok: false, error: getErrorMessage(error) };\n }\n}\n","import { pruneCompiledAgents } from \"./remove-compiled-agents.js\";\nimport { recompileAgents } from \"../../agents/index.js\";\nimport { loadProjectConfigFromDir } from \"../../configuration/project-config.js\";\nimport { buildAgentScopeMap } from \"../../installation/index.js\";\nimport { agentCodec, providerInUse } from \"../../installation/install-layout.js\";\nimport type { Provider } from \"../../../consts.js\";\nimport type { AgentName, SkillDefinitionMap, SkillScope } from \"../../../types/index.js\";\n\nexport type CompileAgentsOptions = {\n projectDir: string;\n /** The installation compiled, where `projectDir` holds two; the default is the one in use. */\n provider?: Provider;\n sourcePath: string;\n pluginDir?: string;\n skills?: SkillDefinitionMap;\n agentScopeMap?: Map<AgentName, SkillScope>;\n agents?: AgentName[];\n scopeFilter?: SkillScope;\n outputDir?: string;\n};\n\nexport type CompilationResult = {\n compiled: AgentName[];\n /** The subset of `compiled` whose file this pass actually wrote. */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nexport async function compileAgents(options: CompileAgentsOptions): Promise<CompilationResult> {\n const provider = options.provider ?? providerInUse(options.projectDir);\n const roster = await rosterForPass(options, provider);\n\n const recompileResult = await recompileAgents({\n pluginDir: options.pluginDir ?? options.projectDir,\n sourcePath: options.sourcePath,\n ...(roster.agents !== undefined && { agents: roster.agents }),\n ...(options.skills !== undefined && { skills: options.skills }),\n projectDir: options.projectDir,\n provider,\n ...(options.outputDir !== undefined && { outputDir: options.outputDir }),\n ...(roster.agentScopeMap !== undefined && { agentScopeMap: roster.agentScopeMap }),\n });\n\n await pruneStaleAgentsForPass(options, provider, recompileResult);\n\n return {\n compiled: recompileResult.compiled,\n rewritten: recompileResult.rewritten,\n failed: recompileResult.failed,\n warnings: recompileResult.warnings,\n };\n}\n\ntype PassRoster = {\n agents: AgentName[] | undefined;\n agentScopeMap: Map<AgentName, SkillScope> | undefined;\n};\n\nasync function rosterForPass(\n options: CompileAgentsOptions,\n provider: Provider,\n): Promise<PassRoster> {\n if (!options.scopeFilter) return { agents: options.agents, agentScopeMap: options.agentScopeMap };\n return rosterForScope(options, options.scopeFilter, provider);\n}\n\nasync function rosterForScope(\n options: CompileAgentsOptions,\n scope: SkillScope,\n provider: Provider,\n): Promise<PassRoster> {\n const config = (await loadProjectConfigFromDir(options.projectDir, provider))?.config;\n const activeAtScope = config?.agents\n .filter((agent) => !agent.excluded && agent.scope === scope)\n .map((agent) => agent.name);\n\n return {\n agents: requestedAgentsAmong(options.agents, activeAtScope),\n agentScopeMap: options.agentScopeMap ?? (config ? buildAgentScopeMap(config) : undefined),\n };\n}\n\nfunction requestedAgentsAmong(\n requested: AgentName[] | undefined,\n activeAtScope: AgentName[] | undefined,\n): AgentName[] | undefined {\n if (activeAtScope === undefined) return requested;\n if (requested === undefined) return activeAtScope;\n\n const atScope = new Set(activeAtScope);\n return requested.filter((name) => atScope.has(name));\n}\n\n/**\n * Only an unfiltered pass owns its whole `outputDir`, so only it prunes agents no longer compiled\n * there; a scope-filtered pass must never delete another scope's files.\n */\nasync function pruneStaleAgentsForPass(\n options: CompileAgentsOptions,\n provider: Provider,\n recompileResult: CompilationResult,\n): Promise<void> {\n if (options.scopeFilter || !options.outputDir) return;\n\n const compiledForDir = new Set<AgentName>([\n ...recompileResult.compiled,\n ...recompileResult.failed,\n ]);\n await pruneCompiledAgents({\n agentsDir: options.outputDir,\n keep: compiledForDir,\n // A Codex role is a `.toml`, so the prune must know the host's extension.\n codec: agentCodec(provider),\n });\n}\n"],"mappings":"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","names":["path","skillsDir","path","path","path"]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
hostFor,
|
|
7
7
|
loadProjectConfigFromDir,
|
|
8
8
|
refuseUnofferedPlacements
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ENET4IF6.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/lib/hosts/configured-placements.ts
|
|
12
12
|
async function unofferablePlacementsFound(cwd) {
|
|
@@ -36,4 +36,4 @@ async function configuredSkillsAt({ dir, provider }) {
|
|
|
36
36
|
export {
|
|
37
37
|
unofferablePlacementsFound
|
|
38
38
|
};
|
|
39
|
-
//# sourceMappingURL=chunk-
|
|
39
|
+
//# sourceMappingURL=chunk-ZBI6GFJD.js.map
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BaseCommand,
|
|
4
4
|
EXIT_CODES
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-JTMSFBCA.js";
|
|
6
|
+
import "../../chunk-FACDJH6O.js";
|
|
6
7
|
import {
|
|
7
8
|
NO_VALID_DEFAULT_EXPORT,
|
|
8
9
|
configLoadFailure,
|
|
@@ -23,10 +24,10 @@ import {
|
|
|
23
24
|
warn,
|
|
24
25
|
writeFile,
|
|
25
26
|
writeMarketplace
|
|
26
|
-
} from "../../chunk-
|
|
27
|
+
} from "../../chunk-ENET4IF6.js";
|
|
27
28
|
import {
|
|
28
29
|
plural
|
|
29
|
-
} from "../../chunk-
|
|
30
|
+
} from "../../chunk-UE4Z3YMB.js";
|
|
30
31
|
import {
|
|
31
32
|
CATALOG_JSON,
|
|
32
33
|
CLI_INVOKE_COMMAND,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/commands/build/marketplace.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { z } from \"zod\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose, warn } from \"../../utils/logger\";\nimport {\n configUnreadableError,\n marketplaceHasNoVersion,\n marketplaceNameNotPublishable,\n marketplaceOwnerHasNoName,\n} from \"../../utils/messages\";\nimport { readFile, writeFile } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { readSourceRepoConfig } from \"../../lib/configuration/config\";\nimport { configLoadFailure, NO_VALID_DEFAULT_EXPORT } from \"../../lib/configuration/config-loader\";\nimport { loadMarketplaceMatrix } from \"../../lib/loading\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n validateMarketplaceName,\n validateSkillIdNamespace,\n} from \"../../lib/marketplace-generator\";\nimport {\n CATALOG_JSON,\n CLI_INVOKE_COMMAND,\n GENERATED_AT_BUILD,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n PLUGINS_DIST_PATH,\n STANDARD_FILES,\n} from \"../../consts\";\nimport type { Marketplace, MergedSkillsMatrix } from \"../../types\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { plural } from \"../../utils/string.js\";\n\nconst DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;\n\nconst AUTHOR_STRING_PATTERN = /^(.*?)\\s*<([^>]+)>\\s*(?:\\(([^)]+)\\))?\\s*$/;\n\nconst MARKETPLACE_NOUN = \"Marketplace\";\n\nconst RESERVED_NAME_WAY_OUT = \"set package.json 'name', or pass --name\";\n\nconst packageAuthorObjectSchema = z.object({\n name: z.string(),\n email: z.string().exactOptional(),\n url: z.string().exactOptional(),\n});\n\nconst packageJsonSchema = z\n .object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n author: z.union([z.string(), packageAuthorObjectSchema]).exactOptional(),\n })\n .passthrough();\n\ntype PackageJson = z.infer<typeof packageJsonSchema>;\ntype MarketplaceIdentity = Pick<PackageJson, \"name\" | \"version\" | \"description\"> & {\n ownerName: string;\n ownerEmail?: string;\n};\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary = \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file. Reads marketplace identity (name, version, description, author) from package.json in the current working directory. Use --name to override the marketplace name when package.json uses an npm scoped name (e.g. @scope/pkg), which is not a valid marketplace name.\";\n\n static examples = [\n {\n description: \"Generate marketplace.json from the default plugins directory\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Generate marketplace.json from a custom plugins directory\",\n command: \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n },\n {\n description: \"Write marketplace.json to a custom output path\",\n command: \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n },\n {\n description:\n \"Override the marketplace name (use when package.json has an npm scoped name like @scope/pkg)\",\n command: \"<%= config.bin %> <%= command.id %> --name my-marketplace\",\n },\n ];\n\n static flags = {\n name: Flags.string({\n description:\n \"Override the marketplace name (defaults to package.json 'name'). Must be kebab-case.\",\n }),\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: PLUGINS_DIST_PATH,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);\n\n this.printHeader(pluginsDir, outputPath);\n\n try {\n // Read and refuse everything before the first write, so manifest and catalogue always agree.\n const marketplace = await this.scanPlugins(pluginsDir, flags[\"plugins-dir\"], identity);\n const catalog = await this.readCatalog(projectRoot);\n\n await this.writeManifest(outputPath, marketplace);\n await this.writeCatalog(outputPath, catalog);\n this.printStats(marketplace);\n this.printSample(marketplace);\n\n this.log(\"\");\n this.logSuccess(\n `Marketplace generated with ${plural(getMarketplaceStats(marketplace).total, \"plugin\")}!`,\n );\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.handleError(error);\n }\n }\n\n private async loadMarketplaceIdentity(\n projectRoot: string,\n nameOverride?: string,\n ): Promise<MarketplaceIdentity> {\n const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);\n const { name, version, description, author } = await this.readPackageJson(\n projectRoot,\n packageJsonPath,\n );\n\n if (version.trim() === \"\") {\n this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const owner = parseAuthor(author);\n if (owner.name.trim() === \"\") {\n this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);\n\n const reservedError = validateMarketplaceName(resolvedName, name, RESERVED_NAME_WAY_OUT);\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n\n return {\n name: resolvedName,\n version,\n description,\n ownerName: owner.name,\n ...(owner.email !== undefined && { ownerEmail: owner.email }),\n };\n }\n\n private async readPackageJson(\n projectRoot: string,\n packageJsonPath: string,\n ): Promise<PackageJson> {\n let rawContent: string;\n try {\n rawContent = await readFile(packageJsonPath);\n } catch {\n this.error(\n `Missing package.json at ${projectRoot}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawContent);\n } catch (error) {\n this.error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const parseResult = packageJsonSchema.safeParse(parsedJson);\n if (!parseResult.success) {\n const missingFields = parseResult.error.issues.map((i) => i.path.join(\".\")).join(\", \");\n this.error(\n `package.json at ${packageJsonPath} is missing required fields: ${missingFields}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n return parseResult.data;\n }\n\n /** A package.json name that fails gets a different refusal: its way out is `--name`. */\n private resolvePublishableName(\n packageName: string,\n nameOverride: string | undefined,\n packageJsonPath: string,\n ): string {\n if (nameOverride !== undefined) {\n const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);\n if (invalidOverride) {\n this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return nameOverride;\n }\n\n if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {\n this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n return packageName;\n }\n\n private printHeader(pluginsDir: string, outputPath: string): void {\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n }\n\n private async scanPlugins(\n pluginsDir: string,\n pluginsDirFlag: string,\n identity: MarketplaceIdentity,\n ): Promise<Marketplace> {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: identity.name,\n version: identity.version,\n description: identity.description,\n ownerName: identity.ownerName,\n ...(identity.ownerEmail !== undefined && { ownerEmail: identity.ownerEmail }),\n pluginRoot: `./${pluginsDirFlag}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${plural(stats.total, \"plugin\")}`);\n\n if (marketplace.plugins.length === 0) {\n this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });\n }\n\n const namespaceError = validateSkillIdNamespace(marketplace);\n if (namespaceError) {\n this.error(namespaceError, { exit: EXIT_CODES.ERROR });\n }\n\n return marketplace;\n }\n\n /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */\n private async readCatalog(projectRoot: string): Promise<MergedSkillsMatrix> {\n this.log(`Reading the skills for ${CATALOG_JSON}...`);\n await this.refuseAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\n }\n\n /** Every other reader takes such a file as absent; the build is where its author can fix it. */\n private async refuseAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind !== \"declares-nothing\") return;\n\n this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n private async writeManifest(outputPath: string, marketplace: Marketplace): Promise<void> {\n this.log(`Writing ${MARKETPLACE_JSON}...`);\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n }\n\n private async writeCatalog(outputPath: string, catalog: MergedSkillsMatrix): Promise<void> {\n const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);\n\n this.log(`Writing ${CATALOG_JSON}...`);\n await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\\n`);\n this.log(`Wrote ${catalogPath}`);\n }\n\n private printStats(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = sortBy(\n Object.entries(getMarketplaceStats(marketplace).byCategory),\n ([, count]) => -count,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n }\n\n private printSample(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n }\n}\n\ntype ParsedAuthor = {\n name: string;\n email?: string;\n};\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/build/marketplace.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { z } from \"zod\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose, warn } from \"../../utils/logger\";\nimport {\n configUnreadableError,\n marketplaceHasNoVersion,\n marketplaceNameNotPublishable,\n marketplaceOwnerHasNoName,\n} from \"../../utils/messages\";\nimport { readFile, writeFile } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { readSourceRepoConfig } from \"../../lib/configuration/config\";\nimport { configLoadFailure, NO_VALID_DEFAULT_EXPORT } from \"../../lib/configuration/config-loader\";\nimport { loadMarketplaceMatrix } from \"../../lib/loading\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n validateMarketplaceName,\n validateSkillIdNamespace,\n} from \"../../lib/marketplace-generator\";\nimport {\n CATALOG_JSON,\n CLI_INVOKE_COMMAND,\n GENERATED_AT_BUILD,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n PLUGINS_DIST_PATH,\n STANDARD_FILES,\n} from \"../../consts\";\nimport type { Marketplace, MergedSkillsMatrix } from \"../../types\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { plural } from \"../../utils/string.js\";\n\nconst DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;\n\nconst AUTHOR_STRING_PATTERN = /^(.*?)\\s*<([^>]+)>\\s*(?:\\(([^)]+)\\))?\\s*$/;\n\nconst MARKETPLACE_NOUN = \"Marketplace\";\n\nconst RESERVED_NAME_WAY_OUT = \"set package.json 'name', or pass --name\";\n\nconst packageAuthorObjectSchema = z.object({\n name: z.string(),\n email: z.string().exactOptional(),\n url: z.string().exactOptional(),\n});\n\nconst packageJsonSchema = z\n .object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n author: z.union([z.string(), packageAuthorObjectSchema]).exactOptional(),\n })\n .passthrough();\n\ntype PackageJson = z.infer<typeof packageJsonSchema>;\ntype MarketplaceIdentity = Pick<PackageJson, \"name\" | \"version\" | \"description\"> & {\n ownerName: string;\n ownerEmail?: string;\n};\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary = \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file. Reads marketplace identity (name, version, description, author) from package.json in the current working directory. Use --name to override the marketplace name when package.json uses an npm scoped name (e.g. @scope/pkg), which is not a valid marketplace name.\";\n\n static examples = [\n {\n description: \"Generate marketplace.json from the default plugins directory\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Generate marketplace.json from a custom plugins directory\",\n command: \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n },\n {\n description: \"Write marketplace.json to a custom output path\",\n command: \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n },\n {\n description:\n \"Override the marketplace name (use when package.json has an npm scoped name like @scope/pkg)\",\n command: \"<%= config.bin %> <%= command.id %> --name my-marketplace\",\n },\n ];\n\n static flags = {\n name: Flags.string({\n description:\n \"Override the marketplace name (defaults to package.json 'name'). Must be kebab-case.\",\n }),\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: PLUGINS_DIST_PATH,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);\n\n this.printHeader(pluginsDir, outputPath);\n\n try {\n // Read and refuse everything before the first write, so manifest and catalogue always agree.\n const marketplace = await this.scanPlugins(pluginsDir, flags[\"plugins-dir\"], identity);\n const catalog = await this.readCatalog(projectRoot);\n\n await this.writeManifest(outputPath, marketplace);\n await this.writeCatalog(outputPath, catalog);\n this.printStats(marketplace);\n this.printSample(marketplace);\n\n this.log(\"\");\n this.logSuccess(\n `Marketplace generated with ${plural(getMarketplaceStats(marketplace).total, \"plugin\")}!`,\n );\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.handleError(error);\n }\n }\n\n private async loadMarketplaceIdentity(\n projectRoot: string,\n nameOverride?: string,\n ): Promise<MarketplaceIdentity> {\n const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);\n const { name, version, description, author } = await this.readPackageJson(\n projectRoot,\n packageJsonPath,\n );\n\n if (version.trim() === \"\") {\n this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const owner = parseAuthor(author);\n if (owner.name.trim() === \"\") {\n this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);\n\n const reservedError = validateMarketplaceName(resolvedName, name, RESERVED_NAME_WAY_OUT);\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n\n return {\n name: resolvedName,\n version,\n description,\n ownerName: owner.name,\n ...(owner.email !== undefined && { ownerEmail: owner.email }),\n };\n }\n\n private async readPackageJson(\n projectRoot: string,\n packageJsonPath: string,\n ): Promise<PackageJson> {\n let rawContent: string;\n try {\n rawContent = await readFile(packageJsonPath);\n } catch {\n this.error(\n `Missing package.json at ${projectRoot}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawContent);\n } catch (error) {\n this.error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const parseResult = packageJsonSchema.safeParse(parsedJson);\n if (!parseResult.success) {\n const missingFields = parseResult.error.issues.map((i) => i.path.join(\".\")).join(\", \");\n this.error(\n `package.json at ${packageJsonPath} is missing required fields: ${missingFields}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n return parseResult.data;\n }\n\n /** A package.json name that fails gets a different refusal: its way out is `--name`. */\n private resolvePublishableName(\n packageName: string,\n nameOverride: string | undefined,\n packageJsonPath: string,\n ): string {\n if (nameOverride !== undefined) {\n const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);\n if (invalidOverride) {\n this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return nameOverride;\n }\n\n if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {\n this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n return packageName;\n }\n\n private printHeader(pluginsDir: string, outputPath: string): void {\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n }\n\n private async scanPlugins(\n pluginsDir: string,\n pluginsDirFlag: string,\n identity: MarketplaceIdentity,\n ): Promise<Marketplace> {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: identity.name,\n version: identity.version,\n description: identity.description,\n ownerName: identity.ownerName,\n ...(identity.ownerEmail !== undefined && { ownerEmail: identity.ownerEmail }),\n pluginRoot: `./${pluginsDirFlag}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${plural(stats.total, \"plugin\")}`);\n\n if (marketplace.plugins.length === 0) {\n this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });\n }\n\n const namespaceError = validateSkillIdNamespace(marketplace);\n if (namespaceError) {\n this.error(namespaceError, { exit: EXIT_CODES.ERROR });\n }\n\n return marketplace;\n }\n\n /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */\n private async readCatalog(projectRoot: string): Promise<MergedSkillsMatrix> {\n this.log(`Reading the skills for ${CATALOG_JSON}...`);\n await this.refuseAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\n }\n\n /** Every other reader takes such a file as absent; the build is where its author can fix it. */\n private async refuseAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind !== \"declares-nothing\") return;\n\n this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n private async writeManifest(outputPath: string, marketplace: Marketplace): Promise<void> {\n this.log(`Writing ${MARKETPLACE_JSON}...`);\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n }\n\n private async writeCatalog(outputPath: string, catalog: MergedSkillsMatrix): Promise<void> {\n const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);\n\n this.log(`Writing ${CATALOG_JSON}...`);\n await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\\n`);\n this.log(`Wrote ${catalogPath}`);\n }\n\n private printStats(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = sortBy(\n Object.entries(getMarketplaceStats(marketplace).byCategory),\n ([, count]) => -count,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n }\n\n private printSample(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n }\n}\n\ntype ParsedAuthor = {\n name: string;\n email?: string;\n};\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
compileAllAgentPlugins,
|
|
4
4
|
printAgentCompilationSummary
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-EC3JXT23.js";
|
|
6
|
+
import "../../chunk-MQZNDK5F.js";
|
|
7
7
|
import {
|
|
8
8
|
BaseCommand
|
|
9
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-JTMSFBCA.js";
|
|
10
|
+
import "../../chunk-FACDJH6O.js";
|
|
10
11
|
import {
|
|
11
12
|
compileAllSkillPlugins,
|
|
12
13
|
compileSkillPlugin,
|
|
@@ -15,10 +16,10 @@ import {
|
|
|
15
16
|
readPluginManifest,
|
|
16
17
|
remove,
|
|
17
18
|
setVerbose
|
|
18
|
-
} from "../../chunk-
|
|
19
|
+
} from "../../chunk-ENET4IF6.js";
|
|
19
20
|
import {
|
|
20
21
|
plural
|
|
21
|
-
} from "../../chunk-
|
|
22
|
+
} from "../../chunk-UE4Z3YMB.js";
|
|
22
23
|
import {
|
|
23
24
|
DIRS,
|
|
24
25
|
PLUGINS_DIST_PATH
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/commands/build/plugins.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { listDirectories, remove } from \"../../utils/fs\";\nimport { DIRS, PLUGINS_DIST_PATH } from \"../../consts\";\nimport {\n compileAllSkillPlugins,\n compileSkillPlugin,\n printCompilationSummary,\n} from \"../../lib/skills\";\nimport { compileAllAgentPlugins, printAgentCompilationSummary } from \"../../lib/agents\";\nimport { readPluginManifest } from \"../../lib/plugins\";\nimport { plural } from \"../../utils/string\";\n\nexport default class BuildPlugins extends BaseCommand {\n static summary = \"Build skills and agents into standalone plugins\";\n\n static description =\n \"Build skills and agents into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only. Use --agents-dir to also compile agents.\";\n\n static examples = [\n {\n description: \"Compile every skill into plugins\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Compile a single skill by name\",\n command: \"<%= config.bin %> <%= command.id %> --skill cli-commander\",\n },\n {\n description: \"Write plugins to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> --output-dir ./plugins\",\n },\n {\n description: \"Also compile agents from a directory\",\n command: \"<%= config.bin %> <%= command.id %> --agents-dir ./agents\",\n },\n {\n description: \"Compile with verbose logging\",\n command: \"<%= config.bin %> <%= command.id %> --verbose\",\n },\n ];\n\n static flags = {\n \"agents-dir\": Flags.string({\n char: \"a\",\n description: \"Agents source directory (builds one plugin per agent)\",\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: PLUGINS_DIST_PATH,\n }),\n skill: Flags.string({\n description: \"Compile only a specific skill (path to skill directory)\",\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildPlugins);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const skillsDir = path.resolve(projectRoot, DIRS.skills);\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n this.printHeader(skillsDir, outputDir);\n\n try {\n const expectedSkillPlugins = await this.compileSkills(flags.skill, skillsDir, outputDir);\n\n if (flags[\"agents-dir\"]) {\n await this.compileAgents(projectRoot, flags[\"agents-dir\"], outputDir);\n }\n\n if (expectedSkillPlugins) {\n await this.pruneStaleSkillPlugins(outputDir, expectedSkillPlugins);\n }\n\n this.log(\"\");\n this.logSuccess(\"Plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.handleError(error);\n }\n }\n\n private printHeader(skillsDir: string, outputDir: string): void {\n this.log(\"\");\n this.log(\"Compiling skill plugins\");\n this.log(` Skills directory: ${skillsDir}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n }\n\n /**\n * Returns the plugin names that should remain, or `null` to skip pruning: in single-skill mode,\n * or after a failure, since a failed skill is indistinguishable from a removed one.\n */\n private async compileSkills(\n skillFlag: string | undefined,\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n if (skillFlag) {\n await this.compileOneSkill(path.resolve(skillsDir, skillFlag), outputDir);\n return null;\n }\n\n return this.compileEverySkill(skillsDir, outputDir);\n }\n\n private async compileOneSkill(skillPath: string, outputDir: string): Promise<void> {\n this.log(`Compiling skill at ${skillPath}...`);\n\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n\n this.log(`Compiled ${result.skillName}`);\n this.log(` Plugin path: ${result.pluginPath}`);\n }\n\n private async compileEverySkill(\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n this.log(\"Finding and compiling all skills...\");\n\n const { compiled, failed } = await compileAllSkillPlugins(skillsDir, outputDir);\n\n this.log(`Compiled ${plural(compiled.length, \"skill plugin\")}`);\n printCompilationSummary(compiled);\n\n if (failed.length > 0) {\n this.warn(\n `Skipping stale-plugin pruning: ${failed.length} skill(s) failed to compile ` +\n `(${failed.join(\", \")}). A failed skill is indistinguishable from a removed one.`,\n );\n return null;\n }\n\n return new Set(compiled.map((result) => result.skillName));\n }\n\n private async compileAgents(\n projectRoot: string,\n agentsDir: string,\n outputDir: string,\n ): Promise<void> {\n const resolvedAgentsDir = path.resolve(projectRoot, agentsDir);\n\n this.log(\"\");\n this.log(\"Compiling agent plugins\");\n this.log(` Agents directory: ${resolvedAgentsDir}`);\n this.log(\"\");\n\n this.log(\"Finding and compiling all agents...\");\n\n const agentResults = await compileAllAgentPlugins(resolvedAgentsDir, outputDir);\n\n this.log(`Compiled ${plural(agentResults.length, \"agent plugin\")}`);\n printAgentCompilationSummary(agentResults);\n }\n\n /** Prunes skill plugins only; agent plugins and non-plugin directories are left alone. */\n private async pruneStaleSkillPlugins(\n outputDir: string,\n expectedSkillPlugins: ReadonlySet<string>,\n ): Promise<void> {\n const dirNames = await listDirectories(outputDir);\n\n for (const dirName of dirNames) {\n if (expectedSkillPlugins.has(dirName)) continue;\n\n const pluginDir = path.join(outputDir, dirName);\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) continue;\n if (manifest.agents !== undefined) continue;\n\n await remove(pluginDir);\n this.log(` Pruned stale plugin: ${dirName}`);\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/build/plugins.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { listDirectories, remove } from \"../../utils/fs\";\nimport { DIRS, PLUGINS_DIST_PATH } from \"../../consts\";\nimport {\n compileAllSkillPlugins,\n compileSkillPlugin,\n printCompilationSummary,\n} from \"../../lib/skills\";\nimport { compileAllAgentPlugins, printAgentCompilationSummary } from \"../../lib/agents\";\nimport { readPluginManifest } from \"../../lib/plugins\";\nimport { plural } from \"../../utils/string\";\n\nexport default class BuildPlugins extends BaseCommand {\n static summary = \"Build skills and agents into standalone plugins\";\n\n static description =\n \"Build skills and agents into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only. Use --agents-dir to also compile agents.\";\n\n static examples = [\n {\n description: \"Compile every skill into plugins\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Compile a single skill by name\",\n command: \"<%= config.bin %> <%= command.id %> --skill cli-commander\",\n },\n {\n description: \"Write plugins to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> --output-dir ./plugins\",\n },\n {\n description: \"Also compile agents from a directory\",\n command: \"<%= config.bin %> <%= command.id %> --agents-dir ./agents\",\n },\n {\n description: \"Compile with verbose logging\",\n command: \"<%= config.bin %> <%= command.id %> --verbose\",\n },\n ];\n\n static flags = {\n \"agents-dir\": Flags.string({\n char: \"a\",\n description: \"Agents source directory (builds one plugin per agent)\",\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: PLUGINS_DIST_PATH,\n }),\n skill: Flags.string({\n description: \"Compile only a specific skill (path to skill directory)\",\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildPlugins);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const skillsDir = path.resolve(projectRoot, DIRS.skills);\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n this.printHeader(skillsDir, outputDir);\n\n try {\n const expectedSkillPlugins = await this.compileSkills(flags.skill, skillsDir, outputDir);\n\n if (flags[\"agents-dir\"]) {\n await this.compileAgents(projectRoot, flags[\"agents-dir\"], outputDir);\n }\n\n if (expectedSkillPlugins) {\n await this.pruneStaleSkillPlugins(outputDir, expectedSkillPlugins);\n }\n\n this.log(\"\");\n this.logSuccess(\"Plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.handleError(error);\n }\n }\n\n private printHeader(skillsDir: string, outputDir: string): void {\n this.log(\"\");\n this.log(\"Compiling skill plugins\");\n this.log(` Skills directory: ${skillsDir}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n }\n\n /**\n * Returns the plugin names that should remain, or `null` to skip pruning: in single-skill mode,\n * or after a failure, since a failed skill is indistinguishable from a removed one.\n */\n private async compileSkills(\n skillFlag: string | undefined,\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n if (skillFlag) {\n await this.compileOneSkill(path.resolve(skillsDir, skillFlag), outputDir);\n return null;\n }\n\n return this.compileEverySkill(skillsDir, outputDir);\n }\n\n private async compileOneSkill(skillPath: string, outputDir: string): Promise<void> {\n this.log(`Compiling skill at ${skillPath}...`);\n\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n\n this.log(`Compiled ${result.skillName}`);\n this.log(` Plugin path: ${result.pluginPath}`);\n }\n\n private async compileEverySkill(\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n this.log(\"Finding and compiling all skills...\");\n\n const { compiled, failed } = await compileAllSkillPlugins(skillsDir, outputDir);\n\n this.log(`Compiled ${plural(compiled.length, \"skill plugin\")}`);\n printCompilationSummary(compiled);\n\n if (failed.length > 0) {\n this.warn(\n `Skipping stale-plugin pruning: ${failed.length} skill(s) failed to compile ` +\n `(${failed.join(\", \")}). A failed skill is indistinguishable from a removed one.`,\n );\n return null;\n }\n\n return new Set(compiled.map((result) => result.skillName));\n }\n\n private async compileAgents(\n projectRoot: string,\n agentsDir: string,\n outputDir: string,\n ): Promise<void> {\n const resolvedAgentsDir = path.resolve(projectRoot, agentsDir);\n\n this.log(\"\");\n this.log(\"Compiling agent plugins\");\n this.log(` Agents directory: ${resolvedAgentsDir}`);\n this.log(\"\");\n\n this.log(\"Finding and compiling all agents...\");\n\n const agentResults = await compileAllAgentPlugins(resolvedAgentsDir, outputDir);\n\n this.log(`Compiled ${plural(agentResults.length, \"agent plugin\")}`);\n printAgentCompilationSummary(agentResults);\n }\n\n /** Prunes skill plugins only; agent plugins and non-plugin directories are left alone. */\n private async pruneStaleSkillPlugins(\n outputDir: string,\n expectedSkillPlugins: ReadonlySet<string>,\n ): Promise<void> {\n const dirNames = await listDirectories(outputDir);\n\n for (const dirName of dirNames) {\n if (expectedSkillPlugins.has(dirName)) continue;\n\n const pluginDir = path.join(outputDir, dirName);\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) continue;\n if (manifest.agents !== undefined) continue;\n\n await remove(pluginDir);\n this.log(` Pruned stale plugin: ${dirName}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/commands/compile.js
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
unofferablePlacementsFound
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ZBI6GFJD.js";
|
|
5
5
|
import {
|
|
6
6
|
hostCompileNotices
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-U672FZVC.js";
|
|
8
8
|
import {
|
|
9
9
|
detectBothInstallations,
|
|
10
10
|
reconcileTypesFromDisk
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-CKBWEWHZ.js";
|
|
12
12
|
import {
|
|
13
13
|
compileAgents,
|
|
14
14
|
discoverInstalledSkills
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-XMQIWPIR.js";
|
|
16
16
|
import {
|
|
17
17
|
loadAgentDefs
|
|
18
|
-
} from "../chunk-
|
|
19
|
-
import "../chunk-
|
|
20
|
-
import "../chunk-
|
|
18
|
+
} from "../chunk-JNRACLNS.js";
|
|
19
|
+
import "../chunk-EC3JXT23.js";
|
|
20
|
+
import "../chunk-MQZNDK5F.js";
|
|
21
21
|
import {
|
|
22
22
|
BaseCommand,
|
|
23
23
|
EXIT_CODES,
|
|
24
24
|
providerFlag,
|
|
25
25
|
providerNamedBy,
|
|
26
26
|
refuseAnAmbiguousInstallation
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-JTMSFBCA.js";
|
|
28
|
+
import {
|
|
29
|
+
namedByActiveEntries
|
|
30
|
+
} from "../chunk-FACDJH6O.js";
|
|
28
31
|
import {
|
|
29
32
|
ConfigLoadError,
|
|
30
33
|
ERROR_MESSAGES,
|
|
@@ -47,10 +50,10 @@ import {
|
|
|
47
50
|
skillMetadataUnusableDetail,
|
|
48
51
|
skillMetadataUnusableError,
|
|
49
52
|
verbose
|
|
50
|
-
} from "../chunk-
|
|
53
|
+
} from "../chunk-ENET4IF6.js";
|
|
51
54
|
import {
|
|
52
55
|
plural
|
|
53
|
-
} from "../chunk-
|
|
56
|
+
} from "../chunk-UE4Z3YMB.js";
|
|
54
57
|
import {
|
|
55
58
|
STANDARD_FILES,
|
|
56
59
|
effectivelyExcludedSkillIds,
|
|
@@ -202,8 +205,9 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
202
205
|
async warnScopeDroppedStackPairs(projectDir) {
|
|
203
206
|
const loaded = await loadProjectConfig(projectDir);
|
|
204
207
|
if (!loaded?.config.stack) return;
|
|
208
|
+
const namedBy = namedByActiveEntries(loaded.config.skills);
|
|
205
209
|
for (const [skillId, agentNames] of findScopeDroppedStackPairs(loaded.config)) {
|
|
206
|
-
this.warn(scopeBlockedStackAssignment(agentNames, skillId));
|
|
210
|
+
this.warn(scopeBlockedStackAssignment(agentNames, skillId, namedBy));
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
/** Points at global-scope agents so "No agents to recompile" doesn't read as a silent no-op. */
|