// engine/skill-registry/anthropic-adapter.ts — SPEC-150: Anthropic skills.sh adapter
// Fetches skills from github.com/anthropics/skills using the public GitHub API.
// No auth required for public repos. Results cached in-memory (TTL 5 min).
const GITHUB_API_BASE = 'https://api.github.com';
const REPO_OWNER = 'anthropics';
const REPO_NAME = 'skills';
const SKILLS_DIR = 'skills';
const CACHE_TTL_MS = 5 * 60 * 1000;
const USER_AGENT = 'Planu/1.0';
// In-memory cache for the full skill list (avoids GitHub API rate limits)
let skillCache = null;
/** Parse YAML frontmatter from SKILL.md content (simple key:value only). */
function parseSkillFrontmatter(content) {
    const match = /^---\n([\s\S]*?)\n---/.exec(content);
    if (!match?.[1]) {
        return {};
    }
    const result = {};
    for (const line of match[1].split('\n')) {
        const kv = /^(\w+):\s*(.+)$/.exec(line.trim());
        if (!kv?.[1] || kv[2] === undefined) {
            continue;
        }
        const key = kv[1];
        const val = kv[2].trim().replace(/^["']|["']$/g, '');
        if (key === 'tags') {
            result.tags = val
                .replace(/^\[|\]$/g, '')
                .split(',')
                .map((t) => t.trim().replace(/^["']|["']$/g, ''))
                .filter(Boolean);
        }
        else {
            result[key] = val;
        }
    }
    return result;
}
/** Fetch raw text from GitHub API (returns null on any error). */
async function fetchGitHub(path) {
    try {
        const response = await globalThis.fetch(`${GITHUB_API_BASE}${path}`, {
            headers: {
                'User-Agent': USER_AGENT,
                Accept: 'application/vnd.github.v3+json',
            },
            signal: AbortSignal.timeout(10_000),
        });
        if (!response.ok) {
            return null;
        }
        return await response.json();
    }
    catch {
        return null;
    }
}
/** Fetch the list of all skill directories from the Anthropic skills repo. */
async function fetchSkillList() {
    if (skillCache && Date.now() - skillCache.fetchedAt < CACHE_TTL_MS) {
        return skillCache.data;
    }
    const contents = await fetchGitHub(`/repos/${REPO_OWNER}/${REPO_NAME}/contents/${SKILLS_DIR}`);
    if (!Array.isArray(contents)) {
        return [];
    }
    const skillDirs = contents.filter((item) => item.type === 'dir');
    const results = await Promise.allSettled(skillDirs.map(async (dir) => {
        const skillMdRaw = await fetchGitHub(`/repos/${REPO_OWNER}/${REPO_NAME}/contents/${SKILLS_DIR}/${dir.name}/SKILL.md`);
        if (!skillMdRaw ||
            typeof skillMdRaw !== 'object' ||
            !('content' in skillMdRaw) ||
            typeof skillMdRaw.content !== 'string') {
            return null;
        }
        const rawContent = skillMdRaw.content;
        const decoded = Buffer.from(rawContent.replace(/\n/g, ''), 'base64').toString('utf-8');
        const meta = parseSkillFrontmatter(decoded);
        return {
            name: meta.name ?? dir.name,
            description: meta.description ?? `Skill: ${dir.name}`,
            source: 'anthropic',
            installCommand: `planu registry install anthropics/skills/${dir.name}`,
            url: `https://github.com/${REPO_OWNER}/${REPO_NAME}/tree/main/${SKILLS_DIR}/${dir.name}`,
            author: meta.author ?? REPO_OWNER,
            tags: meta.tags,
            license: meta.license,
            relevanceScore: 0,
        };
    }));
    const skills = results
        .map((r) => (r.status === 'fulfilled' ? r.value : null))
        .filter((s) => s !== null);
    skillCache = { data: skills, fetchedAt: Date.now() };
    return skills;
}
/** Search Anthropic skills by query string (filters name/description/tags). */
export async function searchAnthropicSkills(query, limit) {
    const all = await fetchSkillList();
    const q = query.toLowerCase();
    const filtered = all.filter((s) => s.name.toLowerCase().includes(q) ||
        s.description.toLowerCase().includes(q) ||
        s.tags?.some((t) => t.toLowerCase().includes(q)));
    return filtered.slice(0, limit ?? filtered.length);
}
/** Fetch SKILL.md content and list of sibling files for a specific skill. */
export async function fetchAnthropicSkillContent(skillName) {
    const dirContents = await fetchGitHub(`/repos/${REPO_OWNER}/${REPO_NAME}/contents/${SKILLS_DIR}/${skillName}`);
    if (!Array.isArray(dirContents)) {
        return null;
    }
    const items = dirContents;
    const skillMdItem = items.find((f) => f.name === 'SKILL.md' && f.type === 'file');
    if (!skillMdItem) {
        return null;
    }
    const skillMdRaw = await fetchGitHub(`/repos/${REPO_OWNER}/${REPO_NAME}/contents/${SKILLS_DIR}/${skillName}/SKILL.md`);
    if (!skillMdRaw ||
        typeof skillMdRaw !== 'object' ||
        !('content' in skillMdRaw) ||
        typeof skillMdRaw.content !== 'string') {
        return null;
    }
    const rawContent = skillMdRaw.content;
    const skillMd = Buffer.from(rawContent.replace(/\n/g, ''), 'base64').toString('utf-8');
    const files = items.filter((f) => f.type === 'file' && f.name !== 'SKILL.md').map((f) => f.name);
    return { skillMd, files };
}
/** Invalidate the in-memory skill list cache (useful for tests). */
export function clearAnthropicCache() {
    skillCache = null;
}
//# sourceMappingURL=anthropic-adapter.js.map