import test from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const pkg = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8")); function getPackedPaths(cwd: string) { const out = execFileSync("npm", ["pack", "--dry-run", "--json"], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 30_000, }); const parsed = JSON.parse(out); // npm pack --dry-run --json returns array with first entry containing files return (parsed[0]?.files ?? []).map((f: { path: string }) => f.path); } test("package.json exposes pi-web-search as a standalone pi package", () => { assert.equal(pkg.name, "pi-web-search"); assert.equal(pkg.type, "module"); assert.ok(Array.isArray(pkg.keywords)); assert.ok(pkg.keywords.includes("pi-package")); assert.deepEqual(pkg.pi, { extensions: ["./index.ts"], }); // description + repository exact match assert.equal( pkg.description, "Pi extension package that adds web_search and web_fetch tools backed by pluggable providers such as Exa and Tavily." ); assert.deepEqual(pkg.repository, { type: "git", url: "https://gitea.rwiesner.com/pi/pi-web-search", }); assert.equal(pkg.peerDependencies["@mariozechner/pi-coding-agent"], "*"); assert.equal(pkg.peerDependencies["@mariozechner/pi-tui"], "*"); assert.equal(pkg.peerDependencies["@sinclair/typebox"], "*"); assert.ok("exa-js" in (pkg.dependencies ?? {})); assert.ok(!("@sinclair/typebox" in (pkg.dependencies ?? {}))); assert.deepEqual(pkg.files, ["index.ts", "src"]); // ensure manifest does not bundle dependencies by default assert.equal(pkg.bundledDependencies, undefined); }); test("README contains local and git install examples", () => { const readme = readFileSync(resolve(packageRoot, "README.md"), "utf8"); assert.match(readme, /pi install \/absolute\/path\/to\/web-search/); assert.match(readme, /pi install https:\/\/gitea.rwiesner.com\/pi\/pi-web-search/); }); test("npm pack includes expected assets and excludes .test.ts files", () => { const packedPaths = getPackedPaths(packageRoot); // meaningful pack assertions assert.ok(packedPaths.includes("index.ts"), "index.ts should be included in package"); assert.ok(packedPaths.includes("src/runtime.ts"), "src/runtime.ts should be included in package"); assert.ok(packedPaths.includes("src/tools/web-search.ts"), "src/tools/web-search.ts should be included in package"); assert.ok(packedPaths.includes("src/tools/web-fetch.ts"), "src/tools/web-fetch.ts should be included in package"); // no test files packed assert.deepEqual(packedPaths.filter((p) => p.endsWith(".test.ts")), []); });