Ctrl K
ComunidadGuías…

server/bot-package.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { describe, expect, it } from "vitest";

import { parseBotPackage, renderBotPackageMarkdown } from "./bot-package.ts";
import { memberFromAgent } from "./package-import.ts";

const validPackage: any = {
  format: "openmaus.package",
  version: 1,
  package: {
    id: "research-desk",
    release: "1.0.0",
    name: "Research Desk",
    tagline: "Turn a question into a sourced brief.",
    summary: "A small research team.",
    category: "Research",
    author: { name: "OpenMausBot" },
    license: "MIT",
    outcomes: ["Produce a sourced brief."],
    setupMinutes: 3,
    requirements: { apps: [], capabilities: [] },
    agents: [
      {
        key: "lead",
        name: "Ada",
        title: "Research Lead",
        description: "Own the brief.",
        appearance: { color: "purple" },
        playbooks: ["source-check"],
        approvalMode: "full",
        autoApprove: true,
      },
    ],
    chiefOfStaff: "lead",
    rooms: [
      {
        key: "desk",
        name: "Research Desk",
        members: ["lead"],
        bulletin: "Cite sources.",
        defaultResponder: { kind: "agent", agent: "lead" },
      },
    ],
    playbooks: [
      {
        key: "source-check",
        name: "Source Check",
        summary: "Verify sources.",
        triggers: ["research brief"],
        instructions: "Separate facts from inference.",
      },
    ],
  },
};

