import fs from "node:fs";
import path from "node:path";
import { z } from "zod";
import { tool } from "@anthropic-ai/claude-agent-sdk";
import { getSkillsDir, getUserCatalogDir } from "../config/index.js";
import { getCatalogSourceDir } from "../skills/install.js";
export const MAX_SKILLS = 20;
function readSkillDescription(skillMdPath) {
    if (!fs.existsSync(skillMdPath))
        return "(no description)";
    const raw = fs.readFileSync(skillMdPath, "utf-8");
    const match = /^description:\s*(.+)$/m.exec(raw);
    return match ? match[1] : "(no description)";
}
function countSkills(skillsDir) {
    if (!fs.existsSync(skillsDir))
        return 0;
    return fs.readdirSync(skillsDir, { withFileTypes: true })
        .filter((e) => e.isDirectory()).length;
}
function buildSkillLimitWarning(skillsDir) {
    const count = countSkills(skillsDir);
    if (count >= MAX_SKILLS) {
        return `\n\nWarning: You have ${count} skills installed. Adding more may degrade performance due to increased context usage. Consider removing unused skills first.`;
    }
    return "";
}
export function serializeSkillFrontmatter(description) {
    // JSON strings are valid YAML double-quoted scalars. This keeps descriptions
    // with colons, quotes, backslashes, or newlines from being parsed as mappings.
    return `---\ndescription: ${JSON.stringify(description)}\n---`;
}
function isBuiltinCatalogSkill(skillName) {
    const catalogDir = getCatalogSourceDir();
    if (!catalogDir)
        return false;
    return fs.existsSync(path.join(catalogDir, skillName, "SKILL.md"));
}
/**
 * Collect all catalog skills from both the built-in catalog and the user catalog.
 * Returns a map of skill name to source directory path.
 */
