repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/the-system/__tests__/bundle-slot-tool.test.ts
Rawimport 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/);
});
});