Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/the-system/__tests__/bundle-slot-tool.test.ts

Raw
import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { initTheme } from "@earendil-works/pi-coding-agent";
import { afterEach, describe, it } from "vitest";
import { reserveBundleSlot } from "../bundle-slot.ts";
import { createBundleSlotTool } from "../bundle-slot-tool.ts";

const roots: string[] = [];
const project = () => {
	const root = mkdtempSync(path.join(tmpdir(), "system-slot-"));
	roots.push(root);
	for (const directory of ["specs", "phases", "plans", "issues", "research"])
		mkdirSync(path.join(root, ".system", directory), { recursive: true });
	writeFileSync(
		path.join(root, ".system/config.json"),
		'{"prefix":"PX","schemaVersion":0}',
	);
	return root;
};

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

const theme = {
	fg: (_style: string, text: string) => text,
	bold: (text: string) => text,
} as never;
const render = (component: { render(width: number): string[] }) =>
	component.render(120).join("\n");
const renderContext = (expanded: boolean, lastComponent?: unknown) =>
	({ expanded, lastComponent, isError: false }) as never;

describe("system_bundle_slot", () => {
	it("derives semantic slugs and reserves unique IDs on demand", () => {
		const root = project();
		const reserved = new Set<string>();
		const first = reserveBundleSlot(
			root,
			{ type: "phase", title: "Service Übergang" },
			reserved,
		);
		const second = reserveBundleSlot(
			root,
			{ type: "phase", title: "Service Übergang" },
			reserved,
		);
		assert.equal(first.slug, "service-ubergang");
		assert.notEqual(first.id, second.id);
		assert.match(
			first.path,
			/^\.system\/phases\/PX-PHASE-[A-Z0-9_]{8}-service-ubergang\/index\.md$/,
		);
	});

	it("uses concise prompt metadata and Pi-style tool rendering", () => {
		initTheme("default", false);
		const root = project();
		const slot = reserveBundleSlot(root, {
			type: "plan",
			title: "Replace cache invalidation",
		});
		const tool = createBundleSlotTool();
		assert.equal(tool.label, "system_bundle_slot");
		assert.equal(
			tool.description,
			"Reserve a unique System document ID and canonical bundle path from its type and semantic title.",
		);
		assert.equal(
			tool.promptSnippet,
			"Reserve an ID and path for a System bundle",
		);
		assert.notEqual(tool.promptSnippet, tool.description);
		assert.deepEqual(tool.promptGuidelines, [
			"Resolve needed clarifications before calling system_bundle_slot.",
			"Call system_bundle_slot once per required bundle after choosing its final type and title; use each returned ID and path exactly.",
		]);

		assert.ok(tool.renderCall);
		const callComponent = tool.renderCall(
			{ type: "plan", title: slot.title },
			theme,
			renderContext(false),
		);
		assert.match(
			render(callComponent),
			/^system_bundle_slot plan · Replace cache invalidation/,
		);

		assert.ok(tool.renderResult);
		const result = { content: [], details: slot };
		const collapsedComponent = tool.renderResult(
			result,
			{ expanded: false, isPartial: false },
			theme,
			renderContext(false),
		);
		const collapsed = render(collapsedComponent);
		const expandedComponent = tool.renderResult(
			result,
			{ expanded: true, isPartial: false },
			theme,
			renderContext(true, collapsedComponent),
		);
		const expanded = render(expandedComponent);
		assert.equal(expandedComponent, collapsedComponent);
		assert.match(collapsed, new RegExp(`^✓ reserved ${slot.id}`));
		assert.match(collapsed, /replace-cache-invalidation/);
		assert.match(collapsed, /to expand/);
		assert.doesNotMatch(collapsed, new RegExp(slot.path));
		assert.match(expanded, /type plan/);
		assert.match(expanded, /title Replace cache invalidation/);
		assert.ok(expanded.includes(`path ${slot.path}`));

		const errorResult = {
			content: [
				{ type: "text", text: "reservation failed\nEND-RESERVATION-DETAILS" },
			],
			details: {},
		};
		const error = render(
			tool.renderResult(
				errorResult,
				{ expanded: false, isPartial: false },
				theme,
				{ ...renderContext(false), isError: true } as never,
			),
		);
		const expandedError = render(
			tool.renderResult(
				errorResult,
				{ expanded: true, isPartial: false },
				theme,
				{ ...renderContext(true), isError: true } as never,
			),
		);
		assert.match(error, /^reservation failed/);
		assert.match(error, /to expand/);
		assert.doesNotMatch(error, /END-RESERVATION-DETAILS/);
		assert.match(expandedError, /END-RESERVATION-DETAILS/);
	});
});