feat(skills): add refresh summary for discovery health
This commit is contained in:
@@ -12,6 +12,13 @@ export interface SkillListRow {
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface SkillRefreshSummary {
|
||||
total: number;
|
||||
available: number;
|
||||
unavailable: number;
|
||||
tiers: Record<Skill['manifest']['tier'], number>;
|
||||
}
|
||||
|
||||
export function toSkillListRows(skills: Skill[]): SkillListRow[] {
|
||||
return skills
|
||||
.map((skill) => ({
|
||||
@@ -71,6 +78,37 @@ export function renderSkillInfo(skill: Skill): string {
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
export function summarizeSkillsRefresh(skills: Skill[]): SkillRefreshSummary {
|
||||
const summary: SkillRefreshSummary = {
|
||||
total: skills.length,
|
||||
available: 0,
|
||||
unavailable: 0,
|
||||
tiers: {
|
||||
bundled: 0,
|
||||
managed: 0,
|
||||
workspace: 0,
|
||||
},
|
||||
};
|
||||
|
||||
for (const skill of skills) {
|
||||
if (skill.available) {
|
||||
summary.available += 1;
|
||||
} else {
|
||||
summary.unavailable += 1;
|
||||
}
|
||||
summary.tiers[skill.manifest.tier] += 1;
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
export function renderSkillsRefreshSummary(summary: SkillRefreshSummary): string {
|
||||
return [
|
||||
`Refreshed ${summary.total} skills (${summary.available} available, ${summary.unavailable} unavailable).`,
|
||||
`By tier: bundled=${summary.tiers.bundled}, managed=${summary.tiers.managed}, workspace=${summary.tiers.workspace}`,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
function loadSkillsFromConfig(configPath?: string): { skills?: Skill[]; error?: string } {
|
||||
const loaded = loadConfigSafe(configPath);
|
||||
if (loaded.error || !loaded.config) {
|
||||
@@ -242,4 +280,26 @@ export function registerSkillsCommand(program: Command): void {
|
||||
|
||||
console.log(`Uninstalled skill '${name}'.`);
|
||||
});
|
||||
|
||||
skills
|
||||
.command('refresh')
|
||||
.description('Refresh skill discovery and print summary')
|
||||
.option('--json', 'Output as JSON')
|
||||
.option('-c, --config <path>', 'Config file path')
|
||||
.action((opts: { json?: boolean; config?: string }) => {
|
||||
const loaded = loadSkillsFromConfig(opts.config);
|
||||
if (loaded.error || !loaded.skills) {
|
||||
console.error(loaded.error ?? 'Failed to load skills');
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const summary = summarizeSkillsRefresh(loaded.skills);
|
||||
if (opts.json) {
|
||||
console.log(JSON.stringify(summary, null, 2));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(renderSkillsRefreshSummary(summary));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user