Download packages/evals/src/extensions.eval.ts from SaylorTwift/pi: direct link, hf CLI and curl.
- Browser
- Download file 4.9 kB
-
https://huggingface.co/SaylorTwift/pi/resolve/main/packages/evals/src/extensions.eval.ts
- Command line
-
hf download hf://SaylorTwift/pi/packages/evals/src/extensions.eval.ts
-
curl -L -o extensions.eval.ts https://huggingface.co/SaylorTwift/pi/resolve/main/packages/evals/src/extensions.eval.ts
4.9 kB
| import { existsSync, readFileSync } from "node:fs"; | |
| import { join } from "node:path"; | |
| import { describe, expect } from "vitest"; | |
| import { createJudge, describeEval } from "vitest-evals"; | |
| import { createPiCodingAgentHarness, excludePiDocumentation, type PiCodingAgentInput } from "./pi-harness.ts"; | |
| import { recordEvalSourceArtifact } from "./vitest-evals/artifacts.ts"; | |
| import { evalHarnessTable } from "./vitest-evals/harness-table.ts"; | |
| type ExtensionAuthoringOutput = { | |
| response: string; | |
| systemPromptHasGuidelines: boolean; | |
| systemPromptHasPiDocs: boolean; | |
| extensionErrors: Array<{ path: string; error: string }>; | |
| loadedExtensions: Array<{ path: string; tools: string[] }>; | |
| extensionSource: string | null; | |
| }; | |
| function createExtensionAuthoringHarness(name: string, transformSystemPrompt?: (defaultPrompt: string) => string) { | |
| return createPiCodingAgentHarness({ | |
| name, | |
| ...(transformSystemPrompt ? { transformSystemPrompt } : {}), | |
| output: ({ response, session, systemPrompt }) => { | |
| const extensions = session.resourceLoader.getExtensions(); | |
| const extensionPath = join(session.sessionManager.getCwd(), ".pi", "extensions", "hello.ts"); | |
| const extensionSource = existsSync(extensionPath) ? readFileSync(extensionPath, "utf8") : null; | |
| return { | |
| response, | |
| systemPromptHasGuidelines: systemPrompt.includes("\nGuidelines:\n"), | |
| systemPromptHasPiDocs: systemPrompt.includes("\nPi documentation (read only"), | |
| extensionErrors: extensions.errors, | |
| loadedExtensions: extensions.extensions.map(({ path, tools }) => ({ | |
| path, | |
| tools: [...tools.keys()], | |
| })), | |
| extensionSource, | |
| }; | |
| }, | |
| }); | |
| } | |
| const ExtensionAuthoringJudge = createJudge<PiCodingAgentInput, ExtensionAuthoringOutput>( | |
| "ExtensionAuthoringJudge", | |
| ({ output, toolCalls }) => { | |
| const failures: string[] = []; | |
| if (output.extensionSource === null) { | |
| failures.push("generated extension source is unavailable"); | |
| } else { | |
| const imports = Array.from( | |
| output.extensionSource.matchAll(/\b(?:from|import)\s+["']([^"']+)["']/g), | |
| (match) => match[1], | |
| ); | |
| if (!imports.includes("@earendil-works/pi-coding-agent")) { | |
| failures.push("extension does not import the canonical @earendil-works/pi-coding-agent package"); | |
| } | |
| if (imports.some((specifier) => specifier.startsWith("@mariozechner/"))) { | |
| failures.push("extension imports a legacy @mariozechner package"); | |
| } | |
| if (imports.some((specifier) => specifier.startsWith("@sinclair/typebox"))) { | |
| failures.push('extension imports legacy "@sinclair/typebox" instead of "typebox"'); | |
| } | |
| } | |
| if (output.extensionErrors.length > 0) failures.push("extension loader reported errors"); | |
| if (!output.loadedExtensions.some(({ tools }) => tools.includes("hello"))) { | |
| failures.push('no loaded extension registered the "hello" tool'); | |
| } | |
| if ( | |
| !toolCalls.some( | |
| (call) => | |
| call.name === "hello" && | |
| call.status === "ok" && | |
| call.arguments?.name === "Bob" && | |
| call.result === "Hello, Bob!", | |
| ) | |
| ) { | |
| failures.push('no successful hello({ name: "Bob" }) call returned "Hello, Bob!"'); | |
| } | |
| if (output.response !== "Hello, Bob!") failures.push('final response was not exactly "Hello, Bob!"'); | |
| return { | |
| score: failures.length === 0 ? 1 : 0, | |
| metadata: { | |
| rationale: failures.length === 0 ? "Extension authoring workflow completed." : failures.join("; "), | |
| }, | |
| }; | |
| }, | |
| ); | |
| const extensionHarnessTable = evalHarnessTable("Create and use a tool extension", { | |
| baseline: createExtensionAuthoringHarness("system-prompt-without-docs", excludePiDocumentation), | |
| candidate: createExtensionAuthoringHarness("default-system-prompt"), | |
| }); | |
| describe.for(extensionHarnessTable)("$name", ({ harness }) => { | |
| describeEval( | |
| "Create and use a tool extension", | |
| { harness, judges: [ExtensionAuthoringJudge], judgeThreshold: null }, | |
| (it) => { | |
| it("creates and uses the extension", async ({ run, task }) => { | |
| const result = await run([ | |
| { | |
| type: "prompt", | |
| content: | |
| "Create a Pi extension with a hello tool that takes a name and returns a greeting. For example, passing Bob should return `Hello, Bob!`.", | |
| }, | |
| { type: "reload" }, | |
| { | |
| type: "prompt", | |
| content: | |
| "Use the hello tool to greet Bob. Respond with exactly the tool's greeting and nothing else.", | |
| }, | |
| ]); | |
| if (result.output.extensionSource !== null) { | |
| const runId = result.artifacts?.runId; | |
| if (typeof runId !== "string") throw new Error("Pi eval run did not record a run ID."); | |
| await recordEvalSourceArtifact(task, runId, { | |
| name: "hello.ts", | |
| contentType: "text/typescript", | |
| body: result.output.extensionSource, | |
| bodyEncoding: "utf-8", | |
| }); | |
| } | |
| expect(result.output.systemPromptHasGuidelines).toBe(true); | |
| expect(result.output.systemPromptHasPiDocs).toBe(harness.name === "default-system-prompt"); | |
| }); | |
| }, | |
| ); | |
| }); | |