function collectCatalogSkills() {
    const result = new Map();
    const builtinDir = getCatalogSourceDir();
    if (builtinDir && fs.existsSync(builtinDir)) {
        for (const e of fs.readdirSync(builtinDir, { withFileTypes: true })) {
            if (e.isDirectory() && fs.existsSync(path.join(builtinDir, e.name, "SKILL.md"))) {
                result.set(e.name, path.join(builtinDir, e.name));
            }
        }
    }
    const userDir = getUserCatalogDir();
    if (fs.existsSync(userDir)) {
        for (const e of fs.readdirSync(userDir, { withFileTypes: true })) {
            if (e.isDirectory() && fs.existsSync(path.join(userDir, e.name, "SKILL.md"))) {
                if (!result.has(e.name)) {
                    result.set(e.name, path.join(userDir, e.name));
                }
            }
        }
    }
    return result;
}
export const manageSkillsTool = tool("manage_skills", "Manage your skills. Skills are SKILL.md files that the SDK discovers and you can invoke via the Skill tool when relevant. You can create, update, list, uninstall (delete moves user-created skills to catalog), browse the catalog, and install catalog skills.", {
    action: z
        .enum(["create", "update", "delete", "list", "list_catalog", "install_catalog"])
        .describe("Action to perform"),
    name: z
        .string()
        .regex(/^[a-z0-9-]+$/)
        .optional()
        .describe("Skill name (required for create, update, delete, install_catalog)"),
    description: z
        .string()
        .optional()
        .describe("Short description of when this skill should be used (required for create/update)"),
    content: z
        .string()
        .optional()
        .describe("Skill instructions in Markdown (required for create/update)"),
}, (args) => {
    try {
        const skillsDir = getSkillsDir();
        switch (args.action) {
            case "create":
            case "update": {
                if (!args.name || !args.description || !args.content) {
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: "Error: name, description, and content are required for create/update.",
                            }],
                        isError: true,
                    });
                }
                const skillDir = path.join(skillsDir, args.name);
                if (!fs.existsSync(skillDir)) {
                    fs.mkdirSync(skillDir, { recursive: true });
                }
                const filePath = path.join(skillDir, "SKILL.md");
                const existed = fs.existsSync(filePath);
                const skillContent = `${serializeSkillFrontmatter(args.description)}\n\n${args.content}\n`;
                fs.writeFileSync(filePath, skillContent, "utf-8");
                const resultText = `Skill "${args.name}" ${existed ? "updated" : "created"} at ${filePath}.${existed ? "" : buildSkillLimitWarning(skillsDir)}`;
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: resultText,
                        }],
                });
            }
            case "delete": {
                if (!args.name) {
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: "Error: name is required for delete.",
                            }],
                        isError: true,
                    });
                }
                const skillDir = path.join(skillsDir, args.name);
                if (!fs.existsSync(skillDir)) {
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: `Skill "${args.name}" not found.`,
                            }],
                        isError: true,
                    });
                }
                if (isBuiltinCatalogSkill(args.name)) {
                    fs.rmSync(skillDir, { recursive: true });
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: `Skill "${args.name}" uninstalled. It remains available in the built-in catalog — use install_catalog to reinstall.`,
                            }],
                    });
                }
                const userCatalogDir = getUserCatalogDir();
                if (!fs.existsSync(userCatalogDir)) {
                    fs.mkdirSync(userCatalogDir, { recursive: true });
                }
                const archiveDir = path.join(userCatalogDir, args.name);
                if (fs.existsSync(archiveDir)) {
                    fs.rmSync(archiveDir, { recursive: true });
                }
                fs.renameSync(skillDir, archiveDir);
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: `Skill "${args.name}" uninstalled and moved to catalog. Use install_catalog to reinstall later.`,
                        }],
                });
            }
            case "list": {
                if (!fs.existsSync(skillsDir)) {
                    return Promise.resolve({
                        content: [{ type: "text", text: "No skills directory found." }],
                    });
                }
                const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
                const skills = entries.filter((e) => e.isDirectory());
                if (skills.length === 0) {
                    return Promise.resolve({
                        content: [{ type: "text", text: "No skills installed." }],
                    });
                }
                const lines = skills.map((dir) => {
                    const skillFile = path.join(skillsDir, dir.name, "SKILL.md");
                    return `- ${dir.name}: ${readSkillDescription(skillFile)}`;
                });
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: `${skills.length} skill(s):\n${lines.join("\n")}`,
                        }],
                });
            }
            case "list_catalog": {
                const allCatalogSkills = collectCatalogSkills();
                if (allCatalogSkills.size === 0) {
                    return Promise.resolve({
                        content: [{ type: "text", text: "No catalog skills found." }],
                    });
                }
                const installedSet = new Set();
                if (fs.existsSync(skillsDir)) {
                    for (const e of fs.readdirSync(skillsDir, { withFileTypes: true })) {
                        if (e.isDirectory())
                            installedSet.add(e.name);
                    }
                }
                const lines = [];
                for (const [name, sourceDir] of allCatalogSkills) {
                    const skillFile = path.join(sourceDir, "SKILL.md");
                    const installed = installedSet.has(name) ? " [installed]" : "";
                    const isUserSkill = sourceDir.startsWith(getUserCatalogDir());
                    const origin = isUserSkill ? " (user-created)" : "";
                    lines.push(`- ${name}${installed}${origin}: ${readSkillDescription(skillFile)}`);
                }
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: `${allCatalogSkills.size} catalog skill(s):\n${lines.join("\n")}`,
                        }],
                });
            }
            case "install_catalog": {
                if (!args.name) {
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: "Error: name is required for install_catalog.",
                            }],
                        isError: true,
                    });
                }
                const allCatalog = collectCatalogSkills();
                const catalogSkillDir = allCatalog.get(args.name);
                if (!catalogSkillDir) {
                    return Promise.resolve({
                        content: [{
                                type: "text",
                                text: `Catalog skill "${args.name}" not found. Use list_catalog to see available skills.`,
                            }],
                        isError: true,
                    });
                }
                const targetSkillDir = path.join(skillsDir, args.name);
                if (!fs.existsSync(targetSkillDir)) {
                    fs.mkdirSync(targetSkillDir, { recursive: true });
                }
                const files = fs.readdirSync(catalogSkillDir);
                for (const file of files) {
                    fs.copyFileSync(path.join(catalogSkillDir, file), path.join(targetSkillDir, file));
                }
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: `Catalog skill "${args.name}" installed. You can now invoke it via the Skill tool.${buildSkillLimitWarning(skillsDir)}`,
                        }],
                });
            }
            default:
                return Promise.resolve({
                    content: [{
                            type: "text",
                            text: `Unknown action: ${args.action}`,
                        }],
                    isError: true,
                });
        }
    }
    catch (err) {
        return Promise.resolve({
            content: [{
                    type: "text",
                    text: `Skill operation failed: ${err instanceof Error ? err.message : String(err)}`,
                }],
            isError: true,
        });
    }
});
//# sourceMappingURL=skill.js.map