Merge remote-tracking branch 'origin/farm/39009a49/fix-extension-validation-shims'

This commit is contained in:
can1357
2026-06-18 04:52:33 +02:00
7 changed files with 296 additions and 23 deletions
@@ -88,6 +88,29 @@ describe("legacy-pi @(scope)/pi-ai root `Type` remap (issue #1437)", () => {
expect(loaded.zodObj.safeParse({ name: "ok" }).success).toBe(true);
expect(loaded.zodObj.safeParse({}).success).toBe(false);
});
it("preserves legacy StringEnum root imports as plain string enum schemas", async () => {
const entry = await writeFixtureExtension(
[
'import { StringEnum } from "@earendil-works/pi-ai";',
'export const schema = StringEnum(["upstream", "downstream"] as const, { default: "upstream" });',
"export const wireSchema = JSON.parse(JSON.stringify(schema));",
].join("\n"),
);
const loaded = (await loadLegacyPiModule(entry)) as {
schema: { safeParse: (input: unknown) => { success: boolean } };
wireSchema: { type?: string; enum?: string[]; default?: string; anyOf?: unknown };
};
expect(loaded.schema.safeParse("downstream").success).toBe(true);
expect(loaded.schema.safeParse("sideways").success).toBe(false);
expect(loaded.wireSchema).toEqual({
type: "string",
enum: ["upstream", "downstream"],
default: "upstream",
});
expect(loaded.wireSchema.anyOf).toBeUndefined();
});
it("does not redirect subpath imports such as @oh-my-pi/pi-ai/utils/schema", async () => {
const entry = await writeFixtureExtension(
@@ -124,6 +147,68 @@ describe("legacy pi package root remaps (issue #1474)", () => {
expect(loaded.loadedVersion).toMatch(/^\d+\.\d+\.\d+/);
});
it("preserves legacy defineTool root imports and usable coding tools", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "omp-legacy-coding-tools-"));
tempRoots.push(dir);
await fs.writeFile(path.join(dir, "sample.txt"), "legacy read body", "utf8");
const entry = path.join(dir, "index.ts");
await fs.writeFile(
entry,
[
'import { dirname } from "node:path";',
'import { fileURLToPath } from "node:url";',
'import { createCodingTools, defineTool, Type } from "@earendil-works/pi-coding-agent";',
"const definition = {",
'\tname: "legacy_define_tool",',
'\tlabel: "Legacy Define Tool",',
'\tdescription: "legacy helper probe",',
"\tparameters: Type.Object({}),",
'\texecute: async () => ({ content: [{ type: "text", text: "ok" }] }),',
"};",
"const cwd = dirname(fileURLToPath(import.meta.url));",
"const codingTools = createCodingTools(cwd);",
"const readTool = codingTools.find(tool => tool.name === 'read');",
"export const tool = defineTool(definition);",
"export const sameReference = tool === definition;",
"export const codingToolNames = codingTools.map(tool => tool.name);",
"export const readResult = await readTool?.execute('legacy-read', { path: 'sample.txt' });",
].join("\n"),
"utf8",
);
const loaded = (await loadLegacyPiModule(entry)) as {
tool: { name: string; parameters: { safeParse: (input: unknown) => { success: boolean } } };
sameReference: boolean;
codingToolNames: string[];
readResult: { content: Array<{ type: string; text?: string }> };
};
expect(loaded.sameReference).toBe(true);
expect(loaded.tool.name).toBe("legacy_define_tool");
expect(loaded.codingToolNames).toEqual(["read", "bash", "edit", "write"]);
expect(loaded.readResult.content[0]?.text).toContain("legacy read body");
});
it("preserves legacy frontmatter helper root imports", async () => {
const entry = await writeFixtureExtension(
[
'import { parseFrontmatter, stripFrontmatter } from "@earendil-works/pi-coding-agent";',
"const content = ['---', 'name: demo', '---', '# Body'].join('\\n');",
"export const parsed = parseFrontmatter(content);",
"export const stripped = stripFrontmatter(content);",
].join("\n"),
);
const loaded = (await loadLegacyPiModule(entry)) as {
parsed: { frontmatter: { name?: string }; body: string };
stripped: string;
};
expect(loaded.parsed.frontmatter.name).toBe("demo");
expect(loaded.parsed.body).toBe("# Body");
expect(loaded.stripped).toBe("# Body");
});
it("falls back to legacy-scoped subpath peers for direct plugin imports", async () => {
const realResolveSync = Bun.resolveSync.bind(Bun);
vi.spyOn(Bun, "resolveSync").mockImplementation((specifier: string, from: string) => {
@@ -31,7 +31,7 @@ async function writeFixtureExtension(source: string): Promise<string> {
return entry;
}
describe("legacy-pi @sinclair/typebox remap", () => {
describe("legacy-pi TypeBox remap", () => {
it("redirects bare @sinclair/typebox imports inside legacy extensions to the in-repo shim", async () => {
const entry = await writeFixtureExtension(
[
@@ -50,4 +50,23 @@ describe("legacy-pi @sinclair/typebox remap", () => {
expect(loaded.objectSchema.safeParse({ name: "ok" }).success).toBe(true);
expect(loaded.objectSchema.safeParse({ name: "ok", extra: 1 }).success).toBe(false);
});
it("redirects bare typebox imports inside legacy extensions to the in-repo shim", async () => {
const entry = await writeFixtureExtension(
[
'import { Type } from "typebox";',
"export const probe = Type;",
"export const enumSchema = Type.Enum(['upstream', 'downstream']);",
].join("\n"),
);
const loaded = (await loadLegacyPiModule(entry)) as {
probe: typeof TypeBoxShimType;
enumSchema: { safeParse: (input: unknown) => { success: boolean } };
};
expect(loaded.probe).toBe(TypeBoxShimType);
expect(loaded.enumSchema.safeParse("upstream").success).toBe(true);
expect(loaded.enumSchema.safeParse("sideways").success).toBe(false);
});
});