Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

scripts/readme/config.test.ts

Raw
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { extensionDirs, extractSurface, renderSurface } from "./config.ts";

const roots: string[] = [];

afterEach(() => {
	for (const root of roots.splice(0))
		rmSync(root, { recursive: true, force: true });
});

function extension(files: Record<string, string>): string {
	const root = mkdtempSync(join(tmpdir(), "pi-ext-readme-config-"));
	roots.push(root);
	for (const [path, content] of Object.entries(files)) {
		const target = join(root, path);
		mkdirSync(join(target, ".."), { recursive: true });
		writeFileSync(target, content, "utf8");
	}
	return root;
}

describe("README configuration extraction", () => {
	it("resolves declarations, identifiers, factories, and nested defaults", () => {
		const dir = extension({
			"index.ts": `
const DESCRIPTION = "Use "+"the tool";
const tool = { name: "fixture_tool", description: DESCRIPTION };
const unrelated = { key: "not-a-setting", default: true };
function modelSetting(key: string) { return { key, parse: () => undefined, default: undefined }; }
const MODEL = modelSetting("fixture.model");
const OPTIONS = { key: "fixture.options", parse: () => undefined, default: { nested: [1, true] }, env: "FIXTURE_OPTIONS", flag: { name: "fixture-options" } };
export function load(pi: any, ctx: any) {
  pi.registerTool(tool);
  pi.registerCommand("fixture", { description: DESCRIPTION });
  pi.registerFlag("verbose", { type: "boolean", description: DESCRIPTION });
  resolveSetting(pi, ctx, MODEL);
  resolveSetting(pi, ctx, OPTIONS);
}
`,
		});
		const surface = extractSurface(dir);
		expect(surface.diagnostics).toEqual([]);
		expect(surface.tools).toEqual([
			{ name: "fixture_tool", description: "Use the tool" },
		]);
		expect(surface.commands).toEqual([
			{ name: "/fixture", description: "Use the tool" },
		]);
		expect(surface.flags).toEqual([
			{ name: "--verbose", type: "boolean", description: "Use the tool" },
		]);
		expect(surface.settings).toEqual([
			{ key: "fixture.model", default: "`undefined`" },
			{
				key: "fixture.options",
				env: "FIXTURE_OPTIONS",
				flag: "--fixture-options",
				default: "`{ nested: [1, true] }`",
			},
		]);
	});

	it("extracts typed, satisfies, and factory setting declarations without helper diagnostics", () => {
		const dir = extension({
			"index.ts": `
const direct: SettingDeclaration<string> = { key: "direct", parse: text, default: "value" };
const grouped = {
  nested: { key: "grouped", env: "GROUPED", parse: text, default: 42 },
} satisfies Record<string, SettingDeclaration<unknown>>;
const factory = (name: string) => ({ key: "factory." + name, parse: text, default: undefined });
const derived = factory("value");
function helper(declaration: SettingDeclaration<unknown>) { resolveSetting(pi, ctx, declaration); }
resolveSetting(pi, ctx, direct);
resolveSetting(pi, ctx, derived);
`,
		});
		expect(extractSurface(dir).settings).toEqual([
			{ key: "direct", shape: "string", default: '`"value"`' },
			{ key: "factory.value", default: "`undefined`" },
			{ key: "grouped", env: "GROUPED", default: "`42`" },
		]);
		expect(extractSurface(dir).diagnostics).toEqual([]);
	});

	it("renders declared object shapes without treating nested paths as settings", () => {
		const dir = extension({
			"index.ts": `
interface Pair { executor: string; advisor: string }
interface Settings { enabled?: boolean; pairs?: Pair[]; names: "all" | "none" | string[] }
const setting: SettingDeclaration<Settings> = { key: "angel", parse: parse, default: {} };
const omitted: SettingDeclaration<boolean> = { key: "omitted", parse: parse };
resolveSetting(pi, ctx, setting);
resolveSetting(pi, ctx, omitted);
`,
		});
		expect(extractSurface(dir).settings).toMatchObject([
			{
				key: "angel",
				shape:
					'{ enabled?: boolean; pairs?: { executor: string; advisor: string }[]; names: "all" | "none" | string[] }',
				default: "`{}`",
			},
			{ key: "omitted", shape: "boolean", default: "omitted" },
		]);
		const markdown = renderSurface(extractSurface(dir));
		expect(markdown).toContain("| Setting |");
		expect(markdown).not.toContain("Optional |\n");
		expect(markdown).toContain("`angel`");
		expect(markdown).toContain("`angel.pairs`");
		expect(markdown).toContain("`angel.pairs[].executor`");
		expect(markdown).toContain("not literal top-level keys");
	});

	it("extracts Angel's declared nested configuration shape", () => {
		const surface = extractSurface(join(process.cwd(), "extensions", "angel"));
		expect(surface.settings).toMatchObject([
			{
				key: "angel",
				shape:
					'{ pairs?: { executor: string; advisor: string }[]; enabled?: boolean; thinkingLevel?: ThinkingLevel; subagentExtensions?: "none" | "all" | string[] }',
				default: "`{}`",
			},
		]);
		expect(surface.settings[0]?.fields?.map((field) => field.path)).toEqual([
			"angel.pairs",
			"angel.pairs[].executor",
			"angel.pairs[].advisor",
			"angel.enabled",
			"angel.thinkingLevel",
			"angel.subagentExtensions",
		]);
	});

	it("identifies Masks' parser result instead of documenting it as input", () => {
		const surface = extractSurface(join(process.cwd(), "extensions", "masks"));
		expect(surface.settings).toMatchObject([
			{
				key: "masks",
				shape: "parser-defined input (parsed as ParsedMasks)",
				default: "`{ config, errors }`",
			},
		]);
	});

	it("resolves exposure overrides spread from native defineTool declarations", () => {
		const dir = extension({
			"index.ts": `
const tool = defineTool({ name: "wrapped", description: "Native tool" });
pi.registerTool({ ...tool, exposure: "hidden" });
pi.registerTool({ ...tool, exposure: "direct" });
`,
		});
		const surface = extractSurface(dir);
		expect(surface.diagnostics).toEqual([]);
		expect(surface.tools).toEqual([
			{ name: "wrapped", description: "Native tool" },
		]);
	});

	it("handles external tool factories and discovery-derived tools", () => {
		const dir = extension({
			"index.ts": `
import { createTool } from "./tool.js";
pi.registerTool(createTool());
pi.registerTool({ name: catalog.localName, description: skillText });
`,
			"tool.ts": `export function createTool() { return defineTool({ name: "external", description: "First sentence.\\n${"x".repeat(500)}" }); }`,
		});
		const surface = extractSurface(dir);
		expect(surface.diagnostics).toEqual([]);
		expect(surface.tools).toEqual([
			{ name: "external", description: "First sentence." },
		]);
		expect(surface.toolDiscovery).toBe(true);
		expect(renderSurface(surface)).not.toContain("catalog");
	});

	it("covers repository wrappers, loops, factories, and discovery-derived tools", () => {
		const root = join(process.cwd(), "extensions");
		for (const name of extensionDirs(process.cwd()))
			expect(extractSurface(join(root, name)).diagnostics, name).toEqual([]);
		for (const name of [
			"ask",
			"bak",
			"chrome-cdp",
			"decay",
			"firefox-bidi",
			"git-safe",
			"good-job",
			"intellij",
			"notes",
			"the-system",
			"web",
			"ultra",
		])
			expect(extractSurface(join(root, name)).diagnostics).toEqual([]);
		const intellij = extractSurface(join(root, "intellij"));
		expect(intellij.toolDiscovery).toBe(false);
		expect(intellij.tools).toEqual([]);
		expect(intellij.commands).toEqual([]);
		expect(
			extractSurface(join(root, "notes")).settings.map(({ key }) => key),
		).toEqual([
			"notes.addFromEditorShortcut",
			"notes.sendPickerShortcut",
			"notes.toggleShortcut",
		]);
		expect(
			extractSurface(join(root, "web")).settings.find(
				({ key }) => key === "web.zai.mcpUrl",
			)?.env,
		).toBe("ZAI_SEARCH_MCP_URL | ZAI_SEARCH_BASE_URL");
	});

	it("bounds recursive factory resolution", () => {
		const dir = extension({
			"index.ts": `function loop(value: string) { return loop(value); } const setting = loop("x"); resolveSetting(pi, ctx, setting);`,
		});
		expect(extractSurface(dir).diagnostics).toEqual([]);
	});

	it("bounds recursive spread resolution after factory substitution", () => {
		const dir = extension({
			"index.ts": `function wrap() { return { ...wrap() }; } const value = wrap(); resolveSetting(pi, ctx, value);`,
		});
		expect(extractSurface(dir).settings).toEqual([]);
	});

	it("escapes aliases in table cells", () => {
		const surface = extractSurface(
			extension({
				"index.ts": `const setting = { key: "a", parse: String, default: null, env: "A | B" };`,
			}),
		);
		expect(renderSurface(surface)).toContain("`A \\| B`");
	});

	it("reports unresolved registrations and never claims the surface is empty", () => {
		const dir = extension({
			"index.ts":
				"export function load(pi: any, tool: unknown) { pi.registerTool(tool); }\n",
			"demo/ignored.ts":
				'pi.registerTool({ name: "ignored", description: "ignored" });\n',
			"__tests__/ignored.ts":
				'pi.registerTool({ name: "ignored_test", description: "ignored" });\n',
		});
		const surface = extractSurface(dir);
		expect(surface.tools).toEqual([]);
		expect(surface.diagnostics).toEqual([
			"index.ts: tool definition cannot be resolved statically",
		]);
		const markdown = renderSurface(surface);
		expect(markdown).toContain("### Extraction diagnostics");
		expect(markdown).not.toContain(
			"This extension has no commands, tools, flags, or settings.",
		);
	});

	it("reports parse errors instead of silently omitting a source file", () => {
		const dir = extension({ "broken.ts": "export const = ;\n" });
		expect(extractSurface(dir).diagnostics[0]).toMatch(
			/^broken\.ts: parse failed:/,
		);
	});
});