agentinit 1.16.2 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +49 -310
- package/dist/cli.js +448 -87
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +131 -8
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +128 -18
- package/dist/commands/skills.js.map +1 -1
- package/dist/core/pluginManager.d.ts +19 -3
- package/dist/core/pluginManager.d.ts.map +1 -1
- package/dist/core/pluginManager.js +17 -2
- package/dist/core/pluginManager.js.map +1 -1
- package/dist/core/skillsManager.d.ts +22 -0
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +137 -8
- package/dist/core/skillsManager.js.map +1 -1
- package/dist/types/skills.d.ts +3 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/skills.js +2 -1
- package/dist/types/skills.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16945,6 +16945,13 @@ var init_marketplaceRegistry = __esm(() => {
|
|
|
16945
16945
|
CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
|
|
16946
16946
|
});
|
|
16947
16947
|
|
|
16948
|
+
// dist/types/skills.js
|
|
16949
|
+
var SHARED_SKILLS_TARGET_ID, SHARED_SKILLS_TARGET_NAME;
|
|
16950
|
+
var init_skills = __esm(() => {
|
|
16951
|
+
SHARED_SKILLS_TARGET_ID = "agents";
|
|
16952
|
+
SHARED_SKILLS_TARGET_NAME = "AGENTS.md ecosystem";
|
|
16953
|
+
});
|
|
16954
|
+
|
|
16948
16955
|
// dist/core/mcpFilter.js
|
|
16949
16956
|
class MCPFilter {
|
|
16950
16957
|
static filterForAgent(agent, servers) {
|
|
@@ -17048,6 +17055,11 @@ __export(exports_pluginManager, {
|
|
|
17048
17055
|
return PluginManager;
|
|
17049
17056
|
}
|
|
17050
17057
|
},
|
|
17058
|
+
MultipleBundlePluginsError: () => {
|
|
17059
|
+
{
|
|
17060
|
+
return MultipleBundlePluginsError;
|
|
17061
|
+
}
|
|
17062
|
+
},
|
|
17051
17063
|
MarketplacePluginNotFoundError: () => {
|
|
17052
17064
|
{
|
|
17053
17065
|
return MarketplacePluginNotFoundError;
|
|
@@ -17058,6 +17070,16 @@ import {resolve as resolve7, join as join4, basename as basename2, relative as r
|
|
|
17058
17070
|
import {promises as fs22} from "fs";
|
|
17059
17071
|
import {homedir as homedir4} from "os";
|
|
17060
17072
|
|
|
17073
|
+
class MultipleBundlePluginsError extends Error {
|
|
17074
|
+
entries;
|
|
17075
|
+
constructor(pluginDir, entries) {
|
|
17076
|
+
const names = entries.map((e) => e.name).join(", ");
|
|
17077
|
+
super(`Repository "${pluginDir}" is a Claude marketplace bundle with multiple plugins. Select one of: ${names}.`);
|
|
17078
|
+
this.name = "MultipleBundlePluginsError";
|
|
17079
|
+
this.entries = entries;
|
|
17080
|
+
}
|
|
17081
|
+
}
|
|
17082
|
+
|
|
17061
17083
|
class MarketplacePluginNotFoundError extends Error {
|
|
17062
17084
|
pluginName;
|
|
17063
17085
|
marketplaceId;
|
|
@@ -17195,7 +17217,7 @@ class PluginManager {
|
|
|
17195
17217
|
const candidates = new Set([source.pluginName, source.repo].filter((value) => !!value).flatMap((value) => [value, basename2(value)]));
|
|
17196
17218
|
const matched = entries.find((entry) => candidates.has(entry.name) || candidates.has(basename2(entry.source)));
|
|
17197
17219
|
if (!matched) {
|
|
17198
|
-
throw new
|
|
17220
|
+
throw new MultipleBundlePluginsError(pluginDir, entries);
|
|
17199
17221
|
}
|
|
17200
17222
|
selectedEntry = matched;
|
|
17201
17223
|
}
|
|
@@ -17272,6 +17294,9 @@ class PluginManager {
|
|
|
17272
17294
|
throw new Error(`Local path not found: ${pluginDir}`);
|
|
17273
17295
|
}
|
|
17274
17296
|
}
|
|
17297
|
+
if (options2.pluginName) {
|
|
17298
|
+
effectiveSource = { ...effectiveSource, pluginName: options2.pluginName };
|
|
17299
|
+
}
|
|
17275
17300
|
return {
|
|
17276
17301
|
plugin: await this.loadPluginFromDirectory(pluginDir, effectiveSource, resolutionWarnings),
|
|
17277
17302
|
effectiveSource,
|
|
@@ -18111,7 +18136,10 @@ ${body.trim()}
|
|
|
18111
18136
|
};
|
|
18112
18137
|
}
|
|
18113
18138
|
async installPlugin(source, projectPath, options2 = {}) {
|
|
18114
|
-
const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, {
|
|
18139
|
+
const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, {
|
|
18140
|
+
from: options2.from,
|
|
18141
|
+
...options2.pluginName ? { pluginName: options2.pluginName } : {}
|
|
18142
|
+
});
|
|
18115
18143
|
try {
|
|
18116
18144
|
const plugin = context.plugin;
|
|
18117
18145
|
if (options2.list) {
|
|
@@ -18526,6 +18554,7 @@ import {promisify} from "util";
|
|
|
18526
18554
|
|
|
18527
18555
|
class SkillsManager {
|
|
18528
18556
|
agentManager;
|
|
18557
|
+
preparedSourceContexts = new Map;
|
|
18529
18558
|
constructor(agentManager3) {
|
|
18530
18559
|
this.agentManager = agentManager3 || new AgentManager;
|
|
18531
18560
|
}
|
|
@@ -18668,7 +18697,7 @@ class SkillsManager {
|
|
|
18668
18697
|
}
|
|
18669
18698
|
}
|
|
18670
18699
|
async discoverSkills(repoPath) {
|
|
18671
|
-
const
|
|
18700
|
+
const skills2 = [];
|
|
18672
18701
|
const seen = new Set;
|
|
18673
18702
|
for (const searchDir of SKILL_SEARCH_DIRS) {
|
|
18674
18703
|
const fullDir = resolve8(repoPath, searchDir);
|
|
@@ -18679,7 +18708,7 @@ class SkillsManager {
|
|
|
18679
18708
|
const parsed = await this.parseSkillMd(directSkillMd);
|
|
18680
18709
|
if (parsed && !seen.has(parsed.name)) {
|
|
18681
18710
|
seen.add(parsed.name);
|
|
18682
|
-
|
|
18711
|
+
skills2.push({ ...parsed, path: resolve8(fullDir) });
|
|
18683
18712
|
}
|
|
18684
18713
|
}
|
|
18685
18714
|
const directSkillMdLower = join5(fullDir, "skill.md");
|
|
@@ -18687,7 +18716,7 @@ class SkillsManager {
|
|
|
18687
18716
|
const parsed = await this.parseSkillMd(directSkillMdLower);
|
|
18688
18717
|
if (parsed && !seen.has(parsed.name)) {
|
|
18689
18718
|
seen.add(parsed.name);
|
|
18690
|
-
|
|
18719
|
+
skills2.push({ ...parsed, path: resolve8(fullDir) });
|
|
18691
18720
|
}
|
|
18692
18721
|
}
|
|
18693
18722
|
if (!await isDirectory(fullDir))
|
|
@@ -18705,11 +18734,11 @@ class SkillsManager {
|
|
|
18705
18734
|
const parsed = await this.parseSkillMd(skillFile);
|
|
18706
18735
|
if (parsed && !seen.has(parsed.name)) {
|
|
18707
18736
|
seen.add(parsed.name);
|
|
18708
|
-
|
|
18737
|
+
skills2.push({ ...parsed, path: entryPath });
|
|
18709
18738
|
}
|
|
18710
18739
|
}
|
|
18711
18740
|
}
|
|
18712
|
-
return
|
|
18741
|
+
return skills2;
|
|
18713
18742
|
}
|
|
18714
18743
|
async cloneRepo(url) {
|
|
18715
18744
|
const tempDir = await fs24.mkdtemp(join5(tmpdir(), "agentinit-skills-"));
|
|
@@ -18740,12 +18769,13 @@ class SkillsManager {
|
|
|
18740
18769
|
const marketplaceHints = marketplaces.length > 0 ? ` If you meant a marketplace skill, use "${marketplaces[0]}/${normalizedSource}" or "--from ${marketplaces[0]}".` : "";
|
|
18741
18770
|
return new Error(`Local path not found: ${resolvedPath}. If you meant a local path, prefix it with "./".${marketplaceHints}`);
|
|
18742
18771
|
}
|
|
18743
|
-
async discoverMarketplaceSkills(source, projectPath) {
|
|
18772
|
+
async discoverMarketplaceSkills(source, projectPath, pluginName) {
|
|
18744
18773
|
const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_pluginManager(), exports_pluginManager));
|
|
18745
18774
|
const pluginManager = new PluginManager2(this.agentManager);
|
|
18746
18775
|
const result = await pluginManager.installPlugin(source.pluginName || this.getMarketplaceSourceId(source), projectPath, {
|
|
18747
18776
|
from: source.marketplace,
|
|
18748
|
-
list: true
|
|
18777
|
+
list: true,
|
|
18778
|
+
...pluginName ? { pluginName } : {}
|
|
18749
18779
|
});
|
|
18750
18780
|
const warnings = [...result.warnings];
|
|
18751
18781
|
if (result.plugin.mcpServers.length > 0) {
|
|
@@ -18809,6 +18839,9 @@ class SkillsManager {
|
|
|
18809
18839
|
async loadDiscoveredSkillsContext(source, projectPath, options2 = {}) {
|
|
18810
18840
|
const request = this.resolveSourceRequest(source, options2);
|
|
18811
18841
|
const resolved = request.source;
|
|
18842
|
+
if (options2.pluginName && resolved.type !== "marketplace") {
|
|
18843
|
+
resolved.pluginName = options2.pluginName;
|
|
18844
|
+
}
|
|
18812
18845
|
let tempDir = null;
|
|
18813
18846
|
const cleanup = async () => {
|
|
18814
18847
|
await this.cleanupTempDir(tempDir);
|
|
@@ -18816,7 +18849,7 @@ class SkillsManager {
|
|
|
18816
18849
|
};
|
|
18817
18850
|
try {
|
|
18818
18851
|
if (resolved.type === "marketplace") {
|
|
18819
|
-
const discovered = await this.discoverMarketplaceSkills(resolved, projectPath);
|
|
18852
|
+
const discovered = await this.discoverMarketplaceSkills(resolved, projectPath, options2.pluginName);
|
|
18820
18853
|
return {
|
|
18821
18854
|
...discovered,
|
|
18822
18855
|
cleanup
|
|
@@ -18836,24 +18869,24 @@ class SkillsManager {
|
|
|
18836
18869
|
}
|
|
18837
18870
|
}
|
|
18838
18871
|
const discoveryRoot = await this.resolveDiscoveryRoot(repoPath, resolved, source);
|
|
18839
|
-
let
|
|
18872
|
+
let skills2 = await this.discoverSkills(discoveryRoot);
|
|
18840
18873
|
let pluginWarnings = [];
|
|
18841
|
-
if (
|
|
18874
|
+
if (skills2.length === 0) {
|
|
18842
18875
|
const pluginBackedSkills = await this.discoverPortablePluginSkills(discoveryRoot, source, resolved, projectPath);
|
|
18843
18876
|
if (pluginBackedSkills) {
|
|
18844
|
-
|
|
18877
|
+
skills2 = pluginBackedSkills.skills;
|
|
18845
18878
|
pluginWarnings = pluginBackedSkills.warnings;
|
|
18846
18879
|
}
|
|
18847
18880
|
}
|
|
18848
18881
|
if (request.implicitSkills.length > 0) {
|
|
18849
18882
|
const names = new Set(request.implicitSkills.map((skill) => skill.toLowerCase()));
|
|
18850
|
-
|
|
18883
|
+
skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()));
|
|
18851
18884
|
}
|
|
18852
18885
|
const warnings = [
|
|
18853
18886
|
...pluginWarnings,
|
|
18854
18887
|
...request.implicitSkills.length > 0 ? [`Resolved "${source}" from the default skills catalog ${DEFAULT_SKILLS_CATALOG.owner}/${DEFAULT_SKILLS_CATALOG.repo}. Use "./${source}" for a local path.`] : []
|
|
18855
18888
|
];
|
|
18856
|
-
return { skills, warnings, cleanup };
|
|
18889
|
+
return { skills: skills2, warnings, cleanup };
|
|
18857
18890
|
} catch (error) {
|
|
18858
18891
|
await cleanup();
|
|
18859
18892
|
throw error;
|
|
@@ -18870,6 +18903,37 @@ class SkillsManager {
|
|
|
18870
18903
|
await context.cleanup();
|
|
18871
18904
|
}
|
|
18872
18905
|
}
|
|
18906
|
+
getPreparedSourceKey(source, projectPath, from) {
|
|
18907
|
+
return `${projectPath}\n${from || ""}\n${source}`;
|
|
18908
|
+
}
|
|
18909
|
+
async storePreparedSourceContext(source, projectPath, from, context) {
|
|
18910
|
+
const key = this.getPreparedSourceKey(source, projectPath, from);
|
|
18911
|
+
const existing = this.preparedSourceContexts.get(key);
|
|
18912
|
+
this.preparedSourceContexts.set(key, context);
|
|
18913
|
+
if (existing && existing !== context) {
|
|
18914
|
+
await existing.cleanup();
|
|
18915
|
+
}
|
|
18916
|
+
}
|
|
18917
|
+
takePreparedSourceContext(source, projectPath, from) {
|
|
18918
|
+
const key = this.getPreparedSourceKey(source, projectPath, from);
|
|
18919
|
+
const existing = this.preparedSourceContexts.get(key) || null;
|
|
18920
|
+
if (existing) {
|
|
18921
|
+
this.preparedSourceContexts.delete(key);
|
|
18922
|
+
}
|
|
18923
|
+
return existing;
|
|
18924
|
+
}
|
|
18925
|
+
async prepareSource(source, projectPath, options2 = {}) {
|
|
18926
|
+
const context = await this.loadDiscoveredSkillsContext(source, projectPath, options2);
|
|
18927
|
+
await this.storePreparedSourceContext(source, projectPath, options2.from, context);
|
|
18928
|
+
return {
|
|
18929
|
+
skills: context.skills,
|
|
18930
|
+
warnings: context.warnings
|
|
18931
|
+
};
|
|
18932
|
+
}
|
|
18933
|
+
async discardPreparedSource(source, projectPath, options2 = {}) {
|
|
18934
|
+
const context = this.takePreparedSourceContext(source, projectPath, options2.from);
|
|
18935
|
+
await context?.cleanup();
|
|
18936
|
+
}
|
|
18873
18937
|
async getTargetAgents(projectPath, options2) {
|
|
18874
18938
|
if (options2.agents && options2.agents.length > 0) {
|
|
18875
18939
|
const agents = [];
|
|
@@ -18997,6 +19061,27 @@ class SkillsManager {
|
|
|
18997
19061
|
}
|
|
18998
19062
|
return plan;
|
|
18999
19063
|
}
|
|
19064
|
+
async installSkillToCanonicalStore(skillPath, skillName, projectPath, options2 = {}) {
|
|
19065
|
+
const plan = this.getCanonicalInstallPlan(skillName, projectPath, options2);
|
|
19066
|
+
await this.cleanAndCreateDirectory(plan.path);
|
|
19067
|
+
await this.copyDir(skillPath, plan.path);
|
|
19068
|
+
return plan;
|
|
19069
|
+
}
|
|
19070
|
+
async installSkillFromContentToCanonicalStore(skillName, skillContent, projectPath, options2 = {}) {
|
|
19071
|
+
const plan = this.getCanonicalInstallPlan(skillName, projectPath, options2);
|
|
19072
|
+
await this.cleanAndCreateDirectory(plan.path);
|
|
19073
|
+
await fs24.writeFile(join5(plan.path, "SKILL.md"), skillContent, "utf8");
|
|
19074
|
+
return plan;
|
|
19075
|
+
}
|
|
19076
|
+
getCanonicalInstallPlan(skillName, projectPath, options2 = {}) {
|
|
19077
|
+
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
19078
|
+
const canonicalPath = this.resolveInstallPath(this.getCanonicalSkillsDir(projectPath, options2.global ?? false), normalizedSkillName);
|
|
19079
|
+
return {
|
|
19080
|
+
path: canonicalPath,
|
|
19081
|
+
canonicalPath,
|
|
19082
|
+
mode: "symlink"
|
|
19083
|
+
};
|
|
19084
|
+
}
|
|
19000
19085
|
normalizeSkillName(skillName) {
|
|
19001
19086
|
const normalized = skillName.trim();
|
|
19002
19087
|
if (!normalized) {
|
|
@@ -19032,45 +19117,60 @@ class SkillsManager {
|
|
|
19032
19117
|
await fs24.cp(src, dest, { recursive: true, dereference: true });
|
|
19033
19118
|
}
|
|
19034
19119
|
async addFromSource(source, projectPath, options2 = {}) {
|
|
19035
|
-
const context = await this.loadDiscoveredSkillsContext(source, projectPath, {
|
|
19036
|
-
...options2.from !== undefined ? { from: options2.from } : {}
|
|
19120
|
+
const context = this.takePreparedSourceContext(source, projectPath, options2.from) || await this.loadDiscoveredSkillsContext(source, projectPath, {
|
|
19121
|
+
...options2.from !== undefined ? { from: options2.from } : {},
|
|
19122
|
+
...options2.pluginName !== undefined ? { pluginName: options2.pluginName } : {}
|
|
19037
19123
|
});
|
|
19038
19124
|
try {
|
|
19039
|
-
let
|
|
19040
|
-
if (
|
|
19125
|
+
let skills2 = context.skills;
|
|
19126
|
+
if (skills2.length === 0) {
|
|
19041
19127
|
return { installed: [], skipped: [], warnings: context.warnings };
|
|
19042
19128
|
}
|
|
19043
19129
|
if (options2.skills && options2.skills.length > 0) {
|
|
19044
19130
|
const names = new Set(options2.skills.map((skill) => skill.toLowerCase()));
|
|
19045
|
-
|
|
19131
|
+
skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()));
|
|
19046
19132
|
}
|
|
19133
|
+
const installToSharedStore = options2.agents?.includes(SHARED_SKILLS_TARGET_ID) ?? false;
|
|
19047
19134
|
const agents = await this.getTargetAgents(projectPath, options2);
|
|
19048
|
-
if (agents.length === 0) {
|
|
19135
|
+
if (agents.length === 0 && !installToSharedStore) {
|
|
19049
19136
|
return {
|
|
19050
19137
|
installed: [],
|
|
19051
|
-
skipped:
|
|
19138
|
+
skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" })),
|
|
19052
19139
|
warnings: context.warnings
|
|
19053
19140
|
};
|
|
19054
19141
|
}
|
|
19055
19142
|
const result = { installed: [], skipped: [], warnings: context.warnings };
|
|
19056
19143
|
const installableAgents = [];
|
|
19144
|
+
if (installToSharedStore) {
|
|
19145
|
+
for (const skill of skills2) {
|
|
19146
|
+
try {
|
|
19147
|
+
const installOptions = {
|
|
19148
|
+
...options2.global !== undefined ? { global: options2.global } : {}
|
|
19149
|
+
};
|
|
19150
|
+
const installed = skill.generatedContent ? await this.installSkillFromContentToCanonicalStore(skill.name, skill.generatedContent, projectPath, installOptions) : await this.installSkillToCanonicalStore(skill.path, skill.name, projectPath, installOptions);
|
|
19151
|
+
result.installed.push({ skill, agent: SHARED_SKILLS_TARGET_ID, ...installed });
|
|
19152
|
+
} catch (error) {
|
|
19153
|
+
result.skipped.push({ skill, reason: error.message });
|
|
19154
|
+
}
|
|
19155
|
+
}
|
|
19156
|
+
}
|
|
19057
19157
|
for (const agent of agents) {
|
|
19058
19158
|
if (!agent.supportsSkills()) {
|
|
19059
|
-
for (const skill of
|
|
19159
|
+
for (const skill of skills2) {
|
|
19060
19160
|
result.skipped.push({ skill, reason: `${agent.name} does not support skills` });
|
|
19061
19161
|
}
|
|
19062
19162
|
continue;
|
|
19063
19163
|
}
|
|
19064
19164
|
const skillsDir = agent.getSkillsDir(projectPath, options2.global);
|
|
19065
19165
|
if (!skillsDir) {
|
|
19066
|
-
for (const skill of
|
|
19166
|
+
for (const skill of skills2) {
|
|
19067
19167
|
result.skipped.push({ skill, reason: `No skills directory for ${agent.name}` });
|
|
19068
19168
|
}
|
|
19069
19169
|
continue;
|
|
19070
19170
|
}
|
|
19071
19171
|
installableAgents.push(agent);
|
|
19072
19172
|
}
|
|
19073
|
-
for (const skill of
|
|
19173
|
+
for (const skill of skills2) {
|
|
19074
19174
|
for (const agent of installableAgents) {
|
|
19075
19175
|
try {
|
|
19076
19176
|
const installOptions = {
|
|
@@ -19149,6 +19249,43 @@ class SkillsManager {
|
|
|
19149
19249
|
}
|
|
19150
19250
|
}
|
|
19151
19251
|
}
|
|
19252
|
+
const includeSharedTarget = !options2.agents || options2.agents.includes(SHARED_SKILLS_TARGET_ID);
|
|
19253
|
+
if (includeSharedTarget) {
|
|
19254
|
+
const scopes = options2.global ? ["global"] : ["project", "global"];
|
|
19255
|
+
const referencedCanonicalPaths = new Set(installed.map((entry) => entry.canonicalPath).filter((value) => !!value).map((value) => resolve8(value)));
|
|
19256
|
+
for (const scope of scopes) {
|
|
19257
|
+
const canonicalDir = this.getCanonicalSkillsDir(projectPath, scope === "global");
|
|
19258
|
+
if (!await fileExists(canonicalDir))
|
|
19259
|
+
continue;
|
|
19260
|
+
const entries = await listFiles(canonicalDir);
|
|
19261
|
+
for (const entry of entries) {
|
|
19262
|
+
const entryPath = join5(canonicalDir, entry);
|
|
19263
|
+
if (!await isDirectory(entryPath))
|
|
19264
|
+
continue;
|
|
19265
|
+
const resolvedEntryPath = resolve8(entryPath);
|
|
19266
|
+
if (referencedCanonicalPaths.has(resolvedEntryPath))
|
|
19267
|
+
continue;
|
|
19268
|
+
const skillMdPath = join5(entryPath, "SKILL.md");
|
|
19269
|
+
const skillMdPathLower = join5(entryPath, "skill.md");
|
|
19270
|
+
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
19271
|
+
if (!skillFile)
|
|
19272
|
+
continue;
|
|
19273
|
+
const parsed = await this.parseSkillMd(skillFile);
|
|
19274
|
+
if (!parsed)
|
|
19275
|
+
continue;
|
|
19276
|
+
installed.push({
|
|
19277
|
+
name: parsed.name,
|
|
19278
|
+
description: parsed.description,
|
|
19279
|
+
path: entryPath,
|
|
19280
|
+
canonicalPath: resolvedEntryPath,
|
|
19281
|
+
agent: SHARED_SKILLS_TARGET_ID,
|
|
19282
|
+
scope,
|
|
19283
|
+
isSymlink: false,
|
|
19284
|
+
mode: "symlink"
|
|
19285
|
+
});
|
|
19286
|
+
}
|
|
19287
|
+
}
|
|
19288
|
+
}
|
|
19152
19289
|
return installed;
|
|
19153
19290
|
}
|
|
19154
19291
|
async remove(skillNames, projectPath, options2 = {}) {
|
|
@@ -19159,11 +19296,19 @@ class SkillsManager {
|
|
|
19159
19296
|
const skipped = [];
|
|
19160
19297
|
const namesLower = new Set(skillNames.map((n) => n.toLowerCase()));
|
|
19161
19298
|
const targetAgentIds = new Set(agents.map((agent) => agent.id));
|
|
19299
|
+
if (options2.agents?.includes(SHARED_SKILLS_TARGET_ID) || options2.agents === undefined) {
|
|
19300
|
+
targetAgentIds.add(SHARED_SKILLS_TARGET_ID);
|
|
19301
|
+
}
|
|
19162
19302
|
const installed = await this.listInstalledForAgents(projectPath, allAgents, options2);
|
|
19163
|
-
const
|
|
19303
|
+
const sharedTargetInstalled = options2.agents?.includes(SHARED_SKILLS_TARGET_ID) ? await this.listInstalledForAgents(projectPath, [], options2) : [];
|
|
19304
|
+
const installedEntries = Array.from(new Map([...installed, ...sharedTargetInstalled].map((entry) => [
|
|
19305
|
+
`${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`,
|
|
19306
|
+
entry
|
|
19307
|
+
])).values());
|
|
19308
|
+
const scopedInstalled = installedEntries.filter((entry) => options2.global ? entry.scope === "global" : entry.scope === "project");
|
|
19164
19309
|
const targetedEntries = scopedInstalled.filter((entry) => targetAgentIds.has(entry.agent) && namesLower.has(entry.name.toLowerCase()));
|
|
19165
19310
|
const targetedKeys = new Set(targetedEntries.map((entry) => `${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`));
|
|
19166
|
-
const remainingEntries =
|
|
19311
|
+
const remainingEntries = installedEntries.filter((entry) => !targetedKeys.has(`${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`));
|
|
19167
19312
|
const removedPaths = new Set;
|
|
19168
19313
|
const removedCanonicalPaths = new Set;
|
|
19169
19314
|
for (const entry of targetedEntries) {
|
|
@@ -19223,6 +19368,7 @@ var init_skillsManager = __esm(() => {
|
|
|
19223
19368
|
init_fs();
|
|
19224
19369
|
init_agentManager();
|
|
19225
19370
|
init_marketplaceRegistry();
|
|
19371
|
+
init_skills();
|
|
19226
19372
|
execFileAsync = promisify(execFile);
|
|
19227
19373
|
DEFAULT_SKILLS_CATALOG = {
|
|
19228
19374
|
owner: "vercel-labs",
|
|
@@ -39992,7 +40138,7 @@ init_fs();
|
|
|
39992
40138
|
import {dirname as dirname8, join as join9} from "path";
|
|
39993
40139
|
async function discoverProjectSkills(projectPath, skillsManager4) {
|
|
39994
40140
|
const sources = [];
|
|
39995
|
-
const
|
|
40141
|
+
const skills2 = new Map;
|
|
39996
40142
|
for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
|
|
39997
40143
|
const absoluteSourceDir = join9(projectPath, sourceDir);
|
|
39998
40144
|
if (!await fileExists(absoluteSourceDir)) {
|
|
@@ -40002,23 +40148,23 @@ async function discoverProjectSkills(projectPath, skillsManager4) {
|
|
|
40002
40148
|
const discovered = await skillsManager4.discoverSkills(absoluteSourceDir);
|
|
40003
40149
|
for (const skill of discovered) {
|
|
40004
40150
|
const key = skill.name.toLowerCase();
|
|
40005
|
-
if (!
|
|
40006
|
-
|
|
40151
|
+
if (!skills2.has(key)) {
|
|
40152
|
+
skills2.set(key, skill);
|
|
40007
40153
|
}
|
|
40008
40154
|
}
|
|
40009
40155
|
}
|
|
40010
40156
|
return {
|
|
40011
40157
|
sources,
|
|
40012
|
-
skills: [...
|
|
40158
|
+
skills: [...skills2.values()]
|
|
40013
40159
|
};
|
|
40014
40160
|
}
|
|
40015
40161
|
async function applyProjectSkills(projectPath, targetAgentIds, managedState2, options2 = {}) {
|
|
40016
40162
|
const agentManager6 = new AgentManager;
|
|
40017
40163
|
const skillsManager4 = new SkillsManager(agentManager6);
|
|
40018
|
-
const { sources, skills } = await discoverProjectSkills(projectPath, skillsManager4);
|
|
40164
|
+
const { sources, skills: skills2 } = await discoverProjectSkills(projectPath, skillsManager4);
|
|
40019
40165
|
const installed = [];
|
|
40020
40166
|
const skipped = [];
|
|
40021
|
-
if (
|
|
40167
|
+
if (skills2.length === 0) {
|
|
40022
40168
|
return {
|
|
40023
40169
|
discovered: 0,
|
|
40024
40170
|
sources,
|
|
@@ -40029,22 +40175,22 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
|
|
|
40029
40175
|
const targetAgents = targetAgentIds.map((id) => agentManager6.getAgentById(id)).filter((agent) => !!agent);
|
|
40030
40176
|
if (targetAgents.length === 0) {
|
|
40031
40177
|
return {
|
|
40032
|
-
discovered:
|
|
40178
|
+
discovered: skills2.length,
|
|
40033
40179
|
sources,
|
|
40034
40180
|
installed,
|
|
40035
|
-
skipped:
|
|
40181
|
+
skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" }))
|
|
40036
40182
|
};
|
|
40037
40183
|
}
|
|
40038
40184
|
for (const agent of targetAgents) {
|
|
40039
40185
|
if (!agent.supportsSkills()) {
|
|
40040
|
-
for (const skill of
|
|
40186
|
+
for (const skill of skills2) {
|
|
40041
40187
|
skipped.push({ skill, reason: `${agent.name} does not support skills` });
|
|
40042
40188
|
}
|
|
40043
40189
|
continue;
|
|
40044
40190
|
}
|
|
40045
40191
|
const skillsDir = agent.getSkillsDir(projectPath, false);
|
|
40046
40192
|
if (!skillsDir) {
|
|
40047
|
-
for (const skill of
|
|
40193
|
+
for (const skill of skills2) {
|
|
40048
40194
|
skipped.push({ skill, reason: `No skills directory for ${agent.name}` });
|
|
40049
40195
|
}
|
|
40050
40196
|
continue;
|
|
@@ -40055,7 +40201,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
|
|
|
40055
40201
|
continue;
|
|
40056
40202
|
if (!agent.getSkillsDir(projectPath, false))
|
|
40057
40203
|
continue;
|
|
40058
|
-
for (const skill of
|
|
40204
|
+
for (const skill of skills2) {
|
|
40059
40205
|
try {
|
|
40060
40206
|
const installOptions = {
|
|
40061
40207
|
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
@@ -40079,7 +40225,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
|
|
|
40079
40225
|
}
|
|
40080
40226
|
}
|
|
40081
40227
|
return {
|
|
40082
|
-
discovered:
|
|
40228
|
+
discovered: skills2.length,
|
|
40083
40229
|
sources,
|
|
40084
40230
|
installed,
|
|
40085
40231
|
skipped
|
|
@@ -41079,12 +41225,14 @@ var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
|
41079
41225
|
import {homedir as homedir6} from "os";
|
|
41080
41226
|
import {relative as relative7, resolve as resolve12} from "path";
|
|
41081
41227
|
init_skillsManager();
|
|
41228
|
+
init_pluginManager();
|
|
41082
41229
|
init_marketplaceRegistry();
|
|
41083
41230
|
init_agentManager();
|
|
41231
|
+
init_skills();
|
|
41084
41232
|
function registerSkillsCommand(program2) {
|
|
41085
41233
|
const marketplaceHelp = getMarketplaceIds().join(", ");
|
|
41086
|
-
const
|
|
41087
|
-
|
|
41234
|
+
const skills3 = program2.command("skills").description("Manage agent skills");
|
|
41235
|
+
skills3.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts and auto-detect project-configured agents only").action(async (source, options2) => {
|
|
41088
41236
|
logger.titleBox("AgentInit Skills");
|
|
41089
41237
|
const agentManager9 = new AgentManager;
|
|
41090
41238
|
const skillsManager5 = new SkillsManager(agentManager9);
|
|
@@ -41097,11 +41245,64 @@ function registerSkillsCommand(program2) {
|
|
|
41097
41245
|
spinner2.stop();
|
|
41098
41246
|
displayDiscoveredSkills(result.skills, result.warnings);
|
|
41099
41247
|
} catch (error) {
|
|
41100
|
-
|
|
41101
|
-
|
|
41248
|
+
if (error instanceof MultipleBundlePluginsError) {
|
|
41249
|
+
spinner2.stop();
|
|
41250
|
+
const selected = await selectBundlePlugin(error, "list");
|
|
41251
|
+
if (!selected) {
|
|
41252
|
+
return;
|
|
41253
|
+
}
|
|
41254
|
+
const retrySpinner = ora("Discovering skills...").start();
|
|
41255
|
+
try {
|
|
41256
|
+
const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
|
|
41257
|
+
from: options2.from,
|
|
41258
|
+
pluginName: selected
|
|
41259
|
+
});
|
|
41260
|
+
retrySpinner.stop();
|
|
41261
|
+
displayDiscoveredSkills(result.skills, result.warnings);
|
|
41262
|
+
} catch (retryError) {
|
|
41263
|
+
retrySpinner.fail("Failed to discover skills");
|
|
41264
|
+
logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
|
|
41265
|
+
}
|
|
41266
|
+
} else {
|
|
41267
|
+
spinner2.fail("Failed to discover skills");
|
|
41268
|
+
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
41269
|
+
}
|
|
41102
41270
|
}
|
|
41103
41271
|
return;
|
|
41104
41272
|
}
|
|
41273
|
+
const verifySpinner = ora("Verifying skill source...").start();
|
|
41274
|
+
let selectedPluginName;
|
|
41275
|
+
try {
|
|
41276
|
+
await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41277
|
+
from: options2.from
|
|
41278
|
+
});
|
|
41279
|
+
verifySpinner.stop();
|
|
41280
|
+
} catch (error) {
|
|
41281
|
+
if (error instanceof MultipleBundlePluginsError && !options2.yes) {
|
|
41282
|
+
verifySpinner.stop();
|
|
41283
|
+
const selected = await selectBundlePlugin(error, "install");
|
|
41284
|
+
if (!selected) {
|
|
41285
|
+
return;
|
|
41286
|
+
}
|
|
41287
|
+
selectedPluginName = selected;
|
|
41288
|
+
const retrySpinner = ora("Verifying skill source...").start();
|
|
41289
|
+
try {
|
|
41290
|
+
await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41291
|
+
from: options2.from,
|
|
41292
|
+
pluginName: selectedPluginName
|
|
41293
|
+
});
|
|
41294
|
+
retrySpinner.stop();
|
|
41295
|
+
} catch (retryError) {
|
|
41296
|
+
retrySpinner.fail("Failed to verify skill source");
|
|
41297
|
+
logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
|
|
41298
|
+
return;
|
|
41299
|
+
}
|
|
41300
|
+
} else {
|
|
41301
|
+
verifySpinner.fail("Failed to verify skill source");
|
|
41302
|
+
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
41303
|
+
return;
|
|
41304
|
+
}
|
|
41305
|
+
}
|
|
41105
41306
|
let targetAgents = options2.agent;
|
|
41106
41307
|
let targetGlobal = options2.global;
|
|
41107
41308
|
if (!targetAgents && !options2.yes) {
|
|
@@ -41110,6 +41311,9 @@ function registerSkillsCommand(program2) {
|
|
|
41110
41311
|
global: options2.global
|
|
41111
41312
|
});
|
|
41112
41313
|
if (selection?.aborted) {
|
|
41314
|
+
await skillsManager5.discardPreparedSource(source, process.cwd(), {
|
|
41315
|
+
from: options2.from
|
|
41316
|
+
});
|
|
41113
41317
|
return;
|
|
41114
41318
|
}
|
|
41115
41319
|
if (selection?.agents && selection.agents.length > 0) {
|
|
@@ -41123,6 +41327,7 @@ function registerSkillsCommand(program2) {
|
|
|
41123
41327
|
...targetAgents !== undefined ? { agents: targetAgents } : {},
|
|
41124
41328
|
...options2.skill !== undefined ? { skills: options2.skill } : {},
|
|
41125
41329
|
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
41330
|
+
...selectedPluginName !== undefined ? { pluginName: selectedPluginName } : {},
|
|
41126
41331
|
...options2.yes !== undefined ? { yes: options2.yes } : {}
|
|
41127
41332
|
});
|
|
41128
41333
|
const spinner = ora("Installing skills...").start();
|
|
@@ -41134,7 +41339,7 @@ function registerSkillsCommand(program2) {
|
|
|
41134
41339
|
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
41135
41340
|
}
|
|
41136
41341
|
});
|
|
41137
|
-
|
|
41342
|
+
skills3.command("list").alias("ls").description("List installed skills").option("-g, --global", "List only global skills").option("-a, --agent <agents...>", "Filter by specific agent(s)").action(async (options2) => {
|
|
41138
41343
|
logger.titleBox("AgentInit Skills");
|
|
41139
41344
|
const agentManager9 = new AgentManager;
|
|
41140
41345
|
const skillsManager5 = new SkillsManager(agentManager9);
|
|
@@ -41163,7 +41368,7 @@ function registerSkillsCommand(program2) {
|
|
|
41163
41368
|
if (skill.mode === "symlink") {
|
|
41164
41369
|
existing.mode = "symlink";
|
|
41165
41370
|
}
|
|
41166
|
-
existing.agents.add(agentManager9
|
|
41371
|
+
existing.agents.add(formatSkillTargetName(agentManager9, skill.agent));
|
|
41167
41372
|
bySkill.set(key, existing);
|
|
41168
41373
|
}
|
|
41169
41374
|
for (const skill of bySkill.values()) {
|
|
@@ -41174,7 +41379,7 @@ function registerSkillsCommand(program2) {
|
|
|
41174
41379
|
logger.info(` Agents: ${[...skill.agents].join(", ")}`);
|
|
41175
41380
|
}
|
|
41176
41381
|
});
|
|
41177
|
-
|
|
41382
|
+
skills3.command("remove [names...]").alias("rm").description("Remove installed skills by name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Target specific agent(s)").option("-y, --yes", "Skip confirmation prompts").action(async (names, options2) => {
|
|
41178
41383
|
logger.titleBox("AgentInit Skills");
|
|
41179
41384
|
if (!names || names.length === 0) {
|
|
41180
41385
|
if (!options2.yes) {
|
|
@@ -41210,6 +41415,22 @@ function registerSkillsCommand(program2) {
|
|
|
41210
41415
|
}
|
|
41211
41416
|
});
|
|
41212
41417
|
}
|
|
41418
|
+
async function selectBundlePlugin(error, actionLabel) {
|
|
41419
|
+
const response = await import_prompts2.default({
|
|
41420
|
+
type: "select",
|
|
41421
|
+
name: "plugin",
|
|
41422
|
+
message: `This repository contains multiple plugins. Select one to ${actionLabel}:`,
|
|
41423
|
+
choices: error.entries.map((entry) => ({
|
|
41424
|
+
title: entry.name,
|
|
41425
|
+
value: entry.name
|
|
41426
|
+
}))
|
|
41427
|
+
});
|
|
41428
|
+
if (!response.plugin) {
|
|
41429
|
+
logger.info("Cancelled.");
|
|
41430
|
+
return null;
|
|
41431
|
+
}
|
|
41432
|
+
return response.plugin;
|
|
41433
|
+
}
|
|
41213
41434
|
async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
|
|
41214
41435
|
let installGlobal = !!options2.global;
|
|
41215
41436
|
if (!options2.global) {
|
|
@@ -41258,9 +41479,9 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
|
|
|
41258
41479
|
instructions: false,
|
|
41259
41480
|
min: 1,
|
|
41260
41481
|
choices: availableGroups.map((group) => ({
|
|
41261
|
-
title:
|
|
41482
|
+
title: formatSkillGroupTitle(group),
|
|
41262
41483
|
...group.description ? { description: group.description } : {},
|
|
41263
|
-
value: group.agents.map((agent) => agent.id),
|
|
41484
|
+
value: group.kind === "canonical-shared" ? [SHARED_SKILLS_TARGET_ID] : group.agents.map((agent) => agent.id),
|
|
41264
41485
|
selected: shouldPreselectSkillGroup(group, installGlobal, detectedGroups.length > 0, recommendedAgentId)
|
|
41265
41486
|
}))
|
|
41266
41487
|
});
|
|
@@ -41309,15 +41530,23 @@ var buildSkillGroups = function(agents, projectPath, global3) {
|
|
|
41309
41530
|
existing.push(agent);
|
|
41310
41531
|
dirToAgents.set(skillsDir, existing);
|
|
41311
41532
|
}
|
|
41312
|
-
return Array.from(dirToAgents.entries()).map(([dir, groupedAgents]) =>
|
|
41313
|
-
dir,
|
|
41314
|
-
|
|
41315
|
-
|
|
41316
|
-
|
|
41317
|
-
|
|
41318
|
-
|
|
41319
|
-
|
|
41320
|
-
|
|
41533
|
+
return Array.from(dirToAgents.entries()).map(([dir, groupedAgents]) => {
|
|
41534
|
+
const canonicalShared = resolve12(dir) === getCanonicalSkillsDirForScope(projectPath, !!global3) && groupedAgents.every((agent) => agent.getProjectSkillsStandard() === "agents");
|
|
41535
|
+
return {
|
|
41536
|
+
dir,
|
|
41537
|
+
displayDir: formatSkillsDir(projectPath, dir),
|
|
41538
|
+
agents: groupedAgents,
|
|
41539
|
+
agentNames: groupedAgents.map((agent) => agent.name),
|
|
41540
|
+
compatibleAgents: [],
|
|
41541
|
+
compatibleAgentNames: [],
|
|
41542
|
+
...canonicalShared ? {
|
|
41543
|
+
description: `Install only into the shared AGENTS.md store. Compatible tools: ${groupedAgents.map((agent) => agent.name).join(", ")}.`,
|
|
41544
|
+
kind: "canonical-shared"
|
|
41545
|
+
} : {
|
|
41546
|
+
kind: "native"
|
|
41547
|
+
}
|
|
41548
|
+
};
|
|
41549
|
+
});
|
|
41321
41550
|
};
|
|
41322
41551
|
var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
41323
41552
|
const canonicalDir = getCanonicalGlobalSkillsDir();
|
|
@@ -41332,7 +41561,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
|
41332
41561
|
return [
|
|
41333
41562
|
{
|
|
41334
41563
|
...existingCanonical,
|
|
41335
|
-
description: existingCanonical.description ||
|
|
41564
|
+
description: existingCanonical.description || `Install only into the shared AGENTS.md store. Compatible tools: ${existingCanonical.agentNames.join(", ")}.`,
|
|
41336
41565
|
kind: "canonical-shared"
|
|
41337
41566
|
},
|
|
41338
41567
|
...remaining
|
|
@@ -41346,7 +41575,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
|
41346
41575
|
agentNames: sharedAgents.map((agent) => agent.name),
|
|
41347
41576
|
compatibleAgents: [],
|
|
41348
41577
|
compatibleAgentNames: [],
|
|
41349
|
-
description:
|
|
41578
|
+
description: `Install only into the shared AGENTS.md store. Compatible tools: ${sharedAgents.map((agent) => agent.name).join(", ")}.`,
|
|
41350
41579
|
kind: "canonical-shared"
|
|
41351
41580
|
},
|
|
41352
41581
|
...groups.map((group) => {
|
|
@@ -41384,12 +41613,15 @@ var formatPromptPath = function(path) {
|
|
|
41384
41613
|
var getCanonicalGlobalSkillsDir = function() {
|
|
41385
41614
|
return resolve12(homedir6(), ".agents/skills");
|
|
41386
41615
|
};
|
|
41616
|
+
var getCanonicalSkillsDirForScope = function(projectPath, global3) {
|
|
41617
|
+
return global3 ? getCanonicalGlobalSkillsDir() : resolve12(projectPath, ".agents/skills");
|
|
41618
|
+
};
|
|
41387
41619
|
var getCanonicalGlobalSkillsDisplayPath = function() {
|
|
41388
41620
|
return formatPromptPath(getCanonicalGlobalSkillsDir());
|
|
41389
41621
|
};
|
|
41390
41622
|
var describeGlobalSkillGroup = function(group) {
|
|
41391
41623
|
if (group.kind === "canonical-shared") {
|
|
41392
|
-
return group.description
|
|
41624
|
+
return group.description || `Install only into the shared AGENTS.md store. Compatible tools: ${group.agentNames.join(", ")}.`;
|
|
41393
41625
|
}
|
|
41394
41626
|
if (group.agents.every((agent) => agent.getProjectSkillsStandard() === "agents")) {
|
|
41395
41627
|
return `Native agent directory linked to ${getCanonicalGlobalSkillsDisplayPath()} when symlinks are used.`;
|
|
@@ -41399,6 +41631,18 @@ var describeGlobalSkillGroup = function(group) {
|
|
|
41399
41631
|
}
|
|
41400
41632
|
return;
|
|
41401
41633
|
};
|
|
41634
|
+
var formatSkillGroupTitle = function(group) {
|
|
41635
|
+
if (group.kind === "canonical-shared") {
|
|
41636
|
+
return `${group.displayDir} -> ${SHARED_SKILLS_TARGET_NAME}`;
|
|
41637
|
+
}
|
|
41638
|
+
return `${group.displayDir} -> ${group.agentNames.join(", ")}${formatCompatibleAgents(group)}`;
|
|
41639
|
+
};
|
|
41640
|
+
var formatSkillTargetName = function(agentManager9, agentId) {
|
|
41641
|
+
if (agentId === SHARED_SKILLS_TARGET_ID) {
|
|
41642
|
+
return SHARED_SKILLS_TARGET_NAME;
|
|
41643
|
+
}
|
|
41644
|
+
return agentManager9.getAgentById(agentId)?.name || agentId;
|
|
41645
|
+
};
|
|
41402
41646
|
var shouldPreselectSkillGroup = function(group, installGlobal, hasDetectedGroups, recommendedAgentId) {
|
|
41403
41647
|
const includesRecommendedAgent = !!recommendedAgentId && group.agents.some((agent) => agent.id === recommendedAgentId);
|
|
41404
41648
|
if (!installGlobal) {
|
|
@@ -41451,18 +41695,18 @@ var buildSkillsAddCommand = function(source, from, extraArgs) {
|
|
|
41451
41695
|
args.push(...extraArgs);
|
|
41452
41696
|
return args.join(" ");
|
|
41453
41697
|
};
|
|
41454
|
-
var displayDiscoveredSkills = function(
|
|
41455
|
-
if (
|
|
41698
|
+
var displayDiscoveredSkills = function(skills3, warnings) {
|
|
41699
|
+
if (skills3.length === 0) {
|
|
41456
41700
|
logger.info("No skills found in the source.");
|
|
41457
41701
|
for (const warning of warnings) {
|
|
41458
41702
|
logger.warn(warning);
|
|
41459
41703
|
}
|
|
41460
41704
|
return;
|
|
41461
41705
|
}
|
|
41462
|
-
logger.info(`Found ${green(String(
|
|
41706
|
+
logger.info(`Found ${green(String(skills3.length))} skill(s):\n`);
|
|
41463
41707
|
logger.info(" Name Description");
|
|
41464
41708
|
logger.info(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
41465
|
-
for (const skill of
|
|
41709
|
+
for (const skill of skills3) {
|
|
41466
41710
|
const name = skill.name.padEnd(18);
|
|
41467
41711
|
logger.info(` ${green(name)} ${skill.description}`);
|
|
41468
41712
|
}
|
|
@@ -41503,7 +41747,7 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
41503
41747
|
agents: new Set,
|
|
41504
41748
|
skills: new Set
|
|
41505
41749
|
};
|
|
41506
|
-
existing.agents.add(agentManager9
|
|
41750
|
+
existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
|
|
41507
41751
|
existing.skills.add(item.skill.name);
|
|
41508
41752
|
byPath.set(path, existing);
|
|
41509
41753
|
}
|
|
@@ -42335,11 +42579,11 @@ function registerPluginsCommand(program2) {
|
|
|
42335
42579
|
plugins.command("install <source>").description("Install a plugin from <marketplace>/<name>, a GitHub repo, or a local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Install globally").option("--copy-skills", "Copy plugin skills instead of using canonical symlink installs").option("-l, --list", "Preview plugin contents without installing").option("-y, --yes", "Skip confirmation prompts, auto-detect project-configured agents").action(async (source, options2) => {
|
|
42336
42580
|
logger.titleBox("AgentInit Plugins");
|
|
42337
42581
|
const agentManager12 = new AgentManager;
|
|
42338
|
-
const
|
|
42582
|
+
const pluginManager3 = new PluginManager(agentManager12);
|
|
42339
42583
|
if (options2.list) {
|
|
42340
42584
|
const spinner2 = ora("Fetching plugin...").start();
|
|
42341
42585
|
try {
|
|
42342
|
-
const preview2 = await
|
|
42586
|
+
const preview2 = await pluginManager3.inspectPlugin(source, {
|
|
42343
42587
|
from: options2.from
|
|
42344
42588
|
});
|
|
42345
42589
|
spinner2.stop();
|
|
@@ -42366,8 +42610,49 @@ function registerPluginsCommand(program2) {
|
|
|
42366
42610
|
}
|
|
42367
42611
|
renderPluginWarnings(preview2, process.cwd());
|
|
42368
42612
|
} catch (error) {
|
|
42369
|
-
|
|
42370
|
-
|
|
42613
|
+
if (error instanceof MultipleBundlePluginsError) {
|
|
42614
|
+
spinner2.stop();
|
|
42615
|
+
const selected = await selectBundlePlugin2(error, "preview");
|
|
42616
|
+
if (!selected) {
|
|
42617
|
+
return;
|
|
42618
|
+
}
|
|
42619
|
+
const retrySpinner = ora("Fetching plugin...").start();
|
|
42620
|
+
try {
|
|
42621
|
+
const preview2 = await pluginManager3.inspectPlugin(source, {
|
|
42622
|
+
from: options2.from,
|
|
42623
|
+
pluginName: selected
|
|
42624
|
+
});
|
|
42625
|
+
retrySpinner.stop();
|
|
42626
|
+
const p = preview2.plugin;
|
|
42627
|
+
console.log("");
|
|
42628
|
+
logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
|
|
42629
|
+
if (p.description)
|
|
42630
|
+
logger.info(` ${p.description}`);
|
|
42631
|
+
console.log("");
|
|
42632
|
+
if (p.skills.length > 0) {
|
|
42633
|
+
logger.info(` ${green("Skills")} (${p.skills.length}):`);
|
|
42634
|
+
for (const skill of p.skills) {
|
|
42635
|
+
logger.info(` ${green(skill.name)} - ${skill.description}`);
|
|
42636
|
+
}
|
|
42637
|
+
}
|
|
42638
|
+
if (p.mcpServers.length > 0) {
|
|
42639
|
+
logger.info(` ${cyan("MCP Servers")} (${p.mcpServers.length}):`);
|
|
42640
|
+
for (const mcp of p.mcpServers) {
|
|
42641
|
+
logger.info(` ${cyan(mcp.name)} [${mcp.type}]`);
|
|
42642
|
+
}
|
|
42643
|
+
}
|
|
42644
|
+
if (p.skills.length === 0 && p.mcpServers.length === 0) {
|
|
42645
|
+
logger.info(" No portable components found (no skills or MCP servers).");
|
|
42646
|
+
}
|
|
42647
|
+
renderPluginWarnings(preview2, process.cwd());
|
|
42648
|
+
} catch (retryError) {
|
|
42649
|
+
retrySpinner.fail("Failed to fetch plugin");
|
|
42650
|
+
logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
|
|
42651
|
+
}
|
|
42652
|
+
} else {
|
|
42653
|
+
spinner2.fail("Failed to fetch plugin");
|
|
42654
|
+
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
42655
|
+
}
|
|
42371
42656
|
}
|
|
42372
42657
|
return;
|
|
42373
42658
|
}
|
|
@@ -42375,24 +42660,48 @@ function registerPluginsCommand(program2) {
|
|
|
42375
42660
|
let targetGlobal = options2.global;
|
|
42376
42661
|
let preview = null;
|
|
42377
42662
|
let previewRendered = false;
|
|
42663
|
+
let selectedPluginName;
|
|
42378
42664
|
if (!agentIds && !options2.yes) {
|
|
42379
42665
|
const previewSpinner = ora("Inspecting plugin...").start();
|
|
42380
42666
|
try {
|
|
42381
|
-
preview = await
|
|
42667
|
+
preview = await pluginManager3.preparePluginInstall(source, {
|
|
42382
42668
|
from: options2.from
|
|
42383
42669
|
});
|
|
42384
42670
|
previewSpinner.stop();
|
|
42385
42671
|
renderPluginWarnings(preview, process.cwd());
|
|
42386
42672
|
previewRendered = true;
|
|
42387
42673
|
} catch (error) {
|
|
42388
|
-
|
|
42389
|
-
|
|
42390
|
-
|
|
42674
|
+
if (error instanceof MultipleBundlePluginsError) {
|
|
42675
|
+
previewSpinner.stop();
|
|
42676
|
+
const selected = await selectBundlePlugin2(error, "install");
|
|
42677
|
+
if (!selected) {
|
|
42678
|
+
return;
|
|
42679
|
+
}
|
|
42680
|
+
selectedPluginName = selected;
|
|
42681
|
+
const retrySpinner = ora("Inspecting plugin...").start();
|
|
42682
|
+
try {
|
|
42683
|
+
preview = await pluginManager3.preparePluginInstall(source, {
|
|
42684
|
+
from: options2.from,
|
|
42685
|
+
pluginName: selectedPluginName
|
|
42686
|
+
});
|
|
42687
|
+
retrySpinner.stop();
|
|
42688
|
+
renderPluginWarnings(preview, process.cwd());
|
|
42689
|
+
previewRendered = true;
|
|
42690
|
+
} catch (retryError) {
|
|
42691
|
+
retrySpinner.fail("Failed to inspect plugin");
|
|
42692
|
+
logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
|
|
42693
|
+
return;
|
|
42694
|
+
}
|
|
42695
|
+
} else {
|
|
42696
|
+
previewSpinner.fail("Failed to inspect plugin");
|
|
42697
|
+
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
42698
|
+
return;
|
|
42699
|
+
}
|
|
42391
42700
|
}
|
|
42392
42701
|
try {
|
|
42393
|
-
const selection = await interactiveAgentSelect(
|
|
42702
|
+
const selection = await interactiveAgentSelect(pluginManager3, agentManager12, process.cwd(), targetGlobal, preview);
|
|
42394
42703
|
if (!selection || selection.aborted || !selection.agents || selection.agents.length === 0) {
|
|
42395
|
-
await
|
|
42704
|
+
await pluginManager3.discardPreparedPlugin(source, { from: options2.from });
|
|
42396
42705
|
logger.info("No agents selected. Aborting.");
|
|
42397
42706
|
return;
|
|
42398
42707
|
}
|
|
@@ -42407,12 +42716,13 @@ function registerPluginsCommand(program2) {
|
|
|
42407
42716
|
}
|
|
42408
42717
|
const spinner = ora("Installing plugin...").start();
|
|
42409
42718
|
try {
|
|
42410
|
-
const result = await
|
|
42719
|
+
const result = await pluginManager3.installPlugin(source, process.cwd(), {
|
|
42411
42720
|
from: options2.from,
|
|
42412
42721
|
agents: agentIds,
|
|
42413
42722
|
global: targetGlobal,
|
|
42414
42723
|
copySkills: options2.copySkills,
|
|
42415
|
-
yes: options2.yes
|
|
42724
|
+
yes: options2.yes,
|
|
42725
|
+
...selectedPluginName ? { pluginName: selectedPluginName } : {}
|
|
42416
42726
|
});
|
|
42417
42727
|
const p = result.plugin;
|
|
42418
42728
|
const totalSkills = result.skills.installed.length;
|
|
@@ -42444,13 +42754,48 @@ function registerPluginsCommand(program2) {
|
|
|
42444
42754
|
}
|
|
42445
42755
|
logger.success("Plugin installation complete.");
|
|
42446
42756
|
} catch (error) {
|
|
42447
|
-
|
|
42448
|
-
|
|
42757
|
+
if (error instanceof MultipleBundlePluginsError && !options2.yes) {
|
|
42758
|
+
spinner.stop();
|
|
42759
|
+
const selected = await selectBundlePlugin2(error, "install");
|
|
42760
|
+
if (!selected) {
|
|
42761
|
+
return;
|
|
42762
|
+
}
|
|
42763
|
+
const retrySpinner = ora("Installing plugin...").start();
|
|
42764
|
+
try {
|
|
42765
|
+
const result = await pluginManager3.installPlugin(source, process.cwd(), {
|
|
42766
|
+
from: options2.from,
|
|
42767
|
+
agents: agentIds,
|
|
42768
|
+
global: targetGlobal,
|
|
42769
|
+
copySkills: options2.copySkills,
|
|
42770
|
+
yes: options2.yes,
|
|
42771
|
+
pluginName: selected
|
|
42772
|
+
});
|
|
42773
|
+
const p = result.plugin;
|
|
42774
|
+
const totalSkills = result.skills.installed.length;
|
|
42775
|
+
const totalMcp = result.mcpServers.applied.length;
|
|
42776
|
+
const totalNative = result.nativePlugins.installed.length;
|
|
42777
|
+
if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
|
|
42778
|
+
retrySpinner.warn(`Plugin "${p.name}" has no portable components to install.`);
|
|
42779
|
+
renderPluginWarnings(result, process.cwd());
|
|
42780
|
+
return;
|
|
42781
|
+
}
|
|
42782
|
+
retrySpinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
|
|
42783
|
+
renderInstalledComponents(result, agentManager12, process.cwd());
|
|
42784
|
+
renderPluginWarnings(result, process.cwd());
|
|
42785
|
+
logger.success("Plugin installation complete.");
|
|
42786
|
+
} catch (retryError) {
|
|
42787
|
+
retrySpinner.fail("Failed to install plugin");
|
|
42788
|
+
logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
|
|
42789
|
+
}
|
|
42790
|
+
} else {
|
|
42791
|
+
spinner.fail("Failed to install plugin");
|
|
42792
|
+
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
42793
|
+
}
|
|
42449
42794
|
}
|
|
42450
42795
|
});
|
|
42451
42796
|
plugins.command("search [query]").description("Search marketplace plugins").option("--from <marketplace>", `Which marketplace to search (available: ${marketplaceHelp})`).option("--category <category>", `Filter by marketplace category (examples: ${marketplaceCategoryHelp})`).action(async (query, options2) => {
|
|
42452
42797
|
logger.titleBox("AgentInit Plugin Search");
|
|
42453
|
-
const
|
|
42798
|
+
const pluginManager3 = new PluginManager;
|
|
42454
42799
|
const registryId = options2.from || getConfiguredDefaultMarketplaceId();
|
|
42455
42800
|
if (!registryId) {
|
|
42456
42801
|
logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
|
|
@@ -42461,7 +42806,7 @@ function registerPluginsCommand(program2) {
|
|
|
42461
42806
|
}
|
|
42462
42807
|
const spinner = ora(`Fetching ${registryId} marketplace...`).start();
|
|
42463
42808
|
try {
|
|
42464
|
-
const results = await
|
|
42809
|
+
const results = await pluginManager3.listMarketplacePlugins(registryId, query, options2.category);
|
|
42465
42810
|
spinner.stop();
|
|
42466
42811
|
if (results.length === 0) {
|
|
42467
42812
|
logger.info(query ? `No plugins matching "${query}".` : "No plugins found.");
|
|
@@ -42491,8 +42836,8 @@ function registerPluginsCommand(program2) {
|
|
|
42491
42836
|
});
|
|
42492
42837
|
plugins.command("list").alias("ls").description("List installed plugins").option("-a, --agent <agents...>", "Filter by specific agent(s)").option("-g, --global", "List global plugins").action(async (options2) => {
|
|
42493
42838
|
logger.titleBox("AgentInit Installed Plugins");
|
|
42494
|
-
const
|
|
42495
|
-
const installed = await
|
|
42839
|
+
const pluginManager3 = new PluginManager;
|
|
42840
|
+
const installed = await pluginManager3.listPlugins(process.cwd(), {
|
|
42496
42841
|
global: options2.global,
|
|
42497
42842
|
agents: options2.agent
|
|
42498
42843
|
});
|
|
@@ -42527,10 +42872,10 @@ function registerPluginsCommand(program2) {
|
|
|
42527
42872
|
});
|
|
42528
42873
|
plugins.command("remove <name>").alias("rm").description("Remove an installed plugin").option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Remove from global scope").option("-y, --yes", "Skip confirmation prompts").action(async (name, options2) => {
|
|
42529
42874
|
logger.titleBox("AgentInit Remove Plugin");
|
|
42530
|
-
const
|
|
42875
|
+
const pluginManager3 = new PluginManager;
|
|
42531
42876
|
const spinner = ora(`Removing plugin "${name}"...`).start();
|
|
42532
42877
|
try {
|
|
42533
|
-
const result = await
|
|
42878
|
+
const result = await pluginManager3.removePlugin(name, process.cwd(), {
|
|
42534
42879
|
global: options2.global,
|
|
42535
42880
|
agents: options2.agent,
|
|
42536
42881
|
yes: options2.yes
|
|
@@ -42552,6 +42897,22 @@ function registerPluginsCommand(program2) {
|
|
|
42552
42897
|
}
|
|
42553
42898
|
});
|
|
42554
42899
|
}
|
|
42900
|
+
async function selectBundlePlugin2(error, actionLabel) {
|
|
42901
|
+
const response = await import_prompts3.default({
|
|
42902
|
+
type: "select",
|
|
42903
|
+
name: "plugin",
|
|
42904
|
+
message: `This repository contains multiple plugins. Select one to ${actionLabel}:`,
|
|
42905
|
+
choices: error.entries.map((entry) => ({
|
|
42906
|
+
title: entry.name,
|
|
42907
|
+
value: entry.name
|
|
42908
|
+
}))
|
|
42909
|
+
});
|
|
42910
|
+
if (!response.plugin) {
|
|
42911
|
+
logger.info("Cancelled.");
|
|
42912
|
+
return null;
|
|
42913
|
+
}
|
|
42914
|
+
return response.plugin;
|
|
42915
|
+
}
|
|
42555
42916
|
var formatPathForDisplay = function(pathValue, projectPath) {
|
|
42556
42917
|
if (pathValue.startsWith(`${projectPath}/`)) {
|
|
42557
42918
|
return relative8(projectPath, pathValue) || ".";
|
|
@@ -42841,9 +43202,9 @@ var getPluginGroupDescription = function(group, preview, projectPath) {
|
|
|
42841
43202
|
const receiveVerb = otherAgents.length === 1 ? "receives" : "receive";
|
|
42842
43203
|
return `${portableSummary}. Full plugin support is available in Claude Code; the native plugin installs at ${installPath}. ${otherAgentsLabel} ${shareVerb} this skills directory but only ${receiveVerb} the installed skills.`;
|
|
42843
43204
|
};
|
|
42844
|
-
async function interactiveAgentSelect(
|
|
43205
|
+
async function interactiveAgentSelect(pluginManager3, agentManager12, projectPath, global3, preview) {
|
|
42845
43206
|
let installGlobal = !!global3;
|
|
42846
|
-
let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await
|
|
43207
|
+
let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager3.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
|
|
42847
43208
|
...group,
|
|
42848
43209
|
displayDir: group.dir
|
|
42849
43210
|
}));
|