"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.coercePluginScope = coercePluginScope;
exports.runClaudePlugin = runClaudePlugin;
exports.listPlugins = listPlugins;
exports.listMarketplaces = listMarketplaces;
exports.setPluginEnabled = setPluginEnabled;
exports.uninstallPlugin = uninstallPlugin;
exports.installPlugin = installPlugin;
exports.updatePlugin = updatePlugin;
exports.addMarketplace = addMarketplace;
exports.removeMarketplace = removeMarketplace;
exports.updateMarketplace = updateMarketplace;
const node_child_process_1 = require("node:child_process");
const node_util_1 = require("node:util");
const claude_bin_1 = require("../server/claude-bin");
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
// Marketplace refresh and `install`/`update` shell out to git, which can be slow
// on a cold cache. Read commands are sub-second, but share the same ceiling.
const PLUGIN_CMD_TIMEOUT_MS = 120_000;
// The `--available` catalog JSON is ~110KB today (200+ plugins); leave headroom.
const PLUGIN_CMD_MAX_BUFFER = 32 * 1024 * 1024;
const PLUGIN_SCOPES = new Set(["user", "project", "local"]);
/** Narrow an arbitrary string to a PluginScope, or undefined to let the CLI decide. */
function coercePluginScope(value) {
    return value && PLUGIN_SCOPES.has(value) ? value : undefined;
}
/**
 * Run `claude plugin <args...>` non-interactively and capture its output.
 * Never throws on a non-zero exit -- the caller inspects `ok` and `stderr` so
 * CLI errors surface to the UI instead of crashing the route.
 */
async function runClaudePlugin(args) {
    try {
        const { stdout, stderr } = await execFileAsync((0, claude_bin_1.getClaudeBin)(), ["plugin", ...args], {
            encoding: "utf-8",
            timeout: PLUGIN_CMD_TIMEOUT_MS,
            maxBuffer: PLUGIN_CMD_MAX_BUFFER,
        });
        return { ok: true, stdout, stderr };
    }
    catch (err) {
        const e = err;
        return { ok: false, stdout: e.stdout ?? "", stderr: e.stderr || e.message || "plugin command failed" };
    }
}
/** Installed plugins plus the full marketplace catalog, in one CLI call. */
async function listPlugins() {
    const res = await runClaudePlugin(["list", "--available", "--json"]);
    if (!res.ok)
        throw new Error(res.stderr);
    const parsed = JSON.parse(res.stdout);
    return { installed: parsed.installed ?? [], available: parsed.available ?? [] };
}
async function listMarketplaces() {
    const res = await runClaudePlugin(["marketplace", "list", "--json"]);
    if (!res.ok)
        throw new Error(res.stderr);
    return JSON.parse(res.stdout);
}
/** Enable or disable an installed plugin. Scope defaults to the CLI's auto-detect. */
async function setPluginEnabled(id, enabled, scope) {
    const args = [enabled ? "enable" : "disable", id];
    if (scope)
        args.push("-s", scope);
    return runClaudePlugin(args);
}
/** Uninstall a plugin. `-y` is required because cockpit runs the CLI without a TTY. */
async function uninstallPlugin(id, scope) {
    const args = ["uninstall", id, "-y"];
    if (scope)
        args.push("-s", scope);
    return runClaudePlugin(args);
}
/** Install a plugin (id is "name@marketplace"). Clones from the marketplace source, so it can be slow. */
async function installPlugin(id, scope = "user") {
    return runClaudePlugin(["install", id, "-s", scope]);
}
/** Update an installed plugin from its marketplace source. Runs git pull on the plugin's source. */
async function updatePlugin(id) {
    return runClaudePlugin(["update", id]);
}
/** Add a marketplace from a URL, path, or GitHub repo. Clones from the source, so it can be slow. Scope defaults to user. */
async function addMarketplace(source, scope) {
    const args = ["marketplace", "add", source];
    if (scope)
        args.push("--scope", scope);
    return runClaudePlugin(args);
}
/** Remove a configured marketplace. Omitting scope removes its declaration from every settings scope. */
async function removeMarketplace(name, scope) {
    const args = ["marketplace", "remove", name];
    if (scope)
        args.push("--scope", scope);
    return runClaudePlugin(args);
}
/** Update one marketplace from its source, or all when name is omitted. Hits git, so it can be slow. */
async function updateMarketplace(name) {
    const args = ["marketplace", "update"];
    if (name)
        args.push(name);
    return runClaudePlugin(args);
}
