fix: include bundled skills/ dir in skills status and sync discovery (#461)
This commit is contained in:
@@ -335,11 +335,18 @@ async function main() {
|
||||
break;
|
||||
|
||||
case 'skills': {
|
||||
const { showStatus, runSkillsSync } = await import('./skills/index.js');
|
||||
const { showStatus, runSkillsSync, enableSkill } = await import('./skills/index.js');
|
||||
switch (subCommand) {
|
||||
case 'status':
|
||||
await showStatus();
|
||||
break;
|
||||
case 'enable':
|
||||
if (!args[2]) {
|
||||
console.error('Usage: lettabot skills enable <name>');
|
||||
process.exit(1);
|
||||
}
|
||||
enableSkill(args[2]);
|
||||
break;
|
||||
default:
|
||||
await runSkillsSync();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { existsSync, readdirSync, cpSync, mkdirSync, rmSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import * as p from '@clack/prompts';
|
||||
import { PROJECT_SKILLS_DIR, GLOBAL_SKILLS_DIR, SKILLS_SH_DIR, parseSkillFile } from './loader.js';
|
||||
import { PROJECT_SKILLS_DIR, BUNDLED_SKILLS_DIR, GLOBAL_SKILLS_DIR, SKILLS_SH_DIR, parseSkillFile } from './loader.js';
|
||||
|
||||
const HOME = process.env.HOME || process.env.USERPROFILE || '';
|
||||
const WORKING_DIR = process.env.WORKING_DIR || '/tmp/lettabot';
|
||||
@@ -68,10 +68,12 @@ function discoverSkills(): SkillInfo[] {
|
||||
}
|
||||
};
|
||||
|
||||
// Discover from all sources (order matters - first source wins for duplicates)
|
||||
// Discover from all sources (order matters - first source wins for duplicates).
|
||||
// Priority matches the loader hierarchy: project (.skills/) > bundled (skills/) > external.
|
||||
addFromDir(PROJECT_SKILLS_DIR, 'builtin'); // .skills/ project overrides
|
||||
addFromDir(BUNDLED_SKILLS_DIR, 'builtin'); // skills/ bundled with repo
|
||||
addFromDir(CLAWDHUB_DIR, 'clawdhub');
|
||||
addFromDir(VERCEL_DIR, 'vercel');
|
||||
addFromDir(PROJECT_SKILLS_DIR, 'builtin');
|
||||
|
||||
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
@@ -218,3 +220,32 @@ export async function runSkillsSync(): Promise<void> {
|
||||
p.log.info(`Skills directory: ${TARGET_DIR}`);
|
||||
p.outro(`✨ Added ${toAdd.length}, removed ${toRemove.length} skill(s)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-interactively enable a single skill by name.
|
||||
* Searches BUNDLED_SKILLS_DIR, then GLOBAL_SKILLS_DIR, then SKILLS_SH_DIR.
|
||||
*/
|
||||
export function enableSkill(name: string): void {
|
||||
// Search order: highest priority first (project local > global > bundled > skills.sh)
|
||||
const sourceDirs = [PROJECT_SKILLS_DIR, GLOBAL_SKILLS_DIR, BUNDLED_SKILLS_DIR, SKILLS_SH_DIR];
|
||||
|
||||
mkdirSync(TARGET_DIR, { recursive: true });
|
||||
|
||||
const dest = join(TARGET_DIR, name);
|
||||
if (existsSync(dest)) {
|
||||
console.log(`Skill '${name}' is already enabled.`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const dir of sourceDirs) {
|
||||
const src = join(dir, name);
|
||||
if (existsSync(src) && existsSync(join(src, 'SKILL.md'))) {
|
||||
cpSync(src, dest, { recursive: true });
|
||||
console.log(`Enabled skill '${name}' from ${dir}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(`Skill '${name}' not found. Run 'lettabot skills status' to see available skills.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as p from '@clack/prompts';
|
||||
import { join } from 'node:path';
|
||||
import { getSkillsSummary, type SkillsSummary } from './status.js';
|
||||
import { installSkillDeps } from './install.js';
|
||||
import { hasBinary, GLOBAL_SKILLS_DIR, SKILLS_SH_DIR } from './loader.js';
|
||||
import { hasBinary, BUNDLED_SKILLS_DIR, GLOBAL_SKILLS_DIR, SKILLS_SH_DIR } from './loader.js';
|
||||
import type { NodeManager, SkillStatus } from './types.js';
|
||||
|
||||
import { createLogger } from '../logger.js';
|
||||
@@ -261,7 +261,7 @@ export async function listSkills(): Promise<void> {
|
||||
*/
|
||||
export async function showStatus(): Promise<void> {
|
||||
const enabledSummary = getSkillsSummary([WORKING_SKILLS_DIR]);
|
||||
const availableSummary = getSkillsSummary([GLOBAL_SKILLS_DIR, SKILLS_SH_DIR]);
|
||||
const availableSummary = getSkillsSummary([BUNDLED_SKILLS_DIR, GLOBAL_SKILLS_DIR, SKILLS_SH_DIR]);
|
||||
|
||||
// Get names of enabled skills to filter available
|
||||
const enabledNames = new Set(enabledSummary.skills.map(s => s.skill.name));
|
||||
@@ -297,6 +297,6 @@ export async function showStatus(): Promise<void> {
|
||||
}
|
||||
|
||||
log.info('');
|
||||
log.info(` To enable: lettabot skills enable <name>`);
|
||||
log.info(` To enable: lettabot skills enable <name> (or run: lettabot skills)`);
|
||||
log.info(` Skills dir: ${WORKING_SKILLS_DIR}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user