// engine/skill-registry/skillssh-adapter.ts — SPEC-150: skills.sh registry adapter
// Searches the skills.sh catalog API for installable agent skills.
// Uses native fetch() (Node 18+). No external dependencies.
const SKILLS_SH_BASE = 'https://skills.sh';
const CATALOG_PATH = '/api/catalog';
const SEARCH_PATH = '/api/search';
const USER_AGENT = 'Planu/1.0';
const DEFAULT_LIMIT = 10;
/** Build the search URL with query and stack params. */
function buildUrl(query, stack) {
    const hasQuery = query.trim().length > 0;
    const endpoint = hasQuery ? SEARCH_PATH : CATALOG_PATH;
    const url = new URL(`${SKILLS_SH_BASE}${endpoint}`);
    if (hasQuery) {
        url.searchParams.set('q', query);
    }
    if (stack) {
        url.searchParams.set('stack', stack);
    }
    return url.toString();
}
/** Perform a single fetch against skills.sh, returning parsed JSON or null. */
async function fetchSkillsSh(url) {
    try {
        const response = await globalThis.fetch(url, {
            headers: {
                'User-Agent': USER_AGENT,
                Accept: 'application/json',
            },
            signal: AbortSignal.timeout(10_000),
        });
        if (!response.ok) {
            return null;
        }
        return (await response.json());
    }
    catch {
        return null;
    }
}
/** Map a raw skills.sh entry to a unified SkillSearchResult. */
function mapEntry(entry) {
    const slug = entry.owner ? `${entry.owner}/${entry.name ?? ''}` : (entry.name ?? '');
    return {
        name: entry.name ?? slug,
        description: entry.description ?? `Skill: ${entry.name ?? slug}`,
        source: 'skillssh',
        installCommand: entry.installCommand ?? `planu registry install ${slug}`,
        url: entry.url ?? `${SKILLS_SH_BASE}/skills/${slug}`,
        author: entry.author ?? entry.owner,
        installs: entry.installs,
        license: entry.license,
        tags: entry.tags,
        relevanceScore: 0,
    };
}
/**
 * Search skills.sh catalog for skills matching the given query and optional stack.
 * Returns an empty array on network errors or unexpected response shapes.
 */
export async function searchSkillsSh(query, stack, limit) {
    const url = buildUrl(query, stack);
    const data = await fetchSkillsSh(url);
    if (!data) {
        return [];
    }
    const raw = data.skills ?? data.results ?? [];
    const q = query.toLowerCase();
    // Client-side filter when using catalog endpoint (no query param)
    const filtered = query.trim().length > 0
        ? raw
        : raw.filter((entry) => (entry.name ?? '').toLowerCase().includes(q) ||
            (entry.description ?? '').toLowerCase().includes(q) ||
            entry.tags?.some((t) => t.toLowerCase().includes(q)));
    const cap = limit ?? DEFAULT_LIMIT;
    return filtered.slice(0, cap).map(mapEntry);
}
//# sourceMappingURL=skillssh-adapter.js.map