Files
2026-05-30 14:16:04 -05:00

109 lines
3.0 KiB
TypeScript

/**
* Copy all memory-* skills from the top-level basic-memory skills source.
*
* Auto-discovers skill directories in ../../../skills, copies each SKILL.md
* into this package's skills/<dir>/SKILL.md, and generates skills/manifest.json.
*/
import {
existsSync,
mkdirSync,
readdirSync,
readFileSync,
writeFileSync,
} from "node:fs"
import { dirname, resolve } from "node:path"
import { fileURLToPath } from "node:url"
const __dirname = dirname(fileURLToPath(import.meta.url))
const SKILLS_DIR = resolve(__dirname, "..", "skills")
const SOURCE_SKILLS_DIR = resolve(__dirname, "..", "..", "..", "skills")
interface SkillManifestEntry {
dir: string
name: string
description: string
}
function parseFrontmatter(md: string): { name: string; description: string } {
const match = md.match(/^---\r?\n([\s\S]*?)\r?\n---/)
if (!match) throw new Error("SKILL.md missing YAML frontmatter")
const yaml = match[1]
const name = yaml
.match(/^name:\s*(.+)$/m)?.[1]
?.trim()
.replace(/^["']|["']$/g, "")
const description = yaml
.match(/^description:\s*(.+)$/m)?.[1]
?.trim()
.replace(/^["']|["']$/g, "")
if (!name) throw new Error("Frontmatter missing 'name'")
if (!description) throw new Error("Frontmatter missing 'description'")
return { name, description }
}
function discoverSkillDirs(): string[] {
if (!existsSync(SOURCE_SKILLS_DIR)) {
throw new Error(`Missing source skills directory: ${SOURCE_SKILLS_DIR}`)
}
const skillDirs = readdirSync(SOURCE_SKILLS_DIR, { withFileTypes: true })
.filter((e) => e.isDirectory() && e.name.startsWith("memory-"))
.map((e) => e.name)
.sort()
if (skillDirs.length === 0) {
throw new Error(`No memory-* directories found in ${SOURCE_SKILLS_DIR}`)
}
return skillDirs
}
function main() {
console.log(`Copying skills from ${SOURCE_SKILLS_DIR}`)
const skillDirs = discoverSkillDirs()
console.log(`Found ${skillDirs.length} skills: ${skillDirs.join(", ")}`)
const manifest: SkillManifestEntry[] = []
for (const dir of skillDirs) {
const skillPath = resolve(SOURCE_SKILLS_DIR, dir, "SKILL.md")
if (!existsSync(skillPath)) {
throw new Error(`Missing SKILL.md for ${dir}: ${skillPath}`)
}
const content = readFileSync(skillPath, "utf8")
const meta = parseFrontmatter(content)
const outDir = resolve(SKILLS_DIR, dir)
mkdirSync(outDir, { recursive: true })
writeFileSync(resolve(outDir, "SKILL.md"), content)
manifest.push({ dir, name: meta.name, description: meta.description })
console.log(`${dir}`)
}
manifest.sort((a, b) => a.dir.localeCompare(b.dir))
mkdirSync(SKILLS_DIR, { recursive: true })
writeFileSync(
resolve(SKILLS_DIR, "manifest.json"),
`${JSON.stringify(manifest, null, 2)}\n`,
)
console.log(
`\nWrote ${manifest.length} skills + manifest.json to ${SKILLS_DIR}`,
)
}
try {
main()
} catch (err) {
const message = err instanceof Error ? err.message : String(err)
console.error("Fatal:", message)
process.exit(1)
}