describe("bot packages", () => {
  const portableSkill = {
    name: "source-check",
    description: "Check sources before writing.",
    source: "conversation:source-check",
    instructions: "---\nname: source-check\ndescription: Check sources before writing.\n---\n\n# Source check\n",
  };

  it("round-trips portable skills and rejects dangling or mismatched references", () => {
    const withSkill = {
      ...validPackage,
      package: {
        ...validPackage.package,
        agents: [{ ...validPackage.package.agents[0], skills: [portableSkill.name] }],
        skills: { version: 1, entries: [portableSkill] },
      },
    };
    const parsed = parseBotPackage(withSkill);
    expect(parsed.package.agents[0]?.skills).toEqual(["source-check"]);
    expect(parseBotPackage(renderBotPackageMarkdown(parsed)).package.skills?.entries).toEqual([portableSkill]);
    expect(() => parseBotPackage({
      ...withSkill,
      package: { ...withSkill.package, agents: [{ ...withSkill.package.agents[0], skills: ["missing"] }] },
    })).toThrow("unknown skill");
    expect(() => parseBotPackage({
      ...withSkill,
      package: { ...withSkill.package, skills: { version: 1, entries: [{ ...portableSkill, description: "Different" }] } },
    })).toThrow("does not match its description");
  });

  it("round-trips optional soul through Markdown and the import persona, with the profile byte cap", () => {
    const input = structuredClone(validPackage);
    const soul = "  Preserve precise instructions. 🐭\n";
    input.package.agents[0].soul = soul;
    const parsed = parseBotPackage(renderBotPackageMarkdown(parseBotPackage(input)));
    expect(memberFromAgent(parsed.package.agents[0]).soul).toBe(soul);
    input.package.agents[0].soul = "🐭".repeat(6_001);
    expect(() => parseBotPackage(input)).toThrow("24000 bytes");
  });
  it.each([
    { name: "../escape" },
    { instructions: "not frontmatter" },
    { source: "/private/skill" },
    { source: "file:///private/skill" },
    { license: "not the SKILL.md license" },
    { compatibility: "not the SKILL.md compatibility" },
    { instructions: "---\nname: source-check\ndescription: Check sources before writing.\n---\n" + "🐭".repeat(65_536) },
  ])("rejects invalid portable skill data: %j", (patch) => {
    expect(() => parseBotPackage({
      ...validPackage,
      package: { ...validPackage.package, agents: [{ ...validPackage.package.agents[0], skills: ["source-check"] }],
        skills: { version: 1, entries: [{ ...portableSkill, ...patch }] } },
    })).toThrow();
  });

  it("rejects duplicate, unassigned and excessive packaged skills", () => {
    const document = structuredClone(validPackage);
    document.package.skills = { version: 1, entries: [portableSkill] };
    expect(() => parseBotPackage(document)).toThrow("not referenced");
    document.package.agents[0].skills = ["source-check"];
    document.package.skills.entries.push(portableSkill);
    expect(() => parseBotPackage(document)).toThrow("Duplicate skill");
    document.package.skills.entries = Array(21).fill(portableSkill);
    expect(() => parseBotPackage(document)).toThrow();
  });
  it("refuses to render a skill bundle larger than the Markdown import limit", () => {
    const document = structuredClone(validPackage);
    document.package.agents[0].skills = Array.from({ length: 5 }, (_, i) => `large-${i}`);
    document.package.skills = { version: 1, entries: document.package.agents[0].skills.map((name: string) => ({
      name, description: "Large fixture", instructions: `---\nname: ${name}\ndescription: Large fixture\n---\n${"a".repeat(210_000)}`,
    })) };
    expect(() => renderBotPackageMarkdown(parseBotPackage(document))).toThrow("too large");
  });
  it("parses the complete portable structure and strips authority fields", () => {
    const parsed = parseBotPackage(validPackage);
    expect(parsed.package.rooms![0]?.defaultResponder).toEqual({ kind: "agent", agent: "lead" });
    expect(parsed.package.agents[0]).not.toHaveProperty("approvalMode");
    expect(parsed.package.agents[0]).not.toHaveProperty("autoApprove");
    expect(memberFromAgent(parsed.package.agents[0]!)).toEqual({
      key: "lead",
      name: "Ada",
      title: "Research Lead",
      description: "Own the brief.",
      appearance: { color: "purple" },
    });
  });

  it("round-trips one Chief-of-Staff-readable Markdown playbook", () => {
    const markdown = renderBotPackageMarkdown(parseBotPackage(validPackage));
    expect(markdown).toContain("## Activation");
    expect(markdown).toContain("Give this file to your Chief of Staff");
    expect(markdown).not.toContain("autoApprove");
    expect(markdown).not.toContain("approvalMode");
    expect(parseBotPackage(markdown).package).toMatchObject({
      id: "research-desk",
      chiefOfStaff: "lead",
      agents: [{ key: "lead", name: "Ada" }],
    });
  });

  it("accepts five-minute routine windows and rejects shorter ones", () => {
    const routine = {
      key: "morning-brief",
      name: "Morning brief",
      agent: "lead",
      prompt: "Summarize the overnight queue.",
      runOn: "maus",
      schedule: { type: "daily", time: "09:00", weekdays: [1] },
      durationMinutes: 5,
      enabledAfterInstall: false,
    };
    const document = {
      ...validPackage,
      package: { ...validPackage.package, routines: [routine] },
    };

    expect(parseBotPackage(document).package.routines?.[0]?.durationMinutes).toBe(5);
    expect(() => parseBotPackage({
      ...document,
      package: {
        ...document.package,
        routines: [{ ...routine, durationMinutes: 4 }],
      },
    })).toThrow(/expected number to be >=5/);
  });

  it("round-trips monthly cron in JSON and Markdown without enabling imported routines", () => {
    const schedule = { type: "cron", expression: "0 9 1 * *", timeZone: "Asia/Kolkata" };
    const document = {
      ...validPackage,
      package: { ...validPackage.package, routines: [{
        key: "monthly", name: "Monthly report", agent: "lead", prompt: "Prepare the report.",
        runOn: "maus", schedule, durationMinutes: 30, enabledAfterInstall: false,
      }] },
    };
    const parsed = parseBotPackage(document);
    const markdown = renderBotPackageMarkdown(parsed);
    expect(markdown).toContain("Monthly on day 1 at 9:00 India time");
    expect(parseBotPackage(markdown).package.routines?.[0]).toMatchObject({ schedule, enabledAfterInstall: false });
    for (const invalid of [{ ...schedule, expression: "0 9 31 2 *" }, { ...schedule, timeZone: "Invalid/Zone" }]) {
      expect(() => parseBotPackage({ ...document, package: { ...document.package,
        routines: [{ ...document.package.routines[0], schedule: invalid }],
      } })).toThrow();
    }
  });

  it("round-trips interval routine schedules", () => {
    const document = {
      ...validPackage,
      package: {
        ...validPackage.package,
        routines: [{
          key: "frequent-check",
          name: "Frequent check",
          agent: "lead",
          prompt: "Check the queue.",
          runOn: "maus",
          schedule: {
            type: "interval",
            everyMinutes: 15,
            anchorAt: 1_788_254_400_000,
            weekdays: [1, 3, 5],
            window: { start: "09:00", end: "17:00" },
            endsAt: 1_790_843_400_000,
          },
          durationMinutes: 30,
          timeoutMinutes: 20,
          enabledAfterInstall: false,
        }],
      },
    };

    const parsed = parseBotPackage(document);
    expect(parsed.package.routines?.[0]?.schedule).toEqual({
      type: "interval",
      everyMinutes: 15,
      anchorAt: 1_788_254_400_000,
      weekdays: [1, 3, 5],
      window: { start: "09:00", end: "17:00" },
      endsAt: 1_790_843_400_000,
    });
    expect(parsed.package.routines?.[0]?.timeoutMinutes).toBe(20);
    expect(renderBotPackageMarkdown(parsed)).toContain("every 15 minutes");
    expect(renderBotPackageMarkdown(parsed)).toContain("Monday, Wednesday, Friday");
    expect(renderBotPackageMarkdown(parsed)).toContain("09:00–17:00");
    expect(renderBotPackageMarkdown(parsed)).toContain("**Run limit:** 20 minutes");
    expect(() => parseBotPackage({
      ...document,
      package: {
        ...document.package,
        routines: [{
          ...document.package.routines[0],
          schedule: {
            type: "interval",
            everyMinutes: 15,
            anchorAt: Number.MAX_SAFE_INTEGER,
          },
        }],
      },
    })).toThrow();
    expect(() => parseBotPackage({
      ...document,
      package: {
        ...document.package,
        routines: [{
          ...document.package.routines[0],
          schedule: {
            ...document.package.routines[0].schedule,
            weekdays: [1, 1],
          },
        }],
      },
    })).toThrow(/unique weekdays/);
    expect(() => parseBotPackage({
      ...document,
      package: {
        ...document.package,
        routines: [{
          ...document.package.routines[0],
          schedule: {
            ...document.package.routines[0].schedule,
            window: { start: "17:00", end: "09:00" },
          },
        }],
      },
    })).toThrow(/later on the same day/);
  });


  it("rejects dangling agent, room, playbook, chief, and routine references", () => {
    expect(() => parseBotPackage({
      ...validPackage,
      package: { ...validPackage.package, chiefOfStaff: "missing" },
    })).toThrow("Unknown Chief of Staff");
    expect(() => parseBotPackage({
      ...validPackage,
      package: {
        ...validPackage.package,
        agents: [{ ...validPackage.package.agents[0], playbooks: ["missing"] }],
      },
    })).toThrow("unknown playbook");
  });
});