Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 36 additions & 44 deletions scripts/dist/discover-components.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7646,7 +7646,7 @@ function validateComponent(componentPath, config, options2) {
errors.push(`Invalid frontmatter in ${filePath}: ${err.message}`);
return { valid: false, errors };
}
const { name, description } = parsed.data;
const { name, description, author, category } = parsed.data;
if (!name) {
errors.push(`Missing required field 'name' in ${filePath}`);
}
Expand Down Expand Up @@ -7683,7 +7683,9 @@ function validateComponent(componentPath, config, options2) {
valid: errors.length === 0,
errors,
name,
description
description,
author,
category
};
}
function validateSkill(skillPath, config) {
Expand Down Expand Up @@ -7926,62 +7928,51 @@ function discoverPlugins(rootDir, config) {
const { plugins } = groupIntoPlugins(components, rootDir, config);
return plugins;
}
function generatePluginJson(plugin, config) {
function extractPluginMetadata(plugin, config) {
const { components } = plugin;
const { owner } = config.marketplace;
let pluginName = plugin.name;
let pluginDescription = `${plugin.name} plugin`;
if (components.agents && components.agents.length > 0) {
const validation = validateAgent(components.agents[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.commands && components.commands.length > 0) {
const validation = validateCommand(components.commands[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.skills && components.skills.length > 0) {
const validation = validateSkill(components.skills[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
let pluginAuthor;
let pluginCategory;
const componentSources = [
...(components.agents || []).map((p) => validateAgent(p, config)),
...(components.commands || []).map((p) => validateCommand(p, config)),
...(components.skills || []).map((p) => validateSkill(p, config))
];
for (const validation of componentSources) {
if (!validation.valid)
continue;
if (!pluginDescription || pluginDescription === `${plugin.name} plugin`) {
if (validation.description)
pluginDescription = validation.description;
}
if (!pluginAuthor && validation.author)
pluginAuthor = validation.author;
if (!pluginCategory && validation.category)
pluginCategory = validation.category;
}
return { name: pluginName, description: pluginDescription, author: pluginAuthor, category: pluginCategory };
}
function generatePluginJson(plugin, config) {
const { owner } = config.marketplace;
const metadata = extractPluginMetadata(plugin, config);
return {
name: pluginName,
description: pluginDescription,
author: owner
name: metadata.name,
description: metadata.description,
author: metadata.author || owner
};
}
function generateMarketplace(plugins, config) {
const { name, owner, description } = config.marketplace;
const marketplacePlugins = [];
for (const plugin of plugins) {
const { components } = plugin;
let pluginName = plugin.name;
let pluginDescription = `${plugin.name} plugin`;
if (components.agents && components.agents.length > 0) {
const validation = validateAgent(components.agents[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.commands && components.commands.length > 0) {
const validation = validateCommand(components.commands[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.skills && components.skills.length > 0) {
const validation = validateSkill(components.skills[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
}
const metadata = extractPluginMetadata(plugin, config);
marketplacePlugins.push({
name: pluginName,
description: pluginDescription,
name: metadata.name,
description: metadata.description,
source: plugin.source,
author: owner,
category: plugin.category === "code" || plugin.category === "analysis" ? "development" : "productivity"
author: metadata.author || owner,
category: metadata.category || (plugin.category === "code" || plugin.category === "analysis" ? "development" : "productivity")
});
}
const marketplacePath = path.join(".claude-plugin", "marketplace.json");
Expand Down Expand Up @@ -8043,6 +8034,7 @@ module.exports = {
getCategoryNames,
groupIntoPlugins,
discoverPlugins,
extractPluginMetadata,
generatePluginJson,
generateMarketplace,
writePluginJsonFiles
Expand Down
100 changes: 46 additions & 54 deletions scripts/src/discover-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ function validateComponent(componentPath, config, options) {
return { valid: false, errors };
}

const { name, description } = parsed.data;
const { name, description, author, category } = parsed.data;

// Validate required fields
if (!name) {
Expand Down Expand Up @@ -650,7 +650,9 @@ function validateComponent(componentPath, config, options) {
valid: errors.length === 0,
errors,
name,
description
description,
author,
category
};
}

Expand Down Expand Up @@ -1213,41 +1215,52 @@ function discoverPlugins(rootDir, config) {
}

/**
* Generates individual plugin.json for a plugin directory.
* @param {Object} plugin - Plugin metadata
* Extracts name, description, author, and category from a plugin's components.
* Validates each component type and takes metadata from the first valid one found.
* @param {Object} plugin - Plugin metadata with components
* @param {Object} config - Configuration object
* @returns {Object} Plugin manifest object
* @returns {{ name: string, description: string, author?: Object, category?: string }}
*/
function generatePluginJson(plugin, config) {
function extractPluginMetadata(plugin, config) {
const { components } = plugin;
const { owner } = config.marketplace;

// Get metadata from the first valid component
let pluginName = plugin.name;
let pluginDescription = `${plugin.name} plugin`;
let pluginAuthor;
let pluginCategory;

// Validate all component types, take metadata from first valid one
const componentSources = [
...(components.agents || []).map(p => validateAgent(p, config)),
...(components.commands || []).map(p => validateCommand(p, config)),
...(components.skills || []).map(p => validateSkill(p, config))
];

// Try to extract description from components
if (components.agents && components.agents.length > 0) {
const validation = validateAgent(components.agents[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.commands && components.commands.length > 0) {
const validation = validateCommand(components.commands[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.skills && components.skills.length > 0) {
const validation = validateSkill(components.skills[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
for (const validation of componentSources) {
if (!validation.valid) continue;
if (!pluginDescription || pluginDescription === `${plugin.name} plugin`) {
if (validation.description) pluginDescription = validation.description;
}
if (!pluginAuthor && validation.author) pluginAuthor = validation.author;
if (!pluginCategory && validation.category) pluginCategory = validation.category;
}

return { name: pluginName, description: pluginDescription, author: pluginAuthor, category: pluginCategory };
}

/**
* Generates individual plugin.json for a plugin directory.
* @param {Object} plugin - Plugin metadata
* @param {Object} config - Configuration object
* @returns {Object} Plugin manifest object
*/
function generatePluginJson(plugin, config) {
const { owner } = config.marketplace;
const metadata = extractPluginMetadata(plugin, config);

return {
name: pluginName,
description: pluginDescription,
author: owner
name: metadata.name,
description: metadata.description,
author: metadata.author || owner
};
}

Expand All @@ -1263,36 +1276,14 @@ function generateMarketplace(plugins, config) {
const marketplacePlugins = [];

for (const plugin of plugins) {
const { components } = plugin;

// Get metadata from the first valid component
let pluginName = plugin.name;
let pluginDescription = `${plugin.name} plugin`;

// Try to extract description from components
if (components.agents && components.agents.length > 0) {
const validation = validateAgent(components.agents[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.commands && components.commands.length > 0) {
const validation = validateCommand(components.commands[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
} else if (components.skills && components.skills.length > 0) {
const validation = validateSkill(components.skills[0], config);
if (validation.valid && validation.description) {
pluginDescription = validation.description;
}
}
const metadata = extractPluginMetadata(plugin, config);

marketplacePlugins.push({
name: pluginName,
description: pluginDescription,
name: metadata.name,
description: metadata.description,
source: plugin.source,
author: owner,
category: plugin.category === 'code' || plugin.category === 'analysis' ? 'development' : 'productivity'
author: metadata.author || owner,
category: metadata.category || (plugin.category === 'code' || plugin.category === 'analysis' ? 'development' : 'productivity')
});
}

Expand Down Expand Up @@ -1374,6 +1365,7 @@ module.exports = {
getCategoryNames,
groupIntoPlugins,
discoverPlugins,
extractPluginMetadata,
generatePluginJson,
generateMarketplace,
writePluginJsonFiles
Expand Down
Loading