// skill-load surfaces `requiredInputs` to the agent.
//
// Tests the frontmatter parser (`parseRequiredInputs`) and the
// integration contract: when a SKILL.md declares `requiredInputs:`, the
// body the skill-load handler returns to the agent must carry a
// `<!-- skill-input-contract requiredInputs=... -->` marker that
// `parseClaudeStream` can grep without re-parsing YAML. This pair is the
// writer; the stream-parser is the reader.
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { loadSkill, parseRequiredInputs } from "../skill-resolution.js";
let root;
beforeEach(() => {
    root = mkdtempSync(join(tmpdir(), "skill-load-required-inputs-"));
});
afterEach(() => {
    rmSync(root, { recursive: true, force: false });
});
function seedSkill(plugin, skill, body) {
    const dir = join(root, "plugins", plugin, "skills", skill);
    mkdirSync(dir, { recursive: true });
    writeFileSync(join(dir, "SKILL.md"), body);
}
describe("parseRequiredInputs", () => {
    it("property-brochure-shaped frontmatter parses one slot with two alternatives", () => {
        const body = [
            "---",
            "name: property-brochure",
            "description: Create A4 brochures",
            "requiredInputs:",
            "  - propertyAssetsDir | listingURL",
            "---",
            "",
            "# Property Brochure",
        ].join("\n");
        expect(parseRequiredInputs(body)).toEqual([["propertyAssetsDir", "listingURL"]]);
    });
    it("make-brochure-shaped frontmatter parses two slots, each with two alternatives", () => {
        const body = [
            "---",
            "name: make-brochure",
            "description: end-to-end brochure",
            "allowed-tools:",
            "  - Bash",
            "  - Read",
            "requiredInputs:",
            "  - agentURL | brandPackDir",
            "  - listingURL | propertyAssetsDir",
            "---",
            "",
            "# make-brochure",
        ].join("\n");
        expect(parseRequiredInputs(body)).toEqual([
            ["agentURL", "brandPackDir"],
            ["listingURL", "propertyAssetsDir"],
        ]);
    });
    it("returns undefined when frontmatter has no requiredInputs key", () => {
        const body = [
            "---",
            "name: plainly",
            "description: Strip AI tells",
            "---",
            "",
            "# Plainly",
        ].join("\n");
        expect(parseRequiredInputs(body)).toBeUndefined();
    });
    it("returns undefined when body has no frontmatter at all", () => {
        expect(parseRequiredInputs("# Just a title\n\nNo frontmatter here.\n")).toBeUndefined();
    });
    it("stops scanning at the next column-0 key (no cross-talk into siblings)", () => {
        const body = [
            "---",
            "name: example",
            "requiredInputs:",
            "  - x | y",
            "allowed-tools:",
            "  - Bash",
            "  - Read",
            "---",
            "",
        ].join("\n");
        expect(parseRequiredInputs(body)).toEqual([["x", "y"]]);
    });
});
describe("loadSkill + parseRequiredInputs integration", () => {
    it("loadSkill returns body verbatim; parseRequiredInputs extracts the declared slots", async () => {
        seedSkill("brochures", "property-brochure", [
            "---",
            "name: property-brochure",
            "description: Create A4 brochures",
            "requiredInputs:",
            "  - propertyAssetsDir | listingURL",
            "---",
            "",
            "# Property Brochure",
        ].join("\n"));
        const outcome = await loadSkill(root, "property-brochure");
        expect(outcome.status).toBe("unique");
        if (outcome.status !== "unique")
            return;
        expect(parseRequiredInputs(outcome.body)).toEqual([
            ["propertyAssetsDir", "listingURL"],
        ]);
    });
    it("loadSkill on a skill without requiredInputs leaves parser at undefined", async () => {
        seedSkill("admin", "plainly", "---\nname: plainly\ndescription: Strip AI tells\n---\n\n# Plainly\n");
        const outcome = await loadSkill(root, "plainly");
        expect(outcome.status).toBe("unique");
        if (outcome.status !== "unique")
            return;
        expect(parseRequiredInputs(outcome.body)).toBeUndefined();
    });
});
describe("skill-input-contract marker shape (writer/reader contract)", () => {
    it("the marker the handler prepends survives JSON round-trip and matches the stream-parser regex", () => {
        // Mirror the regex literal in
        // platform/ui/app/lib/claude-agent/stream-parser.ts.
        const RE = /<!-- skill-input-contract requiredInputs=(\[[^]+?\]) -->/;
        const slots = [["propertyAssetsDir", "listingURL"]];
        const marker = `<!-- skill-input-contract requiredInputs=${JSON.stringify(slots)} -->`;
        const m = marker.match(RE);
        expect(m).not.toBeNull();
        expect(JSON.parse(m[1])).toEqual(slots);
    });
    it("the make-brochure two-slot case also round-trips through the regex", () => {
        const RE = /<!-- skill-input-contract requiredInputs=(\[[^]+?\]) -->/;
        const slots = [
            ["agentURL", "brandPackDir"],
            ["listingURL", "propertyAssetsDir"],
        ];
        const marker = `<!-- skill-input-contract requiredInputs=${JSON.stringify(slots)} -->`;
        const m = marker.match(RE);
        expect(m).not.toBeNull();
        expect(JSON.parse(m[1])).toEqual(slots);
    });
});
//# sourceMappingURL=skill-load-required-inputs.test.js.map