=== NEW === - studio/ — MCPEngine Studio scaffold (Next.js monorepo, build plan) - docs/FACTORY-V2.md — Factory v2 architecture doc - docs/CALENDLY_MCP_BUILD_SUMMARY.md — Calendly MCP build report === UPDATED SERVERS === - fieldedge: Added jobs-tools, UI build script, main entry update - lightspeed: Updated main + server entry points - squarespace: Added collection-browser + page-manager apps - toast: Added main + server entry points === INFRA === - infra/command-center/state.json — Updated pipeline state - infra/command-center/FACTORY-V2.md — Factory v2 operator playbook
79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
// Skill Loader — reads .md skill files from skills/data/, caches in memory
|
|
|
|
import { readFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { SKILL_REGISTRY, type SkillName } from './registry';
|
|
|
|
const SKILLS_DIR = join(__dirname, 'data');
|
|
|
|
// In-memory cache: filename → content
|
|
const fileCache = new Map<string, string>();
|
|
|
|
// Combined skill cache: skill name → concatenated content
|
|
const skillCache = new Map<string, string>();
|
|
|
|
function loadFile(filename: string): string {
|
|
const cached = fileCache.get(filename);
|
|
if (cached) return cached;
|
|
|
|
const filePath = join(SKILLS_DIR, filename);
|
|
const content = readFileSync(filePath, 'utf-8');
|
|
fileCache.set(filename, content);
|
|
return content;
|
|
}
|
|
|
|
/**
|
|
* Get the combined skill content for a named skill.
|
|
* Multi-file skills (builder, designer) are concatenated with separators.
|
|
*/
|
|
export function getSkill(name: string): string {
|
|
const cached = skillCache.get(name);
|
|
if (cached) return cached;
|
|
|
|
const mapping = SKILL_REGISTRY[name as SkillName];
|
|
if (!mapping) {
|
|
throw new Error(
|
|
`Unknown skill "${name}". Available: ${Object.keys(SKILL_REGISTRY).join(', ')}`
|
|
);
|
|
}
|
|
|
|
const parts = mapping.files.map((file) => {
|
|
const content = loadFile(file);
|
|
return `<!-- SKILL: ${file} -->\n${content}`;
|
|
});
|
|
|
|
const combined = parts.join('\n\n---\n\n');
|
|
skillCache.set(name, combined);
|
|
return combined;
|
|
}
|
|
|
|
/**
|
|
* Get a single raw skill file by filename.
|
|
*/
|
|
export function getSkillFile(filename: string): string {
|
|
return loadFile(filename);
|
|
}
|
|
|
|
/**
|
|
* Preload all skill files into cache. Call at startup for faster first requests.
|
|
*/
|
|
export function preloadSkills(): void {
|
|
for (const mapping of Object.values(SKILL_REGISTRY)) {
|
|
for (const file of mapping.files) {
|
|
loadFile(file);
|
|
}
|
|
}
|
|
// Also build combined caches
|
|
for (const name of Object.keys(SKILL_REGISTRY)) {
|
|
getSkill(name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all caches. Useful for development hot-reload.
|
|
*/
|
|
export function clearSkillCache(): void {
|
|
fileCache.clear();
|
|
skillCache.clear();
|
|
}
|