{"_id":"@danypops/pi-extension-harness","_rev":"10-363426bef2eae50bd48c204ea999bd73","name":"@danypops/pi-extension-harness","dist-tags":{"latest":"0.8.3"},"versions":{"0.1.0":{"name":"@danypops/pi-extension-harness","version":"0.1.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.1.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-extension-harness/issues"},"dist":{"shasum":"44de13d26d7cf0c7f9dec154c0053ad677aa05ab","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.1.0.tgz","fileCount":19,"integrity":"sha512-kOUZIkMM6nBCv2xRjYVd+s4g3hkBTwUxRhjj9W+fy6e42x6IqKm4oaQoamiJNldcSTQxnzgHBWUwZpRO/QXPzQ==","signatures":[{"sig":"MEYCIQDhyZrNCh+UpyckUm4670XZGIPvg1K4TRB7vwhko2/cdwIhAIiPBpLP5T+uwtuMavGEUnEmgQFUiQF4ObKG+bqAOlLq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71221},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"3454da3ff99d7a18389d54ef9a1792135b1d2992","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","check":"tsc --noEmit"},"_npmUser":{"name":"danypops","email":"danypops@protonmail.com"},"repository":{"url":"git+https://github.com/DanyPops/pi-extension-harness.git","type":"git"},"_npmVersion":"11.14.1","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jiti":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.7.0","@types/node":"^22.0.0","@earendil-works/pi-coding-agent":"*"},"peerDependencies":{"typebox":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.1.0_1785410028764_0.837178356433042","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@danypops/pi-extension-harness","version":"0.2.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.2.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-extension-harness/issues"},"dist":{"shasum":"357972f59b2e80ed30c4ce88f164ba6e9fefb058","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.2.0.tgz","fileCount":19,"integrity":"sha512-jnyoA6VpQS+OciEPQeRHwvBHKJyaokgA73moSBSvi1DUoCn5sL39P/ooatu8nei/hhJTKkFN2FYlQahvBigznw==","signatures":[{"sig":"MEUCID4L10i0rRqodrMN7zXxPnkI4136X6yuX19Nsc3nqI2oAiEAg5r0PljlkLdpzIl36Xdz/0GTnPknl6Um7D7XptrvVfk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":72943},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"3b87126c7027052790117091e82ee7d4bfa6e48a","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:04860545-e666-4142-b260-d181a59ba3b5"}},"repository":{"url":"git+https://github.com/DanyPops/pi-extension-harness.git","type":"git"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.7.0","@types/node":"^22.0.0","@earendil-works/pi-coding-agent":"*"},"peerDependencies":{"typebox":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.2.0_1785508287771_0.4940402089998843","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@danypops/pi-extension-harness","version":"0.3.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.3.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"9ec4f513f24ce2b1a9fab9cff6ad207fb9de5f25","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.3.0.tgz","fileCount":19,"integrity":"sha512-zAEq6Sh+6mixAVFthzqW1kzspUuskzy+woHUXohk59sfM/7vdVBBie9akQ+t0t6jVFIytw8EMpLA2w5J2FAyJw==","signatures":[{"sig":"MEUCIQDS6S8ubxJ3wrJy5mZs5ekn8pBjqqdkMrGAVssOVqdDIQIgMeMtzx/f5NUjBQlYGlOHUJx6uNdOKmx6zFmlH6QNVwE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":78798},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"22128d68d05fc788e654986e858bb7228ef4406a","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.7.0","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.3.0_1785772362004_0.12837068637706217","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@danypops/pi-extension-harness","version":"0.4.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.4.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"fafc4c78bda4b5dd1af600d5d5b6c4fd1bab0bcd","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.4.0.tgz","fileCount":19,"integrity":"sha512-BzLMi3DH7IelnYMx66rnjb3cgW++xwxmpnlxcZZuaz6LvY++85J8C+qSAG9PEuMeE/mhoItBdNCEWAZASpqeig==","signatures":[{"sig":"MEYCIQD+czYrXZ3RSUiXdtfpiYOXk63wfNMFsrVFxlvO6UT0GAIhALrFwr7J0yE13YYtUbyjp7Rl4Li5pB3ykm7+9H9nUzsr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":79578},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"e50f472fed17e4fadef0e2b494d99e853240b982","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.7.0","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.4.0_1785772715099_0.3503111640358645","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@danypops/pi-extension-harness","version":"0.5.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.5.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"588aec351872b9b002614a9d32de9308c6bfc74c","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.5.0.tgz","fileCount":19,"integrity":"sha512-btxDBxGyQsBMmb9D4DF6qFJ0uvRr9OPusG5WN+ltNuTGpP5xykWtOqHtdxHwoZ/VQyL4ppw40110mpIlLWb3ew==","signatures":[{"sig":"MEUCIQCjgN1Dn/vtb0lpkvqzspxXkaB/1BHB1ctbc5pdezlK3gIgWOCijCjrJuFQMSaRW/Gki8hWJpqy/ybJj/kT1LCODls=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":80415},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"01ca9d81afd3881537676b67aa33bc276e63364e","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.9.2","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.5.0_1786017125027_0.5163402223469549","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@danypops/pi-extension-harness","version":"0.6.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.6.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"4bc5e1835fcca3b28b07fac2cb774e2187c30589","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.6.0.tgz","fileCount":19,"integrity":"sha512-jFnU2UnYSFdRFp/CLL48JdsOvHOssA3Z4RYYzJVPiZz49tFXIQr9tSB5CU5h/pV8nBTmAQT7T2IWXlXHMVkqWg==","signatures":[{"sig":"MEUCIQCpASN3sDT4vvSDZynHM/n+dJQPLPj9V651Gm66HIBRwAIgb6LFLkwA1bF+muEGylG5v0ntqieEzRd2CceC4iOudgc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":88815},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"c0cb79915e15ec1b74157edf5fb1941c9de3725c","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.9.2","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.6.0_1786018051327_0.04610160503953331","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"@danypops/pi-extension-harness","version":"0.6.1","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.6.1","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"8b1fe696947f9f0e4a3afbf95781dcc093691671","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.6.1.tgz","fileCount":19,"integrity":"sha512-AOhTN05dxOVxvp5k050umJMplPdLHoiBJD5CE7DFAixy7Kk+LdShDOnJSCJCEhdpDM4vNrmSQxL9sdw3g6DEiA==","signatures":[{"sig":"MEYCIQDhJ3OvwMP+Z0KYz8fTdJkYRa1/PpofcKc1IfPSXI7uiQIhAPyrCN2myEmACWVqw2mVcq6ZexV+iLJgZYoHx3razYtA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":92995},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"c50205dbdec24f78bf5747787045f8e8340b0844","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.9.2","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.6.1_1786024360299_0.6536806437565683","host":"s3://npm-registry-packages-npm-production"}},"0.6.2":{"name":"@danypops/pi-extension-harness","version":"0.6.2","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.6.2","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"7aa8bc8160115255132a690c09d709595416dc7d","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.6.2.tgz","fileCount":19,"integrity":"sha512-3tzvyhkrnUHaADXMaCbtGX6i3W+KmT+qDWFJhGMGeFt+KBeVvG4VClGCa177X5fPYP2m4EB7ElVJVeAcxibF+Q==","signatures":[{"sig":"MEYCIQDbeCBDfzwYm9R9EccMIJ73n+jUlZMe5jfdDOA/Uw54jwIhAON64iDv592B7NB0wdSjU62BqkWS2PxrOYNHv+oCApSk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.6.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":96701},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"a31f745e9a4a5d53c8311bf78a0b86d64bee9e2d","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.9.2","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.6.2_1786125512487_0.11050899227521382","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@danypops/pi-extension-harness","version":"0.7.0","keywords":["pi","pi-extension","testing","test-harness","jiti"],"license":"MIT","_id":"@danypops/pi-extension-harness@0.7.0","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"dist":{"shasum":"87d7e9d74e9a49e3a77e05f127cfabf42164beea","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.7.0.tgz","fileCount":19,"integrity":"sha512-8kCj0IwzglQqsXKOkQqalp/4gNrIP9NsRizhnRtYi7H4LiX3ccQFxioUXG7aT93F/qn6873U0yifr82Rbft9ng==","signatures":[{"sig":"MEUCIQC8qZsCnfuvzQNKF9kQTc4ZbAlPnE/YPsSakFYIbfryXQIgbUmbH+6WigJ46VkOwkeFcthqUMBsAYeDQ4Agt1in4jQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":99605},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs"},"gitHead":"1fdb4bdb330ddbf953dffe1fd7b0e26320a8d156","scripts":{"test":"bun run build && bun test test","build":"rm -rf dist && tsc -p tsconfig.build.json","format":"biome format --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"repository":{"url":"git+https://github.com/DanyPops/pi-integral.git","type":"git","directory":"packages/pi-extension-harness"},"_npmVersion":"12.0.2","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","directories":{},"_nodeVersion":"24.18.0","dependencies":{"jiti":"^2.7.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.8.0","typebox":"^1.1.0","bun-types":"^1.3.0","typescript":"^5.9.2","@types/node":"^22.0.0","@biomejs/biome":"^2.5.6","typescript-eslint":"^8.65.0","@earendil-works/pi-tui":"*","eslint-plugin-import-x":"^4.17.1","@earendil-works/pi-coding-agent":"*","eslint-import-resolver-typescript":"^4.4.5"},"peerDependencies":{"typebox":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"trustedDependencies":["unrs-resolver"],"_npmOperationalInternal":{"tmp":"tmp/pi-extension-harness_0.7.0_1786363101861_0.017850509571816442","host":"s3://npm-registry-packages-npm-production"}},"0.8.3":{"name":"@danypops/pi-extension-harness","version":"0.8.3","description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","type":"module","license":"MIT","main":"./dist/index.js","sideEffects":false,"types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./mock-pi-cli":"./src/mock-pi-cli.mjs","./package.json":"./package.json"},"keywords":["pi","pi-extension","testing","test-harness","jiti"],"scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit","test":"bun run build && bun test test","format":"biome format --write ."},"dependencies":{"jiti":"^2.7.0"},"peerDependencies":{"@earendil-works/pi-coding-agent":"*","@earendil-works/pi-tui":"*","typebox":"*"},"devDependencies":{"@biomejs/biome":"^2.5.6","@earendil-works/pi-coding-agent":"*","@earendil-works/pi-tui":"*","@types/node":"^22.0.0","bun-types":"^1.3.0","eslint":"^10.8.0","eslint-import-resolver-typescript":"^4.4.5","eslint-plugin-import-x":"^4.17.1","typebox":"^1.1.0","typescript":"^5.9.2","typescript-eslint":"^8.65.0"},"repository":{"type":"git","url":"git+https://github.com/DanyPops/pi-integral.git","directory":"packages/pi-extension-harness"},"homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"publishConfig":{"access":"public"},"trustedDependencies":["unrs-resolver"],"gitHead":"6895932d80ff004d0b82d25f610dbcb4bcdbc0b4","_id":"@danypops/pi-extension-harness@0.8.3","_nodeVersion":"24.19.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-ZZLELYOZQvOWDFUhEVfAFpllaInTWIcMOEhHYheJOp9kidfd1nYpRPAoEsg9/7zHcIBIRMNsoSwI13NZthoQlQ==","shasum":"2d83fc0024e3355b7682dec3a2a4c41d41f0bd4e","tarball":"https://registry.npmjs.org/@danypops/pi-extension-harness/-/pi-extension-harness-0.8.3.tgz","fileCount":19,"unpackedSize":107653,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@danypops%2fpi-extension-harness@0.8.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDK3PRS+R9OXyjy73uh/nZmpgvOqVbYAcZaeJ0WN2BrGAIgBoaQO/bQtRbdv0fZhkmKwx6R9SrZyS/bIq9W4kHYTHM="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53ec6a3c-e8c9-4ae3-a4a6-1de4dd5815c6"}},"directories":{},"maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pi-extension-harness_0.8.3_1787649675250_0.7257577510747075"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-30T11:13:48.512Z","modified":"2026-08-25T09:21:15.845Z","0.1.0":"2026-07-30T11:13:48.926Z","0.2.0":"2026-07-31T14:31:27.983Z","0.3.0":"2026-08-03T15:52:42.157Z","0.4.0":"2026-08-03T15:58:35.275Z","0.5.0":"2026-08-06T11:52:05.184Z","0.6.0":"2026-08-06T12:07:31.495Z","0.6.1":"2026-08-06T13:52:40.451Z","0.6.2":"2026-08-07T17:58:32.619Z","0.7.0":"2026-08-10T11:58:22.011Z","0.8.3":"2026-08-25T09:21:15.425Z"},"bugs":{"url":"https://github.com/DanyPops/pi-integral/issues"},"license":"MIT","homepage":"https://github.com/DanyPops/pi-integral/tree/main/packages/pi-extension-harness#readme","keywords":["pi","pi-extension","testing","test-harness","jiti"],"repository":{"type":"git","url":"git+https://github.com/DanyPops/pi-integral.git","directory":"packages/pi-extension-harness"},"description":"A lightweight, in-process test host for Pi extensions -- unit-test hooks, tools, and commands without booting a real AgentSession, LLM, or I/O. Analogous to ESLint's RuleTester: ships the testing primitives so extension authors stop hand-rolling ad-hoc fa","maintainers":[{"name":"danypops","email":"danypops@protonmail.com"}],"readme":"# @danypops/pi-extension-harness\n\nA lightweight, in-process test host for [Pi](https://pi.dev) extensions.\nAnalogous to ESLint's `RuleTester`: unit-test hooks, tools, and commands\nwithout booting a real `AgentSession`, an LLM, or any I/O — instead of every\nextension author hand-rolling their own fake `ExtensionAPI`.\n\n## Install\n\n```bash\nbun add -d @danypops/pi-extension-harness\n```\n\n## Why this exists\n\nTesting a Pi extension usually means one of:\n\n- A hand-rolled fake `ExtensionAPI` object, re-written slightly differently\n  in every project (`{ registerTool: (t) => tools.push(t), on: ... }`) —\n  easy to get subtly wrong, and each project's version drifts from the\n  others'.\n- Real `pi -e ./src/index.ts --print \"...\"` invocations — slow, coupled to\n  whatever's on the machine (a real daemon, real ambient env vars, real\n  global settings), and not something a CI pipeline should depend on.\n\nThis package is the shared, well-tested middle ground: a real `ExtensionAPI`/\n`ExtensionContext` stub, plus a loader that exercises Pi's actual jiti-based\nproduction load path — so a bug that only manifests under jiti (not under a\nplain `import`) still gets caught in a fast, hermetic unit test.\n\n## Three layers\n\n**1. `createExtensionHarness` — pure in-process behavior testing.**\nFastest layer. No jiti involved unless you use layer 2 alongside it.\n\n```ts\nimport { createExtensionHarness } from \"@danypops/pi-extension-harness\";\nimport myExtension from \"../src/index.ts\";\n\nconst h = createExtensionHarness(myExtension, { cwd: \"/tmp/workspace\" });\nawait h.boot(); // fires session_start\n\nconst result = await h.invokeTool(\"my_tool\", { file: \"src/foo.ts\" });\nexpect(h.activeTools).toContain(\"my_tool\");\nexpect(h.notifications[0]).toEqual({ message: \"connected\", type: \"info\" });\nexpect(h.leaks).toHaveLength(0); // catches direct console.log/stdout writes\n\nawait h.shutdown(); // fires session_shutdown, clears state\n```\n\n**2. `loadExtensionViaJiti` — the same harness, loaded through jiti.**\nCatches real jiti/Bun-CJS-interop bugs (a `Map`/`Set` constructed inside a\njiti-transformed module can fail `instanceof` checks against the same class\nconstructed natively — a real, previously-hit bug class) before the\nextension ever reaches a real Pi session.\n\n```ts\nimport { loadExtensionViaJiti, createExtensionHarness } from \"@danypops/pi-extension-harness\";\n\nconst factory = await loadExtensionViaJiti(\"/abs/path/to/src/index.ts\");\nconst h = createExtensionHarness(factory);\nawait h.boot();\nexpect(h.tools.has(\"my_tool\")).toBe(true);\n```\n\nPass `nativeModules` to control which packages jiti loads natively instead\nof transforming (defaults to `JITI_NATIVE_MODULES`, the same list Pi's own\nproduction loader uses — vendored here since Pi doesn't export it publicly).\n\n**3. `mock-pi-cli` — full production-fidelity E2E, as a real subprocess.**\nFor the rare case that needs the *other* jiti mode (`tryNative:true`, the\nNode ESM baseline Pi's own binary uses in some contexts) or genuine process\nisolation (e.g. testing daemon auto-spawn without touching the operator's\nreal `$XDG_*` state).\n\n```ts\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\n\nconst cli = createRequire(import.meta.url).resolve(\"@danypops/pi-extension-harness/mock-pi-cli\");\nconst proc = spawn(\"node\", [\n  cli,\n  \"--extension\", \"/abs/path/to/src/index.ts\",\n  \"--tool\", \"my_tool\",\n  \"--params\", JSON.stringify({ file: \"src/foo.ts\" }),\n  \"--env\", \"XDG_RUNTIME_DIR=/tmp/isolated-run\",\n]);\n// proc emits NDJSON events on stdout: tool_execution_start / _end / _error, exit\n```\n\n`--tool` is optional. Omit it for a headless \"does this extension even\nload\" check -- the real use case being a package manager validating an\nextension before committing to install it, in a real isolated subprocess\nrather than assuming a clean `import` means anything under jiti:\n\n```ts\nconst proc = spawn(\"node\", [cli, \"--extension\", \"/abs/path/to/candidate/index.ts\"]);\n// emits exactly one of, then exits 0/1 to match:\n//   { type: \"load_ok\" }\n//   { type: \"load_error\", error: \"...\" }\n```\n\n## What the harness stubs\n\n`ctx.ui.notify`, `sendUserMessage`, `registerCommand` handlers,\n`setActiveTools`, and every lifecycle event via `pi.on(...)` + `h.emit(...)`\nare all real, observable state — inspect `h.notifications`, `h.userMessages`,\n`h.commands`, `h.activeTools` directly. `pi.exec()` is stubbable via the\n`exec` option for extensions that shell out. Env var overrides passed via\n`env` are applied for `boot()..shutdown()` and restored after.\n\n`pi.events` is a real `EventBus` (Pi's own `createEventBus()`), not a second\nhand-rolled stub — extensions using the shared cross-extension bus need no\nadditional fake.\n\n`ctx` is typed as `ExtensionCommandContext` (a superset of `ExtensionContext`\nwith `waitForIdle`/`newSession`/`fork`/`navigateTree`/`switchSession`/`reload`/\n`getSystemPromptOptions`, all safe never-cancelled/no-op stubs by default) so\nthe same `h.ctx` works for a `pi.on(...)` event handler and a\n`pi.registerCommand(...)` handler's ctx alike — no separate\n`ExtensionCommandContext` fake needed for command-handler tests.\n\n`ctx.ui.confirm`/`ctx.ui.input` are configurable via the `confirm`/`input`\noptions: a fixed value answers every call the same way, or a function\nreceives the real title/message/placeholder for scenario-specific answers\n(e.g. deciding by title text, or queuing a sequence of typed values).\n`ctx.ui.custom` has no meaningful generic default (it normally drives a live\nTUI component), so the `custom` option hands the raw `factory` straight to\nyour own implementation — call it with fixture args, drive the returned\ncomponent, and return whatever the scenario needs `custom()` to resolve\nwith.\n\n```ts\nconst h = createExtensionHarness(myExtension, {\n  confirm: (title) => title.includes(\"recovery\"),\n  input: () => queuedInputs.shift(),\n  custom: (factory) => {\n    const component = factory(tui, theme, keybindings, done);\n    return component.render(80).join(\"\\n\");\n  },\n});\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}