import fs from "node:fs/promises";
import path from "node:path";
import { LISA_HOME } from "../paths.js";
import { ensureDir, pathExists } from "../fs-utils.js";
import { parseFrontmatter } from "../skills/frontmatter.js";
const PLUGINS_DIR = path.join(LISA_HOME, "plugins");
export async function loadAllPlugins() {
    await ensureDir(PLUGINS_DIR);
    const entries = await fs.readdir(PLUGINS_DIR, { withFileTypes: true });
    const out = [];
    for (const entry of entries) {
        if (!entry.isDirectory() || entry.name.startsWith("."))
            continue;
        const root = path.join(PLUGINS_DIR, entry.name);
        try {
            const plugin = await loadPlugin(root);
            out.push(plugin);
        }
        catch {
            // skip unparseable plugins
        }
    }
    return out;
}
async function loadPlugin(root) {
    const manifestPath = path.join(root, ".lisa-plugin", "plugin.json");
    let manifest = {
        name: path.basename(root),
    };
    if (await pathExists(manifestPath)) {
        const raw = await fs.readFile(manifestPath, "utf8");
        manifest = JSON.parse(raw);
    }
    const [commands, agents, skills, hooks, mcpServers] = await Promise.all([
        loadCommands(path.join(root, "commands")),
        loadAgents(path.join(root, "agents")),
        loadSkills(path.join(root, "skills")),
        loadHooks(path.join(root, "hooks")),
        loadMcp(root),
    ]);
    return { manifest, root, commands, agents, skills, hooks, mcpServers };
}
async function loadCommands(dir) {
    if (!(await pathExists(dir)))
        return [];
    const entries = await fs.readdir(dir);
    const out = [];
    for (const entry of entries) {
        if (!entry.endsWith(".md"))
            continue;
        const file = path.join(dir, entry);
        const raw = await fs.readFile(file, "utf8");
        const parsed = parseFrontmatter(raw);
        const description = parsed?.frontmatter?.["description"];
        const argumentHint = parsed?.frontmatter?.["argument-hint"];
        out.push({
            name: path.basename(entry, ".md"),
            description: typeof description === "string"
                ? description
                : "(no description)",
            argumentHint: typeof argumentHint === "string" ? argumentHint : undefined,
            body: parsed?.body ?? raw,
            source: file,
        });
    }
    return out;
}
async function loadAgents(dir) {
    if (!(await pathExists(dir)))
        return [];
    const entries = await fs.readdir(dir);
    const out = [];
    for (const entry of entries) {
        if (!entry.endsWith(".md"))
            continue;
        const file = path.join(dir, entry);
        const raw = await fs.readFile(file, "utf8");
        const parsed = parseFrontmatter(raw);
        if (!parsed)
            continue;
        const fm = parsed.frontmatter;
        out.push({
            name: typeof fm.name === "string" ? fm.name : path.basename(entry, ".md"),
            description: typeof fm.description === "string" ? fm.description : "(no description)",
            body: parsed.body,
            source: file,
            tools: typeof fm.tools === "string"
                ? fm.tools.split(",").map((s) => s.trim())
                : undefined,
            model: typeof fm.model === "string" ? fm.model : undefined,
        });
    }
    return out;
}
async function loadSkills(dir) {
    if (!(await pathExists(dir)))
        return [];
    const entries = await fs.readdir(dir, { withFileTypes: true });
    const out = [];
    for (const entry of entries) {
        if (!entry.isDirectory())
            continue;
        const skillFile = path.join(dir, entry.name, "SKILL.md");
        if (!(await pathExists(skillFile)))
            continue;
        const raw = await fs.readFile(skillFile, "utf8");
        const parsed = parseFrontmatter(raw);
        if (!parsed)
            continue;
        out.push({ ...parsed, path: skillFile });
    }
    return out;
}
async function loadHooks(dir) {
    const file = path.join(dir, "hooks.json");
    if (!(await pathExists(file)))
        return [];
    const raw = await fs.readFile(file, "utf8");
    const parsed = JSON.parse(raw);
    const out = [];
    for (const [event, group] of Object.entries(parsed.hooks ?? {})) {
        if (!Array.isArray(group))
            continue;
        for (const item of group) {
            const matcher = item.matcher;
            const hooks = item.hooks ?? [];
            for (const h of hooks) {
                const hookObj = h;
                if (hookObj.type !== "command" || !hookObj.command)
                    continue;
                out.push({
                    event: event,
                    matcher,
                    command: hookObj.command,
                    timeout_ms: hookObj.timeout,
                });
            }
        }
    }
    return out;
}
async function loadMcp(root) {
    const file = path.join(root, ".mcp.json");
    if (!(await pathExists(file)))
        return [];
    const raw = await fs.readFile(file, "utf8");
    const parsed = JSON.parse(raw);
    return Object.entries(parsed.mcpServers ?? {}).map(([name, spec]) => ({
        name,
        command: spec.command,
        args: spec.args,
        env: spec.env,
    }));
}
export const PLUGINS_ROOT = PLUGINS_DIR;
//# sourceMappingURL=loader.js.map