import { RegistryError } from './types.js';
const DEFAULT_MARKETPLACES = [
    { owner: 'anthropics', repo: 'claude-plugins-official' },
    { owner: 'anthropics', repo: 'skills' }
];
async function fetchMarketplace(mp) {
    const ref = mp.ref ?? 'HEAD';
    const url = `https://raw.githubusercontent.com/${mp.owner}/${mp.repo}/${ref}/.claude-plugin/marketplace.json`;
    const res = await fetch(url, { headers: { accept: 'application/json' } });
    if (!res.ok) {
        throw new RegistryError(`Marketplace fetch failed for ${mp.owner}/${mp.repo}: ${res.status}`);
    }
    return (await res.json());
}
async function fetchFile(owner, repo, ref, path) {
    const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path.replace(/^\//, '')}`;
    const res = await fetch(url);
    if (!res.ok)
        throw new RegistryError(`File fetch failed: ${url} ${res.status}`);
    return res.text();
}
export class ClaudeMarketplaceAdapter {
    marketplaces;
    descriptor = {
        id: 'claude-marketplace',
        label: 'Claude Plugin Marketplaces',
        kinds: ['skill', 'mcp'],
        requiresAuth: false,
        enabled: true
    };
    constructor(marketplaces = DEFAULT_MARKETPLACES) {
        this.marketplaces = marketplaces;
    }
    async search(query, limit = 100) {
        const q = query.trim().toLowerCase();
        const entries = [];
        for (const mp of this.marketplaces) {
            let manifest;
            try {
                manifest = await fetchMarketplace(mp);
            }
            catch (error) {
                if (error instanceof RegistryError)
                    continue;
                throw error;
            }
            for (const plugin of manifest.plugins ?? []) {
                if (q && !plugin.name.toLowerCase().includes(q) && !(plugin.description ?? '').toLowerCase().includes(q)) {
                    continue;
                }
                const skillCount = plugin.skills?.length ?? 0;
                const mcpCount = Object.keys(plugin.mcpServers ?? {}).length;
                if (skillCount === 0 && mcpCount === 0)
                    continue;
                if (skillCount > 0) {
                    for (const skill of plugin.skills) {
                        entries.push({
                            id: `${mp.owner}/${mp.repo}#${plugin.name}::${skill.name}`,
                            source: 'claude-marketplace',
                            kind: 'skill',
                            name: skill.name,
                            title: plugin.name,
                            description: skill.description ?? plugin.description ?? null,
                            version: plugin.version ?? null,
                            repository: `https://github.com/${mp.owner}/${mp.repo}`,
                            homepage: null,
                            installManifest: {
                                marketplace: mp,
                                plugin,
                                skill
                            }
                        });
                    }
                }
                if (mcpCount > 0) {
                    for (const [name, server] of Object.entries(plugin.mcpServers ?? {})) {
                        entries.push({
                            id: `${mp.owner}/${mp.repo}#${plugin.name}::mcp::${name}`,
                            source: 'claude-marketplace',
                            kind: 'mcp',
                            name,
                            title: plugin.name,
                            description: plugin.description ?? null,
                            version: plugin.version ?? null,
                            repository: `https://github.com/${mp.owner}/${mp.repo}`,
                            homepage: null,
                            installManifest: {
                                marketplace: mp,
                                plugin,
                                mcpServer: { name, ...server }
                            }
                        });
                    }
                }
                if (entries.length >= limit)
                    break;
            }
            if (entries.length >= limit)
                break;
        }
        return entries.slice(0, limit);
    }
    async resolveInstall(entry) {
        const manifest = entry.installManifest;
        const { marketplace, plugin } = manifest;
        const ref = plugin.source?.ref ?? marketplace.ref ?? 'HEAD';
        const sourceOwner = (() => {
            const repo = plugin.source?.repo;
            if (!repo)
                return marketplace;
            const m = repo.match(/^(?:https?:\/\/github\.com\/)?([^/]+)\/([^/.]+)/);
            if (!m)
                return marketplace;
            return { owner: m[1], repo: m[2], ref };
        })();
        if (entry.kind === 'skill' && manifest.skill) {
            const skillPath = manifest.skill.path
                ? `${manifest.skill.path}/SKILL.md`
                : `${manifest.skill.name}/SKILL.md`;
            const text = await fetchFile(sourceOwner.owner, sourceOwner.repo, ref, skillPath);
            return {
                name: manifest.skill.name,
                skillMarkdown: text,
                source: {
                    registry: 'claude-marketplace',
                    ref: `${sourceOwner.owner}/${sourceOwner.repo}@${ref}`,
                    version: plugin.version ?? null,
                    url: `https://github.com/${sourceOwner.owner}/${sourceOwner.repo}`
                }
            };
        }
        if (entry.kind === 'mcp' && manifest.mcpServer) {
            const server = manifest.mcpServer;
            const isHttp = server.type === 'http' || server.type === 'sse' || typeof server.url === 'string';
            return {
                name: server.name,
                transport: isHttp ? 'http' : 'stdio',
                command: server.command ?? undefined,
                args: server.args ?? [],
                env: server.env ?? {},
                url: server.url ?? undefined,
                headers: server.headers ?? {},
                source: {
                    registry: 'claude-marketplace',
                    ref: `${sourceOwner.owner}/${sourceOwner.repo}@${ref}`,
                    version: plugin.version ?? null,
                    url: `https://github.com/${sourceOwner.owner}/${sourceOwner.repo}`
                }
            };
        }
        throw new RegistryError('Unsupported manifest entry', 422);
    }
}
export const claudeMarketplaceAdapter = new ClaudeMarketplaceAdapter();
//# sourceMappingURL=claude-marketplace.js.map