99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
/**
|
|
* agents.test.ts — markdown agent-definition loader.
|
|
*/
|
|
import { describe, expect, it } from "bun:test";
|
|
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { extensionRoot, loadAgents } from "../src/agents.js";
|
|
|
|
/** Build an agent markdown file with frontmatter + body. */
|
|
async function writeAgent(
|
|
dir: string,
|
|
file: string,
|
|
name: string,
|
|
body: string,
|
|
tools?: string[],
|
|
): Promise<string> {
|
|
const lines = ["---", `name: ${name}`];
|
|
if (tools) {
|
|
lines.push("allowedTools:");
|
|
for (const t of tools) lines.push(` - ${t}`);
|
|
}
|
|
lines.push("---", body, "");
|
|
await writeFile(join(dir, file), lines.join("\n"), "utf8");
|
|
return join(dir, file);
|
|
}
|
|
|
|
describe("loadAgents", () => {
|
|
it("loads scanner.md and fixer.md shipped with the extension", async () => {
|
|
const agents = await loadAgents();
|
|
expect(agents.has("scanner")).toBe(true);
|
|
expect(agents.has("fixer")).toBe(true);
|
|
const scanner = agents.get("scanner");
|
|
expect(scanner).toBeDefined();
|
|
expect(scanner?.systemPrompt).toContain("scanner");
|
|
expect(scanner?.allowedTools).toContain("read");
|
|
expect(scanner?.allowedTools).not.toContain("edit"); // scanner is read-only
|
|
expect(scanner?.sourcePath).toContain("agents/scanner.md");
|
|
const fixer = agents.get("fixer");
|
|
expect(fixer?.allowedTools).toContain("edit");
|
|
});
|
|
|
|
it("extensionRoot resolves to the package directory", () => {
|
|
expect(extensionRoot()).toMatch(/(pygenium|pygienium)$/);
|
|
});
|
|
|
|
it("project-local agents override the extension's by name", async () => {
|
|
const cwd = await mkdtemp(join(tmpdir(), "pygium-agents-"));
|
|
try {
|
|
await mkdir(join(cwd, "agents"));
|
|
const path = await writeAgent(
|
|
join(cwd, "agents"),
|
|
"scanner.md",
|
|
"scanner",
|
|
"Project-tuned scanner prompt.",
|
|
["read", "grep", "find", "edit"],
|
|
);
|
|
const agents = await loadAgents({ cwd });
|
|
const scanner = agents.get("scanner");
|
|
expect(scanner?.systemPrompt).toContain("Project-tuned");
|
|
expect(scanner?.allowedTools).toContain("edit"); // repo override widens tools
|
|
expect(scanner?.sourcePath).toBe(path);
|
|
// Extension baseline is retained for agents the repo doesn't override.
|
|
expect(agents.get("fixer")).toBeDefined();
|
|
} finally {
|
|
await rm(cwd, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("project-local agents can add brand-new agents", async () => {
|
|
const cwd = await mkdtemp(join(tmpdir(), "pygium-agents-"));
|
|
try {
|
|
await mkdir(join(cwd, "agents"));
|
|
await writeAgent(
|
|
join(cwd, "agents"),
|
|
"judge.md",
|
|
"judge",
|
|
"Scoring judge.",
|
|
);
|
|
const agents = await loadAgents({ cwd });
|
|
expect(agents.has("judge")).toBe(true);
|
|
expect(agents.get("judge")?.systemPrompt).toContain("Scoring judge");
|
|
} finally {
|
|
await rm(cwd, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("a project without agents/ falls back to the extension agents", async () => {
|
|
const cwd = await mkdtemp(join(tmpdir(), "pygium-agents-"));
|
|
try {
|
|
const agents = await loadAgents({ cwd });
|
|
expect(agents.has("scanner")).toBe(true);
|
|
expect(agents.has("fixer")).toBe(true);
|
|
} finally {
|
|
await rm(cwd, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|